"""Extract serviceToken using passToken and save to ~/.mi.token""" import asyncio, json, base64, hashlib, secrets, string from pathlib import Path from aiohttp import ClientSession PASS_TOKEN = "V1:DXmurwq2/R1BHTELu6obCYX7Rq/4OZACAywwHdbXYQdJStLxyGwZzcsUMnk6tnJfQvY6HNI1whU+hcSk8uE2Odjpi89ldPfcJTiZ9Tzm4tcaXJakpJa4yk+FuEFO3bqcF941B0MznsQT+HGEETHP/CHAKpKlxavwIZNwuH2TYJH9gFMEhxzKf5vDASX86lyVPUjXOZF1e+qN0+62zJU6HTorL2fiYXYWL+ikS3mKCHQCaB/+NjqLEGohcmXsCKEEyE6ImJbk6nnQB/EobhcK6GhE8zHSL8MAXhppsfhCt+flp0ymq5ntBGnqHshdySMQaQxklVv8JNvVCr5FdZs4kQ==" USER_ID = "1136458602" async def main(): async with ClientSession() as s: headers = {"User-Agent": "Mozilla/5.0"} device_id = "".join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(16)) cookies = { "sdkVersion": "3.9", "deviceId": device_id, "userId": USER_ID, "passToken": PASS_TOKEN, } url = "https://account.xiaomi.com/pass/serviceLogin?sid=micoapi&_json=true" async with s.get(url, cookies=cookies, headers=headers) as r: raw = await r.text() data = json.loads(raw[11:]) print(f"serviceLogin code: {data.get('code')}") ssecurity = data["ssecurity"] location = data["location"] nonce = str(data["nonce"]) new_pass = data.get("passToken", PASS_TOKEN) nsec = f"nonce={nonce}&{ssecurity}" client_sign = base64.b64encode(hashlib.sha1(nsec.encode()).digest()).decode() sts_url = f"{location}&clientSign={client_sign}" async with s.get(sts_url, headers=headers) as r2: st_cookie = r2.cookies.get("serviceToken") if not st_cookie: print(f"❌ 错误:未能获取 serviceToken。请检查 PASS_TOKEN 是否过期。") print(f"响应状态码: {r2.status}") return service_token = st_cookie.value token = { "deviceId": device_id, "userId": USER_ID, "passToken": new_pass, "micoapi": [ssecurity, service_token], } token_path = Path(__file__).resolve().parent / ".mi.token" token_path.write_text(json.dumps(token, ensure_ascii=False, indent=2), encoding="utf-8") print(f"Token saved to {token_path}") print(f" userId: {USER_ID}") print(f" passToken: OK") print(f" ssecurity: OK") print(f" serviceToken: OK ({service_token[:30]}...)") # --- 新增推送至 NAS 逻辑 --- nas_url = "http://5kan.cc:42000/sync" headers = {"X-Auth-Key": "my_private_key_123"} # 注意:请确保与服务器端的 SECRET_KEY 一致 print(f"\n正在同步至 NAS ({nas_url})...") try: async with s.post(nas_url, json=token, headers=headers, timeout=15) as resp: if resp.status == 200: result = await resp.json() print(f"✅ NAS 同步成功: {result.get('msg')}") else: text = await resp.text() print(f"❌ NAS 同步失败 (状态码 {resp.status}): {text}") except Exception as e: print(f"❌ 无法连接到 NAS: {e}") print("请检查:1. 宝塔是否放行 42000 端口;2. 路由器是否做了端口转发;3. 接收端脚本是否正在运行。") asyncio.run(main())