mirror of
https://github.com/xiaoyaDev/xiaoya-alist.git
synced 2026-08-29 02:20:45 +08:00
201 lines
6.5 KiB
Python
201 lines
6.5 KiB
Python
#!/usr/local/bin/python3
|
|
# pylint: disable=C0114
|
|
|
|
import json
|
|
import time
|
|
import logging
|
|
import os
|
|
import threading
|
|
import sys
|
|
import argparse
|
|
import uuid
|
|
|
|
import requests
|
|
import qrcode
|
|
from flask import Flask, send_file, render_template, jsonify
|
|
|
|
|
|
app = Flask(__name__)
|
|
logging.basicConfig(level=logging.INFO)
|
|
LAST_STATUS = 0
|
|
stop_event = threading.Event()
|
|
if sys.platform.startswith("win32"):
|
|
QRCODE_DIR = "qrcode.png"
|
|
else:
|
|
QRCODE_DIR = "/quark_cookie/qrcode.png"
|
|
QUARK_UA = (
|
|
"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 Channel/pckk_other_ch" # noqa: E501
|
|
)
|
|
|
|
|
|
def cookiejar_to_string(cookiejar):
|
|
"""
|
|
转换 Cookie 格式
|
|
"""
|
|
cookie_string = ""
|
|
for cookie in cookiejar:
|
|
cookie_string += cookie.name + "=" + cookie.value + "; "
|
|
return cookie_string.strip('; ')
|
|
|
|
|
|
# pylint: disable=W0603
|
|
def poll_qrcode_status(_token, stop, log_print):
|
|
"""
|
|
循环等待扫码
|
|
"""
|
|
global LAST_STATUS
|
|
while not stop.is_set():
|
|
api_url = "https://uop.quark.cn/cas/ajax/getServiceTicketByQrcodeToken"
|
|
_re = requests.get(
|
|
f"{api_url}?client_id=532&v=1.2&token={_token}&request_id={uuid.uuid4()}",
|
|
timeout=10,
|
|
)
|
|
if _re.status_code == 200:
|
|
re_data = json.loads(_re.text)
|
|
if re_data["status"] == 2000000:
|
|
logging.info("扫码成功!")
|
|
service_ticket = re_data["data"]["members"]["service_ticket"]
|
|
_re = requests.get(f"https://pan.quark.cn/account/info?st={service_ticket}&lw=scan", timeout=10)
|
|
if _re.status_code == 200:
|
|
quark_cookie = cookiejar_to_string(_re.cookies)
|
|
headers = {
|
|
"User-Agent": QUARK_UA,
|
|
"Referer": "https://pan.quark.cn",
|
|
"Cookie": quark_cookie,
|
|
}
|
|
_re = requests.get(
|
|
"https://drive-pc.quark.cn/1/clouddrive/config?pr=ucpro&fr=pc&uc_param_str=",
|
|
headers=headers,
|
|
timeout=10,
|
|
) # noqa: E501
|
|
if _re.status_code == 200:
|
|
quark_cookie += "; " + cookiejar_to_string(_re.cookies)
|
|
else:
|
|
logging.error("获取 __puus 失败!")
|
|
LAST_STATUS = 2
|
|
break
|
|
if sys.platform.startswith("win32"):
|
|
with open("quark_cookie.txt", "w", encoding="utf-8") as f:
|
|
f.write(quark_cookie)
|
|
else:
|
|
with open("/data/quark_cookie.txt", "w", encoding="utf-8") as f:
|
|
f.write(quark_cookie)
|
|
logging.info("扫码成功,夸克 Cookie 已写入文件!")
|
|
LAST_STATUS = 1
|
|
break
|
|
elif re_data["status"] == 50004002:
|
|
logging.error("二维码无效或已过期!")
|
|
LAST_STATUS = 2
|
|
break
|
|
elif re_data["status"] == 50004001:
|
|
if log_print:
|
|
logging.info("等待用户扫码...")
|
|
time.sleep(2)
|
|
|
|
|
|
@app.route("/")
|
|
def index():
|
|
"""
|
|
网页扫码首页
|
|
"""
|
|
return render_template("index.html")
|
|
|
|
|
|
@app.route("/image")
|
|
def serve_image():
|
|
"""
|
|
获取二维码图片
|
|
"""
|
|
return send_file(QRCODE_DIR, mimetype="image/png")
|
|
|
|
|
|
@app.route("/status")
|
|
def status():
|
|
"""
|
|
扫码状态获取
|
|
"""
|
|
if LAST_STATUS == 1:
|
|
return jsonify({"status": "success"})
|
|
elif LAST_STATUS == 2:
|
|
return jsonify({"status": "failure"})
|
|
else:
|
|
return jsonify({"status": "unknown"})
|
|
|
|
|
|
@app.route("/shutdown_server", methods=["GET"])
|
|
def shutdown():
|
|
"""
|
|
退出进程
|
|
"""
|
|
if os.path.isfile(QRCODE_DIR):
|
|
os.remove(QRCODE_DIR)
|
|
os._exit(0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if os.path.isfile(QRCODE_DIR):
|
|
os.remove(QRCODE_DIR)
|
|
parser = argparse.ArgumentParser(description="Quark Cookie")
|
|
parser.add_argument("--qrcode_mode", type=str, required=True, help="扫码模式")
|
|
args = parser.parse_args()
|
|
logging.info("二维码生成中...")
|
|
re = requests.get(
|
|
f"https://uop.quark.cn/cas/ajax/getTokenForQrcodeLogin?client_id=532&v=1.2&request_id={uuid.uuid4()}",
|
|
timeout=10,
|
|
) # noqa: E501
|
|
if re.status_code == 200:
|
|
token = json.loads(re.text)["data"]["members"]["token"]
|
|
qr = qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=5, border=4)
|
|
qr.add_data(
|
|
f"https://su.quark.cn/4_eMHBJ?token={token}&client_id=532&ssb=weblogin&uc_param_str=&uc_biz_str=S%3Acustom%7COPT%3ASAREA%400%7COPT%3AIMMERSIVE%401%7COPT%3ABACK_BTN_STYLE%400"
|
|
)
|
|
qr.make(fit=True)
|
|
img = qr.make_image(fill_color="black", back_color="white")
|
|
img.save(QRCODE_DIR)
|
|
logging.info("二维码生成完成!")
|
|
else:
|
|
logging.error("二维码生成失败,退出进程")
|
|
os._exit(1)
|
|
try:
|
|
if args.qrcode_mode == "web":
|
|
wait_status = threading.Thread(
|
|
target=poll_qrcode_status,
|
|
args=(
|
|
token,
|
|
stop_event,
|
|
True,
|
|
),
|
|
)
|
|
wait_status.start()
|
|
app.run(host="0.0.0.0", port=34256)
|
|
elif args.qrcode_mode == "shell":
|
|
wait_status = threading.Thread(
|
|
target=poll_qrcode_status,
|
|
args=(
|
|
token,
|
|
stop_event,
|
|
False,
|
|
),
|
|
)
|
|
wait_status.start()
|
|
logging.info("请打开 夸克 APP 扫描此二维码!")
|
|
qr.print_ascii(invert=True, tty=sys.stdout.isatty())
|
|
while LAST_STATUS not in [1, 2]:
|
|
time.sleep(1)
|
|
if os.path.isfile(QRCODE_DIR):
|
|
os.remove(QRCODE_DIR)
|
|
if LAST_STATUS == 2:
|
|
os._exit(1)
|
|
os._exit(0)
|
|
else:
|
|
logging.error("未知的扫码模式")
|
|
if os.path.isfile(QRCODE_DIR):
|
|
os.remove(QRCODE_DIR)
|
|
os._exit(1)
|
|
except KeyboardInterrupt:
|
|
if os.path.isfile(QRCODE_DIR):
|
|
os.remove(QRCODE_DIR)
|
|
stop_event.set()
|
|
wait_status.join()
|
|
os._exit(0)
|