mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-10-05 22:05:50 +01:00
Keep Prowlarr results from distinct indexer entries separate (#1140)
Results were deduplicated on `guid` alone. When one tracker is configured in Prowlarr as several indexer entries differing only by a server-side search filter, all of them return the same guid for the same torrent, so every entry but the first was silently discarded. Freeleech and other filter-specific releases became invisible, replaced by the unfiltered entry's copy, and which copy survived depended on query ordering rather than user intent. Include the indexer id in the dedup key so the entries stay distinct. Release.source_id is qualified the same way. It keys the release cache and becomes the download task id, so rows sharing a guid would otherwise collide and a grab would route through whichever entry cached last, defeating the point of showing them separately. The handler's task matcher still accepts a bare guid or infoUrl so tasks queued before this change still resolve. Ordering now follows the priority already configured in Prowlarr (1-50, lower preferred) rather than a new setting, since users curate that ranking there and filtered entries are typically ranked ahead of their unfiltered counterparts. The enabled-indexer list is fetched once and reused for the enrichment check, so this costs no extra round trip. Releases carry extra.indexer_priority, and the sort dropdown gains an "Indexer priority" entry, ascending, alongside the existing alphabetical "Indexer" sort; SortOption grew a default_direction for that, defaulting to desc so "Peers" is unchanged. PROWLARR_COLLAPSE_DUPLICATES (default off) optionally collapses a release back to one row, resolved by the same Prowlarr priority. Left off, every entry that carried a release keeps its own row, which is what makes filtered results visible again. Identity handling is defensive about partial payloads: a result that cannot be identified is never dropped or merged, and collapse only merges on a strong identifier (guid/downloadUrl/magnetUrl/infoUrl) because merging on title alone would discard genuinely different releases that share a name. Fixes #1137 Co-authored-by: delize <4028612+delize@users.noreply.github.com>
This commit is contained in:
@@ -18,7 +18,7 @@ from shelfmark.download.clients import (
|
||||
from shelfmark.release_sources import Release, ReleaseProtocol
|
||||
from shelfmark.release_sources.prowlarr.cache import cache_release, remove_release
|
||||
from shelfmark.release_sources.prowlarr.handler import ProwlarrHandler
|
||||
from shelfmark.release_sources.prowlarr.utils import get_protocol
|
||||
from shelfmark.release_sources.prowlarr.utils import build_source_id, get_protocol
|
||||
|
||||
|
||||
class ProgressRecorder:
|
||||
@@ -1584,3 +1584,57 @@ class TestProwlarrHandlerPostProcessCleanup:
|
||||
assert args[1] == "nzbget"
|
||||
assert args[2] == "123"
|
||||
assert str(args[3]) == "delete failed"
|
||||
|
||||
|
||||
class TestRawReleaseMatchesTask:
|
||||
"""Refreshing a stale release has to find it by whichever id form the task holds."""
|
||||
|
||||
RAW = {
|
||||
"guid": "https://tracker.example/torrent/555",
|
||||
"infoUrl": "https://tracker.example/details/555",
|
||||
"indexerId": 25,
|
||||
}
|
||||
|
||||
def test_matches_the_indexer_qualified_source_id(self):
|
||||
assert ProwlarrHandler._raw_release_matches_task(
|
||||
self.RAW, "25:https://tracker.example/torrent/555"
|
||||
)
|
||||
|
||||
def test_still_matches_a_bare_guid_from_a_task_queued_before_the_change(self):
|
||||
assert ProwlarrHandler._raw_release_matches_task(
|
||||
self.RAW, "https://tracker.example/torrent/555"
|
||||
)
|
||||
|
||||
def test_still_matches_a_bare_info_url(self):
|
||||
assert ProwlarrHandler._raw_release_matches_task(
|
||||
self.RAW, "https://tracker.example/details/555"
|
||||
)
|
||||
|
||||
def test_does_not_match_the_same_guid_from_a_different_indexer_entry(self):
|
||||
assert not ProwlarrHandler._raw_release_matches_task(
|
||||
self.RAW, "10:https://tracker.example/torrent/555"
|
||||
)
|
||||
|
||||
def test_does_not_match_an_unrelated_release(self):
|
||||
assert not ProwlarrHandler._raw_release_matches_task(self.RAW, "25:something-else")
|
||||
|
||||
|
||||
class TestRawReleaseMatchesTaskEdgeCases:
|
||||
"""Matching the wrong release here grabs the wrong torrent."""
|
||||
|
||||
def test_blank_task_id_never_matches(self):
|
||||
raw = {"guid": "g", "infoUrl": "i", "indexerId": 25}
|
||||
|
||||
assert not ProwlarrHandler._raw_release_matches_task(raw, "")
|
||||
assert not ProwlarrHandler._raw_release_matches_task(raw, " ")
|
||||
assert not ProwlarrHandler._raw_release_matches_task(raw, None)
|
||||
|
||||
def test_a_release_with_no_identifiers_does_not_match_a_blank_task_id(self):
|
||||
assert not ProwlarrHandler._raw_release_matches_task({}, None)
|
||||
assert not ProwlarrHandler._raw_release_matches_task({}, "")
|
||||
|
||||
def test_matches_a_qualified_id_built_from_a_guidless_release(self):
|
||||
raw = {"indexerId": 25, "indexer": "MAM", "title": "Dune"}
|
||||
built = build_source_id(raw)
|
||||
|
||||
assert ProwlarrHandler._raw_release_matches_task(raw, built)
|
||||
|
||||
Reference in New Issue
Block a user