diff --git a/app/Ejaculation.php b/app/Ejaculation.php index 399783a..48bdaf9 100644 --- a/app/Ejaculation.php +++ b/app/Ejaculation.php @@ -27,4 +27,9 @@ class Ejaculation extends Model { return $this->belongsToMany('App\Tag')->withTimestamps(); } + + public function textTags() + { + return implode(' ', $this->tags->map(function ($v) { return $v->name; })->all()); + } } diff --git a/app/MetadataResolver/Metadata.php b/app/MetadataResolver/Metadata.php new file mode 100644 index 0000000..ae2508b --- /dev/null +++ b/app/MetadataResolver/Metadata.php @@ -0,0 +1,10 @@ + NicoSeigaResolver::class, + '~nijie\.info/view\.php~' => NijieResolver::class, + '/.*/' => OGPResolver::class + ]; + + public function resolve(string $url): Metadata + { + foreach ($this->rules as $pattern => $class) { + if (preg_match($pattern, $url) === 1) { + $resolver = new $class; + return $resolver->resolve($url); + } + } + + throw new \UnexpectedValueException('URL not matched.'); + } +} \ No newline at end of file diff --git a/app/MetadataResolver/NicoSeigaResolver.php b/app/MetadataResolver/NicoSeigaResolver.php new file mode 100644 index 0000000..dbd81bc --- /dev/null +++ b/app/MetadataResolver/NicoSeigaResolver.php @@ -0,0 +1,24 @@ +get($url); + if ($res->getStatusCode() === 200) { + $ogpResolver = new OGPResolver(); + $metadata = $ogpResolver->parse($res->getBody()); + + // ページURLからサムネイルURLに変換 + preg_match('~http://(?:(?:sp\\.)?seiga\\.nicovideo\\.jp/seiga(?:/#!)?|nico\\.ms)/im(\\d+)~', $url, $matches); + $metadata->image = "http://lohas.nicoseiga.jp/thumb/${matches[1]}l?"; + + return $metadata; + } else { + throw new \RuntimeException("{$res->getStatusCode()}: $url"); + } + } +} \ No newline at end of file diff --git a/app/MetadataResolver/NijieResolver.php b/app/MetadataResolver/NijieResolver.php new file mode 100644 index 0000000..9bfef14 --- /dev/null +++ b/app/MetadataResolver/NijieResolver.php @@ -0,0 +1,37 @@ +get($url); + if ($res->getStatusCode() === 200) { + $ogpResolver = new OGPResolver(); + $metadata = $ogpResolver->parse($res->getBody()); + + $dom = new \DOMDocument(); + @$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8')); + $xpath = new \DOMXPath($dom); + $dataNode = $xpath->query('//script[substring(@type, string-length(@type) - 3, 4) = "json"]'); + foreach ($dataNode as $node) { + // 改行がそのまま入っていることがあるのでデコード前にエスケープが必要 + $imageData = json_decode(preg_replace('/\r?\n/', '\n', $node->nodeValue), true); + if (isset($imageData['thumbnailUrl']) && !ends_with($imageData['thumbnailUrl'], '.gif') && !ends_with($imageData['thumbnailUrl'], '.mp4')) { + $metadata->image = preg_replace('~nijie\\.info/.*/nijie_picture/~', 'nijie.info/nijie_picture/', $imageData['thumbnailUrl']); + break; + } + } + + return $metadata; + } else { + throw new \RuntimeException("{$res->getStatusCode()}: $url"); + } + } +} \ No newline at end of file diff --git a/app/MetadataResolver/OGPResolver.php b/app/MetadataResolver/OGPResolver.php new file mode 100644 index 0000000..0475d7d --- /dev/null +++ b/app/MetadataResolver/OGPResolver.php @@ -0,0 +1,52 @@ +get($url); + if ($res->getStatusCode() === 200) { + return $this->parse($res->getBody()); + } else { + throw new \RuntimeException("{$res->getStatusCode()}: $url"); + } + } + + public function parse(string $html): Metadata + { + $dom = new \DOMDocument(); + @$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); + $xpath = new \DOMXPath($dom); + + $metadata = new Metadata(); + + $titleNode = $xpath->query('//meta[@*="og:title"]'); + foreach ($titleNode as $node) { + if (!empty($node->getAttribute('content'))) { + $metadata->title = $node->getAttribute('content'); + break; + } + } + + $descriptionNode = $xpath->query('//meta[@*="og:description"]'); + foreach ($descriptionNode as $node) { + if (!empty($node->getAttribute('content'))) { + $metadata->description = $node->getAttribute('content'); + break; + } + } + + $imageNode = $xpath->query('//meta[@*="og:image"]'); + foreach ($imageNode as $node) { + if (!empty($node->getAttribute('content'))) { + $metadata->image = $node->getAttribute('content'); + break; + } + } + + return $metadata; + } +} \ No newline at end of file diff --git a/app/MetadataResolver/Resolver.php b/app/MetadataResolver/Resolver.php new file mode 100644 index 0000000..cc54d28 --- /dev/null +++ b/app/MetadataResolver/Resolver.php @@ -0,0 +1,8 @@ +app->singleton(MetadataResolver::class, function ($app) { + return new MetadataResolver(); + }); } } diff --git a/resources/views/ejaculation/edit.blade.php b/resources/views/ejaculation/edit.blade.php index ed94a68..293802d 100644 --- a/resources/views/ejaculation/edit.blade.php +++ b/resources/views/ejaculation/edit.blade.php @@ -37,7 +37,7 @@