diff --git a/app/modules/qbittorrent/__init__.py b/app/modules/qbittorrent/__init__.py index b1441376..d0b54839 100644 --- a/app/modules/qbittorrent/__init__.py +++ b/app/modules/qbittorrent/__init__.py @@ -195,9 +195,6 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): ignore_category_check=False ) - # 获取种子内容布局: `Original: 原始, Subfolder: 创建子文件夹, NoSubfolder: 不创建子文件夹` - torrent_layout = server.get_content_layout() - if not state: # 查询所有下载器的种子 torrents, error = server.get_torrents() @@ -210,7 +207,8 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): if torrent.get("name") == getattr(torrent_from_file, 'name', '') \ and torrent.get("total_size") == getattr(torrent_from_file, 'total_size', 0): torrent_hash = torrent.get("hash") - torrent_tags = [str(tag).strip() for tag in torrent.get("tags").split(',')] + server.delete_torrents_tag(torrent_hash, tag) + torrent_tags = [str(tag).strip() for tag in (torrent.get("tags") or "").split(',')] logger.warn(f"下载器中已存在该种子任务:{torrent_hash} - {torrent.get('name')}") # 给种子打上标签 if "已整理" in torrent_tags: @@ -218,7 +216,8 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): if settings.TORRENT_TAG and settings.TORRENT_TAG not in torrent_tags: logger.info(f"给种子 {torrent_hash} 打上标签:{settings.TORRENT_TAG}") server.set_torrents_tag(ids=torrent_hash, tags=[settings.TORRENT_TAG]) - server.delete_torrents_tag(torrent_hash, tag) + # 获取种子内容布局: `Original: 原始, Subfolder: 创建子文件夹, NoSubfolder: 不创建子文件夹` + torrent_layout = server.get_content_layout() return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, f"下载任务已存在" finally: torrents.clear() @@ -234,6 +233,8 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): if not torrent_hash: return None, None, None, f"下载任务添加成功,但获取Qbittorrent任务信息失败:{content}" else: + # 获取种子内容布局: `Original: 原始, Subfolder: 创建子文件夹, NoSubfolder: 不创建子文件夹` + torrent_layout = server.get_content_layout() if is_paused: # 种子文件 torrent_files = server.get_files( diff --git a/app/modules/qbittorrent/qbittorrent.py b/app/modules/qbittorrent/qbittorrent.py index 44903372..658dcbc5 100644 --- a/app/modules/qbittorrent/qbittorrent.py +++ b/app/modules/qbittorrent/qbittorrent.py @@ -303,14 +303,16 @@ class Qbittorrent: def delete_torrents_tag(self, ids: Union[str, list], tag: Union[str, list]) -> bool: """ - 删除Tag + 从指定种子移除标签,并删除全局标签定义 :param ids: 种子Hash列表 :param tag: 标签内容 + :return: 是否删除成功 """ if not self.qbc: return False try: - self.qbc.torrents_delete_tags(torrent_hashes=ids, tags=tag) + self.qbc.torrents_remove_tags(torrent_hashes=ids, tags=tag) + self.qbc.torrents_delete_tags(tags=tag) return True except Exception as err: logger.error(f"删除种子Tag出错:{str(err)}") diff --git a/tests/test_qbittorrent_compat.py b/tests/test_qbittorrent_compat.py index eb13980f..1b462d52 100644 --- a/tests/test_qbittorrent_compat.py +++ b/tests/test_qbittorrent_compat.py @@ -3,7 +3,7 @@ import sys import types from enum import Enum from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import call, MagicMock, patch def _load_qbittorrent_modules(): @@ -518,6 +518,9 @@ def test_download_prefers_added_torrent_ids_before_tag_lookup(): fake_server.delete_torrents_tag.assert_called_once_with("abc123", "tmp-tag-01") fake_server.get_torrent_id_by_tag.assert_not_called() assert fake_server.add_torrent.call_args.kwargs["tag"] == ["tmp-tag-01", "moviepilot-tag"] + assert fake_server.mock_calls.index( + call.delete_torrents_tag("abc123", "tmp-tag-01") + ) < fake_server.mock_calls.index(call.get_content_layout()) def test_download_falls_back_to_tag_lookup_when_added_ids_missing(): @@ -550,7 +553,7 @@ def test_download_removes_temporary_tag_from_existing_torrent(): "name": "test", "total_size": len(b"torrent-content"), "hash": "existing123", - "tags": "tmp-tag-01,moviepilot-tag", + "tags": None, }], None) module = _build_module(fake_server) @@ -563,6 +566,23 @@ def test_download_removes_temporary_tag_from_existing_torrent(): assert result == ("qb", "existing123", "Original", "下载任务已存在") fake_server.delete_torrents_tag.assert_called_once_with("existing123", "tmp-tag-01") + assert fake_server.mock_calls.index( + call.delete_torrents_tag("existing123", "tmp-tag-01") + ) < fake_server.mock_calls.index(call.get_content_layout()) + + +def test_delete_torrents_tag_uses_supported_qbittorrent_api_arguments(): + """删除标签时应分别调用任务移除接口和全局标签删除接口。""" + fake_client = MagicMock() + downloader = Qbittorrent.__new__(Qbittorrent) + downloader.qbc = fake_client + + assert downloader.delete_torrents_tag("abc123", "tmp-tag-01") + fake_client.torrents_remove_tags.assert_called_once_with( + torrent_hashes="abc123", + tags="tmp-tag-01", + ) + fake_client.torrents_delete_tags.assert_called_once_with(tags="tmp-tag-01") def test_get_files_retries_until_qbittorrent_files_available():