91 lines
2.9 KiB
PHP
91 lines
2.9 KiB
PHP
<?php
|
|
namespace Uiharu\Lookup;
|
|
|
|
use DOMDocument;
|
|
use RuntimeException;
|
|
use Uiharu\Url;
|
|
|
|
final class NicoNicoLookup implements \Uiharu\ILookup {
|
|
private const SHORT_DOMAINS = [
|
|
'nico.ms',
|
|
'www.nico.ms',
|
|
];
|
|
|
|
private const LONG_DOMAINS = [
|
|
'www.nicovideo.jp',
|
|
'nicovideo.jp',
|
|
];
|
|
|
|
public static function isShortDomain(string $host): bool {
|
|
return in_array($host, self::SHORT_DOMAINS);
|
|
}
|
|
|
|
public static function isLongDomain(string $host): bool {
|
|
return in_array($host, self::LONG_DOMAINS);
|
|
}
|
|
|
|
public function match(Url $url): bool {
|
|
if(!$url->isWeb())
|
|
return false;
|
|
|
|
if(self::isShortDomain($url->getHost()))
|
|
return true;
|
|
|
|
if(self::isLongDomain($url->getHost()) && str_starts_with($url->getPath(), '/watch/sm'))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
public function lookup(Url $url): NicoNicoLookupResult {
|
|
if(self::isShortDomain($url->getHost()))
|
|
$videoId = explode('/', trim($url->getPath(), '/'))[0] ?? '';
|
|
else
|
|
$videoId = explode('/', trim($url->getPath(), '/'))[1] ?? '';
|
|
|
|
if(empty($videoId))
|
|
throw new RuntimeException('Nico Nico Douga video id missing.');
|
|
|
|
$thumbDoc = self::lookupThumbInfo($videoId);
|
|
|
|
$thumbResp = $thumbDoc->getElementsByTagName('nicovideo_thumb_response')[0] ?? null;
|
|
if(empty($thumbResp) || !$thumbResp->hasAttribute('status') || $thumbResp->getAttribute('status') !== 'ok')
|
|
throw new RuntimeException('Nico Nico Douga video with the given id could not be found.');
|
|
|
|
$thumbInfo = $thumbResp->getElementsByTagName('thumb')[0] ?? null;
|
|
if(empty($thumbInfo))
|
|
throw new RuntimeException('Nico Nico Douga thumb info missing from API result????');
|
|
|
|
parse_str($url->getQuery(), $urlQuery);
|
|
|
|
return new NicoNicoLookupResult($url, $videoId, $thumbInfo, $urlQuery);
|
|
}
|
|
|
|
private static function lookupThumbInfo(string $videoId): DOMDocument {
|
|
$curl = curl_init("https://ext.nicovideo.jp/api/getthumbinfo/{$videoId}");
|
|
curl_setopt_array($curl, [
|
|
CURLOPT_AUTOREFERER => false,
|
|
CURLOPT_CERTINFO => false,
|
|
CURLOPT_FAILONERROR => false,
|
|
CURLOPT_FOLLOWLOCATION => false,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TCP_FASTOPEN => true,
|
|
CURLOPT_CONNECTTIMEOUT => 2,
|
|
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
|
|
CURLOPT_TIMEOUT => 5,
|
|
CURLOPT_USERAGENT => 'Uiharu/' . UIH_VERSION,
|
|
]);
|
|
$resp = curl_exec($curl);
|
|
curl_close($curl);
|
|
|
|
if(empty($resp))
|
|
throw new RuntimeException('Nico Nico Douga API request failed.');
|
|
|
|
$doc = new DOMDocument;
|
|
if(!$doc->loadXML($resp))
|
|
throw new RuntimeException('Failed to parse Nico Nico Douga API response.');
|
|
|
|
return $doc;
|
|
}
|
|
}
|