From 952f312fbca03a5018dcc351f2451d2bc7695784 Mon Sep 17 00:00:00 2001 From: XXhaos Date: Fri, 3 Apr 2026 15:43:33 +0800 Subject: [PATCH] Delete Surge-main directory --- Surge-main/Discard/AddToCart.js | 129 ------------- .../Discard/CoreHaloLinkCollector.sgmodule | 24 --- Surge-main/Discard/GetProductId.js | 41 ----- Surge-main/Discard/corehalo_capture.js | 51 ------ Surge-main/Discard/corehalo_dump.js | 84 --------- Surge-main/Modules/BuyRequestReplace.sgmodule | 12 -- Surge-main/Modules/MS-Family-Block.sgmodule | 11 -- Surge-main/Modules/Q-Search-Plus.sgmodule | 171 ------------------ Surge-main/Modules/XboxCartWeb.sgmodule | 16 -- Surge-main/Modules/XboxParamCapturer.sgmodule | 26 --- Surge-main/Modules/XboxWebController.sgmodule | 26 --- Surge-main/Modules/Xbox_Rewrite.sgmodule | 17 -- Surge-main/Modules/batch_approval.sgmodule | 13 -- Surge-main/README.md | 2 - Surge-main/Scripts/Add8TFDlcToCart.js | 103 ----------- Surge-main/Scripts/ApprovalCartId.js | 56 ------ Surge-main/Scripts/AutoClearApprovalCartId.js | 22 --- Surge-main/Scripts/BuyRequestReplace.js | 83 --------- Surge-main/Scripts/CartParameter.js | 89 --------- Surge-main/Scripts/ClearApprovalCartId.js | 48 ----- .../Scripts/ClearXboxProductList_Web.js | 48 ----- Surge-main/Scripts/NewAddToCart.js | 156 ---------------- Surge-main/Scripts/NewAddToCart_Web.js | 102 ----------- Surge-main/Scripts/SyncXboxCloud.js | 171 ------------------ Surge-main/Scripts/XboxProductList.js | 113 ------------ Surge-main/Scripts/authorization&cartId.js | 44 ----- Surge-main/Scripts/batch_purchase_send.js | 141 --------------- Surge-main/Scripts/ms_family_block.js | 58 ------ 28 files changed, 1857 deletions(-) delete mode 100644 Surge-main/Discard/AddToCart.js delete mode 100644 Surge-main/Discard/CoreHaloLinkCollector.sgmodule delete mode 100644 Surge-main/Discard/GetProductId.js delete mode 100644 Surge-main/Discard/corehalo_capture.js delete mode 100644 Surge-main/Discard/corehalo_dump.js delete mode 100644 Surge-main/Modules/BuyRequestReplace.sgmodule delete mode 100644 Surge-main/Modules/MS-Family-Block.sgmodule delete mode 100644 Surge-main/Modules/Q-Search-Plus.sgmodule delete mode 100644 Surge-main/Modules/XboxCartWeb.sgmodule delete mode 100644 Surge-main/Modules/XboxParamCapturer.sgmodule delete mode 100644 Surge-main/Modules/XboxWebController.sgmodule delete mode 100644 Surge-main/Modules/Xbox_Rewrite.sgmodule delete mode 100644 Surge-main/Modules/batch_approval.sgmodule delete mode 100644 Surge-main/README.md delete mode 100644 Surge-main/Scripts/Add8TFDlcToCart.js delete mode 100644 Surge-main/Scripts/ApprovalCartId.js delete mode 100644 Surge-main/Scripts/AutoClearApprovalCartId.js delete mode 100644 Surge-main/Scripts/BuyRequestReplace.js delete mode 100644 Surge-main/Scripts/CartParameter.js delete mode 100644 Surge-main/Scripts/ClearApprovalCartId.js delete mode 100644 Surge-main/Scripts/ClearXboxProductList_Web.js delete mode 100644 Surge-main/Scripts/NewAddToCart.js delete mode 100644 Surge-main/Scripts/NewAddToCart_Web.js delete mode 100644 Surge-main/Scripts/SyncXboxCloud.js delete mode 100644 Surge-main/Scripts/XboxProductList.js delete mode 100644 Surge-main/Scripts/authorization&cartId.js delete mode 100644 Surge-main/Scripts/batch_purchase_send.js delete mode 100644 Surge-main/Scripts/ms_family_block.js diff --git a/Surge-main/Discard/AddToCart.js b/Surge-main/Discard/AddToCart.js deleted file mode 100644 index 0fef111..0000000 --- a/Surge-main/Discard/AddToCart.js +++ /dev/null @@ -1,129 +0,0 @@ -// ==== 配置项 ==== // -const PRODUCT_IDS = $persistentStore.read("TempProductId"); // 格式:id1&id2 -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).toString(16) : (Math.random()*4|8).toString(16))); - -// ==== 执行逻辑 ==== // -const productIdArray = PRODUCT_IDS?.split("&") || []; -const results = { success: [], failure: [] }; -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": "ha-Latn-NG,ha;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 sendRequest() { - if (currentIndex >= productIdArray.length) { - const successCount = results.success.length; - const failureList = results.failure.join("\n"); - - // 如果全部请求成功,则清空 TempProductId - if (results.failure.length === 0) { - $persistentStore.write("", "TempProductId"); - } - - $notification.post( - "🎮 操作完成", - `成功: ${successCount}个`, - failureList || "所有请求均成功,TempProductId已清空" - ); - $done(); - return; - } - - const productId = productIdArray[currentIndex]; - const riskSessionId = generateRiskSessionId(); - const timeoutId = setTimeout(() => { - recordResult(productId, "超时"); - proceed(); - }, 30000); - - // 发送skuId为0001的请求 - $httpClient.put({ - url: API_URL, - headers: HEADERS, - body: JSON.stringify({ - locale: "en-ng", - market: "NG", - catalogClientType: "storeWeb", - friendlyName: "cart-NG", - riskSessionId: riskSessionId, - clientContext: { client: "UniversalWebStore.Cart", deviceType: "Pc" }, - itemsToAdd: { items: [{ productId, skuId: "0001", quantity: 1 }] } - }) - }, (error1, response1) => { - clearTimeout(timeoutId); - if (error1 || response1.status !== 200) { - recordResult(productId, `HTTP ${response1 ? response1.status : "Error1"}`); - proceed(); - return; - } - - // 发送skuId为0010的请求 - $httpClient.put({ - url: API_URL, - headers: HEADERS, - body: JSON.stringify({ - locale: "en-ng", - market: "NG", - catalogClientType: "storeWeb", - friendlyName: "cart-NG", - riskSessionId: riskSessionId, - clientContext: { client: "UniversalWebStore.Cart", deviceType: "Pc" }, - itemsToAdd: { items: [{ productId, skuId: "0010", quantity: 1 }] } - }) - }, (error2, response2) => { - if (error2 || response2.status !== 200) { - recordResult(productId, `HTTP ${response2 ? response2.status : "Error2"}`); - } else { - // 两次请求都成功 - handleSuccess(productId); - } - proceed(); - }); - }); -} - -// ==== 辅助函数 ==== // -function handleSuccess(id) { - results.success.push(id); - console.log(`✅ ${id}`); -} - -function recordResult(id, reason) { - results.failure.push(`${id}: ${reason}`); - console.log(`❌ ${id} - ${reason}`); -} - -function proceed() { - currentIndex++; - setTimeout(sendRequest, 10); // 请求间隔0.01秒 -} - -// ==== 启动检查 ==== // -if (!MUID || !PRODUCT_IDS) { - console.log("⚠️ 配置错误 - 缺少必要参数 MUID 或 PRODUCT_IDS"); - $notification.post("配置错误", "缺少必要参数", ""); - $done(); -} else { - console.log("🚀 开始执行请求"); - sendRequest(); -} diff --git a/Surge-main/Discard/CoreHaloLinkCollector.sgmodule b/Surge-main/Discard/CoreHaloLinkCollector.sgmodule deleted file mode 100644 index 924ee23..0000000 --- a/Surge-main/Discard/CoreHaloLinkCollector.sgmodule +++ /dev/null @@ -1,24 +0,0 @@ -#!name=CoreHalo Link Collector -#!desc=Capture Xianyu/Goofish links, expose at https://corehalo.dump/ -#!author=Ah Long -#!category=XBOX -#!version=1.4 -#!homepage=https://github.com/XXhaos/Surge - -[Host] -# 将 corehalo.dump 解析到 Surge 虚拟 IP -corehalo.dump = 198.18.0.1 - -[Script] -# 1. 捕获脚本 (保持原样,匹配闲鱼域名) -corehalo-capture = type=http-request, pattern=https?://h5\.m\.goofish\.com/.*reminderUrl=.+, requires-body=0, timeout=5, script-path=https://raw.githubusercontent.com/XXhaos/Surge/main/corehalo_capture.js - -# 2. 导出脚本 (修改点) -# - 正则改为匹配 https://corehalo.dump/ (兼容 http) -# - 去掉了 fetch 路径,匹配根路径 -corehalo-dump = type=http-request, pattern=^https?://corehalo\.dump/?$, requires-body=0, timeout=5, script-path=https://raw.githubusercontent.com/XXhaos/Surge/main/corehalo_dump.js - -[MITM] -# 必须包含 corehalo.dump 才能解密 HTTPS 流量 -# 同时也需要包含闲鱼域名(h5.m.goofish.com)以确保捕获功能正常 -hostname = %APPEND% corehalo.dump, h5.m.goofish.com diff --git a/Surge-main/Discard/GetProductId.js b/Surge-main/Discard/GetProductId.js deleted file mode 100644 index d45a11a..0000000 --- a/Surge-main/Discard/GetProductId.js +++ /dev/null @@ -1,41 +0,0 @@ -// Surge 脚本:从特定URL中提取并更新 TempProductId - -const key = "TempProductId"; - -// 获取已有 TempProductId 的值 -const existingIds = $persistentStore.read(key); - -// 从URL提取新的产品ID (仅匹配特定的 xbox 链接) -const url = $request.url; - -// 改进正则表达式,匹配 store/ 后面的游戏ID(支持大小写) -const matches = url.match(/^https:\/\/www\.xbox\.com\/[eE][nN]-[uU][sS]\/games\/store\/[^\/]+\/([^\/?]+)/); - -if (matches && matches[1]) { - const newProductId = matches[1]; - - // 将已有的 TempProductId 分割为数组 - const existingIdArray = existingIds ? existingIds.split("&") : []; - - if (!existingIdArray.includes(newProductId)) { - // 如果已有内容不为空,则先加入 '&' 再追加新ID - const finalProductId = existingIdArray.length > 0 - ? `${existingIdArray.join("&")}&${newProductId}` - : newProductId; - - // 更新 TempProductId 的值 - $persistentStore.write(finalProductId, key); - - // 控制台输出操作 - console.log(`✅ 已更新 TempProductId: ${finalProductId}`); - - // 发送通知表示操作完成 - $notification.post("✅ 操作成功", "已更新 TempProductId", finalProductId); - } else { - console.log(`⚠️ TempProductId 未更新,已存在: ${newProductId}`); - $notification.post("⚠️ 操作跳过", "TempProductId 已存在", newProductId); - } -} - -// 结束脚本 -$done(); diff --git a/Surge-main/Discard/corehalo_capture.js b/Surge-main/Discard/corehalo_capture.js deleted file mode 100644 index fab1a23..0000000 --- a/Surge-main/Discard/corehalo_capture.js +++ /dev/null @@ -1,51 +0,0 @@ -// corehalo_capture.js -// -// 触发:请求 URL 匹配 h5.m.goofish.com/...reminderUrl=... -// 逻辑: -// 1. 从 $request.url 提取 reminderUrl= 后的编码串 -// 2. decodeURIComponent -> 真正目标链接 realLink -// 3. 保存到 persistentStore("corehalo_links") -// 4. 发通知,提示捕获到了什么 - -let reqUrl = $request && $request.url ? $request.url : ""; - -// 提取 reminderUrl= 后面的编码内容 -let m = reqUrl.match(/reminderUrl=([^&]+)/); - -if (m && m[1]) { - // decode 出真实外链 - let realLink = decodeURIComponent(m[1]); - - // 从持久化存储读现有列表 - let raw = $persistentStore.read("corehalo_links") || "[]"; - let list; - try { - list = JSON.parse(raw); - if (!Array.isArray(list)) { - list = []; - } - } catch (e) { - list = []; - } - - // 去重后推入 - let added = false; - if (!list.includes(realLink)) { - list.push(realLink); - $persistentStore.write(JSON.stringify(list), "corehalo_links"); - added = true; - } - - // 给你发一条通知,告诉你本次抓到的情况 - // 标题:CoreHalo Capture - // 副标题:Added / Duplicate - // 正文:具体链接 - $notification.post( - "CoreHalo Capture", - added ? "Added to list" : "Already in list", - realLink - ); -} - -// 放行原始请求 -$done({}); diff --git a/Surge-main/Discard/corehalo_dump.js b/Surge-main/Discard/corehalo_dump.js deleted file mode 100644 index 24124cf..0000000 --- a/Surge-main/Discard/corehalo_dump.js +++ /dev/null @@ -1,84 +0,0 @@ -/* - * CoreHalo Web Dump - * 作用:访问 http://corehalo.dump/fetch 时,以网页形式显示捕获的链接并清空存储 - */ - -// 1. 读取数据 -let raw = $persistentStore.read("corehalo_links") || "[]"; -let list; -try { - list = JSON.parse(raw); - if (!Array.isArray(list)) list = []; -} catch (e) { - list = []; -} - -const count = list.length; - -// 2. 发送通知 (保持原有的系统通知功能) -if (count > 0) { - $notification.post("CoreHalo Dump", `捕获 ${count} 条链接`, "已在浏览器显示并清空"); -} else { - $notification.post("CoreHalo Dump", "没有新链接", "列表为空"); -} - -// 3. 准备 HTML 内容 -// 生成列表项 HTML -const listHtml = list.map((link, index) => ` -
- ${index + 1}. - ${link} -
-`).join(""); - -// 页面样式 -const css = ` - -`; - -const bodyContent = count > 0 - ? `
${listHtml}
` - : `
📭 暂无捕获的链接
`; - -const html = ` - - - - - - CoreHalo Links - ${css} - - -
-

