From c4602070b1f172a5189b7108a0a772a556cf0228 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Wed, 10 Jun 2026 06:59:23 +0800 Subject: [PATCH] fix: create missing subtitle download directories --- app/modules/subtitle/__init__.py | 19 ++---- tests/test_subtitle_links.py | 101 +++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 13 deletions(-) diff --git a/app/modules/subtitle/__init__.py b/app/modules/subtitle/__init__.py index d305ccf3..17564f1f 100644 --- a/app/modules/subtitle/__init__.py +++ b/app/modules/subtitle/__init__.py @@ -202,25 +202,18 @@ class SubtitleModule(_ModuleBase): fileURI = FileURI.from_uri(download_dir.as_posix()) storage = fileURI.storage download_dir = Path(fileURI.path) + target_dir = download_dir / folder_name if folder_name else download_dir for _ in range(30): - found = storageChain.get_file_item(storage, download_dir / folder_name) + found = storageChain.get_file_item(storage, target_dir) if found: working_dir_item = found break time.sleep(1) - # 目录仍然不存在,且有文件夹名,则创建目录 - if not working_dir_item and folder_name: - parent_dir_item = storageChain.get_folder(storage, download_dir) - if parent_dir_item: - working_dir_item = storageChain.create_folder( - parent_dir_item, - folder_name - ) - else: - logger.error(f"下载根目录不存在,无法创建字幕文件夹:{download_dir}") - return + # 下载器可能还未创建保存目录,字幕保存前需要按完整目标路径补齐目录。 if not working_dir_item: - logger.error(f"下载目录不存在,无法保存字幕:{download_dir / folder_name}") + working_dir_item = storageChain.get_folder(storage, target_dir) + if not working_dir_item: + logger.error(f"下载目录不存在,无法保存字幕:{target_dir}") return # 读取网站代码 sublink_list = self._get_subtitle_links(torrent) diff --git a/tests/test_subtitle_links.py b/tests/test_subtitle_links.py index 745c3eac..02f0c879 100644 --- a/tests/test_subtitle_links.py +++ b/tests/test_subtitle_links.py @@ -1,9 +1,66 @@ +from pathlib import Path + from lxml import etree +from app.core.context import Context, TorrentInfo from app.modules.subtitle import SubtitleModule +from app.schemas.file import FileItem + + +class _FakeStorageChain: + """ + 模拟字幕下载使用的存储链,记录目录查询与创建行为。 + """ + + def __init__(self): + """ + 初始化调用记录。 + """ + self.file_item_paths = [] + self.created_paths = [] + self.uploaded_files = [] + + def get_file_item(self, storage, path): + """ + 记录文件项查询,模拟目标目录和字幕文件都不存在。 + """ + self.file_item_paths.append((storage, path)) + return None + + def get_folder(self, storage, path): + """ + 记录递归创建目录请求,并返回创建后的目录项。 + """ + self.created_paths.append((storage, path)) + return FileItem(storage=storage, type="dir", path=path.as_posix(), name=path.name) + + def upload_file(self, fileitem, path): + """ + 记录上传请求,并返回上传后的文件项。 + """ + self.uploaded_files.append((fileitem, path)) + return FileItem( + storage=fileitem.storage, + type="file", + path=(path.parent / path.name).as_posix(), + name=path.name, + ) + + +class _FakeResponse: + """ + 构造字幕下载响应对象。 + """ + + status_code = 200 + content = b"subtitle" + headers = {"Content-Disposition": 'attachment; filename="example.srt"'} def test_parse_subtitle_links_filters_detail_page_action_links(): + """ + 详情页解析字幕链接时应过滤上传和外部搜索动作链接。 + """ html_text = """ 字幕 @@ -43,3 +100,47 @@ def test_parse_subtitle_links_filters_detail_page_action_links(): assert links == [ "https://audiences.me/downloadsubs.php?torrentid=621182&subid=2148" ] + + +def test_download_added_creates_missing_target_directory(monkeypatch): + """ + 下载字幕时目标目录不存在,应按完整下载目录自动创建后再保存字幕。 + """ + storage_chain = _FakeStorageChain() + module = SubtitleModule() + context = Context( + torrent_info=TorrentInfo( + page_url="https://example.test/details.php?id=1", + site_cookie="cookie", + site_ua="ua", + ) + ) + + monkeypatch.setattr("app.modules.subtitle.StorageChain", lambda: storage_chain) + monkeypatch.setattr( + "app.modules.subtitle.TorrentHelper.get_fileinfo_from_torrent_content", + lambda self, content: ("Example Folder", []), + ) + monkeypatch.setattr( + "app.modules.subtitle.TorrentHelper.get_url_filename", + lambda response, url: "example.srt", + ) + monkeypatch.setattr( + "app.modules.subtitle.RequestUtils", + lambda **kwargs: type( + "FakeRequest", + (), + {"get_res": lambda self, url: _FakeResponse()}, + )(), + ) + monkeypatch.setattr("app.modules.subtitle.time.sleep", lambda seconds: None) + monkeypatch.setattr(module, "_get_subtitle_links", lambda torrent: ["https://example.test/subtitle.srt"]) + + module.download_added( + context=context, + download_dir=Path("/downloads"), + torrent_content=b"torrent", + ) + + assert storage_chain.created_paths == [("local", Path("/downloads/Example Folder"))] + assert storage_chain.uploaded_files