Merge pull request #3201 from InfinityPacer/feature/event

This commit is contained in:
jxxghp
2024-11-22 16:25:52 +08:00
committed by GitHub
4 changed files with 72 additions and 35 deletions

View File

@@ -84,7 +84,6 @@ class EventManager(metaclass=Singleton):
self.__disabled_handlers = set() # 禁用的事件处理器集合
self.__disabled_classes = set() # 禁用的事件处理器类集合
self.__lock = threading.Lock() # 线程锁
self.__processing_events = {} # 用于记录当前正在处理的事件 {event_hash: event}
def start(self):
"""
@@ -130,14 +129,6 @@ class EventManager(metaclass=Singleton):
for handler in handlers.values()
)
@staticmethod
def __get_event_hash(event: Event) -> str:
"""
计算事件的唯一标识符hash
"""
data_string = str(event.event_type.value) + str(event.event_data)
return str(uuid.uuid5(uuid.NAMESPACE_DNS, data_string))
def send_event(self, etype: Union[EventType, ChainEventType], data: Optional[Union[Dict, ChainEventData]] = None,
priority: int = DEFAULT_EVENT_PRIORITY) -> Optional[Event]:
"""
@@ -148,12 +139,6 @@ class EventManager(metaclass=Singleton):
:return: 如果是链式事件,返回处理后的事件数据;否则返回 None
"""
event = Event(etype, data, priority)
event_hash = self.__get_event_hash(event)
with self.__lock:
if event_hash in self.__processing_events:
logger.debug(f"Duplicate event ignored: {event}")
return None
self.__processing_events[event_hash] = event
if isinstance(etype, EventType):
self.__trigger_broadcast_event(event)
elif isinstance(etype, ChainEventType):
@@ -335,14 +320,9 @@ class EventManager(metaclass=Singleton):
"""
触发链式事件,按顺序调用订阅的处理器,并记录处理耗时
"""
try:
logger.debug(f"Triggering synchronous chain event: {event}")
dispatch = self.__dispatch_chain_event(event)
return event if dispatch else None
finally:
event_hash = self.__get_event_hash(event)
with self.__lock:
self.__processing_events.pop(event_hash, None)
logger.debug(f"Triggering synchronous chain event: {event}")
dispatch = self.__dispatch_chain_event(event)
return event if dispatch else None
def __trigger_broadcast_event(self, event: Event):
"""
@@ -383,9 +363,6 @@ class EventManager(metaclass=Singleton):
return
for handler_id, handler in handlers.items():
self.__executor.submit(self.__safe_invoke_handler, handler, event)
event_hash = self.__get_event_hash(event)
with self.__lock:
self.__processing_events.pop(event_hash, None)
def __safe_invoke_handler(self, handler: Callable, event: Event):
"""

View File

@@ -7,6 +7,7 @@ from jinja2 import Template
from app.core.config import settings
from app.core.context import MediaInfo
from app.core.event import eventmanager
from app.core.meta import MetaBase
from app.core.metainfo import MetaInfo, MetaInfoPath
from app.helper.directory import DirectoryHelper
@@ -16,7 +17,8 @@ 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
from app.schemas.types import MediaType, ModuleType
from app.schemas.event import SmartRenameEventData
from app.schemas.types import MediaType, ModuleType, ChainEventType
from app.utils.system import SystemUtils
lock = Lock()
@@ -130,7 +132,6 @@ class FileManagerModule(_ModuleBase):
)
return str(path)
def save_config(self, storage: str, conf: Dict) -> None:
"""
保存存储配置
@@ -1146,18 +1147,46 @@ class FileManagerModule(_ModuleBase):
# 文件后缀
"fileExt": file_ext,
# 自定义占位符
"customization": meta.customization
"customization": meta.customization,
# 文件元数据
"__meta__": meta,
# 识别的媒体信息
"__mediainfo__": mediainfo,
# 当前季的全部集信息
"__episodes_info__": episodes_info,
}
@staticmethod
def get_rename_path(template_string: str, rename_dict: dict, path: Path = None) -> Path:
"""
生成重命名后的完整路径
生成重命名后的完整路径,支持智能重命名事件
:param template_string: Jinja2 模板字符串
:param rename_dict: 渲染上下文,用于替换模板中的变量
:param path: 可选的基础路径,如果提供,将在其基础上拼接生成的路径
:return: 生成的完整路径
"""
# 创建jinja2模板对象
template = Template(template_string)
# 渲染生成的字符串
render_str = template.render(rename_dict)
logger.debug(f"Initial render string: {render_str}")
# 发送智能重命名事件
event_data = SmartRenameEventData(
template_string=template_string,
rename_dict=rename_dict,
render_str=render_str,
path=path
)
event = eventmanager.send_event(ChainEventType.SmartRename, event_data)
# 检查事件返回的结果
if event and event.event_data:
event_data: SmartRenameEventData = event.event_data
if event_data.updated and event_data.updated_str:
logger.debug(f"Render string updated by event: "
f"{render_str} -> {event_data.updated_str} (source: {event_data.source})")
render_str = event_data.updated_str
# 目的路径
if path:
return path / render_str

View File

@@ -1,4 +1,5 @@
from typing import Optional, Dict
from pathlib import Path
from typing import Optional, Dict, Any
from pydantic import BaseModel, Field, root_validator
@@ -114,3 +115,31 @@ class CommandRegisterEventData(ChainEventData):
# 输出参数
cancel: bool = Field(False, description="是否取消注册")
source: str = Field("未知拦截源", description="拦截源")
class SmartRenameEventData(ChainEventData):
"""
SmartRename 事件的数据模型
Attributes:
# 输入参数
template_string (str): Jinja2 模板字符串
rename_dict (dict): 渲染上下文
render_str (str): 渲染生成的字符串
path (Optional[Path]): 当前文件的目标路径
# 输出参数
updated (bool): 是否已更新,默认值为 False
updated_str (str): 更新后的字符串
source (str): 拦截源,默认值为 "未知拦截源"
"""
# 输入参数
template_string: str = Field(..., description="模板字符串")
rename_dict: Dict[str, Any] = Field(..., description="渲染上下文")
path: Optional[Path] = Field(None, description="文件的目标路径")
render_str: str = Field(..., description="渲染生成的字符串")
# 输出参数
updated: bool = Field(False, description="是否已更新")
updated_str: Optional[str] = Field(None, description="更新后的字符串")
source: Optional[str] = Field("未知拦截源", description="拦截源")

View File

@@ -60,14 +60,16 @@ class EventType(Enum):
# 同步链式事件
class ChainEventType(Enum):
# 名称识别请求
# 名称识别
NameRecognize = "name.recognize"
# 认证验证请求
# 认证验证
AuthVerification = "auth.verification"
# 认证拦截请求
# 认证拦截
AuthIntercept = "auth.intercept"
# 命令注册请求
# 命令注册
CommandRegister = "command.register"
# 智能重命名
SmartRename = "SmartRename"
# 系统配置Key字典