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
This commit is contained in:
root
2026-05-04 19:06:15 +08:00
parent 2dbe121446
commit 5a69db8af9

266
README.md
View File

@ -6,29 +6,37 @@
## 架构
```
QQ 客户端 服务器
│ QQ 协议
NapCatDocker │ ← 第2步部署
OneBot HTTP
├── POST 消息 → qqrebot (:25580) ← 第3步部署
├── openclaw_bridge 插件
│ │
│ ▼
│ OpenClaw Gateway (:18789) ← 已有
│ │
│ ▼
新建的 qq-agent ← 第5步创建
│ │
◄── 回复/操作 ←─── qqrebot ◄─────┘
NapCat Docker 端口映射:
6099/tcp ← HTTP API脚本发消息/管理都走这个端口)
3001/tcp ← WebSocketqqrebot 内部使用这个通道)
9000/tcp ← WebUI 管理面板
QQ 用户 →→→ NapCatDocker:6099
HTTP POST事件推送
qqrebotHTTP Server :25580 ← 消息接收
├── 执行 openclaw_bridge 插件
│ │ HTTP POST /v1/chat/completions
│ ▼
OpenClaw Gateway:18789
│ │
│ ▼
│ qq-agentAI 模型)
│ │
◄── 返回回复文本 ──┘
│ HTTP POSTsend_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` |
## 前提条件
| 组件 | 状态 | 由本仓库部署 |
@ -52,24 +60,27 @@ NapCat Docker 端口映射:
|---|---|---|
| `ADMIN_QQ` | 管理员的 QQ 号(白名单使用) | `123456789` |
| `GATEWAY_TOKEN` | OpenClaw Gateway 的认证 Token | 读取 `~/.openclaw/openclaw.json``gateway.auth.token` |
| `NAP CAT_HOST` | 服务器 IPNapCat 所在机器) | `192.168.1.100` |
| `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 消息并通过 OneBot HTTP 协议转发给下游(qqrebot
NapCat 是 QQ 协议实现,接收 QQ 消息并通过 **HTTP POST** 推送到 qqrebot。
#### 2.1 创建目录结构
```bash
# 共享文件目录(用于发文件到 QQ
# 共享文件目录(NapCat Docker 内发文件时读取
SHARED_DIR="${SHARED_DIR:-/opt/napcat_shared}"
mkdir -p "${SHARED_DIR}"
# NapCat 配置目录
# NapCat 配置目录 + QQ 登录数据持久化
mkdir -p /opt/napcat/config
mkdir -p /opt/napcat/qq_data
```
@ -81,8 +92,6 @@ docker run -d \
--name napcat \
--restart unless-stopped \
-p 6099:6099 \
-p 3001:3001 \
-p 9000:9000 \
-v /opt/napcat/config:/app/napcat/config \
-v /opt/napcat/qq_data:/app/.config/QQ \
-v "${SHARED_DIR}:/app/napcat/share" \
@ -92,32 +101,34 @@ docker run -d \
端口说明:
| 端口 | 用途 |
|---|---|
| 6099 | OneBot HTTP API脚本发消息/管理 |
| 3001 | OneBot WebSocketqqrebot 接收消息用 |
| 9000 | WebUI 管理面板(首次本地扫码登录用) |
| 端口 | 是否必开 | 用途 |
|---|---|---|
| `6099` | ✅ | OneBot HTTP API脚本发消息/管理/取数据都用这个端口 |
| `3001` | ❌ | WebSocket Server本教程用 HTTP POST 推送,不需要 |
| `9000` | 按需 | WebUI 管理面板(首次扫码登录可临时用) |
如果机器防扫描严格,**只开 6099** 即可WebUI 按需用完即关。
#### 2.3 首次登录配置
> NapCat 首次启动需要扫码登录 QQ 账号。登录后自动持久化 `/opt/napcat/qq_data`。
> NapCat 首次启动需要扫码登录 QQ 账号。登录数据持久化 `/opt/napcat/qq_data`。
```bash
# 查看登录二维码
# 查看登录二维码(日志中会打印链接)
docker logs napcat 2>&1 | grep -o 'http[s]*://[^ ]*\.png'
# 或用浏览器打开 http://<服务器IP>:9000/webui/扫码登录
# 或用浏览器打开 http://<服务器IP>:9000/webui 扫码登录
# 等待登录成功
docker logs napcat -f | grep "登录成功"
```
#### 2.4 配置 OneBot HTTP 端点
#### 2.4 配置事件推送HTTP POST → qqrebot
登录成功后,通过 WebUI 或直接编辑配置文件配置 HTTP 上报地址:
NapCat 需要将所有消息事件通过 HTTP POST 推送到 qqrebot端口 `25580`)。
```bash
# 编辑 NapCat OneBot 配置
cat > /opt/napcat/config/onebot11.json << 'EOF'
编辑 `/opt/napcat/config/onebot11.json`
```json
{
"http": {
"enable": true,
@ -126,26 +137,34 @@ cat > /opt/napcat/config/onebot11.json << 'EOF'
"enableHttpPost": false,
"enableHttpHeartbeat": false
},
"httpPost": [
{
"url": "http://${QQREBOT_HOST}/",
"secret": ""
}
],
"ws": {
"enable": true,
"host": "0.0.0.0",
"port": 3001
},
"reverseWs": {
"enable": false
},
"heartbeat": {
"enable": true,
"interval": 30000
"enable": false
},
"enableLocalFile2Url": true
}
EOF
docker restart napcat
```
> **注意**NapCat 通过 `reverseWs` 或 WebSocket 推送消息给 qqrebot。本配置使用 WebSocket Server 模式qqrebot 作为客户端连接 `ws://napcat_host:3001`。
> **关键说明:**
> - `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
@ -161,33 +180,38 @@ curl -s http://localhost:6099/get_version_info | python3 -m json.tool
### 第3步部署 qqrebot消息接收器
从 [chatrebot1.0 release](https://jianfgit.xyz/jianf/chat_rebot-connect-with-onebot-standard-/src/tag/chatrebot1.0/) 下载 qqrebot 框架:
qqrebot 是 HTTP 服务器NapCat 将 QQ 消息 POST 到 qqrebotqqrebot 加载插件处理。
#### 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
```
**配置 `config/config.toml`**
#### 3.2 配置
编辑 `config/config.toml`
```toml
[app]
list_port = 25580
send_url = "http://${NAP CAT_HOST}:6099" # NapCat HTTP 端口 6099
send_url = "http://${NAP CAT_HOST}:6099" # → 插件回复时调 NapCat HTTP API 用
[rebot]
id = "" # 不需要 bot_id
id = ""
[plugins]
dir = ["plugins"]
```
**注意**NapCat HTTP API 端口是 `6099`(不是 go-cqhttp 的 `25570`),所有脚本中的 `CQHTTP_URL` 最终也要替换为 `http://${NAP CAT_HOST}:6099`
> **`send_url`**qqrebot 框架用它作为 NapCat HTTP API 的基础地址。插件中的 `ctx.group.url` 来自此值,后续所有 `send_private_msg` / `send_group_msg` 调用都走这个地址。如果 NapCat 和 qqrebot 同机,填 `http://127.0.0.1:6099`。
**创建 systemd 服务**
#### 3.3 创建 systemd 服务
```ini
# /etc/systemd/system/qqrebot.service
@ -220,25 +244,21 @@ systemctl enable --now qqrebot
本仓库即 openclaw_bridge 插件的源码,需打包后部署到 qqrebot。
**在目标机上执行打包(因含 C 扩展,必须在此机器上执行**
**打包(必须在目标机上执行因含 C 扩展):**
```bash
cd /path/to/chatrebot_aireply_plug
# 安装依赖
pip install -r requirements.txt
# 打包
python3 package.py
```
**将生成的 ZIP 复制到 qqrebot 插件目录**
**部署**
```bash
cp dist/openclaw_bridge.zip /opt/qqrebot/plugins/
```
**创建插件配置文件 `/opt/qqrebot/config/openclawbridge/config.toml`**
**创建插件配置 `/opt/qqrebot/config/openclawbridge/config.toml`**
```toml
[openclaw]
@ -255,7 +275,7 @@ agent_id = "${NEW_AGENT_ID}"
systemctl restart qqrebot
```
**验证插件加载:**
**验证插件加载:**
```bash
journalctl -u qqrebot -f | grep OpenClawBridge
@ -276,7 +296,6 @@ Config loaded: url=http://127.0.0.1:18789, allowed=123456789
AGENT_ID="${NEW_AGENT_ID}"
AGENT_WORKSPACE="/home/program/${AGENT_ID}-workspace"
# 创建 workspace 目录
mkdir -p "${AGENT_WORKSPACE}/scripts"
mkdir -p "${AGENT_WORKSPACE}/skills"
mkdir -p "${AGENT_WORKSPACE}/self-workplace"
@ -284,7 +303,7 @@ mkdir -p "${AGENT_WORKSPACE}/memory"
mkdir -p "${AGENT_WORKSPACE}/files"
```
添加 agent 配置项到 OpenClaw 的 `agents.list`
添加 agent 配置项到 `agents.list`
```json
{
@ -295,7 +314,7 @@ mkdir -p "${AGENT_WORKSPACE}/files"
}
```
> **注意**通过 `GET /api/config/all` 获取当前配置,找到 `agents.list` 数组push 上述对象,然后通过 `POST /api/config/set` 写入。或直接编辑 `~/.openclaw/openclaw.json` 文件后重启 Gateway。
> 通过 `GET /api/config/all` 获取当前配置,找到 `agents.list` 数组执行 push然后 `POST /api/config/set`。或直接编辑 `~/.openclaw/openclaw.json` 后重启 Gateway。
---
@ -315,35 +334,31 @@ for SKILL in qq-messenger qq-management qq-resolver qq-napcat-extras mc-query ni
done
```
**替换脚本中的占位符:**
**替换占位符(关键!必须执行)**
```bash
cd "${AGENT_WORKSPACE}/scripts"
# 替换 NapCat HTTP API 地址端口 6099
# 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
# 管理员 QQ
sed -i "s|YOUR_ADMIN_QQ|${ADMIN_QQ}|g" *.py
# 替换 Gateway Token
# Gateway Token
sed -i "s|YOUR_GATEWAY_TOKEN|${GATEWAY_TOKEN}|g" *.py
# 替换工作区路径
# 工作区路径
sed -i "s|YOUR_WORKSPACE_PATH|${AGENT_WORKSPACE}|g" *.py
# 替换共享目录Docker 挂载的 shared 目录)
# 共享目录
sed -i "s|YOUR_SHARED_DIR|${SHARED_DIR}|g" *.py
# 替换群 ID 占位符(可选:群 ID 通常按需传入,但 DEFAULT_GID 需用户指定)
# sed -i "s|YOUR_GROUP_ID|${DEFAULT_GROUP_ID}|g" *.py
# sed -i "s|YOUR_BOT_QQ|${BOT_QQ}|g" *.py
```
同样处理 `skills/` 目录下的 SKILL.md 文件中的 `YOUR_WORKSPACE_PATH``YOUR_ADMIN_QQ`
同样处理 `skills/` 目录下的 SKILL.md 文件。
---
@ -356,11 +371,8 @@ openclaw gateway restart
确认新 agent 已加载:
```bash
# 查看代理列表
openclaw config get agents.list
# 或在日志中确认
journalctl -u openclaw -f | grep "agent.${NEW_AGENT_ID}"
# 或 journalctl -u openclaw -f | grep "agent.${NEW_AGENT_ID}"
```
---
@ -374,59 +386,43 @@ journalctl -u openclaw -f | grep "agent.${NEW_AGENT_ID}"
---
## 脚本适配说明NapCat vs go-cqhttp
## 脚本适配说明
如果从 go-cqhttp 迁移到 NapCat或者混合使用以下脚本需要关注差异点
### 端口差异
### 端口对照
| 组件 | go-cqhttp | NapCatDocker |
|---|---|---|
| HTTP API 端口 | `25570` | **6099** |
| WebSocket 端口 | `25570` | **3001** |
| qqrebot 配置中 `send_url` | `http://host:25570` | `http://host:6099` |
| WebSocket | `25570`(兼用) | 不启用(本教程) |
> 所有脚本中 `CQHTTP_URL = "http://YOUR_NAP CAT_HOST:25570"` 替换时会自动改为 `6099`。
> 脚本中 `CQHTTP_URL = "http://YOUR_NAP CAT_HOST:25570"` 替换后变为 `http://<host>:6099`。
### 文件发送适配
### 文件发送与共享目录
#### 跨主机文件访问
NapCat 运行在 Docker 中,宿主机文件不能直接在 NapCat 内部访问。需要用 Docker volume 映射:
NapCat 运行在 Docker 内部,宿主机文件路径不能直接访问。解决方式:
```
宿主机 ${SHARED_DIR}/ ⇔ NapCat 容器内 /app/napcat/share/
宿主机 ${SHARED_DIR}/ ⇔ Docker volume → 容器内 /app/napcat/share/
```
受影响的脚本:
| 脚本 | 依赖 | 影响说明 |
| 脚本 | 关联 | 说明 |
|---|---|---|
| `qq_send_file.py` | 文件先复制到 `TARGET_DIR`,再由 NapCat 读取 | 需确保 `TARGET_DIR` = `SHARED_DIR` |
| `qq_ocr_image.py` | NapCat 回退时需文件在共享目录 | 需复制到 `SHARED_DIR` |
| `qq_get_file.py` | NapCat 返回文件 URL 或 base64 | 自动处理,不需要共享目录 |
| `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:// 编码直接上传,不依赖共享目录 |
#### 文件上传方式对比
| 方式 | 支持 NapCat | 说明 |
|---|---|---|
| `upload_group_file` API | ✅ | NapCat 原生支持,底层走共享目录 |
| `base64://` 方式 | ✅ | 小文件(<10MB直接编码嵌入无需共享目录 |
| 文件路径引用 | | 文件路径需在 NapCat 容器内可访问 |
`qq_upload_group_file.py` 使用 base64 方式上传可以跨主机工作不依赖共享目录但大文件可能有性能问题
### 脚本变量速查
### 变量速查
| 占位符 | 替换值 | 出现位置 |
|---|---|---|
| `YOUR_NAP CAT_HOST:25570` | `${NAP CAT_HOST}:6099` | 所有 py 脚本 |
| `YOUR_NAP CAT_HOST` | `${NAP CAT_HOST}:6099` | 所有 py 脚本 |
| `YOUR_NAPCAT_HOST` | `${NAP CAT_HOST}:6099` | 部分 py 脚本 |
| `YOUR_ADMIN_QQ` | `${ADMIN_QQ}` | py 脚本 + SKILL.md |
| `YOUR_GATEWAY_TOKEN` | `${GATEWAY_TOKEN}` | py 脚本 |
| `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 + py 脚本 |
| `YOUR_WORKSPACE_PATH` | `${AGENT_WORKSPACE}` | SKILL.md + 脚本 |
---
@ -464,9 +460,7 @@ NapCat 运行在 Docker 中,宿主机文件不能直接在 NapCat 内部访问
### 安全上报
当非管理员触发高危词时插件自动
1. 通过 OneBot API `allowed_sender` 发送告警消息
2. 告警内容用户 QQ所在群触发的原文摘要
当非管理员触发高危词时,插件自动通过 NapCat HTTP API 给 `allowed_sender` 发送告警(调用 `send_private_msg`)。
### 错误脱敏
@ -477,10 +471,10 @@ NapCat 运行在 Docker 中,宿主机文件不能直接在 NapCat 内部访问
| 配置项 | 必填 | 说明 |
|---|---|---|
| `gateway_url` | ✅ | OpenClaw Gateway 地址 |
| `gateway_token` | | Gateway 认证 Token从用户处获取 |
| `allowed_sender` | | 管理员 QQ 从用户处获取 |
| `gateway_token` | ✅ | Gateway 认证 Token |
| `allowed_sender` | ✅ | 管理员 QQ 号 |
| `model` | ✅ | Agent 模型 ID格式`openclaw/${AGENT_ID}` |
| `agent_id` | | Agent ID `agents.list` 中一致 |
| `agent_id` | ✅ | Agent ID `agents.list` 一致) |
## 目录结构
@ -496,12 +490,12 @@ chatrebot_aireply_plug/
│ ├── plugin_modules.py # BasePlugin + MessageContext
│ └── user_module.py # User/Group 封装
├── scripts/ # ✅ 部署时复制到 agent workspace
│ ├── qq_send_msg.py # 发送消息(端口 6099
│ ├── qq_send_file.py # 发送文件/图片(共享目录映射)
│ ├── 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
@ -509,17 +503,17 @@ chatrebot_aireply_plug/
│ ├── qq-napcat-extras/SKILL.md
│ ├── mc-query/SKILL.md
│ └── ...
├── dependence.py # 依赖安装工具
├── package.py # ZIP 打包器
├── packup.sh / packup.bat # 一键打包脚本
├── test.py # 本地测试
├── requirements.txt # Python 依赖
└── README.md # 本文件
├── dependence.py
├── package.py
├── packup.sh / packup.bat
├── test.py
├── requirements.txt
└── README.md
```
## 自定义安全词库
编辑 `src/process.py` 中的 `HIGH_RISK_WORDS` 列表
编辑 `src/process.py` 中的 `HIGH_RISK_WORDS` 列表后重新打包部署重启:
```python
HIGH_RISK_WORDS = {
@ -530,8 +524,6 @@ HIGH_RISK_WORDS = {
}
```
添加后重新打包部署重启 qqrebot
## 许可证
MIT