Files
Surge/Discard/NewAddToCart.js
2026-04-23 16:17:31 +08:00

157 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const MARKET = "NG";
const LOCALE = "en-ng";
const FRIENDLY_NAME = `cart-${MARKET}`;
const CLIENT_CONTEXT = { client: "UniversalWebStore.Cart", deviceType: "Pc" };
const LIST_RAW = $persistentStore.read("XboxProductList") || "{}";
const MUID = $persistentStore.read("cart-x-authorization-muid");
const MS_CV = $persistentStore.read("cart-ms-cv");
const generateRiskSessionId = () =>
"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 };
};
let parsed; try { parsed = JSON.parse(LIST_RAW); } catch { parsed = {}; }
const productList = Object.keys(parsed)
.filter(k => /^product\d+$/.test(k))
.sort((a,b) => toNum(a) - toNum(b))
.map(k => {
const norm = normEntry(parsed[k]);
return norm ? { key: k, ...norm } : null;
})
.filter(Boolean);
const results = { success: [], failure: [] };
const successKeys = [];
let currentIndex = 0;
const API_URL = "https://cart.production.store-web.dynamics.com/cart/v1.0/cart/loadCart?cartType=consumer&appId=StoreWeb";
const HEADERS = {
"content-type": "application/json",
"accept": "*/*",
"x-authorization-muid": MUID,
"sec-fetch-site": "cross-site",
"x-validation-field-1": "9pgbhbppjf2b",
"ms-cv": MS_CV,
"accept-language": "en-US,en;q=0.9",
"accept-encoding": "gzip, deflate, br",
"sec-fetch-mode": "cors",
"origin": "https://www.microsoft.com",
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) EdgiOS/133.0.3065.54 Version/18.0 Mobile/15E148 Safari/604.1",
"referer": "https://www.microsoft.com/",
"x-ms-vector-id": "",
"sec-fetch-dest": "empty"
};
function finalizeAndClean() {
const successCount = results.success.length;
const failureList = results.failure.join("\n");
let remainingCount = 0;
try {
let storeObj; try { storeObj = JSON.parse($persistentStore.read("XboxProductList") || "{}"); } catch { storeObj = {}; }
for (const k of successKeys) if (k && Object.prototype.hasOwnProperty.call(storeObj, k)) delete storeObj[k];
remainingCount = Object.keys(storeObj).filter(k => /^product\d+$/.test(k)).length;
$persistentStore.write(JSON.stringify(storeObj), "XboxProductList");
} catch (e) {
console.log("清理存储异常:" + e);
}
const subtitle = `成功: ${successCount} 个 / 共 ${productList.length}`;
const body = (failureList || "所有请求均成功") + `\n剩余待处理 product${remainingCount}`;
$notification.post("🎮 操作完成", subtitle, body);
$done();
}
function sendRequest() {
if (currentIndex >= productList.length) return finalizeAndClean();
const { key, productId, skuId, availabilityId } = productList[currentIndex];
const riskSessionId = generateRiskSessionId();
const idTriple = `${productId}/${skuId}/${availabilityId}`;
const timeoutId = setTimeout(() => {
recordResult(idTriple, "超时");
proceed();
}, 30000);
const bodyObj = {
locale: LOCALE,
market: MARKET,
catalogClientType: "storeWeb",
friendlyName: FRIENDLY_NAME,
riskSessionId,
clientContext: CLIENT_CONTEXT,
itemsToAdd: {
items: [
{
productId,
skuId,
availabilityId,
campaignId: "xboxcomct",
quantity: 1
}
]
}
};
$httpClient.put(
{ url: API_URL, headers: HEADERS, body: JSON.stringify(bodyObj) },
(error, response) => {
clearTimeout(timeoutId);
if (error || response.status !== 200) {
recordResult(idTriple, `HTTP ${response ? response.status : "Error"}`);
} else {
handleSuccess(idTriple, key);
}
proceed();
}
);
}
function handleSuccess(id, key) {
results.success.push(id);
if (key) successKeys.push(key);
console.log(`${id} (${key})`);
}
function recordResult(id, reason) {
results.failure.push(`${id}: ${reason}`);
console.log(`${id} - ${reason}`);
}
function proceed() {
currentIndex++;
setTimeout(sendRequest, 10);
}
if (!MUID || !MS_CV) {
console.log("缺少必要参数 MUID 或 MS_CV");
$notification.post("配置错误", "缺少必要参数 MUID 或 MS_CV", "");
$done();
} else if (productList.length === 0) {
console.log("XboxProductList 为空或无有效条目");
$notification.post("无任务", "XboxProductList 为空或无有效条目", "");
$done();
} else {
console.log(`开始执行请求(共 ${productList.length} 个)`);
sendRequest();
}