diff --git a/app/routers/qbit.py b/app/routers/qbit.py index 564e880..1a9f6fe 100644 --- a/app/routers/qbit.py +++ b/app/routers/qbit.py @@ -88,7 +88,7 @@ async def webapi_version() -> Response: @router.get("/api/v2/app/preferences", dependencies=[Depends(_require_sid)]) async def app_preferences() -> dict: - return {} + return {"save_path": "/downloads"} @router.get("/api/v2/transfer/info", dependencies=[Depends(_require_sid)]) @@ -180,9 +180,19 @@ async def torrents_properties(hash: str) -> dict: } +_categories: dict[str, dict] = {} + + @router.get("/api/v2/torrents/categories", dependencies=[Depends(_require_sid)]) async def torrents_categories() -> dict: - return {} + return _categories + + +@router.post("/api/v2/torrents/createCategory", dependencies=[Depends(_require_sid)]) +async def torrents_create_category(category: str = Form(""), savePath: str = Form("")) -> Response: + if category: + _categories[category] = {"name": category, "savePath": savePath} + return _plain("Ok.") @router.get("/api/v2/torrents/tags", dependencies=[Depends(_require_sid)]) diff --git a/app/routers/torznab.py b/app/routers/torznab.py index bd7827f..aa2c2ff 100644 --- a/app/routers/torznab.py +++ b/app/routers/torznab.py @@ -58,10 +58,9 @@ async def torznab_api( if t in ("tvsearch", "search"): if not q or len(q) < 2: + releases = await torznab.latest_releases() return Response( - torznab.error_xml(200, "Paramètre q requis"), - media_type="application/xml", - status_code=400, + torznab.results_xml(base, key, releases), media_type="application/rss+xml" ) try: releases = await torznab.tvsearch(q, season=season, ep=ep) diff --git a/app/services/sonarr.py b/app/services/sonarr.py index c83a18b..91c0227 100644 --- a/app/services/sonarr.py +++ b/app/services/sonarr.py @@ -50,6 +50,7 @@ class SonarrService: base_url=url, timeout=_REQUEST_TIMEOUT, headers={"X-Api-Key": apikey}, + verify=False, # reverse proxy swizzin : certificat auto-signé (LAN uniquement) ) async def _get(self, path: str, params: dict | None = None) -> dict | list | None: diff --git a/app/services/torznab.py b/app/services/torznab.py index 9c6d248..6a6768a 100644 --- a/app/services/torznab.py +++ b/app/services/torznab.py @@ -169,6 +169,31 @@ class TorznabService: """Recherche libre : tous les épisodes des fiches trouvées.""" return await self.tvsearch(q) + async def latest_releases(self) -> list[Release]: + """Flux RSS (Sonarr) : dernier épisode de chaque nouveauté du catalogue.""" + releases: list[Release] = [] + for source in await self._enabled_sources(): + try: + latest = await asyncio.wait_for(source.latest(), timeout=_SEARCH_TIMEOUT) + except (ScrapeError, TimeoutError) as exc: + logger.warning("Torznab : nouveautés %s KO : %s", source.name, exc) + continue + for result in latest[:_MAX_SERIES_PER_SOURCE]: + try: + episodes = await self._episodes_of(source, result.source_id) + except (ScrapeError, TimeoutError): + continue + whole = [e for e in episodes if e.number == int(e.number)] + if not whole: + continue + newest = max(whole, key=lambda e: (e.season, e.number)) + releases.extend( + self._releases_for(result.title, source, result.source_id, [newest], None, None) + ) + if len(releases) >= _MAX_RELEASES: + return releases[:_MAX_RELEASES] + return releases + async def _search_source(self, source: SourceScraper, q: str): try: return await asyncio.wait_for(source.search(q), timeout=_SEARCH_TIMEOUT)