diff --git a/app/modules/filemanager/__init__.py b/app/modules/filemanager/__init__.py index acbc9894..d81ce5b4 100644 --- a/app/modules/filemanager/__init__.py +++ b/app/modules/filemanager/__init__.py @@ -16,7 +16,8 @@ from app.helper.module import ModuleHelper from app.log import logger from app.modules import _ModuleBase from app.modules.filemanager.storages import StorageBase -from app.schemas import TransferInfo, ExistMediaInfo, TmdbEpisode, TransferDirectoryConf, FileItem, StorageUsage, TransferRenameEventData +from app.schemas import TransferInfo, ExistMediaInfo, TmdbEpisode, TransferDirectoryConf, FileItem, StorageUsage, \ + TransferRenameEventData, TransferInterceptEventData from app.schemas.types import MediaType, ModuleType, ChainEventType, OtherModulesType from app.utils.system import SystemUtils @@ -763,6 +764,21 @@ class FileManagerModule(_ModuleBase): target_item = target_oper.get_folder(target_path) if not target_item: return None, f"获取目标目录失败:{target_path}" + event_data = TransferInterceptEventData( + fileitem=fileitem, + target_storage=target_storage, + target_path=target_path, + transfer_type=transfer_type + ) + event = eventmanager.send_event(ChainEventType.TransferRename, event_data) + if event and event.event_data: + event_data = event.event_data + # 如果事件被取消,跳过文件整理 + if event_data.cancel: + logger.debug( + f"Transfer dir canceled by event: {event_data.source}," + f"Reason: {event_data.reason}") + return None, event_data.reason # 处理所有文件 state, errmsg = self.__transfer_dir_files(fileitem=fileitem, target_storage=target_storage, @@ -830,6 +846,24 @@ class FileManagerModule(_ModuleBase): target_file.unlink() logger.info(f"正在整理文件:【{fileitem.storage}】{fileitem.path} 到 【{target_storage}】{target_file}," f"操作类型:{transfer_type}") + event_data = TransferInterceptEventData( + fileitem=fileitem, + target_storage=target_storage, + target_path=target_file, + transfer_type=transfer_type, + options={ + "over_flag": over_flag + } + ) + event = eventmanager.send_event(ChainEventType.TransferRename, event_data) + if event and event.event_data: + event_data = event.event_data + # 如果事件被取消,跳过文件整理 + if event_data.cancel: + logger.debug( + f"Transfer file canceled by event: {event_data.source}," + f"Reason: {event_data.reason}") + return None, event_data.reason new_item, errmsg = self.__transfer_command(fileitem=fileitem, target_storage=target_storage, target_file=target_file, @@ -1127,7 +1161,7 @@ class FileManagerModule(_ModuleBase): if episode.episode_number == meta.begin_episode: episode_date = episode.air_date break - + return { # 标题 "title": __convert_invalid_characters(mediainfo.title), diff --git a/app/schemas/event.py b/app/schemas/event.py index ea57c78e..c2c74a98 100644 --- a/app/schemas/event.py +++ b/app/schemas/event.py @@ -3,7 +3,7 @@ from typing import Optional, Dict, Any, List, Set from pydantic import BaseModel, Field, root_validator -from app.schemas import MessageChannel +from app.schemas import MessageChannel, FileItem class BaseEventData(BaseModel): @@ -50,7 +50,7 @@ class AuthCredentials(ChainEventData): service: Optional[str] = Field(default=None, description="服务名称") @root_validator(pre=True) - def check_fields_based_on_grant_type(cls, values): # noqa + def check_fields_based_on_grant_type(cls, values): # noqa grant_type = values.get("grant_type") if not grant_type: values["grant_type"] = "password" @@ -202,3 +202,32 @@ class ResourceDownloadEventData(ChainEventData): cancel: bool = Field(default=False, description="是否取消下载") source: str = Field(default="未知拦截源", description="拦截源") reason: str = Field(default="", description="拦截原因") + + +class TransferInterceptEventData(ChainEventData): + """ + TransferIntercept 事件的数据模型 + + Attributes: + # 输入参数 + fileitem (FileItem): 源文件 + target_storage (str): 目标存储 + target_path (Path): 目标路径 + transfer_type (str): 整理方式(copy、move、link、softlink等) + options (dict): 其他参数 + + # 输出参数 + cancel (bool): 是否取消下载,默认值为 False + source (str): 拦截源,默认值为 "未知拦截源" + reason (str): 拦截原因,描述拦截的具体原因 + """ + fileitem: FileItem = Field(..., description="源文件") + target_storage: str = Field(..., description="目标存储") + target_path: Path = Field(..., description="目标路径") + transfer_type: str = Field(..., description="整理方式") + options: Optional[dict] = Field(None, description="其他参数") + + # 输出参数 + cancel: bool = Field(default=False, description="是否取消整理") + source: str = Field(default="未知拦截源", description="拦截源") + reason: str = Field(default="", description="拦截原因") diff --git a/app/schemas/types.py b/app/schemas/types.py index 84f59631..05550f40 100644 --- a/app/schemas/types.py +++ b/app/schemas/types.py @@ -75,6 +75,8 @@ class ChainEventType(Enum): CommandRegister = "command.register" # 整理重命名 TransferRename = "transfer.rename" + # 整理拦截 + TransferIntercept = "transfer.intercept" # 资源选择 ResourceSelection = "resource.selection" # 资源下载