mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-03-20 03:57:30 +08:00
fix Config reload
This commit is contained in:
@@ -37,6 +37,7 @@ from app.utils.crypto import HashUtils
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.security import SecurityUtils
|
||||
from app.utils.url import UrlUtils
|
||||
from core.event import eventmanager
|
||||
from version import APP_VERSION
|
||||
|
||||
router = APIRouter()
|
||||
@@ -230,6 +231,10 @@ def set_env_setting(env: dict,
|
||||
}
|
||||
)
|
||||
|
||||
if success_updates:
|
||||
for key, value in success_updates.items():
|
||||
eventmanager.send_event()
|
||||
|
||||
return schemas.Response(
|
||||
success=True,
|
||||
message="所有配置项更新成功",
|
||||
|
||||
@@ -4,115 +4,17 @@ import os
|
||||
import secrets
|
||||
import sys
|
||||
import threading
|
||||
from collections import defaultdict
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Tuple, Type, Callable
|
||||
from typing import Any, Dict, List, Optional, Tuple, Type
|
||||
|
||||
from dotenv import set_key
|
||||
from pydantic import BaseModel, BaseSettings, validator, Field
|
||||
|
||||
from app.log import logger, log_settings, LogConfigModel
|
||||
from app.utils.object import ObjectUtils
|
||||
from app.utils.system import SystemUtils
|
||||
from app.utils.url import UrlUtils
|
||||
|
||||
|
||||
class ConfigChangeType(Enum):
|
||||
"""
|
||||
配置变更类型
|
||||
"""
|
||||
ADD = "add"
|
||||
UPDATE = "update"
|
||||
DELETE = "delete"
|
||||
|
||||
|
||||
class ConfigChangeEvent:
|
||||
"""
|
||||
配置变更事件
|
||||
"""
|
||||
|
||||
def __init__(self, key: str, old_value: Any, new_value: Any,
|
||||
change_type: ConfigChangeType = ConfigChangeType.UPDATE):
|
||||
self.key = key
|
||||
self.old_value = old_value
|
||||
self.new_value = new_value
|
||||
self.change_type = change_type
|
||||
self.timestamp = threading.Event()
|
||||
|
||||
|
||||
class ConfigObserver:
|
||||
"""
|
||||
配置观察者接口
|
||||
"""
|
||||
|
||||
def on_config_changed(self, event: ConfigChangeEvent):
|
||||
"""
|
||||
配置变更回调
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class ConfigNotifier:
|
||||
"""
|
||||
配置变更通知器
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._observers: Dict[str, List[ConfigObserver]] = defaultdict(list)
|
||||
self._global_observers: List[ConfigObserver] = []
|
||||
self._lock = threading.RLock()
|
||||
|
||||
def add_observer(self, observer: ConfigObserver, config_keys: Optional[List[str]] = None):
|
||||
"""
|
||||
添加观察者
|
||||
:param observer: 观察者对象
|
||||
:param config_keys: 监听的配置键列表,为None时监听所有配置变更
|
||||
"""
|
||||
with self._lock:
|
||||
if config_keys is None:
|
||||
self._global_observers.append(observer)
|
||||
else:
|
||||
for key in config_keys:
|
||||
self._observers[key].append(observer)
|
||||
|
||||
def remove_observer(self, observer: ConfigObserver, config_keys: Optional[List[str]] = None):
|
||||
"""
|
||||
移除观察者
|
||||
:param observer: 观察者对象
|
||||
:param config_keys: 监听的配置键列表,为None时移除全局观察者
|
||||
"""
|
||||
with self._lock:
|
||||
if config_keys is None:
|
||||
if observer in self._global_observers:
|
||||
self._global_observers.remove(observer)
|
||||
else:
|
||||
for key in config_keys:
|
||||
if observer in self._observers[key]:
|
||||
self._observers[key].remove(observer)
|
||||
|
||||
def notify(self, event: ConfigChangeEvent):
|
||||
"""
|
||||
通知观察者配置变更
|
||||
"""
|
||||
with self._lock:
|
||||
# 通知全局观察者
|
||||
for observer in self._global_observers:
|
||||
try:
|
||||
observer.on_config_changed(event)
|
||||
except Exception as e:
|
||||
logger.error(f"配置观察者 {observer} 处理配置变更时出错: {e}")
|
||||
|
||||
# 通知特定配置键的观察者
|
||||
for observer in self._observers.get(event.key, []):
|
||||
try:
|
||||
observer.on_config_changed(event)
|
||||
except Exception as e:
|
||||
logger.error(f"配置观察者 {observer} 处理配置变更 {event.key} 时出错: {e}")
|
||||
|
||||
|
||||
# 全局配置通知器
|
||||
config_notifier = ConfigNotifier()
|
||||
from app.schemas.types import EventType
|
||||
from app.schemas import ConfigChangeEventData
|
||||
|
||||
|
||||
class ConfigModel(BaseModel):
|
||||
@@ -558,8 +460,13 @@ class Settings(BaseSettings, ConfigModel, LogConfigModel):
|
||||
if hasattr(log_settings, key):
|
||||
setattr(log_settings, key, converted_value)
|
||||
# 发送配置变更通知
|
||||
event = ConfigChangeEvent(key, old_value, converted_value)
|
||||
config_notifier.notify(event)
|
||||
from app.core.event import eventmanager
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
old_value=old_value,
|
||||
new_value=converted_value,
|
||||
change_type="update"
|
||||
))
|
||||
|
||||
return success, message
|
||||
return True, ""
|
||||
@@ -791,91 +698,3 @@ class GlobalVar(object):
|
||||
|
||||
# 全局标识
|
||||
global_vars = GlobalVar()
|
||||
|
||||
|
||||
class HotReloadManager(ConfigObserver):
|
||||
"""
|
||||
配置热更新管理器
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._reload_handlers: Dict[str, Callable] = {}
|
||||
# 注册为全局配置观察者
|
||||
config_notifier.add_observer(self)
|
||||
|
||||
def register_handler(self, config_keys: List[str], handler: Callable[[Any, Any], None]):
|
||||
"""
|
||||
注册配置变更处理器
|
||||
:param config_keys: 配置键列表
|
||||
:param handler: 处理函数,接收 (old_value, new_value) 参数
|
||||
"""
|
||||
for key in config_keys:
|
||||
self._reload_handlers[key] = handler
|
||||
|
||||
@staticmethod
|
||||
def __get_callable(name: str):
|
||||
"""
|
||||
根据类名获取类实例,首先检查全局变量中是否存在该类,如果不存在则尝试动态导入模块。
|
||||
:param name: 方法名/类名.方法名
|
||||
:return: 类的实例
|
||||
"""
|
||||
# 检查类是否在全局变量中
|
||||
if name in globals():
|
||||
try:
|
||||
class_obj = globals()[name]()
|
||||
return class_obj
|
||||
except Exception as e:
|
||||
logger.error(str(e))
|
||||
return None
|
||||
|
||||
# TODO 如果类不在全局变量中,尝试动态导入模块并创建实例
|
||||
|
||||
return None
|
||||
|
||||
def on_config_changed(self, event: ConfigChangeEvent):
|
||||
"""
|
||||
处理配置变更事件
|
||||
"""
|
||||
if event.key in self._reload_handlers:
|
||||
try:
|
||||
handler = self._reload_handlers[event.key]
|
||||
# 可执行函数
|
||||
func = self.__get_callable(handler.__qualname__)
|
||||
# 参数数量
|
||||
args_num = ObjectUtils.arguments(func)
|
||||
if args_num < 2:
|
||||
func()
|
||||
else:
|
||||
func(event.old_value, event.new_value)
|
||||
logger.info(f"配置 {event.key} 热更新成功:{func}")
|
||||
except Exception as e:
|
||||
logger.error(f"配置 {event.key} 热更新失败: {e}")
|
||||
|
||||
|
||||
# 初始化热更新管理器
|
||||
hot_reload_manager = HotReloadManager()
|
||||
|
||||
|
||||
def on_config_change(config_keys: List[str]):
|
||||
"""
|
||||
装饰器:用于注册配置变更处理函数
|
||||
|
||||
使用示例:
|
||||
@on_config_change(['PROXY_HOST', 'TMDB_API_KEY'])
|
||||
def handle_config_change(old_value, new_value):
|
||||
pass
|
||||
"""
|
||||
|
||||
def decorator(func: Callable[[Any, Any], None]):
|
||||
hot_reload_manager.register_handler(config_keys, func)
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
@on_config_change(['DEBUG', 'LOG_LEVEL'])
|
||||
def handle_logger_change():
|
||||
"""
|
||||
默认的配置变更处理函数
|
||||
"""
|
||||
logger.update_loggers()
|
||||
|
||||
@@ -10,7 +10,6 @@ from functools import lru_cache
|
||||
from queue import Empty, PriorityQueue
|
||||
from typing import Callable, Dict, List, Optional, Union
|
||||
|
||||
from app.helper.message import MessageHelper
|
||||
from app.helper.thread import ThreadHelper
|
||||
from app.log import logger
|
||||
from app.schemas import ChainEventData
|
||||
@@ -75,7 +74,6 @@ class EventManager(metaclass=Singleton):
|
||||
__event = threading.Event()
|
||||
|
||||
def __init__(self):
|
||||
self.__messagehelper = MessageHelper()
|
||||
self.__executor = ThreadHelper() # 动态线程池,用于消费事件
|
||||
self.__consumer_threads = [] # 用于保存启动的事件消费者线程
|
||||
self.__event_queue = PriorityQueue() # 优先级队列
|
||||
@@ -140,11 +138,12 @@ class EventManager(metaclass=Singleton):
|
||||
"""
|
||||
event = Event(etype, data, priority)
|
||||
if isinstance(etype, EventType):
|
||||
self.__trigger_broadcast_event(event)
|
||||
return self.__trigger_broadcast_event(event)
|
||||
elif isinstance(etype, ChainEventType):
|
||||
return self.__trigger_chain_event(event)
|
||||
else:
|
||||
logger.error(f"Unknown event type: {etype}")
|
||||
return None
|
||||
|
||||
def add_event_listener(self, event_type: Union[EventType, ChainEventType], handler: Callable,
|
||||
priority: Optional[int] = DEFAULT_EVENT_PRIORITY):
|
||||
@@ -293,7 +292,7 @@ class EventManager(metaclass=Singleton):
|
||||
|
||||
# 对于类实例(实现了 __call__ 方法)
|
||||
if not inspect.isfunction(handler) and hasattr(handler, "__call__"):
|
||||
handler_cls = handler.__class__ # noqa
|
||||
handler_cls = handler.__class__ # noqa
|
||||
return cls.__get_handler_identifier(handler_cls)
|
||||
|
||||
# 对于未绑定方法、静态方法、类方法,使用 __qualname__ 提取类信息
|
||||
@@ -303,6 +302,7 @@ class EventManager(metaclass=Singleton):
|
||||
module = inspect.getmodule(handler)
|
||||
module_name = module.__name__ if module else "unknown_module"
|
||||
return f"{module_name}.{class_name}"
|
||||
return None
|
||||
|
||||
def __is_handler_enabled(self, handler: Callable) -> bool:
|
||||
"""
|
||||
@@ -398,16 +398,28 @@ class EventManager(metaclass=Singleton):
|
||||
|
||||
try:
|
||||
from app.core.plugin import PluginManager
|
||||
from app.core.module import ModuleManager
|
||||
|
||||
if class_name in PluginManager().get_plugin_ids():
|
||||
# 定义一个插件调用函数
|
||||
def plugin_callable():
|
||||
"""
|
||||
插件调用函数
|
||||
"""
|
||||
PluginManager().run_plugin_method(class_name, method_name, event_to_process)
|
||||
|
||||
if is_broadcast_event:
|
||||
self.__executor.submit(plugin_callable)
|
||||
else:
|
||||
plugin_callable()
|
||||
elif class_name in ModuleManager().get_module_ids():
|
||||
module = ModuleManager().get_running_module(class_name)
|
||||
if module:
|
||||
method = getattr(module, method_name, None)
|
||||
if method:
|
||||
if is_broadcast_event:
|
||||
self.__executor.submit(method, event_to_process)
|
||||
else:
|
||||
method(event_to_process)
|
||||
else:
|
||||
# 获取全局对象或模块类的实例
|
||||
class_obj = self.__get_class_instance(class_name)
|
||||
@@ -441,11 +453,20 @@ class EventManager(metaclass=Singleton):
|
||||
if class_name == "Command":
|
||||
module_name = "app.command"
|
||||
module = importlib.import_module(module_name)
|
||||
elif class_name == "Monitor":
|
||||
module_name = "app.monitor"
|
||||
module = importlib.import_module(module_name)
|
||||
elif class_name == "Scheduler":
|
||||
module_name = "app.scheduler"
|
||||
module = importlib.import_module(module_name)
|
||||
elif class_name == "PluginManager":
|
||||
module_name = "app.core.plugin"
|
||||
module = importlib.import_module(module_name)
|
||||
elif class_name.endswith("Chain"):
|
||||
module_name = f"app.chain.{class_name[:-5].lower()}"
|
||||
module = importlib.import_module(module_name)
|
||||
else:
|
||||
logger.debug(f"事件处理出错:无效的 Chain 类名: {class_name},类名必须以 'Chain' 结尾")
|
||||
logger.debug(f"事件处理出错:不支持的类名: {class_name}")
|
||||
return None
|
||||
if hasattr(module, class_name):
|
||||
class_obj = getattr(module, class_name)()
|
||||
@@ -491,9 +512,11 @@ class EventManager(metaclass=Singleton):
|
||||
names = handler.__qualname__.split(".")
|
||||
class_name, method_name = names[0], names[1]
|
||||
|
||||
self.__messagehelper.put(title=f"{event.event_type} 事件处理出错",
|
||||
message=f"{class_name}.{method_name}:{str(e)}",
|
||||
role="system")
|
||||
# 发送系统错误通知
|
||||
from app.helper.message import MessageHelper
|
||||
MessageHelper().put(title=f"{event.event_type} 事件处理出错",
|
||||
message=f"{class_name}.{method_name}:{str(e)}",
|
||||
role="system")
|
||||
self.send_event(
|
||||
EventType.SystemError,
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import traceback
|
||||
from typing import Generator, Optional, Tuple, Any, Union
|
||||
from typing import Generator, Optional, Tuple, Any, Union, List
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.event import eventmanager
|
||||
@@ -164,3 +164,9 @@ class ModuleManager(metaclass=Singleton):
|
||||
获取模块列表
|
||||
"""
|
||||
return self._modules
|
||||
|
||||
def get_module_ids(self) -> List[str]:
|
||||
"""
|
||||
获取模块id列表
|
||||
"""
|
||||
return list(self._modules.keys())
|
||||
|
||||
@@ -15,8 +15,8 @@ from watchdog.events import FileSystemEventHandler
|
||||
from watchdog.observers import Observer
|
||||
|
||||
from app import schemas
|
||||
from app.core.config import settings, on_config_change
|
||||
from app.core.event import eventmanager
|
||||
from app.core.config import settings
|
||||
from app.core.event import eventmanager, Event
|
||||
from app.db.plugindata_oper import PluginDataOper
|
||||
from app.db.systemconfig_oper import SystemConfigOper
|
||||
from app.helper.module import ModuleHelper
|
||||
@@ -241,11 +241,17 @@ class PluginManager(metaclass=Singleton):
|
||||
"""
|
||||
return self._plugins
|
||||
|
||||
@on_config_change(['PLUGIN_AUTO_RELOAD', 'DEV'])
|
||||
def handle_config_change(self):
|
||||
@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 ['DEV', 'PLUGIN_AUTO_RELOAD']:
|
||||
return
|
||||
self.reload_monitor()
|
||||
|
||||
def reload_monitor(self):
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from typing import Any, Union
|
||||
|
||||
from app.core.config import ConfigChangeEvent, config_notifier, ConfigChangeType
|
||||
from app.db import DbOper
|
||||
from app.db.models.systemconfig import SystemConfig
|
||||
from app.schemas.types import SystemConfigKey
|
||||
from app.schemas.types import SystemConfigKey, EventType
|
||||
from app.utils.singleton import Singleton
|
||||
from app.schemas import ConfigChangeEventData
|
||||
|
||||
|
||||
class SystemConfigOper(DbOper, metaclass=Singleton):
|
||||
@@ -35,22 +35,34 @@ class SystemConfigOper(DbOper, metaclass=Singleton):
|
||||
conf.update(self._db, {"value": value})
|
||||
# 发送配置变更通知
|
||||
if old_value != value:
|
||||
event = ConfigChangeEvent(key, old_value=old_value, new_value=value,
|
||||
change_type=ConfigChangeType.UPDATE)
|
||||
config_notifier.notify(event)
|
||||
from app.core.event import eventmanager
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
old_value=old_value,
|
||||
new_value=value,
|
||||
change_type="update"
|
||||
))
|
||||
else:
|
||||
conf.delete(self._db, conf.id)
|
||||
# 发送配置删除通知
|
||||
event = ConfigChangeEvent(key, old_value=old_value, new_value=None,
|
||||
change_type=ConfigChangeType.DELETE)
|
||||
config_notifier.notify(event)
|
||||
from app.core.event import eventmanager
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
old_value=old_value,
|
||||
new_value=value,
|
||||
change_type="delete"
|
||||
))
|
||||
else:
|
||||
conf = SystemConfig(key=key, value=value)
|
||||
conf.create(self._db)
|
||||
# 发送配置变更通知
|
||||
event = ConfigChangeEvent(key, old_value=None, new_value=value,
|
||||
change_type=ConfigChangeType.ADD)
|
||||
config_notifier.notify(event)
|
||||
from app.core.event import eventmanager
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
old_value=old_value,
|
||||
new_value=value,
|
||||
change_type="add"
|
||||
))
|
||||
|
||||
def get(self, key: Union[str, SystemConfigKey] = None) -> Any:
|
||||
"""
|
||||
@@ -81,9 +93,13 @@ class SystemConfigOper(DbOper, metaclass=Singleton):
|
||||
if conf:
|
||||
conf.delete(self._db, conf.id)
|
||||
# 发送配置变更通知
|
||||
event = ConfigChangeEvent(key, old_value=old_value, new_value=None,
|
||||
change_type=ConfigChangeType.ADD)
|
||||
config_notifier.notify(event)
|
||||
from app.core.event import eventmanager
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
old_value=old_value,
|
||||
new_value=None,
|
||||
change_type="delete"
|
||||
))
|
||||
return True
|
||||
|
||||
def __del__(self):
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
from typing import Any, Generator, List, Optional, Tuple, Union
|
||||
|
||||
from app import schemas
|
||||
from app.core.config import on_config_change
|
||||
from app.core.context import MediaInfo
|
||||
from app.core.event import eventmanager
|
||||
from app.core.event import eventmanager, Event
|
||||
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
|
||||
from app.schemas.types import MediaType, ModuleType, ChainEventType, MediaServerType, SystemConfigKey, EventType
|
||||
|
||||
|
||||
class EmbyModule(_ModuleBase, _MediaServerBase[Emby]):
|
||||
|
||||
@on_config_change([SystemConfigKey.MediaServers.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -20,6 +18,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "Emby"
|
||||
@@ -271,7 +282,8 @@ class EmbyModule(_ModuleBase, _MediaServerBase[Emby]):
|
||||
) for season, episodes in seasoninfo.items()]
|
||||
|
||||
def mediaserver_playing(self, server: str,
|
||||
count: Optional[int] = 20, username: Optional[str] = None) -> List[schemas.MediaServerPlayItem]:
|
||||
count: Optional[int] = 20, username: Optional[str] = None) -> List[
|
||||
schemas.MediaServerPlayItem]:
|
||||
"""
|
||||
获取媒体服务器正在播放信息
|
||||
"""
|
||||
@@ -290,7 +302,8 @@ class EmbyModule(_ModuleBase, _MediaServerBase[Emby]):
|
||||
return server_obj.get_play_url(item_id)
|
||||
|
||||
def mediaserver_latest(self, server: Optional[str] = None,
|
||||
count: Optional[int] = 20, username: Optional[str] = None) -> List[schemas.MediaServerPlayItem]:
|
||||
count: Optional[int] = 20, username: Optional[str] = None) -> List[
|
||||
schemas.MediaServerPlayItem]:
|
||||
"""
|
||||
获取媒体服务器最新入库条目
|
||||
"""
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
from typing import Any, Generator, List, Optional, Tuple, Union
|
||||
|
||||
from app import schemas
|
||||
from app.core.config import on_config_change
|
||||
from app.core.context import MediaInfo
|
||||
from app.core.event import eventmanager
|
||||
from app.core.event import eventmanager, Event
|
||||
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
|
||||
from app.schemas.types import MediaType, ModuleType, ChainEventType, MediaServerType, SystemConfigKey, EventType
|
||||
|
||||
|
||||
class JellyfinModule(_ModuleBase, _MediaServerBase[Jellyfin]):
|
||||
|
||||
@on_config_change([SystemConfigKey.MediaServers.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -21,6 +19,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "Jellyfin"
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
from typing import Optional, Tuple, Union, Any, List, Generator
|
||||
|
||||
from app import schemas
|
||||
from app.core.config import on_config_change
|
||||
from app.core.context import MediaInfo
|
||||
from app.core.event import eventmanager
|
||||
from app.core.event import eventmanager, Event
|
||||
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
|
||||
from app.schemas.types import MediaType, ModuleType, ChainEventType, MediaServerType, SystemConfigKey, EventType
|
||||
|
||||
|
||||
class PlexModule(_ModuleBase, _MediaServerBase[Plex]):
|
||||
|
||||
@on_config_change([SystemConfigKey.MediaServers.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -21,6 +19,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "Plex"
|
||||
|
||||
@@ -5,19 +5,19 @@ from qbittorrentapi import TorrentFilesList
|
||||
from torrentool.torrent import Torrent
|
||||
|
||||
from app import schemas
|
||||
from app.core.config import settings, on_config_change
|
||||
from app.core.config import settings
|
||||
from app.core.metainfo import MetaInfo
|
||||
from app.core.event import eventmanager, Event
|
||||
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
|
||||
from app.schemas.types import TorrentStatus, ModuleType, DownloaderType, SystemConfigKey, EventType
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]):
|
||||
|
||||
@on_config_change([SystemConfigKey.Downloaders.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -25,6 +25,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "Qbittorrent"
|
||||
@@ -287,7 +300,8 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]):
|
||||
dlspeed=StringUtils.str_filesize(torrent.get('dlspeed')),
|
||||
upspeed=StringUtils.str_filesize(torrent.get('upspeed')),
|
||||
left_time=StringUtils.str_secends(
|
||||
(torrent.get('total_size') - torrent.get('completed')) / torrent.get('dlspeed')) if torrent.get(
|
||||
(torrent.get('total_size') - torrent.get('completed')) / torrent.get(
|
||||
'dlspeed')) if torrent.get(
|
||||
'dlspeed') > 0 else ''
|
||||
))
|
||||
else:
|
||||
|
||||
@@ -2,18 +2,17 @@ import json
|
||||
import re
|
||||
from typing import Optional, Union, List, Tuple, Any
|
||||
|
||||
from app.core.config import on_config_change
|
||||
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
|
||||
from app.schemas.types import ModuleType, SystemConfigKey
|
||||
from app.schemas import MessageChannel, CommingMessage, Notification, ConfigChangeEventData
|
||||
from app.schemas.types import ModuleType, SystemConfigKey, EventType
|
||||
|
||||
|
||||
class SlackModule(_ModuleBase, _MessageBase[Slack]):
|
||||
|
||||
@on_config_change([SystemConfigKey.Notifications.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -22,6 +21,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "Slack"
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
from typing import Optional, Union, List, Tuple, Any
|
||||
|
||||
from app.core.config import on_config_change
|
||||
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
|
||||
from app.schemas.types import ModuleType, SystemConfigKey
|
||||
from app.schemas import MessageChannel, CommingMessage, Notification, ConfigChangeEventData
|
||||
from app.schemas.types import ModuleType, SystemConfigKey, EventType
|
||||
|
||||
|
||||
class SynologyChatModule(_ModuleBase, _MessageBase[SynologyChat]):
|
||||
|
||||
@on_config_change([SystemConfigKey.Notifications.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -20,6 +19,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "Synology Chat"
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import copy
|
||||
import json
|
||||
from typing import Optional, Union, List, Tuple, Any, Dict
|
||||
from typing import Dict
|
||||
from typing import Optional, Union, List, Tuple, Any
|
||||
|
||||
from app.core.config import on_config_change
|
||||
from app.core.context import MediaInfo, Context
|
||||
from app.core.event import 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
|
||||
from app.schemas.types import ModuleType, ChainEventType, SystemConfigKey
|
||||
from app.schemas import MessageChannel, CommingMessage, Notification, CommandRegisterEventData, ConfigChangeEventData
|
||||
from app.schemas.types import ModuleType, ChainEventType, SystemConfigKey, EventType
|
||||
from app.utils.structures import DictUtils
|
||||
|
||||
|
||||
class TelegramModule(_ModuleBase, _MessageBase[Telegram]):
|
||||
|
||||
@on_config_change([SystemConfigKey.Notifications.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -24,6 +24,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "Telegram"
|
||||
|
||||
@@ -5,19 +5,19 @@ from torrentool.torrent import Torrent
|
||||
from transmission_rpc import File
|
||||
|
||||
from app import schemas
|
||||
from app.core.config import settings, on_config_change
|
||||
from app.core.config import settings
|
||||
from app.core.metainfo import MetaInfo
|
||||
from app.core.event import eventmanager, Event
|
||||
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
|
||||
from app.schemas.types import TorrentStatus, ModuleType, DownloaderType, SystemConfigKey, EventType
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]):
|
||||
|
||||
@on_config_change([SystemConfigKey.Downloaders.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -25,6 +25,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "Transmission"
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
from typing import Any, Generator, List, Optional, Tuple, Union
|
||||
|
||||
from app import schemas
|
||||
from app.core.config import on_config_change
|
||||
from app.core.context import MediaInfo
|
||||
from app.core.event import eventmanager
|
||||
from app.core.event import eventmanager, Event
|
||||
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
|
||||
from app.schemas.types import ChainEventType, MediaServerType, MediaType, ModuleType, SystemConfigKey, EventType
|
||||
|
||||
|
||||
class TrimeMediaModule(_ModuleBase, _MediaServerBase[TrimeMedia]):
|
||||
|
||||
@on_config_change([SystemConfigKey.MediaServers.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -25,6 +23,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "飞牛影视"
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import json
|
||||
from typing import Optional, Union, List, Tuple, Any, Dict
|
||||
|
||||
from app.core.config import on_config_change
|
||||
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
|
||||
from app.schemas.types import ModuleType, SystemConfigKey
|
||||
from app.schemas import MessageChannel, CommingMessage, Notification, ConfigChangeEventData
|
||||
from app.schemas.types import ModuleType, SystemConfigKey, EventType
|
||||
|
||||
|
||||
class VoceChatModule(_ModuleBase, _MessageBase[VoceChat]):
|
||||
|
||||
@on_config_change([SystemConfigKey.Notifications.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -21,6 +20,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "VoceChat"
|
||||
|
||||
@@ -3,16 +3,16 @@ from typing import Union, Tuple
|
||||
|
||||
from pywebpush import webpush, WebPushException
|
||||
|
||||
from app.core.config import global_vars, settings, on_config_change
|
||||
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
|
||||
from app.schemas.types import ModuleType, MessageChannel, SystemConfigKey
|
||||
from app.schemas import Notification, ConfigChangeEventData
|
||||
from app.schemas.types import ModuleType, MessageChannel, SystemConfigKey, EventType
|
||||
|
||||
|
||||
class WebPushModule(_ModuleBase, _MessageBase):
|
||||
|
||||
@on_config_change([SystemConfigKey.Notifications.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -20,6 +20,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "WebPush"
|
||||
|
||||
@@ -2,22 +2,20 @@ import copy
|
||||
import xml.dom.minidom
|
||||
from typing import Optional, Union, List, Tuple, Any, Dict
|
||||
|
||||
from app.core.config import on_config_change
|
||||
from app.core.context import Context, MediaInfo
|
||||
from app.core.event import eventmanager
|
||||
from app.core.event import Event, 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
|
||||
from app.schemas.types import ModuleType, ChainEventType, SystemConfigKey
|
||||
from app.schemas import MessageChannel, CommingMessage, Notification, CommandRegisterEventData, ConfigChangeEventData
|
||||
from app.schemas.types import ModuleType, ChainEventType, SystemConfigKey, EventType
|
||||
from app.utils.dom import DomUtils
|
||||
from app.utils.structures import DictUtils
|
||||
|
||||
|
||||
class WechatModule(_ModuleBase, _MessageBase[WeChat]):
|
||||
|
||||
@on_config_change([SystemConfigKey.Notifications.value])
|
||||
def init_module(self) -> None:
|
||||
"""
|
||||
初始化模块
|
||||
@@ -26,6 +24,19 @@ 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
|
||||
self.init_module()
|
||||
|
||||
@staticmethod
|
||||
def get_name() -> str:
|
||||
return "微信"
|
||||
|
||||
@@ -14,14 +14,16 @@ from watchdog.observers.polling import PollingObserver
|
||||
from app.chain import ChainBase
|
||||
from app.chain.storage import StorageChain
|
||||
from app.chain.transfer import TransferChain
|
||||
from app.core.config import settings, on_config_change
|
||||
from app.core.config import settings
|
||||
from app.db.systemconfig_oper import SystemConfigOper
|
||||
from app.helper.directory import DirectoryHelper
|
||||
from app.helper.message import MessageHelper
|
||||
from app.log import logger
|
||||
from app.schemas import FileItem
|
||||
from app.schemas.types import SystemConfigKey
|
||||
from app.schemas.types import SystemConfigKey, EventType
|
||||
from app.utils.singleton import Singleton
|
||||
from app.core.event import Event, eventmanager
|
||||
from app.schemas import ConfigChangeEventData
|
||||
|
||||
lock = Lock()
|
||||
snapshot_lock = Lock()
|
||||
@@ -86,7 +88,19 @@ class Monitor(metaclass=Singleton):
|
||||
# 启动目录监控和文件整理
|
||||
self.init()
|
||||
|
||||
@on_config_change([SystemConfigKey.Directories.value])
|
||||
@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.Directories.value]:
|
||||
return
|
||||
self.init()
|
||||
|
||||
def init(self):
|
||||
"""
|
||||
启动监控
|
||||
|
||||
@@ -18,18 +18,17 @@ from app.chain.subscribe import SubscribeChain
|
||||
from app.chain.tmdb import TmdbChain
|
||||
from app.chain.transfer import TransferChain
|
||||
from app.chain.workflow import WorkflowChain
|
||||
from app.core.config import settings, on_config_change
|
||||
from app.core.event import EventManager
|
||||
from app.core.config import settings
|
||||
from app.core.event import EventManager, eventmanager, Event
|
||||
from app.core.plugin import PluginManager
|
||||
from app.db.systemconfig_oper import SystemConfigOper
|
||||
from app.helper.sites import SitesHelper
|
||||
from app.log import logger
|
||||
from app.schemas import Notification, NotificationType, Workflow
|
||||
from app.schemas import Notification, NotificationType, Workflow, ConfigChangeEventData
|
||||
from app.schemas.types import EventType, SystemConfigKey
|
||||
from app.utils.singleton import Singleton
|
||||
from app.utils.timer import TimerUtils
|
||||
|
||||
|
||||
lock = threading.Lock()
|
||||
|
||||
|
||||
@@ -57,8 +56,20 @@ class Scheduler(metaclass=Singleton):
|
||||
def __init__(self):
|
||||
self.init()
|
||||
|
||||
@on_config_change(['DEV', 'COOKIECLOUD_INTERVAL', 'MEDIASERVER_SYNC_INTERVAL', 'SUBSCRIBE_SEARCH',
|
||||
'SUBSCRIBE_MODE', 'SUBSCRIBE_RSS_INTERVAL', 'SITEDATA_REFRESH_INTERVAL'])
|
||||
@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 ['DEV', 'COOKIECLOUD_INTERVAL', 'MEDIASERVER_SYNC_INTERVAL', 'SUBSCRIBE_SEARCH',
|
||||
'SUBSCRIBE_MODE', 'SUBSCRIBE_RSS_INTERVAL', 'SITEDATA_REFRESH_INTERVAL']:
|
||||
return
|
||||
self.init()
|
||||
|
||||
def init(self):
|
||||
"""
|
||||
初始化定时服务
|
||||
|
||||
@@ -22,6 +22,16 @@ class BaseEventData(BaseModel):
|
||||
pass
|
||||
|
||||
|
||||
class ConfigChangeEventData(BaseEventData):
|
||||
"""
|
||||
ConfigChange 事件的数据模型
|
||||
"""
|
||||
key: str = Field(..., description="配置项的键")
|
||||
old_value: Optional[Any] = Field(default=None, description="配置项的旧值")
|
||||
new_value: Optional[Any] = Field(default=None, description="配置项的新值")
|
||||
change_type: str = Field(default="update", description="配置项的变更类型,如 'add', 'update', 'delete'")
|
||||
|
||||
|
||||
class ChainEventData(BaseEventData):
|
||||
"""
|
||||
链式事件数据的基类,所有具体事件数据类应继承自此类
|
||||
|
||||
@@ -61,6 +61,8 @@ class EventType(Enum):
|
||||
MetadataScrape = "metadata.scrape"
|
||||
# 模块需要重载
|
||||
ModuleReload = "module.reload"
|
||||
# 配置项更新
|
||||
ConfigChanged = "config.updated"
|
||||
|
||||
|
||||
# 同步链式事件
|
||||
|
||||
Reference in New Issue
Block a user