Merge pull request #6884 from MiCat-S/fix/downloader-add-failure-name

fix(downloader): 添加种子失败提示改用种子名称
This commit is contained in:
jxxghp
2026-10-04 20:29:41 +08:00
committed by GitHub
5 changed files with 100 additions and 6 deletions

View File

@@ -120,6 +120,9 @@ class QbittorrentModule(_DownloaderModuleBase[Qbittorrent]):
if not torrent_from_file and not is_magnet:
return None, None, None, f"添加种子任务失败:无法读取种子文件"
# 失败提示使用种子名称(磁力链接保留原文),不拼接种子文件的二进制内容
torrent_desc = torrent_from_file.name if torrent_from_file else content
# 获取下载器
server: Qbittorrent = self.get_instance(downloader)
if not server:
@@ -176,7 +179,7 @@ class QbittorrentModule(_DownloaderModuleBase[Qbittorrent]):
finally:
torrents.clear()
del torrents
return None, None, None, f"添加种子任务失败:{content}"
return None, None, None, f"添加种子任务失败:{torrent_desc}"
else:
# 获取种子Hash
torrent_hash = next(iter(added_torrent_ids), None)
@@ -185,7 +188,7 @@ class QbittorrentModule(_DownloaderModuleBase[Qbittorrent]):
if torrent_hash:
temporary_tag_cleaned = server.delete_torrents_tag(torrent_hash, tag)
if not torrent_hash:
return None, None, None, f"下载任务添加成功,但获取Qbittorrent任务信息失败:{content}"
return None, None, None, f"下载任务添加成功,但获取Qbittorrent任务信息失败:{torrent_desc}"
else:
# 获取种子内容布局: `Original: 原始, Subfolder: 创建子文件夹, NoSubfolder: 不创建子文件夹`
torrent_layout = server.get_content_layout()

View File

@@ -102,6 +102,9 @@ class RtorrentModule(_DownloaderModuleBase[Rtorrent]):
if not torrent_from_file and not is_magnet:
return None, None, None, f"添加种子任务失败:无法读取种子文件"
# 失败提示使用种子名称(磁力链接保留原文),不拼接种子文件的二进制内容
torrent_desc = torrent_from_file.name if torrent_from_file else content
# 获取下载器
server: Rtorrent = self.get_instance(downloader)
if not server:
@@ -176,7 +179,7 @@ class RtorrentModule(_DownloaderModuleBase[Rtorrent]):
finally:
torrents.clear()
del torrents
return None, None, None, f"添加种子任务失败:{content}"
return None, None, None, f"添加种子任务失败:{torrent_desc}"
else:
# 获取种子Hash
torrent_hash = server.get_torrent_id_by_tag(tags=tag)
@@ -185,7 +188,7 @@ class RtorrentModule(_DownloaderModuleBase[Rtorrent]):
None,
None,
None,
f"下载任务添加成功,但获取rTorrent任务信息失败:{content}",
f"下载任务添加成功,但获取rTorrent任务信息失败:{torrent_desc}",
)
else:
if is_paused:

View File

@@ -99,6 +99,9 @@ class TransmissionModule(_DownloaderModuleBase[Transmission]):
if not torrent_from_file and not is_magnet:
return None, None, None, f"添加种子任务失败:无法读取种子文件"
# 失败提示使用种子名称(磁力链接保留原文),不拼接种子文件的二进制内容
torrent_desc = torrent_from_file.name if torrent_from_file else content
# 获取下载器
server: Transmission = self.get_instance(downloader)
if not server:
@@ -153,7 +156,7 @@ class TransmissionModule(_DownloaderModuleBase[Transmission]):
finally:
torrents.clear()
del torrents
return None, None, None, f"添加种子任务失败:{content}"
return None, None, None, f"添加种子任务失败:{torrent_desc}"
else:
torrent_hash = added_torrent.hashString
if is_paused:

View File

