Files
chatrebot_aireply_plug/README.md
root 42b5e022e1 feat: AGENT_NAME 占位符 + Step 6.2 自动获取 QQ 昵称
- AGENTS.md/SOUL.md/IDENTITY.md 中 'the Real' → AGENT_NAME 占位符
- Step 6.2 新增 NapCat /get_login_info 接口自动获取登录 QQ 昵称
- 获取失败时回退到 ADMIN_NAME
- sed 替换新增 AGENT_NAME 占位符替换
- config/agent-templates/README.md 同步更新
2026-05-04 20:32:24 +08:00

832 lines
24 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 agentOpenClaw 基础智能体引导其完成全流程部署NapCat → qqrebot → 插件 → agent
## 架构
```
QQ 用户 →→→ NapCatDocker
│ HTTP POST事件推送:6097→qqrebot:25580
qqrebotHTTP Server :25580 ← 消息接收
├── 执行 openclaw_bridge 插件
│ │
│ │ HTTP POST /v1/chat/completions
│ ▼
│ OpenClaw Gateway:18789
│ │
│ ▼
│ qq-agentAI 模型)
│ │
◄── 返回回复文本 ──┘
│ HTTP POSTsend_private_msg / send_group_msg
NapCatDocker:6097→ 回复发送到 QQ
```
**关键通信链路(全是 HTTP无 WebSocket**
| 链路 | 方向 | 协议 | 地址 |
|---|---|---|---|
| NapCat → qqrebot | 事件推送 | HTTP POST | `http://172.17.0.1:25580/` |
| 插件 → OpenClaw | AI 请求 | HTTP POST | `127.0.0.1:18789` |
| 插件 → NapCat | 发送回复 | HTTP POST | `127.0.0.1:6097` |
| 脚本 → NapCat | 发消息/管理 | HTTP POST | `127.0.0.1:6097` |
## 前提条件
| 组件 | 状态 | 由本仓库部署 |
|---|---|---|
| OpenClaw Gateway | 假设已运行 | ❌(由用户自行部署) |
| NapCatDocker | 需部署 | ✅ |
| qqrebot消息接收器| 需部署 | ✅ |
| openclaw_bridge 插件 | 需部署 | ✅ |
| qq-agentAI agent | 需创建 | ✅ |
| QQ 技能/脚本 | 需部署 | ✅ |
## 部署步骤(阅读此文档的 AI agent 请按以下顺序执行)
> ⚠️ **关于变量持久化:** 以下每个步骤中的 bash 代码块可能在独立 shell 中执行。
> agent 应**将变量保存到文件**以便跨步骤使用,而不是依赖 `export` 在当前 shell 的生存期。
> 建议策略Step 1 执行后,将导出的变量写入 `/tmp/env_vars.sh`
> 后续每个 bash 块开头先 `source /tmp/env_vars.sh` 恢复环境。
---
### 第1步环境自动检测 + 询问关键信息
本步骤将自动推导绝大多数配置,**只需向用户确认两个不可推导的值**。
#### 1.0 前置依赖检查
agent 执行以下检查,缺少即自动安装:
```bash
# ⚠️ 本机如果缺少 apt-get如 Alpine请自行替换为 apk
# 本教程以 Debian/Ubuntu 系为例
MISSING=""
for cmd in git wget docker python3 curl tar; do
command -v $cmd &>/dev/null || MISSING="$MISSING $cmd"
done
if [ -n "$MISSING" ]; then
echo "❌ 缺少命令:$MISSING"
echo "请安装后重试apt-get install -y$MISSING"
exit 1
fi
# Docker daemon 检查
if ! docker info &>/dev/null; then
echo "❌ Docker 未运行或权限不足"
echo " 请确保 Docker 已安装且当前用户有 docker 组权限"
exit 1
fi
# python3-venv
if ! python3 -m venv --help &>/dev/null; then
apt-get update && apt-get install -y python3-venv
fi
echo "✅ 所有前置依赖已就绪"
```
#### 1.1 设置默认值 + 持久化到文件
```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
NAPCAT_HOST="127.0.0.1"
# OneBot HTTP API 端口(与 WebUI 端口 6099 不同)
NAPCAT_API_PORT="${NAPCAT_API_PORT:-6097}"
# 从 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)
# ─── 持久化到文件,供后续步骤使用 ───
cat > /tmp/env_vars.sh << EOF
NEW_AGENT_ID='${NEW_AGENT_ID}'
AGENT_WORKSPACE='${AGENT_WORKSPACE}'
SHARED_DIR='${SHARED_DIR}'
NAPCAT_HOST='${NAPCAT_HOST}'
NAPCAT_API_PORT='${NAPCAT_API_PORT}'
QQREBOT_HOST='${QQREBOT_HOST}'
GATEWAY_TOKEN='${GATEWAY_TOKEN}'
EOF
echo "变量已写入 /tmp/env_vars.sh后续步骤请先 source 该文件"
```
> 持久化文件使用 **无引号 heredoc**`<< EOF`bash 在 Step 1.1 执行时即展开 `${}` 变量。
> 后续步骤每次执行 bash 代码块前,先 `source /tmp/env_vars.sh` 恢复环境。
#### 1.2 向用户确认
只有以下两项无法自动推导agent 需向用户询问:
| 变量 | 必须 | 说明 |
|---|---|---|
| `ADMIN_QQ` | ✅ | 管理员 QQ 号,用于白名单和安全告警上报 |
| `GATEWAY_TOKEN` | 看情况 | 自动读取失败时(空值)才需要用户提供 |
> 其余变量(`NEW_AGENT_ID`、`SHARED_DIR`、`NAPCAT_HOST`、`NAPCAT_API_PORT`、`QQREBOT_HOST`)全部使用默认值即可。仅在跨机部署时需要用户调整 `NAPCAT_HOST` 或 `NAPCAT_API_PORT`。
#### 1.3 获取必填值并持久化
```bash
# 用户已提供 ADMIN_QQ由 agent 通过询问获得)
# 将该值追加到持久化变量文件
source /tmp/env_vars.sh
if [ -z "$ADMIN_QQ" ]; then
echo "❌ ADMIN_QQ 为空,请提供"
exit 1
fi
if [ -z "$GATEWAY_TOKEN" ]; then
echo "❌ GATEWAY_TOKEN 为空,请提供"
exit 1
fi
cat >> /tmp/env_vars.sh << EOF
ADMIN_QQ='${ADMIN_QQ}'
EOF
echo "✅ 变量全部就绪ADMIN_QQ=$ADMIN_QQ, AGENT=$NEW_AGENT_ID"
```
> 之后每一步 bash 代码块,第一条命令都应是 `source /tmp/env_vars.sh`。
---
### 第2步通过 Docker 部署 NapCat
NapCat 是 QQ 协议实现,接收 QQ 消息并通过 **HTTP POST** 推送到 qqrebot。
#### 2.1 端口说明
| 端口 | 是否必开 | 用途 |
|---|---|---|
| `6097` | ✅ | OneBot HTTP API脚本发消息/群管理/取数据都用此端口) |
| `6099` | ✅ | WebUI 管理面板NapCat 默认占用,不能与 API 共用) |
| `3001` | ❌ | WebSocket Server本教程用 HTTP POST不启用 |
> NapCat v4 的 WebUI 默认绑定端口 6099。OneBot HTTP API 需要独立端口(本教程使用 6097
> WebUI 用于扫码登录和管理界面,首次部署时需保持开启;生产环境可关闭或将 WebUI 绑定到 `127.0.0.1`。
#### 2.2 创建目录结构
```bash
source /tmp/env_vars.sh
mkdir -p "${SHARED_DIR}"
mkdir -p /opt/napcat/config
mkdir -p /opt/napcat/qq_data
```
#### 2.3 创建 onebot11.json 配置
> ⚠️ onebot11.json 默认不存在需手动创建。NapCat v4 使用 `network` 配置格式(非旧版 `http{} ws{}` 格式)。
```bash
source /tmp/env_vars.sh
cat > /opt/napcat/config/onebot11.json << ONEBOTEOF
{
"network": {
"httpServers": [
{
"name": "http-server",
"enable": true,
"host": "0.0.0.0",
"port": 6097,
"token": "",
"enableCors": true,
"debug": false
}
],
"httpClients": [
{
"name": "http-post",
"enable": true,
"url": "http://${QQREBOT_HOST}/",
"messagePostFormat": "array",
"reportSelfMessage": false,
"token": "",
"debug": false
}
],
"websocketServers": [],
"websocketClients": []
},
"musicSignUrl": "",
"enableLocalFile2Url": true,
"parseMultMsg": false
}
ONEBOTEOF
```
> `httpServers`OneBot HTTP API脚本通过此端口发送消息/管理群组。
> `httpClients`NapCat 将消息事件通过 HTTP POST 推送到 qqrebot。
> `httpClients[0].url` 使用 `${QQREBOT_HOST}`,因 heredoc 无引号bash 自动展开(同机部署时为 `172.17.0.1:25580`)。
**验证:**
```bash
source /tmp/env_vars.sh
cat /opt/napcat/config/onebot11.json | grep -o 'http://[^"]*'
# 预期http://172.17.0.1:25580/
```
#### 2.4 启动 NapCat Docker 容器
```bash
source /tmp/env_vars.sh
docker run -d \
--name napcat \
--restart unless-stopped \
-p 6097:6097 \
-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
```
> 必须同时暴露 `6097`OneBot API和 `6099`WebUI缺一不可。
#### 2.5 QQ 登录(扫码)— ⚠️ 需要人工介入
> ⚠️ **OneBot HTTP API 在 QQ 登录成功之前不会启动!**
> **这一步无法由 AI agent 自动完成,必须暂停并请用户操作。**
>
> agent 行为:打印二维码链接/URL 后**等待用户确认登录成功**,再继续后续步骤。
```bash
# 1) 获取二维码 URL打印给用户
docker logs napcat 2>&1 | grep -o 'http[s]*://[^ ]*\.png'
# 2) 或者告诉用户打开 WebUI
echo ""
echo "=========================================="
echo " 请在浏览器打开以下地址扫码登录 QQ"
echo " http://<服务器IP>:6099/webui"
echo "=========================================="
echo ""
# 3) 💡 agent 应在此处暂停并询问用户是否已登录
# (可选:自动等待登录成功日志)
echo "等待登录成功agent 请等待用户确认后继续)"
```
**验证 HTTP API 可访问:**
```bash
# 仅在用户确认登录后可执行
curl -s http://localhost:6097/get_version_info | python3 -m json.tool
# 预期:{"status": "ok", "data": {"app_name": "NapCat", ...}, ...}
```
---
### 第3步克隆本仓库确保源码可在后续步骤使用
> ⚠️ **顺序说明:** 本步提前于"部署 qqrebot"和"打包插件",因为后两者都需要本仓库的源码。
> 原序 Step 6.1 的逻辑移动到此。
```bash
source /tmp/env_vars.sh
# 确保 git 可用
command -v git &>/dev/null || { apt-get update && apt-get install -y git; }
# 克隆本仓库
if [ ! -d /opt/chatrebot_aireply_plug ]; then
git clone https://jianfgit.xyz/jianf/chatrebot_aireply_plug.git /opt/chatrebot_aireply_plug
else
echo "/opt/chatrebot_aireply_plug 已存在,跳过 clone"
fi
ls /opt/chatrebot_aireply_plug/README.md
```
> 后续步骤使用 `/opt/chatrebot_aireply_plug` 作为仓库根目录。
---
### 第4步部署 qqrebot消息接收器
qqrebot 是 HTTP 服务器NapCat 将 QQ 消息 POST 到 qqrebotqqrebot 加载插件处理。
#### 4.1 下载并安装 qqrebot
```bash
source /tmp/env_vars.sh
command -v wget &>/dev/null || { apt-get update && apt-get install -y wget; }
cd /tmp
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
```
#### 4.2 检查端口冲突
```bash
source /tmp/env_vars.sh
if ss -tlnp | grep -q :25580; then
echo "⚠️ 端口 25580 已被占用,请修改为 25581 或其他空闲端口"
echo " 修改 qqrebot config.toml 中的 list_port"
exit 1
fi
```
#### 4.3 配置
编辑 `config/config.toml`(使用 sed 替换变量):
```bash
source /tmp/env_vars.sh
cd /opt/qqrebot
mkdir -p config
cat > config/config.toml << REBOTEOF
[app]
list_port = 25580
send_url = "http://${NAPCAT_HOST}:${NAPCAT_API_PORT}"
[rebot]
id = ""
[plugins]
dir = ["plugins"]
REBOTEOF
```
> `send_url` 是 qqrebot 发给插件的 NapCat API 基础地址。
#### 4.4 创建 systemd 服务
```bash
source /tmp/env_vars.sh
cat > /etc/systemd/system/qqrebot.service << 'SERVICEEOF'
[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
SERVICEEOF
systemctl daemon-reload
# ⚠️ 先不启动,等插件部署完成后再启
```
---
### 第5步安装 openclaw_bridge 插件
本仓库即 openclaw_bridge 插件的源码,需打包后部署到 qqrebot。
**打包(必须在目标主机上执行,因含 C 扩展):**
> ⚠️ **必须使用虚拟环境,严禁 `--break-system-packages`。**
> 如果 `python3 -m venv` 报错(如 Debian 未安装 `python3-venv`),先用包管理器安装。
```bash
source /tmp/env_vars.sh
cd /opt/chatrebot_aireply_plug
# 确保 python3-venv 可用
if ! python3 -m venv --help &>/dev/null; then
apt-get update && apt-get install -y python3-venv
fi
# 创建并激活虚拟环境
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python3 package.py
# 部署到 qqrebot
cp dist/openclaw_bridge.zip /opt/qqrebot/plugins/
```
**创建插件配置 `/opt/qqrebot/config/openclawbridge/config.toml`**
```bash
source /tmp/env_vars.sh
mkdir -p /opt/qqrebot/config/openclawbridge
cat > /opt/qqrebot/config/openclawbridge/config.toml << CONFIGEOF
[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}"
CONFIGEOF
```
**启动 qqrebot**
```bash
systemctl enable --now qqrebot
```
**验证插件加载:**
```bash
journalctl -u qqrebot -f | grep OpenClawBridge
```
预期输出:
```
Config loaded: url=http://127.0.0.1:18789, allowed=123456789
```
---
### 第6步创建新的 OpenClaw agent
`~/.openclaw/openclaw.json``agents.list` 中添加新 agent
```bash
source /tmp/env_vars.sh
AGENT_WORKSPACE="/home/program/${NEW_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"
# 读取当前 OpenClaw 配置
CONFIG_PATH="$HOME/.openclaw/openclaw.json"
if [ ! -f "$CONFIG_PATH" ]; then
echo "❌ 未找到 OpenClaw 配置:$CONFIG_PATH"
exit 1
fi
# 检查 agent 是否已存在
python3 -c "
import json
with open('$CONFIG_PATH') as f:
cfg = json.load(f)
agents = cfg.setdefault('agents', {}).setdefault('list', [])
if not any(a.get('id') == '$NEW_AGENT_ID' for a in agents):
agents.append({
'id': '$NEW_AGENT_ID',
'name': '$NEW_AGENT_ID',
'model': 'kimi/kimi-for-coding',
'workspace': '$AGENT_WORKSPACE'
})
with open('$CONFIG_PATH', 'w') as f:
json.dump(cfg, f, indent=2)
print('agent 已添加')
else:
print('agent 已存在,跳过')
"
```
#### 6.2 部署角色定义文件AGENTS.md / SOUL.md 等)
将角色模板文件复制到 agent workspace。这些文件定义 agent 的人设、安全红线、越狱防护和内容审查规则。
```bash
source /tmp/env_vars.sh
# 模板目录在本仓库 config/agent-templates/
TEMPLATES_DIR="/opt/chatrebot_aireply_plug/config/agent-templates"
if [ -d "$TEMPLATES_DIR" ]; then
# ─── 自动获取已登录 QQ 的昵称作为 agent 名字 ───
echo "正在获取 QQ 昵称..."
AGENT_NAME=$(curl -s -X POST "http://${NAPCAT_HOST}:${NAPCAT_API_PORT}/get_login_info" \
-H "Content-Type: application/json" -d '{}' \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('data',{}).get('nickname',''))" 2>/dev/null)
if [ -z "$AGENT_NAME" ]; then
echo "⚠️ 无法获取 QQ 昵称,使用 ADMIN_NAME 代替"
AGENT_NAME="${ADMIN_NAME}"
else
echo "✅ 获取到 QQ 昵称:$AGENT_NAME"
fi
# ─── 持久化到 env_vars ───
echo "export AGENT_NAME='${AGENT_NAME}'" >> /tmp/env_vars.sh
# 复制模板文件(不覆盖已有文件)
for f in AGENTS.md SOUL.md IDENTITY.md USER.md TOOLS.md HEARTBEAT.md; do
if [ ! -f "${AGENT_WORKSPACE}/${f}" ]; then
cp "${TEMPLATES_DIR}/${f}" "${AGENT_WORKSPACE}/${f}"
echo "created: ${f}"
else
echo "跳过(已存在): ${f}"
fi
done
# ─── 替换占位符 ───
cd "${AGENT_WORKSPACE}"
sed -i "s/ADMIN_QQ/${ADMIN_QQ}/g" *.md
sed -i "s|ADMIN_NAME|${ADMIN_NAME}|g" *.md
sed -i "s|ADMIN_GAME_ID|${ADMIN_GAME_ID}|g" *.md
sed -i "s|AGENT_WORKSPACE|${AGENT_WORKSPACE}|g" *.md
sed -i "s|AGENT_NAME|${AGENT_NAME}|g" *.md
echo "✅ 角色文件已部署占位符已替换agent 昵称:$AGENT_NAME"
else
echo "⚠️ 模板目录不存在:$TEMPLATES_DIR,请确认仓库已克隆到 /opt/chatrebot_aireply_plug"
fi
```
> ⚡ `AGENT_NAME` 自动从 NapCat `/get_login_info` 接口获取已登录 QQ 的昵称。获取失败时回退到 `ADMIN_NAME`。
> 其余占位符(`ADMIN_QQ`、`ADMIN_NAME`、`ADMIN_GAME_ID`、`AGENT_WORKSPACE`)由 sed 自动替换为实际值。
> 如需自定义人设,可直接编辑 agent workspace 中的对应 `.md` 文件。
---
### 第7步将脚本和 Skills 部署到 agent workspace
#### 7.1 复制脚本
```bash
source /tmp/env_vars.sh
cp -r /opt/chatrebot_aireply_plug/scripts/* "${AGENT_WORKSPACE}/scripts/"
ls "${AGENT_WORKSPACE}/scripts/" | wc -l
# 预期输出26
```
#### 7.2 复制 Skills
```bash
source /tmp/env_vars.sh
for SKILL in qq-messenger qq-management qq-resolver qq-napcat-extras mc-query nix-helper browser file-process; do
srcdir="/opt/chatrebot_aireply_plug/skills/${SKILL}"
if [ -d "$srcdir" ]; then
cp -r "$srcdir" "${AGENT_WORKSPACE}/skills/"
echo "copied: $SKILL"
else
echo "⚠️ skill 不存在: $SKILL"
fi
done
```
#### 7.3 替换占位符
```bash
source /tmp/env_vars.sh
# ─── 替换脚本占位符 ───
cd "${AGENT_WORKSPACE}/scripts"
sed -i "s|YOUR_NAPCAT_HOST:25570|${NAPCAT_HOST}:${NAPCAT_API_PORT}|g" *.py
sed -i "s|YOUR_NAPCAT_HOST|${NAPCAT_HOST}:${NAPCAT_API_PORT}|g" *.py
sed -i "s|YOUR_ADMIN_QQ|${ADMIN_QQ}|g" *.py
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 占位符 ───
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"
sed -i "s|YOUR_SHARED_DIR|${SHARED_DIR}|g" "$f"
done
```
#### 7.4 验证完整性
```bash
source /tmp/env_vars.sh
echo "scripts: $(ls "${AGENT_WORKSPACE}/scripts/" | wc -l) 个"
echo "skills: $(ls "${AGENT_WORKSPACE}/skills/" | wc -l) 个"
if grep -r "YOUR_ADMIN_QQ\|YOUR_WORKSPACE_PATH\|YOUR_NAPCAT_HOST\|YOUR_SHARED_DIR\|ADMIN_QQ\|AGENT_WORKSPACE" "${AGENT_WORKSPACE}/"; then
echo "⚠️ 还有未替换的占位符!"
else
echo "✅ 占位符全部替换完毕(含角色模板)"
fi
```
---
### 第8步重启 OpenClaw Gateway
> ⚠️ **重要:在确认已走完前 7 步前,不要执行本步!**
> 重启 Gateway 会中断所有正在进行的操作(包括包安装、文件复制等)。
> **本步之前的所有步骤1-7必须全部执行完毕。**
```bash
source /tmp/env_vars.sh
openclaw gateway restart
```
确认新 agent 已加载:
```bash
openclaw config get agents.list
# 或 journalctl -u openclaw -f | grep "agent.${NEW_AGENT_ID}"
```
---
### 第9步端到端验证
1. 确认 NapCat QQ 已登录(`docker logs napcat 2>&1 | grep "登录成功"`
2. 确认 OneBot API 可访问(`curl localhost:6097/get_version_info`
3. 确认 qqrebot 正在运行(`systemctl status qqrebot`
4. 在 QQ 上给机器人发消息
5. 检查 qqrebot 日志:`journalctl -u qqrebot -f | grep OpenClawBridge`
6. 检查 OpenClaw 日志:`journalctl -u openclaw -f`
7. 验证 agent 已回复
---
## 脚本适配说明
### 端口对照
| 组件 | 旧版 go-cqhttp | NapCat本教程 |
|---|---|---|
| HTTP API 端口 | `25570` | **6097** |
| WebUI | N/A | **6099**(扫码登录用) |
| WebSocket | `25570`(兼用) | 不启用 |
> 脚本中 `CQHTTP_URL = "http://YOUR_NAPCAT_HOST:25570"` 替换后变为 `http://127.0.0.1:6097`。
### 文件发送与共享目录
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_NAPCAT_HOST:25570` | `${NAPCAT_HOST}:${NAPCAT_API_PORT}` | 所有脚本 |
| `YOUR_NAPCAT_HOST` | `${NAPCAT_HOST}:${NAPCAT_API_PORT}` | 部分脚本 |
| `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``qq-messenger/SKILL.md``qq-napcat-extras/SKILL.md` |
| `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 :6097
│ ├── 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