初始化提交

This commit is contained in:
2026-04-07 14:11:45 +08:00
parent 46342134b6
commit c412e4de5f
69 changed files with 19321 additions and 1 deletions
File diff suppressed because it is too large Load Diff
+317
View File
@@ -0,0 +1,317 @@
# WxAuto HTTP API 使用文档
## 接口认证
所有API请求都需要在请求头中包含API密钥:
```http
X-API-Key: test-key-2
```
## API接口示例
### 1. API密钥验证
验证API密钥是否有效。
```bash
curl -X POST http://10.255.0.90:5000/api/auth/verify \
-H "X-API-Key: test-key-2"
```
响应示例:
```json
{
"code": 0,
"message": "验证成功",
"data": {
"valid": true
}
}
```
### 2. 微信基础功能
#### 2.1 初始化微信
初始化微信实例,建议在使用其他接口前先调用此接口。
```bash
curl -X POST http://10.255.0.90:5000/api/wechat/initialize \
-H "X-API-Key: test-key-2"
```
响应示例:
```json
{
"code": 0,
"message": "初始化成功",
"data": {
"status": "connected"
}
}
```
#### 2.2 获取微信状态
检查微信连接状态。
```bash
curl -X GET http://10.255.0.90:5000/api/wechat/status \
-H "X-API-Key: test-key-2"
```
响应示例:
```json
{
"code": 0,
"message": "获取成功",
"data": {
"status": "online"
}
}
```
### 3. 消息相关接口
#### 3.1 发送普通文本消息
发送普通文本消息到指定联系人或群组。
```bash
curl -X POST http://10.255.0.90:5000/api/message/send \
-H "X-API-Key: test-key-2" \
-H "Content-Type: application/json" \
-d '{
"receiver": "文件传输助手",
"message": "这是一条测试消息",
"at_list": ["张三", "李四"],
"clear": true
}'
```
参数说明:
- receiver: 接收者(联系人或群组名称)
- message: 消息内容
- at_list: (可选)需要@的群成员列表
- clear: (可选)是否清除输入框,默认为true
响应示例:
```json
{
"code": 0,
"message": "发送成功",
"data": {
"message_id": "success"
}
}
```
#### 3.2 发送打字机模式消息
使用打字机模式发送消息(模拟真人打字效果)。
```bash
curl -X POST http://10.255.0.90:5000/api/message/send-typing \
-H "X-API-Key: test-key-2" \
-H "Content-Type: application/json" \
-d '{
"receiver": "文件传输助手",
"message": "这是一条打字机模式消息\n这是第二行",
"at_list": ["张三"],
"clear": true
}'
```
参数说明同普通消息发送。
#### 3.3 发送文件
发送一个或多个文件。
```bash
curl -X POST http://10.255.0.90:5000/api/message/send-file \
-H "X-API-Key: test-key-2" \
-H "Content-Type: application/json" \
-d '{
"receiver": "文件传输助手",
"file_paths": [
"D:/test/file1.txt",
"D:/test/image.jpg"
]
}'
```
参数说明:
- receiver: 接收者
- file_paths: 要发送的文件路径列表
响应示例:
```json
{
"code": 0,
"message": "发送成功",
"data": {
"success_count": 2,
"failed_files": []
}
}
```
### 4. 群组相关接口
#### 4.1 获取群列表
获取当前账号的群聊列表。
```bash
curl -X GET http://10.255.0.90:5000/api/group/list \
-H "X-API-Key: test-key-2"
```
响应示例:
```json
{
"code": 0,
"message": "获取成功",
"data": {
"groups": [
{"name": "测试群1"},
{"name": "测试群2"}
]
}
}
```
#### 4.2 群组管理
执行群组管理操作(如重命名、退群等)。
```bash
curl -X POST http://10.255.0.90:5000/api/group/manage \
-H "X-API-Key: test-key-2" \
-H "Content-Type: application/json" \
-d '{
"group_name": "测试群",
"action": "rename",
"params": {
"new_name": "新群名称"
}
}'
```
支持的操作类型:
- rename: 重命名群组
- quit: 退出群组
### 5. 联系人相关接口
#### 5.1 获取好友列表
获取当前账号的好友列表。
```bash
curl -X GET http://10.255.0.90:5000/api/contact/list \
-H "X-API-Key: test-key-2"
```
响应示例:
```json
{
"code": 0,
"message": "获取成功",
"data": {
"friends": [
{"nickname": "张三"},
{"nickname": "李四"}
]
}
}
```
### 6. 健康检查接口
获取服务和微信连接状态。
```bash
curl -X GET http://10.255.0.90:5000/api/health \
-H "X-API-Key: test-key-2"
```
响应示例:
```json
{
"code": 0,
"message": "服务正常",
"data": {
"status": "ok",
"wechat_status": "connected",
"uptime": 3600
}
}
```
## 错误码说明
- 0: 成功
- 1001: 认证失败(API密钥无效)
- 1002: 参数错误
- 2001: 微信未初始化
- 2002: 微信已掉线
- 3001: 发送消息失败
- 3002: 获取消息失败
- 4001: 群操作失败
- 5001: 好友操作失败
- 5000: 服务器内部错误
## 使用建议
1. 在使用其他接口前,先调用初始化接口
2. 使用健康检查接口监控服务状态
3. 合理处理错误码,做好重试机制
4. 注意文件发送时的路径正确性
5. 群发消息时建议加入适当延时
## PowerShell示例
如果您使用PowerShell,可以使用以下格式发送请求:
```powershell
$headers = @{
"X-API-Key" = "test-key-2"
"Content-Type" = "application/json"
}
$body = @{
receiver = "文件传输助手"
message = "测试消息"
} | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri "http://10.255.0.90:5000/api/message/send" -Headers $headers -Body $body
```
## Python示例
使用Python requests库的示例:
```python
import requests
API_KEY = "test-key-2"
BASE_URL = "http://10.255.0.90:5000/api"
headers = {
"X-API-Key": API_KEY,
"Content-Type": "application/json"
}
# 发送消息示例
response = requests.post(
f"{BASE_URL}/message/send",
headers=headers,
json={
"receiver": "文件传输助手",
"message": "测试消息"
}
)
print(response.json())
File diff suppressed because it is too large Load Diff
+344
View File
@@ -0,0 +1,344 @@
# ///
# API.md
# 描述:WXAuto Center API 接口文档
# 作者:AI Generated
# 创建日期:2026-04-06
# 更新日期:2026-04-06
# ///
# WXAuto Center API 接口文档
## 概述
本系统提供完整的 RESTful API,支持节点管理、消息发送、插件管理、外部程序接入、Webhook 管理等功能。所有 API 均使用 JSON 格式进行请求和响应。
## 基础信息
| 项目 | 说明 |
|------|------|
| Base URL | `http://{host}:{port}/api/v1` |
| 默认端口 | 8080 |
| 内部 API 认证 | Header: `X-API-Key: your-external-api-key` |
| 外部 API 认证 | Header: `X-ExternalKey: your-external-api-key` |
| 响应格式 | JSON |
## API 列表
### 节点管理 `/api/v1/nodes`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/nodes/` | 获取所有节点 |
| GET | `/nodes/{node_id}` | 获取指定节点信息 |
| POST | `/nodes/` | 添加节点 |
| PUT | `/nodes/{node_id}` | 更新节点信息 |
| DELETE | `/nodes/{node_id}` | 删除节点 |
| GET | `/nodes/{node_id}/status` | 检查节点状态 |
| POST | `/nodes/{node_id}/enable` | 启用节点 |
| POST | `/nodes/{node_id}/disable` | 禁用节点 |
| GET | `/nodes/{node_id}/friends` | 获取节点好友列表 |
| GET | `/nodes/{node_id}/groups` | 获取节点群列表 |
| GET | `/nodes/{node_id}/messages/{chat_name}` | 获取聊天消息 |
### 消息管理 `/api/v1/messages`
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/messages/send` | 发送消息 |
| POST | `/messages/send_group` | 发送群消息 |
| POST | `/messages/batch` | 批量发送消息 |
| POST | `/messages/template/{node_id}/{who}` | 发送模板消息 |
| GET | `/messages/history/{node_id}/{chat_name}` | 获取消息历史 |
### 插件管理 `/api/v1/plugins`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/plugins/` | 获取所有插件 |
| GET | `/plugins/{plugin_name}` | 获取插件详情 |
| GET | `/plugins/{plugin_name}/schema` | 获取插件表单Schema |
| POST | `/plugins/{plugin_name}/enable` | 启用插件 |
| POST | `/plugins/{plugin_name}/disable` | 禁用插件 |
| PUT | `/plugins/{plugin_name}/config` | 更新插件配置 |
| POST | `/plugins/{plugin_name}/execute` | 执行插件 |
| GET | `/plugins/{plugin_name}/logs` | 获取插件日志 |
| POST | `/plugins/{plugin_name}/logs/clear` | 清空插件日志 |
| GET | `/plugins/type/{plugin_type}` | 按类型获取插件 |
### 回调接口 `/api/v1/callback`
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/callback/node/reset` | 重置节点微信状态 |
| POST | `/callback/node/check` | 检测节点微信状态 |
| GET | `/callback/node/{node_id}/status` | 获取节点回调状态 |
### Webhook 管理 `/api/v1/webhook`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/webhook/` | 获取所有Webhook |
| GET | `/webhook/{webhook_id}` | 获取指定Webhook |
| POST | `/webhook/` | 添加Webhook |
| PUT | `/webhook/{webhook_id}` | 更新Webhook |
| DELETE | `/webhook/{webhook_id}` | 删除Webhook |
| POST | `/webhook/{webhook_id}/enable` | 启用Webhook |
| POST | `/webhook/{webhook_id}/disable` | 禁用Webhook |
### 外部接口 `/api/v1/external`
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/external/send` | 外部接口-发送消息 |
| POST | `/external/trigger` | 外部接口-触发数据处理 |
| POST | `/external/plugin/execute` | 外部接口-执行插件 |
| GET | `/external/plugins` | 外部接口-获取可用插件列表 |
| GET | `/external/nodes` | 外部接口-获取可用节点 |
| POST | `/external/ai/process` | 外部接口-AI处理消息 |
| POST | `/external/webhook/{event}` | 外部接口-Webhook接收 |
---
## 节点管理 API 详解
### 获取所有节点
```
GET /api/v1/nodes/
```
**响应示例:**
```json
{
"success": true,
"data": [
{
"node_id": "wx1",
"name": "微信1",
"api_url": "http://192.168.20.84:5000",
"enabled": true,
"description": "",
"group": "wechat",
"status": "error",
"wechat_status": "online",
"is_healthy": false
}
],
"count": 1
}
```
### 添加节点
```
POST /api/v1/nodes/
```
**请求体:**
```json
{
"node_id": "wx1",
"name": "微信1",
"api_url": "http://192.168.20.84:5000",
"api_key": "your-node-api-key",
"description": "测试节点",
"group": "wechat"
}
```
### 更新节点
```
PUT /api/v1/nodes/{node_id}
```
**请求体:**
```json
{
"api_url": "http://192.168.20.84:5000",
"api_key": "updated-key"
}
```
---
## 消息发送 API 详解
### 发送消息
```
POST /api/v1/messages/send
```
**请求体:**
```json
{
"node_id": "wx1",
"who": "文件传输助手",
"msg": "测试消息",
"msg_type": "text"
}
```
**响应示例:**
```json
{
"success": true,
"message": "消息发送成功"
}
```
### 发送群消息
```
POST /api/v1/messages/send_group
```
**请求体:**
```json
{
"node_id": "wx1",
"group_name": "测试群",
"msg": "群消息测试",
"msg_type": "text"
}
```
---
## 插件管理 API 详解
### 获取所有插件
```
GET /api/v1/plugins/
```
**响应示例:**
```json
{
"success": true,
"plugins": [
{
"name": "http_scheduled_sender",
"version": "1.0.0",
"type": "scheduled_task",
"description": "定时HTTP数据源推送",
"enabled": true,
"config": {
"node_id": "wx1",
"receiver": "asq",
"cron": "0 8 * * *"
}
}
],
"count": 1
}
```
### 配置插件
```
PUT /api/v1/plugins/{plugin_name}/config
```
**请求体:**
```json
{
"name": "http_scheduled_sender",
"config": {
"node_id": "wx1",
"receiver": "文件传输助手",
"cron": "0 8 * * *",
"http_url": "https://api.example.com/news",
"message_template": "📰 {title}\n{url}"
}
}
```
### 执行插件
```
POST /api/v1/plugins/{plugin_name}/execute
```
**请求体:**
```json
{
"action": "preview"
}
```
**action 选项:**
- `send` - 执行完整流程
- `fetch` - 仅请求API
- `parse` - 请求并解析数据
- `preview` - 预览格式化后的消息
- `test` - 测试cron表达式
---
## 通用响应格式
**成功:**
```json
{
"success": true,
"data": {},
"message": "操作成功"
}
```
**失败:**
```json
{
"success": false,
"error": "错误描述"
}
```
---
## 插件类型
| 类型 | 值 | 说明 |
|------|-----|------|
| `message_handler` | MESSAGE_HANDLER | 消息处理器 |
| `data_source` | DATA_SOURCE | 数据源 |
| `action_trigger` | ACTION_TRIGGER | 动作触发器 |
| `ai_agent` | AI_AGENT | AI智能体 |
| `scheduled_task` | SCHEDULED_TASK | 定时任务 |
| `http_scheduled_sender` | HTTP_SCHEDULED_SENDER | 定时HTTP推送 |
| `custom` | CUSTOM | 自定义 |
---
## 节点数据模型
```json
{
"node_id": "wx1",
"name": "微信1",
"api_url": "http://192.168.20.84:5000",
"api_key": "your-key",
"enabled": true,
"description": "",
"group": "wechat",
"status": "active",
"wechat_status": "online",
"is_healthy": true
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| node_id | string | 节点唯一标识 |
| name | string | 节点显示名称 |
| api_url | string | 节点API地址 |
| api_key | string | 节点API密钥 |
| enabled | bool | 是否启用 |
| description | string | 节点描述 |
| group | string | 节点分组 |
| status | string | API状态 (active/inactive/error) |
| wechat_status | string | 微信状态 (online/offline) |
| is_healthy | bool | 健康状态 |
+235
View File
@@ -0,0 +1,235 @@
# ///
# ARCHITECTURE.md
# 描述:WXAuto Center 系统架构文档
# 作者:AI Generated
# 创建日期:2026-04-05
# 更新日期:2026-04-06
# ///
# WXAuto Center 系统架构文档
## 概述
WXAuto Center 是一个模块化的微信多节点中控系统,采用前后端分离架构,支持多节点管理、消息发送、插件扩展、定时任务等功能。
## 系统架构图
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ WXAuto Center │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Frontend (Static) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │Dashboard │ │ Nodes │ │ Messages │ │ Plugins │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ FastAPI Backend │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │ │
│ │ │nodes router │ │messages router│ │plugins router│ │webhook router│ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └───────────┘ │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │ │
│ │ │callback router│ │external router│ │webhook service│ │queue service│ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ └───────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────┼────────────────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Redis │ │ PostgreSQL │ │ Nodes │ │
│ │ (Queue) │ │ (Storage) │ │ (External) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## 核心组件
### 1. 前端 (Frontend)
静态文件服务,基于原生 JavaScript 开发。
**页面模块:**
| 页面 | 文件 | 说明 |
|------|------|------|
| 首页/仪表盘 | app.js | 系统概览 |
| 节点管理 | app.js | 节点 CRUD |
| 快捷消息 | app.js | 快速发送消息 |
| 监控告警 | app.js | Webhook 配置 |
| 日志查看 | app.js | 系统日志 |
| 外部接入 | app.js | 外部 API 文档 |
| 插件管理 | app.js | 插件配置 |
### 2. 后端 (Backend)
基于 FastAPI 的 RESTful API 服务。
**API 模块:**
| 模块 | 路径 | 说明 |
|------|------|------|
| nodes | /api/v1/nodes | 节点管理 |
| messages | /api/v1/messages | 消息发送 |
| plugins | /api/v1/plugins | 插件管理 |
| webhook | /api/v1/webhook | Webhook 管理 |
| callback | /api/v1/callback | 回调接口 |
| external | /api/v1/external | 外部接口 |
### 3. 服务层 (Services)
| 服务 | 说明 |
|------|------|
| node_manager | 节点管理器,内存缓存 |
| monitor_service | 节点健康监控服务 |
| scheduler_service | 定时任务调度服务 |
| log_service | 日志服务 |
| queue_service | 消息队列服务 |
| webhook_service | Webhook 通知服务 |
### 4. 插件系统 (Plugins)
| 插件 | 类型 | 说明 |
|------|------|------|
| http_data_source | DATA_SOURCE | HTTP 数据源 |
| database_query | DATA_SOURCE | 数据库查询 |
| webhook_trigger | ACTION_TRIGGER | Webhook 触发 |
| simple_ai_agent | AI_AGENT | AI 智能体 |
| http_scheduled_sender | SCHEDULED_TASK | 定时 HTTP 推送 |
### 5. 数据层 (Data)
| 组件 | 说明 |
|------|------|
| PostgreSQL | 主数据库,存储节点、Webhook、日志、插件配置 |
| Redis | 消息队列、缓存 |
---
## 目录结构
```
wxauto_api/
├── main.py # 应用入口
├── config.py # 配置管理
├── models.py # 数据模型
├── database_service.py # 数据库服务
├── requirements.txt # Python 依赖
├── Dockerfile # Docker 镜像
├── docker-compose.yml # Docker 编排
│
├── api/ # API 路由
│ ├── __init__.py
│ ├── nodes.py # 节点管理
│ ├── messages.py # 消息发送
│ ├── plugins.py # 插件管理
│ ├── webhook.py # Webhook 管理
│ ├── callback.py # 回调接口
│ └── external.py # 外部接口
│
├── services/ # 业务服务
│ ├── __init__.py
│ ├── node_manager.py # 节点管理
│ ├── monitor_service.py # 健康监控
│ ├── scheduler_service.py # 定时调度
│ ├── log_service.py # 日志服务
│ ├── queue_service.py # 队列服务
│ └── webhook_service.py # Webhook 服务
│
├── plugins/ # 插件系统
│ ├── __init__.py
│ ├── base.py # 插件基类
│ ├── builtin.py # 内置插件
│ └── http_scheduled_sender.py # 定时推送插件
│
├── utils/ # 工具函数
│ └── auth.py # 认证中间件
│
├── static/ # 静态文件
│ ├── index.html # 主页面
│ └── js/ # JavaScript
│ ├── api.js # API 封装
│ ├── app.js # 主应用
│ └── pages/
│ └── templates.js # 页面模板
│
└── doc/ # 文档
└── wxauto_center/
├── ARCHITECTURE.md # 架构文档
├── API.md # API 文档
├── DATABASE.md # 数据库文档
├── FLOWS.md # 流程文档
└── PLUGIN.md # 插件文档
```
---
## 技术栈
| 层级 | 技术 | 说明 |
|------|------|------|
| 前端 | HTML/CSS/JavaScript | 原生开发,无框架依赖 |
| 后端 | Python 3.11 + FastAPI | 高性能异步框架 |
| 数据库 | PostgreSQL | 关系型数据库 |
| 缓存/队列 | Redis | 内存数据库、消息队列 |
| 容器 | Docker + Docker Compose | 容器化部署 |
| ORM | SQLAlchemy | Python ORM |
| HTTP 客户端 | httpx | 异步 HTTP 客户端 |
---
## 部署架构
```
┌─────────────────────────────────────────────────────────────┐
│ Docker Network │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ wxauto-center│ │ wxauto-redis │ │wxauto-postgres│ │
│ │ :8080 │ │ :6379 │ │ :5432 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ External Nodes │ │ External │
│ (wxauto nodes) │ │ Webhook URLs │
│ :5000 │ │ │
└──────────────────┘ └──────────────────┘
```
### 环境变量
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `POSTGRES_USER` | PostgreSQL 用户 | wxauto |
| `POSTGRES_PASSWORD` | PostgreSQL 密码 | wxauto_password |
| `POSTGRES_DB` | 数据库名 | wxauto |
| `REDIS_PASSWORD` | Redis 密码 | wxauto_redis |
| `API_KEY` | API 认证密钥 | your-external-api-key |
| `EXTERNAL_KEY` | 外部接口密钥 | your-external-api-key |
---
## 安全机制
### 1. API 认证
- 内部 API:Header `X-API-Key`
- 外部 API:Header `X-ExternalKey`
### 2. 异常处理
- 全局异常处理器
- 所有 API 调用包裹 try/except
- 10 秒 HTTP 超时
### 3. 数据一致性
- 数据库优先原则
- 启动时从数据库加载配置
- 操作时同时更新内存和数据库
+618
View File
@@ -0,0 +1,618 @@
# ///
# CONFIG.md
# 描述:配置文件说明
# 作者:AI Generated
# 创建日期:2026-04-06
# 最后更新:2026-04-06
# ///
# WXAuto Center 配置文件说明
## 概述
系统配置支持多种配置源,按优先级从高到低依次为:
1. 环境变量(`.env` 文件)
2. 配置文件(`config.json`)
3. 代码默认值
## 配置文件结构
### config.json
主配置文件,仅包含应用配置。**节点配置和 Webhook 配置已迁移到数据库**。
```json
{
"app_name": "WXAuto Center",
"host": "0.0.0.0",
"port": 8080,
"debug": true,
"secret_key": "wxauto-center-secret-key-change-in-production",
"workers": 1,
"cors_origins": ["*"],
"api_prefix": "/api/v1",
"external_api_key": "your-external-api-key",
"monitor": {
"enabled": true,
"check_interval": 30
}
}
```
### .env 环境变量文件
Docker 环境变量配置文件。
```
# ///
# .env
# 描述:环境变量配置(用于 Docker 环境)
# ///
# 数据库配置
DATABASE_URL=postgresql://wxauto:wxauto_password@postgres:5432/wxauto
# Redis 配置
REDIS_URL=redis://redis:6379/0
# 应用配置
APP_NAME=WXAuto Center
HOST=0.0.0.0
PORT=8080
DEBUG=true
SECRET_KEY=wxauto-center-secret-key-change-in-production
WORKERS=1
# API 配置
API_PREFIX=/api/v1
EXTERNAL_API_KEY=your-external-api-key
CORS_ORIGINS=["*"]
# 监控配置
MONITOR_ENABLED=true
MONITOR_CHECK_INTERVAL=30
```
---
## 配置项详细说明
### 应用配置
#### app_name
| 属性 | 说明 |
|------|------|
| 类型 | string |
| 默认值 | "WXAuto Center" |
| 环境变量 | APP_NAME |
| 说明 | 应用名称,显示在页面标题和日志中 |
#### host
| 属性 | 说明 |
|------|------|
| 类型 | string |
| 默认值 | "0.0.0.0" |
| 环境变量 | HOST |
| 说明 | 服务监听地址,0.0.0.0 表示监听所有网络接口 |
#### port
| 属性 | 说明 |
|------|------|
| 类型 | int |
| 默认值 | 8080 |
| 环境变量 | PORT |
| 说明 | 服务监听端口 |
#### debug
| 属性 | 说明 |
|------|------|
| 类型 | bool |
| 默认值 | false |
| 环境变量 | DEBUG |
| 说明 | 调试模式,启用时支持热重载 |
#### secret_key
| 属性 | 说明 |
|------|------|
| 类型 | string |
| 默认值 | "wxauto-center-secret-key-change-in-production" |
| 环境变量 | SECRET_KEY |
| 说明 | 应用密钥,用于会话加密等安全用途,生产环境必须修改 |
---
### API 配置
#### api_prefix
| 属性 | 说明 |
|------|------|
| 类型 | string |
| 默认值 | "/api/v1" |
| 环境变量 | API_PREFIX |
| 说明 | API 路由前缀,所有 API 路径都会此前缀开头 |
#### external_api_key
| 属性 | 说明 |
|------|------|
| 类型 | string |
| 默认值 | "your-external-api-key" |
| 环境变量 | EXTERNAL_API_KEY |
| 说明 | 外部 API 密钥,用于外部系统调用时的认证 |
#### cors_origins
| 属性 | 说明 |
|------|------|
| 类型 | array[string] |
| 默认值 | ["*"] |
| 环境变量 | CORS_ORIGINS |
| 说明 | 允许的 CORS 来源,* 表示允许所有来源(仅限开发环境使用) |
---
## 节点配置 (NodeConfig)
**重要更新**:节点配置已从 config.json 迁移到 PostgreSQL 数据库的 `nodes` 表。
### 配置存储
| 存储位置 | 说明 |
|----------|------|
| PostgreSQL | nodes 表(生产环境推荐) |
| config.json | 已废弃,不再支持 |
### 节点数据模型
```json
{
"node_id": "wx1",
"name": "微信1",
"api_url": "http://192.168.1.100:5000",
"api_key": "your-node-api-key",
"enabled": true,
"description": "主节点",
"group": "default",
"status": "active",
"wechat_status": "online",
"is_healthy": true
}
```
### 节点标识说明
每个节点有两个标识:
| 字段 | 说明 | 示例 |
|------|------|------|
| node_id | 节点唯一标识,用于 API 调用 | "wx1", "node_001" |
| name | 节点显示名称,用于界面展示 | "微信1", "测试节点" |
### 配置项说明
| 配置项 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| node_id | string | 是 | - | 节点唯一标识(不可重复) |
| name | string | 否 | 等于 node_id | 节点显示名称 |
| api_url | string | 是 | - | 节点 API 服务地址 |
| api_key | string | 是 | - | 节点 API 密钥 |
| enabled | bool | 否 | true | 是否启用该节点 |
| description | string | 否 | "" | 节点描述信息 |
| group | string | 否 | "default" | 节点分组,用于分类管理 |
### API 管理节点
通过 API 管理节点配置:
```bash
# 添加节点
curl -X POST http://localhost:8080/api/v1/nodes \
-H "Content-Type: application/json" \
-H "X-API-Key: your-external-api-key" \
-d '{
"node_id": "wx1",
"name": "微信1",
"api_url": "http://192.168.1.100:5000",
"api_key": "your-node-api-key",
"description": "主节点",
"group": "production"
}'
# 获取所有节点
curl http://localhost:8080/api/v1/nodes \
-H "X-API-Key: your-external-api-key"
# 更新节点
curl -X PUT http://localhost:8080/api/v1/nodes/wx1 \
-H "Content-Type: application/json" \
-H "X-API-Key: your-external-api-key" \
-d '{"enabled": false}'
# 删除节点
curl -X DELETE http://localhost:8080/api/v1/nodes/wx1 \
-H "X-API-Key: your-external-api-key"
```
### 节点分组
节点分组功能允许将节点按业务线或用途进行分类管理:
```bash
# 查询特定分组的节点
curl "http://localhost:8080/api/v1/nodes?group=production" \
-H "X-API-Key: your-external-api-key"
```
---
## Webhook 配置 (WebhookConfig)
**重要更新**:Webhook 配置已从 config.json 迁移到 PostgreSQL 数据库的 `webhook_urls` 表。
### 配置存储
| 存储位置 | 说明 |
|----------|------|
| PostgreSQL | webhook_urls 表(推荐) |
| config.json | 已废弃,不再支持 |
### Webhook 数据模型
```json
{
"id": 1,
"name": "企业微信告警",
"url": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxx",
"format": "wechat",
"enabled": true,
"event_types": "wechat_offline,wechat_online,node_offline,node_online",
"created_at": "2026-04-06T10:00:00",
"updated_at": "2026-04-06T10:00:00"
}
```
### 配置项说明
| 配置项 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| name | string | 是 | - | Webhook 名称 |
| url | string | 是 | - | Webhook URL 地址 |
| format | string | 否 | "bark" | 消息格式:bark 或 wechat |
| enabled | bool | 否 | true | 是否启用 |
| event_types | string | 否 | 全部事件 | 需要触发 Webhook 的事件类型 |
### 支持的事件类型
| 事件类型 | 说明 | 触发时机 |
|----------|------|----------|
| api_error | API 错误 | 调用节点 API 失败 |
| wechat_offline | 微信掉线 | 微信状态变为 offline |
| wechat_online | 微信上线 | 微信状态变为 online/connected |
| node_offline | 节点离线 | 节点 API 不可达 |
| node_online | 节点在线 | 节点 API 恢复可用 |
### 消息格式
#### 企业微信格式 (format: "wechat")
```json
{
"msgtype": "text",
"text": {
"content": "【WXAuto Center 告警】\n事件类型: 微信掉线\n节点: wx1\n状态: offline\n时间: 2026-04-05 10:00:00"
}
}
```
#### Bark 格式 (format: "bark")
```json
{
"title": "WXAuto告警 - 微信掉线",
"body": "wx1\n状态: offline\n时间: 2026-04-05 10:00:00"
}
```
### API 管理 Webhook
```bash
# 添加 Webhook
curl -X POST http://localhost:8080/api/v1/webhook \
-H "Content-Type: application/json" \
-H "X-API-Key: your-external-api-key" \
-d '{
"name": "企业微信告警",
"url": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxx",
"format": "wechat",
"enabled": true,
"event_types": "wechat_offline,wechat_online,node_offline,node_online"
}'
# 获取所有 Webhook
curl http://localhost:8080/api/v1/webhook \
-H "X-API-Key: your-external-api-key"
# 更新 Webhook
curl -X PUT http://localhost:8080/api/v1/webhook/1 \
-H "Content-Type: application/json" \
-H "X-API-Key: your-external-api-key" \
-d '{"enabled": false}'
# 删除 Webhook
curl -X DELETE http://localhost:8080/api/v1/webhook/1 \
-H "X-API-Key: your-external-api-key"
# 启用/禁用 Webhook
curl -X POST http://localhost:8080/api/v1/webhook/1/enable \
-H "X-API-Key: your-external-api-key"
curl -X POST http://localhost:8080/api/v1/webhook/1/disable \
-H "X-API-Key: your-external-api-key"
```
---
## 监控配置 (MonitorConfig)
监控服务负责定时检测节点和微信状态。
```json
{
"monitor": {
"enabled": true,
"check_interval": 30
}
}
```
### 配置项说明
| 配置项 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| enabled | bool | 否 | true | 是否启用监控服务 |
| check_interval | int | 否 | 30 | 检测间隔(秒) |
### 检测逻辑
1. **API 检测**:定期调用节点 `/health` 接口检查节点是否在线
2. **微信检测**:定期调用 `/api/wechat/initialize` 检测微信连接状态
3. **状态变化**:当检测到状态变化时,触发 Webhook 通知
---
## 数据库配置
数据库配置通过环境变量设置:
| 环境变量 | 说明 | 默认值 |
|----------|------|--------|
| DATABASE_URL | PostgreSQL 连接 URL | postgresql://wxauto:wxauto_password@postgres:5432/wxauto |
### Docker 环境
```bash
DATABASE_URL=postgresql://wxauto:wxauto_password@postgres:5432/wxauto
```
### 本地环境
```bash
DATABASE_URL=postgresql://wxauto:wxauto_password@localhost:5432/wxauto
```
---
## Redis 配置
Redis 用于消息队列和缓存支持。
| 环境变量 | 说明 | 默认值 |
|----------|------|--------|
| REDIS_URL | Redis 连接 URL | redis://redis:6379/0 |
### Docker 环境
```bash
REDIS_URL=redis://redis:6379/0
```
### 本地环境
```bash
REDIS_URL=redis://localhost:6379/0
```
---
## Workers 配置
Workers 用于多进程部署,提高并发处理能力。
```json
{
"workers": 1
}
```
### 配置项说明
| 配置项 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| workers | int | 否 | 1 | 工作进程数,1 表示单进程模式 |
### 启动方式
| 模式 | workers | 说明 |
|------|---------|------|
| 单进程 | 1 | 默认模式,不启用多进程 |
| 多进程 | >1 | 启用多进程模式,需要 Redis 支持 |
**注意**:多进程模式需要 Redis 支持,队列服务依赖 Redis 进行进程间通信。
### 启动命令
```bash
# 单进程
python main.py
# 多进程
python main.py --workers 4
```
---
## 完整配置示例
### config.json
```json
{
"app_name": "WXAuto Center",
"host": "0.0.0.0",
"port": 8080,
"debug": false,
"secret_key": "your-production-secret-key",
"api_prefix": "/api/v1",
"external_api_key": "your-external-api-key",
"cors_origins": ["http://localhost:3000"],
"workers": 1,
"monitor": {
"enabled": true,
"check_interval": 30
}
}
```
### .env
```bash
# 数据库配置
DATABASE_URL=postgresql://wxauto:wxauto_password@postgres:5432/wxauto
# Redis 配置
REDIS_URL=redis://redis:6379/0
# 应用配置
APP_NAME=WXAuto Center
HOST=0.0.0.0
PORT=8080
DEBUG=false
SECRET_KEY=your-production-secret-key
WORKERS=1
# API 配置
API_PREFIX=/api/v1
EXTERNAL_API_KEY=your-external-api-key
CORS_ORIGINS=["http://localhost:3000"]
# 监控配置
MONITOR_ENABLED=true
MONITOR_CHECK_INTERVAL=30
```
---
## 环境变量配置优先级
某些敏感配置项可以通过环境变量覆盖配置文件:
| 环境变量 | 对应配置项 |
|----------|------------|
| APP_NAME | app_name |
| HOST | host |
| PORT | port |
| DEBUG | debug |
| SECRET_KEY | secret_key |
| API_PREFIX | api_prefix |
| EXTERNAL_API_KEY | external_api_key |
| CORS_ORIGINS | cors_origins |
| WORKERS | workers |
| DATABASE_URL | database.url |
| REDIS_URL | redis.url |
| MONITOR_ENABLED | monitor.enabled |
| MONITOR_CHECK_INTERVAL | monitor.check_interval |
---
## 配置加载与保存流程
```
启动时 (startup_event)
│
├──► load_config_from_file("config.json")
│ │
│ ▼
│ 解析 JSON 配置
│ │
│ ▼
│ 设置 Settings 各属性
│ │
│ ▼
│ 初始化数据库连接
│ │
│ ▼
│ 从数据库加载节点配置 (nodes 表)
│ │
│ ▼
│ NodeManager.add_node() 注册节点
│
└──► register_builtin_plugins()
关闭时 (shutdown_event)
│
├──► monitor_service.stop()
│
└──► 保存配置到文件 (如需要)
```
---
## 数据库表结构
### nodes 表
| 字段 | 类型 | 说明 |
|------|------|------|
| node_id | VARCHAR(50) | 节点唯一标识符 |
| name | VARCHAR(100) | 节点显示名称 |
| api_url | VARCHAR(255) | 节点 API 地址 |
| api_key | VARCHAR(255) | 节点 API 密钥 |
| enabled | BOOLEAN | 是否启用 |
| description | TEXT | 节点描述 |
| group | VARCHAR(50) | 节点分组 |
| status | VARCHAR(20) | API 状态 |
| wechat_status | VARCHAR(20) | 微信状态 |
| is_healthy | BOOLEAN | 健康状态 |
| created_at | TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | 更新时间 |
### webhook_urls 表
| 字段 | 类型 | 说明 |
|------|------|------|
| id | SERIAL | Webhook ID |
| name | VARCHAR(100) | Webhook 名称 |
| url | VARCHAR(500) | Webhook URL 地址 |
| format | VARCHAR(20) | 消息格式 (bark/wechat) |
| enabled | BOOLEAN | 是否启用 |
| event_types | TEXT | 支持的事件类型 |
| created_at | TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | 更新时间 |
### logs 表
| 字段 | 类型 | 说明 |
|------|------|------|
| id | SERIAL | 日志 ID |
| timestamp | TIMESTAMP | 日志时间 |
| level | VARCHAR(20) | 日志级别 |
| source | VARCHAR(50) | 日志来源 |
| message | TEXT | 日志消息 |
详细表结构请参阅 [DATABASE.md](./DATABASE.md)。
+282
View File
@@ -0,0 +1,282 @@
# ///
# DATABASE.md
# 描述:WXAuto Center 数据库设计文档
# 作者:AI Generated
# 创建日期:2026-04-05
# 更新日期:2026-04-06
# ///
# WXAuto Center 数据库设计文档
## 概述
本系统使用 PostgreSQL 数据库,通过 SQLAlchemy ORM 进行数据访问。数据库包含以下表:
| 表名 | 说明 |
|------|------|
| `nodes` | 节点配置表 |
| `webhook_urls` | Webhook URL 表 |
| `logs` | 日志表 |
| `plugin_configs` | 插件配置表 |
## ER 图
```
┌─────────────────┐ ┌─────────────────┐
│ nodes │ │ webhook_urls │
├─────────────────┤ ├─────────────────┤
│ node_id (PK) │ │ id (PK) │
│ name │ │ name │
│ api_url │ │ url │
│ api_key │ │ format │
│ enabled │ │ enabled │
│ description │ │ event_types │
│ group │ │ created_at │
│ status │ │ updated_at │
│ wechat_status │ └─────────────────┘
│ is_healthy │
│ health_message │
│ created_at │
│ updated_at │
└─────────────────┘
┌─────────────────┐ ┌─────────────────┐
│ logs │ │ plugin_configs │
├─────────────────┤ ├─────────────────┤
│ id (PK) │ │ id (PK) │
│ timestamp │ │ plugin_name │
│ level │ │ config_json │
│ source │ │ enabled │
│ message │ │ created_at │
└─────────────────┘ │ updated_at │
└─────────────────┘
```
---
## 表结构详解
### 1. nodes - 节点配置表
存储所有微信节点的信息。
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| `node_id` | VARCHAR(50) | **PK** | 节点唯一标识 |
| `name` | VARCHAR(100) | NOT NULL | 节点显示名称 |
| `api_url` | VARCHAR(255) | NOT NULL | 节点 API 地址 |
| `api_key` | VARCHAR(255) | NOT NULL | 节点 API 密钥 |
| `enabled` | BOOLEAN | DEFAULT true | 是否启用 |
| `description` | TEXT | DEFAULT '' | 节点描述 |
| `group` | VARCHAR(50) | DEFAULT 'default' | 节点分组 |
| `status` | VARCHAR(20) | DEFAULT 'inactive' | API 状态 |
| `wechat_status` | VARCHAR(20) | DEFAULT 'online' | 微信状态 |
| `is_healthy` | BOOLEAN | DEFAULT false | 健康检查状态 |
| `health_message` | VARCHAR(255) | DEFAULT '' | 健康检查消息 |
| `created_at` | TIMESTAMP | DEFAULT now | 创建时间 |
| `updated_at` | TIMESTAMP | DEFAULT now | 更新时间 |
**状态值说明:**
| status 值 | 说明 |
|------------|------|
| `active` | API 正常响应 |
| `inactive` | API 未响应 |
| `error` | API 返回错误 |
| wechat_status 值 | 说明 |
|------------------|------|
| `online` | 微信已登录 |
| `offline` | 微信未登录 |
**SQL:**
```sql
CREATE TABLE nodes (
node_id VARCHAR(50) PRIMARY KEY,
name VARCHAR(100) NOT NULL,
api_url VARCHAR(255) NOT NULL,
api_key VARCHAR(255) NOT NULL,
enabled BOOLEAN DEFAULT true,
description TEXT DEFAULT '',
group VARCHAR(50) DEFAULT 'default',
status VARCHAR(20) DEFAULT 'inactive',
wechat_status VARCHAR(20) DEFAULT 'online',
is_healthy BOOLEAN DEFAULT false,
health_message VARCHAR(255) DEFAULT '',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
---
### 2. webhook_urls - Webhook URL 表
存储告警 webhook 配置。
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| `id` | INTEGER | **PK**, AUTO | 主键 |
| `name` | VARCHAR(100) | NOT NULL | Webhook 名称 |
| `url` | VARCHAR(500) | NOT NULL | Webhook URL |
| `format` | VARCHAR(20) | DEFAULT 'bark' | 消息格式 |
| `enabled` | BOOLEAN | DEFAULT true | 是否启用 |
| `event_types` | TEXT | DEFAULT '' | 触发事件类型(逗号分隔) |
| `created_at` | TIMESTAMP | DEFAULT now | 创建时间 |
| `updated_at` | TIMESTAMP | DEFAULT now | 更新时间 |
**format 支持的格式:**
- `bark` - Bark 推送格式
- `wecom` - 企业微信
- `dingtalk` - 钉钉
- `feishu` - 飞书
- `telegram` - Telegram
- `serverchan` - Server酱
**event_types 支持的类型:**
- `node_offline` - 节点离线
- `node_error` - 节点错误
- `wechat_offline` - 微信离线
- `all` - 所有事件
---
### 3. logs - 日志表
存储系统运行日志。
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| `id` | INTEGER | **PK**, AUTO | 主键 |
| `timestamp` | TIMESTAMP | DEFAULT now | 日志时间 |
| `level` | VARCHAR(20) | NOT NULL | 日志级别 |
| `source` | VARCHAR(50) | NOT NULL | 日志来源 |
| `message` | TEXT | NOT NULL | 日志消息 |
**level 值:**
- `INFO` - 信息
- `WARNING` - 警告
- `ERROR` - 错误
- `SUCCESS` - 成功
- `DEBUG` - 调试
---
### 4. plugin_configs - 插件配置表
存储插件的配置和启用状态。
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| `id` | INTEGER | **PK**, AUTO | 主键 |
| `plugin_name` | VARCHAR(100) | **UNIQUE**, NOT NULL | 插件名称 |
| `config_json` | TEXT | DEFAULT '{}' | 插件配置(JSON格式) |
| `enabled` | BOOLEAN | DEFAULT false | 是否启用 |
| `created_at` | TIMESTAMP | DEFAULT now | 创建时间 |
| `updated_at` | TIMESTAMP | DEFAULT now | 更新时间 |
**config_json 示例:**
```json
{
"node_id": "wx1",
"receiver": "文件传输助手",
"cron": "0 8 * * *",
"http_url": "https://api.example.com/news",
"message_template": "📰 {title}\n{url}"
}
```
---
## 数据库操作
### DatabaseService 主要方法
#### 节点操作
```python
# 获取所有节点
db_service.get_all_nodes() -> List[Node]
# 获取指定节点
db_service.get_node(node_id: str) -> Optional[Node]
# 添加节点
db_service.add_node(node_id, name, api_url, api_key, description, group)
# 更新节点
db_service.update_node(node_id, **kwargs) -> bool
# 删除节点
db_service.delete_node(node_id) -> bool
# 获取启用的节点
db_service.get_enabled_nodes() -> List[Node]
```
#### Webhook 操作
```python
# 获取所有 Webhook
db_service.get_all_webhooks() -> List[WebhookUrl]
# 获取启用的 Webhook
db_service.get_enabled_webhooks() -> List[WebhookUrl]
# 添加 Webhook
db_service.add_webhook(name, url, format, event_types) -> bool
# 更新 Webhook
db_service.update_webhook(webhook_id, **kwargs) -> bool
# 删除 Webhook
db_service.delete_webhook(webhook_id) -> bool
```
#### 插件配置操作
```python
# 获取插件配置
db_service.get_plugin_config(plugin_name: str) -> Optional[PluginConfig]
# 获取所有插件配置
db_service.get_all_plugin_configs() -> List[PluginConfig]
# 保存插件配置
db_service.save_plugin_config(plugin_name, config, enabled) -> bool
# 更新插件启用状态
db_service.update_plugin_enabled(plugin_name, enabled) -> bool
```
---
## 索引
```sql
-- nodes 表索引
CREATE INDEX idx_nodes_enabled ON nodes(enabled);
CREATE INDEX idx_nodes_group ON nodes(group);
CREATE INDEX idx_nodes_status ON nodes(status);
-- webhook_urls 表索引
CREATE INDEX idx_webhook_enabled ON webhook_urls(enabled);
-- logs 表索引
CREATE INDEX idx_logs_timestamp ON logs(timestamp);
CREATE INDEX idx_logs_level ON logs(level);
```
---
## 迁移注意
如果数据库已存在,新增 `plugin_configs` 表:
```sql
CREATE TABLE IF NOT EXISTS plugin_configs (
id SERIAL PRIMARY KEY,
plugin_name VARCHAR(100) UNIQUE NOT NULL,
config_json TEXT DEFAULT '{}',
enabled BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
+770
View File
@@ -0,0 +1,770 @@
# WXAuto Center 开发指南
## 开发环境搭建
### 环境要求
- Python 3.8+
- Node.js 14+ (可选,用于前端开发)
- Git
### 克隆与安装
```bash
# 克隆项目
git clone <repository-url>
cd wxauto_api/wxauto_center
# 创建虚拟环境(推荐)
python -m venv venv
source venv/bin/activate # Linux/Mac
# 或 venv\Scripts\activate # Windows
# 安装依赖
pip install -r requirements.txt
```
### 配置开发环境
```bash
# 复制环境变量示例文件
cp .env.example .env
# 编辑 .env 文件
vim .env
```
### 启动开发服务器
```bash
# 方式1:使用 run.py(推荐)
python run.py
# 方式2:单进程开发模式
python run.py --reload
# 方式3:使用 uvicorn
uvicorn main:app --host 0.0.0.0 --port 8080 --reload
# 方式4:多进程模式(需要 Redis)
python run.py --workers 4
```
### 访问服务
- 主界面:http://localhost:8080/static/index.html
- API 文档:http://localhost:8080/docs
- ReDoc:http://localhost:8080/redoc
---
## 项目结构详解
### 目录结构
```
wxauto_center/
├── main.py # FastAPI 应用入口
├── run.py # 多进程启动脚本
├── config.py # 配置管理模块
├── api/ # API 路由目录
│ ├── __init__.py
│ ├── nodes.py # 节点管理 API
│ ├── messages.py # 消息发送 API
│ ├── external.py # 外部扩展 API
│ ├── callback.py # 回调接口 API
│ └── plugins.py # 插件管理 API
├── services/ # 业务逻辑目录
│ ├── __init__.py
│ ├── node_manager.py # 节点管理器
│ ├── monitor_service.py # 监控服务
│ ├── log_service.py # 日志服务(支持Redis+文件持久化)
│ └── queue_service.py # 消息队列服务(支持Redis后端)
├── plugins/ # 插件目录
│ ├── __init__.py
│ ├── base.py # 插件基类
│ └── builtin.py # 内置插件
├── models/ # 数据模型目录
├── utils/ # 工具函数目录
├── static/ # 静态文件目录
│ ├── index.html # 主页面
│ ├── css/ # 样式目录
│ └── js/ # JavaScript 目录
├── logs/ # 日志目录
│ └── app.log # 应用日志
├── config.json # 配置文件
└── requirements.txt # 依赖列表
```
---
## 代码架构说明
### 主入口 (main.py)
`main.py` 是 FastAPI 应用的入口文件,负责:
1. 初始化 FastAPI 应用
2. 配置 CORS 中间件
3. 注册路由(nodes, messages, external, plugins)
4. 处理启动/关闭事件
关键代码流程:
```python
# 启动事件
@app.on_event("startup")
async def startup_event():
load_config_from_file("config.json") # 加载配置
register_builtin_plugins() # 注册内置插件
for node_data in config_manager.get_all_nodes():
await node_manager.add_node(...) # 添加节点
await monitor_service.start() # 启动监控服务
# 关闭事件
@app.on_event("shutdown")
async def shutdown_event():
await monitor_service.stop() # 停止监控
save_config_to_file("config.json") # 保存配置
```
### 配置管理 (config.py)
采用 Pydantic Settings 进行配置管理:
```python
# 配置模型
Settings # 主配置类
NodeConfig # 节点配置
PluginConfig # 插件配置
WebhookConfig # Webhook 配置
MonitorConfig # 监控配置
# 配置管理器
ConfigManager # 提供节点配置的增删改查
# 配置加载/保存
load_config_from_file() # 从文件加载
save_config_to_file() # 保存到文件
```
### 节点管理器 (services/node_manager.py)
`NodeManager` 是核心服务类,负责与 WXAuto-HTTP-API 节点通信。
```python
# 节点状态
class NodeStatus:
ACTIVE = "active" # API 可用
INACTIVE = "inactive" # API 不可用
ERROR = "error" # API 错误
# 节点类
class Node:
node_id: str # 节点唯一标识
name: str # 节点显示名称
api_url: str
api_key: str
description: str
group: str
enabled: bool
status: str # NodeStatus
wechat_status: str
is_healthy: bool
health_message: str
# NodeManager 方法
class NodeManager:
async def add_node(...) # 添加节点
async def remove_node(node_id) # 删除节点
async def get_node(node_id) # 获取单个节点
async def get_all_nodes() # 获取所有节点
async def get_enabled_nodes() # 获取已启用节点
async def get_nodes_by_group() # 按分组获取节点
async def update_node(node_id, **kwargs) # 更新节点
async def check_node_status(node_id) # 检查节点状态
async def is_node_healthy(node_id) # 检查节点健康状态
async def send_message(node_id, who, msg, msg_type) # 发送消息
async def send_message_to_group(node_id, group_name, msg, msg_type) # 发送群消息
async def get_friends_list(node_id) # 获取好友列表
async def get_groups_list(node_id) # 获取群列表
async def get_messages(node_id, chat_name, limit) # 获取消息历史
**注意**:已移除 `broadcast_message()` 方法,广播功能不再支持。
### 监控服务 (services/monitor_service.py)
`MonitorService` 负责定时检测节点和微信状态。
```python
class MonitorService:
async def start() # 启动监控
async def stop() # 停止监控
async def _monitor_loop() # 主监控循环
async def _check_all_nodes() # 检查所有节点
async def _check_node(node_id) # 检查单个节点
async def _send_webhook(event, data) # 发送Webhook通知
def get_last_status(node_id) # 获取最后状态
def get_all_status() # 获取所有状态
```
### 日志服务 (services/log_service.py)
`LogService` 提供日志记录和实时推送功能。
```python
class LogService:
def __init__(self, max_logs=500):
self.max_logs = max_logs
self._logs: deque = deque(maxlen=max_logs) # 限制500条
self._subscribers: List[asyncio.Queue] = []
# 日志方法
def info/warning/error/success(message, source)
# SSE 订阅
async def subscribe() -> asyncio.Queue # 订阅日志流
def unsubscribe(queue) # 取消订阅
# 日志查询
def get_recent_logs(count) # 获取最近日志
def get_all_logs() # 获取所有日志
```
---
## 插件开发指南
### 插件架构
系统采用插件化设计,支持扩展:
```
PluginBase (抽象基类)
├── MessageHandlerPlugin
├── DataSourcePlugin
├── ActionTriggerPlugin
└── AIAgentPlugin
```
### 开发自定义插件
#### 1. 创建插件类
```python
# my_plugin.py
from plugins.base import PluginBase, PluginType
class MyCustomPlugin(PluginBase):
plugin_name = "my_custom_plugin"
plugin_version = "1.0.0"
plugin_type = PluginType.CUSTOM
plugin_description = "我的自定义插件"
def initialize(self, config: Dict[str, Any]) -> bool:
self.config = config
# 初始化逻辑
return True
def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
# 插件逻辑
return {"success": True, "result": "done"}
```
#### 2. 注册插件
```python
# 在 builtin.py 或 main.py 中注册
from plugins.base import PluginRegistry
my_plugin = MyCustomPlugin()
my_plugin.initialize({"key": "value"})
PluginRegistry.register(my_plugin)
```
### 插件类型详解
#### DataSourcePlugin
用于从外部数据源获取数据:
```python
class MyDataSourcePlugin(DataSourcePlugin):
plugin_name = "my_data_source"
def fetch_data(self, query: str, params: Dict[str, Any]) -> List[Dict[str, Any]]:
# 获取数据逻辑
return [...]
```
#### AIAgentPlugin
用于 AI 消息处理:
```python
class MyAIAgentPlugin(AIAgentPlugin):
plugin_name = "my_ai_agent"
def process(self, input_text: str, context: Dict[str, Any]) -> str:
# 处理输入,返回 AI 回复
return "AI 回复"
def get_response(self, messages: List[Dict[str, str]]) -> str:
# 获取对话响应
return "AI 回复"
```
---
## API 调用示例
### 使用 Python 调用
```python
import httpx
API_KEY = "your-external-api-key"
BASE_URL = "http://localhost:8080/api/v1"
headers = {
"X-API-Key": API_KEY,
"Content-Type": "application/json"
}
# 添加节点
response = httpx.post(
f"{BASE_URL}/nodes",
json={
"node_id": "wx1",
"name": "微信1",
"api_url": "http://192.168.1.100:5000",
"api_key": "node-api-key"
},
headers=headers
)
print(response.json())
# 发送消息
response = httpx.post(
f"{BASE_URL}/messages/send",
json={
"node_id": "wx1",
"who": "wxid_friend",
"msg": "Hello!"
},
headers=headers
)
print(response.json())
```
### 使用 curl 调用
```bash
# 添加节点
curl -X POST http://localhost:8080/api/v1/nodes \
-H "X-API-Key: your-external-api-key" \
-H "Content-Type: application/json" \
-d '{"node_id": "wx1", "name": "微信1", "api_url": "http://192.168.1.100:5000", "api_key": "key"}'
# 发送消息
curl -X POST http://localhost:8080/api/v1/messages/send \
-H "X-API-Key: your-external-api-key" \
-H "Content-Type: application/json" \
-d '{"node_id": "wx1", "who": "wxid_friend", "msg": "Hello"}'
# 获取节点状态
curl http://localhost:8080/api/v1/nodes/wx1/status \
-H "X-API-Key: your-external-api-key"
# 获取监控状态
curl http://localhost:8080/api/v1/monitor/status \
-H "X-API-Key: your-external-api-key"
# 获取最近日志
curl "http://localhost:8080/api/v1/logs/recent?count=20" \
-H "X-API-Key: your-external-api-key"
# 重置节点微信状态(回调接口)
curl -X POST http://localhost:8080/api/v1/callback/node/reset \
-H "X-API-Key: your-external-api-key" \
-H "Content-Type: application/json" \
-d '{"node_id": "wx1"}'
```
### 使用 JavaScript 调用
```javascript
const API_KEY = 'your-external-api-key';
const BASE_URL = 'http://localhost:8080/api/v1';
async function sendMessage(nodeId, who, msg) {
const response = await fetch(`${BASE_URL}/messages/send`, {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
node_id: nodeId,
who: who,
msg: msg
})
});
return await response.json();
}
// 使用示例
sendMessage('wx1', 'wxid_friend', 'Hello!')
.then(result => console.log(result));
```
---
## 前端开发
### 前端架构
前端采用纯 JavaScript 模块化设计:
```
static/
├── index.html # 主页面
├── css/
│ └── style.css # 样式文件
└── js/
├── api.js # API 调用封装
├── app.js # 主逻辑
└── pages/
└── templates.js # 页面模板
```
### 页面模块
系统前端包含以下页面:
| 页面 | 功能 |
|------|------|
| dashboard | 系统概览 |
| nodes | 节点管理 |
| monitor | 监控状态 |
| send | 消息发送 |
| logs | 日志查看 |
| external | 外部接口 |
| docs | 文档 |
| settings | 设置 |
### API 封装 (api.js)
```javascript
// 基础配置
const API_BASE = '/api/v1';
const API_KEY = 'your-api-key';
// 通用请求函数
async function apiRequest(endpoint, options = {}) {
const url = `${API_BASE}${endpoint}`;
const headers = {
'X-API-Key': API_KEY,
'Content-Type': 'application/json',
...options.headers
};
const response = await fetch(url, {
...options,
headers
});
return response.json();
}
// API 方法封装
const API = {
// 节点管理
getNodes: (group) => apiRequest(`/nodes${group ? `?group=${group}` : ''}`),
addNode: (data) => apiRequest('/nodes', { method: 'POST', body: JSON.stringify(data) }),
deleteNode: (name) => apiRequest(`/nodes/${name}`, { method: 'DELETE' }),
// 消息发送
sendMessage: (data) => apiRequest('/messages/send', { method: 'POST', body: JSON.stringify(data) }),
sendGroupMessage: (data) => apiRequest('/messages/send_group', { method: 'POST', body: JSON.stringify(data) }),
batchSendMessage: (data) => apiRequest('/messages/batch', { method: 'POST', body: JSON.stringify(data) }),
// 监控状态
getMonitorStatus: () => apiRequest('/monitor/status'),
getRecentLogs: (count) => apiRequest(`/logs/recent?count=${count || 50}`)
};
```
### SSE 日志订阅
```javascript
async function subscribeLogs(callback) {
const eventSource = new EventSource('/api/v1/logs/stream');
eventSource.onmessage = (event) => {
const logEntry = JSON.parse(event.data);
callback(logEntry);
};
eventSource.onerror = (error) => {
console.error('SSE Error:', error);
eventSource.close();
};
return eventSource; // 使用完毕后调用 close()
}
// 使用示例
const es = subscribeLogs((log) => {
console.log(`[${log.level}] ${log.message}`);
});
// 关闭时: es.close();
```
---
## 测试
### 运行测试
```bash
# 安装测试依赖
pip install pytest pytest-asyncio httpx
# 运行所有测试
pytest
# 运行指定测试文件
pytest tests/test_nodes.py
# 带详细输出
pytest -v
```
### 编写测试
```python
# tests/test_nodes.py
import pytest
from httpx import AsyncClient
from main import app
@pytest.mark.asyncio
async def test_add_node():
async with AsyncClient(app=app, base_url="http://test") as client:
response = await client.post(
"/api/v1/nodes",
json={
"name": "test_node",
"api_url": "http://localhost:5000",
"api_key": "test_key"
},
headers={"X-API-Key": "test-key"}
)
assert response.status_code == 200
data = response.json()
assert data["success"] is True
```
---
## 调试技巧
### 启用调试模式
```bash
# 方式1:环境变量
export DEBUG=true
python main.py
# 方式2:命令行参数(如果支持)
uvicorn main:app --reload --log-level debug
# 方式3:修改 .env
DEBUG=true
```
### 查看详细日志
系统内置日志服务,可通过 API 查看:
```bash
# 获取最近日志
curl http://localhost:8080/api/v1/logs/recent?count=100 \
-H "X-API-Key: your-api-key"
# 订阅实时日志流
curl -N http://localhost:8080/api/v1/logs/stream \
-H "X-API-Key: your-api-key"
```
### API 测试工具
- FastAPI 内置 docs:http://localhost:8080/docs
- ReDoc:http://localhost:8080/redoc
- Postman / Insomnia
---
## 代码规范
### Python 代码规范
遵循 PEP 8 和项目规则:
- 使用 4 空格缩进
- 类名使用 PascalCase
- 函数/变量使用 camelCase
- 常量使用 UPPER_SNAKE_CASE
- 每个文件包含头部注释
### 注释要求
```python
# ///
# filename.py
# 描述:该文件负责 [核心功能]
# 作者:AI Generated
# 创建日期:YYYY-MM-DD
# ///
def function_name(param1, param2):
"""
函数简要描述
@param {type} param1 - 参数说明
@return {type} 返回值说明
@throws {异常类型} 异常情况说明
"""
pass
```
---
## 部署注意事项
### 生产环境配置
1. 修改 `secret_key` 为强密码
2. 设置 `debug: false`
3. 配置正确的 `cors_origins`
4. 使用 HTTPS
5. 配置防火墙规则
### 使用 Nginx 反向代理
```nginx
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /api {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
}
```
### 使用 systemd 服务
```ini
# /etc/systemd/system/wxauto-center.service
[Unit]
Description=WXAuto Center Service
After=network.target
[Service]
Type=simple
User=your-user
WorkingDirectory=/path/to/wxauto_center
ExecStart=/path/to/venv/bin/python main.py
Restart=always
[Install]
WantedBy=multi-user.target
```
```bash
sudo systemctl enable wxauto-center
sudo systemctl start wxauto-center
```
---
## 关键实现细节
### 1. 健康检测机制 (is_node_healthy)
每次发送消息前,系统会调用此方法检测节点健康状态:
```python
async def is_node_healthy(self, name: str) -> tuple[bool, str]:
# 1. 检查 API 状态
api_status = await self.check_node_status(name)
if api_status != NodeStatus.ACTIVE:
return False, f"API status: {api_status}"
# 2. 调用 /api/wechat/initialize 检测微信
init_result = await self.call_node_api(name, "/api/wechat/initialize", method="POST")
# 3. 解析返回状态
if not init_result.get("success"):
return False, f"WeChat check failed: {init_result.get('error')}"
# 4. 检查 code 和 status
wx_code = init_result.get("code") or init_result.get("data", {}).get("code")
wx_status = init_result.get("data", {}).get("data", {}).get("status")
if wx_code != 0:
return False, "WeChat error: ..."
if wx_status not in ["connected", "online"]:
return False, f"WeChat status: {wx_status}"
return True, "OK"
```
### 2. 消息发送流程
```python
async def send_message(self, name: str, who: str, msg: str, msg_type: str = "text"):
# 1. 先初始化微信
await self.call_node_api(name, "/api/wechat/initialize", method="POST")
# 2. 发送消息
return await self.call_node_api(
name,
"/api/message/send",
method="POST",
data={"receiver": who, "message": msg}
)
```
### 3. 监控告警流程
```python
async def _check_node(self, node_id: str):
# 检测 API 状态变化
api_status = await node_manager.check_node_status(node_id)
if old_api_status != api_status:
event = "node_online" if api_status == "active" else "node_offline"
await self._send_webhook(event, {...})
# 检测微信状态变化(通过发送消息检测)
wechat_status = node.wechat_status # 从节点对象获取
if old_wechat_status != wechat_status:
event = "wechat_online" if wechat_status == "online" else "wechat_offline"
await self._send_webhook(event, {...})
```
**注意**:微信状态现在通过消息发送结果自动更新,不需要主动检测。
+662
View File
@@ -0,0 +1,662 @@
# WXAuto Center 业务流程文档
## 概述
本文档详细描述 WXAuto Center 的核心业务流程,包括消息发送流程、回调重置流程、监控告警流程、健康检测流程和日志发布订阅流程。
---
## 1. 节点标识系统
### 1.1 node_id 与 name 的区别
每个节点有两个标识:
| 字段 | 说明 | 示例 | 用途 |
|------|------|------|------|
| node_id | 节点唯一标识 | "wx1", "node_001" | API 调用、系统内部引用 |
| name | 节点显示名称 | "微信1", "测试节点" | 界面展示、用户友好提示 |
### 1.2 节点数据模型
```json
{
"node_id": "wx1",
"name": "微信1",
"api_url": "http://192.168.20.18:5000",
"api_key": "key",
"enabled": true,
"description": "",
"group": "wechat",
"status": "active",
"wechat_status": "online",
"is_healthy": true
}
```
---
## 2. 消息发送流程
### 2.1 流程图
```
外部请求
│
▼
┌─────────────────────────────────────────────────────────────┐
│ POST /api/v1/messages/send │
│ 或 │
│ POST /api/v1/external/send │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ check_node_health(node_id) │
│ 调用 /api/wechat/initialize 检测微信状态 │
└─────────────────────────────────────────────────────────────┘
│
├──► 微信状态异常?
│ │
│ ▼ (是)
│ 返回 HTTP 503
│ "Node 'wx1' is not healthy..."
│ │
│ ▼
│ 流程结束
│
▼ (否)
┌─────────────────────────────────────────────────────────────┐
│ node_manager.send_message(node_id, who, msg, msg_type) │
└─────────────────────────────────────────────────────────────┘
│
├──► POST /api/wechat/initialize (初始化微信)
│
└──► POST /api/message/send (发送消息)
│
▼
发送成功?
│
├──► 是 → wechat_status = "online"
│ │
│ ▼
│ 返回成功响应
│
└──► 否 → wechat_status = "offline"
│
▼
返回错误响应
```
### 2.2 详细步骤说明
| 步骤 | 操作 | 说明 |
|------|------|------|
| 1 | 接收发送消息请求 | 解析 node_id, who, msg, msg_type |
| 2 | 健康检测 | 调用 is_node_healthy() 检测节点 |
| 3 | 初始化微信 | 调用 /api/wechat/initialize |
| 4 | 发送消息 | 调用 /api/message/send |
| 5 | 更新状态 | 根据发送结果更新 wechat_status |
| 6 | 返回响应 | 返回发送结果给客户端 |
### 2.3 代码逻辑
```python
async def send_message(node_id: str, who: str, msg: str, msg_type: str = "text"):
# 1. 检查节点是否健康
is_healthy, health_msg = await node_manager.is_node_healthy(node_id)
if not is_healthy:
raise HTTPException(
status_code=503,
detail=f"Node '{node_id}' is not healthy: {health_msg}"
)
# 2. 初始化微信
await node_manager.call_node_api(node_id, "/api/wechat/initialize", method="POST")
# 3. 发送消息
result = await node_manager.call_node_api(
node_id,
"/api/message/send",
method="POST",
data={"receiver": who, "message": msg}
)
# 4. 更新状态
if result.get("code") == 0:
node_manager.update_node_status(node_id, wechat_status="online")
else:
node_manager.update_node_status(node_id, wechat_status="offline")
return result
```
---
## 3. 回调重置流程
### 3.1 流程图
```
外部节点回调
│
▼
┌─────────────────────────────────────────────────────────────┐
│ POST /api/v1/callback/node/reset │
│ 请求体: {"node_id": "wx1"} │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 调用 /api/wechat/initialize 初始化微信 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 调用 /api/message/send 发送检测消息到"文件传输助手" │
│ receiver: "filehelper" │
│ message: "WXAuto Center 检测消息" │
└─────────────────────────────────────────────────────────────┘
│
▼
检测结果
│
├──► 发送成功
│ │
│ ▼
│ wechat_status = "online"
│ │
│ ▼
│ 返回 {"success": true, "wechat_status": "online"}
│
└──► 发送失败
│
▼
wechat_status = "offline"
│
▼
返回 {"success": false, "wechat_status": "offline"}
│
▼
MonitorService 检测到状态变化
│
▼
触发 Webhook 告警 (wechat_offline)
```
### 3.2 详细步骤说明
| 步骤 | 操作 | 说明 |
|------|------|------|
| 1 | 接收重置请求 | 解析 node_id |
| 2 | 初始化微信 | 调用 /api/wechat/initialize |
| 3 | 发送检测消息 | 发送消息到文件传输助手(filehelper) |
| 4 | 判断结果 | 根据发送是否成功设置状态 |
| 5 | 触发告警 | 状态变化时触发 Webhook |
### 3.3 回调接口说明
**POST /api/v1/callback/node/reset**
用于重置节点的微信状态。当微信掉线后,可以通过此接口重新检测微信状态。
**请求体**:
```json
{
"node_id": "wx1"
}
```
**响应示例 - 成功**:
```json
{
"success": true,
"message": "微信状态已重置",
"data": {
"node_id": "wx1",
"wechat_status": "online",
"check_result": "success"
}
}
```
**响应示例 - 失败**:
```json
{
"success": false,
"message": "微信状态检测失败",
"data": {
"node_id": "wx1",
"wechat_status": "offline",
"check_result": "failed",
"error": "Unknown error"
}
}
```
---
## 4. 监控告警流程
### 4.1 流程图
```
MonitorService 启动
│
▼
┌─────────────────────────────────────────────────────────────┐
│ _monitor_loop() 定时循环 │
│ 间隔: check_interval (默认 60 秒) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ _check_all_nodes() │
│ 遍历所有节点 │
└─────────────────────────────────────────────────────────────┘
│
▼
对每个节点执行 _check_node(node_id):
│
├──► api_check_enabled?
│ │
│ ▼ (是)
│ check_node_status(node_id)
│ │
│ ▼
│ API 状态变化?
│ │
│ ├──► 是 → 触发 Webhook (node_online/node_offline)
│ │
│ └──► 否 → 无操作
│
└──► wechat_check_enabled?
│
▼ (是)
initialize_wechat(node_id)
│
▼
get_wechat_status(node_id)
│
▼
微信状态变化?
│
├──► 是 → 触发 Webhook (wechat_online/wechat_offline)
│
└──► 否 → 无操作
```
### 4.2 支持的事件类型
| 事件类型 | 触发条件 | 消息内容 |
|----------|----------|----------|
| api_error | API 调用失败 | "API Error: {error}" |
| wechat_offline | 微信状态变为 offline | "微信掉线" |
| wechat_online | 微信状态变为 online/connected | "微信上线" |
| node_offline | 节点 API 不可用 | "节点离线" |
| node_online | 节点 API 恢复可用 | "节点在线" |
### 4.3 Webhook 消息格式
**企业微信格式**:
```json
{
"msgtype": "text",
"text": {
"content": "【WXAuto Center 告警】\n事件类型: 微信掉线\n节点: wx1 (微信1)\n状态: offline\n时间: 2026-04-05 10:00:00"
}
}
```
**Bark 格式**:
```json
{
"title": "WXAuto告警 - 微信掉线",
"body": "wx1\n状态: offline\n时间: 2026-04-05 10:00:00",
"icon": "https://..."
}
```
---
## 5. 健康检测流程
### 5.1 流程图
```
is_node_healthy(node_id) 调用
│
▼
┌─────────────────────────────────────────────────────────────┐
│ check_node_status(node_id) │
│ 调用 GET /health 检测 API 可用性 │
└─────────────────────────────────────────────────────────────┘
│
▼
API 状态检查
│
├──► API 不可用 → 返回 (False, "API status: {status}")
│
▼ (API 可用)
┌─────────────────────────────────────────────────────────────┐
│ /api/wechat/initialize │
│ 调用 POST /api/wechat/initialize 初始化微信 │
└─────────────────────────────────────────────────────────────┘
│
▼
解析返回状态 (code, message, status)
│
├──► code != 0?
│ │
│ ├──► "无效"/"1400"/"拒绝访问"
│ │ │
│ │ ▼
│ │ 返回 (False, "WeChat window invalid")
│ │
│ └──► 其他错误消息
│ │
│ ▼
│ 返回 (False, "WeChat error: {message}")
│
├──► status not in ["connected", "online"]?
│ │
│ └──► 是 → 返回 (False, "WeChat status: {status}")
│
└──► 其他情况
│
▼
返回 (True, "OK")
```
### 5.2 健康检测判断逻辑
```python
async def is_node_healthy(node_id: str) -> tuple[bool, str]:
# 1. 检查 API 状态
api_status = await self.check_node_status(node_id)
if api_status != NodeStatus.ACTIVE:
return False, f"API status: {api_status}"
# 2. 调用 /api/wechat/initialize 检测微信
init_result = await self.call_node_api(node_id, "/api/wechat/initialize", method="POST")
# 3. 解析返回状态
if not init_result.get("success"):
return False, f"WeChat check failed: {init_result.get('error')}"
wx_code = init_result.get("code") or init_result.get("data", {}).get("code")
wx_status = init_result.get("data", {}).get("data", {}).get("status")
if wx_code != 0:
return False, "WeChat error: ..."
if wx_status not in ["connected", "online"]:
return False, f"WeChat status: {wx_status}"
return True, "OK"
```
---
## 6. 微信状态机
### 6.1 状态定义
| 状态 | 说明 | 可转换状态 |
|------|------|------------|
| online | 微信正常在线(默认/成功状态) | offline |
| offline | 微信掉线或不可用 | online |
### 6.2 状态转换图
```
┌──────────────┐
│ online │
│ (默认/成功) │
└──────┬───────┘
│
发送消息失败
或微信掉线检测
│
▼
┌──────────────┐
│ offline │
└──────┬───────┘
│
回调重置成功
(文件传输助手检测)
│
▼
┌──────────────┐
│ online │
└──────────────┘
```
### 6.3 状态转换场景
| 场景 | 原状态 | 新状态 | 触发条件 |
|------|--------|--------|----------|
| 消息发送成功 | online | online | code == 0 |
| 消息发送失败 | online | offline | code != 0 |
| 微信掉线 | online | offline | 监控检测到异常 |
| 回调重置成功 | offline | online | 检测消息发送成功 |
| 回调重置失败 | offline | offline | 检测消息发送失败 |
---
## 7. 日志发布订阅流程
### 7.1 流程图
```
业务操作调用
│
├──► log_service.info(message, source)
├──► log_service.warning(message, source)
├──► log_service.error(message, source)
└──► log_service.success(message, source)
│
▼
┌─────────────────────────────────────────────────────────────┐
│ LogEntry 创建 │
│ {timestamp, level, source, message} │
└─────────────────────────────────────────────────────────────┘
│
├──► 存入 deque (本地缓存,最多 500 条)
│
└──► 推送到 SSE Queue
│
▼
所有订阅者收到消息
│
▼
unsubscribe() 取消订阅
```
### 7.2 SSE 订阅示例
```javascript
// 前端订阅日志流
const eventSource = new EventSource('/api/v1/logs/stream');
eventSource.onmessage = (event) => {
const logEntry = JSON.parse(event.data);
console.log(`[${logEntry.level}] ${logEntry.message}`);
};
eventSource.onerror = (error) => {
console.error('SSE Error:', error);
eventSource.close();
};
```
### 7.3 日志级别
| 级别 | 说明 | 使用场景 |
|------|------|----------|
| INFO | 信息 | 一般操作日志 |
| WARNING | 警告 | 异常但可恢复 |
| ERROR | 错误 | 操作失败 |
| SUCCESS | 成功 | 操作成功确认 |
---
## 8. 批量操作流程
### 8.1 广播消息流程
```
广播请求
│
▼
┌─────────────────────────────────────────────────────────────┐
│ POST /api/v1/messages/broadcast │
│ 请求体: {node_ids, who, msg, msg_type} │
└─────────────────────────────────────────────────────────────┘
│
▼
node_ids 为空?
│
├──► 是 → 获取所有已启用节点
│
▼ (否)
使用指定的 node_ids
│
▼
对每个节点并行发送消息
│
├──► 节点1 → send_message() → 结果1
├──► 节点2 → send_message() → 结果2
└──► 节点N → send_message() → 结果N
│
▼
汇总结果
│
▼
返回批量结果
```
### 8.2 批量发送流程
```
批量请求
│
▼
┌─────────────────────────────────────────────────────────────┐
│ POST /api/v1/messages/batch │
│ 请求体: {messages: [{node_id, who, msg, msg_type}, ...]} │
└─────────────────────────────────────────────────────────────┘
│
▼
验证消息列表
│
▼
对每条消息并行发送
│
├──► 消息1 → send_message() → 结果1
├──► 消息2 → send_message() → 结果2
└──► 消息N → send_message() → 结果N
│
▼
汇总结果
│
▼
返回批量结果
```
---
## 9. 插件执行流程
### 9.1 外部触发流程
```
外部请求
│
▼
┌─────────────────────────────────────────────────────────────┐
│ POST /api/v1/external/trigger │
│ 请求体: {source, event, data, auto_send, target, node_id} │
└─────────────────────────────────────────────────────────────┘
│
▼
获取插件
│
▼
执行插件
│
├──► plugin.execute(event, data)
│
▼
auto_send = true?
│
├──► 是 → 发送消息到 target
│ │
│ ▼
│ 返回 {plugin_result, send_result}
│
└──► 否 → 返回 {plugin_result}
```
---
## 10. 完整状态流转图
```
┌─────────────────────────────────────┐
│ 系统启动 │
│ 节点创建 (wechat_status=online) │
└─────────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 正常运行 │
│ wechat_status=online │
└─────────────────┬───────────────────┘
│
┌─────────────────┴─────────────────┐
│ │
▼ ▼
┌───────────────────────┐ ┌───────────────────────┐
│ 消息发送成功 │ │ 消息发送失败 │
│ wechat_status= │ │ wechat_status= │
│ online │ │ offline │
└───────────────────────┘ └───────────┬───────────┘
│
▼
┌───────────────────────┐
│ 调用回调重置接口 │
│ POST /callback/node/ │
│ reset │
└───────────┬───────────┘
│
┌───────────────┴───────────────┐
│ │
▼ ▼
┌───────────────────────┐ ┌───────────────────────┐
│ 重置成功 │ │ 重置失败 │
│ 发送检测消息成功 │ │ 发送检测消息失败 │
│ wechat_status= │ │ wechat_status= │
│ online │ │ offline │
└───────────────────────┘ └───────────────────────┘
│
▼
┌───────────────────────┐
│ 触发 Webhook 告警 │
│ wechat_offline │
└───────────────────────┘
```
---
## 更新日志
| 日期 | 更新内容 |
|------|----------|
| 2026-04-05 | 创建 FLOWS.md 业务流程文档 |
| 2026-04-05 | 添加消息发送流程图 |
| 2026-04-05 | 添加回调重置流程图 |
| 2026-04-05 | 添加监控告警流程图 |
| 2026-04-05 | 添加健康检测流程图 |
| 2026-04-05 | 添加微信状态机说明 |
| 2026-04-05 | 添加日志发布订阅流程图 |
+615
View File
@@ -0,0 +1,615 @@
# WXAuto Center 模块索引文档
## 1. 模块概览
WXAuto Center 采用分层架构,主要分为以下模块:
| 层级 | 模块 | 路径 | 职责 |
|------|------|------|------|
| 接入层 | API Routes | `api/` | 处理 HTTP 请求,提供 RESTful 接口 |
| 业务逻辑层 | Services | `services/` | 核心业务逻辑处理 |
| 公共工具层 | Utils | `utils/` | 公共函数和依赖注入 |
| 插件系统 | Plugins | `plugins/` | 扩展功能插件 |
| 配置层 | Config | `config.py` | 系统配置管理 |
| 入口 | Main | `main.py` | FastAPI 应用入口 |
---
## 2. 模块详细说明
### 2.1 接入层 (API Layer)
#### api/nodes.py - 节点管理 API
**文件路径**:[nodes.py](../../wxauto_center/api/nodes.py)
**职责**:
- 节点的增删改查 (CRUD)
- 节点状态检测
- 微信初始化
- 节点启用/禁用
- 获取好友列表、群列表、聊天消息
**主要端点**:
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /nodes | 获取所有节点 |
| GET | /nodes/{node_id} | 获取指定节点 |
| POST | /nodes | 添加节点 |
| PUT | /nodes/{node_id} | 更新节点 |
| DELETE | /nodes/{node_id} | 删除节点 |
| POST | /nodes/{node_id}/enable | 启用节点 |
| POST | /nodes/{node_id}/disable | 禁用节点 |
| GET | /nodes/{node_id}/status | 检查节点状态 |
| GET | /nodes/{node_id}/wechat/status | 获取微信状态 |
| POST | /nodes/{node_id}/wechat/initialize | 初始化微信 |
**依赖**:`services.node_manager`, `utils.require_api_key`
**节点标识说明**:所有接口使用 `node_id` 作为节点唯一标识。
---
#### api/messages.py - 消息管理 API
**文件路径**:[messages.py](../../wxauto_center/api/messages.py)
**职责**:
- 发送消息
- 发送群消息
- 批量发送消息
- 发送模板消息
- 获取消息历史
**主要端点**:
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /messages/send | 发送消息 |
| POST | /messages/send_group | 发送群消息 |
| POST | /messages/batch | 批量发送 |
| POST | /messages/template/{node_id}/{who} | 发送模板消息 |
| GET | /messages/history/{node_id}/{chat_name} | 获取消息历史 |
**依赖**:`services.node_manager`, `utils.require_api_key`, `utils.check_node_health`
**说明**:已移除广播功能。
---
#### api/external.py - 外部扩展 API
**文件路径**:[external.py](../../wxauto_center/api/external.py)
**职责**:
- 供外部系统调用的接口
- 外部消息发送
- 数据处理触发
- 插件执行
- AI 消息处理
- Webhook 接收
**主要端点**:
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /external/send | 外部接口-发送消息 |
| POST | /external/trigger | 外部接口-触发数据处理 |
| POST | /external/plugin/execute | 外部接口-执行插件 |
| GET | /external/plugins | 外部接口-获取插件列表 |
| GET | /external/nodes | 外部接口-获取可用节点 |
| POST | /external/ai/process | 外部接口-AI处理消息 |
| POST | /external/webhook/{event} | 外部接口-Webhook接收 |
**认证方式**:`X-ExternalKey` Header
**依赖**:`services.node_manager`, `plugins.base.PluginRegistry`, `utils.require_external_key`
---
#### api/plugins.py - 插件管理 API
**文件路径**:[plugins.py](../../wxauto_center/api/plugins.py)
**职责**:
- 插件注册和管理
- 插件启用/禁用
- 插件配置更新
- 按类型获取插件
**主要端点**:
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /plugins | 获取所有插件 |
| GET | /plugins/{plugin_name} | 获取插件详情 |
| POST | /plugins/{plugin_name}/enable | 启用插件 |
| POST | /plugins/{plugin_name}/disable | 禁用插件 |
| PUT | /plugins/{plugin_name}/config | 更新插件配置 |
| POST | /plugins/{plugin_name}/execute | 执行插件 |
| GET | /plugins/type/{plugin_type} | 按类型获取插件 |
**依赖**:`plugins.base.PluginRegistry`, `utils.require_api_key`
---
#### api/callback.py - 回调接口 API
**文件路径**:[callback.py](../../wxauto_center/api/callback.py)
**职责**:
- 外部节点回调
- 节点微信状态重置
- 节点微信状态检测
- 节点状态查询
**主要端点**:
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /callback/node/reset | 重置节点微信状态 |
| POST | /callback/node/check | 检测节点微信状态 |
| GET | /callback/node/{node_id}/status | 获取节点回调状态 |
**业务流程**:
```
1. 发送消息 → 失败 → wechat_status = offline
2. 回调重置接口 → 发送检测消息 → 成功 → wechat_status = online
3. 监控服务检测状态变化 → 触发Webhook告警
```
**依赖**:`services.node_manager`, `services.log_service`, `utils.require_api_key`
---
### 2.2 业务逻辑层 (Service Layer)
#### services/node_manager.py - 节点管理服务
**文件路径**:[node_manager.py](../../wxauto_center/services/node_manager.py)
**职责**:
- 节点注册和注销
- 节点通信管理
- API 调用封装
- 消息发送
- 节点状态检测
**核心类**:
| 类名 | 说明 |
|------|------|
| NodeStatus | 节点状态枚举 (ACTIVE, INACTIVE, ERROR) |
| Node | 节点数据模型(包含 node_id 和 name) |
| NodeManager | 节点管理服务类 |
**主要方法**:
| 方法 | 说明 |
|------|------|
| add_node() | 添加节点 |
| remove_node(node_id) | 删除节点 |
| get_node(node_id) | 获取节点 |
| get_all_nodes() | 获取所有节点 |
| get_enabled_nodes() | 获取已启用节点 |
| check_node_status(node_id) | 检测节点状态 |
| is_node_healthy(node_id) | 判断节点是否健康 |
| call_node_api() | 调用节点 API |
| send_message(node_id, who, msg, msg_type) | 发送消息 |
| send_message_to_group(node_id, group_name, msg, msg_type) | 发送群消息 |
**内部方法**:
| 方法 | 说明 |
|------|------|
| _send_message_internal() | 发送消息的内部方法 (复用逻辑) |
**依赖**:`services.log_service`
---
#### services/monitor_service.py - 监控服务
**文件路径**:[monitor_service.py](../../wxauto_center/services/monitor_service.py)
**职责**:
- 定时检测节点状态
- 检测 API 状态变化
- 检测微信状态变化
- 触发 Webhook 告警
**主要方法**:
| 方法 | 说明 |
|------|------|
| start() | 启动监控服务 |
| stop() | 停止监控服务 |
| get_last_status() | 获取节点最后状态 |
| get_all_status() | 获取所有节点状态 |
**内部方法**:
| 方法 | 说明 |
|------|------|
| _monitor_loop() | 监控主循环 |
| _check_all_nodes() | 检测所有节点 |
| _check_node() | 检测单个节点 |
| _send_webhook() | 发送 Webhook 通知 |
**依赖**:`config.get_settings`, `services.node_manager`, `services.log_service`
---
#### services/log_service.py - 日志服务
**文件路径**:[log_service.py](../../wxauto_center/services/log_service.py)
**职责**:
- 日志记录
- 日志缓存 (deque,最多 500 条)
- SSE 实时推送
- 发布订阅模式
- Redis 缓存支持
- 文件持久化 (logs/app.log)
**日志级别**:INFO, WARNING, ERROR, SUCCESS
**主要方法**:
| 方法 | 说明 |
|------|------|
| info() | 记录 INFO 日志 |
| warning() | 记录 WARNING 日志 |
| error() | 记录 ERROR 日志 |
| success() | 记录 SUCCESS 日志 |
| subscribe() | 订阅日志流 |
| unsubscribe() | 取消订阅 |
| get_recent_logs() | 获取最近日志 |
| get_all_logs() | 获取所有日志 |
---
#### services/queue_service.py - 消息队列服务
**文件路径**:[queue_service.py](../../wxauto_center/services/queue_service.py)
**职责**:
- 消息队列管理
- Redis 后端支持(可选)
- 本地队列回退
- 异步任务处理
**队列名称**:
| 队列名 | 说明 |
|--------|------|
| MESSAGE_SEND | 消息发送队列 |
| MESSAGE_BROADCAST | 消息广播队列(已废弃) |
**主要方法**:
| 方法 | 说明 |
|------|------|
| enqueue() | 入队操作 |
| dequeue() | 出队操作(异步) |
| get_queue_length() | 获取队列长度 |
| start_worker() | 启动工作进程 |
| stop_worker() | 停止工作进程 |
**依赖**:Redis (可选),若 Redis 不可用则使用本地 asyncio.Queue
---
### 2.3 公共工具层 (Utils Layer)
#### utils/common.py - 公共函数
**文件路径**:[common.py](../../wxauto_center/utils/common.py)
**职责**:
- API Key 验证依赖 (require_api_key)
- External Key 验证依赖 (require_external_key)
**主要函数**:
| 函数名 | 说明 |
|--------|------|
| require_api_key | API Key 验证依赖,用于 X-API-Key Header |
| require_external_key | External Key 验证依赖,用于 X-ExternalKey Header |
**使用示例**:
```python
from utils import require_api_key
@router.post("/endpoint")
async def endpoint(_=Depends(require_api_key)):
# 处理请求
pass
```
---
#### utils/helpers.py - 业务辅助函数
**文件路径**:[helpers.py](../../wxauto_center/utils/helpers.py)
**职责**:
- 节点健康检查
- 响应构建
- 结果解析
**主要函数**:
| 函数名 | 说明 |
|--------|------|
| check_node_health() | 检查节点健康状态,不健康则抛 503 异常 |
| build_success_response() | 构建成功响应 |
| build_error_response() | 构建错误响应 |
| parse_node_result() | 解析节点 API 调用结果 |
---
### 2.4 插件系统 (Plugin Layer)
#### plugins/base.py - 插件基类
**文件路径**:[base.py](../../wxauto_center/plugins/base.py)
**职责**:
- 定义插件接口
- 插件注册表
**核心类**:
| 类名 | 说明 |
|------|------|
| PluginType | 插件类型枚举 |
| PluginBase | 插件基类 |
| MessageHandlerPlugin | 消息处理插件基类 |
| DataSourcePlugin | 数据源插件基类 |
| ActionTriggerPlugin | 动作触发插件基类 |
| AIAgentPlugin | AI 智能体插件基类 |
| PluginRegistry | 插件注册表 |
**PluginType 枚举值**:
- MESSAGE_HANDLER = "message_handler"
- DATA_SOURCE = "data_source"
- ACTION_TRIGGER = "action_trigger"
- AI_AGENT = "ai_agent"
- CUSTOM = "custom"
---
#### plugins/builtin.py - 内置插件
**文件路径**:[builtin.py](../../wxauto_center/plugins/builtin.py)
**内置插件**:
| 插件名 | 类名 | 说明 |
|--------|------|------|
| http_data_source | HTTPDataSourcePlugin | HTTP 数据源插件,从外部 API 获取数据 |
| database_query | DatabaseQueryPlugin | 数据库查询插件 (预留) |
| webhook_trigger | WebhookTriggerPlugin | Webhook 触发器 |
| simple_ai_agent | SimpleAIAgentPlugin | 简单 AI 智能体 |
**注册函数**:`register_builtin_plugins()`
---
### 2.5 配置层 (Config Layer)
#### config.py - 配置管理
**文件路径**:[config.py](../../wxauto_center/config.py)
**职责**:
- 系统配置管理
- 配置文件读写
- 多环境支持
**核心配置类**:
| 类名 | 说明 |
|------|------|
| NodeConfig | 节点配置 |
| PluginConfig | 插件配置 |
| WebhookConfig | Webhook 配置 |
| MonitorConfig | 监控配置 |
| Settings | 应用设置 (继承 BaseSettings) |
| ConfigManager | 配置管理器 |
**主要函数**:
| 函数名 | 说明 |
|--------|------|
| get_settings() | 获取全局设置单例 |
| update_settings() | 更新设置 |
| load_config_from_file() | 从文件加载配置 |
| save_config_to_file() | 保存配置到文件 |
**ConfigManager 方法**:
| 方法 | 说明 |
|------|------|
| get_node() | 获取节点配置 |
| get_all_nodes() | 获取所有节点配置 |
| get_enabled_nodes() | 获取已启用节点配置 |
| add_node() | 添加节点配置 |
| update_node() | 更新节点配置 |
| remove_node() | 删除节点配置 |
| save_config() | 保存配置 |
| load_config() | 加载配置 |
---
### 2.6 入口 (Main)
#### main.py - 应用入口
**文件路径**:[main.py](../../wxauto_center/main.py)
**职责**:
- FastAPI 应用初始化
- 中间件配置
- 路由注册
- 启动/关闭事件处理
- 配置管理 API
- 监控状态 API
- 日志流 API
---
## 3. 模块依赖关系
```
┌─────────────┐
│ main.py │
└──────┬──────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ config │ │ api/* │ │ services│
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
│ ▼ ▼
│ ┌───────────┐ ┌─────────┐
│ │ utils/* │ │plugins/*│
│ └───────────┘ └─────────┘
│ │ │
└─────────────────┼─────────────────┘
│
▼
┌─────────────┐
│ external │
│ (WXAuto-HTTP │
│ -API) │
└─────────────┘
```
**依赖详解**:
| 模块 | 被依赖 | 依赖 |
|------|--------|------|
| main.py | - | config, api, services, plugins |
| config.py | api, services, main | pydantic, pydantic_settings |
| api/* | main | services, plugins, utils, config |
| services/* | api | config, log_service |
| utils/* | api | config |
| plugins/* | api, main | httpx |
| log_service | services | - |
---
## 4. 代码导览
### 4.1 新增代码路径
重构后新增的公共模块:
| 文件 | 说明 |
|------|------|
| [utils/__init__.py](../../wxauto_center/utils/__init__.py) | 工具模块导出 |
| [utils/common.py](../../wxauto_center/utils/common.py) | API Key 验证依赖 |
| [utils/helpers.py](../../wxauto_center/utils/helpers.py) | 业务辅助函数 |
### 4.2 重构变更
#### 删除的重复代码
以下文件中删除了重复定义的 `require_api_key` 函数:
- `api/nodes.py` - 现在从 `utils` 导入
- `api/messages.py` - 现在从 `utils` 导入
- `api/external.py` - 现在从 `utils` 导入
- `api/plugins.py` - 现在从 `utils` 导入
- `api/callback.py` - 现在从 `utils` 导入
#### 重构的方法
| 文件 | 原方法 | 新方法 |
|------|--------|--------|
| services/node_manager.py | send_message() 和 send_message_to_group() 重复代码 | 新增 _send_message_internal() 内部方法 |
| api/callback.py | reset_node_wechat_status() 和 check_node_wechat_status() 重复逻辑 | 新增 _check_wechat_and_update_status() 公共函数 |
### 4.3 代码审计指南
#### 审计要点
1. **API Key 验证**
- 所有 API 端点必须使用 `Depends(require_api_key)` 或 `Depends(require_external_key)`
- 检查 `X-API-Key` 和 `X-ExternalKey` 是否正确使用
2. **节点健康检查**
- 发送消息前必须调用 `check_node_health()`
- 使用 `utils.check_node_health` 而非直接调用 `node_manager.is_node_healthy`
3. **配置保存**
- 修改节点配置后必须调用 `save_nodes_config()` 保存
- 修改全局配置后必须调用 `save_config_to_file()` 保存
4. **错误处理**
- 使用 `build_success_response()` 和 `build_error_response()` 构建响应
- 节点不存在时抛出 `HTTPException(status_code=404)`
5. **异步处理**
- 所有 `node_manager` 方法都是异步的,使用 `await`
- API 端点需要 `async def`
---
## 5. 模块索引
### 5.1 文件快速查找
| 功能 | 文件路径 |
|------|----------|
| API Key 验证 | [utils/common.py](../../wxauto_center/utils/common.py) |
| 节点健康检查 | [utils/helpers.py](../../wxauto_center/utils/helpers.py) |
| 节点管理 | [services/node_manager.py](../../wxauto_center/services/node_manager.py) |
| 状态监控 | [services/monitor_service.py](../../wxauto_center/services/monitor_service.py) |
| 日志服务 | [services/log_service.py](../../wxauto_center/services/log_service.py) |
| 节点 API | [api/nodes.py](../../wxauto_center/api/nodes.py) |
| 消息 API | [api/messages.py](../../wxauto_center/api/messages.py) |
| 外部 API | [api/external.py](../../wxauto_center/api/external.py) |
| 插件 API | [api/plugins.py](../../wxauto_center/api/plugins.py) |
| 回调 API | [api/callback.py](../../wxauto_center/api/callback.py) |
| 插件基类 | [plugins/base.py](../../wxauto_center/plugins/base.py) |
| 内置插件 | [plugins/builtin.py](../../wxauto_center/plugins/builtin.py) |
| 配置管理 | [config.py](../../wxauto_center/config.py) |
| 应用入口 | [main.py](../../wxauto_center/main.py) |
### 5.2 类和函数查找
| 类/函数 | 文件 | 行号 |
|---------|------|------|
| NodeStatus | [node_manager.py](../../wxauto_center/services/node_manager.py#L15) | L15 |
| Node | [node_manager.py](../../wxauto_center/services/node_manager.py#L21) | L21 |
| NodeManager | [node_manager.py](../../wxauto_center/services/node_manager.py#L46) | L46 |
| MonitorService | [monitor_service.py](../../wxauto_center/services/monitor_service.py#L18) | L18 |
| LogService | [log_service.py](../../wxauto_center/services/log_service.py#L14) | L14 |
| PluginBase | [base.py](../../wxauto_center/plugins/base.py#L21) | L21 |
| PluginRegistry | [base.py](../../wxauto_center/plugins/base.py#L92) | L92 |
| require_api_key | [common.py](../../wxauto_center/utils/common.py#L10) | L10 |
| require_external_key | [common.py](../../wxauto_center/utils/common.py#L30) | L30 |
| check_node_health | [helpers.py](../../wxauto_center/utils/helpers.py#L20) | L20 |
| ConfigManager | [config.py](../../wxauto_center/config.py#L148) | L148 |
---
## 6. 更新日志
| 日期 | 更新内容 |
|------|----------|
| 2026-04-05 | 更新 API 路径,将 node_name 替换为 node_id |
| 2026-04-05 | 重构代码,新增 utils 模块,抽取公共函数 |
| 2026-04-05 | 新增 MODULES.md 模块索引文档 |
| 2026-04-05 | 更新 API.md,添加回调接口文档 |
| 2026-04-05 | 更新 ARCHITECTURE.md,添加回调流程图和微信状态机 |
| 2026-04-05 | 新增 QueueService 消息队列服务模块 |
| 2026-04-05 | 更新 LogService 支持 Redis 缓存和文件持久化 |
| 2026-04-05 | 移除广播功能相关文档 |
+615
View File
@@ -0,0 +1,615 @@
# ///
# 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()`
+286
View File
@@ -0,0 +1,286 @@
# WXAuto Center 中控系统
## 项目简介
WXAuto Center 是一款基于 FastAPI + PostgreSQL + Redis 构建的多节点微信管理中控系统,为企业级微信自动化运营提供集中管理平台。该系统能够同时管理多个 WXAuto-HTTP-API 节点,实现消息统一发送、节点状态监控、实时日志查看和外部程序接入等功能。
## 主要功能
- **多节点微信管理**:支持同时接入多个微信节点,按组分类管理
- **节点标识系统**:每个节点拥有唯一的 `node_id`(如 "wx1", "node_001")和显示用的 `name`(如 "微信1", "测试节点")
- **消息发送**:支持单发、群发、批量发送、模板消息等多种发送模式
- **健康检测机制**:通过 `/api/wechat/initialize` 接口检测微信状态,确保消息发送前微信正常运行
- **Webhook 告警**:支持企业微信(wechat)和 Bark 两种格式,节点/微信状态变化时自动通知
- **实时日志**:通过 SSE(Server-Sent Events)技术实现日志实时推送,默认保留最近500条
- **Redis 消息队列**:支持 Redis 后端的消息队列,用于异步消息处理
- **多进程支持**:支持多 worker 部署,适应高并发场景
- **外部程序接入**:提供标准 RESTful API,支持外部系统调用
- **插件系统**:支持扩展插件,包括数据源、AI 智能体、Webhook触发器等
## 快速开始
### 环境要求
- Python 3.8+
- Redis (用于消息队列和多进程场景)
- FastAPI
- httpx(异步 HTTP 客户端)
- uvicorn(ASGI 服务器)
- pydantic
- pydantic-settings
### 安装步骤
```bash
# 进入项目目录
cd wxauto_center
# 安装依赖
pip install -r requirements.txt
# 复制配置示例文件
cp .env.example .env
# 编辑 .env 文件,修改必要的配置项
```
### 启动服务
```bash
# 单进程启动(默认)
python run.py
# 多进程启动(需要 Redis)
python run.py --workers 4
# 带参数启动
python run.py --host 0.0.0.0 --port 8080 --workers 4
# 开发模式(支持热重载,单进程)
python run.py --reload
# 调试模式
python run.py --debug
```
**替代启动方式**:
```bash
# 使用 uvicorn 直接启动
uvicorn main:app --host 0.0.0.0 --port 8080 --reload
```
### 访问地址
- 主界面:http://localhost:8080/static/index.html
- API 文档:http://localhost:8080/docs
- ReDoc 文档:http://localhost:8080/redoc
### 快速使用示例
#### 1. 添加节点
```bash
curl -X POST http://localhost:8080/api/v1/nodes \
-H "Content-Type: application/json" \
-H "X-API-Key: your-external-api-key" \
-d '{
"node_id": "wx1",
"name": "微信1",
"api_url": "http://192.168.20.18:5000",
"api_key": "your-node-api-key",
"description": "生产节点",
"group": "wechat"
}'
```
**节点标识说明**:
- `node_id`:节点唯一标识,如 "wx1", "node_001",用于 API 调用
- `name`:节点显示名称,如 "微信1", "测试节点",用于界面展示
#### 2. 发送消息
```bash
curl -X POST http://localhost:8080/api/v1/messages/send \
-H "Content-Type: application/json" \
-H "X-API-Key: your-external-api-key" \
-d '{
"node_id": "wx1",
"who": "wxid_friend",
"msg": "您好,这是一条测试消息",
"msg_type": "text"
}'
```
#### 3. 查询节点状态
```bash
curl http://localhost:8080/api/v1/nodes/wx1/status \
-H "X-API-Key: your-external-api-key"
```
#### 4. 重置微信状态(当微信掉线时)
```bash
curl -X POST http://localhost:8080/api/v1/callback/node/reset \
-H "Content-Type: application/json" \
-H "X-API-Key: your-external-api-key" \
-d '{
"node_id": "wx1"
}'
```
## 项目结构
```
wxauto_api/
├── main.py # FastAPI 主入口
├── run.py # 启动脚本
├── config.py # 配置管理
├── config.json # 应用配置(不含节点和 Webhook)
├── .env # Docker 环境变量配置
├── models.py # 数据模型(Node, LogEntry, WebhookUrl)
├── database_service.py # 数据库服务
├── api/ # API 路由模块
│ ├── __init__.py
│ ├── nodes.py # 节点管理 API
│ ├── messages.py # 消息发送 API
│ ├── external.py # 外部扩展接口
│ ├── callback.py # 回调接口
│ ├── plugins.py # 插件管理 API
│ └── webhook.py # Webhook 管理 API
├── services/ # 业务逻辑服务
│ ├── node_manager.py # 节点管理器
│ ├── monitor_service.py # 监控服务
│ └── log_service.py # 日志服务
├── plugins/ # 插件系统
│ ├── base.py # 插件基类
│ └── builtin.py # 内置插件
├── static/ # Web 静态资源
│ ├── index.html # 主页面
│ ├── css/style.css # 样式表
│ └── js/ # JavaScript 模块
├── scripts/ # 脚本目录
│ ├── start_amd64.sh # amd64 启动脚本
│ ├── start_arm64.sh # arm64 启动脚本
│ └── database/ # 数据库脚本
├── doc/ # 文档目录
│ └── wxauto_center/ # 项目文档
├── data/ # 数据目录
│ ├── db/ # PostgreSQL 数据
│ ├── redis/ # Redis 数据
│ └── logs/ # 应用日志
├── docker-compose.yml # Docker Compose 配置
└── Dockerfile # Docker 构建文件
```
## 配置说明
系统配置支持多种配置源,按优先级从高到低依次为:
1. 环境变量(`.env` 文件)
2. 配置文件(`config.json`)
3. 代码默认值
### 配置文件
**config.json** - 应用配置(不含节点和 Webhook):
```json
{
"app_name": "WXAuto Center",
"host": "0.0.0.0",
"port": 8080,
"debug": true,
"secret_key": "wxauto-center-secret-key-change-in-production",
"workers": 1,
"cors_origins": ["*"],
"api_prefix": "/api/v1",
"external_api_key": "your-external-api-key",
"monitor": {
"enabled": true,
"check_interval": 30
}
}
```
**.env** - Docker 环境变量配置:
```
DATABASE_URL=postgresql://wxauto:wxauto_password@postgres:5432/wxauto
REDIS_URL=redis://redis:6379/0
APP_NAME=WXAuto Center
HOST=0.0.0.0
PORT=8080
DEBUG=true
SECRET_KEY=wxauto-center-secret-key-change-in-production
WORKERS=1
API_PREFIX=/api/v1
EXTERNAL_API_KEY=your-external-api-key
CORS_ORIGINS=["*"]
MONITOR_ENABLED=true
MONITOR_CHECK_INTERVAL=30
```
### 节点配置
节点配置存储在 PostgreSQL 的 `nodes` 表中,运行时从数据库加载。详细说明请参阅 [CONFIG.md](./CONFIG.md)。
### Webhook 配置
Webhook 配置存储在 PostgreSQL 的 `webhook_urls` 表中,支持企业微信和 Bark 两种格式。详细说明请参阅 [CONFIG.md](./CONFIG.md)。
## API 文档
系统提供完整的 RESTful API,包括:
- **节点管理**:`/api/v1/nodes` - 节点的添加、删除、启用/禁用、状态检测
- **消息发送**:`/api/v1/messages` - 单发、群发、批量发送、模板消息
- **外部接口**:`/api/v1/external` - 供外部程序调用的接口
- **回调接口**:`/api/v1/callback` - 节点状态重置、状态检测
- **插件管理**:`/api/v1/plugins` - 插件的注册和调用
- **配置管理**:`/api/v1/config/webhook`, `/api/v1/config/monitor` - Webhook和监控配置
- **监控状态**:`/api/v1/monitor/status` - 实时监控状态
- **日志服务**:`/api/v1/logs/*` - 日志查询和实时推送(SSE)
详细 API 说明请参阅 [API.md](./API.md)
## 业务流程
系统主要业务流程包括消息发送流程、回调重置流程和监控告警流程。详细说明请参阅 [FLOWS.md](./FLOWS.md)。
## 开发指南
如需进行二次开发或扩展功能,请参阅 [DEVELOPMENT.md](./DEVELOPMENT.md),其中包含:
- 开发环境搭建
- 代码结构说明
- 插件开发指南
- API 调用示例
## 常见问题
如遇到问题,请参阅 [TROUBLESHOOTING.md](./TROUBLESHOOTING.md)
## 核心设计理念
### 1. 节点标识系统
每个节点有两个标识:
- `node_id`:节点唯一标识符,用于 API 调用和系统内部引用,示例:"wx1", "node_001"
- `name`:节点显示名称,用于界面展示和用户友好提示,示例:"微信1", "测试节点"
### 2. 健康检测机制
每次发送消息前,系统会自动调用 `/api/wechat/initialize` 接口初始化微信,确保微信处于可发送消息的状态。这是官方推荐的正确流程。
### 3. 监控告警
监控服务定时检测所有节点和微信状态,当状态发生变化时自动触发Webhook通知。支持的事件类型包括:api_error、wechat_offline、wechat_online、node_offline、node_online。
### 4. 日志服务
采用内存存储+发布订阅模式,支持SSE实时推送。默认保留最近500条日志,足够应对日常调试和监控需求。
## 许可证
本项目仅供学习交流使用,请勿用于违规用途。
+619
View File
@@ -0,0 +1,619 @@
# WXAuto Center 常见问题与解决方案
## 概述
本文档收集了 WXAuto Center 使用过程中可能遇到的常见问题及其解决方案。
---
## 1. 服务启动问题
### 1.1 端口被占用
**问题描述**:
```
Error: [Errno 48] Address already in use
```
**可能原因**:
- 另一个进程正在使用 8080 端口
- 上一次启动的服务未正常关闭
**解决方案**:
```bash
# 查找占用端口的进程
lsof -i :8080 # macOS
# 或
netstat -tlnp | grep 8080 # Linux
# 终止占用进程
kill -9 <PID>
# 或使用其他端口启动
# 修改 config.json 中 port 为其他值,如 8081
```
### 1.2 依赖库安装失败
**问题描述**:
```
ModuleNotFoundError: No module named 'fastapi'
```
**解决方案**:
```bash
# 确保使用 Python 3.8+
python --version
# 升级 pip
pip install --upgrade pip
# 重新安装依赖
pip install -r requirements.txt
# 或使用国内镜像
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
```
### 1.3 配置文件格式错误
**问题描述**:
```
JSONDecodeError: Expecting property name enclosed in double quotes
```
**解决方案**:
检查 `config.json` 文件是否为有效的 JSON 格式:
```bash
# 验证 JSON 格式
python -c "import json; json.load(open('config.json'))"
# 或使用在线 JSON 验证工具
```
---
## 2. API 认证问题
### 2.1 API Key 无效
**问题描述**:
```json
{
"detail": "Invalid API Key"
}
```
**可能原因**:
- 请求时未提供 `X-API-Key` Header
- 提供的 API Key 与配置不匹配
**解决方案**:
1. 确认在请求头中添加了正确的 Header:
```bash
curl -H "X-API-Key: your-external-api-key" http://localhost:8080/api/v1/nodes
```
2. 检查 `config.json` 或 `.env` 中的 `external_api_key` 配置:
```json
{
"external_api_key": "your-external-api-key"
}
```
### 2.2 CORS 跨域问题
**问题描述**:
```
Access-Control-Allow-Origin' header is present on the requested resource
```
**解决方案**:
1. 在 `config.json` 中配置允许的来源:
```json
{
"cors_origins": ["http://localhost:3000", "https://your-domain.com"]
}
```
2. 或设置 `cors_origins": ["*"]`(仅开发环境)
---
## 3. 节点管理问题
### 3.1 节点添加失败
**问题描述**:
```json
{
"success": false,
"error": "Node 'xxx' already exists"
}
```
**解决方案**:
- 节点名称具有唯一性,不能重复
- 使用不同的名称添加节点
- 或先删除已有节点后再添加
```bash
# 删除节点
curl -X DELETE http://localhost:8080/api/v1/nodes/node1 \
-H "X-API-Key: your-api-key"
```
### 3.2 节点连接失败
**问题描述**:
```json
{
"data": {
"is_healthy": false,
"health_message": "API status: error"
}
}
```
**可能原因**:
- 节点服务未启动
- API URL 配置错误
- 网络不通
- API Key 不正确
**解决方案**:
1. 确认节点服务正在运行:
```bash
# 在节点服务器上检查
curl http://节点IP:5000/health
```
2. 检查节点配置:
```bash
# 获取节点信息
curl http://localhost:8080/api/v1/nodes/node1 \
-H "X-API-Key: your-api-key"
```
3. 测试节点 API 连通性:
```bash
# 直接测试节点 API
curl -X POST http://节点IP:5000/api/wechat/initialize \
-H "X-API-Key: 节点API密钥"
```
### 3.3 节点健康检测失败
**问题描述**:
```json
{
"health_message": "WeChat error: 无效"
}
```
**可能原因**:
- 微信窗口未打开或已关闭
- 微信版本不兼容
- WXAuto-HTTP-API 服务异常
**解决方案**:
1. 在对应节点上手动初始化微信:
```bash
curl -X POST http://localhost:8080/api/v1/nodes/node1/wechat/initialize \
-H "X-API-Key: your-api-key"
```
2. 检查节点服务器的微信客户端是否正常运行
3. 重启节点服务
---
## 4. 消息发送问题
### 4.1 消息发送失败 - 节点不健康
**问题描述**:
```json
{
"detail": "Node 'node1' is not healthy: WeChat check failed. Message sending failed."
}
```
**HTTP 状态码**:503
**解决方案**:
1. 先检查节点状态:
```bash
curl http://localhost:8080/api/v1/nodes/node1/status \
-H "X-API-Key: your-api-key"
```
2. 确保微信客户端在节点机器上正常运行
3. 手动初始化微信:
```bash
curl -X POST http://localhost:8080/api/v1/nodes/node1/wechat/initialize \
-H "X-API-Key: your-api-key"
```
### 4.2 消息发送失败 - 接收者不存在
**问题描述**:
```json
{
"data": {
"code": 1,
"message": "receiver not found"
}
}
```
**解决方案**:
1. 确认接收者的 wxid 或群ID 是否正确
2. 获取好友/群列表确认:
```bash
# 获取好友列表
curl http://localhost:8080/api/v1/nodes/node1/friends \
-H "X-API-Key: your-api-key"
# 获取群列表
curl http://localhost:8080/api/v1/nodes/node1/groups \
-H "X-API-Key: your-api-key"
```
### 4.3 消息类型不支持
**问题描述**:
```json
{
"data": {
"code": 1,
"message": "unsupported message type"
}
}
```
**解决方案**:
目前系统仅支持 `text` 类型消息,消息发送时指定 `msg_type`:
```json
{
"node_id": "wx1",
"who": "wxid_friend",
"msg": "Hello!",
"msg_type": "text"
}
```
---
## 5. Webhook 问题
### 5.1 Webhook 通知发送失败
**问题描述**:
日志中出现 `Webhook通知发送失败` 相关信息。
**可能原因**:
- Webhook URL 配置错误
- 网络不通
- Webhook 服务不可用
- 消息格式不被接受
**解决方案**:
1. 检查 Webhook 配置:
```bash
curl http://localhost:8080/api/v1/config/webhook \
-H "X-API-Key: your-api-key"
```
2. 测试 Webhook URL 是否可用:
```bash
# 测试企业微信 Webhook
curl -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=your-key" \
-H "Content-Type: application/json" \
-d '{"msgtype": "text", "text": {"content": "test"}}'
```
3. 检查 Webhook 事件类型配置:
```json
{
"event_types": ["api_error", "wechat_offline", "wechat_online", "node_offline", "node_online"]
}
```
### 5.2 Bark 通知格式问题
**问题描述**:
Bark 格式的 Webhook 发送失败。
**解决方案**:
确保 Webhook URL 正确,格式为:`https://api.day.app/your-bark-id`
---
## 6. 监控服务问题
### 6.1 监控服务未启动
**问题描述**:
日志中没有看到监控服务的输出,状态变化不触发 Webhook。
**解决方案**:
1. 检查监控配置:
```bash
curl http://localhost:8080/api/v1/config/monitor \
-H "X-API-Key: your-api-key"
```
2. 确保 `enabled` 为 `true`
3. 检查监控状态:
```bash
curl http://localhost:8080/api/v1/monitor/status \
-H "X-API-Key: your-api-key"
```
### 6.2 监控检测间隔过长
**问题描述**:
状态变化后很久才收到 Webhook 通知。
**解决方案**:
调整 `check_interval` 配置:
```bash
curl -X POST http://localhost:8080/api/v1/config/monitor \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"check_interval": 30
}'
```
---
## 7. 日志问题
### 7.1 SSE 日志流断开
**问题描述**:
前端日志流连接经常断开。
**可能原因**:
- 网络问题
- 服务器负载过高
- 客户端处理不及时
**解决方案**:
1. 检查网络连接
2. 实现断线重连机制:
```javascript
function connectLogStream() {
const eventSource = new EventSource('/api/v1/logs/stream');
eventSource.onmessage = (event) => {
const log = JSON.parse(event.data);
// 处理日志
};
eventSource.onerror = () => {
console.log('Connection lost, reconnecting...');
setTimeout(connectLogStream, 3000);
};
return eventSource;
}
```
### 7.2 日志丢失
**问题描述**:
日志数量超过 500 条后,早期的日志被清除。
**解决方案**:
这是系统设计行为,`LogService` 默认只保留最近 500 条日志。如需更多日志存储,可以:
1. 修改 `log_service.py` 中的 `max_logs` 参数
2. 实现日志持久化存储(写入文件或数据库)
---
## 8. 插件问题
### 8.1 插件未注册
**问题描述**:
```json
{
"detail": "Plugin 'xxx' not found"
}
```
**解决方案**:
1. 检查插件是否已注册:
```bash
curl http://localhost:8080/api/v1/plugins \
-H "X-API-Key: your-api-key"
```
2. 确认内置插件是否在启动时正确注册(检查 `builtin.py`)
### 8.2 插件执行失败
**问题描述**:
```json
{
"success": false,
"error": "Plugin execution failed"
}
```
**解决方案**:
1. 检查插件配置是否正确
2. 查看系统日志获取详细错误信息
3. 测试插件 API:
```bash
curl -X POST http://localhost:8080/api/v1/external/plugin/execute \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"plugin_name": "plugin_name",
"action": "execute",
"params": {}
}'
```
---
## 9. 性能问题
### 9.1 高并发下响应慢
**可能原因**:
- 节点数量过多
- 网络延迟
- 同步阻塞操作
**解决方案**:
1. 增加监控检测间隔
2. 使用异步调用优化
3. 部署多实例负载均衡
### 9.2 内存占用过高
**可能原因**:
- 日志队列过大
- 订阅者过多
- 节点对象未及时释放
**解决方案**:
1. 减少 `LogService` 的 `max_logs` 参数
2. 及时关闭不需要的 SSE 连接
3. 定期重启服务清理内存
---
## 10. 安全问题
### 10.1 API Key 泄露
**风险**:外部系统可能非法访问 API
**解决方案**:
1. 立即更换 API Key
2. 限制 CORS 来源
3. 使用 HTTPS 传输
4. 定期轮换 API Key
### 10.2 生产环境安全建议
1. 修改默认的 `secret_key`
2. 设置 `debug: false`
3. 配置正确的 `cors_origins`
4. 使用强密码的 API Key
5. 启用 HTTPS
6. 配置防火墙规则
---
## 诊断命令汇总
```bash
# 检查服务健康状态
curl http://localhost:8080/health
# 检查监控状态
curl http://localhost:8080/api/v1/monitor/status \
-H "X-API-Key: your-key"
# 检查节点状态
curl http://localhost:8080/api/v1/nodes \
-H "X-API-Key: your-key"
# 检查 Webhook 配置
curl http://localhost:8080/api/v1/config/webhook \
-H "X-API-Key: your-key"
# 检查最近日志
curl "http://localhost:8080/api/v1/logs/recent?count=20" \
-H "X-API-Key: your-key"
# 检查插件列表
curl http://localhost:8080/api/v1/plugins \
-H "X-API-Key: your-key"
```
---
## 获取帮助
如果以上方案无法解决您的问题,请:
1. 查看详细日志输出
2. 检查系统环境配置
3. 确认网络连通性
4. 查看 [API.md](./API.md) 确认 API 使用正确
5. 查看 [ARCHITECTURE.md](./ARCHITECTURE.md) 了解系统架构
+271
View File
@@ -0,0 +1,271 @@
# WXAuto Relogin - API 接口文档
## 1. 概述
本文档定义 WXAuto Relogin 功能所需的 API 接口。
## 2. 回调接口
### 2.1 接收二维码
客户端上传二维码到中控。
```
POST /api/v1/callback/relogin/qrcode
```
**Headers:**
```
X-API-Key: your-api-key
Content-Type: application/json
```
**请求体:**
```json
{
"node_id": "wx1",
"qrcode_base64": "data:image/png;base64,iVBORw0KGgo...",
"expires_in": 120
}
```
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| node_id | string | 是 | 节点ID |
| qrcode_base64 | string | 是 | Base64编码的PNG图片,带data URI前缀 |
| expires_in | integer | 否 | 过期时间(秒),默认120 |
**响应:**
```json
{
"success": true,
"message": "二维码已接收",
"data": {
"status": "qrcode_ready",
"expires_at": "2026-04-07T15:30:00"
}
}
```
### 2.2 更新重登录状态
```
POST /api/v1/callback/relogin/status
```
**请求体:**
```json
{
"node_id": "wx1",
"status": "scanned",
"message": "用户已扫码"
}
```
| 状态 | 说明 |
|------|------|
| waiting_qrcode | 等待获取二维码 |
| qrcode_ready | 二维码已就绪 |
| scanned | 已扫码,待确认 |
| confirmed | 已确认,登录中 |
| completed | 登录完成 |
| failed | 登录失败 |
## 3. 节点接口
### 3.1 获取重登录状态
```
GET /api/v1/nodes/{node_id}/relogin/status
```
**响应:**
```json
{
"success": true,
"data": {
"node_id": "wx1",
"status": "qrcode_ready",
"qrcode_base64": "data:image/png;base64,...",
"qrcode_expires_at": "2026-04-07T15:30:00",
"created_at": "2026-04-07T15:00:00",
"updated_at": "2026-04-07T15:05:00"
}
}
```
### 3.2 清除重登录状态
```
DELETE /api/v1/nodes/{node_id}/relogin/status
```
**响应:**
```json
{
"success": true,
"message": "状态已清除"
}
```
## 4. 客户端管理接口
### 4.1 注册客户端
```
POST /api/v1/relogin/clients
```
**请求体:**
```json
{
"client_name": "服务器1",
"webhook_url": "http://192.168.1.100:8081/webhook/relogin",
"secret_key": "optional_secret_for_signing"
}
```
**响应:**
```json
{
"success": true,
"data": {
"id": 1,
"client_name": "服务器1",
"webhook_url": "http://192.168.1.100:8081/webhook/relogin",
"enabled": true,
"created_at": "2026-04-07T15:00:00"
}
}
```
### 4.2 获取客户端列表
```
GET /api/v1/relogin/clients
```
**响应:**
```json
{
"success": true,
"data": [
{
"id": 1,
"client_name": "服务器1",
"webhook_url": "http://192.168.1.100:8081/webhook/relogin",
"enabled": true,
"created_at": "2026-04-07T15:00:00"
}
]
}
```
### 4.3 更新客户端
```
PUT /api/v1/relogin/clients/{client_id}
```
**请求体:**
```json
{
"enabled": false
}
```
### 4.4 删除客户端
```
DELETE /api/v1/relogin/clients/{client_id}
```
## 5. Webhook 告警格式
中控向客户端发送的告警格式:
```json
{
"event": "wechat_offline",
"node_id": "wx1",
"node_name": "微信1",
"wechat_status": "offline",
"timestamp": "2026-04-07T15:00:00",
"message": "节点 wx1 微信掉线"
}
```
**event 类型:**
| 事件 | 说明 |
|------|------|
| wechat_offline | 微信掉线 |
| wechat_online | 微信上线 |
| node_offline | 节点离线 |
| node_online | 节点上线 |
## 6. 签名验证(可选)
如果配置了 secret_key,客户端应验证请求签名:
```
X-Signature: sha256=xxxxxxxxxxxxxx
```
**验证算法:**
```python
import hmac
import hashlib
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
```
## 7. 错误码
| 错误码 | 说明 |
|--------|------|
| 404 | 节点不存在 |
| 400 | 参数错误 |
| 401 | API Key无效 |
| 403 | 无权限 |
| 500 | 服务器内部错误 |
## 8. 使用示例
### 8.1 完整重登录流程
```bash
# 1. 微信掉线,中控发送告警到客户端
# 客户端接收: POST /webhook/relogin
# 2. 客户端从节点获取二维码
curl -o qrcode.png http://node-api:5000/api/wechat/qrcode \
-H "X-API-Key: node-api-key"
# 3. 客户端上传二维码到中控
curl -X POST http://center:8080/api/v1/callback/relogin/qrcode \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"node_id": "wx1",
"qrcode_base64": "data:image/png;base64,...",
"expires_in": 120
}'
# 4. 前端轮询获取状态
curl http://center:8080/api/v1/nodes/wx1/relogin/status \
-H "X-API-Key: your-api-key"
# 5. 用户扫码确认后,节点回调通知中控
curl -X POST http://center:8080/api/v1/callback/node/check \
-d '{"node_id": "wx1", "status": "online"}'
# 6. 客户端轮询发现 completed
curl http://center:8080/api/v1/nodes/wx1/relogin/status
# 返回: {"status": "completed"}
```
+375
View File
@@ -0,0 +1,375 @@
# WXAuto Relogin - 客户端开发指南
## 1. 概述
本文档说明如何开发 WXAuto Relogin 客户端程序,用于接收中控告警并自动处理微信重登录。
## 2. 技术栈
- Python 3.11+
- FastAPI (Webhook服务)
- httpx (HTTP客户端)
- asyncio (异步处理)
## 3. 项目结构
```
wxauto-relogin-client/
├── client/
│ ├── __init__.py
│ ├── webhook_server.py # Webhook接收服务
│ ├── qrcode_handler.py # 二维码处理
│ ├── node_client.py # 节点通信
│ └── config.py # 配置
├── requirements.txt
└── README.md
```
## 4. 配置
```python
# client/config.py
from pydantic import BaseModel
class ClientConfig(BaseModel):
center_url: str = "http://localhost:8080"
center_api_key: str = "your-external-api-key"
client_name: str = "relogin-client-1"
secret_key: str = "" # 可选,用于签名验证
listen_host: str = "0.0.0.0"
listen_port: int = 8081
config = ClientConfig()
```
## 5. Webhook 接收服务
```python
# client/webhook_server.py
from fastapi import FastAPI, HTTPException, Header
from pydantic import BaseModel
from typing import Optional
import asyncio
import logging
from .qrcode_handler import QRCodeHandler
from .config import config
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("relogin-client")
app = FastAPI()
qrcode_handler = QRCodeHandler()
class ReloginAlert(BaseModel):
event: str
node_id: str
node_name: str
wechat_status: str
timestamp: str
@app.post("/webhook/relogin")
async def receive_alert(
alert: ReloginAlert,
x_signature: Optional[str] = Header(None)
):
"""
接收中控的掉线告警
"""
logger.info(f"Received alert: {alert.node_id} - {alert.wechat_status}")
# 验证签名(如果配置了secret_key)
if config.secret_key:
# TODO: 实现签名验证
pass
# 触发重登录流程
asyncio.create_task(handle_relogin(alert))
return {"status": "accepted", "node_id": alert.node_id}
async def handle_relogin(alert: ReloginAlert):
"""
处理重登录流程
"""
try:
logger.info(f"Starting relogin for {alert.node_id}")
# 1. 获取二维码
qrcode_base64 = await qrcode_handler.get_and_upload_qrcode(alert.node_id)
if qrcode_base64:
logger.info(f"QR code uploaded for {alert.node_id}")
# 2. 等待扫码确认
success = await qrcode_handler.wait_for_scan(alert.node_id, timeout=180)
if success:
logger.info(f"ReLogin successful for {alert.node_id}")
else:
logger.warning(f"ReLogin timeout for {alert.node_id}")
except Exception as e:
logger.error(f"ReLogin failed for {alert.node_id}: {e}")
@app.get("/health")
async def health():
return {"status": "healthy"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host=config.listen_host, port=config.listen_port)
```
## 6. 二维码处理
```python
# client/qrcode_handler.py
import httpx
import asyncio
import time
import base64
from typing import Optional
from .config import config
class QRCodeHandler:
def __init__(self):
self.center_url = config.center_url
self.api_key = config.center_api_key
async def get_qrcode_from_node(self, api_url: str, node_api_key: str) -> Optional[bytes]:
"""
从wxauto节点获取二维码
"""
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(
f"{api_url}/api/wechat/qrcode",
headers={"X-API-Key": node_api_key}
)
if response.status_code == 200:
return response.content
else:
return None
except Exception as e:
print(f"Failed to get QR code from node: {e}")
return None
async def upload_qrcode_to_center(self, node_id: str, qrcode_bytes: bytes, expires_in: int = 120):
"""
上传二维码到中控
"""
qrcode_base64 = base64.b64encode(qrcode_bytes).decode()
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.post(
f"{self.center_url}/api/v1/callback/relogin/qrcode",
headers={"X-API-Key": self.api_key},
json={
"node_id": node_id,
"qrcode_base64": f"data:image/png;base64,{qrcode_base64}",
"expires_in": expires_in
}
)
return response.json().get("success", False)
async def get_node_info(self, node_id: str) -> Optional[dict]:
"""
从中控获取节点信息(包含API地址和密钥)
"""
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.get(
f"{self.center_url}/api/v1/nodes/{node_id}",
headers={"X-API-Key": self.api_key}
)
if response.status_code == 200:
return response.json().get("data")
return None
async def get_and_upload_qrcode(self, node_id: str) -> Optional[str]:
"""
获取二维码并上传到中控
"""
# 1. 获取节点信息
node_info = await self.get_node_info(node_id)
if not node_info:
print(f"Node {node_id} not found")
return None
# 2. 获取二维码
qrcode_bytes = await self.get_qrcode_from_node(
api_url=node_info["api_url"],
node_api_key=node_info["api_key"]
)
if not qrcode_bytes:
print(f"Failed to get QR code for {node_id}")
return None
# 3. 上传到中控
success = await self.upload_qrcode_to_center(node_id, qrcode_bytes)
if success:
return f"data:image/png;base64,{base64.b64encode(qrcode_bytes).decode()}"
return None
async def wait_for_scan(self, node_id: str, timeout: int = 180) -> bool:
"""
轮询中控,等待扫码确认
"""
start_time = time.time()
interval = 2 # 每2秒轮询一次
while time.time() - start_time < timeout:
try:
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.get(
f"{self.center_url}/api/v1/nodes/{node_id}/relogin/status",
headers={"X-API-Key": self.api_key}
)
if response.status_code == 200:
data = response.json().get("data", {})
status = data.get("status")
print(f"Status: {status}")
if status == "completed":
return True
elif status == "failed":
return False
except Exception as e:
print(f"Polling error: {e}")
await asyncio.sleep(interval)
return False
```
## 7. 节点通信客户端
```python
# client/node_client.py
import httpx
from typing import Optional
class NodeClient:
def __init__(self, api_url: str, api_key: str):
self.api_url = api_url.rstrip("/")
self.api_key = api_key
async def get_qrcode(self) -> Optional[bytes]:
"""
获取登录二维码
"""
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(
f"{self.api_url}/api/wechat/qrcode",
headers={"X-API-Key": self.api_key}
)
if response.status_code == 200:
return response.content
return None
except Exception as e:
print(f"Failed to get QR code: {e}")
return None
async def check_login_status(self) -> dict:
"""
检查登录状态
"""
try:
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.get(
f"{self.api_url}/api/wechat/status",
headers={"X-API-Key": self.api_key}
)
if response.status_code == 200:
return response.json()
return {"logged_in": False}
except Exception as e:
return {"logged_in": False, "error": str(e)}
async def logout(self) -> bool:
"""
登出微信
"""
try:
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.post(
f"{self.api_url}/api/wechat/logout",
headers={"X-API-Key": self.api_key}
)
return response.status_code == 200
except Exception as e:
print(f"Logout failed: {e}")
return False
```
## 8. 依赖
```txt
# requirements.txt
fastapi>=0.100.0
uvicorn>=0.23.0
httpx>=0.24.0
pydantic>=2.0.0
python-dotenv>=1.0.0
```
## 9. 运行
```bash
# 安装依赖
pip install -r requirements.txt
# 运行客户端
python -m client.webhook_server
```
## 10. Docker 部署
```dockerfile
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY client/ ./client/
CMD ["python", "-m", "client.webhook_server"]
```
```yaml
# docker-compose.yml
services:
relogin-client:
build: .
ports:
- "8081:8081"
environment:
- CENTER_URL=http://your-center:8080
- CENTER_API_KEY=your-api-key
- CLIENT_NAME=relogin-1
restart: unless-stopped
```
## 11. 完整示例
```python
# main.py
import asyncio
from client.webhook_server import app
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8081)
```
## 12. 注意事项
1. **网络安全**: 确保客户端Webhook端口能从公网访问
2. **签名验证**: 生产环境建议启用signature验证
3. **超时设置**: 二维码有效期通常120秒,需要及时处理
4. **重试机制**: 建议添加失败重试逻辑
5. **日志记录**: 保留完整日志便于排查问题
+400
View File
@@ -0,0 +1,400 @@
# WXAuto Relogin - 微信自动重登录方案
## 1. 背景问题
### 1.1 当前痛点
- 微信掉线后,需要人工介入扫码登录
- 节点多时,人工操作繁琐
- 无法远程自动恢复微信会话
### 1.2 现有架构
```
中控(Center) ←→ 节点(Node)
↑
API通信/回调
```
## 2. 解决方案概述
### 2.1 核心理念
```
微信掉线 → 中控告警 → 客户端接收 → 获取二维码 → 回传中控 → 前端展示扫码
```
### 2.2 系统架构
```
┌─────────────────────────────────────────────────────────────┐
│ WXAuto Center │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 告警系统 │→ │ 插件系统 │← │ 前端展示 │ │
│ │ (Webhook) │ │(wxautorelogin)│ │ (二维码) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ↑ │ │
│ │ ┌──────────────┐ │ │
│ └─────────│ 回调接口 │───────────┘ │
│ │ /callback │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
↑ HTTP
┌─────────────────────────────────────────────────────────────┐
│ WXAuto Relogin Client │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 消息接收 │ │ 二维码获取 │→ │ 状态回调 │ │
│ │ (Webhook) │ │(get QR code) │ │ (重置微信) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
## 3. 实现方案
### 3.1 中控端改动
#### 3.1.1 新增 API 接口
| 接口 | 方法 | 说明 |
|------|------|------|
| `POST /api/v1/callback/relogin/qrcode` | 接收二维码 | 客户端回传二维码图片 |
| `GET /api/v1/nodes/{node_id}/relogin/status` | 重登录状态 | 查询节点重登录进度 |
#### 3.1.2 二维码存储结构
```python
# NodeReloginStatus
{
"node_id": "wx1",
"status": "waiting_qrcode" | "qrcode_ready" | "scanned" | "confirmed" | "completed" | "failed",
"qrcode_base64": "data:image/png;base64,...",
"qrcode_expires_at": "2026-04-07T15:30:00",
"created_at": "2026-04-07T15:00:00",
"updated_at": "2026-04-07T15:05:00"
}
```
#### 3.1.3 前端展示
- 节点详情页增加"重登录"标签页
- 实时显示二维码(轮询 /api/v1/nodes/{node_id}/relogin/status)
- 二维码过期提示
### 3.2 客户端改动
#### 3.2.1 Webhook 接收器
客户端需要暴露一个 HTTP 接口接收中控告警:
```python
# client/webhook_server.py
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.post("/webhook/relogin")
async def receive_alert(data: dict):
"""
接收中控的掉线告警
{
"event": "wechat_offline",
"node_id": "wx1",
"node_name": "微信1",
"wechat_status": "offline",
"timestamp": "2026-04-07T15:00:00"
}
"""
# 触发获取二维码流程
await trigger_relogin(node_id=data["node_id"])
return {"status": "ok"}
async def trigger_relogin(node_id: str):
# 1. 调用节点API获取二维码
# 2. 上传二维码到中控
# 3. 等待扫码确认
pass
```
#### 3.2.2 二维码获取流程
```python
async def get_qrcode_from_node(api_url: str, api_key: str) -> bytes:
"""
从wxauto节点获取二维码
GET /api/wechat/qrcode
返回: PNG图片二进制
"""
async with httpx.AsyncClient() as client:
response = await client.get(
f"{api_url}/api/wechat/qrcode",
headers={"X-API-Key": api_key}
)
return response.content
async def upload_qrcode_to_center(center_url: str, node_id: str, qrcode_bytes: bytes):
"""
上传二维码到中控
POST /api/v1/callback/relogin/qrcode
"""
async with httpx.AsyncClient() as client:
import base64
qrcode_base64 = base64.b64encode(qrcode_bytes).decode()
await client.post(
f"{center_url}/api/v1/callback/relogin/qrcode",
json={
"node_id": node_id,
"qrcode_base64": qrcode_base64
}
)
```
#### 3.2.3 扫码状态轮询
```python
async def wait_for_scan(center_url: str, node_id: str, timeout: int = 120):
"""
轮询中控接口,等待用户扫码确认
"""
start_time = time.time()
while time.time() - start_time < timeout:
async with httpx.AsyncClient() as client:
response = await client.get(
f"{center_url}/api/v1/nodes/{node_id}/relogin/status"
)
status = response.json()
if status["status"] == "completed":
return True
elif status["status"] == "failed":
return False
await asyncio.sleep(2)
return False
```
## 4. 完整流程时序
### 4.1 时序图
```
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ 微信 │ │ 节点 │ │ 中控 │ │ 客户端 │ │ 用户 │
└────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘
│ │ │ │ │
│ 掉线 │ │ │ │
│───────────────→│ │ │ │
│ │ wechat_offline callback │ │
│ │───────────────→│ │ │
│ │ │ Webhook告警 │ │
│ │ │───────────────→│ │
│ │ │ │ │
│ │ │ │ 获取二维码 │
│ │ GET /qrcode │ │───────────────→│
│ 返回二维码 │←──────────────│ │ │
│←───────────────│ │ │ │
│ │ │ │ 上传二维码 │
│ │ │←──────────────│ │
│ │ │ │ │
│ │ │ 前端展示二维码│ │
│ │ │───────────────→│ 扫码 │
│ │ │ │←──────────────│
│ 扫码确认 │ │ │ │
│←───────────────│ │ │ │
│ 登录成功 │ │ │ │
│───────────────→│ │ │ │
│ │ wechat_online callback │ │
│ │───────────────→│ │ │
│ │ │ 更新状态 │ │
│ │ │───────────────→│ 完成 │
```
### 4.2 详细步骤
| 步骤 | 参与者 | 操作 | API/协议 |
|------|--------|------|----------|
| 1 | 微信 | 掉线检测 | - |
| 2 | 节点 | 回调通知中控 | POST /callback |
| 3 | 中控 | 触发Webhook告警 | HTTP |
| 4 | 客户端 | 接收告警 | POST /webhook/relogin |
| 5 | 客户端 | 请求节点二维码 | GET /api/wechat/qrcode |
| 6 | 节点 | 返回二维码图片 | HTTP |
| 7 | 客户端 | 上传二维码到中控 | POST /callback/relogin/qrcode |
| 8 | 中控 | 存储并通知前端 | WebSocket/轮询 |
| 9 | 前端 | 展示二维码 | - |
| 10 | 用户 | 扫码确认 | - |
| 11 | 微信 | 登录成功 | - |
| 12 | 节点 | 回调通知中控 | POST /callback |
| 13 | 中控 | 更新节点状态 | - |
## 5. 数据库设计
### 5.1 新增表
```sql
-- 节点重登录状态表
CREATE TABLE node_relogin_status (
id SERIAL PRIMARY KEY,
node_id VARCHAR(50) UNIQUE NOT NULL,
status VARCHAR(20) DEFAULT 'idle',
qrcode_base64 TEXT,
qrcode_expires_at TIMESTAMP,
error_message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 客户端配置表
CREATE TABLE relogin_clients (
id SERIAL PRIMARY KEY,
client_name VARCHAR(100) NOT NULL,
webhook_url VARCHAR(500) NOT NULL,
secret_key VARCHAR(100),
enabled BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
### 5.2 状态枚举
| 状态 | 说明 |
|------|------|
| `idle` | 空闲,无重登录任务 |
| `waiting_qrcode` | 等待获取二维码 |
| `qrcode_ready` | 二维码已就绪 |
| `scanned` | 已扫码,待确认 |
| `confirmed` | 已确认,登录中 |
| `completed` | 登录完成 |
| `failed` | 登录失败 |
## 6. API 接口详细设计
### 6.1 回调接口 - 接收二维码
```
POST /api/v1/callback/relogin/qrcode
```
**请求体:**
```json
{
"node_id": "wx1",
"qrcode_base64": "data:image/png;base64,iVBORw0KGgo...",
"expires_in": 120
}
```
**响应:**
```json
{
"success": true,
"message": "二维码已接收"
}
```
### 6.2 查询重登录状态
```
GET /api/v1/nodes/{node_id}/relogin/status
```
**响应:**
```json
{
"success": true,
"data": {
"node_id": "wx1",
"status": "qrcode_ready",
"qrcode_base64": "data:image/png;base64,...",
"qrcode_expires_at": "2026-04-07T15:30:00",
"created_at": "2026-04-07T15:00:00"
}
}
```
### 6.3 客户端注册
```
POST /api/v1/relogin/clients
```
**请求体:**
```json
{
"client_name": "服务器1",
"webhook_url": "http://192.168.1.100:8081/webhook/relogin",
"secret_key": "optional_secret"
}
```
### 6.4 客户端列表
```
GET /api/v1/relogin/clients
```
## 7. 安全考虑
### 7.1 客户端认证
- 客户端注册时分配 secret_key
- 回调接口需要携带签名验证
- 中控可配置允许的客户端IP白名单
### 7.2 回调签名验证
```python
import hmac
import hashlib
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
```
## 8. 文件结构
```
wxauto_api/
├── plugins/
│ └── wxautorelogin_plugin.py # 重登录插件
├── api/
│ └── relogin.py # 重登录相关API
├── services/
│ └── relogin_service.py # 重登录服务
└── doc/
└── wxautorelogin/
├── README.md # 本文档
├── CLIENT.md # 客户端开发指南
└── API.md # API接口文档
wxauto-relogin-client/
├── client/
│ ├── __init__.py
│ ├── webhook_server.py # Webhook接收服务
│ ├── qrcode_handler.py # 二维码处理
│ └── config.py # 配置
├── requirements.txt
└── README.md
```
## 9. 可行性结论
### 9.1 技术可行性:✅ 可行
1. **wxauto节点已提供QR码接口** - 通过 `/api/wechat/qrcode` 获取
2. **中控已有回调机制** - 可复用现有 callback 系统
3. **前端支持实时更新** - 可通过轮询或WebSocket展示二维码
### 9.2 实施难度:🟡 中等
1. 需要开发客户端程序
2. 需要新增API接口
3. 需要前端新增重登录页面
### 9.3 建议实施顺序
1. **Phase 1**: 中控端API开发
2. **Phase 2**: 客户端程序开发
3. **Phase 3**: 前端页面开发
4. **Phase 4**: 整体联调测试
## 10. 后续优化方向
- 支持短信/邮件通知
- 支持多客户端负载均衡
- 支持扫码历史记录
- 支持自动重试机制