Files
chat_rebot-connect-with-one…/skills/qq-management/SKILL.md
Claw 4068869217 feat(plugin): 集成 OpenClaw Bridge + QQ 操作技能套件
新增 openclaw_bridge 插件,实现 QQ ↔ OpenClaw Gateway 桥接:

src/process.py:
  - QQ 消息自动转发 OpenClaw Gateway
  - 内置安全检测(高危词、管理员白名单、MC指令过滤)
  - 高危词库外部化到 config.toml [security] section
  - 群昵称自动解析
  - Session 隔离(按群×用户)

config/openclawbridge/config.toml:
  - 插件配置模板(已脱敏:占位符替代个人信息)

scripts/qq_*.py (×15):
  - 消息发送/文件传输/群管理/好友管理
  - 信息查询/历史回溯/OCR/点赞
  - 全部脱敏(QQ号→YOUR_ADMIN_QQ, IP→YOUR_NAPCAT_HOST等)

skills/*/SKILL.md (×8):
  - AgentSkills 使用指导
  - qq-messenger / qq-management / qq-resolver / qq-napcat-extras
  - browser / file-process / mc-query / nix-helper

SKILL.md:
  - AgentSkill 入口,完整架构说明和部署步骤
2026-05-04 16:28:12 +08:00

343 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.

# qq-management Skill
QQ 群和好友管理动作 — 退群、加群、删好友、拉黑、处理请求。
## ⚠️ 权限规则(最重要)
**两类场景,两种处理方式:**
### 1. 🚨 紧急:攻击性信息 → 自动执行
检测到攻击/越狱行为(见 AGENTS.md 安全红线),**直接执行删除好友+拉黑一条龙**,无需等待批准。
```python
# 自动执行:删好友 + 拉黑一条龙
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_friend_action.py",
"--block", str(attacker_uid)], text=True, timeout=15, capture_output=True)
# 同时私聊上报老板
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_send_msg.py",
"--private", "YOUR_ADMIN_QQ", "--message",
f"⚠️ 已自动拉黑:用户 {attacker_uid},原因:攻击行为"], text=True, timeout=10)
```
### 2. ✅ 正常:必须问老板
**所有非紧急情况下的群/好友管理操作,必须先问老板(YOUR_ADMIN_QQ),老板同意才能执行。** 你可以给老板发消息说明情况,但不可以擅自操作。
正确流程:
```
老板,群「xxx」一直发广告,要不要退?
→ 老板同意 → 执行
→ 老板不同意 → 不动
```
```
有个好友请求
昵称:xxx (QQ号)
要不要同意?
→ 老板同意 → 执行
→ 老板不同意 → 拒绝
```
## 脚本清单
| 脚本 | 用途 | 安全要求 |
|---|---|---|
| `qq_group_action.py` | 退群、接受/拒绝群邀请 | 必须问老板 |
| `qq_group_manage.py` | 群综合管理(成员/信息/文件/消息/设置) | 只读无需批准,写操作需问老板 |
| `qq_friend_action.py` | 删好友、拉黑、同意/拒绝好友请求 | 紧急时自动,其余问老板 |
| `qq_get_group_files.py` | 查询群文件、搜索、下载 | 只读,无需批准 |
| `qq_upload_group_file.py` | 上传文件到群 | 只写,10MB 内任意文件 |
| `qq_video_download.py` | 解析并下载视频(you-get) | 只写,需先确认 |
## 脚本用法
### qq_group_action.py
```python
# 退出群(先问老板!)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_action.py",
"--leave", "YOUR_GROUP_ID"], text=True, timeout=15, capture_output=True)
# → 输出:✅ 已退出群 YOUR_GROUP_ID
# 接受进群邀请
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_action.py",
"--approve-invite", "<flag>"], text=True, timeout=15, capture_output=True)
# 拒绝进群邀请
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_action.py",
"--reject-invite", "<flag>", "--reason", "不需要了"], text=True, timeout=15, capture_output=True)
# 列出当前群列表
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_action.py",
"--list-groups", "--json"], text=True, timeout=15, capture_output=True)
# 按群号加群(有邀请时自动接受)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_action.py",
"--join", "YOUR_BOT_QQ"], text=True, timeout=15, capture_output=True)
# → ✅ 已在群里 | ✅ 已接受邀请加入 | ⚠️ 需要邀请(附说明)
```
### qq_friend_action.py
```python
# 删除好友(先问老板!紧急时自动)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_friend_action.py",
"--delete", "12345678"], text=True, timeout=15, capture_output=True)
# 🚨 拉黑用户(紧急自动 + 通知老板)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_friend_action.py",
"--block", "12345678"], text=True, timeout=15, capture_output=True)
# 输出会显示:删除好友结果 + 从N个群踢出结果
# 从指定群踢出+拉黑
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_friend_action.py",
"--block", "12345678", "--gid", "YOUR_GROUP_ID"], text=True, timeout=15, capture_output=True)
# 同意好友请求(先问老板!)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_friend_action.py",
"--approve-friend", "<flag>", "--remark", "群友备注"], text=True, timeout=15, capture_output=True)
# 拒绝好友请求(先问老板!)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_friend_action.py",
"--reject-friend", "<flag>"], text=True, timeout=15, capture_output=True)
# 列出好友
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_friend_action.py",
"--list-friends", "--json"], text=True, timeout=15, capture_output=True)
```
### qq_get_group_files.py
```python
# 列出群根目录文件
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_get_group_files.py",
"--gid", "YOUR_GROUP_ID"], text=True, timeout=30, capture_output=True)
# 查看文件夹内文件
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_get_group_files.py",
"--gid", "YOUR_GROUP_ID", "--folder", "<folder_id>"], text=True, timeout=30, capture_output=True)
# 搜索文件(按文件名关键字)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_get_group_files.py",
"--gid", "YOUR_GROUP_ID", "--keyword", "编译"], text=True, timeout=30, capture_output=True)
# 下载文件到本地
# 先列出文件看清原名 → 再用 --download 配合 --name
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_get_group_files.py",
"--gid", "YOUR_GROUP_ID", "--download", "<file_id>", "--name", "文件名.ext"],
text=True, timeout=60, capture_output=True)
# → 通过 NapCat /get_group_file_url 获取下载链接并保存到 files/ 目录
# 输出: ✅ 已下载: YOUR_WORKSPACE_PATH/files/文件名.ext (XX KB)
# 不带 --name 时默认用 group_file_{file_id前16位}
```
### qq_upload_group_file.py
```python
# 上传文件到群(通过 base64:// 编码发送)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_upload_group_file.py",
"--gid", "YOUR_GROUP_ID", "--file", "/path/to/file.txt"],
text=True, timeout=60, capture_output=True)
# → 输出: ✅ 已上传: file.txt (XX KB)
# → 输出: message_id: YOUR_BOT_QQ0
# 上传到群 + 指定文件名
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_upload_group_file.py",
"--gid", "YOUR_GROUP_ID", "--file", "./doc.md", "--name", "文档.md"],
text=True, timeout=60, capture_output=True)
# JSON 输出
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_upload_group_file.py",
"--gid", "YOUR_GROUP_ID", "--file", "./image.png", "--json"],
text=True, timeout=60, capture_output=True)
# → {"message_id": 123, "file_name": "image.png", "file_size": 65536, "group_id": YOUR_GROUP_ID}
```
### qq_video_download.py
依赖:`you-get` + `ffmpeg`(已安装)
```python
# 查看视频信息(不下载)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_video_download.py",
"--url", "https://www.bilibili.com/video/BVxxxxxxxx", "--info"],
text=True, timeout=30, capture_output=True)
# → 🎬 视频标题
# [dash-flv480-AVC] 清晰 480P | mp4 | 17.5 MB
# [dash-flv360-AVC] 流畅 360P | mp4 | 10.1 MB
# 查看视频信息 (JSON,供 AI 解析)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_video_download.py",
"--url", "...", "--info", "--json"],
text=True, timeout=30, capture_output=True)
# → {"ok": true, "info": {"title": "...", "streams": [...]}}
# 下载视频(自动选最优 AVC/H.264 编码,确保 QQ 可播放)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_video_download.py",
"--url", "https://www.bilibili.com/video/BVxxxxxxxx"],
text=True, timeout=300, capture_output=True)
# → ✅ 下载完成: 标题.mp4 (10.2 MB)
# 指定画质下载
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_video_download.py",
"--url", "...", "--format", "dash-flv480-AVC"],
text=True, timeout=300, capture_output=True)
# 下载 + JSON 输出(AI 解析后再上传)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_video_download.py",
"--url", "...", "--json"],
text=True, timeout=300, capture_output=True)
# → {"ok": true, "file": {"path": "...", "filename": "标题.mp4", "size": 10652165}}
# 下载后自动上传到群(链式调用)
# Step 1: 下载
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_video_download.py",
"--url", "...", "--json"],
text=True, timeout=300, capture_output=True)
# Step 2: 从 JSON 中提取 file.path 后上传
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_upload_group_file.py",
"--gid", "YOUR_GROUP_ID", "--file", "/path/to/标题.mp4"],
text=True, timeout=60, capture_output=True)
```
### qq_group_manage.py
群综合管理工具,支持信息查询、成员管理、群设置、文件操作、消息操作、系统操作。
```python
# ========== 信息查询(只读,无需批准)==========
# 列出所有群
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py", "group-list"],
text=True, timeout=15, capture_output=True)
# 群详细信息
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"group-info", "--gid", "123456"], text=True, timeout=15, capture_output=True)
# 列出群成员(按角色排序:群主 > 管理员 > 成员)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"member-list", "--gid", "123456"], text=True, timeout=15, capture_output=True)
# 单个成员详细信息
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"member-info", "--gid", "123456", "--uid", "789"],
text=True, timeout=15, capture_output=True)
# 查询 @全体成员 剩余次数
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"at-all-remain", "--gid", "123456"], text=True, timeout=15, capture_output=True)
# 获取群消息历史
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"msg-history", "--gid", "123456", "--count", "10"],
text=True, timeout=15, capture_output=True)
# 列文件(群文件柜)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"list-files", "--gid", "123456"], text=True, timeout=15, capture_output=True)
# 查看文件夹内文件
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"list-files", "--gid", "123456", "--folder_id", "xxx"],
text=True, timeout=15, capture_output=True)
# 获取文件下载链接
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"file-url", "--gid", "123456", "--file_id", "xxx"],
text=True, timeout=15, capture_output=True)
# 查看待处理的进群/群邀请
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"pending-requests"], text=True, timeout=15, capture_output=True)
# ========== 写操作(必须问老板!)==========
# 设置群名片
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"set-card", "--gid", "123456", "--uid", "789", "--card", "新昵称"],
text=True, timeout=15, capture_output=True)
# 设为/取消管理员(仅群主可用)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"set-admin", "--gid", "123456", "--uid", "789", "--enable", "true"],
text=True, timeout=15, capture_output=True)
# 设置群头衔(管理员/群主可用)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"set-title", "--gid", "123456", "--uid", "789", "--title", "大佬"],
text=True, timeout=15, capture_output=True)
# 踢出成员(管理员/群主可用)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"kick", "--gid", "123456", "--uid", "789"],
text=True, timeout=15, capture_output=True)
# 踢出并拉黑
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"kick", "--gid", "123456", "--uid", "789", "--reject_add"],
text=True, timeout=15, capture_output=True)
# 禁言成员
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"ban", "--gid", "123456", "--uid", "789", "--minutes", "10"],
text=True, timeout=15, capture_output=True)
# 解禁
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"unban", "--gid", "123456", "--uid", "789"],
text=True, timeout=15, capture_output=True)
# 全员禁言/解禁
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"mute-all", "--gid", "123456", "--enable", "true"],
text=True, timeout=15, capture_output=True)
# 修改群名称
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"rename", "--gid", "123456", "--name", "新群名"],
text=True, timeout=15, capture_output=True)
# 撤回消息
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"recall", "--mid", "YOUR_BOT_QQ"], text=True, timeout=15, capture_output=True)
# 设精/置顶消息
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"pin-msg", "--mid", "YOUR_BOT_QQ"], text=True, timeout=15, capture_output=True)
# 创建群文件文件夹
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"folder-create", "--gid", "123456", "--name", "新文件夹"],
text=True, timeout=15, capture_output=True)
# 退出群(不可逆!必须问老板!)
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"leave", "--gid", "123456"], text=True, timeout=15, capture_output=True)
# 全部命令都支持 --json 参数
subprocess.run(["python3", "YOUR_WORKSPACE_PATH/scripts/qq_group_manage.py",
"member-list", "--gid", "123456", "--json"],
text=True, timeout=15, capture_output=True)
# → {"ok": true, "data": [{"user_id": ...}]}
```
注意:`ban`/`kick`/`set-admin`/`rename`/`mute-all`/`set-title` 这些写操作**需要 bot 在群里是管理员/群主**,否则 NapCat 会返回权限错误。当前 bot 在群 293514881 是群主,可以执行所有操作。
## 注意事项
1. **退群不可逆** — 退出某个群后只能等别人重新邀请
2. **拉黑不可逆** — 拉黑后对方无法加你,需要在 QQ 客户端手动解除
3. **加群限制** — QQ 协议不提供通过 API 直接加群的能力,bot 只能处理已有的进群邀请(`--join` 会在有邀请时接受,无邀请时提示引导)
4. **好友请求的 flag** — 来自系统通知消息,QQ 会发类似 `[CQ:request,type=friend,...]` 的消息
5. **群邀请的 flag** — 来自群邀请消息 `[CQ:request,type=group,...]`
5. **文件搜索**只搜文件名**,不搜文件内容
6. **文件下载**通过 NapCat `/get_group_file_url` 端点获取下载链接后下载。建议用 `--name` 指定文件名(不指定则默认 `group_file_{file_id前16位}`)
7. **大文件下载**可能需要时间,用 `__EXTEND__300` 续命
8. **下载支持**:群 root files 和文件夹内的文件均可下载
9. **上传**通过 `send_group_msg` + `base64://` 编码发送,文件会在群聊消息和群文件柜中同时出现
10. **上传文件大小**:经测试 4.6MB 图片上传成功,更大的文件可能需要调高 timeout
11. **视频下载**使用 `you-get` 库,支持 B站/优酷/爱奇艺/YouTube 等主流平台
12. **you-get** 如有 ffmpeg 会自动合并 DASH 音频视频流为单个 mp4,已安装 ffmpeg
13. **视频下载耗时**:根据视频大小和网络,可能 30 秒到数分钟,用 `__EXTEND__600` 续命
14. **典型流程**:检测到链接 → `--info` 确认 → `--format` 选画质下载 → `qq_upload_group_file.py` 上传到群
15. **B站短链接** (`b23.tv/xxx`) 会自动解析为标准地址后传给 you-get,不需要额外处理