import os import requests from flask import Flask, request, jsonify, render_template_string from datetime import datetime import time app = Flask(__name__) app.secret_key = os.environ.get("SECRET_KEY", "quark-offline-secret-key") # ========== 夸克配置 ========== DEFAULT_COOKIE = os.environ.get("QUARK_COOKIE") if not DEFAULT_COOKIE: raise RuntimeError("请在 Hugging Face Secrets 中配置 QUARK_COOKIE") current_cookie = DEFAULT_COOKIE rate_limit_records = {} def get_client_ip(): if request.headers.get('X-Forwarded-For'): return request.headers.get('X-Forwarded-For').split(',')[0] if request.headers.get('X-Real-IP'): return request.headers.get('X-Real-IP') return request.remote_addr or "unknown" def rate_limit(min_interval=10, max_calls_per_minute=2): def decorator(f): def decorated_function(*args, **kwargs): identifier = get_client_ip() + "_" + f.__name__ now = time.time() record = rate_limit_records.get(identifier, {"last_call": 0, "calls": []}) record["calls"] = [t for t in record["calls"] if now - t < 60] if len(record["calls"]) >= max_calls_per_minute: oldest = record["calls"][0] wait_time = 60 - (now - oldest) return jsonify({"success": False, "error": f"操作过于频繁,请等待 {int(wait_time)} 秒"}), 429 if now - record["last_call"] < min_interval: wait_time = min_interval - (now - record["last_call"]) return jsonify({"success": False, "error": f"请等待 {int(wait_time)} 秒后再试"}), 429 record["last_call"] = now record["calls"].append(now) rate_limit_records[identifier] = record return f(*args, **kwargs) decorated_function.__name__ = f.__name__ return decorated_function return decorator def get_headers(): return { "Cookie": current_cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/2.5.20 Chrome/100.0.4896.160 Electron/18.3.5.4-b478491100 Safari/537.36", "Accept": "application/json, text/plain, */*", "Referer": "https://pan.quark.cn", "Origin": "https://pan.quark.cn", "Content-Type": "application/json" } def mask_cookie(cookie): if not cookie: return "未设置" if len(cookie) <= 20: return cookie[:8] + "***" return cookie[:15] + "..." + cookie[-10:] def safe_format_timestamp(timestamp): if not timestamp: return "暂无" try: ts = int(timestamp) if ts <= 0 or ts > 4102444800: return "暂无" return datetime.fromtimestamp(ts).strftime("%Y-%m-%d") except: return "暂无" def get_space_info(): try: url = "https://drive.quark.cn/1/clouddrive/member" params = {"pr": "ucpro", "fr": "pc", "fetch_subscribe": "false", "_ch": "home", "fetch_identity": "false"} resp = requests.get(url, headers=get_headers(), params=params, timeout=10) data = resp.json() if data.get("status") == 200 or data.get("code") == 0: info = data.get("data", {}) total_bytes = info.get("total_capacity", 1) used_bytes = info.get("use_capacity", 0) total_gb = total_bytes / (1024**3) used_gb = used_bytes / (1024**3) free_gb = max(total_gb - used_gb, 0) percent = min(used_gb / total_gb * 100, 100) if total_gb > 0 else 0 member_status = info.get("member_status", {}) vip_level = "普通用户" is_88vip = False if member_status.get("SUPER_VIP"): vip_level = "超级会员(SVIP)" is_88vip = True # SVIP 通常来自 88VIP elif member_status.get("VIP"): vip_level = "VIP会员" elif member_status.get("Z_VIP"): vip_level = "Z会员" elif member_status.get("MINI_VIP"): vip_level = "迷你会员" expire_ts = info.get("expired_at", 0) or info.get("created_at", 0) return { "success": True, "total": round(total_gb, 2), "used": round(used_gb, 2), "free": round(free_gb, 2), "percent": round(percent, 1), "vip": vip_level, "is_88vip": is_88vip, "expire_date": safe_format_timestamp(expire_ts) } return {"success": False, "error": data.get("message", "获取失败")} except Exception as e: return {"success": False, "error": str(e)} HTML = """ 夸克网盘信息查看器
⚠️ 重要提示:手动点击刷新,建议每小时1-2次,避免Cookie失效

📊 会员信息 & 💾 空间情况

点击刷新按钮获取会员信息

🔧 Cookie 管理

加载中...
💡 如何获取Cookie?浏览器登录 pan.quark.cn → F12 → Application → Cookies → 复制所有键值对
""" @app.route("/", methods=["GET"]) def index(): return render_template_string(HTML) @app.route("/api/space_info", methods=["GET"]) @rate_limit(min_interval=10, max_calls_per_minute=2) def api_space_info(): return jsonify(get_space_info()), 200 @app.route("/api/update_cookie", methods=["POST"]) def api_update_cookie(): global current_cookie data = request.get_json() if not data or "cookie" not in data: return jsonify({"error": "缺少 cookie"}), 400 new_cookie = data["cookie"].strip() if not new_cookie: return jsonify({"error": "Cookie 不能为空"}), 400 current_cookie = new_cookie return jsonify({"status": "success", "message": "Cookie已更新"}), 200 @app.route("/api/current_cookie", methods=["GET"]) def api_current_cookie(): return jsonify({"masked_cookie": mask_cookie(current_cookie)}), 200 if __name__ == "__main__": app.run(host="0.0.0.0", port=7860)