diff --git a/backend/src/module/downloader/rules.py b/backend/src/module/downloader/rules.py index 4187b181..4d199e53 100644 --- a/backend/src/module/downloader/rules.py +++ b/backend/src/module/downloader/rules.py @@ -14,10 +14,18 @@ def build_rss_rule(data: Bangumi | BangumiUpdate, save_path: str) -> dict: affected_feeds = ( data.rss_link if isinstance(data.rss_link, str) else ",".join(data.rss_link) ) + # filter is a comma-separated string of regex terms; qB wants them as a + # single alternation. join() would split the string into characters + # ("720,480" -> "7|2|0|,|4|8|0"); replace keeps whole terms ("720|480"). + must_not_contain = ( + data.filter.replace(",", "|") + if isinstance(data.filter, str) + else "|".join(data.filter) + ) return { "enable": True, "mustContain": data.title_raw, - "mustNotContain": "|".join(data.filter), + "mustNotContain": must_not_contain, "useRegex": True, "episodeFilter": "", "smartFilter": False, diff --git a/backend/src/test/test_download_client.py b/backend/src/test/test_download_client.py index 0e1e0620..85d6a62c 100644 --- a/backend/src/test/test_download_client.py +++ b/backend/src/test/test_download_client.py @@ -123,8 +123,8 @@ class TestSetRule: call_kwargs = mock_qb_client.rss_set_rule.call_args[1] rule = call_kwargs["rule_def"] assert rule["mustContain"] == "Mushoku Tensei" - # filter string is joined char-by-char with "|" (this is how the code works) - assert rule["mustNotContain"] == "|".join("720,480") + # comma-separated filter terms become a regex alternation for qB + assert rule["mustNotContain"] == "720|480" assert rule["enable"] is True assert "Season 2" in rule["savePath"]