Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chaika plugin adds more tags #749

Merged
merged 8 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 51 additions & 16 deletions lib/LANraragi/Plugin/Metadata/Chaika.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
);

Expand All @@ -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 = "";
Expand All @@ -43,25 +48,24 @@ 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 );
}
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of carrying the $addsource variable across all subs, you could just check for it here:

if ($addsource ne "") {
    $newtags .= ", source:" . $addsource;
}

(I think the plugin system is lenient enough to allow the comma at the start even if no other tags came in, but might be good to check)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good catch, thanks. I will put it after the no tags check on line 65 so adding strings like that should be fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it was awkward to test so I decided to carry $addsource across the subs after all.

if ( $newtags eq "" ) {
$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 ); }
Expand All @@ -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);
Expand All @@ -103,33 +106,33 @@ 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 );
}

# 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();

# The jsearch API immediately returns a JSON.
# 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
Expand All @@ -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;
42 changes: 39 additions & 3 deletions tests/LANraragi/Plugin/Metadata/Chaika.t
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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();
11 changes: 7 additions & 4 deletions tests/samples/chaika/001_gid_27240.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,24 @@
"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"
],
"title": "[Kemuri Haku] Zettai Seikou Keikaku | Absolute Intercourse Plan (COMIC Shitsurakuten 2016-03) [English] [Redlantern]",
"title_jpn": "[煙ハク] 絶対セイコウ計画 (COMIC 失楽天 2016年3月号) [英訳]",
"uploader": "dankestdungeon"
}
}
58 changes: 32 additions & 26 deletions tests/samples/chaika/002_sha1_response.json
Original file line number Diff line number Diff line change
@@ -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"
}]
[
{
"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"
}
]