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']['original'] ?? '');
 | 
						||
 | 
						||
            // ページ数の指定がある場合は画像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");
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 |