diff --git a/astrbot/api/event/filter/__init__.py b/astrbot/api/event/filter/__init__.py index 7354ec766c..f5ab15ed09 100644 --- a/astrbot/api/event/filter/__init__.py +++ b/astrbot/api/event/filter/__init__.py @@ -25,6 +25,8 @@ ) from astrbot.core.star.register import register_on_platform_loaded as on_platform_loaded from astrbot.core.star.register import register_on_plugin_error as on_plugin_error +from astrbot.core.star.register import register_on_plugin_loaded as on_plugin_loaded +from astrbot.core.star.register import register_on_plugin_unloaded as on_plugin_unloaded from astrbot.core.star.register import register_on_using_llm_tool as on_using_llm_tool from astrbot.core.star.register import ( register_on_waiting_llm_request as on_waiting_llm_request, @@ -54,6 +56,8 @@ "on_llm_request", "on_llm_response", "on_plugin_error", + "on_plugin_loaded", + "on_plugin_unloaded", "on_platform_loaded", "on_waiting_llm_request", "permission_type", diff --git a/astrbot/core/star/register/__init__.py b/astrbot/core/star/register/__init__.py index f1daf2968b..5e99948cd2 100644 --- a/astrbot/core/star/register/__init__.py +++ b/astrbot/core/star/register/__init__.py @@ -14,6 +14,8 @@ register_on_llm_tool_respond, register_on_platform_loaded, register_on_plugin_error, + register_on_plugin_loaded, + register_on_plugin_unloaded, register_on_using_llm_tool, register_on_waiting_llm_request, register_permission_type, @@ -34,6 +36,8 @@ "register_on_llm_request", "register_on_llm_response", "register_on_plugin_error", + "register_on_plugin_loaded", + "register_on_plugin_unloaded", "register_on_platform_loaded", "register_on_waiting_llm_request", "register_permission_type", diff --git a/astrbot/core/star/register/star_handler.py b/astrbot/core/star/register/star_handler.py index c4ed0d4a7e..87b9b9998f 100644 --- a/astrbot/core/star/register/star_handler.py +++ b/astrbot/core/star/register/star_handler.py @@ -357,6 +357,40 @@ def decorator(awaitable): return decorator +def register_on_plugin_loaded(**kwargs): + """当有插件加载完成时 + + Hook 参数: + metadata + + 说明: + 当有插件加载完成时,触发该事件并获取到该插件的元数据 + """ + + def decorator(awaitable): + _ = get_handler_or_create(awaitable, EventType.OnPluginLoadedEvent, **kwargs) + return awaitable + + return decorator + + +def register_on_plugin_unloaded(**kwargs): + """当有插件卸载完成时 + + Hook 参数: + metadata + + 说明: + 当有插件卸载完成时,触发该事件并获取到该插件的元数据 + """ + + def decorator(awaitable): + _ = get_handler_or_create(awaitable, EventType.OnPluginUnloadedEvent, **kwargs) + return awaitable + + return decorator + + def register_on_waiting_llm_request(**kwargs): """当等待调用 LLM 时的通知事件(在获取锁之前) diff --git a/astrbot/core/star/star_handler.py b/astrbot/core/star/star_handler.py index 63b0c447de..762db86553 100644 --- a/astrbot/core/star/star_handler.py +++ b/astrbot/core/star/star_handler.py @@ -144,6 +144,8 @@ def get_handlers_by_event_type( not in ( EventType.OnAstrBotLoadedEvent, EventType.OnPlatformLoadedEvent, + EventType.OnPluginLoadedEvent, + EventType.OnPluginUnloadedEvent, ) and not plugin.reserved ): @@ -201,6 +203,8 @@ class EventType(enum.Enum): OnLLMToolRespondEvent = enum.auto() # 调用函数工具后 OnAfterMessageSentEvent = enum.auto() # 发送消息后 OnPluginErrorEvent = enum.auto() # 插件处理消息异常时 + OnPluginLoadedEvent = enum.auto() # 插件加载完成 + OnPluginUnloadedEvent = enum.auto() # 插件卸载完成 H = TypeVar("H", bound=Callable[..., Any]) diff --git a/astrbot/core/star/star_manager.py b/astrbot/core/star/star_manager.py index 93512bde21..06e59e2fd4 100644 --- a/astrbot/core/star/star_manager.py +++ b/astrbot/core/star/star_manager.py @@ -33,7 +33,7 @@ from .context import Context from .filter.permission import PermissionType, PermissionTypeFilter from .star import star_map, star_registry -from .star_handler import star_handlers_registry +from .star_handler import EventType, star_handlers_registry from .updator import PluginUpdator try: @@ -772,6 +772,19 @@ async def load( if hasattr(metadata.star_cls, "initialize") and metadata.star_cls: await metadata.star_cls.initialize() + # 触发插件加载事件 + handlers = star_handlers_registry.get_handlers_by_event_type( + EventType.OnPluginLoadedEvent, + ) + for handler in handlers: + try: + logger.info( + f"hook(on_plugin_loaded) -> {star_map[handler.handler_module_path].name} - {handler.handler_name}", + ) + await handler.handler(metadata) + except Exception: + logger.error(traceback.format_exc()) + except BaseException as e: logger.error(f"----- 插件 {root_dir_name} 载入失败 -----") errors = traceback.format_exc() @@ -1159,6 +1172,19 @@ async def _terminate_plugin(star_metadata: StarMetadata) -> None: elif "terminate" in star_metadata.star_cls_type.__dict__: await star_metadata.star_cls.terminate() + # 触发插件卸载事件 + handlers = star_handlers_registry.get_handlers_by_event_type( + EventType.OnPluginUnloadedEvent, + ) + for handler in handlers: + try: + logger.info( + f"hook(on_plugin_unloaded) -> {star_map[handler.handler_module_path].name} - {handler.handler_name}", + ) + await handler.handler(star_metadata) + except Exception: + logger.error(traceback.format_exc()) + async def turn_on_plugin(self, plugin_name: str) -> None: plugin = self.context.get_registered_star(plugin_name) if plugin is None: