cdp_recon_home.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. """Recon the 996box home page: exact game cards, their hrefs/gameIds, and
  2. which one is 玖扬复古176 (gameId 206923) vs the imposter that got launched
  3. last time. Never guess by text alone — match by gameId in href/data attrs.
  4. """
  5. import asyncio
  6. import json
  7. import sys
  8. import httpx
  9. import websockets
  10. async def main():
  11. async with httpx.AsyncClient(timeout=5) as c:
  12. r = await c.get("http://127.0.0.1:9222/json/list")
  13. home = next((t for t in r.json() if "homePage" in t.get("url", "")), None)
  14. if not home:
  15. print("no home page target")
  16. return 1
  17. async with websockets.connect(home["webSocketDebuggerUrl"], max_size=10**7) as ws:
  18. mid = 0
  19. async def ev(expr):
  20. nonlocal mid
  21. mid += 1
  22. await ws.send(json.dumps({"id": mid, "method": "Runtime.evaluate",
  23. "params": {"expression": expr, "returnByValue": True}}))
  24. while True:
  25. m = json.loads(await ws.recv())
  26. if m.get("id") == mid:
  27. return m.get("result", {}).get("result", {}).get("value")
  28. # 1. all elements carrying a gameId anywhere (href, data-*, class context)
  29. info = await ev(r"""
  30. (function() {
  31. const out = [];
  32. const all = document.querySelectorAll('a, [data-id], [data-gameid], [class*=game]');
  33. const seen = new Set();
  34. for (const el of all) {
  35. if (!el.offsetParent) continue;
  36. const href = el.getAttribute('href') || '';
  37. const did = el.getAttribute('data-id') || el.getAttribute('data-gameid') || '';
  38. let gid = '';
  39. const m = href.match(/gameId[=/](\d+)/) || (did.match(/^\d+$/) ? [null, did] : null);
  40. if (m) gid = m[1];
  41. const rect = el.getBoundingClientRect();
  42. const text = (el.innerText || '').trim();
  43. const label = text.split('\n').filter(l => l.trim()).slice(0, 2).join(' | ').slice(0, 50);
  44. const key = gid + '|' + label;
  45. if (seen.has(key)) continue;
  46. seen.add(key);
  47. if (gid || label.includes('复古') || label.includes('玖扬')) {
  48. out.push({gid, label, x: Math.round(rect.x + rect.width/2), y: Math.round(rect.y + rect.height/2),
  49. href: href.slice(0, 70)});
  50. }
  51. if (out.length >= 20) break;
  52. }
  53. return JSON.stringify(out);
  54. })()
  55. """)
  56. print("=== elements with gameId / 复古 / 玖扬 ===")
  57. try:
  58. for g in json.loads(info or "[]"):
  59. mark = " <<< TARGET" if g["gid"] == "206923" else ""
  60. print(f" gid={g['gid'] or '----':<7} '{g['label']}' @({g['x']},{g['y']}) {g['href'][:50]}{mark}")
  61. except Exception as e:
  62. print("parse err:", e)
  63. print((info or "")[:600])
  64. # 2. search input current state + where game suggestions render
  65. sr = await ev(r"""
  66. (function() {
  67. const inp = document.querySelector('input[placeholder]');
  68. if (!inp) return null;
  69. const r = inp.getBoundingClientRect();
  70. return JSON.stringify({ph: inp.placeholder, val: inp.value, x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)});
  71. })()
  72. """)
  73. print(f"\nsearch input: {sr}")
  74. # 3. What is the CURRENT highlighted/recommended game (the one with 启动)?
  75. cur = await ev(r"""
  76. (function() {
  77. const btns = [];
  78. for (const b of document.querySelectorAll('button, [class*=btn]')) {
  79. const t = (b.innerText || '').trim();
  80. if (/^(启动|开始游戏)$/.test(t) && b.offsetParent) {
  81. const r = b.getBoundingClientRect();
  82. // climb up to find the enclosing card's title
  83. let card = b.closest('[class*=game], [class*=card], [class*=item], li, div');
  84. let title = '';
  85. for (let i = 0; i < 6 && card; i++) {
  86. const h = card.querySelector('[class*=name], [class*=title], h3, h4, .title');
  87. if (h) { title = (h.innerText || '').trim().slice(0, 40); break; }
  88. card = card.parentElement;
  89. }
  90. btns.push({text: t, x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2), cardTitle: title});
  91. }
  92. }
  93. return JSON.stringify(btns.slice(0, 8));
  94. })()
  95. """)
  96. print(f"\n启动 buttons + their card titles:")
  97. try:
  98. for b in json.loads(cur or "[]"):
  99. print(f" '{b['text']}' @({b['x']},{b['y']}) card='{b['cardTitle']}'")
  100. except Exception:
  101. print((cur or "")[:400])
  102. return 0
  103. sys.exit(asyncio.run(main()))