feat(config): 优化配置变更事件处理机制

This commit is contained in:
Attente
2025-11-27 23:17:34 +08:00
parent d1d7b8ce55
commit ca5ec8af0f
23 changed files with 205 additions and 335 deletions

View File

@@ -4,15 +4,22 @@ from typing import Generic, Tuple, Union, TypeVar, Type, Dict, Optional, Callabl
from app.helper.service import ServiceConfigHelper
from app.schemas import Notification, NotificationConf, MediaServerConf, DownloaderConf
from app.schemas.types import ModuleType, DownloaderType, MediaServerType, MessageChannel, StorageSchema, \
OtherModulesType
OtherModulesType, SystemConfigKey
from app.utils.mixins import ConfigReloadMixin
class _ModuleBase(metaclass=ABCMeta):
class _ModuleBase(ConfigReloadMixin, metaclass=ABCMeta):
"""
模块基类实现对应方法在有需要时会被自动调用返回None代表不启用该模块将继续执行下一模块
输入参数与输出参数一致的,或没有输出的,可以被多个模块重复实现
"""
def on_config_changed(self):
self.init_module()
def get_reload_name(self):
return self.get_name()
@abstractmethod
def init_module(self) -> None:
"""
@@ -177,6 +184,7 @@ class _MessageBase(ServiceBase[TService, NotificationConf]):
"""
消息基类
"""
CONFIG_WATCH = {SystemConfigKey.Notifications.value}
def __init__(self):
"""
@@ -224,6 +232,7 @@ class _DownloaderBase(ServiceBase[TService, DownloaderConf]):
"""
下载器基类
"""
CONFIG_WATCH = {SystemConfigKey.Downloaders.value}
def __init__(self):
"""
@@ -287,6 +296,7 @@ class _MediaServerBase(ServiceBase[TService, MediaServerConf]):
"""
媒体服务器基类
"""
CONFIG_WATCH = {SystemConfigKey.MediaServers.value}
def get_configs(self) -> Dict[str, MediaServerConf]:
"""

View File

