diff --git a/Scripts/AddMsGames.js b/Scripts/AddMsGames.js
new file mode 100644
index 0000000..d82f591
--- /dev/null
+++ b/Scripts/AddMsGames.js
@@ -0,0 +1,601 @@
+/**
+ * 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 → 直接执行阿区加购
+ *
+ * PersistentStore Key 说明:
+ * - 美区 MUID: cart-us-x-authorization-muid
+ * - 美区 CV: cart-us-ms-cv
+ * - 美区 列表: XboxProductList-US
+ *
+ * - 尼区 MUID: cart-ng-x-authorization-muid
+ * - 尼区 CV: cart-ng-ms-cv
+ * - 尼区 列表: XboxProductList-NG
+ *
+ * - 阿区 MUID: cart-ar-x-authorization-muid
+ * - 阿区 CV: cart-ar-ms-cv
+ * - 阿区 列表: XboxProductList-AR
+ *
+ * 流程:
+ * 1. GET 读取远程当前组(服务端加锁,带 market 参数区分三区)
+ * 2. 执行加购
+ * 3. POST /surge/commit 提交结果
+ * 4. 若远程无数据,回退到本地对应区域的 XboxProductList-{REGION}
+ */
+
+// ========================= 区域配置 =========================
+const REGION_CONFIGS = {
+ US: {
+ label: "美区",
+ flag: "🇺🇸",
+ color: "#4a90e2",
+ MARKET: "US",
+ LOCALE: "en-us",
+ FRIENDLY_NAME:"cart-US",
+ MUID_KEY: "cart-us-x-authorization-muid",
+ CV_KEY: "cart-us-ms-cv",
+ LOCAL_KEY: "XboxProductList-US",
+ CURRENCY: "USD",
+ },
+ NG: {
+ label: "尼区",
+ flag: "🇳🇬",
+ color: "#52b043",
+ MARKET: "NG",
+ LOCALE: "en-ng",
+ FRIENDLY_NAME:"cart-NG",
+ MUID_KEY: "cart-ng-x-authorization-muid",
+ CV_KEY: "cart-ng-ms-cv",
+ LOCAL_KEY: "XboxProductList-NG",
+ CURRENCY: "NGN",
+ },
+ AR: {
+ label: "阿区",
+ flag: "🇦🇷",
+ color: "#e8a838",
+ MARKET: "AR",
+ LOCALE: "es-ar",
+ FRIENDLY_NAME:"cart-AR",
+ MUID_KEY: "cart-ar-x-authorization-muid",
+ CV_KEY: "cart-ar-ms-cv",
+ LOCAL_KEY: "XboxProductList-AR",
+ CURRENCY: "ARS",
+ },
+};
+
+const REMOTE_BASE_READ = "https://locvps.dragonisheep.com/surge?token=xbox123";
+const REMOTE_BASE_COMMIT = "https://locvps.dragonisheep.com/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";
+
+// ========================= 解析 region 参数 =========================
+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 REMOTE_READ_URL = `${REMOTE_BASE_READ}&market=${MARKET}`;
+ const COMMIT_URL = `${REMOTE_BASE_COMMIT}&market=${MARKET}`;
+
+ 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)
+ .filter(k => /^product\d+$/.test(k))
+ .sort((a, b) => toNum(a) - toNum(b))
+ .map(k => { const n = normEntry(parsed[k]); return n ? { key: k, ...n } : null; })
+ .filter(Boolean);
+ }
+
+ function buildResultPage(ngnStr, failedNames) {
+ const sc = results.success.length;
+ const fc = results.failure.length;
+ const failedHtml = failedNames.length
+ ? `加购失败的游戏:${failedNames.map(n => `- ${n}
`).join("")}
`
+ : "";
+ const priceHtml = ngnStr
+ ? `游戏总价 ${ngnStr}
`
+ : "";
+ return `
+
+
+
+
+Xbox · ${flag}${label} 结果
+
+
+
+← 返回区域选择
+
+
+${priceHtml}
+${failedHtml}
+来源: ${sourceLabel}
+
+
+`;
+ }
+
+ function finalizeAndClean() {
+ const fc = results.failure.length;
+ const sc = results.success.length;
+
+ const finish = (ngnStr = "", failedNames = []) => {
+ const priceNote = ngnStr ? ` | ${ngnStr}` : "";
+ const sub = fc === 0 ? `成功: ${sc}${priceNote}` : `成功: ${sc} / 失败: ${fc}${priceNote}`;
+ $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(ngnStr, 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: COMMIT_URL,
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ remaining: failedProducts })
+ }, (_e, _r, commitData) => {
+ let info = {};
+ try { info = JSON.parse(commitData || "{}"); } catch (_) {}
+ const total = info.groupNGN ?? info.successNGN ?? 0;
+ const ngnStr = total > 0 ? `${total.toFixed(2)} ${CURRENCY}` : "";
+ finish(ngnStr, 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 => /^product\d+$/.test(k)).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) => {
+ if (error || response.status !== 200) {
+ results.failure.push(productId);
+ log("error", "失败", productId);
+ } else {
+ results.success.push(productId);
+ if (key) successKeys.push(key);
+ log("success", "成功", productId);
+ }
+ currentIndex++;
+ setTimeout(sendRequest, 50);
+ });
+ }
+
+ function startTask() {
+ if (!MUID || !MS_CV) {
+ $notification.post(`❌ Xbox ${label} 错误`, `缺少 MUID 或 CV`, `请写入 ${MUID_KEY} / ${CV_KEY}`);
+ $done({});
+ return;
+ }
+ if (productList.length === 0) {
+ $notification.post(`⚠️ Xbox ${label}`, "列表为空,无需执行", `来源: ${sourceLabel}`);
+ if (useRemote) {
+ $httpClient.post({ url: COMMIT_URL, headers: { "Content-Type": "application/json" }, body: JSON.stringify({ remaining: {} }) }, () => $done({}));
+ } else {
+ $done({});
+ }
+ return;
+ }
+ log("info", `开始 ${flag}${label} 加购`, `数量: ${productList.length},来源: ${sourceLabel}`);
+ sendRequest();
+ }
+
+ // 主流程
+ $httpClient.get(REMOTE_READ_URL, (err, _res, data) => {
+ let remoteGroup = null, 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);
+}