diff --git a/lib/LANraragi/Plugin/Metadata/Chaika.pm b/lib/LANraragi/Plugin/Metadata/Chaika.pm index 52b11c632..eaa830ce2 100644 --- a/lib/LANraragi/Plugin/Metadata/Chaika.pm +++ b/lib/LANraragi/Plugin/Metadata/Chaika.pm @@ -19,11 +19,16 @@ sub plugin_info { type => "metadata", namespace => "trabant", author => "Difegue", - version => "2.2", + version => "2.3", description => "Searches chaika.moe for tags matching your archive. This will try to use the thumbnail first, and fallback to a default text search.", icon => "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA\nB3RJTUUH4wYCFQocjU4r+QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUH\nAAAEZElEQVQ4y42T3WtTdxzGn/M7J+fk5SRpTk7TxMZkXU84tTbVNrUT3YxO7HA4pdtQZDe7cgx2\ns8vBRvEPsOwFYTDYGJUpbDI2wV04cGXCGFLonIu1L2ptmtrmxeb1JDkvv121ZKVze66f74eH7/f5\nMmjRwMCAwrt4/9KDpflMJpPHvyiR2DPcJklJ3TRDDa0xk36cvrm8vDwHAAwAqKrqjjwXecPG205w\nHBuqa9rk77/d/qJYLD7cCht5deQIIczbgiAEKLVAKXWUiqVV06Tf35q8dYVJJBJem2A7Kwi2nQzD\nZig1CG93+PO5/KN6tf5NKpVqbsBUVVVFUUxwHJc1TXNBoxojS7IbhrnLMMx9pVJlBqFQKBKPxwcB\nkJYgjKIo3QCE1nSKoghbfJuKRqN2RVXexMaQzWaLezyeEUEQDjscjk78PxFFUYRkMsltJgGA3t7e\nyMLCwie6rr8iCILVbDbvMgwzYRjGxe0o4XC4s1AoHPP5fMP5/NNOyzLKAO6Ew+HrDADBbre/Ryk9\nnzx81FXJNlEpVpF+OqtpWu2MpmnXWmH9/f2umZmZi4cOHXnLbILLzOchhz1YerJAs9m1GwRAg2GY\nh7GYah488BJYzYW+2BD61AFBlmX/1nSNRqN9//792ujoaIPVRMjOKHoie3DytVGmp2fXCAEAjuMm\nu7u7Umosho6gjL/u/QHeEgvJZHJ2K/D+/fuL4+PjXyvPd5ldkShy1UXcmb4DnjgQj/fd5gDA6/XS\nYCAwTwh9oT3QzrS1+VDVi+vd3Tsy26yQVoFF3dAXJVmK96p9EJ0iLNOwKKU3CQCk0+lSOpP5WLDz\nF9Q9kZqyO0SloOs6gMfbHSU5NLRiUOuax2/HyZPHEOsLw2SbP83eu/fLxrkNp9P554XxCzVa16MC\n7+BPnTk9cfmH74KJE8nmga7Xy5JkZ8VKifGIHpoBb1VX8hNTd3/t/7lQ3OeXfFPvf/jBRw8ezD/a\n7M/aWq91cGgnJaZ2VcgSdnV1XRNNd3vAoBVVYusmnEQS65hfgSG6c+zy3Kre7nF/KrukcMW0Zg8O\nD08DoJutDxxOEb5IPUymwrq8ft1gLKfkFojkkRxemERCAQUACPFWRazYLJcrFGwQhyufbQQ7rFpy\nLMkCwGZC34qPIuwp+XPOjBFwazQ/txrdFS2GGS/Xuj+pUKLGk1Kjvlded3s72lyGW+PLbGVcmrAA\ngN0wTk1NWYODg9XOKltGtpazi5GigzroUnHN5nUHG1ylRsG7rDXHmnEpu4CeEtEKkqNc6QqlLc/M\n8uT5lLH5eq0aGxsju1O7GQB498a5s/0x9dRALPaQEDZnYwnhWJtMCCNrjeb0UP34Z6e/PW22zjPP\n+vwXBwfPvbw38XnXjk7GsiwKAIQQhjAMMrlsam45d+zLH6/8o6vkWcBcrXbVKQhf6bpucCwLjmUB\nSmmhXC419eblrbD/TAgAkUjE987xE0c7ZDmk66ajUCnq+cL63fErl25s5/8baQPaWLhx6goAAAAA\nSUVORK5CYII=", - parameters => [ { type => "bool", desc => "Save archive title" } ], + parameters => [ + { type => "bool", desc => "Save archive title" }, + { type => "bool", desc => "Add the following tags if available: download URL, gallery ID, category, timestamp" }, + { type => "bool", desc => "Add tags without a namespace to the 'other:' namespace instead, mirroring E-H's behavior of namespacing everything" }, + { type => "string", desc => "Add a custom 'source:' tag to your archive. Example: chaika. Will NOT add a tag if blank" } + ], oneshot_arg => "Chaika Gallery or Archive URL (Will attach matching tags to your archive)" ); @@ -34,7 +39,7 @@ sub get_tags { shift; my $lrr_info = shift; # Global info hash - my ($savetitle) = @_; # Plugin parameters + my ( $savetitle, $addextra, $addother, $addsource ) = @_; # Plugin parameters my $logger = get_plugin_logger(); my $newtags = ""; @@ -43,17 +48,17 @@ sub get_tags { # Parse the given link to see if we can extract type and ID my $oneshotarg = $lrr_info->{oneshot_param}; if ( $oneshotarg =~ /https?:\/\/panda\.chaika\.moe\/(gallery|archive)\/([0-9]*)\/?.*/ ) { - ( $newtags, $newtitle ) = tags_from_chaika_id( $1, $2 ); + ( $newtags, $newtitle ) = tags_from_chaika_id( $1, $2, $addextra, $addother, $addsource ); } else { # Try SHA-1 reverse search first $logger->info("Using thumbnail hash " . $lrr_info->{thumbnail_hash}); - ( $newtags, $newtitle ) = tags_from_sha1( $lrr_info->{thumbnail_hash} ); + ( $newtags, $newtitle ) = tags_from_sha1( $lrr_info->{thumbnail_hash}, $addextra, $addother, $addsource ); # Try text search if it fails if ( $newtags eq "" ) { $logger->info("No results, falling back to text search."); - ( $newtags, $newtitle ) = search_for_archive( $lrr_info->{archive_title}, $lrr_info->{existing_tags} ); + ( $newtags, $newtitle ) = search_for_archive( $lrr_info->{archive_title}, $lrr_info->{existing_tags}, $addextra, $addother, $addsource ); } } @@ -61,7 +66,6 @@ sub get_tags { $logger->info("No matching Chaika Archive Found!"); return ( error => "No matching Chaika Archive Found!" ); } else { - $logger->info("Sending the following tags to LRR: $newtags"); #Return a hash containing the new metadata if ( $savetitle && $newtags ne "" ) { return ( tags => $newtags, title => $newtitle ); } @@ -79,8 +83,7 @@ sub get_tags { sub search_for_archive { my $logger = get_plugin_logger(); - my $title = $_[0]; - my $tags = $_[1]; + my ( $title, $tags, $addextra, $addother, $addsource ) = @_; #Auto-lowercase the title for better results $title = lc($title); @@ -103,7 +106,7 @@ sub search_for_archive { my $textrep = $res->body; $logger->debug("Chaika API returned this JSON: $textrep"); - my ( $chaitags, $chaititle ) = parse_chaika_json( $res->json->{"galleries"}->[0] ); + my ( $chaitags, $chaititle ) = parse_chaika_json( $res->json->{"galleries"}->[0], $addextra, $addother, $addsource ); return ( $chaitags, $chaititle ); } @@ -111,17 +114,17 @@ sub search_for_archive { # Uses the jsearch API to get the best json for a file. sub tags_from_chaika_id { - my ( $type, $ID ) = @_; + my ( $type, $ID, $addextra, $addother, $addsource ) = @_; my $json = get_json_from_chaika( $type, $ID ); - return parse_chaika_json( $json ); + return parse_chaika_json( $json, $addextra, $addother, $addsource ); } # tags_from_sha1 # Uses chaika's SHA-1 search with the first page hash we have. sub tags_from_sha1 { - my ( $sha1 ) = @_; + my ( $sha1, $addextra, $addother, $addsource ) = @_; my $logger = get_plugin_logger(); @@ -129,7 +132,7 @@ sub tags_from_sha1 { # Said JSON is an array containing multiple archive objects. # We just take the first one. my $json_by_sha1 = get_json_from_chaika( 'sha1', $sha1 ); - return parse_chaika_json( $json_by_sha1->[0] ); + return parse_chaika_json( $json_by_sha1->[0], $addextra, $addother, $addsource ); } # Calls chaika's API @@ -154,15 +157,47 @@ sub get_json_from_chaika { # Parses the JSON obtained from the Chaika API to get the tags. sub parse_chaika_json { - my ( $json ) = @_; + my ( $json, $addextra, $addother, $addsource ) = @_; my $tags = $json->{"tags"} || (); foreach my $tag (@$tags) { #Replace underscores with spaces $tag =~ s/_/ /g; + + #Add 'other' namespace if none + if ($addother && index($tag, ":") == -1) { + $tag = "other:" . $tag; + } } - return ( join( ', ', @$tags ), $json->{"title"} ); + my $category = lc $json->{"category"}; + my $download = $json->{"download"} ? $json->{"download"} : $json->{"archives"}->[0]->{"link"}; + my $gallery = $json->{"gallery"} ? $json->{"gallery"} : $json->{"id"}; + my $timestamp = $json->{"posted"}; + if ($tags && $addextra) { + if ($category ne "") { + push(@$tags, "category:" . $category); + } + if ($download ne "") { + push(@$tags, "download:" . $download); + } + if ($gallery ne "") { + push(@$tags, "gallery:" . $gallery); + } + if ($timestamp ne "") { + push(@$tags, "timestamp:" . $timestamp); + } + } + + if ($gallery && $gallery ne "") { + # add custom source, but only if having found gallery + if ($addsource && $addsource ne "") { + push(@$tags, "source:" . $addsource); + } + return ( join( ', ', @$tags ), $json->{"title"} ); + } else { + return ""; + } } 1; diff --git a/tests/LANraragi/Plugin/Metadata/Chaika.t b/tests/LANraragi/Plugin/Metadata/Chaika.t index 65e103d83..981bef3e7 100644 --- a/tests/LANraragi/Plugin/Metadata/Chaika.t +++ b/tests/LANraragi/Plugin/Metadata/Chaika.t @@ -15,9 +15,15 @@ my $SAMPLES = "$cwd/tests/samples"; require "$cwd/tests/mocks.pl"; my @tags_list= ( - 'female:sole female', 'male:sole male', 'artist:kemuri haku', 'full censorship', - 'male:shotacon', 'female:defloration', 'female:nakadashi', 'female:big breasts', - 'language:translated', 'language:english' + 'full censorship', 'female:sole female', 'male:sole male', 'artist:kemuri haku', 'female:tall girl', + 'female:cunnilingus', 'male:shotacon', 'female:defloration', 'female:nakadashi', 'female:x-ray', + 'female:big breasts', 'language:translated', 'language:english' +); +my @tags_list_extra= ( + 'other:full censorship', 'female:sole female', 'male:sole male', 'artist:kemuri haku', 'female:tall girl', + 'female:cunnilingus', 'male:shotacon', 'female:defloration', 'female:nakadashi', 'female:x-ray', + 'female:big breasts', 'language:translated', 'language:english', 'category:manga', 'download:/archive/27240/download/', + 'gallery:23532', 'timestamp:1521357552', 'source:chaika' ); use_ok('LANraragi::Plugin::Metadata::Chaika'); @@ -58,4 +64,34 @@ note ( 'testing retrieving tags by SHA1 ...' ); cmp_deeply( \@type_params, [ 'sha1' ], 'API call sequence'); } +note ( 'testing retrieving tags by SHA1 with additional tags ...' ); + +{ + my $json_by_sha1 = decode_json( Mojo::File->new("$SAMPLES/chaika/002_sha1_response.json")->slurp ); + my $json = decode_json( Mojo::File->new("$SAMPLES/chaika/001_gid_27240.json")->slurp ); + my @type_params = (); + + no warnings 'once', 'redefine'; + local *LANraragi::Plugin::Metadata::Chaika::get_plugin_logger = sub { return get_logger_mock(); }; + local *LANraragi::Plugin::Metadata::Chaika::get_json_from_chaika = sub { + my ( $type, $value ) = @_; + push( @type_params, $type ); + return ( $type eq 'sha1' ) ? $json_by_sha1 : $json; + }; + + my $addextra = 1; + my $addother = 1; + my $addsource = 'chaika'; + my ( $tags, $title ) = LANraragi::Plugin::Metadata::Chaika::tags_from_sha1( + "my-hash", + $addextra, + $addother, + $addsource + ); + + is($title, $json->{title}, 'gallery title'); + cmp_bag( [ split( ', ', $tags ) ] , \@tags_list_extra, 'gallery tag list'); + cmp_deeply( \@type_params, [ 'sha1' ], 'API call sequence'); +} + done_testing(); diff --git a/tests/samples/chaika/001_gid_27240.json b/tests/samples/chaika/001_gid_27240.json index c9524524d..bdff12b94 100644 --- a/tests/samples/chaika/001_gid_27240.json +++ b/tests/samples/chaika/001_gid_27240.json @@ -6,16 +6,19 @@ "filesize": 63418139, "fjord": true, "gallery": 23532, - "posted": 1521353952, - "rating": 4.45, + "posted": 1521357552, + "rating": 4.49, "tags": [ + "full_censorship", "female:sole_female", "male:sole_male", "artist:kemuri_haku", - "full_censorship", + "female:tall_girl", + "female:cunnilingus", "male:shotacon", "female:defloration", "female:nakadashi", + "female:x-ray", "female:big_breasts", "language:translated", "language:english" @@ -23,4 +26,4 @@ "title": "[Kemuri Haku] Zettai Seikou Keikaku | Absolute Intercourse Plan (COMIC Shitsurakuten 2016-03) [English] [Redlantern]", "title_jpn": "[煙ハク] 絶対セイコウ計画 (COMIC 失楽天 2016年3月号) [英訳]", "uploader": "dankestdungeon" -} \ No newline at end of file +} diff --git a/tests/samples/chaika/002_sha1_response.json b/tests/samples/chaika/002_sha1_response.json index ab66d1d7a..d4268c425 100644 --- a/tests/samples/chaika/002_sha1_response.json +++ b/tests/samples/chaika/002_sha1_response.json @@ -1,26 +1,32 @@ -[{ - "category": "Manga", - "download": "/archive/27240/download/", - "expunged": false, - "filecount": 19, - "filesize": 63418139, - "fjord": true, - "gallery": 23532, - "posted": 1521353952, - "rating": 4.45, - "tags": [ - "female:sole_female", - "male:sole_male", - "artist:kemuri_haku", - "full_censorship", - "male:shotacon", - "female:defloration", - "female:nakadashi", - "female:big_breasts", - "language:translated", - "language:english" - ], - "title": "[Kemuri Haku] Zettai Seikou Keikaku | Absolute Intercourse Plan (COMIC Shitsurakuten 2016-03) [English] [Redlantern]", - "title_jpn": "[煙ハク] 絶対セイコウ計画 (COMIC 失楽天 2016年3月号) [英訳]", - "uploader": "dankestdungeon" -}] \ No newline at end of file +[ + { + "category": "Manga", + "download": "/archive/27240/download/", + "expunged": false, + "filecount": 19, + "filesize": 63418139, + "fjord": true, + "gallery": 23532, + "id": 27240, + "posted": 1521357552, + "rating": 4.49, + "tags": [ + "full_censorship", + "female:sole_female", + "male:sole_male", + "artist:kemuri_haku", + "female:tall_girl", + "female:cunnilingus", + "male:shotacon", + "female:defloration", + "female:nakadashi", + "female:x-ray", + "female:big_breasts", + "language:translated", + "language:english" + ], + "title": "[Kemuri Haku] Zettai Seikou Keikaku | Absolute Intercourse Plan (COMIC Shitsurakuten 2016-03) [English] [Redlantern]", + "title_jpn": "[煙ハク] 絶対セイコウ計画 (COMIC 失楽天 2016年3月号) [英訳]", + "uploader": "dankestdungeon" + } +] \ No newline at end of file