捕获列表 ${count}

- ${bodyContent} - -
- -`; - -// 4. 清空存储 (提取后即焚) -$persistentStore.write("[]", "corehalo_links"); - -// 5. 返回网页响应 -$done({ - response: { - status: 200, - headers: { "Content-Type": "text/html;charset=utf-8" }, - body: html - } -}); diff --git a/Surge-main/Modules/BuyRequestReplace.sgmodule b/Surge-main/Modules/BuyRequestReplace.sgmodule deleted file mode 100644 index 8cf5c49..0000000 --- a/Surge-main/Modules/BuyRequestReplace.sgmodule +++ /dev/null @@ -1,12 +0,0 @@ -#!name=Xbox Buy Request Replace -#!desc=替换购买请求参数 (RequestParentalApproval) -#!category=XBOX -#!author=Ah Long - -[Script] -# 替换购买请求参数 -# 触发条件:RequestParentalApproval 接口 -BuyRequestReplace = type=http-request, pattern=^https://buynow\.production\.store-web\.dynamics\.com/v1\.0/Cart/RequestParentalApproval, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/BuyRequestReplace.js, requires-body=1, max-size=0, binary-body-mode=0, script-update-interval=0 - -[MITM] -hostname = %APPEND% buynow.production.store-web.dynamics.com diff --git a/Surge-main/Modules/MS-Family-Block.sgmodule b/Surge-main/Modules/MS-Family-Block.sgmodule deleted file mode 100644 index 0effbfa..0000000 --- a/Surge-main/Modules/MS-Family-Block.sgmodule +++ /dev/null @@ -1,11 +0,0 @@ -#!name=Microsoft Family Block -#!desc=拦截 Microsoft Family 中指定的 ProductId 购买请求 (9PNTSH5SKCL5等) -#!category=XBOX -#!author=Ah Long - -[Script] -# logic: 检查 POST body 是否包含黑名单中的 ID -MS_Family_Block = type=http-request, pattern=^https://account\.microsoft\.com/family/api/buy/requests/complete(\?.*)?$, requires-body=1, max-size=0, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/ms_family_block.js, script-update-interval=-1, timeout=10, debug=0, script-text=var targetIds=["9PNTSH5SKCL5","9nfmccp0pm67","9npbvj8lwsvn","9pcgszz8zpq2","9P54FF0VQD7R","9NCJZN3LBD3P","9P9CLTVLLHD6","9NHXDFLDBN6G"];var body=$request.body;if($request.method==="POST"&&body){var upperBody=body.toUpperCase();for(var i=0;i https://t.me/ddgksf2021 谢谢合作! -# - https://github.com/ddgksf2013/Rewrite/raw/master/Html/Q-Search.conf -############################################## - - -[URL Rewrite] - -#>>>>>>>>>>>>>>>>>>>>>>>自用 -# TMDB -^https:\/\/.*bing.com\/search\?q=tmdb\+([^&]+).+ https://www.themoviedb.org/search?query=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+tmdb.+ https://www.themoviedb.org/search?query=$1 302 -# ng (切换至尼日利亚区) -^https:\/\/.*bing.com\/search\?q=ng&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143561&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=ng&urlDesc= 302 -# pp xxx (perplexity) -^https:\/\/.*bing.com\/search\?q=pp\+([^&]+).+ https://www.perplexity.ai/search?q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+pp.+ https://www.perplexity.ai/search?q=$1 302 -#tf (TestFlight) -^https:\/\/.*bing.com\/search\?q=tf(\+|%20)([^&]+).+ https://www.google.com/search?as_q=$2&as_sitesearch=testflight.apple.com 302 - -#>>>>>>>>>>>>>>>>>>>>>>>翻译 -# yd xxx (有道词典) -^https:\/\/.*bing.com\/search\?q=yd\+([^&]+).+ http://dict.youdao.com/search?q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+yd.+ http://dict.youdao.com/search?q=$1 302 -# trc xxx (Google 译至中) -^https:\/\/.*bing.com\/search\?q=trc\+([^&]+).+ https://translate.google.com/#view=home&op=translate&sl=auto&tl=zh-CN&text=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+trc.+ https://translate.google.com/#view=home&op=translate&sl=auto&tl=zh-CN&text=$1 302 -# tre xxx (Google 译至英) -^https:\/\/.*bing.com\/search\?q=tre\+([^&]+).+ https://translate.google.com/#view=home&op=translate&sl=auto&tl=en&text=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+tre.+ https://translate.google.com/#view=home&op=translate&sl=auto&tl=en&text=$1 302 -# trj xxx (Google 译至日) -^https:\/\/.*bing.com\/search\?q=trj\+([^&]+).+ https://translate.google.com/#view=home&op=translate&sl=auto&tl=ja&text=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+trj.+ https://translate.google.com/#view=home&op=translate&sl=auto&tl=ja&text=$1 302 - -#>>>>>>>>>>>>>>>>>>>>>>>社区 -# tt xxx (头条) -^https:\/\/.*bing.com\/search\?q=tt\+([^&]+).+ https://so.toutiao.com/search?keyword=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+tt.+ https://so.toutiao.com/search?keyword=$1 302 -# db xxx (豆瓣) -^https:\/\/.*bing.com\/search\?q=db\+([^&]+).+ https://m.douban.com/search?query=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+db.+ https://m.douban.com/search?query=$1 302 -# zh xxx (知乎) -^https:\/\/.*bing.com\/search\?q=zh\+([^&]+).+ http://www.zhihu.com/search?q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+zh.+ http://www.zhihu.com/search?q=$1 302 -# wb xxx (微博) -^https:\/\/.*bing.com\/search\?q=wb\+([^&]+).+ https://s.weibo.com/weibo/$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+wb.+ https://s.weibo.com/weibo/$1 302 -# wx xxx (微信) -^https:\/\/.*bing.com\/search\?q=wx\+([^&]+).+ https://weixin.sogou.com/weixinwap?query=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+wx.+ https://weixin.sogou.com/weixinwap?query=$1 302 -# up xxx (Unsplash) -^https:\/\/.*bing.com\/search\?q=up\+([^&]+).+ https://unsplash.com/s/photos/$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+up.+ https://unsplash.com/s/photos/$1 302 -# sspai xxx (少数派站内搜索) -^https:\/\/.*bing.com\/search\?q=sspai\+([^&]+).+ https://sspai.com/search/post/$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+sspai.+ https://sspai.com/search/post/$1 302 -# ssp xxx (Google 搜索少数派) -^https:\/\/.*bing.com\/search\?q=ssp\+([^&]+).+ https://www.google.com/search?as_q=$1&as_sitesearch=sspai.com 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+ssp.+ https://www.google.com/search?as_q=$1&as_sitesearch=sspai.com 302 -# tw xxx (Twitter) -^https:\/\/.*bing.com\/search\?q=tw\+([^&]+).+ https://twitter.com/search?q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+tw.+ https://twitter.com/search?q=$1 302 -# gh xxx (GitHub) -^https:\/\/.*bing.com\/search\?q=gh\+([^&]+).+ https://github.com/search?q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+gh.+ https://github.com/search?q=$1 302 -# gu xxx (GitHub User) -^https:\/\/.*bing.com\/search\?q=gu\+([^&]+).+ https://github.com/search?q=$1&type=users 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+gu.+ https://github.com/search?q=$1&type=users 302 -# gc xxx (GitHub Code) -^https:\/\/.*bing.com\/search\?q=gc\+([^&]+).+ https://github.com/search?o=desc&q=$1&s=indexed&type=Code 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+gc.+ https://github.com/search?o=desc&q=$1&s=indexed&type=Code 302 -# so xxx (Stack Overflow) -^https:\/\/.*bing.com\/search\?q=so\+([^&]+).+ https://stackoverflow.com/search?q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+so.+ https://stackoverflow.com/search?q=$1 302 -# se xxx (StackExchange) -^https:\/\/.*bing.com\/search\?q=se\+([^&]+).+ https://stackexchange.com/search?q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+se.+ https://stackexchange.com/search?q=$1 302 -# wa xxx (WolframAlpha) -^https:\/\/.*bing.com\/search\?q=wa\+([^&]+).+ https://www.wolframalpha.com/input/?i=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+wa.+ https://www.wolframalpha.com/input/?i=$1 302 -# rd xxx (Reddit) -^https:\/\/.*bing.com\/search\?q=rd\+([^&]+).+ https://www.reddit.com/search?q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+rd.+ https://www.reddit.com/search?q=$1 302 - -#>>>>>>>>>>>>>>>>>>>>>>>购物 -# zdm xxx (什么值得买) -^https:\/\/.*bing.com\/search\?q=zdm\+([^&]+).+ https://search.m.smzdm.com/?v=b&s=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+zdm.+ https://search.m.smzdm.com/?v=b&s=$1 302 -# jd xxx (京东) -^https:\/\/.*bing.com\/search\?q=jd\+([^&]+).+ openapp.jdmobile://virtual?params={"des":"productList","keyWord":"$1","from":"search","category":"jump"} 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+jd.+ openapp.jdmobile://virtual?params={"des":"productList","keyWord":"$1","from":"search","category":"jump"} 302 -# tb xxx (淘宝) -^https:\/\/.*bing.com\/search\?q=tb\+([^&]+).+ taobao://s.taobao.com?q=$1 302 -^https:\/\/.*bing.com\/search\q=([^+]+)\+tb.+ taobao://s.taobao.com?q=$1 302 - -#>>>>>>>>>>>>>>>>>>>>>>>视频 -# yt xxx (YouTube) -^https:\/\/.*bing.com\/search\?q=yt\+([^&]+).+ https://www.youtube.com/results?search_query=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+yt.+ https://www.youtube.com/results?search_query=$1 302 -# bli xxx (哔哩哔哩) -^https:\/\/.*bing.com\/search\?q=bli\+([^&]+).+ https://m.bilibili.com/search?keyword=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+bli.+ https://m.bilibili.com/search?keyword=$1 302 -# gd xxx (Google 搜索 Google Drive 资源) -^https:\/\/.*bing.com\/search\?q=gd\+([^&]+).+ https://www.google.com/search?q=%22Google+Drive%22+$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+gd.+ https://www.google.com/search?q=%22Google+Drive%22+$1 302 -# tgd xxx (t.me/gdurl 搜索 Google Drive 资源) -^https:\/\/.*bing.com\/search\?q=tgd\+([^&]+).+ https://t.me/s/gdurl?q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+tgd.+ https://t.me/s/gdurl?q=$1 302 -# ph xxx (PornHub) -^https:\/\/.*bing.com\/search\?q=ph\+([^&]+).+ https://cn.pornhub.com/video/search?search=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+ph.+ https://cn.pornhub.com/video/search?search=$1 302 -# af xxx (Acfun) -^https:\/\/.*bing.com\/search\?q=af\+([^&]+).+ https://www.acfun.cn/search?keyword=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+af.+ https://www.acfun.cn/search?keyword=$1 302 -# ys xxx (搜片) -^https:\/\/.*bing.com\/search\?q=ys\+([^&]+).+ https://soupian.icu/search?key=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+ys.+ https://soupian.icu/search?key=$1 302 - -#>>>>>>>>>>>>>>>>>>>>>>>苹果商店切换 -# cn (切换至中国区) -^https:\/\/.*bing.com\/search\?q=cn&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143465&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=cn&urlDesc= 302 -# hk (切换至香港区) -^https:\/\/.*bing.com\/search\?q=hk&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143463&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=hk&urlDesc= 302 -# tw (切换至台湾区) -^https:\/\/.*bing.com\/search\?q=tw&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143470&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=tw&urlDesc= 302 -# us (切换至美国区) -^https:\/\/.*bing.com\/search\?q=us&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143441&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=us&urlDesc= 302 -# jp (切换至日本区) -^https:\/\/.*bing.com\/search\?q=jp&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143462&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=jp&urlDesc= 302 -# kr (切换至韩国区) -^https:\/\/.*bing.com\/search\?q=kr&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143466&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=kr&urlDesc= 302 -# tr (切换至土耳其区) -^https:\/\/.*bing.com\/search\?q=tr&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143480&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=tr&urlDesc= 302 -# sg (切换至新加坡区) -^https:\/\/.*bing.com\/search\?q=sg&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143464&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=tr&urlDesc= 302 - -#>>>>>>>>>>>>>>>>>>>>>>>搜索 -# bd xxx (百度搜索) -^https:\/\/.*bing.com\/search\?q=bd\+([^&]+).+ https://www.baidu.com/s?wd=$1 302 -^https:\/\/.*bing.com\/search\?q=((.(?!bd))+)\+bd.+ https://www.baidu.com/s?wd=$1 302 -# wk xxx (维基搜索) -^https:\/\/.*bing.com\/search\?q=wk\+([^&]+).+ https://zh.wikipedia.org/wiki/$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+wk.+ https://zh.wikipedia.org/wiki/$1 302 -# wz xxx (无追搜索) -^https:\/\/.*bing.com\/search\?q=wz\+([^&]+).+ https://www.wuzhuiso.com/s?q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+wz.+ https://www.wuzhuiso.com/s?q=$1 302 -# yh xxx (油猴搜索) -^https:\/\/.*bing.com\/search\?q=yh\+([^&]+).+ https://greasyfork.org/zh-CN/scripts?q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+yh.+ https://greasyfork.org/zh-CN/scripts?q=$1 302 -# gi xxx (Google 图片) -^https:\/\/.*bing.com\/search\?q=gi\+([^&]+).+ https://www.google.com/search?&tbm=isch&q=$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+gi.+ https://www.google.com/search?&tbm=isch&q=$1 302 -# ios xxx (苹果应用搜索) -^https:\/\/.*bing.com\/search\?q=ios\+([^&]+).+ https://www.qimai.cn/search/index/search/$1 302 -^https:\/\/.*bing.com\/search\?q=([^+]+)\+ios.+ https://www.qimai.cn/search/index/search/$1 302 -# xxx (无指令默认为 Google) -^https:\/\/.*bing.com\/search\?q=([^&]+).+ https://www.google.com/search?q=$1 302 - -[MITM] -hostname = %APPEND% *.bing.com diff --git a/Surge-main/Modules/XboxCartWeb.sgmodule b/Surge-main/Modules/XboxCartWeb.sgmodule deleted file mode 100644 index 0e18005..0000000 --- a/Surge-main/Modules/XboxCartWeb.sgmodule +++ /dev/null @@ -1,16 +0,0 @@ -#!name=Xbox Cart Web -#!desc=访问 https://addtocart.com 触发远程脚本 -#!author=Ah Long -#!category=XBOX - -[Host] -# 核心:将 addtocart.com 解析到 Surge 内部 IP -# 这样手机发出的请求会被 Surge 直接截获,不会去公网找服务器 -addtocart.com = 198.18.0.1 - -[Script] -# 正则匹配:支持 http 和 https,域名为 addtocart.com -xbox_web_runner = type=http-request, pattern=^https?://addtocart\.com/?.*, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/NewAddToCart_Web.js, timeout=60 - -[MITM] -hostname = %APPEND% addtocart.com diff --git a/Surge-main/Modules/XboxParamCapturer.sgmodule b/Surge-main/Modules/XboxParamCapturer.sgmodule deleted file mode 100644 index 18b5377..0000000 --- a/Surge-main/Modules/XboxParamCapturer.sgmodule +++ /dev/null @@ -1,26 +0,0 @@ -#!name=Xbox Param Capturer -#!desc=抓取 Xbox 参数 (全区/防缓存/忽略大小写) -#!author=Ah Long -#!category=XBOX - -[Script] -# 1. 抓 Product 参数 (Response) -# 修复:优化正则写法,忽略大小写 -XboxProductList = type=http-response, pattern=(?i)^https://emerald\.xboxservices\.com/xboxcomfd/productActions/.*locale=en-us, requires-body=1, max-size=0, binary-body-mode=0, timeout=60, script-update-interval=0, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/XboxProductList.js - -# 2. 获取 Authorization & CartId -# 修复:加上 (?i) 忽略 Cart/cart 大小写,去掉强制结尾的 \? -Xbox_Auth_CartId = type=http-request, pattern=(?i)^https://cart\.production\.store-web\.dynamics\.com/v1\.0/cart/eligibilityCheck, requires-body=0, script-update-interval=0, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/authorization%26cartId.js - -# 3. 获取 CartParameter -# 修复:加上 (?i) 忽略大小写 -Xbox_Mscv_MUID = type=http-request, pattern=(?i)^https://cart\.production\.store-web\.dynamics\.com/v1\.0/cart/loadCart, requires-body=0, script-update-interval=0, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/CartParameter.js - -[Header Rewrite] -# 【防缓存】强制删除 emerald 域名的协商缓存头 -# 修复:简化正则,确保匹配命中 -^https://emerald\.xboxservices\.com/xboxcomfd/productActions/ header-del If-Modified-Since -^https://emerald\.xboxservices\.com/xboxcomfd/productActions/ header-del If-None-Match - -[MITM] -hostname = %APPEND% emerald.xboxservices.com, *.dynamics.com diff --git a/Surge-main/Modules/XboxWebController.sgmodule b/Surge-main/Modules/XboxWebController.sgmodule deleted file mode 100644 index cb45a6a..0000000 --- a/Surge-main/Modules/XboxWebController.sgmodule +++ /dev/null @@ -1,26 +0,0 @@ -#!name=Xbox Web Controller -#!desc=通过访问虚拟域名触发脚本:\n1. 访问 https://addtocart.com -> 触发添加/购买脚本\n2. 访问 https://clearlist.com -> 清空本地 ProductList\n3. 访问 https://clearapprovalcartid.com -> 清空 ApproveCartId\n4. 访问 https://syncxbox.com -> 从云端同步数据并清理云端队列 -#!author=Ah Long & XXhaos -#!category=XBOX - -[Host] -addtocart.com = 198.18.0.1 -clearlist.com = 198.18.0.1 -clearapprovalcartid.com = 198.18.0.1 -syncxbox.com = 198.18.0.1 - -[Script] -# 1. 触发远程添加/购买脚本 -xbox_web_runner = type=http-request, pattern=^https?://addtocart\.com/?.*, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/NewAddToCart_Web.js, timeout=60 - -# 2. 清空本地 XboxProductList -xbox_clear_web = type=http-request, pattern=^https?://clearlist\.com/?.*, script-path=https://raw.githubusercontent.com/XXhaos/Surge/main/Scripts/ClearXboxProductList_Web.js, timeout=10 - -# 3. 清空 ApprovalCartId -clear_cart_id = type=http-request, pattern=^https?://clearapprovalcartid\.com/?.*, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/ClearApprovalCartId.js, timeout=10 - -# 4. 从云端同步数据 (确保 GitHub 上的文件名和路径 100% 正确) -xbox_sync_cloud = type=http-request, pattern=^https?://syncxbox\.com/?.*, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/SyncXboxCloud.js, timeout=30 - -[MITM] -hostname = %APPEND% addtocart.com, clearlist.com, clearapprovalcartid.com, syncxbox.com diff --git a/Surge-main/Modules/Xbox_Rewrite.sgmodule b/Surge-main/Modules/Xbox_Rewrite.sgmodule deleted file mode 100644 index b05c451..0000000 --- a/Surge-main/Modules/Xbox_Rewrite.sgmodule +++ /dev/null @@ -1,17 +0,0 @@ -#!name=Xbox Rewrite Collection -#!desc=Win 商店链接重定向 & 强制锁美区 (保留阿根廷区) -#!category=XBOX -#!author=Ah Long - -[URL Rewrite] -# Microsoft Store -> 对应的 CoreHalo 游戏页(提取 12 位 ID) -(?i)^https?:\/\/(?:www\.)?microsoft\.com\/en-us\/store\/.*?([a-z0-9]{12})(?:[\/\?#]|$) https://www.xbox.com/en-us/games/store/corehalo/$1 302 - -# 非 en-us 的 xbox.com 统一跳转到 en-us(排除 es-ar / es-AR / en-us) -^https:\/\/www\.xbox\.com\/(?!es-ar|es-AR|en-us)([a-zA-Z]{2}-[a-zA-Z]{2})(\/.*)$ https://www.xbox.com/en-us$2 302 - -# app.corehalo.com 的 r 区域参数统一改为 en-us,保留其他 query 参数 -"^https:\/\/app\.corehalo\.com\/ms\/link\/go\?(.*&)?r=(?!es-ar|es-AR|en-us)([a-zA-Z]{2}-[a-zA-Z]{2})(&.*)?$" "https://app.corehalo.com/ms/link/go?$1r=en-us$3" 302 - -[MITM] -hostname = %APPEND% www.microsoft.com, www.xbox.com, app.corehalo.com diff --git a/Surge-main/Modules/batch_approval.sgmodule b/Surge-main/Modules/batch_approval.sgmodule deleted file mode 100644 index 3c091fe..0000000 --- a/Surge-main/Modules/batch_approval.sgmodule +++ /dev/null @@ -1,13 +0,0 @@ -#!name=Microsoft Family Batch Approve -#!desc=自动抓取CartId并替换批量购买流程,购买完成后自动清理 -#!category=XBOX -#!author=Ah Long - -[Script] -ApprovalCartId = type=http-request, pattern=^https:\/\/buynow\.production\.store-web\.dynamics\.com\/v1\.0\/cart\/updateCart.*, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/ApprovalCartId.js, requires-body=0 - -batch_purchase_send = type=http-request, pattern=^https:\/\/buynow\.production\.store-web\.dynamics\.com\/v1\.0\/Cart\/purchase\?appId=BuyNow, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/batch_purchase_send.js, requires-body=1, max-size=1048576, timeout=60, binary-body-mode=0, script-update-interval=0 - -ApprovalCartClean = type=http-request, pattern=^https:\/\/account\.microsoft\.com\/family\/api\/buy\/requests\/complete, script-path=https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/Scripts/AutoClearApprovalCartId.js, requires-body=0 -[MITM] -hostname = %APPEND% buynow.production.store-web.dynamics.com, production.store-web.dynamics.com, account.microsoft.com diff --git a/Surge-main/README.md b/Surge-main/README.md deleted file mode 100644 index 1428af1..0000000 --- a/Surge-main/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Surge -自用 diff --git a/Surge-main/Scripts/Add8TFDlcToCart.js b/Surge-main/Scripts/Add8TFDlcToCart.js deleted file mode 100644 index 4902e6d..0000000 --- a/Surge-main/Scripts/Add8TFDlcToCart.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Surge Script - 微软购物车批量添加 - * 特性:动态生成 riskSessionId - */ - -// ==== 配置项 ==== // -const PRODUCT_IDS = $persistentStore.read("productId"); // 格式:id1&id2 -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).toString(16) : (Math.random()*4|8).toString(16))); - -// ==== 执行逻辑 ==== // -const productIdArray = PRODUCT_IDS?.split("&") || []; -const results = { success: [], failure: [] }; -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": "ha-Latn-NG,ha;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 sendRequest() { - if (currentIndex >= productIdArray.length) { - const successCount = results.success.length; - const failureList = results.failure.join("\n"); - $notification.post( - "🎮 操作完成", - `成功: ${successCount}个`, - failureList || "所有请求均成功" - ); - $done(); - return; - } - - const productId = productIdArray[currentIndex]; - const riskSessionId = generateRiskSessionId(); - const timeoutId = setTimeout(() => { - recordResult(productId, "超时"); - proceed(); - }, 30000); - - $httpClient.put({ - url: API_URL, - headers: HEADERS, - body: JSON.stringify({ - locale: "en-ng", - market: "NG", - catalogClientType: "storeWeb", - friendlyName: "cart-NG", - riskSessionId: riskSessionId, - clientContext: { client: "UniversalWebStore.Cart", deviceType: "Pc" }, - itemsToAdd: { items: [{ productId, skuId: "0010", quantity: 1 }] } - }) - }, (error, response) => { - clearTimeout(timeoutId); - error ? recordResult(productId, error) - : response.status === 200 ? handleSuccess(productId) - : recordResult(productId, `HTTP ${response.status}`); - proceed(); - }); -} - -// ==== 辅助函数 ==== // -function handleSuccess(id) { - results.success.push(id); - console.log(`✅ ${id}`); -} - -function recordResult(id, reason) { - results.failure.push(`${id}: ${reason}`); - console.log(`❌ ${id} - ${reason}`); -} - -function proceed() { - currentIndex++; - setTimeout(sendRequest, 100); // 请求间隔0.0秒 -} - -// ==== 启动检查 ==== // -if (!MUID || !PRODUCT_IDS) { - console.log("⚠️ 配置错误 - 缺少必要参数 MUID 或 PRODUCT_IDS"); - $notification.post("配置错误", "缺少必要参数", ""); - $done(); -} else { - console.log("🚀 开始执行请求"); - sendRequest(); -} diff --git a/Surge-main/Scripts/ApprovalCartId.js b/Surge-main/Scripts/ApprovalCartId.js deleted file mode 100644 index 395b97e..0000000 --- a/Surge-main/Scripts/ApprovalCartId.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Surge 脚本:从 buynow 链接中提取 cartId 并存入 ApprovalCartId - * 存储格式:id1&id2&id3... - */ - -const key = "ApprovalCartId"; - -// 1. 获取已有 ApprovalCartId 的值 -const existingRaw = $persistentStore.read(key); - -// 2. 获取当前请求 URL -const url = $request.url; - -// 3. 正则表达式提取 cartId -// 说明:[?&] 匹配开始的 ? 或中间的 &,cartId= 匹配参数名,([^&]+) 捕获直到下一个 & 或字符串结束的内容 -const matches = url.match(/[?&]cartId=([^&]+)/); - -if (matches && matches[1]) { - const newCartId = matches[1]; - - // 将已有的字符串分割为数组 (过滤掉空字符串,防止 split 产生 bug) - let existingIdArray = existingRaw ? existingRaw.split("&").filter(Boolean) : []; - - // 4. 判重逻辑 - if (!existingIdArray.includes(newCartId)) { - - // 追加新 ID 到数组 - existingIdArray.push(newCartId); - - // 重新组合成字符串 - const finalString = existingIdArray.join("&"); - - // 5. 写入 Persistent Store - $persistentStore.write(finalString, key); - - // 控制台日志 - console.log(`✅ [CartId提取] 已追加: ${newCartId}`); - console.log(`📄 当前列表: ${finalString}`); - - // 发送通知 - $notification.post( - "✅ CartId 抓取成功", - `已存入第 ${existingIdArray.length} 个 ID`, - newCartId - ); - } else { - console.log(`⚠️ [CartId提取] 跳过,已存在: ${newCartId}`); - // 如果需要重复时也弹窗,取消下面这行的注释 - // $notification.post("⚠️ 跳过重复 ID", "该 CartId 已在列表中", newCartId); - } -} else { - console.log("⚠️ URL 中未找到 cartId 参数"); -} - -// 结束脚本,继续请求 -$done({}); diff --git a/Surge-main/Scripts/AutoClearApprovalCartId.js b/Surge-main/Scripts/AutoClearApprovalCartId.js deleted file mode 100644 index 3d9ebed..0000000 --- a/Surge-main/Scripts/AutoClearApprovalCartId.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Surge 脚本:Clear_ApprovalCartId.js - * 作用:监测到 Family Safety 的 Complete 请求时,自动清空 ApprovalCartId - */ - -const STORE_KEY = "ApprovalCartId"; - -(function() { - // 只有 POST 方法才触发清理 - if ($request.method === "POST") { - const oldValue = $persistentStore.read(STORE_KEY); - - if (oldValue) { - $persistentStore.write("", STORE_KEY); - - console.log("🧹 [Batch Approve] 购买流程结束,已自动清空 ApprovalCartId 缓存。"); - - $notification.post("Microsoft Family", "购买流程结束", "ApprovalCartId 缓存已清空"); - } - } - $done({}); -})(); diff --git a/Surge-main/Scripts/BuyRequestReplace.js b/Surge-main/Scripts/BuyRequestReplace.js deleted file mode 100644 index cca6112..0000000 --- a/Surge-main/Scripts/BuyRequestReplace.js +++ /dev/null @@ -1,83 +0,0 @@ -// Surge脚本:拦截 RequestParentalApproval 并替换 CartId/Auth -// 增加了通知功能:成功或失败都会弹窗提示 - -// 1. 判断 HTTP 请求方法是否为 POST -if ($request.method !== "POST") { - $done({}); -} else { - // 定义状态标记,用于最后发通知 - let status = { cartId: false, auth: false }; - let errorMsg = []; - - // 2. 读取持久化存储 - let newCartId = $persistentStore.read("cartId"); - let newAuth = $persistentStore.read("authorization"); - - if (!newCartId) { - console.log("警告:Store 中缺少 cartId"); - errorMsg.push("缺少 cartId"); - } - if (!newAuth) { - console.log("警告:Store 中缺少 authorization"); - errorMsg.push("缺少 Auth"); - } - - // 3. 解析并修改 Request Body (CartId) - let bodyStr = $request.body || ""; - let bodyObj; - try { - bodyObj = JSON.parse(bodyStr); - } catch (e) { - console.log("JSON 解析失败:" + e); - errorMsg.push("JSON 解析错误"); - bodyObj = null; - } - - // 4. 执行替换:CartId - if (bodyObj && newCartId) { - bodyObj.cartId = newCartId; - bodyStr = JSON.stringify(bodyObj); - status.cartId = true; // 标记成功 - } - - // 5. 执行替换:Authorization - let headers = $request.headers; - if (newAuth) { - let authHeaderKey = Object.keys(headers).find(k => k.toLowerCase() === "authorization"); - if (authHeaderKey) { - headers[authHeaderKey] = newAuth; - } else { - headers["Authorization"] = newAuth; - } - status.auth = true; // 标记成功 - } - - // 6. 修正 Content-Length - if (bodyStr !== $request.body) { - let lenKey = Object.keys(headers).find(k => k.toLowerCase() === "content-length"); - if (lenKey) delete headers[lenKey]; - } - - // 7. 发送通知逻辑 - if (status.cartId && status.auth) { - // 情况A:完美,两个都替换了 - $notification.post("✅ 替换成功", "Xbox 购买参数", "CartId 和 Authorization 均已更新"); - } else if (status.cartId || status.auth) { - // 情况B:部分成功 (比如只有Auth没有CartId) - let details = []; - if (status.cartId) details.push("CartId OK"); - if (status.auth) details.push("Auth OK"); - $notification.post("⚠️ 部分替换成功", "Xbox 购买参数", `仅完成: ${details.join(", ")} (请检查参数)`); - } else { - // 情况C:完全失败 - let reason = errorMsg.length > 0 ? errorMsg.join(" & ") : "未知原因"; - $notification.post("❌ 替换失败", "Xbox 购买参数", reason); - } - - // 8. 返回结果 - if (newAuth) { - $done({ body: bodyStr, headers: headers }); - } else { - $done({ body: bodyStr }); - } -} diff --git a/Surge-main/Scripts/CartParameter.js b/Surge-main/Scripts/CartParameter.js deleted file mode 100644 index f5ee7a1..0000000 --- a/Surge-main/Scripts/CartParameter.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Surge 脚本:捕获特定 URL 请求的参数 - * 包含: x-authorization-muid, ms-cv, x-ms-vector-id, x-ms-reference-id - * 新增: x-ms-tracking-id, x-ms-correlation-id - * 并存储到持久化存储($persistentStore)中 - * 只针对 PUT 请求 - */ - -// 修改正则表达式,捕获新的请求 URL -const pattern = /^https:\/\/cart\.production\.store-web\.dynamics\.com\/v1\.0\/cart\/loadCart\?/; -const url = $request.url; - -// 判断是否是 PUT 请求并且 URL 匹配 -if ($request.method === "PUT" && pattern.test(url)) { - try { - // 从请求头中获取所需参数 - const xAuthorizationMuid = $request.headers['x-authorization-muid']; - const msCv = $request.headers['ms-cv']; - const xMsVectorId = $request.headers['x-ms-vector-id']; - const xMsReferenceId = $request.headers['x-ms-reference-id']; - // 新增参数获取 - const xMsTrackingId = $request.headers['x-ms-tracking-id']; - const xMsCorrelationId = $request.headers['x-ms-correlation-id']; - - // 更新存储逻辑(仅在新值有效时更新) - let hasUpdate = false; - - // 1. x-authorization-muid - if (xAuthorizationMuid && xAuthorizationMuid !== $persistentStore.read("cart-x-authorization-muid")) { - $persistentStore.write(xAuthorizationMuid, "cart-x-authorization-muid"); - console.log(`Stored x-authorization-muid: ${xAuthorizationMuid}`); - hasUpdate = true; - } - - // 2. ms-cv - if (msCv && msCv !== $persistentStore.read("cart-ms-cv")) { - $persistentStore.write(msCv, "cart-ms-cv"); - console.log(`Stored ms-cv: ${msCv}`); - hasUpdate = true; - } - - // 3. x-ms-vector-id - if (xMsVectorId && xMsVectorId !== $persistentStore.read("cart-x-ms-vector-id")) { - $persistentStore.write(xMsVectorId, "cart-x-ms-vector-id"); - console.log(`Stored x-ms-vector-id: ${xMsVectorId}`); - hasUpdate = true; - } - - // 4. x-ms-reference-id - if (xMsReferenceId && xMsReferenceId !== $persistentStore.read("cart-x-ms-reference-id")) { - $persistentStore.write(xMsReferenceId, "cart-x-ms-reference-id"); - console.log(`Stored x-ms-reference-id: ${xMsReferenceId}`); - hasUpdate = true; - } - - // 5. [新增] x-ms-tracking-id - if (xMsTrackingId && xMsTrackingId !== $persistentStore.read("cart-x-ms-tracking-id")) { - $persistentStore.write(xMsTrackingId, "cart-x-ms-tracking-id"); - console.log(`Stored x-ms-tracking-id: ${xMsTrackingId}`); - hasUpdate = true; - } - - // 6. [新增] x-ms-correlation-id - if (xMsCorrelationId && xMsCorrelationId !== $persistentStore.read("cart-x-ms-correlation-id")) { - $persistentStore.write(xMsCorrelationId, "cart-x-ms-correlation-id"); - console.log(`Stored x-ms-correlation-id: ${xMsCorrelationId}`); - hasUpdate = true; - } - - // 仅在成功捕获新值时发送通知(如果需要开启通知,取消下方注释) - // if (hasUpdate) { - // $notification.post( - // "Surge 信息存储", - // "已捕获并存储所有加购请求参数", - // "包含 tracking-id 和 correlation-id" - // ); - // } - - } catch (error) { - console.log(`Error capturing parameters: ${error}`); - // $notification.post( - // "Surge 脚本错误", - // "无法捕获所需购物车参数", - // `${error}` - // ); - } -} - -$done({}); diff --git a/Surge-main/Scripts/ClearApprovalCartId.js b/Surge-main/Scripts/ClearApprovalCartId.js deleted file mode 100644 index 49a8662..0000000 --- a/Surge-main/Scripts/ClearApprovalCartId.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Surge 脚本:清空 ApprovalCartId - * 功能:1. 清空数据 2. 系统弹窗 3. 网页显示纯净结果 - * 触发地址:http://clear_list.com - */ - -const key = "ApprovalCartId"; - -// 1. 执行清空 -$persistentStore.write("", key); - -// 2. 控制台日志 -console.log("✅ 操作成功 - 已清空 ApprovalCartId"); - -// 3. 发送系统通知 (手机顶部依然会弹窗) -$notification.post("🗑️ 清单已清空", "操作成功", "ApprovalCartId 已重置为空对象"); - -// 4. 生成网页 HTML (去掉了提示文字) -const html = ` - - - - - - Clear List - - - -
-

