From 3f7f67a4d2b03d926efd9f49efd51b30f0c7a651 Mon Sep 17 00:00:00 2001 From: XXhaos Date: Sat, 18 Apr 2026 11:27:53 +0800 Subject: [PATCH] Create capture_cart.js --- Scripts/capture_cart.js | 109 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 Scripts/capture_cart.js diff --git a/Scripts/capture_cart.js b/Scripts/capture_cart.js new file mode 100644 index 0000000..f59f76b --- /dev/null +++ b/Scripts/capture_cart.js @@ -0,0 +1,109 @@ +/** + * Surge 脚本:gamertag 捕获 + FIFO 配对写入 cartId_history + * - peoplehub 响应到达时捕获 gamertag + * - 若 pending_carts 有等候的 cart → 取最老一条配对 + * - 否则把 gamertag 快照 push 进 pending_gamertags 等待 + * + * Surge 配置: + * [Script] + * capture_gamertag = type=http-response, pattern=^https:\/\/peoplehub-public\.xboxlive\.com\/people\/gt\(.+\), requires-body=true, script-path=xxx.js + * + * [MITM] + * hostname = %APPEND% peoplehub-public.xboxlive.com + */ + +const peoplePattern = /^https:\/\/peoplehub-public\.xboxlive\.com\/people\/gt\(.+\)/; + +const url = $request.url; +const now = Date.now(); + +const PAIR_WINDOW_MS = 30000; +const MAX_QUEUE = 20; +const MAX_HISTORY = 100; + +if (peoplePattern.test(url)) { + if (!$response.body) { + console.log("peoplehub triggered but no response body, skip"); + } else { + try { + const body = JSON.parse($response.body); + const gamertag = body && body.people && body.people[0] && body.people[0].gamertag; + + if (!gamertag) { + console.log("[history] 响应中未找到 gamertag,跳过"); + } else { + if (gamertag !== $persistentStore.read("gamertag")) { + $persistentStore.write(gamertag, "gamertag"); + console.log(`Stored gamertag: ${gamertag}`); + $notification.post( + "Surge 信息存储", + "已捕获 gamertag", + `gamertag: ${gamertag}` + ); + } + + tryPairFromGamertag({ gamertag, ts: now }); + } + } catch (error) { + console.log(`Error (gamertag): ${error}`); + $notification.post("Surge 脚本错误", "gamertag 捕获失败", `${error}`); + } + } +} + +function tryPairFromGamertag(gtSnap) { + let pendingCart = readQueue("pending_carts"); + pendingCart = pendingCart.filter(c => (now - c.ts) <= PAIR_WINDOW_MS); + + if (pendingCart.length > 0) { + const cartSnap = pendingCart.shift(); + writeQueue("pending_carts", pendingCart); + + appendHistory({ + gamertag: gtSnap.gamertag, + cartId: cartSnap.cartId, + authorization: cartSnap.authorization, + timestamp: new Date().toISOString() + }); + + console.log(`[history] ✅ gamertag 到达触发配对: gamertag=${gtSnap.gamertag}, cartId=${cartSnap.cartId}`); + $notification.post("Surge 历史记录", "新三元组已记入", `${gtSnap.gamertag}`); + } else { + let pendingGT = readQueue("pending_gamertags"); + pendingGT = pendingGT.filter(g => (now - g.ts) <= PAIR_WINDOW_MS); + pendingGT.push(gtSnap); + if (pendingGT.length > MAX_QUEUE) pendingGT = pendingGT.slice(-MAX_QUEUE); + writeQueue("pending_gamertags", pendingGT); + + console.log(`[history] gamertag 入队等待,当前 pending_gamertags 长度: ${pendingGT.length}`); + } +} + +function readQueue(key) { + const raw = $persistentStore.read(key); + if (!raw) return []; + try { + const parsed = JSON.parse(raw); + return Array.isArray(parsed) ? parsed : []; + } catch (e) { return []; } +} + +function writeQueue(key, arr) { + $persistentStore.write(JSON.stringify(arr), key); +} + +function appendHistory(entry) { + let history = []; + const raw = $persistentStore.read("cartId_history"); + if (raw) { + try { + const parsed = JSON.parse(raw); + if (Array.isArray(parsed)) history = parsed; + } catch (e) { history = []; } + } + history.push(entry); + if (history.length > MAX_HISTORY) history = history.slice(-MAX_HISTORY); + $persistentStore.write(JSON.stringify(history), "cartId_history"); +} + +$done({});