/** * 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 `