✅ 操作成功

-

ApprovalCartId 已被清空

-
- -`; - -// 5. 返回给浏览器 -$done({ - response: { - status: 200, - headers: { "Content-Type": "text/html;charset=utf-8" }, - body: html - } -}); diff --git a/Surge-main/Scripts/ClearXboxProductList_Web.js b/Surge-main/Scripts/ClearXboxProductList_Web.js deleted file mode 100644 index 546a77d..0000000 --- a/Surge-main/Scripts/ClearXboxProductList_Web.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Surge 脚本:清空 XboxProductList - * 功能:1. 清空数据 2. 系统弹窗 3. 网页显示纯净结果 - * 触发地址:http://clear_list.com - */ - -const key = "XboxProductList"; - -// 1. 执行清空 -$persistentStore.write("{}", key); - -// 2. 控制台日志 -console.log("✅ 操作成功 - 已清空 XboxProductList"); - -// 3. 发送系统通知 (手机顶部依然会弹窗) -$notification.post("🗑️ 清单已清空", "操作成功", "XboxProductList 已重置为空对象"); - -// 4. 生成网页 HTML (去掉了提示文字) -const html = ` - - - - - - Clear List - - - -
-

✅ 操作成功

-

XboxProductList 已被清空

-
- -`; - -// 5. 返回给浏览器 -$done({ - response: { - status: 200, - headers: { "Content-Type": "text/html;charset=utf-8" }, - body: html - } -}); diff --git a/Surge-main/Scripts/NewAddToCart.js b/Surge-main/Scripts/NewAddToCart.js deleted file mode 100644 index 120a71a..0000000 --- a/Surge-main/Scripts/NewAddToCart.js +++ /dev/null @@ -1,156 +0,0 @@ -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(); -} diff --git a/Surge-main/Scripts/NewAddToCart_Web.js b/Surge-main/Scripts/NewAddToCart_Web.js deleted file mode 100644 index 98947e9..0000000 --- a/Surge-main/Scripts/NewAddToCart_Web.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Xbox Cart Web Runner - * 远程路径: https://raw.githubusercontent.com/XXhaos/Surge/refs/heads/main/NewAddToCart_Web.js - */ - -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"); - -// 日志缓存 -let logBuffer = []; -const results = { success: [], failure: [] }; -const successKeys = []; -let currentIndex = 0; - -function log(type, message, detail = "") { - const icon = type === "success" ? "✅" : (type === "error" ? "❌" : "ℹ️"); - const color = type === "success" ? "green" : (type === "error" ? "red" : "#666"); - console.log(`${icon} ${message} ${detail}`); - logBuffer.push(`
${icon} ${message} ${detail}
`); -} - -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 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, "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" }; - -function finalizeAndClean() { - const successCount = results.success.length; - const failureCount = results.failure.length; - 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"); - log("info", "清理完成", `剩余: ${remainingCount}`); - } catch (e) { log("error", "清理异常", e); } - - // 【新增】发送系统通知 - $notification.post( - "🛒 Xbox 加购完成", - `成功: ${successCount} / 失败: ${failureCount}`, - `剩余库存: ${remainingCount}` - ); - - const html = `Xbox Cart

