Files
chatrebot_aireply_plug/README.md
root 5a69db8af9 fix: 修正NapCat通信架构说明(纯HTTP,非WebSocket)
- 移除所有WebSocket/3001端口的错误引用
- NapCat→qqrebot 使用 httpPost 数组配置HTTP POST事件推送
- onebot11.json 配置修正:httpPost而非WS Server模式
- 架构图标注所有链路为HTTP POST,标注各端口用途
- 增加 QQREBOT_HOST 变量说明Docker网关地址(172.17.0.1)
- 端口映射表标清 6099 必开 / 3001免费 / 9000按需
- send_url 指向 NapCat :6099
2026-05-04 19:06:15 +08:00

530 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# OpenClaw Bridge — QQ AI Reply Plugin
> 将 QQ 消息转发到 OpenClaw Gateway,由 AI agent 自动处理并回复。
> 本 README 面向 AI agent(OpenClaw 基础智能体),引导其完成全流程部署(NapCat → qqrebot → 插件 → agent)。
## 架构
```
QQ 用户 →→→ NapCat(Docker:6099)
│
│ HTTP POST(事件推送)
▼
qqrebot(HTTP Server :25580) ← 消息接收
│
├── 执行 openclaw_bridge 插件
│ │
│ │ HTTP POST /v1/chat/completions
│ ▼
│ OpenClaw Gateway(:18789)
│ │
│ ▼
│ qq-agent(AI 模型)
│ │
◄── 返回回复文本 ──┘
│
│ HTTP POST(send_private_msg / send_group_msg)
▼
NapCat(:6099) → 回复发送到 QQ
```
**关键通信链路(全是 HTTP,无 WebSocket):**
| 链路 | 方向 | 协议 | 端口 |
|---|---|---|---|
| NapCat → qqrebot | 事件推送 | HTTP POST | `qqrebot:25580` |
| 插件 → OpenClaw | AI 请求 | HTTP POST | `127.0.0.1:18789` |
| 插件 → NapCat | 发送回复 | HTTP POST | `napcat:6099` |
| 脚本 → NapCat | 发消息/管理 | HTTP POST | `napcat:6099` |
## 前提条件
| 组件 | 状态 | 由本仓库部署 |
|---|---|---|
| OpenClaw Gateway | 假设已运行 | ❌(由用户自行部署) |
| NapCat(Docker) | 需部署 | ✅ |
| qqrebot(消息接收器)| 需部署 | ✅ |
| openclaw_bridge 插件 | 需部署 | ✅ |
| qq-agent(AI agent) | 需创建 | ✅ |
| QQ 技能/脚本 | 需部署 | ✅ |
## 部署步骤(阅读此文档的 AI agent 请按以下顺序执行)
---
### 第1步:询问用户信息
在执行任何操作前,请 **向用户询问以下信息**,不要使用仓库中的占位符:
| 信息 | 说明 | 示例 |
|---|---|---|
| `ADMIN_QQ` | 管理员的 QQ 号(白名单使用) | `123456789` |
| `GATEWAY_TOKEN` | OpenClaw Gateway 的认证 Token | 读取 `~/.openclaw/openclaw.json` 的 `gateway.auth.token` |
| `NAP CAT_HOST` | NapCat 服务器地址(可含端口) | `127.0.0.1`(同机)或 `192.168.1.100:6099` |
| `QQREBOT_HOST` | qqrebot 服务器地址(NapCat 侧看到的) | `127.0.0.1`(同机)或 `172.17.0.1:25580`(Docker 宿主机) |
| `NEW_AGENT_ID` | 新 agent 的唯一 ID | `qq-agent` |
| `SHARED_DIR` | NapCat 与宿主机共享目录路径 | `/opt/napcat_shared` |
> `NAP CAT_HOST` 和 `QQREBOT_HOST` 可能不同:当 NapCat 和 qqrebot 运行在同一台机器上时,NapCat 用 Docker 内部地址访问宿主机 qqrebot(如 `172.17.0.1:25580`),而脚本用外部地址访问 NapCat(如 `127.0.0.1:6099`)。
---
### 第2步:通过 Docker 部署 NapCat
NapCat 是 QQ 协议实现,接收 QQ 消息并通过 **HTTP POST** 推送到 qqrebot。
#### 2.1 创建目录结构
```bash
# 共享文件目录(NapCat Docker 内发文件时读取)
SHARED_DIR="${SHARED_DIR:-/opt/napcat_shared}"
mkdir -p "${SHARED_DIR}"
# NapCat 配置目录 + QQ 登录数据持久化
mkdir -p /opt/napcat/config
mkdir -p /opt/napcat/qq_data
```
#### 2.2 启动 NapCat Docker 容器
```bash
docker run -d \
--name napcat \
--restart unless-stopped \
-p 6099:6099 \
-v /opt/napcat/config:/app/napcat/config \
-v /opt/napcat/qq_data:/app/.config/QQ \
-v "${SHARED_DIR}:/app/napcat/share" \
--dns=114.114.114.114 \
mlikiowa/napcat-docker:latest
```
端口说明:
| 端口 | 是否必开 | 用途 |
|---|---|---|
| `6099` | ✅ | OneBot HTTP API(脚本发消息/群管理/取数据都用这个端口) |
| `3001` | ❌ | WebSocket Server(本教程用 HTTP POST 推送,不需要) |
| `9000` | 按需 | WebUI 管理面板(首次扫码登录可临时用) |
如果机器防扫描严格,**只开 6099** 即可;WebUI 按需用完即关。
#### 2.3 首次登录配置
> NapCat 首次启动需要扫码登录 QQ 账号。登录数据持久化在 `/opt/napcat/qq_data`。
```bash
# 查看登录二维码(日志中会打印链接)
docker logs napcat 2>&1 | grep -o 'http[s]*://[^ ]*\.png'
# 或用浏览器打开 http://<服务器IP>:9000/webui 扫码登录
# 等待登录成功
docker logs napcat -f | grep "登录成功"
```
#### 2.4 配置事件推送(HTTP POST → qqrebot)
NapCat 需要将所有消息事件通过 HTTP POST 推送到 qqrebot(端口 `25580`)。
编辑 `/opt/napcat/config/onebot11.json`:
```json
{
"http": {
"enable": true,
"host": "0.0.0.0",
"port": 6099,
"enableHttpPost": false,
"enableHttpHeartbeat": false
},
"httpPost": [
{
"url": "http://${QQREBOT_HOST}/",
"secret": ""
}
],
"ws": {
"enable": false
},
"heartbeat": {
"enable": false
},
"enableLocalFile2Url": true
}
```
> **关键说明:**
> - `httpPost` 数组中的 URL 是 NapCat 向 qqrebot 推送消息事件的目标地址
> - 如果 NapCat 和 qqrebot 在**同一台宿主机上**,`url` 通常设置为 `http://172.17.0.1:25580/`(Docker 默认网关地址)
> - 如果**不同机器**,填 qqrebot 机器可达的真实 IP
> - `ws.enable = false` — 本教程不用 WebSocket
> - `http.enableHttpPost = false` — httpPost 由专门的 `httpPost` 数组控制
应用配置:
```bash
docker restart napcat
```
#### 2.5 验证 NapCat
```bash
# 验证 HTTP API 可访问
curl -s http://localhost:6099/get_version_info | python3 -m json.tool
# 预期输出:
# {"status": "ok", "data": {"app_name": "NapCat", ...}, ...}
```
---
### 第3步:部署 qqrebot(消息接收器)
qqrebot 是 HTTP 服务器,NapCat 将 QQ 消息 POST 到 qqrebot,qqrebot 加载插件处理。
#### 3.1 安装 qqrebot
从 [chatrebot1.0 release](https://jianfgit.xyz/jianf/chat_rebot-connect-with-onebot-standard-/src/tag/chatrebot1.0/) 下载:
```bash
wget https://jianfgit.xyz/jianf/chat_rebot-connect-with-onebot-standard-/archive/chatrebot1.0.tar.gz
tar xzf chatrebot1.0.tar.gz
mv chat_rebot-connect-with-onebot-standard- /opt/qqrebot
cd /opt/qqrebot
```
#### 3.2 配置
编辑 `config/config.toml`:
```toml
[app]
list_port = 25580
send_url = "http://${NAP CAT_HOST}:6099" # → 插件回复时调 NapCat HTTP API 用
[rebot]
id = ""
[plugins]
dir = ["plugins"]
```
> **`send_url`**:qqrebot 框架用它作为 NapCat HTTP API 的基础地址。插件中的 `ctx.group.url` 来自此值,后续所有 `send_private_msg` / `send_group_msg` 调用都走这个地址。如果 NapCat 和 qqrebot 同机,填 `http://127.0.0.1:6099`。
#### 3.3 创建 systemd 服务
```ini
# /etc/systemd/system/qqrebot.service
[Unit]
Description=QQ Robot
After=network.target docker.service
Requires=docker.service
[Service]
Type=simple
WorkingDirectory=/opt/qqrebot
ExecStart=/opt/qqrebot/run.sh
Restart=always
RestartSec=3
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
```
```bash
systemctl daemon-reload
systemctl enable --now qqrebot
```
---
### 第4步:安装 openclaw_bridge 插件
本仓库即 openclaw_bridge 插件的源码,需打包后部署到 qqrebot。
**打包(必须在目标主机上执行,因含 C 扩展):**
```bash
cd /path/to/chatrebot_aireply_plug
pip install -r requirements.txt
python3 package.py
```
**部署:**
```bash
cp dist/openclaw_bridge.zip /opt/qqrebot/plugins/
```
**创建插件配置 `/opt/qqrebot/config/openclawbridge/config.toml`:**
```toml
[openclaw]
gateway_url = "http://127.0.0.1:18789"
gateway_token = "${GATEWAY_TOKEN}"
allowed_sender = "${ADMIN_QQ}"
model = "openclaw/${NEW_AGENT_ID}"
agent_id = "${NEW_AGENT_ID}"
```
**重启 qqrebot 加载插件:**
```bash
systemctl restart qqrebot
```
**验证插件加载:**
```bash
journalctl -u qqrebot -f | grep OpenClawBridge
```
预期输出:
```
Config loaded: url=http://127.0.0.1:18789, allowed=123456789
```
---
### 第5步:创建新的 OpenClaw agent
在 `~/.openclaw/openclaw.json` 的 `agents.list` 中添加新 agent:
```bash
AGENT_ID="${NEW_AGENT_ID}"
AGENT_WORKSPACE="/home/program/${AGENT_ID}-workspace"
mkdir -p "${AGENT_WORKSPACE}/scripts"
mkdir -p "${AGENT_WORKSPACE}/skills"
mkdir -p "${AGENT_WORKSPACE}/self-workplace"
mkdir -p "${AGENT_WORKSPACE}/memory"
mkdir -p "${AGENT_WORKSPACE}/files"
```
添加 agent 配置项到 `agents.list`:
```json
{
"id": "${NEW_AGENT_ID}",
"name": "${NEW_AGENT_ID}",
"model": "kimi/kimi-for-coding",
"workspace": "/home/program/${NEW_AGENT_ID}-workspace"
}
```
> 通过 `GET /api/config/all` 获取当前配置,找到 `agents.list` 数组执行 push,然后 `POST /api/config/set`。或直接编辑 `~/.openclaw/openclaw.json` 后重启 Gateway。
---
### 第6步:部署脚本和 Skills 到新 agent 的 workspace
**复制脚本:**
```bash
cp -r /path/to/chatrebot_aireply_plug/scripts/* "${AGENT_WORKSPACE}/scripts/"
```
**复制 Skills:**
```bash
for SKILL in qq-messenger qq-management qq-resolver qq-napcat-extras mc-query nix-helper browser file-process; do
cp -r "/path/to/chatrebot_aireply_plug/skills/${SKILL}" "${AGENT_WORKSPACE}/skills/"
done
```
**替换占位符(关键!必须执行):**
```bash
cd "${AGENT_WORKSPACE}/scripts"
# NapCat HTTP API 地址(端口 6099,非 25570)
sed -i "s|YOUR_NAP CAT_HOST:25570|${NAP CAT_HOST}:6099|g" *.py
sed -i "s|YOUR_NAP CAT_HOST|${NAP CAT_HOST}:6099|g" *.py
sed -i "s|YOUR_NAPCAT_HOST:25570|${NAP CAT_HOST}:6099|g" *.py
sed -i "s|YOUR_NAPCAT_HOST|${NAP CAT_HOST}:6099|g" *.py
# 管理员 QQ
sed -i "s|YOUR_ADMIN_QQ|${ADMIN_QQ}|g" *.py
# Gateway Token
sed -i "s|YOUR_GATEWAY_TOKEN|${GATEWAY_TOKEN}|g" *.py
# 工作区路径
sed -i "s|YOUR_WORKSPACE_PATH|${AGENT_WORKSPACE}|g" *.py
# 共享目录
sed -i "s|YOUR_SHARED_DIR|${SHARED_DIR}|g" *.py
```
同样处理 `skills/` 目录下的 SKILL.md 文件。
---
### 第7步:重启 OpenClaw Gateway
```bash
openclaw gateway restart
```
确认新 agent 已加载:
```bash
openclaw config get agents.list
# 或 journalctl -u openclaw -f | grep "agent.${NEW_AGENT_ID}"
```
---
### 第8步:端到端验证
1. 在 QQ 上给机器人发消息
2. 检查 qqrebot 日志:`journalctl -u qqrebot -f | grep OpenClawBridge`
3. 检查 OpenClaw 日志:`journalctl -u openclaw -f`
4. 验证 agent 已回复
---
## 脚本适配说明
### 端口对照
| 组件 | go-cqhttp | NapCat(Docker) |
|---|---|---|
| HTTP API 端口 | `25570` | **6099** |
| WebSocket | `25570`(兼用) | 不启用(本教程) |
> 脚本中 `CQHTTP_URL = "http://YOUR_NAP CAT_HOST:25570"` 替换后变为 `http://<host>:6099`。
### 文件发送与共享目录
NapCat 运行在 Docker 内部,宿主机文件路径不能直接访问。解决方式:
```
宿主机 ${SHARED_DIR}/ ⇔ Docker volume → 容器内 /app/napcat/share/
```
| 脚本 | 关联 | 说明 |
|---|---|---|
| `qq_send_file.py` | 使用 `TARGET_DIR` | 发文件前复制到共享目录,NapCat 从 `/app/napcat/share/` 读取 |
| `qq_ocr_image.py` | 提到 NapCat 回退 | 只在本地 Tesseract 不可用时走 NapCat,此时需文件在共享目录 |
| `qq_get_file.py` | 无依赖 | NapCat 返回 base64 或 URL,自动下载,不依赖共享目录 |
| `qq_upload_group_file.py` | 无依赖 | 使用 base64:// 编码直接上传,不依赖共享目录 |
### 变量速查
| 占位符 | 替换值 | 出现位置 |
|---|---|---|
| `YOUR_NAP CAT_HOST:25570` | `${NAP CAT_HOST}:6099` | 所有脚本 |
| `YOUR_NAP CAT_HOST` | `${NAP CAT_HOST}:6099` | 所有脚本 |
| `YOUR_NAPCAT_HOST` | `${NAP CAT_HOST}:6099` | 部分脚本 |
| `YOUR_ADMIN_QQ` | `${ADMIN_QQ}` | 脚本 + SKILL.md |
| `YOUR_GATEWAY_TOKEN` | `${GATEWAY_TOKEN}` | 脚本 |
| `YOUR_SHARED_DIR` | `${SHARED_DIR}` | `qq_send_file.py`、`qq_ocr_image.py` |
| `YOUR_WORKSPACE_PATH` | `${AGENT_WORKSPACE}` | SKILL.md + 脚本 |
---
## 安全模块说明
部署完成后,新 agent 将具备以下安全能力(全部在 `src/process.py` 中实现):
### 高危词检测
内置 `HIGH_RISK_WORDS` 词库,覆盖以下类别:
| 类别 | 示例关键词 |
|---|---|
| 越狱/提示词攻击 | `ignore all instructions`、`forget previous` |
| 记忆操控 | `delete memory`、`forget everything` |
| 敏感信息泄漏 | `sudo password`、`api key` |
| 系统命令 | `cat /etc/passwd`、`rm -rf` |
**触发时行为:**
- 非管理员 → 自动拦截 + 上报管理员 + 该用户加入黑名单
- 管理员 → 记录日志 + 发送告警到 admin 私聊
### 管理员白名单
| 配置项 | 说明 |
|---|---|
| `allowed_sender` | 唯一的管理员 QQ 号 |
| 非管理员操作 | MC 指令过滤(`/` 开头消息跳过 AI 处理) |
### 消息过滤
- 纯媒体消息(无文字:纯图片/文件/视频)自动跳过
- 系统通知(`[系统通知]`、`[文件回执]`)自动跳过
- 非管理员发送的操作指令(`/` 开头)跳过 AI 处理
### 安全上报
当非管理员触发高危词时,插件自动通过 NapCat HTTP API 给 `allowed_sender` 发送告警(调用 `send_private_msg`)。
### 错误脱敏
所有 HTTP 响应体、异常详情不暴露给 QQ 用户,仅记录日志。
## 配置文件参考
| 配置项 | 必填 | 说明 |
|---|---|---|
| `gateway_url` | ✅ | OpenClaw Gateway 地址 |
| `gateway_token` | ✅ | Gateway 认证 Token |
| `allowed_sender` | ✅ | 管理员 QQ 号 |
| `model` | ✅ | Agent 模型 ID(格式:`openclaw/${AGENT_ID}`) |
| `agent_id` | ✅ | Agent ID(与 `agents.list` 一致) |
## 目录结构
```
chatrebot_aireply_plug/
├── config/
│ └── openclawbridge/
│ └── config.toml # 插件配置模板
├── src/
│ ├── process.py # 插件核心逻辑(含全部安全模块)
│ ├── config.toml # 本地测试配置
│ └── modules/
│ ├── plugin_modules.py # BasePlugin + MessageContext
│ └── user_module.py # User/Group 封装
├── scripts/ # ✅ 部署时复制到 agent workspace
│ ├── qq_send_msg.py # 发送消息(调 NapCat :6099)
│ ├── qq_send_file.py # 发送文件/图片
│ ├── qq_get_groups.py # 获取群列表
│ ├── qq_get_friends.py # 获取好友列表
│ ├── qq_group_manage.py # 群管理(踢/禁言/设管理)
│ └── ...
├── skills/ # ✅ 部署时复制到 agent skills/
│ ├── qq-messenger/SKILL.md
│ ├── qq-management/SKILL.md
│ ├── qq-resolver/SKILL.md
│ ├── qq-napcat-extras/SKILL.md
│ ├── mc-query/SKILL.md
│ └── ...
├── dependence.py
├── package.py
├── packup.sh / packup.bat
├── test.py
├── requirements.txt
└── README.md
```
## 自定义安全词库
编辑 `src/process.py` 中的 `HIGH_RISK_WORDS` 列表后重新打包部署重启:
```python
HIGH_RISK_WORDS = {
"prompt_injection": ["ignore all instructions", ...],
"memory_manipulation": ["delete memory", ...],
"info_leak": ["sudo password", ...],
"system_commands": ["cat /etc/passwd", ...],
}
```
## 许可证
MIT