#!/usr/bin/env python3 """ 从 QQ 接收文件/图片 - 通过 NapCat (OneBot) HTTP API 自动下载到 qqagent 工作区的 files/ 目录,供 agent 直接使用。 用法: python3 qq_get_file.py --file → 下载到 files/ 目录 → 输出保存路径、文件名、大小、类型 python3 qq_get_file.py --file --info --json → 只查文件信息(不下) """ import json import sys import os import argparse import requests CQHTTP_URL = "http://YOUR_NAPCAT_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()