cdp_game_page.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. """Inspect the current 996box game page via CDP: what page are we on, is the
  2. session alive, is there a 启动 button for 玖扬复古176?
  3. Then click it (with capture running in background) to trigger the REAL
  4. launch flow: EnterGameClient -> openApp -> cq.exe -> cq2.exe -> TCP login.
  5. """
  6. import asyncio
  7. import base64
  8. import json
  9. import sys
  10. import httpx
  11. import websockets
  12. async def get_targets():
  13. async with httpx.AsyncClient(timeout=5) as c:
  14. r = await c.get("http://127.0.0.1:9222/json/list")
  15. return r.json()
  16. async def cdp(ws, msg_id, method, params=None):
  17. await ws.send(json.dumps({"id": msg_id, "method": method, "params": params or {}}))
  18. while True:
  19. msg = json.loads(await ws.recv())
  20. if msg.get("id") == msg_id:
  21. return msg.get("result", {})
  22. async def cdp_eval(ws, expr, msg_id):
  23. return await cdp(ws, msg_id, "Runtime.evaluate", {"expression": expr, "returnByValue": True})
  24. async def main():
  25. targets = await get_targets()
  26. print("=== targets ===")
  27. web_pages = []
  28. for t in targets:
  29. if t["type"] == "page":
  30. print(f" [{t['type']}] {t.get('title','')[:40]:<40} {t['url'][:70]}")
  31. if "http" in t["url"]:
  32. web_pages.append(t)
  33. if not web_pages:
  34. print("no web pages")
  35. return 1
  36. # Prefer the hzwlan/996box game page
  37. page = next((t for t in web_pages if "hzwlan" in t["url"] or "996box.com" in t["url"]), web_pages[0])
  38. print(f"\ninspecting: {page['url'][:70]}")
  39. async with websockets.connect(page["webSocketDebuggerUrl"], max_size=10**7) as ws:
  40. # 1. page state
  41. res = await cdp_eval(ws, """
  42. JSON.stringify({
  43. url: location.href.slice(0,80),
  44. title: document.title,
  45. bodyLen: document.body ? document.body.innerText.length : 0,
  46. bodyHead: document.body ? document.body.innerText.slice(0,300) : ''
  47. })
  48. """, 1)
  49. val = res.get("result", {}).get("value", "{}")
  50. try:
  51. st = json.loads(val)
  52. print(f"\nurl: {st['url']}")
  53. print(f"title: {st['title']}")
  54. print(f"body text (first 300):")
  55. print(f" {st['bodyHead'][:300]}")
  56. except Exception:
  57. print(val[:400])
  58. # 2. look for the game + start button
  59. res2 = await cdp_eval(ws, """
  60. (function() {
  61. // find any element mentioning 玖扬 or 复古 or the game id 206923
  62. const all = document.querySelectorAll('*');
  63. let gameEl = null;
  64. for (const el of all) {
  65. if (el.children.length === 0 && el.innerText && (
  66. el.innerText.includes('玖扬') || el.innerText.includes('复古176'))) {
  67. gameEl = el; break;
  68. }
  69. }
  70. // find start/launch buttons
  71. const starts = Array.from(document.querySelectorAll('button, [class*=start], [class*=launch], [class*=play]'))
  72. .filter(b => b.offsetParent && (b.innerText||'').match(/启动|开始|进入|继续/))
  73. .slice(0,10)
  74. .map(b => ({text: b.innerText.trim().slice(0,20), cls: (b.className||'').toString().slice(0,50)}));
  75. return JSON.stringify({
  76. foundGame: !!gameEl,
  77. gameText: gameEl ? gameEl.innerText.slice(0,40) : '',
  78. starts: starts
  79. });
  80. })()
  81. """, 2)
  82. val2 = res2.get("result", {}).get("value", "{}")
  83. try:
  84. g = json.loads(val2)
  85. print(f"\ngame found on page: {g['foundGame']} ({g['gameText']})")
  86. print(f"start buttons: {len(g['starts'])}")
  87. for s in g["starts"]:
  88. print(f" '{s['text']}' cls={s['cls'][:40]}")
  89. except Exception:
  90. print(val2[:400])
  91. # 3. screenshot
  92. shot = await cdp(ws, 3, "Page.captureScreenshot", {"format": "png"})
  93. if shot.get("data"):
  94. with open("cdp_game_page.png", "wb") as f:
  95. f.write(base64.b64decode(shot["data"]))
  96. print("\nscreenshot: cdp_game_page.png")
  97. return 0
  98. sys.exit(asyncio.run(main()))