@@ -234,8 +234,17 @@ async def test_chat_completions_provider_uses_google_compatible_request_options(
assert "reasoning" not in parameters
def test_official_google_provider_uses_native_tool_transport():
def test_official_google_provider_uses_native_tool_transport(monkeypatch):
"""官方 Gemini 主机必须走原生 SDK,避免 OpenAI 兼容层丢失 thought_signature。"""
import langchain_google_genai.chat_models as google_models
# 生产补丁会修改 SDK 模块级解析函数;测试结束时恢复,避免污染后续模型参数测试。
for name in ("_is_gemini_3_or_later", "_parse_chat_history"):
monkeypatch.setattr(google_models, name, getattr(google_models, name))
monkeypatch.setattr(
google_models, "_thought_signature_patched",
getattr(google_models, "_thought_signature_patched", False), raising=False,
)
settings = ModelSettings(
model="gemini-3.1-pro-preview",
base_url="https://generativelanguage.googleapis.com/v1beta",

View File

@@ -0,0 +1,76 @@
"""下载器添加任务失败时的提示文本。"""
from pathlib import Path
from unittest.mock import MagicMock
import pytest
from app.modules.qbittorrent import QbittorrentModule
from app.modules.rtorrent import RtorrentModule
from app.modules.transmission import TransmissionModule
_ANNOUNCE = b"https://tracker.invalid/announce?passkey=0123456789abcdef"
_PIECES = bytes(range(20))
_TORRENT = (
b"d8:announce" + str(len(_ANNOUNCE)).encode() + b":" + _ANNOUNCE
+ b"4:infod6:lengthi1024e4:name8:test.mkv12:piece lengthi16384e"
+ b"6:pieces" + str(len(_PIECES)).encode() + b":" + _PIECES + b"ee"
)
_MAGNET = "magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567"
def _build_module(module_cls, server):
"""构造只包含下载所需依赖的下载器模块。"""
module = module_cls.__new__(module_cls)
module.get_instance = MagicMock(return_value=server)
module.normalize_path = MagicMock(side_effect=lambda path, _downloader: str(path))
module.get_default_config_name = MagicMock(return_value="default")
return module
def _rejecting_server(module_cls):
"""下载器拒绝添加,且没有同名同大小的已有任务。"""
server = MagicMock()
if module_cls is QbittorrentModule:
server.add_torrent.return_value = (False, [])
elif module_cls is TransmissionModule:
server.add_torrent.return_value = None
else:
server.add_torrent.return_value = False
server.get_torrents.return_value = ([], False)
return server
@pytest.mark.parametrize("module_cls", [QbittorrentModule, TransmissionModule, RtorrentModule])
@pytest.mark.parametrize(
("content", "expected"),
[(_TORRENT, "添加种子任务失败:test.mkv"), (_MAGNET, f"添加种子任务失败:{_MAGNET}")],
ids=["torrent", "magnet"],
)
def test_rejected_download_reports_torrent_name_or_magnet(module_cls, content, expected):
"""种子文件被拒时提示种子名称,磁力链接保留原文,不拼接种子二进制内容。"""
module = _build_module(module_cls, _rejecting_server(module_cls))
result = module.download(content=content, download_dir=Path("/downloads"), cookie="")
assert result == (None, None, None, expected)
@pytest.mark.parametrize(
("module_cls", "expected"),
[
(QbittorrentModule, "下载任务添加成功,但获取Qbittorrent任务信息失败:test.mkv"),
(RtorrentModule, "下载任务添加成功,但获取rTorrent任务信息失败:test.mkv"),
],
ids=["qbittorrent", "rtorrent"],
)
def test_added_download_without_hash_reports_torrent_name(module_cls, expected):
"""添加成功但查不到任务时,提示同样使用种子名称。"""
server = MagicMock()
server.add_torrent.return_value = (True, []) if module_cls is QbittorrentModule else True
server.get_torrent_id_by_tag.return_value = None
module = _build_module(module_cls, server)
result = module.download(content=_TORRENT, download_dir=Path("/downloads"), cookie="")
assert result == (None, None, None, expected)