tissue/app/MetadataResolver/PixivResolver.php

126 lines
3.6 KiB
PHP
Raw Normal View History

2019-01-14 16:01:58 +09:00
<?php
namespace App\MetadataResolver;
use GuzzleHttp\Client;
2019-01-14 16:01:58 +09:00
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;
}
/**
* サムネイル画像 URL から最大長辺 1200px の画像 URL に変換する
*
2019-01-14 18:34:33 +09:00
* @param string $thumbnailUrl サムネイル画像 URL
*
* @return string 1200px の画像 URL
*/
2019-01-15 00:05:01 +09:00
public function thumbnailToMasterUrl(string $thumbnailUrl): string
{
2019-01-19 03:02:37 +09:00
$temp = str_replace('/c/128x128', '', $thumbnailUrl);
$largeUrl = str_replace('square1200.jpg', 'master1200.jpg', $temp);
2019-01-15 00:05:01 +09:00
2019-01-14 18:34:33 +09:00
return $largeUrl;
2019-01-14 16:01:58 +09:00
}
/**
* 直リン可能な pixiv.cat のプロキシ URL に変換する
* HUGE THANKS TO PIXIV.CAT!
*
2019-01-14 18:34:33 +09:00
* @param string $pixivUrl i.pximg URL
*
* @return string i.pixiv.cat URL
*/
2019-01-15 00:05:01 +09:00
public function proxize(string $pixivUrl): string
{
2019-01-19 03:02:37 +09:00
return str_replace('i.pximg.net', 'i.pixiv.cat', $pixivUrl);
2019-01-14 16:01:58 +09:00
}
/**
* HTMLからタグとして利用可能な情報を抽出する
* @param string $html ページ HTML
* @return string[] タグ
*/
public function extractTags(string $html): array
{
$dom = new \DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$xpath = new \DOMXPath($dom);
$nodes = $xpath->query("//meta[@name='keywords']");
if ($nodes->length === 0) {
return [];
}
$keywords = $nodes->item(0)->getAttribute('content');
$tags = [];
foreach (mb_split(',', $keywords) as $keyword) {
$keyword = trim($keyword);
if (empty($keyword)) {
continue;
}
// 一部の固定キーワードは無視
if (array_search($keyword, ['R-18', 'イラスト', 'pixiv', 'ピクシブ'], true)) {
continue;
}
$tags[] = preg_replace('/\s/', '_', $keyword);
}
return $tags;
}
2019-01-14 16:01:58 +09:00
public function resolve(string $url): Metadata
{
2019-02-04 02:43:40 +09:00
parse_str(parse_url($url, PHP_URL_QUERY), $params);
$illustId = $params['illust_id'];
$page = 0;
2019-01-14 16:01:58 +09:00
2019-02-04 02:43:40 +09:00
// 漫画ページページ数はmanga_bigならあるかも
if ($params['mode'] === 'manga_big' || $params['mode'] === 'manga') {
$page = $params['page'] ?? 0;
2019-01-14 16:01:58 +09:00
// 未ログインでは漫画ページを開けないため、URL を作品ページに変換する
2019-02-04 02:43:40 +09:00
$url = preg_replace('~mode=manga(_big)?~', 'mode=medium', $url);
}
2019-01-14 16:01:58 +09:00
$res = $this->client->get($url);
if ($res->getStatusCode() === 200) {
$metadata = $this->ogpResolver->parse($res->getBody());
2019-01-14 16:01:58 +09:00
preg_match("~https://i\.pximg\.net/c/128x128/img-master/img/\d{4}/\d{2}/\d{2}/\d{2}/\d{2}/\d{2}/{$illustId}(_p0)?_square1200\.jpg~", $res->getBody(), $match);
$illustThumbnailUrl = $match[0];
2019-01-14 16:01:58 +09:00
if ($page != 0) {
$illustThumbnailUrl = str_replace('_p0', '_p'.$page, $illustThumbnailUrl);
}
$illustUrl = $this->thumbnailToMasterUrl($illustThumbnailUrl);
2019-01-14 16:01:58 +09:00
$metadata->image = $this->proxize($illustUrl);
2019-01-14 16:01:58 +09:00
$metadata->tags = $this->extractTags($res->getBody());
return $metadata;
} else {
throw new \RuntimeException("{$res->getStatusCode()}: $url");
2019-01-14 16:01:58 +09:00
}
}
}