[ 'title' => 'Danbooru', 'type' => 'danbooru', 'randomUrlFormat' => 'https://danbooru.donmai.us/posts.json?limit=20&tags=order:random+limit:20+%s', 'postUrlFormat' => 'https://danbooru.donmai.us/posts/%s', 'implicitTags' => [ 'misaka_mikoto' => ['-shokuhou_misaki'], 'shokuhou_misaki' => ['-misaka_mikoto'], 'kagari_(rewrite)' => ['-screencap'], 'kasuga_ayumu' => ['-rating:explicit'], 'osaka_(azumanga_daioh)' => ['-rating:explicit'], 'yazawa_nico' => ['-nishikino_maki'], 'nishikino_maki' => ['-yazawa_nico'], 'heanna_sumire' => ['-tang_keke'], 'tang_keke' => ['-heanna_sumire'], ], ], 'gelbooru' => [ 'title' => 'Gelbooru', 'type' => 'gelbooru', 'randomUrlFormat' => 'https://gelbooru.com/index.php?page=dapi&s=post&q=index&json=1&limit=20&tags=sort:random+%s', 'postUrlFormat' => 'https://gelbooru.com/index.php?page=post&s=view&id=%s', 'implicitTags' => [ 'misaka_mikoto' => ['-shokuhou_misaki'], 'shokuhou_misaki' => ['-misaka_mikoto'], 'kagari_(rewrite)' => ['-screencap'], 'kasuga_ayumu' => ['-rating:explicit'], 'yazawa_nico' => ['-nishikino_maki'], 'nishikino_maki' => ['-yazawa_nico'], 'heanna_sumire' => ['-tang_keke'], 'tang_keke' => ['-heanna_sumire'], ], ], 'yandere' => [ 'title' => 'Yande.re', 'type' => 'yandere', 'randomUrlFormat' => 'https://yande.re/post.json?api_version=2&limit=20&tags=order:random+%s', 'postUrlFormat' => 'https://yande.re/post/show/%s', 'implicitTags' => [ 'misaka_mikoto' => ['-shokuhou_misaki'], 'shokuhou_misaki' => ['-misaka_mikoto'], 'kagari_(rewrite)' => ['-cap'], 'kasuga_ayumu' => ['-rating:explicit'], 'yazawa_nico' => ['-nishikino_maki'], 'nishikino_maki' => ['-yazawa_nico'], 'heanna_sumire' => ['-tang_keke'], 'tang_keke' => ['-heanna_sumire'], ], ], ]); $config = parse_ini_file(__DIR__ . '/../config/flashii.ini'); header('Content-Type: application/json; charset=utf-8'); $booru = (string)filter_input(INPUT_GET, 'b'); $tags = (string)filter_input(INPUT_GET, 't'); $tags = array_filter(explode(' ', trim($tags))); $randomSource = empty($booru); if($randomSource) $booru = BOORUS[0]; elseif(!in_array($booru, BOORUS)) die('{"error":"booru"}'); if(!array_key_exists($booru, BOORU_INFOS)) die('{"error":"booru-info"}'); $booruInfo = BOORU_INFOS[$booru]; if(empty($booruInfo['randomUrlFormat'])) die('{"error":"random"}'); if(empty($booruInfo['postUrlFormat'])) die('{"error":"post"}'); if(empty($booruInfo['type'])) die('{"error":"type"}'); $isDanbooru = $booruInfo['type'] === 'danbooru'; $isGelbooru = $booruInfo['type'] === 'gelbooru'; $isYandere = $booruInfo['type'] === 'yandere'; if(!empty($booruInfo['implicitTags'])) { $originalTags = $tags; foreach($booruInfo['implicitTags'] as $targetTag => $addTags) { if(!in_array($targetTag, $originalTags)) continue; foreach($addTags as $tag) if(!in_array($tag, $tags)) $tags[] = $tag; } } $tagString = implode('+', array_map(fn($x) => urlencode($x), $tags)); $curl = curl_init(sprintf($booruInfo['randomUrlFormat'], $tagString)); $headers = ['Accept: application/json']; if($isDanbooru) $headers[] = 'Authorization: Basic ' . base64_encode($config['danbooru-token']); curl_setopt_array($curl, [ CURLOPT_AUTOREFERER => true, CURLOPT_CERTINFO => false, CURLOPT_FAILONERROR => false, CURLOPT_FOLLOWLOCATION => true, CURLOPT_MAXREDIRS => 5, CURLOPT_PATH_AS_IS => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TCP_FASTOPEN => true, CURLOPT_PROTOCOLS => CURLPROTO_HTTPS, CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTPS, CURLOPT_CONNECTTIMEOUT => 2, CURLOPT_TIMEOUT => 5, CURLOPT_USERAGENT => 'Satori/20230202 (+https://fii.moe/satori)', CURLOPT_HTTPHEADER => $headers, ]); $response = json_decode(curl_exec($curl)); curl_close($curl); $posts = []; // gelbooru and yandere block remote embedding, so not even going to bother with a file_url for those if($isDanbooru) { if(!empty($response) && is_array($response)) { foreach($response as $raw) { $posts[] = $post = new stdClass; $post->id = $raw->id; $post->rating = $raw->rating; if(!empty($raw->file_url)) $post->file_url = $raw->file_url; $post->post_url = sprintf($booruInfo['postUrlFormat'], $raw->id); $post->tags = explode(' ', $raw->tag_string); $post->tags_general = explode(' ', $raw->tag_string_general); $post->tags_character = explode(' ', $raw->tag_string_character); $post->tags_copyright = explode(' ', $raw->tag_string_copyright); $post->tags_artist = explode(' ', $raw->tag_string_artist); $post->tags_meta = explode(' ', $raw->tag_string_meta); } } } elseif($isGelbooru) { if(!empty($response) && !empty($response->post) && is_array($response->post)) { foreach($response->post as $raw) { $posts[] = $post = new stdClass; $post->id = $raw->id; $post->rating = $raw->rating[0]; //if(!empty($raw->file_url)) // $post->file_url = $raw->file_url; $post->post_url = sprintf($booruInfo['postUrlFormat'], $raw->id); $post->tags = explode(' ', $raw->tags); } } } elseif($isYandere) { if(!empty($response) && !empty($response->posts) && is_array($response->posts)) { foreach($response->posts as $raw) { $posts[] = $post = new stdClass; $post->id = $raw->id; $post->rating = $raw->rating; //if(!empty($raw->file_url)) // $post->file_url = $raw->file_url; $post->post_url = sprintf($booruInfo['postUrlFormat'], $raw->id); $post->tags = explode(' ', $raw->tags); } } } else die('{"error":"support"}'); echo json_encode([ 'source' => [ 'name' => $booru, 'type' => $booruInfo['type'], 'title' => $booruInfo['title'] ?? $booru, ], 'tags' => $tags, 'posts' => $posts, ]);