Kb10uyShortStoryServerResolver とテストを追加
This commit is contained in:
		
							
								
								
									
										42
									
								
								app/MetadataResolver/Kb10uyShortStoryServerResolver.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								app/MetadataResolver/Kb10uyShortStoryServerResolver.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\MetadataResolver;
 | 
			
		||||
 | 
			
		||||
use GuzzleHttp\Client;
 | 
			
		||||
use Symfony\Component\DomCrawler\Crawler;
 | 
			
		||||
 | 
			
		||||
class Kb10uyShortStoryServerResolver implements Resolver
 | 
			
		||||
{
 | 
			
		||||
    protected const EXCLUDED_TAGS = ['R-15', 'R-18'];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Client
 | 
			
		||||
     */
 | 
			
		||||
    private $client;
 | 
			
		||||
 | 
			
		||||
    public function __construct(Client $client)
 | 
			
		||||
    {
 | 
			
		||||
        $this->client = $client;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function resolve(string $url): Metadata
 | 
			
		||||
    {
 | 
			
		||||
        $res = $this->client->get($url);
 | 
			
		||||
        if ($res->getStatusCode() !== 200) {
 | 
			
		||||
            throw new \RuntimeException("{$res->getStatusCode()}: $url");
 | 
			
		||||
 | 
			
		||||
            return $this->parse($res->getBody());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $html = (string) $res->getBody();
 | 
			
		||||
        $crawler = new Crawler($html);
 | 
			
		||||
        $infoElement = $crawler->filter('div.post-info');
 | 
			
		||||
 | 
			
		||||
        $metadata = new Metadata();
 | 
			
		||||
        $metadata->title = $infoElement->filter('h1')->text();
 | 
			
		||||
        $metadata->description = trim($infoElement->filter('p.summary')->text());
 | 
			
		||||
        $metadata->tags = array_values(array_diff($infoElement->filter('ul.tags > li.tag > a')->extract('_text'), self::EXCLUDED_TAGS));
 | 
			
		||||
 | 
			
		||||
        return $metadata;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -32,6 +32,7 @@ class MetadataResolver implements Resolver
 | 
			
		||||
        '~(adult\.)?contents\.fc2\.com\/article_search\.php\?id=\d+~' => FC2ContentsResolver::class,
 | 
			
		||||
        '~store\.steampowered\.com/app/\d+~' => SteamResolver::class,
 | 
			
		||||
        '~www\.xtube\.com/video-watch/.*-\d+$~'=> XtubeResolver::class,
 | 
			
		||||
        '~ss\.kb10uy\.org/posts/\d+$~' => Kb10uyShortStoryServerResolver::class,
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    public $mimeTypes = [
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,35 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Tests\Unit\MetadataResolver;
 | 
			
		||||
 | 
			
		||||
use App\MetadataResolver\Kb10uyShortStoryServerResolver;
 | 
			
		||||
use Tests\TestCase;
 | 
			
		||||
 | 
			
		||||
class Kb10uyShortStoryServerResolverTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
    use CreateMockedResolver;
 | 
			
		||||
 | 
			
		||||
    public function setUp()
 | 
			
		||||
    {
 | 
			
		||||
        parent::setUp();
 | 
			
		||||
 | 
			
		||||
        if (!$this->shouldUseMock()) {
 | 
			
		||||
            sleep(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testNormalPost()
 | 
			
		||||
    {
 | 
			
		||||
        $responseText = file_get_contents(__DIR__ . '/../../fixture/Kb10uyShortStoryServer/tomone.html');
 | 
			
		||||
 | 
			
		||||
        $this->createResolver(Kb10uyShortStoryServerResolver::class, $responseText);
 | 
			
		||||
 | 
			
		||||
        $metadata = $this->resolver->resolve('https://ss.kb10uy.org/posts/14');
 | 
			
		||||
        $this->assertSame('朋音「は、はぁ?おむつ?」', $metadata->title);
 | 
			
		||||
        $this->assertSame('自炊したおかずってやつです。とりあえずこのSSの中ではkb10uyの彼女は朋音ってことにしといてください。そうじゃないと出す男が決定できないので。', $metadata->description);
 | 
			
		||||
        $this->assertSame(['妄想', 'kb10uy', '岩永朋音', 'おむつ'], $metadata->tags);
 | 
			
		||||
        if ($this->shouldUseMock()) {
 | 
			
		||||
            $this->assertSame('https://ss.kb10uy.org/posts/14', (string) $this->handler->getLastRequest()->getUri());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										205
									
								
								tests/fixture/Kb10uyShortStoryServer/tomone.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								tests/fixture/Kb10uyShortStoryServer/tomone.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,205 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="ja">
 | 
			
		||||
    <head>
 | 
			
		||||
        <meta charset="UTF-8">
 | 
			
		||||
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
        <meta name="csrf-token" content="MVlIWAqKUOV500GwG5vpc4AR2tdJA0KMPQVkqBVd">
 | 
			
		||||
        <link
 | 
			
		||||
    rel="stylesheet"
 | 
			
		||||
    href="https://use.fontawesome.com/releases/v5.8.1/css/all.css"
 | 
			
		||||
    integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf"
 | 
			
		||||
    crossorigin="anonymous">
 | 
			
		||||
<link rel="icon" href="/favicon.ico">
 | 
			
		||||
<link rel="stylesheet" href="/styles/app.d45d104d9486642a2e8e.css">
 | 
			
		||||
        <script defer src="/scripts/show-post.d45d104d9486642a2e8e.js"></script>
 | 
			
		||||
<link rel="stylesheet" href="/styles/show-post.d45d104d9486642a2e8e.css" media="all">
 | 
			
		||||
        <title>朋音「は、はぁ?おむつ?」 - ShortStoryServer</title>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
        <header>
 | 
			
		||||
    <nav class="navbar">
 | 
			
		||||
        <a class="logo" href="/">
 | 
			
		||||
            <img src="/images/newlogo.png" alt="kbS3">
 | 
			
		||||
            <span class="title">ShortStoryServer</span>
 | 
			
		||||
        </span>
 | 
			
		||||
        <div class="menu">
 | 
			
		||||
            <a class="item" data-dropdown="list-dropdown">一覧</a>
 | 
			
		||||
            <div id="list-dropdown" class="dropdown" data-dropdown-merge>
 | 
			
		||||
                <a class="item" href="https://ss.kb10uy.org/posts/latest">最近の作品</a>
 | 
			
		||||
                <a class="item" href="https://ss.kb10uy.org/series/latest">最近のシリーズ</a>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <a href="https://ss.kb10uy.org/search" class="item">検索</a>
 | 
			
		||||
 | 
			
		||||
            <a class="item" data-dropdown="help-dropdown">ヘルプ</a>
 | 
			
		||||
            <div id="help-dropdown" class="dropdown" data-dropdown-merge>
 | 
			
		||||
                <a href="https://ss.kb10uy.org/help/playground" class="item">Playground</a>
 | 
			
		||||
                <a href="https://ss.kb10uy.org/help/about" class="item">ShortStoryServer について</a>
 | 
			
		||||
                <a href="https://ss.kb10uy.org/help/terms" class="item">規約</a>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
                            <div class="user" data-dropdown="user-dropdown">
 | 
			
		||||
                <span>ログインしていません</span>
 | 
			
		||||
                <span class="dropdown-caret"></span>
 | 
			
		||||
 | 
			
		||||
                <!-- メニュー -->
 | 
			
		||||
                <div id="user-dropdown" class="dropdown">
 | 
			
		||||
                    <div class="info">
 | 
			
		||||
                        ログインして様々な機能を活用しましょう
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="separator"></div>
 | 
			
		||||
                    <a href="https://ss.kb10uy.org/login" class="item">ログイン</a>
 | 
			
		||||
                    <a href="https://ss.kb10uy.org/register" class="item">サインアップ</a>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            </nav>
 | 
			
		||||
</header>
 | 
			
		||||
                <div class="container">
 | 
			
		||||
    <div class="post-info" id="app">
 | 
			
		||||
        <h1>朋音「は、はぁ?おむつ?」</h1>
 | 
			
		||||
        <div class="user">
 | 
			
		||||
            <img src="https://www.gravatar.com/avatar/4bcb8dbb4c04894bafdc4b54c557d9ef?s=256&d=retro" alt="kb10uy">
 | 
			
		||||
            <div>
 | 
			
		||||
                Author:<br>
 | 
			
		||||
                <a href="https://ss.kb10uy.org/users/kb10uy">kb10uy <small>@kb10uy</small></a>
 | 
			
		||||
            </div>
 | 
			
		||||
                            <details>
 | 
			
		||||
                    <summary>メニュー</summary>
 | 
			
		||||
                </details>
 | 
			
		||||
                    </div>
 | 
			
		||||
        <p class="summary">
 | 
			
		||||
                            自炊したおかずってやつです。とりあえずこのSSの中ではkb10uyの彼女は朋音ってことにしといてください。そうじゃないと出す男が決定できないので。
 | 
			
		||||
                    </p>
 | 
			
		||||
 | 
			
		||||
                    <ul class="tags">
 | 
			
		||||
                                    <li class="tag"><a href="https://ss.kb10uy.org/search?query=%E5%A6%84%E6%83%B3&type=tag">妄想</a></li>
 | 
			
		||||
                                    <li class="tag"><a href="https://ss.kb10uy.org/search?query=R-18&type=tag">R-18</a></li>
 | 
			
		||||
                                    <li class="tag"><a href="https://ss.kb10uy.org/search?query=kb10uy&type=tag">kb10uy</a></li>
 | 
			
		||||
                                    <li class="tag"><a href="https://ss.kb10uy.org/search?query=%E5%B2%A9%E6%B0%B8%E6%9C%8B%E9%9F%B3&type=tag">岩永朋音</a></li>
 | 
			
		||||
                                    <li class="tag"><a href="https://ss.kb10uy.org/search?query=%E3%81%8A%E3%82%80%E3%81%A4&type=tag">おむつ</a></li>
 | 
			
		||||
                            </ul>
 | 
			
		||||
                <div class="social">
 | 
			
		||||
            <a href="javascript:(()=>{window.open(`https://shikorism.net/checkin?link=${encodeURIComponent(location.href)}`)})()" class="tissue share-button">
 | 
			
		||||
    <svg class="logo" version="1.1" viewBox="3 3 10.933333 10.933333">
 | 
			
		||||
        <rect ry="0.61077178" y="8.3200169" x="3.8013506" height="3.7688808"  width="9.5094738" style="fill:transparent;stroke:#ffffff;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
 | 
			
		||||
        <path d="M 5.6372669,8.3056228 5.0631111,4.511235 C 5.33543,6.0470597 6.850946,6.7810892 8.7216603,5.6856858 9.0176595,6.3067847 10.083255,7.5490113 12.072359,6.2277467 l -0.472834,2.0778761 z" style="fill:#ffffff;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.77704424;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
 | 
			
		||||
        <path d="M 3.7504177,10.87423 H 13.589607" style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
 | 
			
		||||
    </svg>
 | 
			
		||||
    <span>チェックイン</span>
 | 
			
		||||
</a>
 | 
			
		||||
            <a href="https://mastoshare.net/post.php?text=%E6%9C%8B%E9%9F%B3%E3%80%8C%E3%81%AF%E3%80%81%E3%81%AF%E3%81%81%EF%BC%9F%E3%81%8A%E3%82%80%E3%81%A4%EF%BC%9F%E3%80%8D+-+ShortStoryServer" class="mastodon share-button" onclick="window.open(this.href, '', 'width=500,height=400'); return false;">
 | 
			
		||||
    <i class="fab fa-mastodon"></i>
 | 
			
		||||
    <span>トゥート</span>
 | 
			
		||||
</a>
 | 
			
		||||
            <a href="https://twitter.com/intent/tweet?text=%E6%9C%8B%E9%9F%B3%E3%80%8C%E3%81%AF%E3%80%81%E3%81%AF%E3%81%81%EF%BC%9F%E3%81%8A%E3%82%80%E3%81%A4%EF%BC%9F%E3%80%8D+-+ShortStoryServer&url=https%3A%2F%2Fss.kb10uy.org%2Fposts%2F14" class="twitter share-button" onclick="window.open(this.href, '', 'width=500,height=400'); return false;">
 | 
			
		||||
    <i class="fab fa-twitter"></i>
 | 
			
		||||
    <span>ツイート</span>
 | 
			
		||||
</a>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        <modal-dialog v-cloak button-type="ok-cancel" v-if="shown.series" @dialog-ok="addToSeries(14)" @dialog-closed="shown.series = false">
 | 
			
		||||
            <template v-slot:label>シリーズに追加</template>
 | 
			
		||||
            <p>
 | 
			
		||||
                作品をシリーズに追加すると、シリーズのページからもこの作品にアクセスできるようになるほか、
 | 
			
		||||
                登録されているシリーズが作品ページにも表示されます。
 | 
			
		||||
            </p>
 | 
			
		||||
            <form>
 | 
			
		||||
                <div class="pair">
 | 
			
		||||
                    <label for="dialog-series">追加先</label>
 | 
			
		||||
                    <select id="dialog-series" name="series_target" v-model="selectedSeries">
 | 
			
		||||
                        <option v-for="seriesItem of series" :key="seriesItem.id" :value="seriesItem.id">{{ seriesItem.title }}</option>
 | 
			
		||||
                    </select>
 | 
			
		||||
                </div>
 | 
			
		||||
            </form>
 | 
			
		||||
        </modal-dialog>
 | 
			
		||||
    </div>
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <style>
 | 
			
		||||
@media (prefers-color-scheme: dark) {}</style>
 | 
			
		||||
<article class="post">
 | 
			
		||||
<p>
 | 
			
		||||
<span class="line male-1">kb10uy「うん、今日はこれ穿いて学校行って」</span>
 | 
			
		||||
<span class="line female-1">朋音「あの……アンタ本気で言ってるの?」</span>
 | 
			
		||||
<span class="line male-1">kb10uy「自分の好きでもない子にそんなおむつ穿いてとか言わないよ」</span>
 | 
			
		||||
<span class="line female-1">朋音「そういうことじゃないのよっ……」</span>
 | 
			
		||||
</p>
 | 
			
		||||
<p>
 | 
			
		||||
kb10uy の要求はいたって単純である。
 | 
			
		||||
</p>
 | 
			
		||||
<ul class="">
 | 
			
		||||
<li class="">今日一日、おむつを穿いていること。 </li>
 | 
			
		||||
<li class="">必ずおむつの中に出すこと(大小問わず)。</li>
 | 
			
		||||
<li class="">必ず人のいる場所で出すこと。</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<p>
 | 
			
		||||
単純か?
 | 
			
		||||
</p>
 | 
			
		||||
<p>
 | 
			
		||||
<span class="line female-1">朋音「いまアンタのカノジョになっちゃったことを心底後悔してるわ……」</span>
 | 
			
		||||
<span class="line male-1">kb10uy「でもやってくれるよね?」</span>
 | 
			
		||||
<span class="line female-1">朋音「うぅ……そうよ、やるわよ……正直、そ、その……やり、たい……し」</span>
 | 
			
		||||
<span class="line male-1">kb10uy「朋音ならそう言ってくれると思った!じゃあよろしくね」</span>
 | 
			
		||||
<span class="line female-1">朋音「何が宜しいのよ……まったく」</span>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<p>
 | 
			
		||||
<span class="line female-1">朋音「え、ちょっと待って、ワタシこれ大きいほうもこれにするの!?」</span>
 | 
			
		||||
<span class="line male-1">kb10uy「うん、言ったじゃん」</span>
 | 
			
		||||
<span class="line female-1">朋音「はぁ……」</span>
 | 
			
		||||
<span class="line male-1">kb10uy「嫌だったら我慢して帰ってきてからしてもいいから」</span>
 | 
			
		||||
<span class="line female-1">朋音「言われなくてもそうするわよ!w」</span>
 | 
			
		||||
<span class="line male-1">kb10uy「おしっこは我慢できなさそう?」</span>
 | 
			
		||||
<span class="line female-1">朋音「ん、正直自信ない……」</span>
 | 
			
		||||
<span class="line male-1">kb10uy「まあ大丈夫だって、きっとバレないよ」</span>
 | 
			
		||||
<span class="line female-1">朋音「よくもそんなヘラヘラと……」</span>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<p>
 | 
			
		||||
はぁ〜……。もうユウウツだわ……。
 | 
			
		||||
<span class="line female-2">夏稀「トモ、大丈夫?なんか妙に落ち込んでるように見えるけど……」</span>
 | 
			
		||||
<span class="line female-1">朋音「うーん……微妙」</span>
 | 
			
		||||
<span class="line female-2">夏稀「何かあった?」</span>
 | 
			
		||||
<span class="line female-1">朋音「あのさ……kb10uyいるじゃん」</span>
 | 
			
		||||
<span class="line female-2">夏稀「あぁ……1つ上の」</span>
 | 
			
		||||
<span class="line female-1">朋音「多分なつには言ってなかったと思うんだけどさ、ワタシちょっと前からあいつと付き合ってるんだわ」</span>
 | 
			
		||||
<span class="line female-2">夏稀「え、ほんとに!!良かったじゃん、おめでとう〜」</span>
 | 
			
		||||
<span class="line female-1">朋音「それがあんまりおめでたくなくてさ……」</span>
 | 
			
		||||
<span class="line female-2">夏稀「というと」</span>
 | 
			
		||||
<span class="line female-1">朋音「kb10uyって精力絶倫ってウワサじゃん」</span>
 | 
			
		||||
<span class="line female-2">夏稀「そうらしいね」</span>
 | 
			
		||||
<span class="line female-1">朋音「絶倫なだけならまだ良くてさ、ワタシもそういうことするんだろうなってのは覚悟してたし」</span>
 | 
			
		||||
<span class="line female-2">夏稀「したんだ?」</span>
 | 
			
		||||
<span class="line female-1">朋音「ん。プロポーズした日に……」</span>
 | 
			
		||||
<span class="line female-2">夏稀「マジで絶倫なんだ……」</span>
 | 
			
		||||
<span class="line female-1">朋音「いやこっからなのよ問題は。kb10uy、性癖もヤバヤバのヤバでさ」</span>
 | 
			
		||||
<span class="line female-2">夏稀「あー、はぁ……」</span>
 | 
			
		||||
<span class="line female-1">朋音「……誰にも言わない?」</span>
 | 
			
		||||
<span class="line female-2">夏稀「……うん。」</span>
 | 
			
		||||
</p>
 | 
			
		||||
<p>
 | 
			
		||||
<span class="line female-1">朋音「ワタシ今おむつ穿かされてるの」</span>
 | 
			
		||||
<span class="line female-2">夏稀「<i class="">えっっ!!</i>」</span>
 | 
			
		||||
</p>
 | 
			
		||||
<p>
 | 
			
		||||
<span class="line female-1">朋音「っ………///」</span>
 | 
			
		||||
<span class="line female-2">夏稀「なるほど……」</span>
 | 
			
		||||
<span class="line female-2">夏稀「でもトモも穿いてるってことはやっぱりムッツリだよね」</span>
 | 
			
		||||
<span class="line female-1">朋音「返す言葉もないわ……」</span>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<p>
 | 
			
		||||
実際に中に放尿するシーンはみなさんのご想像におまかせします
 | 
			
		||||
</p>
 | 
			
		||||
<p>
 | 
			
		||||
僕は廊下で人とぶつかってその衝撃でジョロロロって感じのシチュエーションで抜きました
 | 
			
		||||
</p>
 | 
			
		||||
</article>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
        <script src="/scripts/vendor.d45d104d9486642a2e8e.js"></script>
 | 
			
		||||
        <script src="/scripts/app.d45d104d9486642a2e8e.js"></script>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
		Reference in New Issue
	
	Block a user