执行结果: 成功 ${successCount} / 剩余 ${remainingCount}

${logBuffer.join("")}
`; - - $done({ response: { status: 200, headers: { "Content-Type": "text/html;charset=utf-8" }, body: html } }); -} - -function sendRequest() { - if (currentIndex >= productList.length) return finalizeAndClean(); - const { key, productId, skuId, availabilityId } = productList[currentIndex]; - const bodyObj = { locale: LOCALE, market: MARKET, catalogClientType: "storeWeb", friendlyName: FRIENDLY_NAME, riskSessionId: generateRiskSessionId(), 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) => { - const idStr = `${productId}`; - if (error || response.status !== 200) { - results.failure.push(idStr); log("error", "失败", idStr); - } else { - results.success.push(idStr); if (key) successKeys.push(key); log("success", "成功", idStr); - } - currentIndex++; setTimeout(sendRequest, 50); - }); -} - -if (!MUID || !MS_CV) { - log("error", "缺少 MUID/CV"); - // 即使配置错误也发个通知提醒你 - $notification.post("❌ Xbox 脚本错误", "缺少必要参数", "请检查 MUID 或 MS_CV"); - finalizeAndClean(); -} -else if (productList.length === 0) { - log("info", "列表为空"); - $notification.post("⚠️ Xbox 脚本", "无需执行", "列表为空"); - finalizeAndClean(); -} -else { - log("info", "开始任务", `数量: ${productList.length}`); - sendRequest(); -} diff --git a/Surge-main/Scripts/SyncXboxCloud.js b/Surge-main/Scripts/SyncXboxCloud.js deleted file mode 100644 index 6569a9e..0000000 --- a/Surge-main/Scripts/SyncXboxCloud.js +++ /dev/null @@ -1,171 +0,0 @@ -/** - * SyncXboxCloud.js - * 两步流程:先读取,写入成功后再删除 - * 顶部时间戳锁防止 Surge 规则重复触发脚本 - */ - -const readUrl = 'https://cc.dragonisheep.com/surge?token=xbox123'; -const clearUrl = 'https://cc.dragonisheep.com/surge?token=xbox123&action=clear'; -const storeKey = 'XboxProductList'; -const lockKey = 'SyncXboxLock'; - -// ★ 防重入:5 秒内若已执行过,直接放行不处理 -// Surge 规则会同时拦截 read 和 clear 两个请求,第二次触发在此被阻断 -const lockVal = $persistentStore.read(lockKey); -if (lockVal && Date.now() - parseInt(lockVal, 10) < 5000) { - $done({}); -} -$persistentStore.write(String(Date.now()), lockKey); - -function escapeHTML(str) { - return String(str || '') - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} - -function renderUI(title, message, type = "success") { - const colorMap = { - success: "#107C10", - warning: "#d83b01", - error: "#c50f1f", - info: "#0078d4" - }; - const color = colorMap[type] || "#0078d4"; - - const html = ` - - - - - - ${escapeHTML(title)} - - - -
-

