From 05495e481ddd44c83572a8ebdee05fca78b57e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=AF=E5=A4=A7=E4=BE=A0?= Date: Sun, 13 Jul 2025 00:48:58 +0800 Subject: [PATCH] fix #4602 --- app/api/endpoints/transfer.py | 6 +----- app/chain/storage.py | 3 +-- app/core/config.py | 19 +++++++++++++++++++ app/helper/directory.py | 21 +++++++++++++++------ app/modules/filemanager/__init__.py | 8 +++----- app/modules/filemanager/transhandler.py | 3 +-- 6 files changed, 40 insertions(+), 20 deletions(-) diff --git a/app/api/endpoints/transfer.py b/app/api/endpoints/transfer.py index 2158f0d7..70ec280e 100644 --- a/app/api/endpoints/transfer.py +++ b/app/api/endpoints/transfer.py @@ -38,11 +38,7 @@ def query_name(path: str, filetype: str, return schemas.Response(success=False, message="未识别到新名称") if filetype == "dir": media_path = DirectoryHelper.get_media_root_path( - rename_format=( - settings.TV_RENAME_FORMAT - if mediainfo.type == MediaType.TV - else settings.MOVIE_RENAME_FORMAT - ), + rename_format=settings.RENAME_FORMAT(mediainfo.type), rename_path=Path(new_path), ) if media_path: diff --git a/app/chain/storage.py b/app/chain/storage.py index 2daf03bd..e4396e64 100644 --- a/app/chain/storage.py +++ b/app/chain/storage.py @@ -178,8 +178,7 @@ class StorageChain(ChainBase): if mtype: # 重命名格式 - rename_format = settings.TV_RENAME_FORMAT \ - if mtype == MediaType.TV else settings.MOVIE_RENAME_FORMAT + rename_format = settings.RENAME_FORMAT(mtype) media_path = DirectoryHelper.get_media_root_path( rename_format, rename_path=Path(fileitem.path) ) diff --git a/app/core/config.py b/app/core/config.py index 17cc23d8..80d938a3 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -1,6 +1,7 @@ import copy import json import os +import re import secrets import sys import threading @@ -13,6 +14,7 @@ from pydantic import BaseModel, BaseSettings, validator, Field from app.log import logger, log_settings, LogConfigModel from app.utils.system import SystemUtils from app.utils.url import UrlUtils +from app.schemas import MediaType class SystemConfModel(BaseModel): @@ -651,6 +653,23 @@ class Settings(BaseSettings, ConfigModel, LogConfigModel): return None return UrlUtils.combine_url(host=self.APP_DOMAIN, path=url) + def RENAME_FORMAT(self, media_type: MediaType): + """ + 获取指定类型的重命名格式 + + :param media_type: MediaType.TV 或 MediaType.Movie + :return: 重命名格式 + """ + rename_format = ( + self.TV_RENAME_FORMAT + if media_type == MediaType.TV + else self.MOVIE_RENAME_FORMAT + ) + # 规范重命名格式 + rename_format = rename_format.replace("\\", "/") + rename_format = re.sub(r'/+', '/', rename_format) + return rename_format.strip("/") + # 实例化配置 settings = Settings() diff --git a/app/helper/directory.py b/app/helper/directory.py index de5b2839..5af67197 100644 --- a/app/helper/directory.py +++ b/app/helper/directory.py @@ -1,3 +1,4 @@ +import re from pathlib import Path from typing import List, Optional @@ -8,6 +9,8 @@ from app.log import logger from app.schemas.types import SystemConfigKey from app.utils.system import SystemUtils +JINJA2_VAR_PATTERN = re.compile(r"\{\{.*?\}\}", re.DOTALL) + class DirectoryHelper: """ @@ -120,26 +123,32 @@ class DirectoryHelper: :param rename_path: 重命名后的路径 :return: 媒体文件根路径 """ + if not rename_format: + logger.error("重命名格式不能为空") + return None # 计算重命名中的文件夹层数 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): + matchs = JINJA2_VAR_PATTERN.findall(name) + if not matchs: + continue # 处理特例,有的人重命名的第一层是年份、分辨率 - if "{{title}}" in name: + if any("title" in m for m in matchs): # 找出含标题的这一层作为媒体根目录 rename_format_level -= level break else: # 假定第一层目录是媒体根目录 - logger.warn(f"重命名格式 {rename_format} 缺少 {{{{title}}}}") + logger.warn(f"重命名格式 {rename_format} 缺少标题参数") if rename_format_level > len(rename_path.parents): # 通常因为路径以/结尾,被Path规范化删除了 logger.error(f"路径 {rename_path} 不匹配重命名格式 {rename_format}") return None + if rename_format_level <= 0: + # 所有媒体文件都存在一个目录内的特殊需求 + rename_format_level = 1 # 媒体根路径 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 53523799..44bff9bc 100644 --- a/app/modules/filemanager/__init__.py +++ b/app/modules/filemanager/__init__.py @@ -140,8 +140,7 @@ class FileManagerModule(_ModuleBase): """ handler = TransHandler() # 重命名格式 - rename_format = settings.TV_RENAME_FORMAT \ - if mediainfo.type == MediaType.TV else settings.MOVIE_RENAME_FORMAT + rename_format = settings.RENAME_FORMAT(mediainfo.type) # 获取集信息 episodes_info: Optional[List[TmdbEpisode]] = None if mediainfo.type == MediaType.TV: @@ -534,8 +533,7 @@ class FileManagerModule(_ModuleBase): # 媒体分类路径 dir_path = handler.get_dest_dir(mediainfo=mediainfo, target_dir=dest_dir) # 重命名格式 - rename_format = settings.TV_RENAME_FORMAT \ - if mediainfo.type == MediaType.TV else settings.MOVIE_RENAME_FORMAT + rename_format = settings.RENAME_FORMAT(mediainfo.type) # 元数据补上常用属性,尽可能确保重命名后的路径不出现空白 meta = MetaInfo(mediainfo.title) if meta.type == MediaType.UNKNOWN and mediainfo.type is not None: @@ -560,7 +558,7 @@ class FileManagerModule(_ModuleBase): if not media_path: # 忽略 continue - if dir_path.is_relative_to(media_path): + if dir_path != media_path and dir_path.is_relative_to(media_path): # 兜底检查,避免不必要的扫盘 logger.warn(f"{media_path} 是媒体库目录 {dir_path} 的父目录,忽略获取媒体文件列表,请检查重命名格式!") continue diff --git a/app/modules/filemanager/transhandler.py b/app/modules/filemanager/transhandler.py index 57467048..2091bc8f 100644 --- a/app/modules/filemanager/transhandler.py +++ b/app/modules/filemanager/transhandler.py @@ -106,8 +106,7 @@ class TransHandler: try: # 重命名格式 - rename_format = settings.TV_RENAME_FORMAT \ - if mediainfo.type == MediaType.TV else settings.MOVIE_RENAME_FORMAT + rename_format = settings.RENAME_FORMAT(mediainfo.type) # 判断是否为文件夹 if fileitem.type == "dir":