完整 AgentSkill:词库外部化 + 全部脚本/Skill 脱敏上传
- 高危词库从 process.py 抽到 config.toml [security] section - process.py 改为 _get_high_risk_words() 动态加载(配置优先) - 新增 15 个 QQ 操作脚本(已脱敏:QQ号/IP/Token → 占位符) - 新增 8 个 SKILL.md(qq-messenger/management/resolver/napcat-extras 等) - 新增 SKILL.md 入口(完整部署方案文档) - 保留 SDK 框架(plugin_modules.py, file_store_api.py, package.py 等)
This commit is contained in:
103
scripts/qq_get_file.py
Normal file
103
scripts/qq_get_file.py
Normal file
@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
从 QQ 接收文件/图片 - 通过 NapCat (OneBot) HTTP API
|
||||
|
||||
自动下载到 qqagent 工作区的 files/ 目录,供 agent 直接使用。
|
||||
|
||||
用法:
|
||||
python3 qq_get_file.py --file <file_id>
|
||||
→ 下载到 files/ 目录
|
||||
→ 输出保存路径、文件名、大小、类型
|
||||
|
||||
python3 qq_get_file.py --file <file_id> --info --json
|
||||
→ 只查文件信息(不下)
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import requests
|
||||
|
||||
CQHTTP_URL = "http://YOUR_NAP CAT_HOST:25570"
|
||||
FILES_DIR = "YOUR_WORKSPACE_PATH/files"
|
||||
|
||||
|
||||
def get_file(file_id: str) -> dict:
|
||||
resp = requests.post(
|
||||
f"{CQHTTP_URL}/get_file",
|
||||
json={"file_id": file_id},
|
||||
timeout=15
|
||||
)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
if data.get("status") != "ok":
|
||||
raise Exception(f"API error: {data}")
|
||||
return data["data"]
|
||||
|
||||
|
||||
def save_file(file_info: dict) -> tuple[str, str]:
|
||||
"""下载文件到 FILES_DIR,返回 (本地路径, 文件名)"""
|
||||
os.makedirs(FILES_DIR, exist_ok=True)
|
||||
filename = file_info.get("file_name", "unknown")
|
||||
local_path = os.path.join(FILES_DIR, filename)
|
||||
|
||||
if file_info.get("base64"):
|
||||
import base64
|
||||
with open(local_path, "wb") as f:
|
||||
f.write(base64.b64decode(file_info["base64"]))
|
||||
else:
|
||||
url = file_info.get("url", "")
|
||||
if not url:
|
||||
raise Exception("No base64 or url available")
|
||||
resp = requests.get(url, timeout=30)
|
||||
resp.raise_for_status()
|
||||
with open(local_path, "wb") as f:
|
||||
f.write(resp.content)
|
||||
|
||||
return local_path, filename
|
||||
|
||||
|
||||
def detect_type(filename: str) -> str:
|
||||
ext = filename.lower().rsplit(".", 1)[-1] if "." in filename else ""
|
||||
image_exts = {"jpg", "jpeg", "png", "gif", "bmp", "webp"}
|
||||
return "图片" if ext in image_exts else "文件"
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="从 QQ 接收文件")
|
||||
parser.add_argument("--file", required=True, help="文件 ID(file_id)")
|
||||
parser.add_argument("--output", help="保存目录(默认 files/)")
|
||||
parser.add_argument("--info", action="store_true", help="只查文件信息,不下")
|
||||
parser.add_argument("--json", action="store_true", help="JSON 格式输出")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
file_info = get_file(args.file)
|
||||
|
||||
if args.info or args.json:
|
||||
info = {
|
||||
"file_id": args.file,
|
||||
"name": file_info.get("file_name"),
|
||||
"size": file_info.get("file_size"),
|
||||
"has_base64": bool(file_info.get("base64")),
|
||||
}
|
||||
print(json.dumps(info, ensure_ascii=False, indent=2))
|
||||
return
|
||||
|
||||
save_dir = args.output or FILES_DIR
|
||||
local_path, filename = save_file(file_info)
|
||||
ftype = detect_type(filename)
|
||||
|
||||
print(f"✅ 已保存到 {local_path}")
|
||||
print(f" 文件名: {filename}")
|
||||
print(f" 大小: {file_info.get('file_size')} bytes")
|
||||
print(f" 类型: {ftype}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 错误: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user