# /// # PLUGIN.md # 描述:插件系统开发指南 # 作者:User # 创建日期:2026-04-05 # 更新日期:2026-04-07 # /// # WXAuto Center 插件系统开发指南 ## 目录 1. [概述](#概述) 2. [插件类型](#插件类型) 3. [创建插件](#创建插件) 4. [表单化配置系统](#表单化配置系统) 5. [插件通知系统](#插件通知系统) 6. [热加载插件](#热加载插件) 7. [内置插件](#内置插件) 8. [高级多节点推送插件](#高级多节点推送插件) 9. [插件管理API](#插件管理api) 10. [前端使用](#前端使用) 11. [最佳实践](#最佳实践) 12. [目录结构](#目录结构) 13. [生命周期](#生命周期) --- ## 概述 WXAuto Center 采用模块化插件架构,支持热插拔功能扩展。开发者可以创建自定义插件来处理消息、数据源、定时任务等。 ### 核心组件 | 组件 | 说明 | |------|------| | `PluginBase` | 所有插件的基类 | | `ScheduledTaskPlugin` | 定时任务插件基类(含通知功能) | | `PluginRegistry` | 插件注册表,管理所有插件 | | `PluginType` | 插件类型枚举 | | `PluginConfigSchema` | 表单化配置Schema系统 | | `HotReloadPluginLoader` | 热加载服务,监控插件目录变化 | | `plugin_notification_service` | 插件通知服务 | --- ## 插件类型 | 类型 | 值 | 说明 | |------|-----|------| | `MESSAGE_HANDLER` | `message_handler` | 消息处理器,用于自动回复、消息过滤 | | `DATA_SOURCE` | `data_source` | 数据源,用于获取天气、新闻、股票等 | | `ACTION_TRIGGER` | `action_trigger` | 动作触发器,用于Webhook回调、定时任务 | | `AI_AGENT` | `ai_agent` | AI智能体,用于LLM对话、智能回复 | | `SCHEDULED_TASK` | `scheduled_task` | 定时任务,执行周期性操作 | | `HTTP_SCHEDULED_SENDER` | `http_scheduled_sender` | 定时HTTP推送,定时请求API并发送结果 | | `CUSTOM` | `custom` | 自定义类型 | --- ## 创建插件 ### 基础结构 ```python # /// # my_plugin.py # 描述:我的自定义插件 # /// from plugins.base import PluginBase, PluginType class MyPlugin(PluginBase): plugin_name = "my_plugin" plugin_version = "1.0.0" plugin_type = PluginType.CUSTOM plugin_description = "我的自定义插件" plugin_author = "开发者名称" def initialize(self, config: dict) -> bool: self.config = config return True def execute(self, params: dict) -> dict: return {"success": True, "result": "done"} ``` ### 定时任务插件 ```python # /// # my_scheduled_plugin.py # 描述:定时任务插件示例 # /// from plugins.base import ScheduledTaskPlugin from plugins.plugin_config_schema import ( PluginConfigSchema, ConfigSection, ConfigField, FieldType ) def get_config_schema() -> PluginConfigSchema: schema = PluginConfigSchema("my_scheduled_plugin") schema.add_section(ConfigSection( name="basic", label="基本设置", fields=[ ConfigField( name="cron", label="执行周期", field_type=FieldType.CRON, default="*/5 * * * *" ), ConfigField( name="enabled", label="启用插件", field_type=FieldType.BOOLEAN, default=False ) ] )) return schema class MyScheduledPlugin(ScheduledTaskPlugin): plugin_name = "my_scheduled_plugin" plugin_version = "1.0.0" plugin_description = "定时任务插件" plugin_author = "开发者" config_schema = staticmethod(get_config_schema) def get_cron_expression(self) -> str: return self.cron_expression def should_run_and_get_next(self) -> tuple: return True, None def run_task(self) -> dict: self.notify("任务完成", "定时任务执行成功") return {"success": True} ``` --- ## 表单化配置系统 ### 字段类型 | 类型 | 值 | 说明 | 对应UI | |------|-----|------|--------| | `STRING` | `string` | 文本输入 | input[type=text] | | `PASSWORD` | `password` | 密码输入 | input[type=password] | | `NUMBER` | `number` | 数字输入 | input[type=number] | | `BOOLEAN` | `boolean` | 开关 | checkbox | | `SELECT` | `select` | 下拉选择 | select | | `TEXTAREA` | `textarea` | 多行文本 | textarea | | `CRON` | `cron` | Cron表达式 | input[type=text] | ### 配置示例 ```python from plugins.plugin_config_schema import ( PluginConfigSchema, ConfigSection, ConfigField, FieldType ) def get_config_schema() -> PluginConfigSchema: schema = PluginConfigSchema("my_plugin") schema.add_section(ConfigSection( name="basic", label="基本设置", fields=[ ConfigField( name="cron", label="执行周期", field_type=FieldType.CRON, required=True, default="*/5 * * * *", description="Cron表达式,如 */5 * * * *" ), ConfigField( name="node_id", label="节点ID", field_type=FieldType.STRING, required=True, default="wx1" ), ConfigField( name="receiver", label="接收人", field_type=FieldType.STRING, required=True ), ConfigField( name="timeout", label="超时时间", field_type=FieldType.NUMBER, default=15, min_value=5, max_value=60 ), ConfigField( name="enabled", label="启用插件", field_type=FieldType.BOOLEAN, default=False ) ] )) return schema ``` ### API 调用 ```bash # 获取插件表单Schema curl http://localhost:8080/api/v1/plugins/{plugin_name}/schema \ -H "X-API-Key: your-external-api-key" # 响应示例 { "success": true, "schema": { "plugin_name": "my_plugin", "sections": [ { "name": "basic", "label": "基本设置", "fields": [ {"name": "cron", "label": "执行周期", "type": "cron", ...} ] } ] }, "has_form": true } ``` --- ## 插件通知系统 所有继承 `ScheduledTaskPlugin` 的插件都可以使用通知功能。 ### 使用方法 ```python # 普通通知 self.notify(title, message, level) # 快捷方法 self.notify_error(title, message) # 错误通知 self.notify_warning(title, message) # 警告通知 self.notify_success(title, message) # 成功通知 ``` ### 配置接收 在告警配置中添加 Webhook,勾选 **"插件通知"** 事件类型: ```bash curl -X POST "http://localhost:8080/api/v1/webhook/" \ -H "X-API-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "name": "插件通知", "url": "https://api.day.app/your-bark-key", "format": "bark", "event_types": ["plugin_notification"] }' ``` ### 事件类型 | 事件类型 | 说明 | |----------|------| | `api_error` | API错误 | | `wechat_offline` | 微信离线 | | `wechat_online` | 微信上线 | | `node_offline` | 节点离线 | | `node_online` | 节点上线 | | `plugin_notification` | 插件通知 | --- ## 热加载插件 ### 工作原理 ``` ┌─────────────────────────────────────────────────────────────┐ │ HotReloadPluginLoader (独立线程) │ │ │ │ 1. watchdog 监控 /app/plugins/custom 目录 │ │ 2. 检测到 .py 文件变化 → 自动重新加载 │ │ 3. importlib 动态导入模块 │ │ 4. 自动注册到 PluginRegistry │ └─────────────────────────────────────────────────────────────┘ ``` ### 插件目录 - **Docker 内路径**: `/app/plugins/custom` - **宿主机路径**: `./plugins/custom` ### 挂载配置 ```yaml # docker-compose.yml volumes: - ./plugins/custom:/app/plugins/custom # 双向同步 ``` --- ## 高级多节点推送插件 ### 简介 `advanced_sender` 是高级多节点数据推送插件,支持: - 多数据源独立配置 - 每数据源独立节点和接收人设置 - 外部 MySQL 数据库去重 - 班次时段路由 - Cookie 失效检测和通知 - 熔断保护机制 ### 表单配置 ``` 默认设置(可被数据源覆盖) ├── 默认节点ID: wx1 └── 默认接收人: asq 数据源1 ├── Cookie: [文本框] ├── 节点ID: [留空使用默认] └── 接收人: [留空使用默认] 数据源2 ├── Cookie: [文本框] ├── 节点ID: [留空使用默认] └── 接收人: [留空使用默认] 外部数据库 ├── 数据库地址: 192.168.2.27 ├── 端口: 3306 ├── 用户名: root2 ├── 密码: **** ├── 数据库名: addb └── 表名: user_data 抓取设置 ├── 请求超时(秒): 15 └── 数据源间隔(秒): 20 ``` ### 配置参数 | 参数 | 说明 | 默认值 | |------|------|--------| | `cron` | 执行周期 | `*/2 * * * *` | | `enable_cron` | 启用定时任务 | false | | `node_id` | 默认节点ID | wx1 | | `receiver` | 默认接收人 | asq | | `cookie_1` | 数据源1 Cookie | - | | `cookie_2` | 数据源2 Cookie | - | | `node_id_1` | 数据源1节点ID(留空用默认) | - | | `receiver_1` | 数据源1接收人(留空用默认) | - | | `node_id_2` | 数据源2节点ID(留空用默认) | - | | `receiver_2` | 数据源2接收人(留空用默认) | - | | `db_host` | 数据库地址 | 192.168.2.27 | | `db_port` | 端口 | 3306 | | `db_user` | 用户名 | root2 | | `db_password` | 密码 | root@root | | `db_name` | 数据库名 | addb | | `db_table` | 表名 | user_data | | `fetch_timeout` | 请求超时(秒) | 15 | | `send_interval` | 数据源间隔(秒) | 20 | ### 班次路由 | 时段 | 路由规则 | |------|----------| | 0-7点 | 跳过 | | 8-16点 | 发送 | | 17-21点 | 发送 | | 22-23点 | 跳过 | ### 操作 | action | 说明 | |--------|------| | `send` | 执行完整流程 | | `test` | 测试配置 | | `test_send` | 测试发送(可指定node_id和receiver) | | `query_pending` | 查询待发送数据 | ### 测试发送 ```bash # 使用默认节点和接收人 curl -X POST "http://localhost:8080/api/v1/plugins/advanced_sender/execute" \ -H "X-API-Key: your-api-key" \ -d '{"action": "test_send", "msg": "测试消息"}' # 指定节点和接收人 curl -X POST "http://localhost:8080/api/v1/plugins/advanced_sender/execute" \ -H "X-API-Key: your-api-key" \ -d '{"action": "test_send", "node_id": "wx1", "receiver": "asq", "msg": "测试"}' ``` ### 获取日志 ```bash curl "http://localhost:8080/api/v1/plugins/advanced_sender/logs?lines=100" \ -H "X-API-Key: your-api-key" ``` ### Cookie 失效检测 - 当 HTTP 返回 403/401 时,判定为 Cookie 失效 - 当数据源返回空数据时,判定为 Cookie 可能失效 - 首次检测到问题发送告警通知 - 恢复成功后发送成功通知 - 后续执行不再重复报警 --- ## 插件管理API | 接口 | 方法 | 说明 | |------|------|------| | `GET /api/v1/plugins/` | GET | 获取所有插件 | | `GET /api/v1/plugins/hotloaded` | GET | 获取热加载插件列表 | | `POST /api/v1/plugins/hotreload` | POST | 手动触发热重载 | | `GET /api/v1/plugins/{name}` | GET | 获取插件详情 | | `GET /api/v1/plugins/{name}/schema` | GET | 获取插件表单Schema | | `POST /api/v1/plugins/{name}/enable` | POST | 启用插件 | | `POST /api/v1/plugins/{name}/disable` | POST | 禁用插件 | | `PUT /api/v1/plugins/{name}/config` | PUT | 更新插件配置 | | `POST /api/v1/plugins/{name}/execute` | POST | 执行插件 | | `GET /api/v1/plugins/{name}/logs` | GET | 获取插件日志 | | `POST /api/v1/plugins/{name}/logs/clear` | POST | 清空插件日志 | ### 配置插件示例 ```bash curl -X PUT "http://localhost:8080/api/v1/plugins/advanced_sender/config" \ -H "X-API-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "name": "advanced_sender", "config": { "cron": "*/2 * * * *", "enable_cron": true, "node_id": "wx1", "receiver": "asq", "cookie_1": "PHPSESSID=xxx; think_var=zh-cn", "cookie_2": "PHPSESSID=yyy; think_var=zh-cn", "db_host": "192.168.2.27", "db_port": 3306, "db_user": "root2", "db_password": "root@root", "db_name": "addb", "db_table": "user_data" } }' ``` ### 执行插件示例 ```bash # 执行发送任务 curl -X POST "http://localhost:8080/api/v1/plugins/advanced_sender/execute" \ -H "X-API-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{"action": "send"}' # 测试配置 curl -X POST "http://localhost:8080/api/v1/plugins/advanced_sender/execute" \ -H "X-API-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{"action": "test"}' ``` --- ## 前端使用 访问 **插件管理** 页面(侧边栏菜单): 1. **查看插件列表** - 显示所有已注册插件 2. **启用/禁用** - 点击按钮控制插件状态 3. **配置** - 点击配置按钮打开表单化配置界面 4. **日志** - 点击日志按钮查看插件独立日志 5. **执行** - 点击执行按钮测试插件 ### 配置界面 - 表单化配置,无需手动编辑 JSON - Section 可折叠,方便管理 - 支持所有字段类型(文本、数字、密码、开关、下拉等) - 自动验证必填项 ### 日志界面 - 实时显示插件日志 - 支持刷新 - 日志文件保存在 `/app/data/logs/{plugin_name}.log` --- ## 最佳实践 ### 1. 使用表单化配置 ```python from plugins.plugin_config_schema import ( PluginConfigSchema, ConfigSection, ConfigField, FieldType ) def get_config_schema() -> PluginConfigSchema: schema = PluginConfigSchema("my_plugin") schema.add_section(ConfigSection( name="basic", label="基本设置", fields=[ ConfigField(name="key", label="键", field_type=FieldType.STRING, required=True) ] )) return schema class MyPlugin(ScheduledTaskPlugin): config_schema = staticmethod(get_config_schema) ``` ### 2. 使用通知功能 ```python class MyPlugin(ScheduledTaskPlugin): def run_task(self): try: # 业务逻辑 self.notify_success("任务完成", "发送了 10 条消息") except Exception as e: self.notify_error("任务失败", str(e)) ``` ### 3. 错误处理 ```python def execute(self, params: Dict[str, Any]) -> Dict[str, Any]: try: return {"success": True, "data": result} except Exception as e: return {"success": False, "error": str(e)} ``` ### 4. 定时任务防重复 ```python def run_task(self) -> Dict[str, Any]: if self._running: logger.warning("Previous task still running, skipping") return {"success": False, "error": "上一次执行尚未完成"} ``` --- ## 目录结构 ``` wxauto_api/ ├── plugins/ │ ├── __init__.py │ ├── base.py # 插件基类和注册表 │ ├── builtin.py # 内置插件实现 │ ├── plugin_loader.py # 热加载插件加载器 │ ├── plugin_config_schema.py # 表单化配置系统 │ ├── http_scheduled_sender.py # 定时HTTP推送插件 │ ├── advanced_sender_plugin.py # 高级多节点推送插件 │ └── custom/ # 自定义插件目录(热加载) │ ├── __init__.py │ └── my_plugin.py ├── services/ │ └── plugin_notification_service.py # 插件通知服务 ├── static/ │ ├── js/ │ │ └── app.js # 前端插件管理 │ └── css/ │ └── style.css └── doc/ └── wxauto_center/ └── PLUGIN.md # 本文档 ``` --- ## 生命周期 1. **注册** - `PluginRegistry.register(plugin)` 2. **初始化** - `plugin.initialize(config)` 3. **启用** - `plugin.enable()` 4. **执行** - `plugin.execute(params)` 或 `plugin.run_task()` 5. **禁用** - `plugin.disable()` 6. **卸载** - `PluginRegistry.unregister(name)` ### 热加载流程 1. **启动** - `HotReloadPluginLoader.start()` 2. **扫描** - 扫描 `/app/plugins/custom` 目录 3. **监听** - `watchdog` 监控文件变化 4. **加载** - `importlib` 动态导入模块 5. **注册** - 自动注册到 `PluginRegistry` 6. **停止** - `HotReloadPluginLoader.stop()`