${escapeHTML(title)}

-
${message}
-
SyncXbox Cloud Queue
- -
- -`; - - $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 - } - }); -} - -// 第一步:读取当前组 -$httpClient.get(readUrl, (error, response, data) => { - if (error) { - $notification.post("❌ 同步失败", "无法连接服务器", String(error)); - return renderUI("❌ 连接失败", `

无法连接至服务器。

${escapeHTML(String(error))}

`, "error"); - } - - let payload; - try { - payload = JSON.parse((data || '').trim() || '{}'); - } catch (e) { - $notification.post("❌ 同步失败", "返回 JSON 无法解析", ""); - return renderUI("❌ 解析错误", `

服务器返回内容不是合法 JSON。

${escapeHTML(String(e.message || e))}

`, "error"); - } - - if (!payload || typeof payload !== 'object' || Array.isArray(payload)) { - $notification.post("❌ 同步失败", "返回结构异常", ""); - return renderUI("❌ 数据异常", `

服务器返回的数据结构不正确。

`, "error"); - } - - if (!payload.ok) { - $notification.post("❌ 同步失败", "服务器返回 ok=false", ""); - return renderUI("❌ 同步失败", `

服务器返回失败状态。

`, "error"); - } - - const currentGroup = payload.currentGroup || {}; - const keys = Object.keys(currentGroup); - - if (!keys.length) { - $notification.post("📭 当前无待同步组", "云端队列为空", ""); - return renderUI("📭 没有可同步内容", `

