90 lines
2.9 KiB
PHP
90 lines
2.9 KiB
PHP
<?php
|
||
|
||
namespace App\MetadataResolver;
|
||
|
||
use GuzzleHttp\Client;
|
||
|
||
class PixivResolver implements Resolver
|
||
{
|
||
/**
|
||
* @var Client
|
||
*/
|
||
private $client;
|
||
/**
|
||
* @var OGPResolver
|
||
*/
|
||
private $ogpResolver;
|
||
|
||
public function __construct(Client $client, OGPResolver $ogpResolver)
|
||
{
|
||
$this->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('<br />', 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");
|
||
}
|
||
}
|
||
}
|