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 入口,完整架构说明和部署步骤
This commit is contained in:
89
scripts/qq_upload_group_file.py
Normal file
89
scripts/qq_upload_group_file.py
Normal file
@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
群文件上传 — 通过 NapCat 消息 API 上传文件到群
|
||||
|
||||
用法:
|
||||
python3 qq_upload_group_file.py --gid YOUR_GROUP_ID --file /path/to/file.txt
|
||||
python3 qq_upload_group_file.py --gid YOUR_GROUP_ID --file ./doc.md --name 文档.md
|
||||
python3 qq_upload_group_file.py --gid YOUR_GROUP_ID --file ./image.png --json
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import base64
|
||||
import argparse
|
||||
import requests
|
||||
|
||||
CQHTTP_URL = "http://YOUR_NAP CAT_HOST:25570"
|
||||
DEFAULT_GID = YOUR_GROUP_ID # Liquid Studio 群
|
||||
|
||||
|
||||
def upload_file(group_id: int, file_path: str, file_name: str = None) -> dict:
|
||||
"""上传文件到群,通过 base64:// 方式发送文件消息"""
|
||||
if not os.path.exists(file_path):
|
||||
raise FileNotFoundError(f"文件不存在: {file_path}")
|
||||
|
||||
file_size = os.path.getsize(file_path)
|
||||
file_name = file_name or os.path.basename(file_path)
|
||||
|
||||
# 读取并 base64 编码
|
||||
with open(file_path, "rb") as f:
|
||||
b64_content = base64.b64encode(f.read()).decode()
|
||||
|
||||
resp = requests.post(f"{CQHTTP_URL}/send_group_msg", json={
|
||||
"group_id": group_id,
|
||||
"message": [
|
||||
{
|
||||
"type": "file",
|
||||
"data": {
|
||||
"file": f"base64://{b64_content}",
|
||||
"name": file_name
|
||||
}
|
||||
}
|
||||
]
|
||||
}, timeout=60)
|
||||
|
||||
data = resp.json()
|
||||
if data.get("status") != "ok":
|
||||
raise Exception(data.get("message", data.get("wording", "上传失败")))
|
||||
|
||||
return {
|
||||
"message_id": data["data"]["message_id"],
|
||||
"file_name": file_name,
|
||||
"file_size": file_size,
|
||||
"group_id": group_id
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="群文件上传")
|
||||
parser.add_argument("--gid", type=int, default=DEFAULT_GID, help=f"群号 (默认: {DEFAULT_GID})")
|
||||
parser.add_argument("--file", type=str, required=True, help="要上传的文件路径")
|
||||
parser.add_argument("--name", type=str, help="文件名(默认使用原文件名)")
|
||||
parser.add_argument("--json", action="store_true", help="JSON 格式输出")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
result = upload_file(args.gid, args.file, args.name)
|
||||
|
||||
if args.json:
|
||||
print(json.dumps(result, ensure_ascii=False))
|
||||
else:
|
||||
size_str = f"{result['file_size'] / 1024:.1f} KB" if result['file_size'] >= 1024 else f"{result['file_size']} B"
|
||||
print(f"✅ 已上传: {result['file_name']} ({size_str})")
|
||||
print(f" message_id: {result['message_id']}")
|
||||
|
||||
except FileNotFoundError as e:
|
||||
print(f"❌ {e}")
|
||||
sys.exit(1)
|
||||
except requests.exceptions.ConnectionError:
|
||||
print(f"❌ 连接失败: 无法连接到 NapCat ({CQHTTP_URL})")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"❌ 上传失败: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user