当前没有待同步的 Product 分组。

`, "warning"); - } - - // 第二步:写入本地,成功后才删云端 - const writeOK = $persistentStore.write(JSON.stringify(currentGroup), storeKey); - if (!writeOK) { - $notification.post("❌ 同步失败", "写入 Surge 存储失败", ""); - // 写入失败,不发 clear,云端数据保留,下次可以重试 - return renderUI("❌ 写入失败", `

无法写入 Surge 本地存储,云端数据未删除,下次访问可重试。

`, "error"); - } - - // 第三步:本地写入成功,删除云端当前组 - $httpClient.get(clearUrl, (clearError, clearResponse, clearData) => { - if (clearError) { - $notification.post("⚠️ 本地已写入", `第 ${payload.currentGroupIndex} 组已保存`, "但云端清理失败,下次访问仍是这一组"); - return renderUI( - "⚠️ 当前组已写入,但云端未清理", - `

已成功写入第 ${escapeHTML(String(payload.currentGroupIndex))} 组,共 ${keys.length} 个商品。

-

但清理云端当前组时失败,下次访问时仍会是这一组。

`, - "warning" - ); - } - - let clearPayload = {}; - try { clearPayload = JSON.parse((clearData || '').trim() || '{}'); } catch (_) {} - - const remainingGroups = typeof clearPayload.remainingGroups === 'number' - ? clearPayload.remainingGroups - : (typeof payload.remainingAfterCurrent === 'number' ? payload.remainingAfterCurrent : 0); - const nextGroupIndex = clearPayload.nextGroupIndex ?? null; - const nextGroupCount = clearPayload.nextGroupCount ?? 0; - const list = keys.map(k => `
  • ${escapeHTML(k)}
  • `).join(''); - - let message = - `

    本次只同步了第 ${escapeHTML(String(payload.currentGroupIndex))} 组,共 ${keys.length} 个商品。

    -

    当前这一组已经从云端队列删除。

    -

    现在还剩 ${remainingGroups} 组待处理。

    `; - - if (remainingGroups > 0 && nextGroupIndex !== null) { - message += `

    下次访问网页时,将同步第 ${escapeHTML(String(nextGroupIndex))} 组(共 ${escapeHTML(String(nextGroupCount))} 个商品)。

    `; - } else { - message += `

    所有分组已经处理完毕。

    `; - } - - message += ``; - - $notification.post("✅ 当前组同步成功", `第 ${payload.currentGroupIndex} 组已同步`, `剩余 ${remainingGroups} 组`); - return renderUI("✅ 当前组同步完成", message, "success"); - }); -}); diff --git a/Surge-main/Scripts/XboxProductList.js b/Surge-main/Scripts/XboxProductList.js deleted file mode 100644 index 0ac52df..0000000 --- a/Surge-main/Scripts/XboxProductList.js +++ /dev/null @@ -1,113 +0,0 @@ -// Surge: script-response-body -// 递归提取 GET 响应中 actionType == "Cart" 的 {ProductId,SkuId,AvailabilityId} -// 以 product1/product2… 顺序写入 XboxProductList;ProductId重复则跳过 -// 通知:🆕 新增 / 🔁 已存在(不含 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 }); - } -})(); diff --git a/Surge-main/Scripts/authorization&cartId.js b/Surge-main/Scripts/authorization&cartId.js deleted file mode 100644 index f227554..0000000 --- a/Surge-main/Scripts/authorization&cartId.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Surge 脚本:捕获特定 URL 请求的 Authorization 和 cartId(仅限 PUT 请求) - * 并存储到持久化存储($persistentStore),只有在成功捕获到新值时才更新 - */ - -const pattern = /^https:\/\/cart\.production\.store-web\.dynamics\.com\/v1\.0\/Cart\/eligibilityCheck\?/; -const url = $request.url; - -// 仅处理 PUT 请求 -if ($request.method === "PUT" && pattern.test(url)) { - try { - // 获取 Authorization 请求头的值 - const authorization = $request.headers['authorization']; - // 解析 URL 以提取 cartId 参数 - const urlObj = new URL(url); - const cartId = urlObj.searchParams.get('cartId'); - - // 只有在成功捕获到新值时,才更新 $persistentStore 中的值 - if (authorization && authorization !== $persistentStore.read("authorization")) { - $persistentStore.write(authorization, "authorization"); - console.log(`Stored authorization: ${authorization}`); - } - - if (cartId && cartId !== $persistentStore.read("cartId")) { - $persistentStore.write(cartId, "cartId"); - console.log(`Stored cartId: ${cartId}`); - } - - // 发送通知,成功捕获并存储 Authorization 和 CartId - $notification.post( - "Surge 信息存储", - "已捕获并存储 authorization 和 cartId" - ); - } catch (error) { - console.log(`Error capturing authorization & cartId: ${error}`); - $notification.post( - "Surge 脚本错误", - "无法捕获 authorization 和 cartId", - `${error}` - ); - } -} - -$done({}); diff --git a/Surge-main/Scripts/batch_purchase_send.js b/Surge-main/Scripts/batch_purchase_send.js deleted file mode 100644 index fbe198e..0000000 --- a/Surge-main/Scripts/batch_purchase_send.js +++ /dev/null @@ -1,141 +0,0 @@ -/** - * Surge 脚本:微软家庭组批量购买 (防风控增强版) - * * 特性 1: 随机抖动延迟 (1.5s ~ 3.5s 之间随机),模拟真人。 - * * 特性 2: 智能熔断,遇到 429/403 立即停止,保护账号。 - */ - -const STORE_KEY = "ApprovalCartId"; -const BASE_DELAY = 1500; // 基础间隔 -const JITTER_MAX = 2000; // 最大随机附加间隔 (0~2000ms) - -(async () => { - // 1. 严格限制仅允许 POST - if ($request.method !== "POST") { - $done({}); - return; - } - - // 2. 读取 Store - const rawIds = $persistentStore.read(STORE_KEY); - if (!rawIds) { - console.log("ℹ️ [旁路] 未读取到 ApprovalCartId,放行。"); - $done({}); - return; - } - - const targetIds = rawIds.split("&").filter(Boolean); - if (targetIds.length === 0) { - $done({}); - return; - } - - // 3. 启动通知 - $notification.post( - "🛡️ 防风控批量启动", - `队列: ${targetIds.length} 个请求`, - `启用随机延迟与熔断保护机制...` - ); - - let originalBodyTemplate; - try { - originalBodyTemplate = JSON.parse($request.body); - } catch (e) { - $done({}); - return; - } - - const baseHeaders = { ...$request.headers }; - delete baseHeaders["Content-Length"]; - delete baseHeaders["content-length"]; - - let successCount = 0; - let failCount = 0; - let isBanned = false; // 标记是否被风控 - - // ========================================== - // 串行循环 - // ========================================== - for (let i = 0; i < targetIds.length; i++) { - const id = targetIds[i]; - - // 构造请求 - let currentBody = JSON.parse(JSON.stringify(originalBodyTemplate)); - currentBody.cartId = id; - - const options = { - url: $request.url, - method: "POST", - headers: baseHeaders, - body: JSON.stringify(currentBody) - }; - - console.log(`🔄 [${i + 1}/${targetIds.length}] 处理 ${id.substring(0,6)}...`); - - const result = await sendRequest(options); - - // --- 结果判定与熔断逻辑 --- - if (result && result.status >= 200 && result.status < 300) { - console.log(` ✅ 成功`); - successCount++; - } else if (result.status === 429 || result.status === 403) { - // 429: Too Many Requests (请求太快) - // 403: Forbidden (可能鉴权失败或被封禁) - console.log(` ⛔️ 触发风控 (Code: ${result.status})! 立即停止后续任务!`); - $notification.post("⛔️ 任务熔断停止", `检测到微软风控 (${result.status})`, "已停止后续请求以保护账号"); - isBanned = true; - failCount++; - break; // 👈 核心:立即跳出循环,不再发包 - } else { - console.log(` ❌ 失败 (Code: ${result ? result.status : 'unknown'})`); - failCount++; - } - - // --- 随机抖动延迟 --- - // 只有不是最后一个,且没有被Ban,才等待 - if (i < targetIds.length - 1 && !isBanned) { - // 生成 1500ms 到 3500ms 之间的随机时间 - const randomTime = BASE_DELAY + Math.floor(Math.random() * JITTER_MAX); - console.log(` ⏳ 随机等待 ${(randomTime/1000).toFixed(2)}s...`); - await sleep(randomTime); - } - } - - // 4. 清空 Store - $persistentStore.write(null, STORE_KEY); - - // 5. 最终处理 - if (!isBanned) { - const msg = `成功 ${successCount} | 失败 ${failCount}`; - $notification.post("✅ 批量完成", msg, "原始请求已拦截,请刷新页面"); - } - - // 拦截并返回伪造成功 - $done({ - response: { - status: 200, - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - status: "Complete", - message: "Processed by Surge (Anti-Ban Mode)" - }) - } - }); - -})(); - -function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -function sendRequest(opts) { - return new Promise((resolve) => { - $httpClient.post(opts, (err, resp, data) => { - if (err) { - console.log(`❌ 网络错误: ${err}`); - resolve({ status: 0, error: err }); - } else { - resolve({ status: resp.status, body: data }); - } - }); - }); -} diff --git a/Surge-main/Scripts/ms_family_block.js b/Surge-main/Scripts/ms_family_block.js deleted file mode 100644 index bed90f6..0000000 --- a/Surge-main/Scripts/ms_family_block.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * 脚本名称: Microsoft Family ProductId Block - * 功能: 拦截 Microsoft Family 中指定的 ProductId 购买请求 - */ - -// 定义需要拦截的目标 ID 列表 -const targetIds = [ - "9PNTSH5SKCL5", "9nfmccp0pm67", "9npbvj8lwsvn", "9pcgszz8zpq2", - "9P54FF0VQD7R", "9NCJZN3LBD3P", "9P9CLTVLLHD6", "9NHXDFLDBN6G" -]; - -function main() { - // 1. 检查是否为 POST 请求 (对应 Fiddler 的 oSession.HTTPMethodIs("POST")) - if ($request.method !== "POST") { - $done({}); - return; - } - - // 2. 获取请求体 (对应 oSession.GetRequestBodyAsString()) - // 注意:需要在模块配置中开启 requires-body=1 - const body = $request.body; - - if (!body) { - $done({}); - return; - } - - // 3. 检查是否包含目标 ID (对应 IndexOf + StringComparison.OrdinalIgnoreCase) - // 为了实现忽略大小写匹配,我们将 body 和 targetId 都转换为大写进行比较 - const upperBody = body.toUpperCase(); - - let isMatch = false; - for (let id of targetIds) { - if (upperBody.includes(id.toUpperCase())) { - isMatch = true; - break; - } - } - - // 4. 如果匹配,则拦截 (对应 oSession.oRequest.FailSession(403...)) - if (isMatch) { - console.log(`[MS-Block] 检测到拦截目标,已阻断请求。`); - $done({ - response: { - status: 403, - headers: { - "Content-Type": "text/plain; charset=utf-8" - }, - body: "Blocked by Surge script (Microsoft Family ProductId Rule)" - } - }); - } else { - // 未匹配,放行 - $done({}); - } -} - -main();