/** * Xbox Cart Multi-Region Runner * 远程路径: https://raw.githubusercontent.com/dragonisheep/Surge/refs/heads/master/Scripts/AddMsGames.js * * 完全独立脚本,通过 https://addmsgames.com 触发 * * 使用方式: * - 访问 https://addmsgames.com → 显示区域选择界面 * - 访问 https://addmsgames.com/?region=US → 直接执行美区加购 * - 访问 https://addmsgames.com/?region=NG → 直接执行尼区加购 * - 访问 https://addmsgames.com/?region=AR → 直接执行阿区加购 */ const REGION_CONFIGS = { US: { label: "美区", flag: "🇺🇸", color: "#4a90e2", MARKET: "US", LOCALE: "en-us", FRIENDLY_NAME: "cart-US", MUID_KEY: "cart-x-authorization-muid", CV_KEY: "cart-ms-cv", LOCAL_KEY: "XboxProductList", CURRENCY: "USD", }, NG: { label: "尼区", flag: "🇳🇬", color: "#52b043", MARKET: "NG", LOCALE: "en-ng", FRIENDLY_NAME: "cart-NG", MUID_KEY: "cart-x-authorization-muid", CV_KEY: "cart-ms-cv", LOCAL_KEY: "XboxProductList", CURRENCY: "NGN", }, AR: { label: "阿区", flag: "🇦🇷", color: "#e8a838", MARKET: "AR", LOCALE: "es-ar", FRIENDLY_NAME: "cart-AR", MUID_KEY: "cart-x-authorization-muid", CV_KEY: "cart-ms-cv", LOCAL_KEY: "XboxProductList", CURRENCY: "ARS", }, }; const REMOTE_READ_URL = "https://xbox-bot.biubiubiu-lalala.workers.dev/surge?token=xbox123"; const REMOTE_COMMIT_URL = "https://xbox-bot.biubiubiu-lalala.workers.dev/surge/commit?token=xbox123"; const CLIENT_CONTEXT = { client: "UniversalWebStore.Cart", deviceType: "Pc" }; const API_URL = "https://cart.production.store-web.dynamics.com/cart/v1.0/cart/loadCart?cartType=consumer&appId=StoreWeb"; function getRegionParam() { try { const url = $request.url || ""; const m = url.match(/[?&]region=([A-Za-z]{2})/); if (m) return m[1].toUpperCase(); } catch (_) {} return null; } function serveSelector() { const html = ` Xbox · 区域加购
Xbox

选择加购区域

点击区域后将自动执行加购任务

🇺🇸
美区
MARKET: US · en-us
🇳🇬
尼区
MARKET: NG · en-ng
🇦🇷
阿区
MARKET: AR · es-ar
正在准备...
`; $done({ response: { status: 200, headers: { "Content-Type": "text/html;charset=utf-8", "Cache-Control": "no-store, no-cache, must-revalidate", "Pragma": "no-cache" }, body: html } }); } function runCart(regionCode) { const cfg = REGION_CONFIGS[regionCode]; if (!cfg) { $notification.post("❌ AddMsGames 错误", `未知区域: ${regionCode}`, ""); $done({}); return; } const { label, flag, color, MARKET, LOCALE, FRIENDLY_NAME, MUID_KEY, CV_KEY, LOCAL_KEY, CURRENCY } = cfg; const MUID = $persistentStore.read(MUID_KEY); const MS_CV = $persistentStore.read(CV_KEY); const HEADERS = { "content-type": "application/json", "accept": "*/*", "x-authorization-muid": MUID, "ms-cv": MS_CV, "origin": "https://www.microsoft.com", "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1" }; let logBuffer = []; const results = { success: [], failure: [] }; const successKeys = []; let currentIndex = 0; let productList = []; let sourceLabel = ""; let useRemote = false; function log(type, message, detail = "") { const icon = type === "success" ? "✅" : (type === "error" ? "❌" : "ℹ️"); const clr = type === "success" ? "#52b043" : (type === "error" ? "#e05050" : "#777"); console.log(`${icon} [${regionCode}] ${message} ${detail}`); logBuffer.push(`
  • ${icon} ${message} ${detail}
  • `); } const riskId = () => "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => (c === "x" ? (Math.random() * 16 | 0) : ((Math.random() * 4 | 8) | 0)).toString(16)); const toNum = k => { const m = /^product(\d+)$/.exec(k); return m ? parseInt(m[1], 10) : Number.MAX_SAFE_INTEGER; }; const normEntry = v => { if (!v || typeof v !== "object") return null; const productId = String(v.ProductId ?? v.productId ?? "").trim(); const skuId = String(v.SkuId ?? v.skuId ?? "").trim(); const availabilityId = String(v.AvailabilityId ?? v.availabilityId ?? "").trim(); if (!productId || !skuId || !availabilityId) return null; return { productId, skuId, availabilityId }; }; function parseProductList(raw) { let parsed; try { parsed = JSON.parse(raw || "{}"); } catch { parsed = {}; } return Object.keys(parsed) .sort((a, b) => toNum(a) - toNum(b)) .map(k => { const n = normEntry(parsed[k]); return n ? { key: k, ...n } : null; }) .filter(Boolean); } const normId = v => String(v ?? "").trim().toUpperCase(); const asArr = v => Array.isArray(v) ? v : []; function parseJsonBody(raw) { if (raw && typeof raw === "object") return { ok: true, value: raw }; try { return { ok: true, value: JSON.parse(String(raw || "{}")) }; } catch (e) { return { ok: false, error: String(e) }; } } function getStatusCode(response) { return Number(response && (response.status || response.statusCode)) || 0; } function collectLineItems(cart) { const out = []; const addItems = items => { for (const item of asArr(items)) { if (item && typeof item === "object") out.push(item); } }; addItems(cart && cart.lineItems); addItems(cart && cart.bundleLineItems); for (const bundle of asArr(cart && cart.bundleLineItems)) { addItems(bundle && bundle.lineItems); addItems(bundle && bundle.items); } return out; } function collectBusinessErrors(payload) { const events = payload && payload.events; if (!events || typeof events !== "object") return []; const found = []; const visit = (section, value) => { if (Array.isArray(value)) { for (const event of value) visit(section, event); return; } if (!value || typeof value !== "object") return; const data = value.data || {}; const status = Number(data.httpStatusCode || value.httpStatusCode || 0); const type = String(value.type || value.severity || "").toLowerCase(); if (type === "error" || status >= 400) { found.push({ section, event: value }); return; } for (const key of Object.keys(value)) { if (Array.isArray(value[key])) visit(`${section}.${key}`, value[key]); } }; for (const key of Object.keys(events)) visit(key, events[key]); return found; } function formatBusinessError(item) { const event = item.event || {}; const data = event.data || {}; const parts = []; if (item.section) parts.push(item.section); if (event.provider) parts.push(`provider=${event.provider}`); if (event.code) parts.push(`code=${event.code}`); if (data.reason) parts.push(`reason=${data.reason}`); if (Array.isArray(data.subReasons) && data.subReasons.length) { parts.push(`sub=${data.subReasons.filter(Boolean).join(" / ")}`); } if (data.httpStatusCode) parts.push(`http=${data.httpStatusCode}`); return parts.join(", ") || "unknown business error"; } function validateAddResult(rawBody, target) { const parsed = parseJsonBody(rawBody); if (!parsed.ok) { return { ok: false, reason: `响应不是合法 JSON: ${parsed.error}` }; } const payload = parsed.value || {}; const cart = payload.cart || {}; const market = cart.market ? String(cart.market).toUpperCase() : ""; const language = cart.language ? String(cart.language).toLowerCase() : ""; const contextProblems = []; if (market && market !== MARKET) contextProblems.push(`market=${cart.market}`); if (language && language !== LOCALE.toLowerCase()) contextProblems.push(`language=${cart.language}`); const errors = collectBusinessErrors(payload); const lineItems = collectLineItems(cart); const matchedLine = lineItems.find(item => normId(item.productId) === normId(target.productId) && normId(item.skuId) === normId(target.skuId) && normId(item.availabilityId) === normId(target.availabilityId) ); if (errors.length > 0) { const detail = errors.map(formatBusinessError).join(" | "); const context = contextProblems.length ? ` | context: ${contextProblems.join(", ")}` : ""; return { ok: false, reason: `${detail}${context} | lineItems=${lineItems.length}` }; } if (contextProblems.length > 0) { return { ok: false, reason: `购物车上下文不匹配: ${contextProblems.join(", ")} | lineItems=${lineItems.length}` }; } if (!matchedLine) { return { ok: false, reason: `HTTP 200 但未在 cart.lineItems 找到目标商品 | lineItems=${lineItems.length} | cartId=${cart.id || ""}` }; } const title = matchedLine.title ? ` | ${matchedLine.title}` : ""; const qty = matchedLine.quantity ? ` | qty=${matchedLine.quantity}` : ""; const amount = matchedLine.totalAmount != null ? ` | ${CURRENCY} ${Number(matchedLine.totalAmount).toFixed(2)}` : ""; return { ok: true, detail: `${cart.language || ""}/${cart.market || ""}${title}${qty}${amount}` }; } function buildResultPage(failedNames) { const sc = results.success.length; const fc = results.failure.length; const failedHtml = failedNames.length ? `
    加购失败的游戏:
    ` : ""; return ` Xbox · ${flag}${label} 结果 ← 返回区域选择
    ${flag} ${label} · 加购完成
    ${sc}
    成功
    ${fc}
    失败
    ${sc + fc}
    合计
    ${failedHtml}
    来源: ${sourceLabel}
    `; } function finalizeAndClean() { const fc = results.failure.length; const sc = results.success.length; const finish = (failedNames = []) => { const sub = fc === 0 ? `成功: ${sc}` : `成功: ${sc} / 失败: ${fc}`; $notification.post(`🛒 Xbox ${flag}${label} 加购完成`, sub, `来源: ${sourceLabel}`); $done({ response: { status: 200, headers: { "Content-Type": "text/html;charset=utf-8", "Cache-Control": "no-store, no-cache, must-revalidate", "Pragma": "no-cache" }, body: buildResultPage(failedNames) } }); }; if (useRemote) { const failedProducts = {}; let fi = 1; for (const item of productList) { if (results.failure.includes(item.productId)) { failedProducts[`product${fi++}`] = { ProductId: item.productId, SkuId: item.skuId, AvailabilityId: item.availabilityId }; } } log("info", fc === 0 ? "全部成功,提交 commit(弹出当前组)" : `${fc} 个失败,提交 commit(保留失败部分)`); $httpClient.post({ url: REMOTE_COMMIT_URL, headers: { "Content-Type": "application/json" }, body: JSON.stringify({ remaining: failedProducts }) }, (_e, _r, commitData) => { let info = {}; try { info = JSON.parse(commitData || "{}"); } catch (_) {} finish(info.failedNames || []); }); } else { try { let store; try { store = JSON.parse($persistentStore.read(LOCAL_KEY) || "{}"); } catch { store = {}; } for (const k of successKeys) { if (k && Object.prototype.hasOwnProperty.call(store, k)) delete store[k]; } const rem = Object.keys(store).filter(k => normEntry(store[k]) !== null).length; $persistentStore.write(JSON.stringify(store), LOCAL_KEY); log("info", "本地清理完成", `剩余: ${rem}`); } catch (e) { log("error", "清理异常", String(e)); } finish(); } } function sendRequest() { if (currentIndex >= productList.length) return finalizeAndClean(); const { key, productId, skuId, availabilityId } = productList[currentIndex]; $httpClient.put({ url: API_URL, headers: HEADERS, body: JSON.stringify({ locale: LOCALE, market: MARKET, catalogClientType: "storeWeb", friendlyName: FRIENDLY_NAME, riskSessionId: riskId(), clientContext: CLIENT_CONTEXT, itemsToAdd: { items: [ { productId, skuId, availabilityId, campaignId: "xboxcomct", quantity: 1 } ] } }) }, (error, response, data) => { const statusCode = getStatusCode(response); if (error || statusCode !== 200) { results.failure.push(productId); log("error", "失败", `${productId} | HTTP ${statusCode || "ERR"} ${error ? String(error) : ""}`); } else { const verdict = validateAddResult( data != null ? data : (response && response.body), { productId, skuId, availabilityId } ); if (verdict.ok) { results.success.push(productId); if (key) successKeys.push(key); log("success", "成功", `${productId}${verdict.detail ? " | " + verdict.detail : ""}`); } else { results.failure.push(productId); log("error", "失败", `${productId} | ${verdict.reason}`); } } currentIndex++; setTimeout(sendRequest, 50); }); } function doneWithPage(title, message, type = "warn") { const pageColor = type === "error" ? "#e05050" : type === "warn" ? "#e8a838" : "#52b043"; const icon = type === "error" ? "❌" : type === "warn" ? "⚠️" : "✅"; const html = ` Xbox · ${flag}${label}
    ${icon}
    ${title}
    ${message}
    `; $done({ response: { status: 200, headers: { "Content-Type": "text/html;charset=utf-8", "Cache-Control": "no-store, no-cache, must-revalidate", "Pragma": "no-cache" }, body: html } }); } function startTask() { if (!MUID || !MS_CV) { $notification.post(`❌ Xbox ${label} 错误`, "缺少 MUID 或 CV", `请写入 ${MUID_KEY} / ${CV_KEY}`); doneWithPage("缺少必要参数", `未找到 MUID 或 MS-CV,请确认已正确写入:

    ${MUID_KEY}
    ${CV_KEY}`, "error"); return; } if (productList.length === 0) { $notification.post(`⚠️ Xbox ${label}`, "列表为空,无需执行", `来源: ${sourceLabel}`); if (useRemote) { $httpClient.post({ url: REMOTE_COMMIT_URL, headers: { "Content-Type": "application/json" }, body: JSON.stringify({ remaining: {} }) }, () => { doneWithPage("暂无商品", `远程队列与本地列表均为空,无需加购。

    来源: ${sourceLabel}`, "warn"); }); } else { doneWithPage("暂无商品", `远程队列与本地列表均为空,无需加购。

    来源: ${sourceLabel}`, "warn"); } return; } log("info", `开始 ${flag}${label} 加购`, `数量: ${productList.length},来源: ${sourceLabel}`); sendRequest(); } $httpClient.get(REMOTE_READ_URL, (err, _res, data) => { let remoteGroup = null; let groupIndex = null; if (!err && data) { try { const p = JSON.parse((data || "").trim() || "{}"); if (p.ok && p.currentGroup && Object.keys(p.currentGroup).length > 0) { remoteGroup = p.currentGroup; groupIndex = p.currentGroupIndex; } } catch (_) {} } if (remoteGroup) { useRemote = true; sourceLabel = `远程第 ${groupIndex} 组`; log("info", "使用远程 Product", `${flag}${label} · 第 ${groupIndex} 组,共 ${Object.keys(remoteGroup).length} 个`); productList = parseProductList(JSON.stringify(remoteGroup)); } else { useRemote = false; sourceLabel = "本地"; productList = parseProductList($persistentStore.read(LOCAL_KEY) || "{}"); log("info", err ? `远程连接失败,使用本地 [${label}]` : `远程队列为空,使用本地 [${label}]`, err ? String(err) : ""); } startTask(); }); } const region = getRegionParam(); if (!region) { serveSelector(); } else { runCart(region); }