From 8ea0a3287937b1f9d96db40ebd555f94c575b613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=AF=E5=A4=A7=E4=BE=A0?= Date: Tue, 8 Jul 2025 21:41:40 +0800 Subject: [PATCH] =?UTF-8?q?fix=20=E4=BC=98=E5=8C=96=E9=87=8D=E5=91=BD?= =?UTF-8?q?=E5=90=8D=E5=90=8E=E7=9A=84=E5=AA=92=E4=BD=93=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=A0=B9=E8=B7=AF=E5=BE=84=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/endpoints/transfer.py | 22 +++++++++++++--- app/chain/storage.py | 10 ++++---- app/helper/directory.py | 34 +++++++++++++++++++++++++ app/modules/filemanager/__init__.py | 18 +++++-------- app/modules/filemanager/transhandler.py | 33 ++++++++++++++++++++---- 5 files changed, 92 insertions(+), 25 deletions(-) diff --git a/app/api/endpoints/transfer.py b/app/api/endpoints/transfer.py index 9399cbc5..2158f0d7 100644 --- a/app/api/endpoints/transfer.py +++ b/app/api/endpoints/transfer.py @@ -8,11 +8,13 @@ from app import schemas from app.chain.media import MediaChain from app.chain.storage import StorageChain from app.chain.transfer import TransferChain +from app.core.config import settings from app.core.metainfo import MetaInfoPath from app.core.security import verify_token, verify_apitoken from app.db import get_db from app.db.models.transferhistory import TransferHistory from app.db.user_oper import get_current_active_superuser +from app.helper.directory import DirectoryHelper from app.schemas import MediaType, FileItem, ManualTransferItem router = APIRouter() @@ -35,11 +37,23 @@ def query_name(path: str, filetype: str, if not new_path: return schemas.Response(success=False, message="未识别到新名称") if filetype == "dir": - parents = Path(new_path).parents - if len(parents) > 2: - new_name = parents[1].name + media_path = DirectoryHelper.get_media_root_path( + rename_format=( + settings.TV_RENAME_FORMAT + if mediainfo.type == MediaType.TV + else settings.MOVIE_RENAME_FORMAT + ), + rename_path=Path(new_path), + ) + if media_path: + new_name = media_path.name else: - new_name = parents[0].name + # fallback + parents = Path(new_path).parents + if len(parents) > 2: + new_name = parents[1].name + else: + new_name = parents[0].name else: new_name = Path(new_path).name return schemas.Response(success=True, data={ diff --git a/app/chain/storage.py b/app/chain/storage.py index c5ad52ea..2daf03bd 100644 --- a/app/chain/storage.py +++ b/app/chain/storage.py @@ -180,13 +180,13 @@ class StorageChain(ChainBase): # 重命名格式 rename_format = settings.TV_RENAME_FORMAT \ if mtype == MediaType.TV else settings.MOVIE_RENAME_FORMAT - # 计算重命名中的文件夹层数 - rename_format_level = len(rename_format.split("/")) - 1 - if rename_format_level < 1: + media_path = DirectoryHelper.get_media_root_path( + rename_format, rename_path=Path(fileitem.path) + ) + if not media_path: return True # 处理媒体文件根目录 - dir_item = self.get_file_item(storage=fileitem.storage, - path=Path(fileitem.path).parents[rename_format_level - 1]) + dir_item = self.get_file_item(storage=fileitem.storage, path=media_path) else: # 处理上级目录 dir_item = self.get_parent_item(fileitem) diff --git a/app/helper/directory.py b/app/helper/directory.py index d1a3b7d9..de5b2839 100644 --- a/app/helper/directory.py +++ b/app/helper/directory.py @@ -4,6 +4,7 @@ from typing import List, Optional from app import schemas from app.core.context import MediaInfo from app.db.systemconfig_oper import SystemConfigOper +from app.log import logger from app.schemas.types import SystemConfigKey from app.utils.system import SystemUtils @@ -109,3 +110,36 @@ class DirectoryHelper: return matched_dir return matched_dirs[0] return None + + @staticmethod + def get_media_root_path(rename_format: str, rename_path: Path) -> Optional[Path]: + """ + 获取重命名后的媒体文件根路径 + + :param rename_format: 重命名格式 + :param rename_path: 重命名后的路径 + :return: 媒体文件根路径 + """ + # 计算重命名中的文件夹层数 + rename_list = rename_format.split("/") + rename_format_level = len(rename_list) - 1 + if rename_format_level <= 0: + # 无效重命名格式 + logger.error(f"重命名格式 {rename_format} 不正确") + return None + for level, name in enumerate(rename_list): + # 处理特例,有的人重命名的第一层是年份、分辨率 + if "{{title}}" in name: + # 找出含标题的这一层作为媒体根目录 + rename_format_level -= level + break + else: + # 假定第一层目录是媒体根目录 + logger.warn(f"重命名格式 {rename_format} 缺少 {{{{title}}}}") + if rename_format_level > len(rename_path.parents): + # 通常因为路径以/结尾,被Path规范化删除了 + logger.error(f"路径 {rename_path} 不匹配重命名格式 {rename_format}") + return None + # 媒体根路径 + media_root = rename_path.parents[rename_format_level - 1] + return media_root diff --git a/app/modules/filemanager/__init__.py b/app/modules/filemanager/__init__.py index 18bf543b..719d050e 100644 --- a/app/modules/filemanager/__init__.py +++ b/app/modules/filemanager/__init__.py @@ -547,17 +547,13 @@ class FileManagerModule(_ModuleBase): rename_dict=handler.get_naming_dict(meta=meta, mediainfo=mediainfo) ) - # 计算重命名中的文件夹层数 - rename_list = rename_format.split("/") - rename_format_level = len(rename_list) - 1 - for level, name in enumerate(rename_list): - # 处理特例,有的人重命名第一层是年份、分辨率 - if "{{title}}" in name: - # 找出含标题的这一层作为扫描路径 - rename_format_level -= level - break - # 取相对路径的第1层目录 - media_path = target_path.parents[rename_format_level - 1] + # 获取重命名后的媒体文件根路径 + media_path = DirectoryHelper.get_media_root_path( + rename_format, rename_path=target_path + ) + if not media_path: + # 忽略 + continue if dir_path.is_relative_to(media_path): # 兜底检查,避免不必要的扫盘 logger.warn(f"{media_path} 是媒体库目录 {dir_path} 的父目录,忽略获取媒体文件列表,请检查重命名格式!") diff --git a/app/modules/filemanager/transhandler.py b/app/modules/filemanager/transhandler.py index 67f8dceb..6fb1a311 100644 --- a/app/modules/filemanager/transhandler.py +++ b/app/modules/filemanager/transhandler.py @@ -10,6 +10,7 @@ from app.core.context import MediaInfo from app.core.event import eventmanager from app.core.meta import MetaBase from app.core.metainfo import MetaInfoPath +from app.helper.directory import DirectoryHelper from app.helper.message import TemplateHelper from app.log import logger from app.modules.filemanager.storages import StorageBase @@ -116,7 +117,19 @@ class TransHandler: template_string=rename_format, rename_dict=self.get_naming_dict(meta=in_meta, mediainfo=mediainfo) - ).parent + ) + new_path = DirectoryHelper.get_media_root_path( + rename_format, rename_path=new_path + ) + if not new_path: + self.__set_result( + success=False, + message="重命名格式无效", + fileitem=fileitem, + transfer_type=transfer_type, + need_notify=need_notify, + ) + return self.result else: new_path = target_path / fileitem.name # 整理目录 @@ -156,7 +169,7 @@ class TransHandler: if in_meta.begin_episode is None: logger.warn(f"文件 {fileitem.path} 整理失败:未识别到文件集数") self.__set_result(success=False, - message=f"未识别到文件集数", + message="未识别到文件集数", fileitem=fileitem, fail_list=[fileitem.path], transfer_type=transfer_type, @@ -185,9 +198,19 @@ class TransHandler: file_ext=f".{fileitem.extension}" ) ) - # 计算重命名中的文件夹层级 - rename_format_level = len(rename_format.split("/")) - 1 - folder_path = new_file.parents[rename_format_level - 1] + folder_path = DirectoryHelper.get_media_root_path( + rename_format, rename_path=new_file + ) + if not folder_path: + self.__set_result( + success=False, + message="重命名格式无效", + fileitem=fileitem, + fail_list=[fileitem.path], + transfer_type=transfer_type, + need_notify=need_notify, + ) + return self.result else: new_file = target_path / fileitem.name folder_path = target_path