- 架构概览(拓扑图) - 第1步:NapCat / go-cqhttp 部署 - 第2步:qqrebot 本体部署(含 systemd 服务) - 第3步:OpenClaw Agent 端部署
348 lines
9.6 KiB
Markdown
Executable File
348 lines
9.6 KiB
Markdown
Executable File
# OneBot Chatbot Framework
|
||
|
||
该项目是一个基于OneBot标准的聊天机器人后端框架,采用高度可扩展的插件架构设计,支持消息的模块化处理和插件热加载。如果你有任何意见或建议,可以通过 jianfeee@outlook.com 联系我。
|
||
|
||
## 项目特点
|
||
|
||
- **模块化设计**:每个功能作为独立插件实现,易于扩展和维护
|
||
- **插件生命周期管理**:支持插件加载、注册、依赖处理和实例管理
|
||
- **消息处理管道**:分阶段处理消息,支持各阶段拦截机制
|
||
- **会话管理**:支持群组消息和私聊消息的独立管理
|
||
- **内嵌依赖处理**:自动管理插件内嵌的Python依赖包
|
||
- **兼容性设计**:支持新旧版本插件并存运行
|
||
|
||
## 内置插件
|
||
|
||
### OpenClaw Bridge
|
||
|
||
`src/process.py` — QQ 消息 ↔ OpenClaw Gateway 桥接插件。
|
||
将用户消息转发给 OpenClaw Gateway 上的 AI agent 处理并自动回复。
|
||
|
||
**配置**: `config/openclawbridge/config.toml`
|
||
|
||
### QQ 操作脚本
|
||
|
||
`scripts/qq_*.py` — 15 个独立脚本,agent 可通过 subprocess 直连 NapCat API 主动操作 QQ。
|
||
|
||
### Agent Skills
|
||
|
||
`skills/` — AgentSkills,指导 AI agent 如何使用上述脚本。
|
||
|
||
## 核心组件
|
||
|
||
### 消息处理流程 (`process_message`)
|
||
|
||
```python
|
||
def process_message(uid: str, gid: str | None, message: str) -> str:
|
||
# 1. 创建消息上下文
|
||
ctx = MessageContext(...)
|
||
|
||
# 2. 扫描并加载插件
|
||
plugin_manager.scan_plugins()
|
||
|
||
# 3. 消息处理阶段:
|
||
# - before_load: 加载数据前拦截点
|
||
# - after_load: 加载数据后处理点
|
||
# - after_save: 保存数据后处理点
|
||
|
||
# 4. 会话数据持久化
|
||
ctx.chat_manager.save_message(...)
|
||
|
||
return ctx.response or "ok"
|
||
```
|
||
|
||
### 插件管理器 (`PluginManager`)
|
||
|
||
```python
|
||
class PluginManager:
|
||
def __init__(self):
|
||
self._plugins = {} # 插件类注册表
|
||
self._active_instances = {} # 插件实例
|
||
self._hook_registry = {} # 兼容旧版钩子
|
||
self._temp_dirs = [] # 临时目录
|
||
self._dependency_manager = DependencyManager() # 依赖处理器
|
||
|
||
def scan_plugins(self):
|
||
"""扫描插件目录并加载ZIP格式插件"""
|
||
|
||
def load_plugin(self, zip_path: str) -> bool:
|
||
"""动态加载ZIP格式插件"""
|
||
|
||
def _load_embedded_dependencies(self, plugin_dir: str) -> bool:
|
||
"""加载插件内嵌的依赖包"""
|
||
|
||
def register_hook(self, hook_name: str):
|
||
"""注册兼容旧版钩子(装饰器模式)"""
|
||
|
||
def cleanup(self):
|
||
"""清理临时资源"""
|
||
```
|
||
|
||
## 插件开发指南
|
||
|
||
### 基本插件结构
|
||
|
||
```python
|
||
# process.py
|
||
from src.modules.plugin_modules import BasePlugin, MessageContext
|
||
|
||
class MyPlugin(BasePlugin):
|
||
def __init__(self, ctx: MessageContext):
|
||
super().__init__(ctx)
|
||
|
||
def process(self) -> str | None:
|
||
"""核心处理方法"""
|
||
if self.ctx.command == "help":
|
||
return self._show_help()
|
||
|
||
def before_load(self) -> str | None:
|
||
"""数据加载前拦截点"""
|
||
|
||
def after_load(self) -> str | None:
|
||
"""数据加载后处理点"""
|
||
|
||
def after_save(self) -> str | None:
|
||
"""数据保存后处理点"""
|
||
```
|
||
|
||
### 目录结构要求
|
||
|
||
插件应以ZIP格式打包,包含以下内容:
|
||
|
||
```
|
||
my_plugin.zip
|
||
├── process.py # 必需 - 插件入口文件
|
||
├── requirements.txt # 可选 - 依赖声明
|
||
└── packages/ # 可选 - 内嵌依赖包
|
||
├── package1/
|
||
└── package2/
|
||
```
|
||
|
||
### 依赖声明
|
||
|
||
插件可通过两种方式声明依赖:
|
||
|
||
1. `requirements.txt` 标准格式
|
||
2. `dependencies.json` 自定义格式
|
||
|
||
```json
|
||
// dependencies.json 示例
|
||
{
|
||
"requirements": [
|
||
"requests==2.28.2",
|
||
"numpy>=1.25.0"
|
||
]
|
||
}
|
||
```
|
||
|
||
## 快速启动
|
||
|
||
1. 为启动脚本授权(Linux):
|
||
|
||
```bash
|
||
chmod +x run.sh
|
||
```
|
||
|
||
2. 修改配置文件,`list_port` 为接收消息推送端口,`send_url` 为消息发送地址
|
||
|
||
3. 运行启动脚本
|
||
|
||
Linux:
|
||
|
||
```bash
|
||
./run.sh
|
||
```
|
||
|
||
Windows:
|
||
|
||
```bat
|
||
.\run.bat
|
||
```
|
||
|
||
## 完整部署指南
|
||
|
||
### 架构概览
|
||
|
||
整个系统分三层:
|
||
|
||
```
|
||
QQ客户端 服务器
|
||
│ │
|
||
│ QQ 协议 │
|
||
▼ │
|
||
NapCat / go-cqhttp │
|
||
│ OneBot HTTP │
|
||
├─── POST 消息 → qqrebot (本仓库)
|
||
│ │
|
||
│ HTTP API │
|
||
◄─── 主动操作 ── qqrebot │
|
||
│ ├─── 转发消息 → OpenClaw Gateway
|
||
│ │ └─── agent 处理
|
||
│ ◄─── 回复 ←────┘
|
||
```
|
||
|
||
### 第1步:部署 NapCat / go-cqhttp
|
||
|
||
这是 QQ 协议实现,负责登录 QQ 账号并与腾讯服务器通信。
|
||
|
||
- NapCat:https://napcat.napneko.com/
|
||
- go-cqhttp:https://docs.go-cqhttp.org/
|
||
|
||
配置 NapCat 的 HTTP 上报地址指向 qqrebot(默认 `http://127.0.0.1:25580`)。
|
||
|
||
### 第2步:部署 qqrebot(本仓库)
|
||
|
||
从 [chatrebot1.0 release](https://jianfgit.xyz/jianf/chat_rebot-connect-with-onebot-standard-/src/tag/chatrebot1.0/) 下载并解压:
|
||
|
||
```bash
|
||
# 下载 release 源码
|
||
wget https://jianfgit.xyz/jianf/chat_rebot-connect-with-onebot-standard-/archive/chatrebot1.0.tar.gz
|
||
tar xzf chatrebot1.0.tar.gz
|
||
cd chat_rebot-connect-with-onebot-standard-
|
||
|
||
# 如需安装 OpenClaw Bridge 插件,从 main 分支复制
|
||
wget https://jianfgit.xyz/jianf/chat_rebot-connect-with-onebot-standard-/raw/branch/main/src/process.py
|
||
wget https://jianfgit.xyz/jianf/chat_rebot-connect-with-onebot-standard-/raw/branch/main/config/openclawbridge/config.toml
|
||
mkdir -p plugins config/openclawbridge
|
||
mv process.py plugins/
|
||
mv config.toml config/openclawbridge/
|
||
```
|
||
|
||
**配置 NapCat 地址**(`config/config.toml`):
|
||
|
||
```toml
|
||
[app]
|
||
list_port = 25580 # 接收 NapCat 消息推送的端口
|
||
send_url = "http://127.0.0.1:25570" # NapCat HTTP API 地址
|
||
|
||
[rebot]
|
||
id = ""
|
||
|
||
[plugins]
|
||
dir = ["plugins"]
|
||
```
|
||
|
||
**启动(Linux)**:
|
||
|
||
```bash
|
||
chmod +x run.sh
|
||
./run.sh
|
||
```
|
||
|
||
**配置 systemd 服务(推荐)**:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=QQ Robot
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
WorkingDirectory=/path/to/chat_rebot-connect-with-onebot-standard-
|
||
ExecStart=/path/to/chat_rebot-connect-with-onebot-standard-/run.sh
|
||
Restart=always
|
||
RestartSec=3
|
||
StandardOutput=journal
|
||
StandardError=journal
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
### 第3步:配置 OpenClaw Agent
|
||
|
||
让 agent 能够主动操作 QQ(发消息、管理群、查信息等)。
|
||
|
||
#### 3a. 部署脚本到 agent 工作区
|
||
|
||
```bash
|
||
cp -r scripts/ /path/to/qq-agent/workspace/
|
||
```
|
||
|
||
#### 3b. 部署 Skills 到 agent skills 目录
|
||
|
||
```bash
|
||
cp -r skills/qq-messenger /path/to/agent/skills/
|
||
cp -r skills/qq-management /path/to/agent/skills/
|
||
cp -r skills/qq-resolver /path/to/agent/skills/
|
||
cp -r skills/qq-napcat-extras /path/to/agent/skills/
|
||
```
|
||
|
||
#### 3c. 替换占位符
|
||
|
||
编辑各脚本开头的配置变量,将占位符替换为实际值:
|
||
|
||
```python
|
||
# 需替换的占位符:
|
||
ADMIN_QQ = "YOUR_ADMIN_QQ" # 你的 QQ 号
|
||
CQHTTP_URL = "http://YOUR_NAPCAT_HOST:25570" # NapCat 地址
|
||
GATEWAY_URL = "http://127.0.0.1:18789" # OpenClaw Gateway
|
||
GATEWAY_TOKEN = "YOUR_GATEWAY_TOKEN" # Gateway 鉴权 Token
|
||
```
|
||
|
||
#### 3d. 验证
|
||
|
||
在 agent 工作区尝试执行单个脚本确认连通性:
|
||
|
||
```bash
|
||
cd /path/to/qq-agent/workspace/scripts
|
||
python3 qq_get_groups.py
|
||
```
|
||
|
||
## 常见问题 / 踩坑指南
|
||
|
||
### 1. systemd 下只有 stdin/stdout,没有持久化日志
|
||
|
||
本仓库设计为通过 systemd 托管,`run.sh` 中的 gunicorn 输出全部走 stdout/stderr。systemd 会自动捕获到 journald。
|
||
|
||
查看日志:
|
||
|
||
```bash
|
||
journalctl -u qqrebot --since "5 minutes ago" -f
|
||
```
|
||
|
||
如果发现日志回滚太短,在 service 中设置 `StandardOutput=journal+console`。
|
||
|
||
### 2. `app.py` 端口硬编码
|
||
|
||
`app.py` 的 `__main__` 直接将端口写死在 `port=25580`,不走 `config.toml`。这意味着:
|
||
|
||
- `python3 app.py` 直接运行 → **无视配置**,始终占 25580
|
||
- `run.sh`(gunicorn)→ **自动读取配置**,正常
|
||
|
||
如果直接 `python3 app.py` 启动报 `Address already in use`,检查是否跟 gunicorn 实例抢端口。
|
||
|
||
### 3. ConfigManager 内部字典不自动刷新
|
||
|
||
当插件首次部署,`config/插件名/config.toml` 尚不存在时,`ConfigManager.__init__` 会通过 `build_config_dict()` 扫描目录。此时文件不存在,内部 `self.config` 为空。
|
||
|
||
`BasePlugin.config` 属性的异常处理会触发 `_ensure_config_exists()` 创建文件,但 **ConfigManager 的 `self.config` 不会被刷新**,第二次 `load_config("config")` 仍然 KeyError。解决方法:`_ensure_config_exists` 创建文件后调用 `self._config_manager.build_config_dict()` 手动刷新。
|
||
|
||
### 4. python3-venv 缺失
|
||
|
||
纯净 Debian/Ubuntu 没有 `python3-venv`:
|
||
|
||
```bash
|
||
apt install python3.13-venv # 替换 .13 为实际版本
|
||
```
|
||
|
||
否则 `run.sh` 创建虚拟环境会直接失败。
|
||
|
||
### 5. gunicorn / waitress 不在 requirements.txt 中
|
||
|
||
```bash
|
||
# requirements.txt 未包含,由启动脚本单独安装
|
||
# run.sh: pip install gunicorn
|
||
# run.bat: pip install waitress
|
||
```
|
||
|
||
## 设计优势
|
||
|
||
1. **解耦设计**:插件与核心系统完全解耦
|
||
2. **安全隔离**:使用临时目录加载插件
|
||
3. **版本兼容**:内建依赖版本验证机制
|
||
4. **灵活扩展**:支持多个消息处理点
|
||
5. **新旧兼容**:支持传统钩子和现代OOP插件的共存
|
||
|
||
仓库地址:[chat_rebot-connect-with-onebot-standard-](https://jianfgit.xyz/jianf/chat_rebot-connect-with-onebot-standard-)
|