From 9a20b9e17a15c39f8a4f386d8849cd2475f11142 Mon Sep 17 00:00:00 2001 From: Difegue Date: Sun, 2 Jun 2024 02:42:47 +0200 Subject: [PATCH] (#911) Add support for lastreadtime as a sort key --- lib/LANraragi/Model/Search.pm | 20 +++++++++++++++---- tests/mocks.pl | 8 ++++---- tests/samples/opds/opds_sample.xml | 2 +- tests/search.t | 4 ++++ .../api-documentation/search-api.md | 5 ++++- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/LANraragi/Model/Search.pm b/lib/LANraragi/Model/Search.pm index 10bbabd0a..595e55f03 100644 --- a/lib/LANraragi/Model/Search.pm +++ b/lib/LANraragi/Model/Search.pm @@ -407,11 +407,23 @@ sub sort_results { my ( $sortkey, $sortorder, @filtered ) = @_; my $redis = LANraragi::Model::Config->get_redis; - my $re = qr/$sortkey/; + my %tmpfilter = (); - # Map our archives to a hash, where the key is the ID and the value is the first tag we found that matches the sortkey/namespace. - # (If no tag, defaults to "zzzz") - my %tmpfilter = map { $_ => ( $redis->hget( $_, "tags" ) =~ m/.*${re}:(.*)(\,.*|$)/ ) ? $1 : "zzzz" } @filtered; + # Map our archives to a hash, where the key is the ID and the value is what we want to sort by. + # For lastreadtime, we just get the value directly. + if ( $sortkey eq "lastread" ) { + %tmpfilter = map { $_ => $redis->hget( $_, "lastreadtime" ) } @filtered; + + # Invert sort order for lastreadtime, biggest timestamps come first + $sortorder = !$sortorder; + } else { + + my $re = qr/$sortkey/; + + # For other tags, we use the first tag we found that matches the sortkey/namespace. + # (If no tag, defaults to "zzzz") + %tmpfilter = map { $_ => ( $redis->hget( $_, "tags" ) =~ m/.*${re}:(.*)(\,.*|$)/ ) ? $1 : "zzzz" } @filtered; + } my @sorted = map { $_->[0] } # Map back to only having the ID sort { ncmp( $a->[1], $b->[1] ) } # Sort by the tag diff --git a/tests/mocks.pl b/tests/mocks.pl index 4cfd27e8c..fb3538b3b 100644 --- a/tests/mocks.pl +++ b/tests/mocks.pl @@ -50,7 +50,7 @@ sub setup_redis_mock { "tags": "character:segata, female:very cool too", "title": "Saturn Backup Cartridge - American Manual", "file": "package.json", - "lastreadtime": 1589038280 + "lastreadtime": 1589038281 }, "e4c422fd10943dc169e3489a38cdbf57101a5f7e": { "isnew": "true", @@ -115,14 +115,14 @@ sub setup_redis_mock { return grep { /$expr/ } keys %datamodel; } ); - $redis->mock( 'exists', sub { shift; return $_[0] eq "LRR_SEARCHCACHE" ? 0 : 1 } ); + $redis->mock( 'exists', sub { shift; return $_[0] eq "LRR_SEARCHCACHE" ? 0 : 1 } ); $redis->mock( 'hexists', sub { 1 } ); $redis->mock( 'hset', sub { 1 } ); $redis->mock( 'quit', sub { 1 } ); $redis->mock( 'select', sub { 1 } ); $redis->mock( 'flushdb', sub { 1 } ); $redis->mock( 'zincrby', sub { 1 } ); - $redis->mock( 'zrem', sub { 1 } ); + $redis->mock( 'zrem', sub { 1 } ); $redis->mock( 'watch', sub { 1 } ); $redis->mock( 'hlen', sub { 1337 } ); $redis->mock( 'dbsize', sub { 1337 } ); @@ -212,7 +212,7 @@ sub setup_redis_mock { # for my $i ( 0 .. $#results ) { # if ($element == $value) { - # return + # return # } # } diff --git a/tests/samples/opds/opds_sample.xml b/tests/samples/opds/opds_sample.xml index 4dc826e3a..e608c05a1 100644 --- a/tests/samples/opds/opds_sample.xml +++ b/tests/samples/opds/opds_sample.xml @@ -186,7 +186,7 @@ + href="/api/opds/e69e43e1355267f7d32a4f9b7f2fe108d2401ebg/pse?page={pageNumber}" pse:count="200" pse:lastRead="34" pse:lastReadDate="2020-05-09T15:31:21Z" /> diff --git a/tests/search.t b/tests/search.t index 0cbd2acbb..aa94f3aec 100644 --- a/tests/search.t +++ b/tests/search.t @@ -123,4 +123,8 @@ $search = qq(read:<11, read:>9); do_test_search(); is( $ids[0], "e69e43e1355267f7d32a4f9b7f2fe108d2401ebf", qq(Read search ($search)) ); +$search = ""; +( $total, $filtered, @ids ) = LANraragi::Model::Search::do_search( "", "", 0, "lastreadtime", 0, 0, 0 ); +is( $ids[0], "e69e43e1355267f7d32a4f9b7f2fe108d2401ebg", qq(Last read time sort) ); + done_testing(); diff --git a/tools/Documentation/api-documentation/search-api.md b/tools/Documentation/api-documentation/search-api.md index 625a34d64..9a888d8ee 100644 --- a/tools/Documentation/api-documentation/search-api.md +++ b/tools/Documentation/api-documentation/search-api.md @@ -38,7 +38,10 @@ From 0.8.2 onwards, you can use "-1" here to get the full, unpaged data. {% endswagger-parameter %} {% swagger-parameter name="sortby" type="string" required="false" in="query" %} -Namespace by which you want to sort the results, or _title_ if you want to sort by title. (Default value is title.) +Namespace by which you want to sort the results. There are specific sort keys you can use: +- _title_ if you want to sort by title +- _lastread_ if you want to sort by last read time. (If **Server-side Progress Tracking** is enabled) +(Default value is title.) {% endswagger-parameter %} {% swagger-parameter name="order" type="string" required="false" in="query" %}