client = $client; $this->ogpResolver = $ogpResolver; } /** * 直リン可能な pixiv.cat のプロキシ URL に変換する * HUGE THANKS TO PIXIV.CAT! * * @param string $pixivUrl i.pximg URL * * @return string i.pixiv.cat URL */ public function proxize(string $pixivUrl): string { return str_replace('i.pximg.net', 'i.pixiv.cat', $pixivUrl); } public function resolve(string $url): Metadata { if (preg_match('~www\.pixiv\.net/user/\d+/series/\d+~', $url, $matches)) { $res = $this->client->get($url); if ($res->getStatusCode() === 200) { $metadata = $this->ogpResolver->parse($res->getBody()); $metadata->image = $this->proxize($metadata->image); return $metadata; } else { throw new \RuntimeException("{$res->getStatusCode()}: $url"); } } parse_str(parse_url($url, PHP_URL_QUERY), $params); $illustId = $params['illust_id']; $page = 0; // 漫画ページ(ページ数はmanga_bigならあるかも) if ($params['mode'] === 'manga_big' || $params['mode'] === 'manga') { $page = $params['page'] ?? 0; } $res = $this->client->get('https://www.pixiv.net/ajax/illust/' . $illustId); if ($res->getStatusCode() === 200) { $json = json_decode($res->getBody()->getContents(), true); $metadata = new Metadata(); $metadata->title = $json['body']['illustTitle'] ?? ''; $metadata->description = '投稿者: ' . $json['body']['userName'] . PHP_EOL . strip_tags(str_replace('
', PHP_EOL, $json['body']['illustComment'] ?? '')); $metadata->image = $this->proxize($json['body']['urls']['regular'] ?? ''); // ページ数の指定がある場合は画像URLをそのページにする if ($page != 0) { $metadata->image = str_replace('_p0', '_p'.$page, $metadata->image); } // タグ if (!empty($json['body']['tags']['tags'])) { foreach ($json['body']['tags']['tags'] as $tag) { // 一部の固定キーワードは無視 if (array_search($tag['tag'], ['R-18', 'イラスト', 'pixiv', 'ピクシブ'], true) === false) { $metadata->tags[] = preg_replace('/\s/', '_', $tag['tag']); } } } return $metadata; } else { throw new \RuntimeException("{$res->getStatusCode()}: $url"); } } }