refactor: complete host module and event contracts

This commit is contained in:
jxxghp
2026-08-22 13:21:52 +08:00
parent e61b5168ad
commit 677f6a66c2
9 changed files with 3497 additions and 72 deletions
+185 -1
View File
@@ -1,7 +1,7 @@
from pathlib import Path
from typing import Iterable, Optional, Dict, Any, List, Set, Callable
from pydantic import BaseModel, Field, field_validator, model_validator
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
from app.schemas.common import JsonData
from app.schemas.types import MediaType, NotificationChannel
@@ -29,6 +29,190 @@ class BaseEventData(BaseModel):
pass
class ExtensibleEventData(BaseEventData):
"""允许第三方插件附加字段的类型化事件载荷基类。"""
model_config = ConfigDict(extra="allow", arbitrary_types_allowed=True)
class EmptyEventData(ExtensibleEventData):
"""当前没有固定字段、但仍需进入 typed registry 的事件载荷。"""
class PluginReloadEventData(ExtensibleEventData):
"""插件重载广播事件载荷。"""
plugin_id: str = Field(description="重载的插件 ID")
class PluginActionEventData(ExtensibleEventData):
"""插件命令动作载荷;具体动作参数由目标插件扩展。"""
plugin_id: Optional[str] = Field(default=None, description="目标插件 ID")
action: Optional[str] = Field(default=None, description="插件动作名称")
channel: Optional[str] = Field(default=None, description="消息渠道")
source: Optional[str] = Field(default=None, description="消息来源")
user: Optional[Any] = Field(default=None, description="发起用户")
class PluginTriggeredEventData(ExtensibleEventData):
"""插件主动发布的跨插件事件载荷。"""
plugin_id: str = Field(description="发布事件的插件 ID")
event_name: str = Field(description="插件定义的稳定事件名")
data: Any = Field(default=None, description="插件定义的事件数据")
class CommandExecuteEventData(ExtensibleEventData):
"""斜杠命令执行事件载荷。"""
cmd: str = Field(description="包含参数的完整命令文本")
user: Optional[Any] = Field(default=None, description="发起用户")
channel: Optional[str] = Field(default=None, description="消息渠道")
source: Optional[str] = Field(default=None, description="消息来源")
processing_status: Optional[Any] = Field(default=None, description="交互处理状态")
class SiteEventData(ExtensibleEventData):
"""站点新增、更新、删除或数据刷新事件载荷。"""
site_id: Optional[int | str] = Field(default=None, description="站点 ID 或通配符")
domain: Optional[str] = Field(default=None, description="站点域名")
name: Optional[str] = Field(default=None, description="站点名称")
site_url: Optional[str] = Field(default=None, description="站点地址")
class HistoryDeletedEventData(ExtensibleEventData):
"""历史记录删除事件的兼容载荷。"""
history_id: Optional[int] = Field(default=None, description="历史记录 ID")
src: Optional[str] = Field(default=None, description="关联源路径")
class DownloadFileDeletedEventData(ExtensibleEventData):
"""下载源文件删除事件载荷。"""
src: Optional[str] = Field(default=None, description="已删除的下载源路径")
hash: Optional[str] = Field(default=None, description="下载任务 hash")
class DownloadDeletedEventData(ExtensibleEventData):
"""下载任务删除事件载荷。"""
hash: str = Field(description="下载任务 hash")
torrents: List[Dict[str, Any]] = Field(default_factory=list, description="删除前任务快照")
class UserMessageEventData(ExtensibleEventData):
"""未被宿主命令或交互消费的用户文本消息载荷。"""
text: str = Field(description="用户文本")
userid: Optional[Any] = Field(default=None, description="用户 ID")
channel: Optional[str] = Field(default=None, description="消息渠道")
source: Optional[str] = Field(default=None, description="消息来源")
chat_id: Optional[Any] = Field(default=None, description="会话 ID")
reply_to_message_id: Optional[Any] = Field(default=None, description="回复消息 ID")
class NoticeMessageEventData(ExtensibleEventData):
"""宿主向消息模块发送的通知事件载荷。"""
type: Optional[Any] = Field(default=None, description="兼容消息类型")
title: Optional[str] = Field(default=None, description="消息标题")
text: Optional[str] = Field(default=None, description="消息正文")
userid: Optional[Any] = Field(default=None, description="目标用户 ID")
channel: Optional[Any] = Field(default=None, description="目标消息渠道")
source: Optional[str] = Field(default=None, description="消息来源")
class SubscribeCompleteEventData(ExtensibleEventData):
"""订阅完成广播事件载荷。"""
subscribe_id: int = Field(description="已完成订阅 ID")
subscribe_info: Dict[str, Any] = Field(default_factory=dict, description="订阅快照")
mediainfo: Dict[str, Any] = Field(default_factory=dict, description="媒体信息快照")
class SystemErrorEventData(ExtensibleEventData):
"""事件、模块、插件或调度器错误的宿主诊断载荷。"""
type: str = Field(description="错误来源类别")
error: str = Field(description="错误摘要")
traceback: Optional[str] = Field(default=None, description="错误堆栈")
class MetadataScrapeEventData(ExtensibleEventData):
"""媒体文件元数据刮削事件载荷。"""
fileitem: FileItem = Field(description="待刮削目录或文件项")
file_list: List[str] = Field(default_factory=list, description="待刮削文件清单")
meta: Any = Field(default=None, description="文件名解析对象")
mediainfo: Any = Field(default=None, description="媒体信息对象")
overwrite: bool = Field(default=False, description="是否覆盖已有元数据")
file_contexts: List[Any] = Field(default_factory=list, description="逐文件上下文")
class MessageActionEventData(ExtensibleEventData):
"""定向插件消息交互动作载荷。"""
plugin_id: Optional[str] = Field(default=None, description="目标插件 ID")
text: Optional[str] = Field(default=None, description="兼容动作文本")
input_text: Optional[str] = Field(default=None, description="用户输入文本")
userid: Optional[Any] = Field(default=None, description="用户 ID")
channel: Optional[str] = Field(default=None, description="消息渠道")
source: Optional[str] = Field(default=None, description="消息来源")
input_session_id: Optional[str] = Field(default=None, description="输入会话 ID")
payload: Any = Field(default=None, description="插件自定义交互数据")
class WorkflowExecuteEventData(ExtensibleEventData):
"""请求执行指定工作流的事件载荷。"""
workflow_id: int = Field(description="工作流 ID")
class NameRecognizeEventData(ExtensibleEventData):
"""影视名称辅助识别的输入和插件回写字段。"""
title: str = Field(description="待识别标题")
name: Optional[str] = Field(default=None, description="插件识别后的名称")
year: Optional[Any] = Field(default=None, description="年份")
season: Optional[Any] = Field(default=None, description="季号")
episode: Optional[Any] = Field(default=None, description="集号")
class MusicNameRecognizeEventData(ExtensibleEventData):
"""音乐名称辅助识别的输入和插件回写字段。"""
title: str = Field(description="待识别曲名")
artist: Optional[str] = Field(default=None, description="艺术家")
album: Optional[str] = Field(default=None, description="专辑")
year: Optional[Any] = Field(default=None, description="年份")
duration: Optional[Any] = Field(default=None, description="时长")
name: Optional[str] = Field(default=None, description="插件识别后的曲名")
class MediaRecognizeEventData(ExtensibleEventData):
"""影视媒体身份补充识别的输入和插件回写字段。"""
title: Optional[str] = Field(default=None, description="待识别标题")
year: Optional[Any] = Field(default=None, description="年份")
season: Optional[Any] = Field(default=None, description="季号")
type: Optional[Any] = Field(default=None, description="媒体类型")
media_source: Optional[Any] = Field(default=None, description="媒体数据源")
media_id: Optional[Any] = Field(default=None, description="数据源原生 ID")
mediainfo: Optional[Dict[str, Any]] = Field(default=None, description="插件回写媒体信息")
class MusicMediaRecognizeEventData(MediaRecognizeEventData):
"""音乐媒体身份补充识别的输入和插件回写字段。"""
artists: List[str] = Field(default_factory=list, description="艺术家列表")
album: Optional[str] = Field(default=None, description="专辑")
isrc: Optional[str] = Field(default=None, description="ISRC")
music_type: Optional[str] = Field(default=None, description="音乐实体类型")
class ConfigChangeEventData(BaseEventData):
"""
ConfigChange 事件的数据模型
+22 -1
View File
@@ -65,6 +65,7 @@ SCHEMA_EXPORTS = {
'ChannelCapability': ('app.schemas.notification', 'ChannelCapability'),
'ChannelCapabilityManager': ('app.schemas.notification', 'ChannelCapabilityManager'),
'ClassVar': ('app.schemas.subscribe', 'ClassVar'),
'CommandExecuteEventData': ('app.schemas.event', 'CommandExecuteEventData'),
'CommandRegisterEventData': ('app.schemas.event', 'CommandRegisterEventData'),
'ConfigChangeEventData': ('app.schemas.event', 'ConfigChangeEventData'),
'ConfigDict': ('app.schemas.workflow', 'ConfigDict'),
@@ -86,7 +87,9 @@ SCHEMA_EXPORTS = {
'Discriminator': ('app.schemas.context', 'Discriminator'),
'DownloadAddedData': ('app.schemas.download', 'DownloadAddedData'),
'DownloadAddedEventData': ('app.schemas.event', 'DownloadAddedEventData'),
'DownloadDeletedEventData': ('app.schemas.event', 'DownloadDeletedEventData'),
'DownloadDirectory': ('app.schemas.download', 'DownloadDirectory'),
'DownloadFileDeletedEventData': ('app.schemas.event', 'DownloadFileDeletedEventData'),
'DownloadHistory': ('app.schemas.history', 'DownloadHistory'),
'DownloadTask': ('app.schemas.workflow', 'DownloadTask'),
'DownloadTaskMedia': ('app.schemas.transfer', 'DownloadTaskMedia'),
@@ -94,6 +97,7 @@ SCHEMA_EXPORTS = {
'DownloaderInfo': ('app.schemas.dashboard', 'DownloaderInfo'),
'DownloaderTorrent': ('app.schemas.transfer', 'DownloaderTorrent'),
'DownloadingTorrent': ('app.schemas.transfer', 'DownloadingTorrent'),
'EmptyEventData': ('app.schemas.event', 'EmptyEventData'),
'EndpointStats': ('app.schemas.monitoring', 'EndpointStats'),
'Enum': ('app.schemas.notification', 'Enum'),
'EpisodeFormat': ('app.schemas.transfer', 'EpisodeFormat'),
@@ -103,12 +107,14 @@ SCHEMA_EXPORTS = {
'ErrorRequest': ('app.schemas.monitoring', 'ErrorRequest'),
'Event': ('app.schemas.event', 'Event'),
'ExistMediaInfo': ('app.schemas.mediaserver', 'ExistMediaInfo'),
'ExtensibleEventData': ('app.schemas.event', 'ExtensibleEventData'),
'Field': ('app.schemas.mcp', 'Field'),
'FileItem': ('app.schemas.workflow', 'FileItem'),
'FileNameData': ('app.schemas.common', 'FileNameData'),
'FileURI': ('app.schemas.file', 'FileURI'),
'FilterRuleGroup': ('app.schemas.system', 'FilterRuleGroup'),
'Generic': ('app.schemas.response', 'Generic'),
'HistoryDeletedEventData': ('app.schemas.event', 'HistoryDeletedEventData'),
'IdData': ('app.schemas.common', 'IdData'),
'ImmediateException': ('app.schemas.exception', 'ImmediateException'),
'IncomingMessage': ('app.schemas.message', 'IncomingMessage'),
@@ -173,6 +179,7 @@ SCHEMA_EXPORTS = {
'MediaLanguage': ('app.schemas.context', 'MediaLanguage'),
'MediaPerson': ('app.schemas.context', 'MediaPerson'),
'MediaRecognizeConvertEventData': ('app.schemas.event', 'MediaRecognizeConvertEventData'),
'MediaRecognizeEventData': ('app.schemas.event', 'MediaRecognizeEventData'),
'MediaReleaseDate': ('app.schemas.context', 'MediaReleaseDate'),
'MediaSearchResult': ('app.schemas.context', 'MediaSearchResult'),
'MediaSearchResults': ('app.schemas.context', 'MediaSearchResults'),
@@ -190,6 +197,7 @@ SCHEMA_EXPORTS = {
'MediaSourceInfo': ('app.schemas.event', 'MediaSourceInfo'),
'MediaType': ('app.schemas.subscribe', 'MediaType'),
'Message': ('app.schemas.message', 'Message'),
'MessageActionEventData': ('app.schemas.event', 'MessageActionEventData'),
'MessageClearBefore': ('app.schemas.message', 'MessageClearBefore'),
'MessageClearData': ('app.schemas.message', 'MessageClearData'),
'MessageClearScope': ('app.schemas.message', 'MessageClearScope'),
@@ -197,6 +205,7 @@ SCHEMA_EXPORTS = {
'MessageResponse': ('app.schemas.message', 'MessageResponse'),
'MessageType': ('app.schemas.message', 'MessageType'),
'MetaInfo': ('app.schemas.transfer', 'MetaInfo'),
'MetadataScrapeEventData': ('app.schemas.event', 'MetadataScrapeEventData'),
'MfaChallenge': ('app.schemas.token', 'MfaChallenge'),
'MfaStatusData': ('app.schemas.mfa', 'MfaStatusData'),
'MonitoringConfig': ('app.schemas.monitoring', 'MonitoringConfig'),
@@ -205,16 +214,20 @@ SCHEMA_EXPORTS = {
'MusicArtistInfo': ('app.schemas.music', 'MusicArtistInfo'),
'MusicEntityType': ('app.schemas.music', 'MusicEntityType'),
'MusicInfo': ('app.schemas.transfer', 'MusicInfo'),
'MusicMediaRecognizeEventData': ('app.schemas.event', 'MusicMediaRecognizeEventData'),
'MusicMeta': ('app.schemas.transfer', 'MusicMeta'),
'MusicNameRecognizeEventData': ('app.schemas.event', 'MusicNameRecognizeEventData'),
'MusicRecognitionCacheData': ('app.schemas.music', 'MusicRecognitionCacheData'),
'MusicRecognitionCacheItem': ('app.schemas.music', 'MusicRecognitionCacheItem'),
'MusicRecognizeRequest': ('app.schemas.music', 'MusicRecognizeRequest'),
'MusicRelease': ('app.schemas.music', 'MusicRelease'),
'MusicTargetEntityType': ('app.schemas.transfer', 'MusicTargetEntityType'),
'NameData': ('app.schemas.common', 'NameData'),
'NameRecognizeEventData': ('app.schemas.event', 'NameRecognizeEventData'),
'NameValueOption': ('app.schemas.workflow', 'NameValueOption'),
'NetTestTarget': ('app.schemas.system', 'NetTestTarget'),
'NotExistMediaInfo': ('app.schemas.mediaserver', 'NotExistMediaInfo'),
'NoticeMessageEventData': ('app.schemas.event', 'NoticeMessageEventData'),
'NotificationChannel': ('app.schemas.notification', 'NotificationChannel'),
'NotificationConf': ('app.schemas.system', 'NotificationConf'),
'NotificationSwitch': ('app.schemas.message', 'NotificationSwitch'),
@@ -246,6 +259,7 @@ SCHEMA_EXPORTS = {
'Path': ('app.schemas.transfer', 'Path'),
'PerformanceSnapshot': ('app.schemas.monitoring', 'PerformanceSnapshot'),
'Plugin': ('app.schemas.plugin', 'Plugin'),
'PluginActionEventData': ('app.schemas.event', 'PluginActionEventData'),
'PluginCloneRequest': ('app.schemas.plugin', 'PluginCloneRequest'),
'PluginDashboard': ('app.schemas.plugin', 'PluginDashboard'),
'PluginDashboardMetaItem': ('app.schemas.plugin', 'PluginDashboardMetaItem'),
@@ -261,10 +275,12 @@ SCHEMA_EXPORTS = {
'PluginRatingRequest': ('app.schemas.plugin', 'PluginRatingRequest'),
'PluginReleaseData': ('app.schemas.plugin', 'PluginReleaseData'),
'PluginReleaseItem': ('app.schemas.plugin', 'PluginReleaseItem'),
'PluginReloadEventData': ('app.schemas.event', 'PluginReloadEventData'),
'PluginRemoteInfo': ('app.schemas.plugin', 'PluginRemoteInfo'),
'PluginRuntimeStatus': ('app.schemas.plugin', 'PluginRuntimeStatus'),
'PluginRuntimeSummary': ('app.schemas.plugin', 'PluginRuntimeSummary'),
'PluginSidebarNavItem': ('app.schemas.plugin', 'PluginSidebarNavItem'),
'PluginTriggeredEventData': ('app.schemas.event', 'PluginTriggeredEventData'),
'PluginWorkflowActionGroup': ('app.schemas.workflow', 'PluginWorkflowActionGroup'),
'ProcessInfo': ('app.schemas.dashboard', 'ProcessInfo'),
'ProgressKeyData': ('app.schemas.common', 'ProgressKeyData'),
@@ -304,6 +320,7 @@ SCHEMA_EXPORTS = {
'SiteAuth': ('app.schemas.site', 'SiteAuth'),
'SiteCategory': ('app.schemas.site', 'SiteCategory'),
'SiteCookieUpdate': ('app.schemas.site', 'SiteCookieUpdate'),
'SiteEventData': ('app.schemas.event', 'SiteEventData'),
'SiteIconData': ('app.schemas.site', 'SiteIconData'),
'SiteMappingData': ('app.schemas.site', 'SiteMappingData'),
'SiteStatistic': ('app.schemas.site', 'SiteStatistic'),
@@ -327,6 +344,7 @@ SCHEMA_EXPORTS = {
'SubscrbieInfo': ('app.schemas.subscribe', 'SubscrbieInfo'),
'Subscribe': ('app.schemas.workflow', 'Subscribe'),
'SubscribeAddedEventData': ('app.schemas.event', 'SubscribeAddedEventData'),
'SubscribeCompleteEventData': ('app.schemas.event', 'SubscribeCompleteEventData'),
'SubscribeCompletionCheckEventData': ('app.schemas.event', 'SubscribeCompletionCheckEventData'),
'SubscribeDeletedEventData': ('app.schemas.event', 'SubscribeDeletedEventData'),
'SubscribeDownloadFileInfo': ('app.schemas.subscribe', 'SubscribeDownloadFileInfo'),
@@ -341,6 +359,7 @@ SCHEMA_EXPORTS = {
'SubtitleDownloadData': ('app.schemas.download', 'SubtitleDownloadData'),
'SubtitleInfo': ('app.schemas.search', 'SubtitleInfo'),
'SystemEnvironmentUpdateData': ('app.schemas.system', 'SystemEnvironmentUpdateData'),
'SystemErrorEventData': ('app.schemas.event', 'SystemErrorEventData'),
'SystemModuleInfo': ('app.schemas.system', 'SystemModuleInfo'),
'SystemModuleListData': ('app.schemas.system', 'SystemModuleListData'),
'TMDbException': ('app.schemas.exception', 'TMDbException'),
@@ -386,6 +405,7 @@ SCHEMA_EXPORTS = {
'UserInDB': ('app.schemas.user', 'UserInDB'),
'UserInDBBase': ('app.schemas.user', 'UserInDBBase'),
'UserMessage': ('app.schemas.agent', 'UserMessage'),
'UserMessageEventData': ('app.schemas.event', 'UserMessageEventData'),
'UserPermissions': ('app.schemas.user', 'UserPermissions'),
'UserUpdate': ('app.schemas.user', 'UserUpdate'),
'ValidationIssue': ('app.schemas.response', 'ValidationIssue'),
@@ -397,6 +417,7 @@ SCHEMA_EXPORTS = {
'WechatClawBotKnownTarget': ('app.schemas.notification', 'WechatClawBotKnownTarget'),
'Workflow': ('app.schemas.workflow', 'Workflow'),
'WorkflowActionDefinition': ('app.schemas.workflow', 'WorkflowActionDefinition'),
'WorkflowExecuteEventData': ('app.schemas.event', 'WorkflowExecuteEventData'),
'WorkflowExecutionConfig': ('app.schemas.workflow', 'WorkflowExecutionConfig'),
'WorkflowExecutionState': ('app.schemas.workflow', 'WorkflowExecutionState'),
'WorkflowNodeState': ('app.schemas.workflow', 'WorkflowNodeState'),
@@ -415,7 +436,7 @@ SCHEMA_EXPORTS = {
SCHEMA_CONFLICTS = {
'Any': ['app.schemas.common', 'app.schemas.context', 'app.schemas.event', 'app.schemas.mediaserver', 'app.schemas.message', 'app.schemas.response', 'app.schemas.subscribe', 'app.schemas.system', 'app.schemas.workflow'],
'BaseModel': ['app.schemas.agent', 'app.schemas.cache', 'app.schemas.category', 'app.schemas.common', 'app.schemas.context', 'app.schemas.dashboard', 'app.schemas.download', 'app.schemas.event', 'app.schemas.file', 'app.schemas.history', 'app.schemas.llm', 'app.schemas.mediaserver', 'app.schemas.message', 'app.schemas.mfa', 'app.schemas.music', 'app.schemas.monitoring', 'app.schemas.notification', 'app.schemas.plugin', 'app.schemas.response', 'app.schemas.rule', 'app.schemas.search', 'app.schemas.storage', 'app.schemas.openai', 'app.schemas.servarr', 'app.schemas.servcookie', 'app.schemas.site', 'app.schemas.subscribe', 'app.schemas.system', 'app.schemas.tmdb', 'app.schemas.token', 'app.schemas.transfer', 'app.schemas.user', 'app.schemas.workflow', 'app.schemas.mcp'],
'ConfigDict': ['app.schemas.agent', 'app.schemas.category', 'app.schemas.history', 'app.schemas.mediaserver', 'app.schemas.response', 'app.schemas.openai', 'app.schemas.servcookie', 'app.schemas.site', 'app.schemas.subscribe', 'app.schemas.user', 'app.schemas.workflow'],
'ConfigDict': ['app.schemas.agent', 'app.schemas.category', 'app.schemas.event', 'app.schemas.history', 'app.schemas.mediaserver', 'app.schemas.response', 'app.schemas.openai', 'app.schemas.servcookie', 'app.schemas.site', 'app.schemas.subscribe', 'app.schemas.user', 'app.schemas.workflow'],
'Context': ['app.schemas.context', 'app.schemas.workflow'],
'Dict': ['app.schemas.category', 'app.schemas.common', 'app.schemas.context', 'app.schemas.event', 'app.schemas.mediaserver', 'app.schemas.message', 'app.schemas.notification', 'app.schemas.plugin', 'app.schemas.openai', 'app.schemas.site', 'app.schemas.subscribe', 'app.schemas.mcp'],
'DownloadTask': ['app.schemas.download', 'app.schemas.workflow'],