fix: preserve download context when re-organizing from history

This commit is contained in:
YuF-9468
2026-03-09 18:11:23 +08:00
parent 643cda1abe
commit b4f64eb593
3 changed files with 73 additions and 4 deletions

View File

@@ -93,6 +93,8 @@ def manual_transfer(transer_item: ManualTransferItem,
:param _: Token校验 :param _: Token校验
""" """
force = False force = False
downloader = None
download_hash = None
target_path = Path(transer_item.target_path) if transer_item.target_path else None target_path = Path(transer_item.target_path) if transer_item.target_path else None
if transer_item.logid: if transer_item.logid:
# 查询历史记录 # 查询历史记录
@@ -101,6 +103,8 @@ def manual_transfer(transer_item: ManualTransferItem,
return schemas.Response(success=False, message=f"整理记录不存在ID{transer_item.logid}") return schemas.Response(success=False, message=f"整理记录不存在ID{transer_item.logid}")
# 强制转移 # 强制转移
force = True force = True
downloader = history.downloader
download_hash = history.download_hash
if history.status and ("move" in history.mode): if history.status and ("move" in history.mode):
# 重新整理成功的转移,则使用成功的 dest 做 in_path # 重新整理成功的转移,则使用成功的 dest 做 in_path
src_fileitem = FileItem(**history.dest_fileitem) src_fileitem = FileItem(**history.dest_fileitem)
@@ -121,6 +125,7 @@ def manual_transfer(transer_item: ManualTransferItem,
transer_item.tmdbid = int(history.tmdbid) if history.tmdbid else transer_item.tmdbid transer_item.tmdbid = int(history.tmdbid) if history.tmdbid else transer_item.tmdbid
transer_item.doubanid = str(history.doubanid) if history.doubanid else transer_item.doubanid transer_item.doubanid = str(history.doubanid) if history.doubanid else transer_item.doubanid
transer_item.season = int(str(history.seasons).replace("S", "")) if history.seasons else transer_item.season transer_item.season = int(str(history.seasons).replace("S", "")) if history.seasons else transer_item.season
transer_item.episode_group = history.episode_group or transer_item.episode_group
if history.episodes: if history.episodes:
if "-" in str(history.episodes): if "-" in str(history.episodes):
# E01-E03多集合并 # E01-E03多集合并
@@ -167,7 +172,9 @@ def manual_transfer(transer_item: ManualTransferItem,
library_type_folder=transer_item.library_type_folder, library_type_folder=transer_item.library_type_folder,
library_category_folder=transer_item.library_category_folder, library_category_folder=transer_item.library_category_folder,
force=force, force=force,
background=background background=background,
downloader=downloader,
download_hash=download_hash
) )
# 失败 # 失败
if not state: if not state:

View File

@@ -1634,7 +1634,9 @@ class TransferChain(ChainBase, ConfigReloadMixin, metaclass=Singleton):
library_type_folder: Optional[bool] = None, library_type_folder: Optional[bool] = None,
library_category_folder: Optional[bool] = None, library_category_folder: Optional[bool] = None,
force: Optional[bool] = False, force: Optional[bool] = False,
background: Optional[bool] = False) -> Tuple[bool, Union[str, list]]: background: Optional[bool] = False,
downloader: Optional[str] = None,
download_hash: Optional[str] = None) -> Tuple[bool, Union[str, list]]:
""" """
手动整理,支持复杂条件,带进度显示 手动整理,支持复杂条件,带进度显示
:param fileitem: 文件项 :param fileitem: 文件项
@@ -1653,6 +1655,8 @@ class TransferChain(ChainBase, ConfigReloadMixin, metaclass=Singleton):
:param library_category_folder: 是否按类别建立目录 :param library_category_folder: 是否按类别建立目录
:param force: 是否强制整理 :param force: 是否强制整理
:param background: 是否后台运行 :param background: 是否后台运行
:param downloader: 下载器名称
:param download_hash: 下载任务哈希
""" """
logger.info(f"手动整理:{fileitem.path} ...") logger.info(f"手动整理:{fileitem.path} ...")
if tmdbid or doubanid: if tmdbid or doubanid:
@@ -1682,7 +1686,9 @@ class TransferChain(ChainBase, ConfigReloadMixin, metaclass=Singleton):
library_category_folder=library_category_folder, library_category_folder=library_category_folder,
force=force, force=force,
background=background, background=background,
manual=True manual=True,
downloader=downloader,
download_hash=download_hash
) )
if not state: if not state:
return False, errmsg return False, errmsg
@@ -1703,7 +1709,9 @@ class TransferChain(ChainBase, ConfigReloadMixin, metaclass=Singleton):
library_category_folder=library_category_folder, library_category_folder=library_category_folder,
force=force, force=force,
background=background, background=background,
manual=True) manual=True,
downloader=downloader,
download_hash=download_hash)
return state, errmsg return state, errmsg
def send_transfer_message(self, meta: MetaBase, mediainfo: MediaInfo, def send_transfer_message(self, meta: MetaBase, mediainfo: MediaInfo,

View File

@@ -0,0 +1,54 @@
from types import ModuleType, SimpleNamespace
import sys
# The endpoint import pulls in a wide plugin/helper graph. Some optional modules are
# not present in this test environment, so stub them before importing the endpoint.
sys.modules.setdefault("app.helper.sites", ModuleType("app.helper.sites"))
setattr(sys.modules["app.helper.sites"], "SitesHelper", object)
from app.api.endpoints.transfer import manual_transfer
from app.schemas import ManualTransferItem
def test_manual_transfer_from_history_preserves_download_context(monkeypatch):
history = SimpleNamespace(
status=0,
mode="copy",
src_fileitem={"storage": "local", "path": "/downloads/test.mkv", "name": "test.mkv", "type": "file"},
dest_fileitem=None,
downloader="qbittorrent",
download_hash="abc123",
type="电视剧",
tmdbid="100",
doubanid="200",
seasons="S01",
episodes="E01-E02",
episode_group="WEB-DL",
)
captured = {}
def fake_get(_db, logid):
assert logid == 1
return history
class FakeTransferChain:
def manual_transfer(self, **kwargs):
captured.update(kwargs)
return True, ""
monkeypatch.setattr("app.api.endpoints.transfer.TransferHistory.get", fake_get)
monkeypatch.setattr("app.api.endpoints.transfer.TransferChain", FakeTransferChain)
resp = manual_transfer(
transer_item=ManualTransferItem(logid=1, from_history=True),
background=True,
db=object(),
_="token",
)
assert resp.success is True
assert captured["downloader"] == "qbittorrent"
assert captured["download_hash"] == "abc123"
assert captured["episode_group"] == "WEB-DL"
assert captured["season"] == 1