From 030480410b406397f28d0df97d8ca30949452262 Mon Sep 17 00:00:00 2001 From: Rephl3x Date: Sat, 24 Jan 2026 19:21:40 +1300 Subject: [PATCH] Map Prowlarr releases to Arr indexers for manual grab --- backend/app/clients/radarr.py | 3 +++ backend/app/clients/sonarr.py | 3 +++ backend/app/routers/requests.py | 29 +++++++++++++++++++++++++++++ frontend/app/requests/[id]/page.tsx | 1 + 4 files changed, 36 insertions(+) diff --git a/backend/app/clients/radarr.py b/backend/app/clients/radarr.py index 569ca00..7698b00 100644 --- a/backend/app/clients/radarr.py +++ b/backend/app/clients/radarr.py @@ -21,6 +21,9 @@ class RadarrClient(ApiClient): async def get_queue(self, movie_id: int) -> Optional[Dict[str, Any]]: return await self.get("/api/v3/queue", params={"movieId": movie_id}) + async def get_indexers(self) -> Optional[Dict[str, Any]]: + return await self.get("/api/v3/indexer") + async def search(self, movie_id: int) -> Optional[Dict[str, Any]]: return await self.post("/api/v3/command", payload={"name": "MoviesSearch", "movieIds": [movie_id]}) diff --git a/backend/app/clients/sonarr.py b/backend/app/clients/sonarr.py index 65f1d96..71d0f51 100644 --- a/backend/app/clients/sonarr.py +++ b/backend/app/clients/sonarr.py @@ -18,6 +18,9 @@ class SonarrClient(ApiClient): async def get_queue(self, series_id: int) -> Optional[Dict[str, Any]]: return await self.get("/api/v3/queue", params={"seriesId": series_id}) + async def get_indexers(self) -> Optional[Dict[str, Any]]: + return await self.get("/api/v3/indexer") + async def get_episodes(self, series_id: int) -> Optional[Dict[str, Any]]: return await self.get("/api/v3/episode", params={"seriesId": series_id}) diff --git a/backend/app/routers/requests.py b/backend/app/routers/requests.py index 3de01df..99c08cd 100644 --- a/backend/app/routers/requests.py +++ b/backend/app/routers/requests.py @@ -1608,6 +1608,7 @@ async def action_grab( guid = payload.get("guid") indexer_id = payload.get("indexerId") download_url = payload.get("downloadUrl") + indexer_name = payload.get("indexerName") or payload.get("indexer") if not guid or not indexer_id: raise HTTPException(status_code=400, detail="Missing guid or indexerId") @@ -1617,6 +1618,20 @@ async def action_grab( if not client.configured(): raise HTTPException(status_code=400, detail="Sonarr not configured") try: + if indexer_name: + indexers = await client.get_indexers() + if isinstance(indexers, list): + matched = next( + ( + item + for item in indexers + if isinstance(item, dict) + and str(item.get("name", "")).lower() == str(indexer_name).lower() + ), + None, + ) + if matched and matched.get("id") is not None: + indexer_id = int(matched["id"]) response = await client.grab_release(str(guid), int(indexer_id)) except httpx.HTTPStatusError as exc: raise HTTPException(status_code=502, detail=f"Sonarr grab failed: {exc}") from exc @@ -1629,6 +1644,20 @@ async def action_grab( if not client.configured(): raise HTTPException(status_code=400, detail="Radarr not configured") try: + if indexer_name: + indexers = await client.get_indexers() + if isinstance(indexers, list): + matched = next( + ( + item + for item in indexers + if isinstance(item, dict) + and str(item.get("name", "")).lower() == str(indexer_name).lower() + ), + None, + ) + if matched and matched.get("id") is not None: + indexer_id = int(matched["id"]) response = await client.grab_release(str(guid), int(indexer_id)) except httpx.HTTPStatusError as exc: raise HTTPException(status_code=502, detail=f"Radarr grab failed: {exc}") from exc diff --git a/frontend/app/requests/[id]/page.tsx b/frontend/app/requests/[id]/page.tsx index 73cc0a1..015932a 100644 --- a/frontend/app/requests/[id]/page.tsx +++ b/frontend/app/requests/[id]/page.tsx @@ -590,6 +590,7 @@ export default function RequestTimelinePage({ params }: { params: { id: string } body: JSON.stringify({ guid: release.guid, indexerId: release.indexerId, + indexerName: release.indexer, downloadUrl: release.downloadUrl, }), }