diff --git a/app/MetadataResolver/MetadataResolver.php b/app/MetadataResolver/MetadataResolver.php index a76c30d..64cdefb 100644 --- a/app/MetadataResolver/MetadataResolver.php +++ b/app/MetadataResolver/MetadataResolver.php @@ -27,6 +27,7 @@ class MetadataResolver implements Resolver '~ci-en\.jp/creator/\d+/article/\d+~' => CienResolver::class, '~www\.plurk\.com\/p\/.*~' => PlurkResolver::class, '~(adult\.)?contents\.fc2\.com\/article_search\.php\?id=\d+~' => FC2ContentsResolver::class, + '~store\.steampowered\.com/app/\d+~' => SteamResolver::class, ]; public $mimeTypes = [ diff --git a/app/MetadataResolver/SteamResolver.php b/app/MetadataResolver/SteamResolver.php new file mode 100644 index 0000000..987c97b --- /dev/null +++ b/app/MetadataResolver/SteamResolver.php @@ -0,0 +1,44 @@ +client = $client; + } + + public function resolve(string $url): Metadata + { + if (preg_match('~store\.steampowered\.com/app/(\d+)~', $url, $matches) !== 1) { + throw new \RuntimeException("Unmatched URL Pattern: $url"); + } + $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('
', PHP_EOL, html_entity_decode($data['short_description'] ?? ''))); + $metadata->image = $data['header_image'] ?? ''; + + return $metadata; + } else { + throw new \RuntimeException("{$res->getStatusCode()}: $url"); + } + } +} diff --git a/tests/Unit/MetadataResolver/SteamResolverTest.php b/tests/Unit/MetadataResolver/SteamResolverTest.php new file mode 100644 index 0000000..dadaf47 --- /dev/null +++ b/tests/Unit/MetadataResolver/SteamResolverTest.php @@ -0,0 +1,55 @@ +shouldUseMock()) { + sleep(1); + } + } + + public function test() + { + $responseText = file_get_contents(__DIR__ . '/../../fixture/Steam/test.json'); + + $this->createResolver(SteamResolver::class, $responseText); + + $metadata = $this->resolver->resolve('https://store.steampowered.com/app/333600'); + $this->assertEquals('NEKOPARA Vol. 1', $metadata->title); + $this->assertEquals('水無月嘉祥(みなづき かしょう)は伝統ある老舗和菓子屋である実家を出て、 パティシエとして自身のケーキ屋『ラ・ソレイユ』を一人で開店する。 しかし実家から送った引っ越し荷物の中に、 実家で飼っていた人型ネコのショコラとバニラが紛れ込んでいた。', $metadata->description); + $this->assertStringStartsWith('https://steamcdn-a.akamaihd.net/steam/apps/333600/header.jpg?t=', $metadata->image); + } + + public function testR18() + { + $responseText = file_get_contents(__DIR__ . '/../../fixture/Steam/testR18.json'); + + $this->createResolver(SteamResolver::class, $responseText); + + $metadata = $this->resolver->resolve('https://store.steampowered.com/app/1077580'); + $this->assertEquals('Broke Girl | 負債千金', $metadata->title); + $this->assertEquals('苦労知らずに育ったお嬢様は一夜にして1000万の借金を背負うことになった。借金を返済するために働かなければならない。しかし世間には悪意が満ちており、男達はお金で彼女を誘うか凌辱することしか考えていない。', $metadata->description); + $this->assertStringStartsWith('https://steamcdn-a.akamaihd.net/steam/apps/1077580/header.jpg?t=', $metadata->image); + } + + public function testNotFound() + { + $this->expectException(\RuntimeException::class); + + $responseText = file_get_contents(__DIR__ . '/../../fixture/Steam/testNotFound.json'); + + $this->createResolver(SteamResolver::class, $responseText); + + $this->resolver->resolve('https://store.steampowered.com/app/1'); + } +} diff --git a/tests/fixture/Steam/test.json b/tests/fixture/Steam/test.json new file mode 100644 index 0000000..3c238f4 --- /dev/null +++ b/tests/fixture/Steam/test.json @@ -0,0 +1,10 @@ +{ + "333600": { + "success": true, + "data": { + "name": "NEKOPARA Vol. 1", + "short_description": "水無月嘉祥(みなづき かしょう)は伝統ある老舗和菓子屋である実家を出て、 パティシエとして自身のケーキ屋『ラ・ソレイユ』を一人で開店する。 しかし実家から送った引っ越し荷物の中に、 実家で飼っていた人型ネコのショコラとバニラが紛れ込んでいた。", + "header_image": "https://steamcdn-a.akamaihd.net/steam/apps/333600/header.jpg?t=1558382831" + } + } +} diff --git a/tests/fixture/Steam/testNotFound.json b/tests/fixture/Steam/testNotFound.json new file mode 100644 index 0000000..0c538d2 --- /dev/null +++ b/tests/fixture/Steam/testNotFound.json @@ -0,0 +1 @@ +{"1":{"success":false}} \ No newline at end of file diff --git a/tests/fixture/Steam/testR18.json b/tests/fixture/Steam/testR18.json new file mode 100644 index 0000000..5edf5a1 --- /dev/null +++ b/tests/fixture/Steam/testR18.json @@ -0,0 +1,10 @@ +{ + "1077580": { + "success": true, + "data": { + "name": "Broke Girl | 負債千金", + "short_description": "苦労知らずに育ったお嬢様は一夜にして1000万の借金を背負うことになった。借金を返済するために働かなければならない。しかし世間には悪意が満ちており、男達はお金で彼女を誘うか凌辱することしか考えていない。", + "header_image": "https://steamcdn-a.akamaihd.net/steam/apps/1077580/header.jpg?t=1559506319" + } + } +}