"""Verify the token in users table is REAL (calls 996box API to check).""" import sys from pathlib import Path _HERE = Path(__file__).resolve().parent sys.path.insert(0, str(_HERE.parent / "src")) from cq2_sdk.env_loader import load_env load_env(_HERE.parent / ".env") from cq2_sdk.login import Box996Login, ManualGeetestSolver from cq2_sdk.store import UserStore, connection ACCOUNT = "longwu988" def is_real_token(token: str): """调用 996box 一个无副作用的 API, 验 token 是否真。 真实验证端点 (从 手机号短信验证登录过程.saz session 309 逆向): GET api.996hezi.com/user/v1/phoneOptionInfo → code=200 旧的 getTodayOpen 已 404 (服务端路径变了), 不能再用。 """ import asyncio box = Box996Login(geetest=ManualGeetestSolver(), device_id="00:15:5d:0a:04:00") box.token = token try: r = asyncio.run(box._request( "GET", "https://api.996hezi.com", "/user/v1/phoneOptionInfo", )) if r.get("code") == 200: return True, f"OK, code=200, msg={r.get('msg', '')}" return False, f"code={r.get('code')}, msg={r.get('msg', '')[:80]}" except Exception as e: return False, f"{type(e).__name__}: {str(e)[:120]}" with connection() as conn: u = UserStore(conn).get_by_username(ACCOUNT) if u is None: print(f"[FAIL] {ACCOUNT} not in DB. Run scaffold first.") sys.exit(1) if not u.token: print(f"[FAIL] {ACCOUNT} has no token. Run A1 first.") sys.exit(1) print(f"--- {ACCOUNT} token check ---") print(f" token (24) = {u.token[:24]}...") print(f" password_hash = {u.password_hash}") print(f" phone = {u.phone}") print() # Quick fake-token smell test (no network) if "FAKE" in u.token.upper() or "SCAFFOLD" in u.token.upper(): print("[SMELL] token contains 'FAKE' or 'SCAFFOLD' — definitely not real") print(" run A1 to overwrite with real token") sys.exit(0) # Real check via API call print("calling 996box get_today_open to verify token...") ok, msg = is_real_token(u.token) if ok: print(f"[OK] token is REAL — {msg}") else: print(f"[FAIL] token rejected by 996box — {msg}") print(" re-run A1 to get a fresh token")