diff --git a/backend/src/module/api/rss.py b/backend/src/module/api/rss.py index 5a660005..d4362e6c 100644 --- a/backend/src/module/api/rss.py +++ b/backend/src/module/api/rss.py @@ -1,6 +1,7 @@ from fastapi import APIRouter, Depends from fastapi.responses import JSONResponse +from module.conf.search_provider import get_provider from module.database import Database, get_db from module.downloader import DownloadClient from module.manager import SeasonCollector @@ -204,5 +205,10 @@ async def download_collection(data: Bangumi): "/subscribe", response_model=APIResponse, dependencies=[Depends(get_current_user)] ) async def subscribe(data: Bangumi, rss: RSSItem): - resp = await SeasonCollector.subscribe_season(data, parser=rss.parser) + # 搜索订阅时前端传来的是站点名(nyaa/dmhy/mikan),而分析器只认识解析器 + # 类型 mikan/tmdb(见 rss/analyser.py),站点名会静默跳过 TMDB 补全(#1053)。 + # 这里按搜索源配置把站点名映射为解析器;已是解析器类型的值原样透传。 + providers = get_provider() + parser = providers[rss.parser]["parser"] if rss.parser in providers else rss.parser + resp = await SeasonCollector.subscribe_season(data, parser=parser) return u_response(resp) diff --git a/backend/src/test/test_api_rss.py b/backend/src/test/test_api_rss.py index 3500d86c..258be53c 100644 --- a/backend/src/test/test_api_rss.py +++ b/backend/src/test/test_api_rss.py @@ -361,3 +361,61 @@ class TestSubscribe: ) assert response.status_code == 200 + + _PROVIDERS = { + "mikan": { + "url": "https://mikanani.me/RSS/Search?searchstr=%s", + "parser": "mikan", + }, + "nyaa": {"url": "https://nyaa.si/?page=rss&q=%s", "parser": "tmdb"}, + } + + def test_subscribe_site_name_maps_to_provider_parser(self, authed_client): + """搜索订阅传入站点名(如 nyaa)时应映射为该站点配置的解析器(#1053)。""" + resp_model = ResponseModel( + status=True, status_code=200, msg_en="Subscribed.", msg_zh="订阅成功。" + ) + with ( + patch( + "module.api.rss.SeasonCollector.subscribe_season", + new_callable=AsyncMock, + return_value=resp_model, + ) as mock_subscribe, + patch("module.api.rss.get_provider", return_value=self._PROVIDERS), + ): + response = authed_client.post( + "/api/v1/rss/subscribe", + json={ + "data": make_bangumi(id=1).model_dump(), + "rss": {"url": "https://nyaa.si/?page=rss&q=x", "parser": "nyaa"}, + }, + ) + + assert response.status_code == 200 + assert mock_subscribe.await_args is not None + assert mock_subscribe.await_args.kwargs["parser"] == "tmdb" + + def test_subscribe_parser_value_passes_through_unchanged(self, authed_client): + """已是解析器类型的值(非站点名)应原样传递。""" + resp_model = ResponseModel( + status=True, status_code=200, msg_en="Subscribed.", msg_zh="订阅成功。" + ) + with ( + patch( + "module.api.rss.SeasonCollector.subscribe_season", + new_callable=AsyncMock, + return_value=resp_model, + ) as mock_subscribe, + patch("module.api.rss.get_provider", return_value=self._PROVIDERS), + ): + response = authed_client.post( + "/api/v1/rss/subscribe", + json={ + "data": make_bangumi(id=1).model_dump(), + "rss": {"url": "https://example.com/rss", "parser": "tmdb"}, + }, + ) + + assert response.status_code == 200 + assert mock_subscribe.await_args is not None + assert mock_subscribe.await_args.kwargs["parser"] == "tmdb"