/** * Xbox Cart History Switcher * 远程路径: https://raw.githubusercontent.com/dragonisheep/Surge/refs/heads/master/Scripts/CartHistorySwitcher.js * * 功能: * 1. 访问 https://carthistory.com/ → 展示所有历史 gamertag 卡片列表 * 2. 点击某条记录 → 访问 https://carthistory.com/?action=apply&index=N * → 将该条的 cartId / authorization / gamertag 覆盖到 $persistentStore * 3. 切换后自动跳回列表页,当前激活的卡片会高亮显示 */ const HISTORY_KEY = "cartId_history"; const CART_KEY = "cartId"; const AUTH_KEY = "authorization"; const GAMERTAG_KEY = "gamertag"; const url = $request.url; const parsed = new URL(url); const action = parsed.searchParams.get("action"); const indexStr = parsed.searchParams.get("index"); if (action === "apply" && indexStr !== null) { applySwitch(parseInt(indexStr, 10)); } else { showList(); } // ==================== 读取历史 ==================== function readHistory() { const raw = $persistentStore.read(HISTORY_KEY); if (!raw) return []; try { const arr = JSON.parse(raw); return Array.isArray(arr) ? arr : []; } catch (e) { return []; } } // ==================== 工具函数 ==================== function formatTimestamp(iso) { try { const d = new Date(iso); const pad = n => String(n).padStart(2, '0'); return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`; } catch (e) { return iso; } } function escapeHtml(s) { if (s == null) return ''; return String(s).replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c])); } function respondHtml(body) { $done({ response: { status: 200, headers: { "Content-Type": "text/html;charset=utf-8", "Cache-Control": "no-store, no-cache, must-revalidate", "Pragma": "no-cache" }, body: body } }); } // ==================== 展示列表 ==================== function showList() { const history = readHistory(); const currentCartId = $persistentStore.read(CART_KEY) || ""; const currentGamertag = $persistentStore.read(GAMERTAG_KEY) || ""; // 倒序(最新在前),同时记录在原数组中的 index 用于切换 const reversed = history.map((e, i) => ({ entry: e, originalIndex: i })).reverse(); const cards = reversed.map(({ entry, originalIndex }) => { const isActive = entry.cartId === currentCartId; const cardStyle = isActive ? 'border:2px solid #10b981; background:#f0fdf4;' : 'border:1px solid #e5e7eb; background:#fff;'; const activeBadge = isActive ? '当前激活' : ''; const button = isActive ? '' : ``; return `
${escapeHtml(entry.gamertag)}${activeBadge}
${escapeHtml(formatTimestamp(entry.timestamp))}
${button}
`; }).join(''); const emptyHint = history.length === 0 ? '
暂无历史记录
' : ''; const currentInfo = currentGamertag ? `
当前激活账号
${escapeHtml(currentGamertag)}
` : ''; const html = ` Cart History

🛒 Cart 账号历史

${currentInfo}
共 ${history.length} 条历史记录(最新在前)
${cards} ${emptyHint}
`; respondHtml(html); } // ==================== 执行切换 ==================== function applySwitch(index) { const history = readHistory(); if (!Number.isInteger(index) || index < 0 || index >= history.length) { return showError("无效的记录索引", `index=${index}, 历史长度=${history.length}`); } const entry = history[index]; if (!entry || !entry.cartId || !entry.authorization) { return showError("记录不完整", "该条记录缺少 cartId 或 authorization"); } // 覆盖 persistentStore 中的当前值 $persistentStore.write(entry.cartId, CART_KEY); $persistentStore.write(entry.authorization, AUTH_KEY); $persistentStore.write(entry.gamertag || "", GAMERTAG_KEY); $notification.post( "✅ 账号切换成功", `已切换到 ${entry.gamertag}`, "" ); const html = ` 切换成功
切换成功
已切换到 ${escapeHtml(entry.gamertag)}
1 秒后自动返回列表...
`; respondHtml(html); } // ==================== 错误页 ==================== function showError(title, detail) { const html = ` 错误
${escapeHtml(title)}
${escapeHtml(detail)}
返回列表
`; respondHtml(html); }