Route manual downloads through Arr collectors
This commit is contained in:
@@ -262,6 +262,180 @@ class LiveDownloadProgressTests(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertEqual(result["torrents"][0]["progressPercent"], 13.4)
|
||||
|
||||
|
||||
class CollectorManualDownloadTests(unittest.IsolatedAsyncioTestCase):
|
||||
@staticmethod
|
||||
def _runtime() -> SimpleNamespace:
|
||||
return SimpleNamespace(
|
||||
jellyseerr_base_url=None,
|
||||
jellyseerr_api_key=None,
|
||||
sonarr_base_url="http://sonarr.test",
|
||||
sonarr_api_key="sonarr-key",
|
||||
radarr_base_url="http://radarr.test",
|
||||
radarr_api_key="radarr-key",
|
||||
)
|
||||
|
||||
async def test_tv_manual_search_uses_sonarr_and_keeps_season_packs(self) -> None:
|
||||
snapshot = Snapshot(
|
||||
request_id="3909",
|
||||
title="Example Show",
|
||||
request_type=RequestType.tv,
|
||||
raw={"arr": {"item": {"id": 42}}},
|
||||
)
|
||||
sonarr = SimpleNamespace(
|
||||
configured=lambda: True,
|
||||
get_episodes=AsyncMock(
|
||||
return_value=[
|
||||
{"id": 101, "seasonNumber": 1, "monitored": True, "hasFile": False},
|
||||
{"id": 201, "seasonNumber": 2, "monitored": True, "hasFile": False},
|
||||
{"id": 202, "seasonNumber": 2, "monitored": True, "hasFile": True},
|
||||
]
|
||||
),
|
||||
search_releases=AsyncMock(
|
||||
side_effect=[
|
||||
[
|
||||
{
|
||||
"title": "Example.Show.S01.1080p",
|
||||
"guid": "season-one",
|
||||
"indexerId": 7,
|
||||
"indexer": "Prowlarr",
|
||||
"protocol": "torrent",
|
||||
"fullSeason": True,
|
||||
"seasonNumber": 1,
|
||||
}
|
||||
],
|
||||
[],
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
with patch.object(requests_router, "get_runtime_settings", return_value=self._runtime()), patch.object(
|
||||
requests_router, "build_snapshot", new=AsyncMock(return_value=snapshot)
|
||||
), patch.object(requests_router, "SonarrClient", return_value=sonarr), patch.object(
|
||||
requests_router, "save_action"
|
||||
):
|
||||
result = await requests_router.action_search(
|
||||
"3909", user={"username": "viewer", "role": "user"}
|
||||
)
|
||||
|
||||
sonarr.search_releases.assert_any_await(42, 1)
|
||||
sonarr.search_releases.assert_any_await(42, 2)
|
||||
self.assertEqual(result["collector"], "Sonarr")
|
||||
self.assertTrue(result["releases"][0]["fullSeason"])
|
||||
self.assertEqual(result["releases"][0]["seasonNumber"], 1)
|
||||
|
||||
async def test_movie_manual_search_uses_radarr(self) -> None:
|
||||
snapshot = Snapshot(
|
||||
request_id="4000",
|
||||
title="Example Movie",
|
||||
request_type=RequestType.movie,
|
||||
raw={"arr": {"item": {"id": 84}}},
|
||||
)
|
||||
radarr = SimpleNamespace(
|
||||
configured=lambda: True,
|
||||
search_releases=AsyncMock(
|
||||
return_value=[
|
||||
{
|
||||
"title": "Example.Movie.2026.1080p",
|
||||
"guid": "movie-release",
|
||||
"indexerId": 9,
|
||||
"indexer": "Prowlarr",
|
||||
"protocol": "torrent",
|
||||
}
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
with patch.object(requests_router, "get_runtime_settings", return_value=self._runtime()), patch.object(
|
||||
requests_router, "build_snapshot", new=AsyncMock(return_value=snapshot)
|
||||
), patch.object(requests_router, "RadarrClient", return_value=radarr), patch.object(
|
||||
requests_router, "save_action"
|
||||
):
|
||||
result = await requests_router.action_search(
|
||||
"4000", user={"username": "viewer", "role": "user"}
|
||||
)
|
||||
|
||||
radarr.search_releases.assert_awaited_once_with(84)
|
||||
self.assertEqual(result["collector"], "Radarr")
|
||||
self.assertEqual(result["releases"][0]["guid"], "movie-release")
|
||||
|
||||
async def test_tv_manual_grab_is_sent_to_sonarr_not_qbittorrent(self) -> None:
|
||||
snapshot = Snapshot(
|
||||
request_id="3909",
|
||||
title="Example Show",
|
||||
request_type=RequestType.tv,
|
||||
)
|
||||
sonarr = SimpleNamespace(
|
||||
configured=lambda: True,
|
||||
grab_release=AsyncMock(return_value={"guid": "season-one", "indexerId": 7}),
|
||||
push_release=AsyncMock(),
|
||||
)
|
||||
payload = {
|
||||
"title": "Example.Show.S01.1080p",
|
||||
"guid": "season-one",
|
||||
"indexerId": 7,
|
||||
"protocol": "torrent",
|
||||
}
|
||||
|
||||
with patch.object(requests_router, "get_runtime_settings", return_value=self._runtime()), patch.object(
|
||||
requests_router, "build_snapshot", new=AsyncMock(return_value=snapshot)
|
||||
), patch.object(requests_router, "SonarrClient", return_value=sonarr), patch.object(
|
||||
requests_router, "save_action"
|
||||
):
|
||||
result = await requests_router.action_grab(
|
||||
"3909", payload, user={"username": "viewer", "role": "user"}
|
||||
)
|
||||
|
||||
sonarr.grab_release.assert_awaited_once_with("season-one", 7)
|
||||
sonarr.push_release.assert_not_awaited()
|
||||
self.assertEqual(result["response"], {"collector": "Sonarr", "queued": True})
|
||||
|
||||
async def test_stale_movie_release_still_routes_through_radarr_push(self) -> None:
|
||||
snapshot = Snapshot(
|
||||
request_id="4000",
|
||||
title="Example Movie",
|
||||
request_type=RequestType.movie,
|
||||
)
|
||||
response = httpx.Response(
|
||||
404,
|
||||
request=httpx.Request("POST", "http://radarr.test/api/v3/release"),
|
||||
json={"message": "release cache expired"},
|
||||
)
|
||||
cache_miss = httpx.HTTPStatusError(
|
||||
"release cache expired",
|
||||
request=response.request,
|
||||
response=response,
|
||||
)
|
||||
radarr = SimpleNamespace(
|
||||
configured=lambda: True,
|
||||
grab_release=AsyncMock(side_effect=cache_miss),
|
||||
push_release=AsyncMock(return_value=[{"approved": True, "downloadAllowed": True}]),
|
||||
)
|
||||
payload = {
|
||||
"title": "Example.Movie.2026.1080p",
|
||||
"guid": "stale-release",
|
||||
"indexerId": 9,
|
||||
"indexer": "Prowlarr",
|
||||
"protocol": "torrent",
|
||||
"publishDate": "2026-08-29T00:00:00Z",
|
||||
"downloadUrl": "http://prowlarr.test/download/1",
|
||||
}
|
||||
|
||||
with patch.object(requests_router, "get_runtime_settings", return_value=self._runtime()), patch.object(
|
||||
requests_router, "build_snapshot", new=AsyncMock(return_value=snapshot)
|
||||
), patch.object(requests_router, "RadarrClient", return_value=radarr), patch.object(
|
||||
requests_router, "save_action"
|
||||
):
|
||||
result = await requests_router.action_grab(
|
||||
"4000", payload, user={"username": "viewer", "role": "user"}
|
||||
)
|
||||
|
||||
radarr.push_release.assert_awaited_once()
|
||||
pushed = radarr.push_release.await_args.args[0]
|
||||
self.assertEqual(pushed["downloadUrl"], "http://prowlarr.test/download/1")
|
||||
self.assertEqual(pushed["protocol"], "torrent")
|
||||
self.assertEqual(result["response"], {"collector": "Radarr", "queued": True})
|
||||
|
||||
|
||||
class DatabaseEmailTests(TempDatabaseMixin, unittest.TestCase):
|
||||
def test_set_user_email_is_case_insensitive(self) -> None:
|
||||
created = db.create_user_if_missing(
|
||||
|
||||
Reference in New Issue
Block a user