Files
chatrebot_aireply_plug/README.md
root 2dbe121446 docs: 增加NapCat Docker部署 + 脚本适配说明
- NapCat Docker 部署:目录创建、容器启动、首次扫码登录、OneBot配置
- 端口映射表:6099(HTTP) / 3001(WS) / 9000(WebUI)
- 脚本适配说明表:NapCat vs go-cqhttp 差异、文件发送适配、变量速查
- 前提条件改为 NapCat 由本仓库部署
- 架构图标注端口号
2026-05-04 18:59:02 +08:00

538 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 客户端 服务器
│ │
│ QQ 协议 │
▼ │
NapCat(Docker) │ ← 第2步部署
│ OneBot HTTP │
├── POST 消息 → qqrebot (:25580) ← 第3步部署
│ ├── openclaw_bridge 插件
│ │ │
│ │ ▼
│ │ OpenClaw Gateway (:18789) ← 已有
│ │ │
│ │ ▼
│ │ 新建的 qq-agent ← 第5步创建
│ │ │
◄── 回复/操作 ←─── qqrebot ◄─────┘
NapCat Docker 端口映射:
6099/tcp ← HTTP API(脚本发消息/管理都走这个端口)
3001/tcp ← WebSocket(qqrebot 内部使用这个通道)
9000/tcp ← WebUI 管理面板
```
## 前提条件
| 组件 | 状态 | 由本仓库部署 |
|---|---|---|
| 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` | 服务器 IP(NapCat 所在机器) | `192.168.1.100` |
| `NEW_AGENT_ID` | 新 agent 的唯一 ID | `qq-agent` |
| `SHARED_DIR` | NapCat 与宿主机共享目录路径 | `/opt/napcat_shared` |
---
### 第2步:通过 Docker 部署 NapCat
NapCat 接收 QQ 消息并通过 OneBot HTTP 协议转发给下游(qqrebot)。
#### 2.1 创建目录结构
```bash
# 共享文件目录(用于发文件到 QQ)
SHARED_DIR="${SHARED_DIR:-/opt/napcat_shared}"
mkdir -p "${SHARED_DIR}"
# NapCat 配置目录
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 \
-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" \
--dns=114.114.114.114 \
mlikiowa/napcat-docker:latest
```
端口说明:
| 端口 | 用途 |
|---|---|
| 6099 | OneBot HTTP API(脚本发消息/管理用) |
| 3001 | OneBot WebSocket(qqrebot 接收消息用) |
| 9000 | 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 配置 OneBot HTTP 端点
登录成功后,通过 WebUI 或直接编辑配置文件配置 HTTP 上报地址:
```bash
# 编辑 NapCat OneBot 配置
cat > /opt/napcat/config/onebot11.json << 'EOF'
{
"http": {
"enable": true,
"host": "0.0.0.0",
"port": 6099,
"enableHttpPost": false,
"enableHttpHeartbeat": false
},
"ws": {
"enable": true,
"host": "0.0.0.0",
"port": 3001
},
"reverseWs": {
"enable": false
},
"heartbeat": {
"enable": true,
"interval": 30000
},
"enableLocalFile2Url": true
}
EOF
docker restart napcat
```
> **注意**:NapCat 通过 `reverseWs` 或 WebSocket 推送消息给 qqrebot。本配置使用 WebSocket Server 模式,qqrebot 作为客户端连接 `ws://napcat_host:3001`。
#### 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(消息接收器)
从 [chatrebot1.0 release](https://jianfgit.xyz/jianf/chat_rebot-connect-with-onebot-standard-/src/tag/chatrebot1.0/) 下载 qqrebot 框架:
```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`:**
```toml
[app]
list_port = 25580
send_url = "http://${NAP CAT_HOST}:6099" # NapCat HTTP 端口 6099
[rebot]
id = "" # 不需要 bot_id
[plugins]
dir = ["plugins"]
```
**注意**:NapCat 的 HTTP API 端口是 `6099`(不是 go-cqhttp 的 `25570`),所有脚本中的 `CQHTTP_URL` 最终也要替换为 `http://${NAP CAT_HOST}:6099`。
**创建 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
```
**将生成的 ZIP 复制到 qqrebot 插件目录:**
```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"
# 创建 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 配置项到 OpenClaw 的 `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
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
# 替换共享目录(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`。
---
### 第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 已回复
---
## 脚本适配说明(NapCat vs go-cqhttp)
如果从 go-cqhttp 迁移到 NapCat,或者混合使用,以下脚本需要关注差异点:
### 端口差异
| 组件 | go-cqhttp | NapCat(Docker) |
|---|---|---|
| HTTP API 端口 | `25570` | **6099** |
| WebSocket 端口 | `25570` | **3001** |
| qqrebot 配置中 `send_url` | `http://host:25570` | `http://host:6099` |
> 所有脚本中的 `CQHTTP_URL = "http://YOUR_NAP CAT_HOST:25570"` 在替换时会自动改为 `6099`。
### 文件发送适配
#### 跨主机文件访问
NapCat 运行在 Docker 中,宿主机文件不能直接在 NapCat 内部访问。需要用 Docker volume 映射:
```
宿主机 ${SHARED_DIR}/ ⇔ NapCat 容器内 /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 | 自动处理,不需要共享目录 |
#### 文件上传方式对比
| 方式 | 支持 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_SHARED_DIR` | `${SHARED_DIR}` | `qq_send_file.py`、`qq_ocr_image.py` |
| `YOUR_WORKSPACE_PATH` | `${AGENT_WORKSPACE}` | SKILL.md + py 脚本 |
---
## 安全模块说明
部署完成后,新 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 处理
### 安全上报
当非管理员触发高危词时,插件自动:
1. 通过 OneBot API 给 `allowed_sender` 发送告警消息
2. 告警内容:用户 QQ、所在群、触发的原文摘要
### 错误脱敏
所有 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 # 发送消息(端口 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 # ZIP 打包器
├── packup.sh / packup.bat # 一键打包脚本
├── test.py # 本地测试
├── requirements.txt # Python 依赖
└── 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", ...],
}
```
添加后重新打包、部署、重启 qqrebot。
## 许可证
MIT