Merge branch 'main' of https://gitea.functen.cn/shihao/WechatHookBot
This commit is contained in:
@@ -1,35 +1,144 @@
|
||||
"""
|
||||
插件基类模块
|
||||
|
||||
提供插件的基础功能:
|
||||
- 生命周期钩子(on_load, on_enable, on_disable, on_unload, on_reload)
|
||||
- 定时任务管理
|
||||
- 依赖声明
|
||||
- 插件元数据
|
||||
"""
|
||||
|
||||
from abc import ABC
|
||||
from typing import List
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, List, Optional, TYPE_CHECKING
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from .decorators import scheduler, add_job_safe, remove_job_safe
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from utils.plugin_manager import PluginManager
|
||||
|
||||
|
||||
class PluginState(Enum):
|
||||
"""插件状态"""
|
||||
UNLOADED = "unloaded" # 未加载
|
||||
LOADED = "loaded" # 已加载(未启用)
|
||||
ENABLED = "enabled" # 已启用
|
||||
DISABLED = "disabled" # 已禁用
|
||||
ERROR = "error" # 错误状态
|
||||
|
||||
|
||||
class PluginBase(ABC):
|
||||
"""插件基类"""
|
||||
"""
|
||||
插件基类
|
||||
|
||||
生命周期:
|
||||
1. __init__() - 构造函数(同步)
|
||||
2. on_load() - 加载时调用(异步,可访问其他插件)
|
||||
3. async_init() - 异步初始化(异步,加载配置、资源等)
|
||||
4. on_enable() - 启用时调用(异步,注册定时任务)
|
||||
5. on_disable() - 禁用时调用(异步,清理定时任务)
|
||||
6. on_unload() - 卸载时调用(异步,释放资源)
|
||||
7. on_reload() - 重载前调用(异步,保存状态)
|
||||
|
||||
使用示例:
|
||||
class MyPlugin(PluginBase):
|
||||
description = "我的插件"
|
||||
author = "作者"
|
||||
version = "1.0.0"
|
||||
dependencies = ["AIChat"] # 依赖的插件
|
||||
load_priority = 60 # 加载优先级
|
||||
|
||||
async def on_load(self, plugin_manager):
|
||||
# 可以访问其他插件
|
||||
aichat = plugin_manager.plugins.get("AIChat")
|
||||
|
||||
async def async_init(self):
|
||||
# 加载配置、初始化资源
|
||||
self.config = load_config()
|
||||
|
||||
async def on_enable(self, bot):
|
||||
await super().on_enable(bot) # 注册定时任务
|
||||
# 额外的启用逻辑
|
||||
|
||||
async def on_disable(self):
|
||||
await super().on_disable() # 清理定时任务
|
||||
# 额外的禁用逻辑
|
||||
|
||||
async def on_unload(self):
|
||||
# 释放资源、关闭连接
|
||||
await self.close_connections()
|
||||
|
||||
async def on_reload(self) -> dict:
|
||||
# 返回需要保存的状态
|
||||
return {"counter": self.counter}
|
||||
|
||||
async def restore_state(self, state: dict):
|
||||
# 重载后恢复状态
|
||||
self.counter = state.get("counter", 0)
|
||||
"""
|
||||
|
||||
# ==================== 插件元数据 ====================
|
||||
|
||||
# 插件元数据
|
||||
description: str = "暂无描述"
|
||||
author: str = "未知"
|
||||
version: str = "1.0.0"
|
||||
|
||||
# 插件依赖(填写依赖的插件类名列表)
|
||||
# 例如: dependencies = ["MessageLogger", "AIChat"]
|
||||
dependencies: List[str] = []
|
||||
|
||||
# 加载优先级(数值越大越先加载,默认50)
|
||||
# 基础插件设置高优先级,依赖其他插件的设置低优先级
|
||||
load_priority: int = 50
|
||||
|
||||
# ==================== 实例属性 ====================
|
||||
|
||||
def __init__(self):
|
||||
self.enabled = False
|
||||
self._scheduled_jobs = set()
|
||||
self.state = PluginState.UNLOADED
|
||||
self._scheduled_jobs: set = set()
|
||||
self._bot = None
|
||||
self._plugin_manager: Optional["PluginManager"] = None
|
||||
self._saved_state: Dict[str, Any] = {}
|
||||
|
||||
# ==================== 生命周期钩子 ====================
|
||||
|
||||
async def on_load(self, plugin_manager: "PluginManager"):
|
||||
"""
|
||||
插件加载时调用
|
||||
|
||||
此时其他依赖的插件已经加载完成,可以安全访问。
|
||||
|
||||
Args:
|
||||
plugin_manager: 插件管理器实例
|
||||
"""
|
||||
self._plugin_manager = plugin_manager
|
||||
self.state = PluginState.LOADED
|
||||
logger.debug(f"[{self.__class__.__name__}] on_load 调用")
|
||||
|
||||
async def async_init(self):
|
||||
"""
|
||||
插件异步初始化
|
||||
|
||||
用于加载配置、初始化资源等耗时操作。
|
||||
在 on_load 之后、on_enable 之前调用。
|
||||
"""
|
||||
pass
|
||||
|
||||
async def on_enable(self, bot=None):
|
||||
"""插件启用时调用"""
|
||||
"""
|
||||
插件启用时调用
|
||||
|
||||
# 定时任务
|
||||
注册定时任务、启动后台服务等。
|
||||
|
||||
Args:
|
||||
bot: WechatHookClient 实例
|
||||
"""
|
||||
self._bot = bot
|
||||
self.enabled = True
|
||||
self.state = PluginState.ENABLED
|
||||
|
||||
# 注册定时任务
|
||||
for method_name in dir(self):
|
||||
method = getattr(self, method_name)
|
||||
if hasattr(method, '_is_scheduled'):
|
||||
@@ -39,18 +148,85 @@ class PluginBase(ABC):
|
||||
|
||||
add_job_safe(scheduler, job_id, method, bot, trigger, **trigger_args)
|
||||
self._scheduled_jobs.add(job_id)
|
||||
|
||||
if self._scheduled_jobs:
|
||||
logger.success("插件 {} 已加载定时任务: {}", self.__class__.__name__, self._scheduled_jobs)
|
||||
logger.success(f"插件 {self.__class__.__name__} 已加载定时任务: {self._scheduled_jobs}")
|
||||
|
||||
async def on_disable(self):
|
||||
"""插件禁用时调用"""
|
||||
|
||||
"""
|
||||
插件禁用时调用
|
||||
|
||||
清理定时任务、停止后台服务等。
|
||||
"""
|
||||
self.enabled = False
|
||||
self.state = PluginState.DISABLED
|
||||
|
||||
# 移除定时任务
|
||||
for job_id in self._scheduled_jobs:
|
||||
remove_job_safe(scheduler, job_id)
|
||||
logger.info("已卸载定时任务: {}", self._scheduled_jobs)
|
||||
|
||||
if self._scheduled_jobs:
|
||||
logger.info(f"已卸载定时任务: {self._scheduled_jobs}")
|
||||
self._scheduled_jobs.clear()
|
||||
|
||||
async def async_init(self):
|
||||
"""插件异步初始化"""
|
||||
return
|
||||
async def on_unload(self):
|
||||
"""
|
||||
插件卸载时调用
|
||||
|
||||
释放资源、关闭连接、保存数据等。
|
||||
在 on_disable 之后调用。
|
||||
"""
|
||||
self.state = PluginState.UNLOADED
|
||||
self._bot = None
|
||||
self._plugin_manager = None
|
||||
logger.debug(f"[{self.__class__.__name__}] on_unload 调用")
|
||||
|
||||
async def on_reload(self) -> Dict[str, Any]:
|
||||
"""
|
||||
插件重载前调用
|
||||
|
||||
返回需要在重载后恢复的状态数据。
|
||||
|
||||
Returns:
|
||||
需要保存的状态字典
|
||||
"""
|
||||
logger.debug(f"[{self.__class__.__name__}] on_reload 调用")
|
||||
return {}
|
||||
|
||||
async def restore_state(self, state: Dict[str, Any]):
|
||||
"""
|
||||
重载后恢复状态
|
||||
|
||||
Args:
|
||||
state: on_reload 返回的状态字典
|
||||
"""
|
||||
self._saved_state = state
|
||||
logger.debug(f"[{self.__class__.__name__}] 状态已恢复: {list(state.keys())}")
|
||||
|
||||
# ==================== 辅助方法 ====================
|
||||
|
||||
def get_plugin(self, plugin_name: str) -> Optional["PluginBase"]:
|
||||
"""
|
||||
获取其他插件实例
|
||||
|
||||
Args:
|
||||
plugin_name: 插件类名
|
||||
|
||||
Returns:
|
||||
插件实例,不存在返回 None
|
||||
"""
|
||||
if self._plugin_manager:
|
||||
return self._plugin_manager.plugins.get(plugin_name)
|
||||
return None
|
||||
|
||||
def get_bot(self):
|
||||
"""获取 bot 实例"""
|
||||
return self._bot
|
||||
|
||||
@property
|
||||
def plugin_name(self) -> str:
|
||||
"""获取插件名称"""
|
||||
return self.__class__.__name__
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<{self.__class__.__name__} v{self.version} state={self.state.value}>"
|
||||
|
||||
Reference in New Issue
Block a user