torrent-audit: only filter out complete torrents
All checks were successful
Build and Deploy / mreow (push) Successful in 2m7s
Build and Deploy / yarn (push) Successful in 45s
Build and Deploy / muffin (push) Successful in 1m11s

This commit is contained in:
2026-04-29 14:42:24 -04:00
parent 365efe3482
commit 47565c9e95
2 changed files with 52 additions and 5 deletions

View File

@@ -52,6 +52,7 @@ let
SINGLE_CROSS = "A" * 38 + "0C" # movieId=7 single import AND older import for movieId=8
SINGLE8_NEW = "A" * 38 + "0D" # movieId=8, newer import keeper (not in qBit)
QUEUED_MOV = "A" * 38 + "0E" # in Radarr queue, not in history
INPROGRESS_MOV = "A" * 38 + "0F" # movieId=10, older import, currently re-downloading
# TV
UNMANAGED_TV = "B" * 38 + "01"
@@ -62,13 +63,17 @@ let
REPACK = "B" * 38 + "06" # episodeId=300, newer import active
REMOVED_TV = "B" * 38 + "07" # episodeId=400, older import (series removed)
REMOVED_TV_NEW = "B" * 38 + "08" # episodeId=400, newer import (not in qBit)
INPROGRESS_TV = "B" * 38 + "09" # episodeId=500, older import, currently re-downloading
INPROGRESS_TV_NEW = "B" * 38 + "0A" # episodeId=500, newer import (not in qBit)
INPROGRESS_MOV_NEW = "A" * 38 + "10" # movieId=10, newer import (not in qBit)
def make_torrent(h, name, size, added_on, state="uploading"):
def make_torrent(h, name, size, added_on, state="uploading", progress=1.0):
return {
"hash": h.lower(),
"name": name,
"size": size,
"state": state,
"progress": progress,
"added_on": added_on,
"content_path": f"/downloads/{name}",
}
@@ -84,6 +89,9 @@ let
make_torrent(LARGER_OLD, "Larger.Movie.2024", 10_737_418_240, 1704067206),
make_torrent(SINGLE_CROSS, "SingleCross.Movie.2024", 4_000_000_000, 1704067207),
make_torrent(QUEUED_MOV, "Queued.Movie.2024", 2_000_000_000, 1704067208),
# In-progress re-download: hash matches an old import, but data is
# not yet on disk. Must NOT be flagged as abandoned (regression).
make_torrent(INPROGRESS_MOV, "InProgress.Movie.2024", 8_000_000_000, 1704067209, state="downloading", progress=0.05),
],
"tvshows": [
make_torrent(UNMANAGED_TV, "Unmanaged.Show.S01E01", 1_000_000_000, 1704067200),
@@ -92,6 +100,7 @@ let
make_torrent(NEW_TV, "New.Show.S01E01", 1_200_000_000, 1704067203),
make_torrent(SEASON_PACK, "Season.Pack.S02", 5_000_000_000, 1704067204),
make_torrent(REMOVED_TV, "Removed.Show.S01E01", 900_000_000, 1704067205),
make_torrent(INPROGRESS_TV, "InProgress.Show.S01E01", 1_500_000_000, 1704067209, state="downloading", progress=0.05),
],
}
@@ -115,6 +124,9 @@ let
{"movieId": 7, "downloadId": SINGLE_CROSS, "eventType": "downloadFolderImported", "date": "2024-03-01T00:00:00Z"},
{"movieId": 8, "downloadId": SINGLE_CROSS, "eventType": "downloadFolderImported", "date": "2024-01-01T00:00:00Z"},
{"movieId": 8, "downloadId": SINGLE8_NEW, "eventType": "downloadFolderImported", "date": "2024-06-01T00:00:00Z"},
# In-progress re-download regression case for movies
{"movieId": 10, "downloadId": INPROGRESS_MOV, "eventType": "downloadFolderImported", "date": "2024-01-01T00:00:00Z"},
{"movieId": 10, "downloadId": INPROGRESS_MOV_NEW,"eventType": "downloadFolderImported", "date": "2024-06-01T00:00:00Z"},
]
RADARR_MOVIES = [
@@ -126,6 +138,7 @@ let
{"id": 6, "hasFile": True, "movieFile": {"size": 5_368_709_120, "quality": {"quality": {"name": "Bluray-720p"}}}},
{"id": 7, "hasFile": True, "movieFile": {"size": 4_000_000_000, "quality": {"quality": {"name": "Bluray-1080p"}}}},
{"id": 8, "hasFile": True, "movieFile": {"size": 5_000_000_000, "quality": {"quality": {"name": "Remux-1080p"}}}},
{"id": 10, "hasFile": True, "movieFile": {"size": 8_000_000_000, "quality": {"quality": {"name": "Remux-2160p"}}}},
]
# Sonarr mock data
@@ -148,6 +161,9 @@ let
# Removed series scenario
{"episodeId": 400, "seriesId": 99, "downloadId": REMOVED_TV, "eventType": "downloadFolderImported", "date": "2024-01-01T00:00:00Z"},
{"episodeId": 400, "seriesId": 99, "downloadId": REMOVED_TV_NEW,"eventType": "downloadFolderImported", "date": "2024-06-01T00:00:00Z"},
# In-progress re-download regression case for TV
{"episodeId": 500, "seriesId": 1, "downloadId": INPROGRESS_TV, "eventType": "downloadFolderImported", "date": "2024-01-01T00:00:00Z"},
{"episodeId": 500, "seriesId": 1, "downloadId": INPROGRESS_TV_NEW,"eventType": "downloadFolderImported", "date": "2024-06-01T00:00:00Z"},
]
SONARR_HISTORY_ALL = SONARR_HISTORY_PAGE1 + SONARR_HISTORY_PAGE2
@@ -319,14 +335,14 @@ pkgs.testers.runNixOSTest {
with subtest("Detects unmanaged movie torrent"):
assert "Unmanaged.Movie.2024" in unmanaged_section, \
"Should detect unmanaged movie"
assert "1 unmanaged / 9 total" in unmanaged_section, \
"Should show 1 unmanaged movie out of 9"
assert "1 unmanaged / 10 total" in unmanaged_section, \
"Should show 1 unmanaged movie out of 10"
with subtest("Detects unmanaged TV torrent"):
assert "Unmanaged.Show.S01E01" in unmanaged_section, \
"Should detect unmanaged TV show"
assert "1 unmanaged / 6 total" in unmanaged_section, \
"Should show 1 unmanaged TV show out of 6"
assert "1 unmanaged / 7 total" in unmanaged_section, \
"Should show 1 unmanaged TV show out of 7"
with subtest("Empty category shows zero counts"):
assert "0 unmanaged / 0 total" in unmanaged_section, \
@@ -380,6 +396,16 @@ pkgs.testers.runNixOSTest {
assert "SingleCross.Movie.2024" not in abandoned_section, \
"Hash that is sole import for movieId=7 must be in keeper set, not abandoned"
with subtest("In-progress re-download not abandoned (incomplete payload regression)"):
# A torrent whose hash matches an old downloadFolderImported entry but
# whose data is not currently on disk (progress < 1.0) must not be
# reported as abandoned: its size is metadata, not reclaimable bytes,
# and a SAFE verdict could disrupt a re-download in progress.
assert "InProgress.Movie.2024" not in abandoned_section, \
"In-progress movie re-download must not appear as abandoned"
assert "InProgress.Show.S01E01" not in abandoned_section, \
"In-progress TV re-download must not appear as abandoned"
with subtest("Removed movie triggers REVIEW status"):
assert "Removed.Movie.2024" in abandoned_section, \
"Should detect abandoned torrent for removed movie"