# -*- coding: utf-8 -*- """send_test.py —— 真实发送测试:1ms 签到页的**文字点选**。 只打这一条链路(用户指定): aid 195672344 (1ms.run) 入口 https://1ms.run/console/personal/benefits/check-in 题型 2404 文字点选(prehandle 会混发滑块/图标,脚本按 accept_kinds 刷新到文字点选为止) 遥测 --mode python_values(默认)= tcaptcha/tdc_values.py 的**纯离线**生成 脚本会 hook 客户端的 generate_telemetry,把这一颗 collect 的段几何打出来 —— 用来证明"发出去的确实是新链路生成的包",而不是旧模板回填。 用法: .venv/bin/python scripts/verify/send_test.py .venv/bin/python scripts/verify/send_test.py --mode python_keyed # 对照组:旧模板回填 """ import argparse import json import sys import time from pathlib import Path ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT)) sys.path.insert(0, str(ROOT / "tools")) import tcaptcha.protocol.client as client_mod # noqa: E402 from tcaptcha.protocol.client import (KIND_ICON_CLICK, KIND_SLIDER, # noqa: E402 KIND_TEXT_CLICK, TencentCaptchaClient) AID = "195672344" ENTRY = "https://1ms.run/console/personal/benefits/check-in" REFERER = "https://1ms.run/" KIND_MAP = { "text": (KIND_TEXT_CLICK,), "slider": (KIND_SLIDER,), "icon": (KIND_ICON_CLICK,), "any": (KIND_TEXT_CLICK, KIND_ICON_CLICK, KIND_SLIDER), } def main() -> int: ap = argparse.ArgumentParser(description="1ms 签到页文字点选 · 真实发送测试") ap.add_argument("--mode", default="python_values", choices=["python_values", "python_keyed", "python"]) ap.add_argument("--kind", default="text", choices=list(KIND_MAP), help="只解哪种题(默认 text=文字点选)") ap.add_argument("--max-refreshes", type=int, default=12) ap.add_argument("--max-retries", type=int, default=2) args = ap.parse_args() seen = {} real_gen = client_mod.generate_telemetry def hooked(tdc_code, points, **kw): t0 = time.time() out = real_gen(tdc_code, points, **kw) seen.update({ "source": out.get("source"), "collect_len": len(out.get("collect") or ""), "eks_len": len(out.get("eks") or ""), "gen_ms": int((time.time() - t0) * 1000), "points": [list(p) for p in points], }) # 段几何(新链路才有;旧模板回填没有 segments) if out.get("source") == "python_values": try: from tcaptcha.telemetry.crypto import split_collect_segments, xtea_decrypt_bytes import base64 plain = xtea_decrypt_bytes(base64.b64decode(out["collect"]), out["key"]).decode("latin1").rstrip("\x00") c1, traj, c2, sd = split_collect_segments(plain) seen["segments"] = [len(c1), len(traj), len(c2), len(sd)] seen["traj_points"] = len(json.loads(traj)) seen["traj_tail"] = json.loads(traj)[-1] except Exception as e: # noqa: BLE001 seen["segments_err"] = str(e)[:120] print("[hook] %s" % json.dumps(seen, ensure_ascii=False)) return out client_mod.generate_telemetry = hooked c = TencentCaptchaClient( aid=AID, entry_url=ENTRY, referer=REFERER, wb="1", accept_kinds=KIND_MAP[args.kind], telemetry_mode=args.mode, proxy=None, ) t0 = time.time() try: res = c.solve(max_retries=args.max_retries, max_refreshes=args.max_refreshes) finally: c.close() print() print("=" * 70) print("模式 : %s" % args.mode) print("题型 : %s" % args.kind) print("耗时 : %.1fs" % (time.time() - t0)) print("success : %s" % res.get("success")) print("kind : %s 指令=%r" % (res.get("kind"), res.get("instruction"))) print("points : %s" % res.get("points")) print("ticket : %r" % res.get("ticket")) print("randstr : %r" % res.get("randstr")) print("errorCode : %s" % (res.get("raw_response") or {}).get("errorCode")) print("原始响应 : %s" % json.dumps(res.get("raw_response") or {}, ensure_ascii=False)[:400]) print("本颗遥测 : %s" % json.dumps(seen, ensure_ascii=False)) print("error : %s" % (res.get("error") or "")[:200]) print("=" * 70) return 0 if __name__ == "__main__": raise SystemExit(main())