/**
* 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 · 区域加购
选择加购区域
点击区域后将自动执行加购任务
`;
$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
? `加购失败的游戏:${failedNames.map(n => `- ${n}
`).join("")}
`
: "";
return `
Xbox · ${flag}${label} 结果
← 返回区域选择
${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);
}