@@ -2,11 +2,11 @@ from typing import Any, Generator, List, Optional, Tuple, Union
from app import schemas
from app.core.context import MediaInfo
from app.core.event import eventmanager, Event
from app.core.event import eventmanager
from app.log import logger
from app.modules import _MediaServerBase, _ModuleBase
from app.modules.emby.emby import Emby
from app.schemas.types import MediaType, ModuleType, ChainEventType, MediaServerType, SystemConfigKey, EventType
from app.schemas.types import MediaType, ModuleType, ChainEventType, MediaServerType
class EmbyModule(_ModuleBase, _MediaServerBase[Emby]):
@@ -18,20 +18,6 @@ class EmbyModule(_ModuleBase, _MediaServerBase[Emby]):
super().init_service(service_name=Emby.__name__.lower(),
service_type=lambda conf: Emby(**conf.config, sync_libraries=conf.sync_libraries))
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: schemas.ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.MediaServers.value]:
return
logger.info("配置变更重新初始化Emby模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "Emby"

View File

@@ -2,12 +2,12 @@ from typing import Any, Generator, List, Optional, Tuple, Union
from app import schemas
from app.core.context import MediaInfo
from app.core.event import eventmanager, Event
from app.core.event import eventmanager
from app.log import logger
from app.modules import _MediaServerBase, _ModuleBase
from app.modules.jellyfin.jellyfin import Jellyfin
from app.schemas import AuthCredentials, AuthInterceptCredentials
from app.schemas.types import MediaType, ModuleType, ChainEventType, MediaServerType, SystemConfigKey, EventType
from app.schemas.types import MediaType, ModuleType, ChainEventType, MediaServerType
class JellyfinModule(_ModuleBase, _MediaServerBase[Jellyfin]):
@@ -19,20 +19,6 @@ class JellyfinModule(_ModuleBase, _MediaServerBase[Jellyfin]):
super().init_service(service_name=Jellyfin.__name__.lower(),
service_type=lambda conf: Jellyfin(**conf.config, sync_libraries=conf.sync_libraries))
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: schemas.ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.MediaServers.value]:
return
logger.info("配置变更重新初始化Jellyfin模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "Jellyfin"

View File

@@ -2,12 +2,12 @@ from typing import Optional, Tuple, Union, Any, List, Generator
from app import schemas
from app.core.context import MediaInfo
from app.core.event import eventmanager, Event
from app.core.event import eventmanager
from app.log import logger
from app.modules import _ModuleBase, _MediaServerBase
from app.modules.plex.plex import Plex
from app.schemas import AuthCredentials, AuthInterceptCredentials
from app.schemas.types import MediaType, ModuleType, ChainEventType, MediaServerType, SystemConfigKey, EventType
from app.schemas.types import MediaType, ModuleType, ChainEventType, MediaServerType
class PlexModule(_ModuleBase, _MediaServerBase[Plex]):
@@ -19,20 +19,6 @@ class PlexModule(_ModuleBase, _MediaServerBase[Plex]):
super().init_service(service_name=Plex.__name__.lower(),
service_type=lambda conf: Plex(**conf.config, sync_libraries=conf.sync_libraries))
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: schemas.ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.MediaServers.value]:
return
logger.info("配置变更重新初始化Plex模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "Plex"

View File

@@ -7,13 +7,12 @@ from torrentool.torrent import Torrent
from app import schemas
from app.core.cache import FileCache
from app.core.config import settings
from app.core.event import eventmanager, Event
from app.core.metainfo import MetaInfo
from app.log import logger
from app.modules import _ModuleBase, _DownloaderBase
from app.modules.qbittorrent.qbittorrent import Qbittorrent
from app.schemas import TransferTorrent, DownloadingTorrent
from app.schemas.types import TorrentStatus, ModuleType, DownloaderType, SystemConfigKey, EventType
from app.schemas.types import TorrentStatus, ModuleType, DownloaderType
from app.utils.string import StringUtils
@@ -26,20 +25,6 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]):
super().init_service(service_name=Qbittorrent.__name__.lower(),
service_type=Qbittorrent)
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: schemas.ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.Downloaders.value]:
return
logger.info("配置变更重新加载Qbittorrent模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "Qbittorrent"

View File

@@ -3,12 +3,11 @@ import re
from typing import Optional, Union, List, Tuple, Any
from app.core.context import MediaInfo, Context
from app.core.event import eventmanager, Event
from app.log import logger
from app.modules import _ModuleBase, _MessageBase
from app.modules.slack.slack import Slack
from app.schemas import MessageChannel, CommingMessage, Notification, ConfigChangeEventData
from app.schemas.types import ModuleType, SystemConfigKey, EventType
from app.schemas import MessageChannel, CommingMessage, Notification
from app.schemas.types import ModuleType
class SlackModule(_ModuleBase, _MessageBase[Slack]):
@@ -21,20 +20,6 @@ class SlackModule(_ModuleBase, _MessageBase[Slack]):
service_type=Slack)
self._channel = MessageChannel.Slack
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.Notifications.value]:
return
logger.info("配置变更重新加载Slack模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "Slack"

View File

@@ -1,12 +1,11 @@
from typing import Optional, Union, List, Tuple, Any
from app.core.context import MediaInfo, Context
from app.core.event import eventmanager, Event
from app.log import logger
from app.modules import _ModuleBase, _MessageBase
from app.modules.synologychat.synologychat import SynologyChat
from app.schemas import MessageChannel, CommingMessage, Notification, ConfigChangeEventData
from app.schemas.types import ModuleType, SystemConfigKey, EventType
from app.schemas import MessageChannel, CommingMessage, Notification
from app.schemas.types import ModuleType
class SynologyChatModule(_ModuleBase, _MessageBase[SynologyChat]):
@@ -19,20 +18,6 @@ class SynologyChatModule(_ModuleBase, _MessageBase[SynologyChat]):
service_type=SynologyChat)
self._channel = MessageChannel.SynologyChat
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.Notifications.value]:
return
logger.info("配置变更重新加载SynologyChat模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "Synology Chat"

View File

@@ -4,13 +4,13 @@ import re
from typing import Dict, Optional, Union, List, Tuple, Any
from app.core.context import MediaInfo, Context
from app.core.event import eventmanager, Event
from app.core.event import eventmanager
from app.log import logger
from app.modules import _ModuleBase, _MessageBase
from app.modules.telegram.telegram import Telegram
from app.schemas import MessageChannel, CommingMessage, Notification, CommandRegisterEventData, ConfigChangeEventData, \
from app.schemas import MessageChannel, CommingMessage, Notification, CommandRegisterEventData, \
NotificationConf
from app.schemas.types import ModuleType, ChainEventType, SystemConfigKey, EventType
from app.schemas.types import ModuleType, ChainEventType
from app.utils.structures import DictUtils
@@ -24,20 +24,6 @@ class TelegramModule(_ModuleBase, _MessageBase[Telegram]):
service_type=Telegram)
self._channel = MessageChannel.Telegram
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.Notifications.value]:
return
logger.info("配置变更重新加载Telegram模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "Telegram"

View File

@@ -7,7 +7,6 @@ import zhconv
from app import schemas
from app.core.config import settings
from app.core.context import MediaInfo
from app.core.event import eventmanager, Event
from app.core.meta import MetaBase
from app.log import logger
from app.modules import _ModuleBase
@@ -15,7 +14,7 @@ from app.modules.themoviedb.category import CategoryHelper
from app.modules.themoviedb.scraper import TmdbScraper
from app.modules.themoviedb.tmdb_cache import TmdbCache
from app.modules.themoviedb.tmdbapi import TmdbApi
from app.schemas.types import MediaType, MediaImageType, ModuleType, MediaRecognizeType, EventType
from app.schemas.types import MediaType, MediaImageType, ModuleType, MediaRecognizeType
from app.utils.http import RequestUtils
@@ -23,6 +22,7 @@ class TheMovieDbModule(_ModuleBase):
"""
TMDB媒体信息匹配
"""
CONFIG_WATCH = {"PROXY_HOST", "TMDB_API_DOMAIN", "TMDB_API_KEY", "TMDB_LOCALE"}
# 元数据缓存
cache: TmdbCache = None
@@ -39,18 +39,7 @@ class TheMovieDbModule(_ModuleBase):
self.category = CategoryHelper()
self.scraper = TmdbScraper()
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: schemas.ConfigChangeEventData = event.event_data
if event_data.key not in ["PROXY_HOST", "TMDB_API_DOMAIN", "TMDB_API_KEY", "TMDB_LOCALE"]:
return
logger.info("配置变更重新初始化TheMovieDb模块...")
def on_config_changed(self):
# 停止模块
self.stop()
# 初始化模块

View File

@@ -7,13 +7,12 @@ from transmission_rpc import File
from app import schemas
from app.core.cache import FileCache
from app.core.config import settings
from app.core.event import eventmanager, Event
from app.core.metainfo import MetaInfo
from app.log import logger
from app.modules import _ModuleBase, _DownloaderBase
from app.modules.transmission.transmission import Transmission
from app.schemas import TransferTorrent, DownloadingTorrent
from app.schemas.types import TorrentStatus, ModuleType, DownloaderType, SystemConfigKey, EventType
from app.schemas.types import TorrentStatus, ModuleType, DownloaderType
from app.utils.string import StringUtils
@@ -26,20 +25,6 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]):
super().init_service(service_name=Transmission.__name__.lower(),
service_type=Transmission)
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: schemas.ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.Downloaders.value]:
return
logger.info("配置变更重新加载Transmission模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "Transmission"

View File

@@ -2,12 +2,12 @@ from typing import Any, Generator, List, Optional, Tuple, Union
from app import schemas
from app.core.context import MediaInfo
from app.core.event import eventmanager, Event
from app.core.event import eventmanager
from app.log import logger
from app.modules import _MediaServerBase, _ModuleBase
from app.modules.trimemedia.trimemedia import TrimeMedia
from app.schemas import AuthCredentials, AuthInterceptCredentials
from app.schemas.types import ChainEventType, MediaServerType, MediaType, ModuleType, SystemConfigKey, EventType
from app.schemas.types import ChainEventType, MediaServerType, MediaType, ModuleType
class TrimeMediaModule(_ModuleBase, _MediaServerBase[TrimeMedia]):
@@ -23,20 +23,6 @@ class TrimeMediaModule(_ModuleBase, _MediaServerBase[TrimeMedia]):
),
)
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: schemas.ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.MediaServers.value]:
return
logger.info("配置变更,重新加载飞牛影视模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "飞牛影视"

View File

@@ -2,12 +2,11 @@ import json
from typing import Optional, Union, List, Tuple, Any, Dict
from app.core.context import Context, MediaInfo
from app.core.event import eventmanager, Event
from app.log import logger
from app.modules import _ModuleBase, _MessageBase
from app.modules.vocechat.vocechat import VoceChat
from app.schemas import MessageChannel, CommingMessage, Notification, ConfigChangeEventData
from app.schemas.types import ModuleType, SystemConfigKey, EventType
from app.schemas import MessageChannel, CommingMessage, Notification
from app.schemas.types import ModuleType
class VoceChatModule(_ModuleBase, _MessageBase[VoceChat]):
@@ -20,20 +19,6 @@ class VoceChatModule(_ModuleBase, _MessageBase[VoceChat]):
service_type=VoceChat)
self._channel = MessageChannel.VoceChat
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.Notifications.value]:
return
logger.info("配置变更重新加载VoceChat模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "VoceChat"

View File

@@ -4,11 +4,10 @@ from typing import Union, Tuple
from pywebpush import webpush, WebPushException
from app.core.config import global_vars, settings
from app.core.event import eventmanager, Event
from app.log import logger
from app.modules import _ModuleBase, _MessageBase
from app.schemas import Notification, ConfigChangeEventData
from app.schemas.types import ModuleType, MessageChannel, SystemConfigKey, EventType
from app.schemas import Notification
from app.schemas.types import ModuleType, MessageChannel
class WebPushModule(_ModuleBase, _MessageBase):
@@ -20,20 +19,6 @@ class WebPushModule(_ModuleBase, _MessageBase):
super().init_service(service_name=self.get_name().lower())
self._channel = MessageChannel.WebPush
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.Notifications.value]:
return
logger.info("配置变更重新加载WebPush模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "WebPush"

View File

@@ -3,13 +3,13 @@ import xml.dom.minidom
from typing import Optional, Union, List, Tuple, Any, Dict
from app.core.context import Context, MediaInfo
from app.core.event import Event, eventmanager
from app.core.event import eventmanager
from app.log import logger
from app.modules import _ModuleBase, _MessageBase
from app.modules.wechat.WXBizMsgCrypt3 import WXBizMsgCrypt
from app.modules.wechat.wechat import WeChat
from app.schemas import MessageChannel, CommingMessage, Notification, CommandRegisterEventData, ConfigChangeEventData
from app.schemas.types import ModuleType, ChainEventType, SystemConfigKey, EventType
from app.schemas.types import ModuleType, ChainEventType
from app.utils.dom import DomUtils
from app.utils.structures import DictUtils
@@ -24,20 +24,6 @@ class WechatModule(_ModuleBase, _MessageBase[WeChat]):
service_type=WeChat)
self._channel = MessageChannel.Wechat
@eventmanager.register(EventType.ConfigChanged)
def handle_config_changed(self, event: Event):
"""
处理配置变更事件
:param event: 事件对象
"""
if not event:
return
event_data: ConfigChangeEventData = event.event_data
if event_data.key not in [SystemConfigKey.Notifications.value]:
return
logger.info("配置变更重新加载Wechat模块...")
self.init_module()
@staticmethod
def get_name() -> str:
return "微信"