- 移除NAPCAT_HOST/QQREBOT_HOST/NEW_AGENT_ID/SHARED_DIR 的询问 - 全部使用默认值:qq-agent, 127.0.0.1, 172.17.0.1:25580, /opt/napcat_shared - GATEWAY_TOKEN 自动从 ~/.openclaw/openclaw.json 读取 - 仅保留 ADMIN_QQ 和(自动读取失败时的)GATEWAY_TOKEN 两个询问项 - 跨机部署场景留注释说明
663 lines
19 KiB
Markdown
663 lines
19 KiB
Markdown
# 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步:环境自动检测 + 询问关键信息
|
||
|
||
本步骤将自动推导绝大多数配置,**只需向用户确认两个不可推导的值**。
|
||
|
||
#### 1.1 设置默认值(agent 自动执行)
|
||
|
||
```bash
|
||
# ─── 可自动推导的变量,全部使用默认值 ───
|
||
|
||
# Agent 唯一标识(默认 qq-agent,用户可改但通常不需要)
|
||
NEW_AGENT_ID="${NEW_AGENT_ID:-qq-agent}"
|
||
AGENT_WORKSPACE="/home/program/${NEW_AGENT_ID}-workspace"
|
||
|
||
# 共享目录路径
|
||
SHARED_DIR="${SHARED_DIR:-/opt/napcat_shared}"
|
||
|
||
# NapCat HTTP API 地址(同机部署走 127.0.0.1)
|
||
NAP CAT_HOST="127.0.0.1"
|
||
|
||
# 从 NapCat Docker 容器角度看到的 qqrebot 地址
|
||
# 同机部署时 NapCat 通过 Docker 网关访问宿主机
|
||
QQREBOT_HOST="172.17.0.1:25580"
|
||
|
||
# Gateway Token:自动从本机 OpenClaw 配置文件读取
|
||
GATEWAY_TOKEN=$(python3 -c "
|
||
import json
|
||
with open('$HOME/.openclaw/openclaw.json') as f:
|
||
cfg = json.load(f)
|
||
print(cfg.get('gateway', {}).get('auth', {}).get('token', ''))
|
||
" 2>/dev/null)
|
||
```
|
||
|
||
> 注意:`NAP CAT_HOST` 是**不含端口**的纯 IP/域名,后面所有用到 `send_url` 的地方拼入端口 `:6099`。
|
||
> `QQREBOT_HOST` 带端口 `:25580`,用于 onebot11.json 的 `httpPost.url`。
|
||
|
||
#### 1.2 向用户确认
|
||
|
||
只有以下两项无法自动推导,agent 需向用户询问:
|
||
|
||
```bash
|
||
# 向用户提问示例:
|
||
# "主人,我需要以下信息来完成部署:
|
||
# 1. ADMIN_QQ — 你的管理员 QQ 号(用于白名单和安全上报)
|
||
# 2. GATEWAY_TOKEN — 如上面自动读取的为空,请提供"
|
||
```
|
||
|
||
| 变量 | 必须 | 说明 |
|
||
|---|---|---|
|
||
| `ADMIN_QQ` | ✅ | 管理员 QQ 号,用于白名单和安全告警上报 |
|
||
| `GATEWAY_TOKEN` | 看情况 | 自动读取失败时(空值)才需要用户提供 |
|
||
|
||
> 其余变量(`NEW_AGENT_ID`、`SHARED_DIR`、`NAP CAT_HOST`、`QQREBOT_HOST`)全部使用默认值即可,**无需用户确认**。仅在跨机部署(NapCat 和 OpenClaw 不在同一台机器)时需要用户指定 `NAP CAT_HOST`。
|
||
|
||
#### 1.3 应用变量
|
||
|
||
```bash
|
||
# 确认 ADMIN_QQ
|
||
if [ -z "$ADMIN_QQ" ]; then
|
||
echo "请提供 ADMIN_QQ"
|
||
exit 1
|
||
fi
|
||
|
||
# 确认 GATEWAY_TOKEN 非空
|
||
if [ -z "$GATEWAY_TOKEN" ]; then
|
||
echo "自动读取 GATEWAY_TOKEN 失败,请提供"
|
||
exit 1
|
||
fi
|
||
|
||
export ADMIN_QQ NEW_AGENT_ID AGENT_WORKSPACE SHARED_DIR NAP_CAT_HOST QQREBOT_HOST GATEWAY_TOKEN
|
||
echo "环境变量已就绪:ADMIN_QQ=$ADMIN_QQ, AGENT=$NEW_AGENT_ID, NAPCAT=$NAP CAT_HOST"
|
||
```
|
||
|
||
---
|
||
|
||
### 第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步:获取源码并部署到 agent 的 workspace
|
||
|
||
> agent 需要在目标服务器上获取 chatrebot_aireply_plug 的 `scripts/`(26 个脚本)和 `skills/`(8 个 skill)目录。
|
||
|
||
#### 6.1 在目标服务器上克隆仓库
|
||
|
||
```bash
|
||
# 方案 A:git clone
|
||
git clone https://jianfgit.xyz/jianf/chatrebot_aireply_plug.git /opt/chatrebot_aireply_plug
|
||
|
||
# 方案 B:本机已有 repo,直接复制
|
||
# cp -r /home/program/pm-workspace /opt/chatrebot_aireply_plug
|
||
```
|
||
|
||
后续步骤假设源码解压到 `/opt/chatrebot_aireply_plug`。
|
||
|
||
#### 6.2 复制脚本
|
||
|
||
```bash
|
||
cp -r /opt/chatrebot_aireply_plug/scripts/* "${AGENT_WORKSPACE}/scripts/"
|
||
```
|
||
|
||
脚本清单(26 个),按功能分组:
|
||
|
||
| 分组 | 脚本 | 用途 |
|
||
|---|---|---|
|
||
| **QQ 消息** | `qq_send_msg.py` | 发送文本消息 |
|
||
| | `qq_send_file.py` | 发送文件/图片 |
|
||
| | `qq_upload_group_file.py` | base64 直接上传群文件 |
|
||
| | `qq_send_like.py` | 点赞 |
|
||
| | `qq_ocr_image.py` | 图片 OCR 识别 |
|
||
| **QQ 查询** | `qq_get_groups.py` | 获取群列表 |
|
||
| | `qq_get_friends.py` | 获取好友列表 |
|
||
| | `qq_get_group_files.py` | 获取群文件列表 |
|
||
| | `qq_get_file.py` | 下载文件 |
|
||
| | `qq_get_history.py` | 拉取历史消息 |
|
||
| | `qq_resolve_name.py` | QQ号/群号 ↔ 可读名称 |
|
||
| **QQ 管理** | `qq_group_action.py` | 退群、接受/拒绝群邀请 |
|
||
| | `qq_group_manage.py` | 群成员管理(踢/禁言等) |
|
||
| | `qq_friend_action.py` | 删好友、同意/拒绝好友请求 |
|
||
| **MC 服务器** | `mc_query.py` | 服务器状态查询 |
|
||
| | `mc_status.py` | 状态(简化版) |
|
||
| | `mc_players.py` | 玩家信息 |
|
||
| | `mc_world.py` | 世界详情 |
|
||
| | `mc_rcon.py` | 远程执行 RCON 命令 |
|
||
| | `mc_clear_items.py` | 清理掉落物 |
|
||
| | `mc_config.py` | 服务器配置管理 |
|
||
| **工具** | `browse.py` | 网页浏览/截图 |
|
||
| | `file_store_api.py` | 文件存储 API |
|
||
| | `ask_nix.py` | 向 ops-manager 求助 |
|
||
| | `qq_video_download.py` | 视频下载 |
|
||
| | `__init__.py` | 包初始化 |
|
||
|
||
#### 6.3 复制 Skills
|
||
|
||
Skills 是 agent 的能力描述文件(`SKILL.md`),每个 skill 一个子目录,agent 启动时会加载:
|
||
|
||
```bash
|
||
for SKILL in qq-messenger qq-management qq-resolver qq-napcat-extras mc-query nix-helper browser file-process; do
|
||
cp -r "/opt/chatrebot_aireply_plug/skills/${SKILL}" "${AGENT_WORKSPACE}/skills/"
|
||
done
|
||
```
|
||
|
||
> Skills 中的 SKILL.md 通过 `YOUR_WORKSPACE_PATH/scripts/xxx.py` 引用脚本路径。
|
||
> agent 执行 `subprocess.run` 时,实际调用的是 `${AGENT_WORKSPACE}/scripts/` 下的脚本。
|
||
|
||
#### 6.4 替换占位符(关键!必须执行)
|
||
|
||
**替换脚本占位符:**
|
||
|
||
```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
|
||
|
||
# 共享目录
|
||
sed -i "s|YOUR_SHARED_DIR|${SHARED_DIR}|g" *.py
|
||
```
|
||
|
||
**替换 Skills 占位符:**
|
||
|
||
```bash
|
||
cd "${AGENT_WORKSPACE}/skills"
|
||
|
||
for f in */SKILL.md; do
|
||
sed -i "s|YOUR_WORKSPACE_PATH|${AGENT_WORKSPACE}|g" "$f"
|
||
sed -i "s|YOUR_ADMIN_QQ|${ADMIN_QQ}|g" "$f"
|
||
done
|
||
```
|
||
|
||
> ⚠️ Skills 的替换很关键:如果漏掉,agent 调脚本时会指向不存在的旧路径。
|
||
|
||
#### 6.5 验证完整性
|
||
|
||
```bash
|
||
# 脚本数量
|
||
echo "scripts: $(ls "${AGENT_WORKSPACE}/scripts/" | wc -l) 个"
|
||
# 确认无残留占位符
|
||
if grep -r "YOUR_ADMIN_QQ\|YOUR_WORKSPACE_PATH" "${AGENT_WORKSPACE}/"; then
|
||
echo "⚠️ 还有未替换的占位符!"
|
||
else
|
||
echo "✅ 占位符全部替换完毕"
|
||
fi
|
||
```
|
||
|
||
---
|
||
|
||
### 第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
|