mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-03 22:04:57 +08:00
fix(download): respect configured directory priority (#7282)
This commit is contained in:
@@ -393,6 +393,18 @@ class DirectoryHelper:
|
||||
"""
|
||||
return sorted([d for d in self.get_dirs() if d.download_path], key=lambda x: x.priority or 0)
|
||||
|
||||
def get_download_dir(self, media: Optional[DirectoryMedia]) -> Optional[_SchemaTransferDirectoryConf]:
|
||||
"""
|
||||
按配置优先级返回首个媒体条件匹配且具有下载路径的目录。
|
||||
|
||||
类型和固定分类只用于过滤候选,不覆盖用户配置的优先级;同优先级保留配置顺序。
|
||||
|
||||
:param media: 待下载的影视或音乐媒体信息
|
||||
:return: 首个可用下载目录,无匹配时返回 None
|
||||
"""
|
||||
return next((directory for directory in self.get_download_dirs()
|
||||
if self.matches_media(directory, media)), None)
|
||||
|
||||
def get_local_download_dirs(self) -> List[_SchemaTransferDirectoryConf]:
|
||||
"""
|
||||
获取所有本地的可下载目录
|
||||
|
||||
@@ -335,7 +335,11 @@ class DownloadSubtitleOwner(_DownloadOwnerBase):
|
||||
save_path: Optional[str] = None,
|
||||
) -> Tuple[Optional[str], Optional[Path], str]:
|
||||
"""
|
||||
根据媒体信息解析下载目录。
|
||||
显式路径沿用原有校验与分类规则,默认路径按配置优先级选择可用下载目录。
|
||||
|
||||
:param media_info: 待下载媒体信息
|
||||
:param save_path: 显式保存路径;空白值视为未指定
|
||||
:return: 存储类型、保存目录及错误信息
|
||||
"""
|
||||
storage = 'local'
|
||||
save_path = specified_download_save_path(save_path)
|
||||
@@ -366,7 +370,7 @@ class DownloadSubtitleOwner(_DownloadOwnerBase):
|
||||
)
|
||||
return storage, target_dir, ""
|
||||
|
||||
dir_info = DirectoryHelper().get_dir(media_info, include_unsorted=True)
|
||||
dir_info = DirectoryHelper().get_download_dir(media_info)
|
||||
storage = (dir_info.storage or storage) if dir_info else storage
|
||||
if not dir_info:
|
||||
logger.error(f"未找到下载目录:{media_info.type.value if media_info.type else ""} {media_info.title_year}")
|
||||
|
||||
@@ -189,6 +189,6 @@ def test_resolve_media_download_dir_uses_default_dir_for_blank_save_path():
|
||||
"""
|
||||
default_dir = TransferDirectoryConf(name="剧集库", priority=1, storage="local", download_path="/downloads/tv")
|
||||
media = MediaInfo(type=MediaType.TV, title="测试剧集")
|
||||
with patch.object(DirectoryHelper, "get_dir", return_value=default_dir):
|
||||
with patch.object(DirectoryHelper, "get_download_dir", return_value=default_dir):
|
||||
result = DownloadSubtitleOwner._resolve_media_download_dir(media, save_path="")
|
||||
assert result == ("local", Path("/downloads/tv"), "")
|
||||
|
||||
@@ -388,6 +388,80 @@ def test_directory_priority_applies_only_within_same_match_rank(
|
||||
assert selected is high_priority
|
||||
|
||||
|
||||
@pytest.mark.parametrize("save_path", [None, "", " "])
|
||||
@pytest.mark.parametrize("fixed_category", [False, True])
|
||||
def test_default_download_respects_priority_before_match_specificity(
|
||||
directory_resolver: ClassificationCategoryResolver,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
save_path: str | None,
|
||||
fixed_category: bool,
|
||||
) -> None:
|
||||
"""
|
||||
未指定保存路径时,类型或固定分类更精确的目录不得盖过配置优先级。
|
||||
"""
|
||||
general = TransferDirectoryConf(
|
||||
name="全部", priority=0, download_path="/downloads/all",
|
||||
)
|
||||
specific = TransferDirectoryConf(
|
||||
name="电视剧", priority=1, media_type="tv", download_path="/downloads/tv",
|
||||
media_category_id="tv.anime.jp" if fixed_category else None,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
DirectoryHelper, "get_dirs", staticmethod(lambda: [specific, general]),
|
||||
)
|
||||
|
||||
result = DownloadSubtitleOwner._resolve_media_download_dir(_media(), save_path)
|
||||
|
||||
assert result == ("local", Path("/downloads/all"), "")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"overrides",
|
||||
[
|
||||
{"download_path": None, "library_path": "/library"},
|
||||
{"media_type": "movie"},
|
||||
{"media_category_id": "tv.deleted"},
|
||||
{"media_category": "其他"},
|
||||
],
|
||||
)
|
||||
def test_default_download_skips_unavailable_or_mismatched_directories(
|
||||
directory_resolver: ClassificationCategoryResolver,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
overrides: dict[str, object],
|
||||
) -> None:
|
||||
"""
|
||||
高优先级目录缺少下载路径、类型分类不符或分类失效时,继续选择可用目录。
|
||||
"""
|
||||
invalid = TransferDirectoryConf.model_validate({
|
||||
"priority": 0, "download_path": "/downloads/invalid", **overrides,
|
||||
})
|
||||
fallback = TransferDirectoryConf(priority=1, download_path="/downloads/fallback")
|
||||
monkeypatch.setattr(
|
||||
DirectoryHelper, "get_dirs", staticmethod(lambda: [invalid, fallback]),
|
||||
)
|
||||
assert DirectoryHelper(directory_resolver).get_download_dir(_media()) is fallback
|
||||
|
||||
monkeypatch.setattr(DirectoryHelper, "get_dirs", staticmethod(lambda: [invalid]))
|
||||
assert DownloadSubtitleOwner._resolve_media_download_dir(_media()) == (
|
||||
None, None, "未找到下载目录",
|
||||
)
|
||||
|
||||
|
||||
def test_default_download_preserves_configuration_order_for_equal_priority(
|
||||
directory_resolver: ClassificationCategoryResolver,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""
|
||||
未设置和显式零优先级相同时,按配置顺序选择而非分类精确度。
|
||||
"""
|
||||
first = TransferDirectoryConf(download_path="/downloads/first")
|
||||
second = TransferDirectoryConf(priority=0, media_type="tv", download_path="/downloads/second")
|
||||
monkeypatch.setattr(
|
||||
DirectoryHelper, "get_dirs", staticmethod(lambda: [first, second]),
|
||||
)
|
||||
assert DirectoryHelper(directory_resolver).get_download_dir(_media()) is first
|
||||
|
||||
|
||||
def test_directory_media_type_aliases_match_consistently(
|
||||
directory_resolver: ClassificationCategoryResolver,
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user