Merge pull request #280 from eai04191/feature/remove-status-200
不要な成否判定の削除
This commit is contained in:
		@@ -25,19 +25,15 @@ class CienResolver extends MetadataResolver
 | 
			
		||||
    public function resolve(string $url): Metadata
 | 
			
		||||
    {
 | 
			
		||||
        $res = $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
        $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
 | 
			
		||||
            // 画像URLから有効期限の起点を拾う
 | 
			
		||||
            parse_str(parse_url($metadata->image, PHP_URL_QUERY), $params);
 | 
			
		||||
            if (empty($params['px-time'])) {
 | 
			
		||||
                throw new \RuntimeException('Parameter "px-time" not found. Image=' . $metadata->image . ' Source=' . $url);
 | 
			
		||||
            }
 | 
			
		||||
            $metadata->expires_at = Carbon::createFromTimestamp($params['px-time'])->addHour(1);
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        // 画像URLから有効期限の起点を拾う
 | 
			
		||||
        parse_str(parse_url($metadata->image, PHP_URL_QUERY), $params);
 | 
			
		||||
        if (empty($params['px-time'])) {
 | 
			
		||||
            throw new \RuntimeException('Parameter "px-time" not found. Image=' . $metadata->image . ' Source=' . $url);
 | 
			
		||||
        }
 | 
			
		||||
        $metadata->expires_at = Carbon::createFromTimestamp($params['px-time'])->addHour(1);
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -73,59 +73,55 @@ class DLsiteResolver implements Resolver
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $res = $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
        $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
 | 
			
		||||
            $dom = new \DOMDocument();
 | 
			
		||||
            @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
            $xpath = new \DOMXPath($dom);
 | 
			
		||||
        $dom = new \DOMDocument();
 | 
			
		||||
        @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
        $xpath = new \DOMXPath($dom);
 | 
			
		||||
 | 
			
		||||
            // OGPタイトルから[]に囲まれているmakerを取得する
 | 
			
		||||
            // 複数の作者がいる場合スペース区切りになるためexplodeしている
 | 
			
		||||
            // スペースを含むmakerの場合名前の一部しか取れないが動作には問題ない
 | 
			
		||||
            preg_match('~ \[([^\[\]]*)\] (予告作品 )?\| DLsite(がるまに)?$~', $metadata->title, $match);
 | 
			
		||||
            $makers = explode(' ', $match[1]);
 | 
			
		||||
        // OGPタイトルから[]に囲まれているmakerを取得する
 | 
			
		||||
        // 複数の作者がいる場合スペース区切りになるためexplodeしている
 | 
			
		||||
        // スペースを含むmakerの場合名前の一部しか取れないが動作には問題ない
 | 
			
		||||
        preg_match('~ \[([^\[\]]*)\] (予告作品 )?\| DLsite(がるまに)?$~', $metadata->title, $match);
 | 
			
		||||
        $makers = explode(' ', $match[1]);
 | 
			
		||||
 | 
			
		||||
            //フォローボタン(.btn_follow)はテキストを含んでしまうことがあるので要素を削除しておく
 | 
			
		||||
            $followButtonNode = $xpath->query('//*[@class="btn_follow"]')->item(0);
 | 
			
		||||
            $followButtonNode->parentNode->removeChild($followButtonNode);
 | 
			
		||||
        //フォローボタン(.btn_follow)はテキストを含んでしまうことがあるので要素を削除しておく
 | 
			
		||||
        $followButtonNode = $xpath->query('//*[@class="btn_follow"]')->item(0);
 | 
			
		||||
        $followButtonNode->parentNode->removeChild($followButtonNode);
 | 
			
		||||
 | 
			
		||||
            // maker, makerHeadを探す
 | 
			
		||||
        // maker, makerHeadを探す
 | 
			
		||||
 | 
			
		||||
            // makers
 | 
			
		||||
            // #work_makerから「makerを含むテキスト」を持つ要素を持つtdを探す
 | 
			
		||||
            // 作者名単体の場合もあるし、"作者A / 作者B"のようになることもある
 | 
			
		||||
            $makersNode = $xpath->query('//*[@id="work_maker"]//*[contains(text(), "' . $makers[0] . '")]/ancestor::td')->item(0);
 | 
			
		||||
            // nbspをspaceに置換
 | 
			
		||||
            $makers = trim(str_replace("\xc2\xa0", ' ', $makersNode->textContent));
 | 
			
		||||
        // makers
 | 
			
		||||
        // #work_makerから「makerを含むテキスト」を持つ要素を持つtdを探す
 | 
			
		||||
        // 作者名単体の場合もあるし、"作者A / 作者B"のようになることもある
 | 
			
		||||
        $makersNode = $xpath->query('//*[@id="work_maker"]//*[contains(text(), "' . $makers[0] . '")]/ancestor::td')->item(0);
 | 
			
		||||
        // nbspをspaceに置換
 | 
			
		||||
        $makers = trim(str_replace("\xc2\xa0", ' ', $makersNode->textContent));
 | 
			
		||||
 | 
			
		||||
            // makersHaed
 | 
			
		||||
            // $makerNode(td)に対するthを探す
 | 
			
		||||
            // "著者", "サークル名", "ブランド名"など
 | 
			
		||||
            $makersHeadNode = $xpath->query('preceding-sibling::th', $makersNode)->item(0);
 | 
			
		||||
            $makersHead = trim($makersHeadNode->textContent);
 | 
			
		||||
        // makersHaed
 | 
			
		||||
        // $makerNode(td)に対するthを探す
 | 
			
		||||
        // "著者", "サークル名", "ブランド名"など
 | 
			
		||||
        $makersHeadNode = $xpath->query('preceding-sibling::th', $makersNode)->item(0);
 | 
			
		||||
        $makersHead = trim($makersHeadNode->textContent);
 | 
			
		||||
 | 
			
		||||
            // 余分な文を消す
 | 
			
		||||
        // 余分な文を消す
 | 
			
		||||
 | 
			
		||||
            // OGPタイトルから作者名とサイト名を消す
 | 
			
		||||
            $metadata->title = trim(preg_replace('~ \[[^\[\]]*\] (予告作品 )?\| DLsite(がるまに)?$~', '', $metadata->title));
 | 
			
		||||
        // OGPタイトルから作者名とサイト名を消す
 | 
			
		||||
        $metadata->title = trim(preg_replace('~ \[[^\[\]]*\] (予告作品 )?\| DLsite(がるまに)?$~', '', $metadata->title));
 | 
			
		||||
 | 
			
		||||
            // OGP説明文から定型文を消す
 | 
			
		||||
            if (strpos($url, 'dlsite.com/eng/') || strpos($url, 'dlsite.com/ecchi-eng/')) {
 | 
			
		||||
                $metadata->description = preg_replace('~DLsite.+ is a download shop for .+With a huge selection of products, we\'re sure you\'ll find whatever tickles your fancy\. DLsite is one of the greatest indie contents download shops in Japan\.$~', '', $metadata->description);
 | 
			
		||||
            } else {
 | 
			
		||||
                $metadata->description = preg_replace('~「DLsite.+」は.+のダウンロードショップ。お気に入りの作品をすぐダウンロードできてすぐ楽しめる!毎日更新しているのであなたが探している作品にきっと出会えます。国内最大級の二次元総合ダウンロードショップ「DLsite」!$~', '', $metadata->description);
 | 
			
		||||
            }
 | 
			
		||||
            $metadata->description = trim(strip_tags($metadata->description));
 | 
			
		||||
 | 
			
		||||
            // 整形
 | 
			
		||||
            $metadata->description = $makersHead . ': ' . $makers . PHP_EOL . $metadata->description;
 | 
			
		||||
            $metadata->image = str_replace('img_sam.jpg', 'img_main.jpg', $metadata->image);
 | 
			
		||||
            $metadata->tags = $this->extractTags($res->getBody());
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        // OGP説明文から定型文を消す
 | 
			
		||||
        if (strpos($url, 'dlsite.com/eng/') || strpos($url, 'dlsite.com/ecchi-eng/')) {
 | 
			
		||||
            $metadata->description = preg_replace('~DLsite.+ is a download shop for .+With a huge selection of products, we\'re sure you\'ll find whatever tickles your fancy\. DLsite is one of the greatest indie contents download shops in Japan\.$~', '', $metadata->description);
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
            $metadata->description = preg_replace('~「DLsite.+」は.+のダウンロードショップ。お気に入りの作品をすぐダウンロードできてすぐ楽しめる!毎日更新しているのであなたが探している作品にきっと出会えます。国内最大級の二次元総合ダウンロードショップ「DLsite」!$~', '', $metadata->description);
 | 
			
		||||
        }
 | 
			
		||||
        $metadata->description = trim(strip_tags($metadata->description));
 | 
			
		||||
 | 
			
		||||
        // 整形
 | 
			
		||||
        $metadata->description = $makersHead . ': ' . $makers . PHP_EOL . $metadata->description;
 | 
			
		||||
        $metadata->image = str_replace('img_sam.jpg', 'img_main.jpg', $metadata->image);
 | 
			
		||||
        $metadata->tags = $this->extractTags($res->getBody());
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,21 +24,17 @@ class FC2ContentsResolver implements Resolver
 | 
			
		||||
    public function resolve(string $url): Metadata
 | 
			
		||||
    {
 | 
			
		||||
        $res = $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
        $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
 | 
			
		||||
            $dom = new \DOMDocument();
 | 
			
		||||
            @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
            $xpath = new \DOMXPath($dom);
 | 
			
		||||
        $dom = new \DOMDocument();
 | 
			
		||||
        @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
        $xpath = new \DOMXPath($dom);
 | 
			
		||||
 | 
			
		||||
            $thumbnailNode = $xpath->query('//*[@class="main_thum_img"]/a')->item(0);
 | 
			
		||||
            if ($thumbnailNode) {
 | 
			
		||||
                $metadata->image = preg_replace('~^http:~', 'https:', $thumbnailNode->getAttribute('href'));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        $thumbnailNode = $xpath->query('//*[@class="main_thum_img"]/a')->item(0);
 | 
			
		||||
        if ($thumbnailNode) {
 | 
			
		||||
            $metadata->image = preg_replace('~^http:~', 'https:', $thumbnailNode->getAttribute('href'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,29 +28,25 @@ class FantiaResolver implements Resolver
 | 
			
		||||
        $postId = $match[0];
 | 
			
		||||
 | 
			
		||||
        $res = $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
        $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
 | 
			
		||||
            $dom = new \DOMDocument();
 | 
			
		||||
            @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
            $xpath = new \DOMXPath($dom);
 | 
			
		||||
        $dom = new \DOMDocument();
 | 
			
		||||
        @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
        $xpath = new \DOMXPath($dom);
 | 
			
		||||
 | 
			
		||||
            $node = $xpath->query("//meta[@property='twitter:image']")->item(0);
 | 
			
		||||
            $ogpUrl = $node->getAttribute('content');
 | 
			
		||||
        $node = $xpath->query("//meta[@property='twitter:image']")->item(0);
 | 
			
		||||
        $ogpUrl = $node->getAttribute('content');
 | 
			
		||||
 | 
			
		||||
            // 投稿に画像がない場合(ogp.jpgでない場合)のみ大きい画像に変換する
 | 
			
		||||
            if ($ogpUrl != 'http://fantia.jp/images/ogp.jpg') {
 | 
			
		||||
                preg_match("~https://fantia\.s3\.amazonaws\.com/uploads/post/file/{$postId}/ogp_(.*?)\.(jpg|png)~", $ogpUrl, $match);
 | 
			
		||||
                $uuid = $match[1];
 | 
			
		||||
                $extension = $match[2];
 | 
			
		||||
        // 投稿に画像がない場合(ogp.jpgでない場合)のみ大きい画像に変換する
 | 
			
		||||
        if ($ogpUrl != 'http://fantia.jp/images/ogp.jpg') {
 | 
			
		||||
            preg_match("~https://fantia\.s3\.amazonaws\.com/uploads/post/file/{$postId}/ogp_(.*?)\.(jpg|png)~", $ogpUrl, $match);
 | 
			
		||||
            $uuid = $match[1];
 | 
			
		||||
            $extension = $match[2];
 | 
			
		||||
 | 
			
		||||
                // 大きい画像に変換
 | 
			
		||||
                $metadata->image = "https://c.fantia.jp/uploads/post/file/{$postId}/main_{$uuid}.{$extension}";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
            // 大きい画像に変換
 | 
			
		||||
            $metadata->image = "https://c.fantia.jp/uploads/post/file/{$postId}/main_{$uuid}.{$extension}";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,14 +24,10 @@ class FanzaResolver implements Resolver
 | 
			
		||||
    public function resolve(string $url): Metadata
 | 
			
		||||
    {
 | 
			
		||||
        $res = $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
            $metadata->image = preg_replace("~(pr|ps)\.jpg$~", 'pl.jpg', $metadata->image);
 | 
			
		||||
            $metadata->description = str_replace('<>', '', $metadata->description);
 | 
			
		||||
        $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
        $metadata->image = preg_replace("~(pr|ps)\.jpg$~", 'pl.jpg', $metadata->image);
 | 
			
		||||
        $metadata->description = str_replace('<>', '', $metadata->description);
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        }
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,45 +20,41 @@ class IwaraResolver implements Resolver
 | 
			
		||||
    public function resolve(string $url): Metadata
 | 
			
		||||
    {
 | 
			
		||||
        $res = $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $metadata = new Metadata();
 | 
			
		||||
            $html = (string) $res->getBody();
 | 
			
		||||
            $crawler = new Crawler($html);
 | 
			
		||||
        $metadata = new Metadata();
 | 
			
		||||
        $html = (string) $res->getBody();
 | 
			
		||||
        $crawler = new Crawler($html);
 | 
			
		||||
 | 
			
		||||
            $infoElements = $crawler->filter('#video-player + div, .field-name-field-video-url + div, .field-name-field-images + div');
 | 
			
		||||
            $title = $infoElements->filter('h1.title')->text();
 | 
			
		||||
            $author = $infoElements->filter('.username')->text();
 | 
			
		||||
            $description = $infoElements->filter('.field-type-text-with-summary')->text('');
 | 
			
		||||
            $tags =  $infoElements->filter('a[href^="/videos"], a[href^="/images"]')->extract('_text');
 | 
			
		||||
            // 役に立たないタグを削除する
 | 
			
		||||
            $tags = array_values(array_diff($tags, ['Uncategorized', 'Other']));
 | 
			
		||||
            array_push($tags, $author);
 | 
			
		||||
        $infoElements = $crawler->filter('#video-player + div, .field-name-field-video-url + div, .field-name-field-images + div');
 | 
			
		||||
        $title = $infoElements->filter('h1.title')->text();
 | 
			
		||||
        $author = $infoElements->filter('.username')->text();
 | 
			
		||||
        $description = $infoElements->filter('.field-type-text-with-summary')->text('');
 | 
			
		||||
        $tags =  $infoElements->filter('a[href^="/videos"], a[href^="/images"]')->extract('_text');
 | 
			
		||||
        // 役に立たないタグを削除する
 | 
			
		||||
        $tags = array_values(array_diff($tags, ['Uncategorized', 'Other']));
 | 
			
		||||
        array_push($tags, $author);
 | 
			
		||||
 | 
			
		||||
            $metadata->title = $title;
 | 
			
		||||
            $metadata->description = '投稿者: ' . $author . PHP_EOL . $description;
 | 
			
		||||
            $metadata->tags = $tags;
 | 
			
		||||
        $metadata->title = $title;
 | 
			
		||||
        $metadata->description = '投稿者: ' . $author . PHP_EOL . $description;
 | 
			
		||||
        $metadata->tags = $tags;
 | 
			
		||||
 | 
			
		||||
            // iwara video
 | 
			
		||||
            if ($crawler->filter('#video-player')->count()) {
 | 
			
		||||
                $metadata->image = 'https:' . $crawler->filter('#video-player')->attr('poster');
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // youtube
 | 
			
		||||
            if ($crawler->filter('iframe[src^="//www.youtube.com"]')->count()) {
 | 
			
		||||
                if (preg_match('~youtube\.com/embed/(\S+)\?~', $crawler->filter('iframe[src^="//www.youtube.com"]')->attr('src'), $matches) === 1) {
 | 
			
		||||
                    $youtubeId = $matches[1];
 | 
			
		||||
                    $metadata->image = 'https://img.youtube.com/vi/' . $youtubeId . '/maxresdefault.jpg';
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // images
 | 
			
		||||
            if ($crawler->filter('.field-name-field-images')->count()) {
 | 
			
		||||
                $metadata->image = 'https:' . $crawler->filter('.field-name-field-images a')->first()->attr('href');
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        // iwara video
 | 
			
		||||
        if ($crawler->filter('#video-player')->count()) {
 | 
			
		||||
            $metadata->image = 'https:' . $crawler->filter('#video-player')->attr('poster');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // youtube
 | 
			
		||||
        if ($crawler->filter('iframe[src^="//www.youtube.com"]')->count()) {
 | 
			
		||||
            if (preg_match('~youtube\.com/embed/(\S+)\?~', $crawler->filter('iframe[src^="//www.youtube.com"]')->attr('src'), $matches) === 1) {
 | 
			
		||||
                $youtubeId = $matches[1];
 | 
			
		||||
                $metadata->image = 'https://img.youtube.com/vi/' . $youtubeId . '/maxresdefault.jpg';
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // images
 | 
			
		||||
        if ($crawler->filter('.field-name-field-images')->count()) {
 | 
			
		||||
            $metadata->image = 'https:' . $crawler->filter('.field-name-field-images a')->first()->attr('href');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,33 +24,28 @@ class KomifloResolver implements Resolver
 | 
			
		||||
        $id = $matches[1];
 | 
			
		||||
 | 
			
		||||
        $res = $this->client->get('https://api.komiflo.com/content/id/' . $id);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $json = json_decode($res->getBody()->getContents(), true);
 | 
			
		||||
            $metadata = new Metadata();
 | 
			
		||||
        $json = json_decode($res->getBody()->getContents(), true);
 | 
			
		||||
        $metadata = new Metadata();
 | 
			
		||||
 | 
			
		||||
            $metadata->title = $json['content']['data']['title'] ?? '';
 | 
			
		||||
            $metadata->description = ($json['content']['attributes']['artists']['children'][0]['data']['name'] ?? '?') .
 | 
			
		||||
                ' - ' .
 | 
			
		||||
                ($json['content']['parents'][0]['data']['title'] ?? '?');
 | 
			
		||||
            $metadata->image = 'https://t.komiflo.com/564_mobile_large_3x/' . $json['content']['named_imgs']['cover']['filename'];
 | 
			
		||||
        $metadata->title = $json['content']['data']['title'] ?? '';
 | 
			
		||||
        $metadata->description = ($json['content']['attributes']['artists']['children'][0]['data']['name'] ?? '?') .
 | 
			
		||||
            ' - ' . ($json['content']['parents'][0]['data']['title'] ?? '?');
 | 
			
		||||
        $metadata->image = 'https://t.komiflo.com/564_mobile_large_3x/' . $json['content']['named_imgs']['cover']['filename'];
 | 
			
		||||
 | 
			
		||||
            // 作者情報
 | 
			
		||||
            if (!empty($json['content']['attributes']['artists']['children'])) {
 | 
			
		||||
                foreach ($json['content']['attributes']['artists']['children'] as $artist) {
 | 
			
		||||
                    $metadata->tags[] = preg_replace('/\s/', '_', $artist['data']['name']);
 | 
			
		||||
                }
 | 
			
		||||
        // 作者情報
 | 
			
		||||
        if (!empty($json['content']['attributes']['artists']['children'])) {
 | 
			
		||||
            foreach ($json['content']['attributes']['artists']['children'] as $artist) {
 | 
			
		||||
                $metadata->tags[] = preg_replace('/\s/', '_', $artist['data']['name']);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // タグ
 | 
			
		||||
            if (!empty($json['content']['attributes']['tags']['children'])) {
 | 
			
		||||
                foreach ($json['content']['attributes']['tags']['children'] as $tag) {
 | 
			
		||||
                    $metadata->tags[] = preg_replace('/\s/', '_', $tag['data']['name']);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // タグ
 | 
			
		||||
        if (!empty($json['content']['attributes']['tags']['children'])) {
 | 
			
		||||
            foreach ($json['content']['attributes']['tags']['children'] as $tag) {
 | 
			
		||||
                $metadata->tags[] = preg_replace('/\s/', '_', $tag['data']['name']);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,46 +27,42 @@ class MelonbooksResolver implements Resolver
 | 
			
		||||
        $cookieJar = CookieJar::fromArray(['AUTH_ADULT' => '1'], 'www.melonbooks.co.jp');
 | 
			
		||||
 | 
			
		||||
        $res = $this->client->get($url, ['cookies' => $cookieJar]);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
        $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
 | 
			
		||||
            $dom = new \DOMDocument();
 | 
			
		||||
            @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
            $xpath = new \DOMXPath($dom);
 | 
			
		||||
            $descriptionNodelist = $xpath->query('//div[@id="description"]//p');
 | 
			
		||||
            $specialDescriptionNodelist = $xpath->query('//div[@id="special_description"]//p');
 | 
			
		||||
        $dom = new \DOMDocument();
 | 
			
		||||
        @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
        $xpath = new \DOMXPath($dom);
 | 
			
		||||
        $descriptionNodelist = $xpath->query('//div[@id="description"]//p');
 | 
			
		||||
        $specialDescriptionNodelist = $xpath->query('//div[@id="special_description"]//p');
 | 
			
		||||
 | 
			
		||||
            // censoredフラグの除去
 | 
			
		||||
            if (mb_strpos($metadata->image, '&c=1') !== false) {
 | 
			
		||||
                $metadata->image = preg_replace('/&c=1/u', '', $metadata->image);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 抽出
 | 
			
		||||
            preg_match('~^(.+)((.+))の通販・購入はメロンブックス$~', $metadata->title, $match);
 | 
			
		||||
            $title = $match[1];
 | 
			
		||||
            $maker = $match[2];
 | 
			
		||||
 | 
			
		||||
            // 整形
 | 
			
		||||
            $description = 'サークル: ' . $maker . "\n";
 | 
			
		||||
 | 
			
		||||
            if ($specialDescriptionNodelist->length !== 0) {
 | 
			
		||||
                $description .= trim(str_replace('<br>', "\n", $specialDescriptionNodelist->item(0)->nodeValue)) . "\n";
 | 
			
		||||
                if ($specialDescriptionNodelist->length === 2) {
 | 
			
		||||
                    $description .= "\n";
 | 
			
		||||
                    $description .= trim(str_replace('<br>', "\n", $specialDescriptionNodelist->item(1)->nodeValue)) . "\n";
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($descriptionNodelist->length !== 0) {
 | 
			
		||||
                $description .= trim(str_replace('<br>', "\n", $descriptionNodelist->item(0)->nodeValue));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $metadata->title = $title;
 | 
			
		||||
            $metadata->description = trim($description);
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        // censoredフラグの除去
 | 
			
		||||
        if (mb_strpos($metadata->image, '&c=1') !== false) {
 | 
			
		||||
            $metadata->image = preg_replace('/&c=1/u', '', $metadata->image);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 抽出
 | 
			
		||||
        preg_match('~^(.+)((.+))の通販・購入はメロンブックス$~', $metadata->title, $match);
 | 
			
		||||
        $title = $match[1];
 | 
			
		||||
        $maker = $match[2];
 | 
			
		||||
 | 
			
		||||
        // 整形
 | 
			
		||||
        $description = 'サークル: ' . $maker . "\n";
 | 
			
		||||
 | 
			
		||||
        if ($specialDescriptionNodelist->length !== 0) {
 | 
			
		||||
            $description .= trim(str_replace('<br>', "\n", $specialDescriptionNodelist->item(0)->nodeValue)) . "\n";
 | 
			
		||||
            if ($specialDescriptionNodelist->length === 2) {
 | 
			
		||||
                $description .= "\n";
 | 
			
		||||
                $description .= trim(str_replace('<br>', "\n", $specialDescriptionNodelist->item(1)->nodeValue)) . "\n";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($descriptionNodelist->length !== 0) {
 | 
			
		||||
            $description .= trim(str_replace('<br>', "\n", $descriptionNodelist->item(0)->nodeValue));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $metadata->title = $title;
 | 
			
		||||
        $metadata->description = trim($description);
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,34 +27,30 @@ class NarouResolver implements Resolver
 | 
			
		||||
        $cookieJar = CookieJar::fromArray(['over18' => 'yes'], '.syosetu.com');
 | 
			
		||||
 | 
			
		||||
        $res = $this->client->get($url, ['cookies' => $cookieJar]);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
            $metadata->description = '';
 | 
			
		||||
        $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
        $metadata->description = '';
 | 
			
		||||
 | 
			
		||||
            $dom = new \DOMDocument();
 | 
			
		||||
            @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'ASCII,JIS,UTF-8,eucJP-win,SJIS-win'));
 | 
			
		||||
            $xpath = new \DOMXPath($dom);
 | 
			
		||||
        $dom = new \DOMDocument();
 | 
			
		||||
        @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'ASCII,JIS,UTF-8,eucJP-win,SJIS-win'));
 | 
			
		||||
        $xpath = new \DOMXPath($dom);
 | 
			
		||||
 | 
			
		||||
            $description = [];
 | 
			
		||||
        $description = [];
 | 
			
		||||
 | 
			
		||||
            // 作者名
 | 
			
		||||
            $writerNodes = $xpath->query('//*[contains(@class, "novel_writername")]');
 | 
			
		||||
            if ($writerNodes->length !== 0 && !empty($writerNodes->item(0)->textContent)) {
 | 
			
		||||
                $description[] = trim($writerNodes->item(0)->textContent);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // あらすじ
 | 
			
		||||
            $exNodes = $xpath->query('//*[@id="novel_ex"]');
 | 
			
		||||
            if ($exNodes->length !== 0 && !empty($exNodes->item(0)->textContent)) {
 | 
			
		||||
                $summary = trim($exNodes->item(0)->textContent);
 | 
			
		||||
                $description[] = mb_strimwidth($summary, 0, 101, '…'); // 100 + '…'(1)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $metadata->description = implode(' / ', $description);
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        // 作者名
 | 
			
		||||
        $writerNodes = $xpath->query('//*[contains(@class, "novel_writername")]');
 | 
			
		||||
        if ($writerNodes->length !== 0 && !empty($writerNodes->item(0)->textContent)) {
 | 
			
		||||
            $description[] = trim($writerNodes->item(0)->textContent);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // あらすじ
 | 
			
		||||
        $exNodes = $xpath->query('//*[@id="novel_ex"]');
 | 
			
		||||
        if ($exNodes->length !== 0 && !empty($exNodes->item(0)->textContent)) {
 | 
			
		||||
            $summary = trim($exNodes->item(0)->textContent);
 | 
			
		||||
            $description[] = mb_strimwidth($summary, 0, 101, '…'); // 100 + '…'(1)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $metadata->description = implode(' / ', $description);
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -32,32 +32,28 @@ class NijieResolver implements Resolver
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $res =  $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $html = (string) $res->getBody();
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($html);
 | 
			
		||||
            $crawler = new Crawler($html);
 | 
			
		||||
        $html = (string) $res->getBody();
 | 
			
		||||
        $metadata = $this->ogpResolver->parse($html);
 | 
			
		||||
        $crawler = new Crawler($html);
 | 
			
		||||
 | 
			
		||||
            // DomCrawler内でjson内の日本語がHTMLエンティティに変換されるのでhtml_entity_decode
 | 
			
		||||
            $json = html_entity_decode($crawler->filter('script[type="application/ld+json"]')->first()->text());
 | 
			
		||||
        // DomCrawler内でjson内の日本語がHTMLエンティティに変換されるのでhtml_entity_decode
 | 
			
		||||
        $json = html_entity_decode($crawler->filter('script[type="application/ld+json"]')->first()->text());
 | 
			
		||||
 | 
			
		||||
            // 改行がそのまま入っていることがあるのでデコード前にエスケープが必要
 | 
			
		||||
            $data = json_decode(preg_replace('/\r?\n/', '\n', $json), true);
 | 
			
		||||
        // 改行がそのまま入っていることがあるのでデコード前にエスケープが必要
 | 
			
		||||
        $data = json_decode(preg_replace('/\r?\n/', '\n', $json), true);
 | 
			
		||||
 | 
			
		||||
            $metadata->title = $data['name'];
 | 
			
		||||
            $metadata->description = '投稿者: ' . $data['author']['name'] . PHP_EOL . $data['description'];
 | 
			
		||||
            if (
 | 
			
		||||
                isset($data['thumbnailUrl']) &&
 | 
			
		||||
                !ends_with($data['thumbnailUrl'], '.gif') &&
 | 
			
		||||
                !ends_with($data['thumbnailUrl'], '.mp4')
 | 
			
		||||
            ) {
 | 
			
		||||
                // サムネイルからメイン画像に
 | 
			
		||||
                $metadata->image = str_replace('__rs_l160x160/', '', $data['thumbnailUrl']);
 | 
			
		||||
            }
 | 
			
		||||
            $metadata->tags = $crawler->filter('#view-tag span.tag_name')->extract('_text');
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        $metadata->title = $data['name'];
 | 
			
		||||
        $metadata->description = '投稿者: ' . $data['author']['name'] . PHP_EOL . $data['description'];
 | 
			
		||||
        if (
 | 
			
		||||
            isset($data['thumbnailUrl']) &&
 | 
			
		||||
            !ends_with($data['thumbnailUrl'], '.gif') &&
 | 
			
		||||
            !ends_with($data['thumbnailUrl'], '.mp4')
 | 
			
		||||
        ) {
 | 
			
		||||
            // サムネイルからメイン画像に
 | 
			
		||||
            $metadata->image = str_replace('__rs_l160x160/', '', $data['thumbnailUrl']);
 | 
			
		||||
        }
 | 
			
		||||
        $metadata->tags = $crawler->filter('#view-tag span.tag_name')->extract('_text');
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,12 +18,7 @@ class OGPResolver implements Resolver, Parser
 | 
			
		||||
 | 
			
		||||
    public function resolve(string $url): Metadata
 | 
			
		||||
    {
 | 
			
		||||
        $res = $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            return $this->parse($res->getBody());
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        }
 | 
			
		||||
        return $this->parse($this->client->get($url)->getBody());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function parse(string $html): Metadata
 | 
			
		||||
 
 | 
			
		||||
@@ -25,18 +25,14 @@ class PatreonResolver implements Resolver
 | 
			
		||||
    public function resolve(string $url): Metadata
 | 
			
		||||
    {
 | 
			
		||||
        $res = $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
        $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
 | 
			
		||||
            parse_str(parse_url($metadata->image, PHP_URL_QUERY), $query);
 | 
			
		||||
            if (isset($query['token-time'])) {
 | 
			
		||||
                $expires_at_unixtime = $query['token-time'];
 | 
			
		||||
                $metadata->expires_at = Carbon::createFromTimestamp($expires_at_unixtime);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        parse_str(parse_url($metadata->image, PHP_URL_QUERY), $query);
 | 
			
		||||
        if (isset($query['token-time'])) {
 | 
			
		||||
            $expires_at_unixtime = $query['token-time'];
 | 
			
		||||
            $metadata->expires_at = Carbon::createFromTimestamp($expires_at_unixtime);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -38,14 +38,10 @@ class PixivResolver implements Resolver
 | 
			
		||||
    {
 | 
			
		||||
        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);
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
            $metadata->image = $this->proxize($metadata->image);
 | 
			
		||||
 | 
			
		||||
                return $metadata;
 | 
			
		||||
            } else {
 | 
			
		||||
                throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
            }
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        parse_str(parse_url($url, PHP_URL_QUERY), $params);
 | 
			
		||||
@@ -58,32 +54,28 @@ class PixivResolver implements Resolver
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $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();
 | 
			
		||||
        $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'] ?? '');
 | 
			
		||||
        $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);
 | 
			
		||||
            }
 | 
			
		||||
        // ページ数の指定がある場合は画像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']);
 | 
			
		||||
                    }
 | 
			
		||||
        // タグ
 | 
			
		||||
        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");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,21 +24,17 @@ class PlurkResolver implements Resolver
 | 
			
		||||
    public function resolve(string $url): Metadata
 | 
			
		||||
    {
 | 
			
		||||
        $res = $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
        $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
 | 
			
		||||
            $dom = new \DOMDocument();
 | 
			
		||||
            @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
            $xpath = new \DOMXPath($dom);
 | 
			
		||||
            $imageNode = $xpath->query('//div[@class="text_holder"]/a[1]')->item(0);
 | 
			
		||||
        $dom = new \DOMDocument();
 | 
			
		||||
        @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
        $xpath = new \DOMXPath($dom);
 | 
			
		||||
        $imageNode = $xpath->query('//div[@class="text_holder"]/a[1]')->item(0);
 | 
			
		||||
 | 
			
		||||
            if ($imageNode) {
 | 
			
		||||
                $metadata->image = $imageNode->getAttribute('href');
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        if ($imageNode) {
 | 
			
		||||
            $metadata->image = $imageNode->getAttribute('href');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,21 +24,17 @@ class SteamResolver implements Resolver
 | 
			
		||||
        $appid = $matches[1];
 | 
			
		||||
 | 
			
		||||
        $res = $this->client->get('https://store.steampowered.com/api/appdetails/?l=japanese&appids=' . $appid);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $json = json_decode($res->getBody()->getContents(), true);
 | 
			
		||||
            if ($json[$appid]['success'] === false) {
 | 
			
		||||
                throw new \RuntimeException("API response [$appid][success] is false: $url");
 | 
			
		||||
            }
 | 
			
		||||
            $data = $json[$appid]['data'];
 | 
			
		||||
            $metadata = new Metadata();
 | 
			
		||||
 | 
			
		||||
            $metadata->title = $data['name'] ?? '';
 | 
			
		||||
            $metadata->description = strip_tags(str_replace('<br />', PHP_EOL, html_entity_decode($data['short_description'] ?? '')));
 | 
			
		||||
            $metadata->image = $data['header_image'] ?? '';
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        $json = json_decode($res->getBody()->getContents(), true);
 | 
			
		||||
        if ($json[$appid]['success'] === false) {
 | 
			
		||||
            throw new \RuntimeException("API response [$appid][success] is false: $url");
 | 
			
		||||
        }
 | 
			
		||||
        $data = $json[$appid]['data'];
 | 
			
		||||
        $metadata = new Metadata();
 | 
			
		||||
 | 
			
		||||
        $metadata->title = $data['name'] ?? '';
 | 
			
		||||
        $metadata->description = strip_tags(str_replace('<br />', PHP_EOL, html_entity_decode($data['short_description'] ?? '')));
 | 
			
		||||
        $metadata->image = $data['header_image'] ?? '';
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,20 +25,16 @@ class ToranoanaResolver implements Resolver
 | 
			
		||||
    public function resolve(string $url): Metadata
 | 
			
		||||
    {
 | 
			
		||||
        $res = $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() === 200) {
 | 
			
		||||
            $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
        $metadata = $this->ogpResolver->parse($res->getBody());
 | 
			
		||||
 | 
			
		||||
            $dom = new \DOMDocument();
 | 
			
		||||
            @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
            $xpath = new \DOMXPath($dom);
 | 
			
		||||
            $imgNode = $xpath->query('//*[@id="preview"]//img')->item(0);
 | 
			
		||||
            if ($imgNode !== null) {
 | 
			
		||||
                $metadata->image = $imgNode->getAttribute('src');
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $metadata;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
        $dom = new \DOMDocument();
 | 
			
		||||
        @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
 | 
			
		||||
        $xpath = new \DOMXPath($dom);
 | 
			
		||||
        $imgNode = $xpath->query('//*[@id="preview"]//img')->item(0);
 | 
			
		||||
        if ($imgNode !== null) {
 | 
			
		||||
            $metadata->image = $imgNode->getAttribute('src');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ namespace Tests\Unit\MetadataResolver;
 | 
			
		||||
use App\MetadataResolver\Resolver;
 | 
			
		||||
use GuzzleHttp\Client;
 | 
			
		||||
use GuzzleHttp\Handler\MockHandler;
 | 
			
		||||
use GuzzleHttp\HandlerStack;
 | 
			
		||||
use GuzzleHttp\Psr7\Response;
 | 
			
		||||
use Monolog\Handler\AbstractHandler;
 | 
			
		||||
 | 
			
		||||
@@ -41,7 +42,7 @@ trait CreateMockedResolver
 | 
			
		||||
 | 
			
		||||
        $mockResponse = new Response($status, $headers, $responseText);
 | 
			
		||||
        $this->handler = new MockHandler([$mockResponse]);
 | 
			
		||||
        $client = new Client(['handler' => $this->handler]);
 | 
			
		||||
        $client = new Client(['handler' => HandlerStack::create($this->handler)]);
 | 
			
		||||
        $this->resolver = app()->make($resolverClass, ['client' => $client]);
 | 
			
		||||
 | 
			
		||||
        return $this->resolver;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
namespace Tests\Unit\MetadataResolver;
 | 
			
		||||
 | 
			
		||||
use App\MetadataResolver\OGPResolver;
 | 
			
		||||
use GuzzleHttp\Exception\ClientException;
 | 
			
		||||
use GuzzleHttp\Exception\BadResponseException;
 | 
			
		||||
use Tests\TestCase;
 | 
			
		||||
 | 
			
		||||
class OGPResolverTest extends TestCase
 | 
			
		||||
@@ -14,7 +14,7 @@ class OGPResolverTest extends TestCase
 | 
			
		||||
    {
 | 
			
		||||
        $this->createResolver(OGPResolver::class, '', [], 404);
 | 
			
		||||
 | 
			
		||||
        $this->expectException(\RuntimeException::class);
 | 
			
		||||
        $this->expectException(BadResponseException::class);
 | 
			
		||||
        $this->resolver->resolve('http://example.com/404');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user