From dbafe2c75e0571ee4c466a8232ff0ef9f6021827 Mon Sep 17 00:00:00 2001 From: MitarashiDango Date: Thu, 25 Apr 2019 03:11:11 +0900 Subject: [PATCH 1/7] =?UTF-8?q?=E7=89=B9=E5=AE=9A=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?=E4=B8=8B=E3=81=AB=E3=81=8A=E3=81=84=E3=81=A6=E3=82=BF=E3=82=B0?= =?UTF-8?q?=E5=85=A5=E5=8A=9B=E3=81=8C=E6=AD=A3=E5=B8=B8=E3=81=AB=E8=A1=8C?= =?UTF-8?q?=E3=81=88=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C=E3=81=AE=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/assets/js/checkin.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/resources/assets/js/checkin.js b/resources/assets/js/checkin.js index 5682915..4814a44 100644 --- a/resources/assets/js/checkin.js +++ b/resources/assets/js/checkin.js @@ -28,9 +28,11 @@ $('#tagInput').on('keydown', function (ev) { case 'Tab': case 'Enter': case ' ': - insertTag($this.val().trim()); - $this.val(''); - updateTags(); + if (ev.originalEvent.isComposing !== true) { + insertTag($this.val().trim()); + $this.val(''); + updateTags(); + } ev.preventDefault(); break; } From 1322e89b86449e5d99dca77427f4702a9d6224a9 Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 29 Apr 2019 11:40:03 +0900 Subject: [PATCH 2/7] =?UTF-8?q?Metadata=20-=20Tags=20=E3=81=AE=E5=A4=9A?= =?UTF-8?q?=E5=AF=BE=E5=A4=9A=E3=83=AA=E3=83=AC=E3=83=BC=E3=82=B7=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Metadata.php | 5 +++ ...04_29_111019_create_metadata_tag_table.php | 33 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 database/migrations/2019_04_29_111019_create_metadata_tag_table.php diff --git a/app/Metadata.php b/app/Metadata.php index dc44009..d516b0b 100644 --- a/app/Metadata.php +++ b/app/Metadata.php @@ -14,4 +14,9 @@ class Metadata extends Model protected $visible = ['url', 'title', 'description', 'image', 'expires_at']; protected $dates = ['created_at', 'updated_at', 'expires_at']; + + public function tags() + { + return $this->belongsToMany(Tag::class)->withTimestamps(); + } } diff --git a/database/migrations/2019_04_29_111019_create_metadata_tag_table.php b/database/migrations/2019_04_29_111019_create_metadata_tag_table.php new file mode 100644 index 0000000..fdef664 --- /dev/null +++ b/database/migrations/2019_04_29_111019_create_metadata_tag_table.php @@ -0,0 +1,33 @@ +increments('id'); + $table->text('metadata_url')->index(); + $table->integer('tag_id')->index(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('metadata_tag'); + } +} From e4c942263adcc6340567640823ab95c2e951561d Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 29 Apr 2019 12:26:29 +0900 Subject: [PATCH 3/7] =?UTF-8?q?MetadataResolver=E3=81=8B=E3=82=89=E3=82=BF?= =?UTF-8?q?=E3=82=B0=E6=83=85=E5=A0=B1=E3=82=92=E4=BF=9D=E5=AD=98=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/CardController.php | 8 ++++++++ app/Listeners/LinkCollector.php | 10 +++++++++- app/MetadataResolver/Metadata.php | 14 +++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Api/CardController.php b/app/Http/Controllers/Api/CardController.php index 87eb52d..e5578d2 100644 --- a/app/Http/Controllers/Api/CardController.php +++ b/app/Http/Controllers/Api/CardController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api; use App\Metadata; use App\MetadataResolver\MetadataResolver; +use App\Tag; use App\Utilities\Formatter; use Illuminate\Http\Request; @@ -41,6 +42,13 @@ class CardController 'image' => $resolved->image, 'expires_at' => $resolved->expires_at ]); + + $tagIds = []; + foreach ($resolved->tags as $tagName) { + $tag = Tag::firstOrCreate(['name' => $tagName]); + $tagIds[] = $tag->id; + } + $metadata->tags()->sync($tagIds); } $response = response($metadata); diff --git a/app/Listeners/LinkCollector.php b/app/Listeners/LinkCollector.php index 0354f65..1ca8682 100644 --- a/app/Listeners/LinkCollector.php +++ b/app/Listeners/LinkCollector.php @@ -5,6 +5,7 @@ namespace App\Listeners; use App\Events\LinkDiscovered; use App\Metadata; use App\MetadataResolver\MetadataResolver; +use App\Tag; use App\Utilities\Formatter; use GuzzleHttp\Exception\TransferException; use Illuminate\Contracts\Queue\ShouldQueue; @@ -47,12 +48,19 @@ class LinkCollector if ($metadata == null || ($metadata->expires_at !== null && $metadata->expires_at < now())) { try { $resolved = $this->metadataResolver->resolve($url); - Metadata::updateOrCreate(['url' => $url], [ + $metadata = Metadata::updateOrCreate(['url' => $url], [ 'title' => $resolved->title, 'description' => $resolved->description, 'image' => $resolved->image, 'expires_at' => $resolved->expires_at ]); + + $tagIds = []; + foreach ($resolved->tags as $tagName) { + $tag = Tag::firstOrCreate(['name' => $tagName]); + $tagIds[] = $tag->id; + } + $metadata->tags()->sync($tagIds); } catch (TransferException $e) { // 何らかの通信エラーによってメタデータの取得に失敗した時、とりあえずエラーログにURLを残す Log::error(self::class . ': メタデータの取得に失敗 URL=' . $url); diff --git a/app/MetadataResolver/Metadata.php b/app/MetadataResolver/Metadata.php index dbe8654..62d16e8 100644 --- a/app/MetadataResolver/Metadata.php +++ b/app/MetadataResolver/Metadata.php @@ -6,9 +6,21 @@ use Carbon\Carbon; class Metadata { + /** @var string タイトル */ public $title = ''; + + /** @var string 概要 */ public $description = ''; + + /** @var string サムネイルのURL */ public $image = ''; - /** @var Carbon|null */ + + /** @var Carbon|null メタデータの有効期限 */ public $expires_at = null; + + /** + * @var string[] タグ + * チェックインタグと同様に保存されるため、スペースや改行文字を含めてはいけません。 + */ + public $tags = []; } From 085afd33188adc753a8a0938d3587c0396dab242 Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 29 Apr 2019 14:49:34 +0900 Subject: [PATCH 4/7] =?UTF-8?q?KomifloResolver:=20=E4=BD=9C=E8=80=85?= =?UTF-8?q?=E6=83=85=E5=A0=B1=E3=81=A8=E4=BD=9C=E5=93=81=E3=82=BF=E3=82=B0?= =?UTF-8?q?=E3=82=92=E3=82=BF=E3=82=B0=E3=81=A8=E3=81=97=E3=81=A6=E4=BF=9D?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/MetadataResolver/KomifloResolver.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/MetadataResolver/KomifloResolver.php b/app/MetadataResolver/KomifloResolver.php index c906548..7073015 100644 --- a/app/MetadataResolver/KomifloResolver.php +++ b/app/MetadataResolver/KomifloResolver.php @@ -34,6 +34,20 @@ class KomifloResolver implements Resolver ($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']['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"); From c1330ff6e33b4f0cac63e9db619f2e5657f28ce6 Mon Sep 17 00:00:00 2001 From: shibafu Date: Mon, 29 Apr 2019 16:06:40 +0900 Subject: [PATCH 5/7] =?UTF-8?q?PixivResolver:=20meta[name=3Dkeywords]=20?= =?UTF-8?q?=E3=81=8B=E3=82=89=E3=82=BF=E3=82=B0=E3=81=A3=E3=81=BD=E3=81=84?= =?UTF-8?q?=E6=83=85=E5=A0=B1=E3=82=92=E6=8A=BD=E5=87=BA=E3=81=97=E3=81=A6?= =?UTF-8?q?=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/MetadataResolver/PixivResolver.php | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/app/MetadataResolver/PixivResolver.php b/app/MetadataResolver/PixivResolver.php index b42092b..69c9937 100644 --- a/app/MetadataResolver/PixivResolver.php +++ b/app/MetadataResolver/PixivResolver.php @@ -49,6 +49,43 @@ class PixivResolver implements Resolver return str_replace('i.pximg.net', 'i.pixiv.cat', $pixivUrl); } + /** + * HTMLからタグとして利用可能な情報を抽出する + * @param string $html ページ HTML + * @return string[] タグ + */ + public function extractTags(string $html): array + { + $dom = new \DOMDocument(); + @$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); + $xpath = new \DOMXPath($dom); + + $nodes = $xpath->query("//meta[@name='keywords']"); + if ($nodes->length === 0) { + return []; + } + + $keywords = $nodes->item(0)->getAttribute('content'); + $tags = []; + + foreach (mb_split(',', $keywords) as $keyword) { + $keyword = trim($keyword); + + if (empty($keyword)) { + continue; + } + + // 一部の固定キーワードは無視 + if (array_search($keyword, ['R-18', 'イラスト', 'pixiv', 'ピクシブ'], true)) { + continue; + } + + $tags[] = preg_replace('/\s/', '_', $keyword); + } + + return $tags; + } + public function resolve(string $url): Metadata { parse_str(parse_url($url, PHP_URL_QUERY), $params); @@ -78,6 +115,8 @@ class PixivResolver implements Resolver $metadata->image = $this->proxize($illustUrl); + $metadata->tags = $this->extractTags($res->getBody()); + return $metadata; } else { throw new \RuntimeException("{$res->getStatusCode()}: $url"); From 8e6b96fb8303be64f9d53f3794c7bd525857de3a Mon Sep 17 00:00:00 2001 From: eai04191 Date: Fri, 3 May 2019 09:36:59 +0900 Subject: [PATCH 6/7] =?UTF-8?q?=E6=AD=A3=E8=A6=8F=E8=A1=A8=E7=8F=BE?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/MetadataResolver/MetadataResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/MetadataResolver/MetadataResolver.php b/app/MetadataResolver/MetadataResolver.php index 565e05f..129899a 100644 --- a/app/MetadataResolver/MetadataResolver.php +++ b/app/MetadataResolver/MetadataResolver.php @@ -15,7 +15,7 @@ class MetadataResolver implements Resolver '~www\.melonbooks\.co\.jp/detail/detail\.php~' => MelonbooksResolver::class, '~ec\.toranoana\.(jp|shop)/(tora|joshi)(_[rd]+)?/(ec|digi)/item/~' => ToranoanaResolver::class, '~iwara\.tv/videos/.*~' => IwaraResolver::class, - '~www\.dlsite\.com/.*/work/=/product_id/..\d+\.html~' => DLsiteResolver::class, + '~www\.dlsite\.com/.*/work/=/product_id/..\d+(\.html)?~' => DLsiteResolver::class, '~dlsite\.jp/mawtw/..\d+~' => DLsiteResolver::class, '~www\.pixiv\.net/member_illust\.php\?illust_id=\d+~' => PixivResolver::class, '~fantia\.jp/posts/\d+~' => FantiaResolver::class, From d7f39fcc5a30842d82dd2bc85d60adb83c04a68c Mon Sep 17 00:00:00 2001 From: shibafu Date: Fri, 3 May 2019 10:25:05 +0900 Subject: [PATCH 7/7] =?UTF-8?q?jQuery=203.4.1=E3=81=AB=E3=82=A2=E3=83=83?= =?UTF-8?q?=E3=83=97=E3=83=87=E3=83=BC=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 548e116..9629d93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4157,9 +4157,9 @@ isobject@^3.0.0, isobject@^3.0.1: integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= jquery@^3.2.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" - integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg== + version "3.4.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2" + integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw== js-cookie@^2.2.0: version "2.2.0"