This commit is contained in:
2026-04-02 21:02:16 +08:00
commit 75b01d3e58
56 changed files with 3714 additions and 0 deletions

113
Scripts/XboxProductList.js Normal file
View File

@@ -0,0 +1,113 @@
// Surge: script-response-body
// 递归提取 GET 响应中 actionType == "Cart" 的 {ProductId,SkuId,AvailabilityId}
// 以 product1/product2… 顺序写入 XboxProductListProductId重复则跳过
// 通知:🆕 新增 / 🔁 已存在(不含 URL副标题仅显示「当前共有X个商品📦」
(function () {
const STORE_KEY = 'XboxProductList';
try {
if ($request?.method?.toUpperCase() !== 'GET') return $done({});
if (!$response?.body || typeof $response.body !== 'string') return $done({ body: $response?.body });
// 解析 JSON失败则尝试从文本抠出 JSON 片段
let data;
try {
data = JSON.parse($response.body);
} catch {
const m = $response.body.match(/(\{[\s\S]*\}|\[[\s\S]*\])/);
if (m) { try { data = JSON.parse(m[1]); } catch {} }
if (!data) return $done({ body: $response.body });
}
// 读取已有 store
let store = {};
try {
const raw = $persistentStore.read(STORE_KEY);
if (raw) store = JSON.parse(raw) || {};
} catch { store = {}; }
// 现有条目(仅 productN按数字排序
const entries = Object.keys(store)
.filter(k => /^product\d+$/.test(k))
.sort((a, b) => parseInt(a.slice(7)) - parseInt(b.slice(7)))
.map(k => store[k]);
// 【修改点1】简化判定逻辑只要 ProductId 一致,即判定为相同商品
const same = (a, b) =>
a && b &&
String(a.ProductId||'') === String(b.ProductId||'');
// 递归收集 Cart去重当前响应内
const found = [];
const seen = new Set();
const isObj = v => v && typeof v === 'object';
const visit = (node) => {
if (!isObj(node)) return;
if (typeof node.actionType === 'string' && node.actionType.toLowerCase() === 'cart') {
const args = node.actionArguments;
if (isObj(args)) {
const r = {
ProductId: String(args.ProductId ?? '').trim(),
SkuId: String(args.SkuId ?? '').trim(),
AvailabilityId: String(args.AvailabilityId ?? '').trim()
};
if (r.ProductId && r.SkuId && r.AvailabilityId) {
// 【修改点2】当前响应内部的去重 Set 也只记录 ProductId
const key = r.ProductId;
if (!seen.has(key)) { seen.add(key); found.push(r); }
}
}
}
if (Array.isArray(node)) node.forEach(visit);
else Object.keys(node).forEach(k => visit(node[k]));
};
visit(data);
if (found.length === 0) return $done({ body: $response.body });
// 拆分新增/已存在
const toAdd = [];
const existed = [];
for (const r of found) (entries.some(e => same(e, r)) ? existed : toAdd).push(r);
let title = '';
let detail = null;
if (toAdd.length > 0) {
// 追加为下一个 productN
let maxIndex = 0;
const keys = Object.keys(store).filter(k => /^product\d+$/.test(k));
if (keys.length) maxIndex = Math.max(...keys.map(k => parseInt(k.slice(7), 10) || 0));
for (const r of toAdd) {
const key = `product${++maxIndex}`;
store[key] = { ProductId: r.ProductId, SkuId: r.SkuId, AvailabilityId: r.AvailabilityId };
entries.push(store[key]);
}
$persistentStore.write(JSON.stringify(store), STORE_KEY);
title = '🆕 XboxProductList 已新增';
detail = toAdd[0];
} else {
title = '🔁 XboxProductList 已存在,跳过';
detail = existed[0];
}
// 统计当前商品总数(仅 productN 键)
const productCount = Object.keys(store).filter(k => /^product\d+$/.test(k)).length;
if (detail) {
$notification.post(
title,
`当前共有 ${productCount} 个商品📦`,
`信息如下:${JSON.stringify(detail)}`
);
}
return $done({ body: $response.body });
} catch (err) {
$notification.post('❌ Xbox 抓取脚本异常', '', String(err));
return $done({ body: $response?.body });
}
})();