From aef66fb95e121e042bc2a010db8522fac31d613e Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Thu, 20 Mar 2025 21:25:45 +0800 Subject: [PATCH 001/109] jd_price2.sgmodule --- Surge/jd_price2.sgmodule | 8 + jd_price.js | 338 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 346 insertions(+) create mode 100644 Surge/jd_price2.sgmodule create mode 100644 jd_price.js diff --git a/Surge/jd_price2.sgmodule b/Surge/jd_price2.sgmodule new file mode 100644 index 00000000..fc6aac8e --- /dev/null +++ b/Surge/jd_price2.sgmodule @@ -0,0 +1,8 @@ +#!name= 京东比价 +#!desc= 京东App历史价格(商品、大家评页面触发) + +[Script] +京东比价 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/graphext\/\d+\.html,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price.js,timeout=30 + +[MITM] +hostname = %APPEND% in.m.jd.com \ No newline at end of file diff --git a/jd_price.js b/jd_price.js new file mode 100644 index 00000000..f1028e1c --- /dev/null +++ b/jd_price.js @@ -0,0 +1,338 @@ +/* + * 脚本名称:京东比价 + * 使用说明:进入APP商品“大家评”页面触发。 + * 支持版本:App V15.0.80(自行测试) + * 脚本作者:小白脸 + +[Script] +京东比价 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/graphext\/\d+\.html,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price.js,timeout=60 + +[MITM] +hostname = %APPEND% in.m.jd.com + +*/ + +const http = (op) => { + const { promise, resolve, reject } = Promise.withResolvers(); + + this.$httpClient?.get(op, (err, resp, data) => + err ? reject(err) : resolve(JSON.parse(data)) + ); + + this.$task?.fetch(op).then(({ body }) => resolve(JSON.parse(body)), reject); + + return promise; +}; + +const toDate = (t) => { + const d = new Date(t - new Date().getTimezoneOffset() * 60000); + return d.toISOString().split("T")[0]; +}; + +const parseNumber = (input) => { + const cleaned = `${input}`.replace(/[^0-9.-]/g, ""); + return parseFloat(cleaned); +}; + +const formatNumber = (num) => (Number.isInteger(num) ? num : num.toFixed(2)); + +const comparePrices = (a, b) => { + const diff = formatNumber(parseNumber(a) - parseNumber(b)); + + if (diff > 0) return `↑${diff}`; + if (diff < 0) return `↓${-diff}`; + return "●"; +}; + + + +const priceHistoryTable = (data) => { + if (data.err) return `

${data.msg}

`; + + const themeDetection = ` + + `; + + const css = ``; + + let html = ` + ${css} + ${themeDetection} +
+ + + + + + + + + + `; + + data.atts.forEach((row) => { + const statusClass = row.status?.includes("↑") + ? "price-up" + : row.status.includes("↓") + ? "price-down" + : "price-same"; + + const td = Object.keys(row) + .map((item) => ``) + .join(""); + + html += ` + + ${td} + `; + }); + + html += `
+

${data.groupName}

+
类型日期价格状态
${row[item]}
`; + return html; +}; + + + +const getJdData = (body) => { + const { jiagequshiyh } = body.single; + const jiageData = JSON.parse(`[${jiagequshiyh}]`).reverse().slice(0, 360); + + const { result } = jiageData.reduce( + (acc, cur, index, arr) => { + return acc + .getMinNumber(cur) + .getToday(index) + .getLowestPrice(index, arr) + .getHolidays(cur) + .getHistPrices(++index); + }, + { + map: new Map([ + ["当前到手价", []], + ["历史最低价", []], + ["六一八价格", []], + ["双十一价格", []], + ]), + + price: Number.MAX_SAFE_INTEGER, + todayPrice: null, + time: null, + + get result() { + return [...this.map].flatMap(([name, [date, price, status]]) => + date ? [{ name, date, price, status }] : [] + ); + }, + + getToday(i) { + if (i === 0) { + this.todayPrice = this.price; + this.storePriceInfo("当前到手价"); + } + + return this; + }, + getLowestPrice(i, arr) { + if (i === arr.length - 1) this.storePriceInfo("历史最低价"); + + return this; + }, + getHolidays([time, price]) { + const holidays = ["11-11", "06-18"]; + const date = toDate(time); + const holiday = holidays.find((h) => date.endsWith(h)); + if (holiday) { + const title = holiday === "11-11" ? "双十一价格" : "六一八价格"; + this.storePriceInfo(`${title}`, date, `¥${price.toFixed(2)}`); + } + + return this; + }, + getHistPrices(i) { + if ([30, 60, 90, 180, 360].includes(i)) + this.storePriceInfo(`${i}天最低`); + + return this; + }, + getMinNumber([time, price]) { + if (price < parseNumber(this.price)) { + this.price = `¥${price.toFixed(2)}`; + this.time = toDate(time); + } + + return this; + }, + storePriceInfo(key, date = this.time, price = this.price) { + const value = [date, price, comparePrices(this.todayPrice, price)]; + this.map.set(key, value); + }, + } + ); + + return result; +}; + +const getPriceData = async () => { + const body = await http({ + url: "https://apapia-history.manmanbuy.com/ChromeWidgetServices/WidgetServices.ashx", + headers: { + "user-agent": "CFNetwork/3826.500.101 Darwin/24.4.0", + }, + body: `methodName=getHistoryTrend&p_url=https://item.m.jd.com/product/${$request.url.match( + /\d+/ + )}.html"`, + }); + + if (body.err) return body; + + return { + groupName: "历史比价", + atts: getJdData(body), + }; +}; + +getPriceData().then((priceData) => { + let { body, headers } = $response; + const tableHTML = priceHistoryTable(priceData); + + body = body.replace("", `${tableHTML}`); + + $done({ body, headers }); +}); From 4f55735cb5451f19cf184e95634cbbe9bc1c28d0 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Thu, 20 Mar 2025 21:43:05 +0800 Subject: [PATCH 002/109] jd_price.js --- Surge/jd_price2.sgmodule | 2 +- jd_price.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Surge/jd_price2.sgmodule b/Surge/jd_price2.sgmodule index fc6aac8e..507b2e0c 100644 --- a/Surge/jd_price2.sgmodule +++ b/Surge/jd_price2.sgmodule @@ -1,5 +1,5 @@ #!name= 京东比价 -#!desc= 京东App历史价格(商品、大家评页面触发) +#!desc= 京东App历史价格(商品详情页面触发) [Script] 京东比价 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/graphext\/\d+\.html,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price.js,timeout=30 diff --git a/jd_price.js b/jd_price.js index f1028e1c..99920dbd 100644 --- a/jd_price.js +++ b/jd_price.js @@ -1,6 +1,6 @@ /* * 脚本名称:京东比价 - * 使用说明:进入APP商品“大家评”页面触发。 + * 使用说明:进入APP商品详情页面触发。 * 支持版本:App V15.0.80(自行测试) * 脚本作者:小白脸 From 79cbd05f9badb423c46b9610a9a69e10a817cc79 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Thu, 20 Mar 2025 22:32:57 +0800 Subject: [PATCH 003/109] =?UTF-8?q?jd=5Fprice.js=20=E5=85=BC=E5=AE=B9=20Lo?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jd_price.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jd_price.js b/jd_price.js index 99920dbd..3397b2ce 100644 --- a/jd_price.js +++ b/jd_price.js @@ -15,7 +15,7 @@ hostname = %APPEND% in.m.jd.com const http = (op) => { const { promise, resolve, reject } = Promise.withResolvers(); - this.$httpClient?.get(op, (err, resp, data) => + this.$httpClient?.[op.method || "get"](op, (err, resp, data) => err ? reject(err) : resolve(JSON.parse(data)) ); @@ -311,6 +311,7 @@ const getJdData = (body) => { const getPriceData = async () => { const body = await http({ + method: "post", url: "https://apapia-history.manmanbuy.com/ChromeWidgetServices/WidgetServices.ashx", headers: { "user-agent": "CFNetwork/3826.500.101 Darwin/24.4.0", From 77a2b4db0f0fac56a42ca99f47c8654d124f82e4 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 22 Mar 2025 16:08:32 +0800 Subject: [PATCH 004/109] jd_price.js --- jd_price.js | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/jd_price.js b/jd_price.js index 3397b2ce..d4eeabe9 100644 --- a/jd_price.js +++ b/jd_price.js @@ -12,6 +12,15 @@ hostname = %APPEND% in.m.jd.com */ +Promise.withResolvers ||= function () { + let resolve, reject; + const promise = new this((res, rej) => { + resolve = res; + reject = rej; + }); + return { promise, resolve, reject }; +}; + const http = (op) => { const { promise, resolve, reject } = Promise.withResolvers(); @@ -19,9 +28,16 @@ const http = (op) => { err ? reject(err) : resolve(JSON.parse(data)) ); - this.$task?.fetch(op).then(({ body }) => resolve(JSON.parse(body)), reject); + this.$task?.fetch(op).then( + ({ body }) => resolve(JSON.parse(body)), + ({ error }) => reject(error) + ); + + const timer = setTimeout(() => { + reject(new Error("你超时了呀,我来盲猜一波,你没开直连")); + }, 4 * 1000); - return promise; + return promise.finally(() => clearTimeout(timer)); }; const toDate = (t) => { @@ -44,8 +60,6 @@ const comparePrices = (a, b) => { return "●"; }; - - const priceHistoryTable = (data) => { if (data.err) return `

${data.msg}

`; @@ -228,8 +242,6 @@ const priceHistoryTable = (data) => { return html; }; - - const getJdData = (body) => { const { jiagequshiyh } = body.single; const jiageData = JSON.parse(`[${jiagequshiyh}]`).reverse().slice(0, 360); @@ -329,11 +341,16 @@ const getPriceData = async () => { }; }; -getPriceData().then((priceData) => { - let { body, headers } = $response; - const tableHTML = priceHistoryTable(priceData); +getPriceData() + .then((priceData) => { + let { body, headers } = $response; + const tableHTML = priceHistoryTable(priceData); - body = body.replace("", `${tableHTML}`); + body = body.replace("", `${tableHTML}`); - $done({ body, headers }); -}); + $done({ body, headers }); + }) + .catch((e) => { + console.log(e.toString()); + $done({}); + }); From abe1b680aadc08efd821517cdf3763fd5ea24679 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Fri, 11 Apr 2025 06:24:12 +0800 Subject: [PATCH 005/109] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 参考https://raw.githubusercontent.com/wf021325/qx/master/js/jd_price.js --- jd_price.js | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/jd_price.js b/jd_price.js index d4eeabe9..f8b36253 100644 --- a/jd_price.js +++ b/jd_price.js @@ -12,6 +12,8 @@ hostname = %APPEND% in.m.jd.com */ +intCryptoJS(); + Promise.withResolvers ||= function () { let resolve, reject; const promise = new this((res, rej) => { @@ -244,7 +246,8 @@ const priceHistoryTable = (data) => { const getJdData = (body) => { const { jiagequshiyh } = body.single; - const jiageData = JSON.parse(`[${jiagequshiyh}]`).reverse().slice(0, 360); + const jiageStr = jiagequshiyh.replace(/,\s*\]/g, ']'); + const jiageData = JSON.parse(`[${jiageStr}]`).reverse().slice(0, 360); const { result } = jiageData.reduce( (acc, cur, index, arr) => { @@ -322,16 +325,35 @@ const getJdData = (body) => { }; const getPriceData = async () => { - const body = await http({ - method: "post", + const op = (share_url) => { + const rest_body = { + methodName: "getHistoryTrend", + p_url: encodeURIComponent(share_url), + t: Date.now().toString(), + c_appver: "4.0.10", + }; + rest_body.token = md5( + encodeURIComponent( + "3E41D1331F5DDAFCD0A38FE2D52FF66F" + + jsonToCustomString(rest_body) + + "3E41D1331F5DDAFCD0A38FE2D52FF66F" + ) + ).toUpperCase(); + return { + method: "post", url: "https://apapia-history.manmanbuy.com/ChromeWidgetServices/WidgetServices.ashx", headers: { - "user-agent": "CFNetwork/3826.500.101 Darwin/24.4.0", + "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", + "User-Agent": + "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios", }, - body: `methodName=getHistoryTrend&p_url=https://item.m.jd.com/product/${$request.url.match( + body: jsonToQueryString(rest_body), + }; +}; + + const body = await http(op(`https://item.m.jd.com/product/${$request.url.match( /\d+/ - )}.html"`, - }); + )}.html`)); if (body.err) return body; @@ -354,3 +376,15 @@ getPriceData() console.log(e.toString()); $done({}); }); + + + + +function jsonToQueryString(jsonObject) {return Object.keys(jsonObject).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(jsonObject[key])}`).join('&');} + + +function jsonToCustomString(jsonObject){return Object.keys(jsonObject).filter(key=>jsonObject[key]!==''&&key.toLowerCase()!=='token').sort().map(key=>`${key.toUpperCase()}${jsonObject[key].toUpperCase()}`).join('');} + + +function intCryptoJS(){CryptoJS=function(t,r){var n;if("undefined"!=typeof window&&window.crypto&&(n=window.crypto),"undefined"!=typeof self&&self.crypto&&(n=self.crypto),"undefined"!=typeof globalThis&&globalThis.crypto&&(n=globalThis.crypto),!n&&"undefined"!=typeof window&&window.msCrypto&&(n=window.msCrypto),!n&&"undefined"!=typeof global&&global.crypto&&(n=global.crypto),!n&&"function"==typeof require)try{n=require("crypto")}catch(t){}var e=function(){if(n){if("function"==typeof n.getRandomValues)try{return n.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof n.randomBytes)try{return n.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")},i=Object.create||function(){function t(){}return function(r){var n;return t.prototype=r,n=new t,t.prototype=null,n}}(),o={},a=o.lib={},s=a.Base={extend:function(t){var r=i(this);return t&&r.mixIn(t),r.hasOwnProperty("init")&&this.init!==r.init||(r.init=function(){r.$super.init.apply(this,arguments)}),r.init.prototype=r,r.$super=this,r},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var r in t)t.hasOwnProperty(r)&&(this[r]=t[r]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},c=a.WordArray=s.extend({init:function(t,r){t=this.words=t||[],this.sigBytes=null!=r?r:4*t.length},toString:function(t){return(t||f).stringify(this)},concat:function(t){var r=this.words,n=t.words,e=this.sigBytes,i=t.sigBytes;if(this.clamp(),e%4)for(var o=0;o>>2]>>>24-o%4*8&255;r[e+o>>>2]|=a<<24-(e+o)%4*8}else for(var s=0;s>>2]=n[s>>>2];return this.sigBytes+=i,this},clamp:function(){var r=this.words,n=this.sigBytes;r[n>>>2]&=4294967295<<32-n%4*8,r.length=t.ceil(n/4)},clone:function(){var t=s.clone.call(this);return t.words=this.words.slice(0),t},random:function(r){var n,i=[],o=function(r){r=r;var n=987654321,e=4294967295;return function(){var i=((n=36969*(65535&n)+(n>>16)&e)<<16)+(r=18e3*(65535&r)+(r>>16)&e)&e;return i/=4294967296,(i+=.5)*(t.random()>.5?1:-1)}},a=!1;try{e(),a=!0}catch(t){}for(var s,u=0;u>>2]>>>24-i%4*8&255;e.push((o>>>4).toString(16)),e.push((15&o).toString(16))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>3]|=parseInt(t.substr(e,2),16)<<24-e%8*4;return new c.init(n,r/2)}},h=u.Latin1={stringify:function(t){for(var r=t.words,n=t.sigBytes,e=[],i=0;i>>2]>>>24-i%4*8&255;e.push(String.fromCharCode(o))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>2]|=(255&t.charCodeAt(e))<<24-e%4*8;return new c.init(n,r)}},p=u.Utf8={stringify:function(t){try{return decodeURIComponent(escape(h.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return h.parse(unescape(encodeURIComponent(t)))}},d=a.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new c.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=p.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(r){var n,e=this._data,i=e.words,o=e.sigBytes,a=this.blockSize,s=o/(4*a),u=(s=r?t.ceil(s):t.max((0|s)-this._minBufferSize,0))*a,f=t.min(4*u,o);if(u){for(var h=0;h>>24)|4278255360&(i<<24|i>>>8)}var o=this._hash.words,s=t[r+0],p=t[r+1],d=t[r+2],l=t[r+3],y=t[r+4],v=t[r+5],g=t[r+6],w=t[r+7],_=t[r+8],m=t[r+9],B=t[r+10],b=t[r+11],C=t[r+12],S=t[r+13],x=t[r+14],A=t[r+15],H=o[0],z=o[1],M=o[2],D=o[3];z=h(z=h(z=h(z=h(z=f(z=f(z=f(z=f(z=u(z=u(z=u(z=u(z=c(z=c(z=c(z=c(z,M=c(M,D=c(D,H=c(H,z,M,D,s,7,a[0]),z,M,p,12,a[1]),H,z,d,17,a[2]),D,H,l,22,a[3]),M=c(M,D=c(D,H=c(H,z,M,D,y,7,a[4]),z,M,v,12,a[5]),H,z,g,17,a[6]),D,H,w,22,a[7]),M=c(M,D=c(D,H=c(H,z,M,D,_,7,a[8]),z,M,m,12,a[9]),H,z,B,17,a[10]),D,H,b,22,a[11]),M=c(M,D=c(D,H=c(H,z,M,D,C,7,a[12]),z,M,S,12,a[13]),H,z,x,17,a[14]),D,H,A,22,a[15]),M=u(M,D=u(D,H=u(H,z,M,D,p,5,a[16]),z,M,g,9,a[17]),H,z,b,14,a[18]),D,H,s,20,a[19]),M=u(M,D=u(D,H=u(H,z,M,D,v,5,a[20]),z,M,B,9,a[21]),H,z,A,14,a[22]),D,H,y,20,a[23]),M=u(M,D=u(D,H=u(H,z,M,D,m,5,a[24]),z,M,x,9,a[25]),H,z,l,14,a[26]),D,H,_,20,a[27]),M=u(M,D=u(D,H=u(H,z,M,D,S,5,a[28]),z,M,d,9,a[29]),H,z,w,14,a[30]),D,H,C,20,a[31]),M=f(M,D=f(D,H=f(H,z,M,D,v,4,a[32]),z,M,_,11,a[33]),H,z,b,16,a[34]),D,H,x,23,a[35]),M=f(M,D=f(D,H=f(H,z,M,D,p,4,a[36]),z,M,y,11,a[37]),H,z,w,16,a[38]),D,H,B,23,a[39]),M=f(M,D=f(D,H=f(H,z,M,D,S,4,a[40]),z,M,s,11,a[41]),H,z,l,16,a[42]),D,H,g,23,a[43]),M=f(M,D=f(D,H=f(H,z,M,D,m,4,a[44]),z,M,C,11,a[45]),H,z,A,16,a[46]),D,H,d,23,a[47]),M=h(M,D=h(D,H=h(H,z,M,D,s,6,a[48]),z,M,w,10,a[49]),H,z,x,15,a[50]),D,H,v,21,a[51]),M=h(M,D=h(D,H=h(H,z,M,D,C,6,a[52]),z,M,l,10,a[53]),H,z,B,15,a[54]),D,H,p,21,a[55]),M=h(M,D=h(D,H=h(H,z,M,D,_,6,a[56]),z,M,A,10,a[57]),H,z,g,15,a[58]),D,H,S,21,a[59]),M=h(M,D=h(D,H=h(H,z,M,D,y,6,a[60]),z,M,b,10,a[61]),H,z,d,15,a[62]),D,H,m,21,a[63]),o[0]=o[0]+H|0,o[1]=o[1]+z|0,o[2]=o[2]+M|0,o[3]=o[3]+D|0},_doFinalize:function(){var r=this._data,n=r.words,e=8*this._nDataBytes,i=8*r.sigBytes;n[i>>>5]|=128<<24-i%32;var o=t.floor(e/4294967296),a=e;n[15+(i+64>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),n[14+(i+64>>>9<<4)]=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),r.sigBytes=4*(n.length+1),this._process();for(var s=this._hash,c=s.words,u=0;u<4;u++){var f=c[u];c[u]=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8)}return s},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});function c(t,r,n,e,i,o,a){var s=t+(r&n|~r&e)+i+a;return(s<>>32-o)+r}function u(t,r,n,e,i,o,a){var s=t+(r&e|n&~e)+i+a;return(s<>>32-o)+r}function f(t,r,n,e,i,o,a){var s=t+(r^n^e)+i+a;return(s<>>32-o)+r}function h(t,r,n,e,i,o,a){var s=t+(n^(r|~e))+i+a;return(s<>>32-o)+r}r.MD5=i._createHelper(s),r.HmacMD5=i._createHmacHelper(s)}(Math),function(){var t=CryptoJS,r=t.lib.WordArray;t.enc.Base64={stringify:function(t){var r=t.words,n=t.sigBytes,e=this._map;t.clamp();for(var i=[],o=0;o>>2]>>>24-o%4*8&255)<<16|(r[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|r[o+2>>>2]>>>24-(o+2)%4*8&255,s=0;s<4&&o+.75*s>>6*(3-s)&63));var c=e.charAt(64);if(c)for(;i.length%4;)i.push(c);return i.join("")},parse:function(t){var n=t.length,e=this._map,i=this._reverseMap;if(!i){i=this._reverseMap=[];for(var o=0;o>>6-a%4*2;i[o>>>2]|=(s|c)<<24-o%4*8,o++}return r.create(i,o)}(t,n,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}();}; +function md5(word){return CryptoJS.MD5(word).toString();} From ec21a083bfbc8f5635d06cf2a267a35f66eff5cf Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 12 Apr 2025 14:20:44 +0800 Subject: [PATCH 006/109] =?UTF-8?q?jd=5Fbuy=5Fhelper.js=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=8E=A5=E5=8F=A3=EF=BC=8C=E5=8F=82=E8=80=83=E7=81=B0?= =?UTF-8?q?=E7=81=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jd_buy_helper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jd_buy_helper.js b/jd_buy_helper.js index 4a59c5dd..11727e6b 100644 --- a/jd_buy_helper.js +++ b/jd_buy_helper.js @@ -135,10 +135,10 @@ async function jingfenJingTuiTui() { async function get_price_comparison() { return new Promise((resolve) => { const options = { - url: "https://apapia-history.manmanbuy.com/ChromeWidgetServices/WidgetServices.ashx", + url: "https://appia-history.manmanbuy.com/ChromeWidgetServices/WidgetServices.ashx", // 新接口参考灰灰 headers: { "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", - "User-Agent": "iPhone/CFNetwork/Darwin" + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" }, body: 'methodName=getHistoryTrend&p_url=' + encodeURIComponent(`https://item.m.jd.com/product/${$.sku}.html`) }; From b332d07c9d8ba1402edbdded5df061029d991f3e Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 12 Apr 2025 14:27:00 +0800 Subject: [PATCH 007/109] jd_buy_helper.js --- jd_buy_helper.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/jd_buy_helper.js b/jd_buy_helper.js index 11727e6b..40779c3b 100644 --- a/jd_buy_helper.js +++ b/jd_buy_helper.js @@ -135,10 +135,10 @@ async function jingfenJingTuiTui() { async function get_price_comparison() { return new Promise((resolve) => { const options = { - url: "https://appia-history.manmanbuy.com/ChromeWidgetServices/WidgetServices.ashx", // 新接口参考灰灰 + url: "https://apapia-history.manmanbuy.com/ChromeWidgetServices/WidgetServices.ashx", // 新接口URL headers: { "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", - "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios" }, body: 'methodName=getHistoryTrend&p_url=' + encodeURIComponent(`https://item.m.jd.com/product/${$.sku}.html`) }; @@ -146,21 +146,22 @@ async function get_price_comparison() { try { data = JSON.parse(data); if (data?.ok == 1 && data?.single && data?.PriceRemark?.ListPriceDetail) { - // 获取历史最低价和历史最低日期 const ListPriceDetail = data?.PriceRemark?.ListPriceDetail; - + // 使用 find() 方法找到历史最低对象 const lower_data = ListPriceDetail.find(item => item.ShowName == "历史最低"); if (lower_data) { - const { extraPrice, Price, Difference, Date } = lower_data; // 提取最低价、价格差值和日期信息 - $.Difference = Difference; // 价格差值 - $.desc = `历史最低: ${Price || `¥${extraPrice}`} (${Date})`; // 确保 $.desc 已初始化 + const { extraPrice, Price, Difference, Date } = lower_data; + $.Difference = Difference; + $.desc = `历史最低: ${Price || `¥${extraPrice}`} (${Date})`; } else { $.desc = `历史最低: 暂无`; // 如果未找到历史最低价,初始化 $.desc } - $.price = data?.recentlyZK?.currentprice || $.price; // 当前到手价 - $.skuName = data?.single?.title || $.skuName; // 商品标题 - $.skuImg = data?.single?.smallpic || $.skuImg; // 商品图片 + + // 获取当前到手价和商品信息 + $.price = data?.recentlyZK?.currentprice || $.price; + $.skuName = data?.single?.title || $.skuName; + $.skuImg = data?.single?.smallpic || $.skuImg; } else { $.desc = `历史最低: 暂无`; // 如果获取比价信息失败,初始化 $.desc $.log(`获取比价信息失败`); From c843e9c776d5cca3ffc472bd80fb79042069a96e Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 12 Apr 2025 16:13:04 +0800 Subject: [PATCH 008/109] =?UTF-8?q?jd=5Fbuy=5Fhelper.js=20=E5=8F=82?= =?UTF-8?q?=E8=80=83=E7=81=B0=E7=81=B0=EF=BC=8C=E4=BF=AE=E5=A4=8D=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E6=9C=80=E4=BD=8E=E4=BB=B7=E6=A0=BC=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jd_buy_helper.js | 166 +++++++++++++++++++++++++++++++---------------- 1 file changed, 109 insertions(+), 57 deletions(-) diff --git a/jd_buy_helper.js b/jd_buy_helper.js index 40779c3b..25884776 100644 --- a/jd_buy_helper.js +++ b/jd_buy_helper.js @@ -14,6 +14,7 @@ hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com */ const $ = new Env("购物助手"); +intCryptoJS(); let html = $response.body; !(async () => { @@ -46,7 +47,7 @@ async function init_tools() { $.log("初始化开始"); // 从模块传入参数 - const args = typeof $argument !== 'undefined' ? $argument : ""; + const args = typeof $argument !== "undefined" ? $argument : ""; $.log(`传入的参数: ${args}`); const argObj = Object.fromEntries( args.split("&").map((item) => item.split("=").map(decodeURIComponent)) @@ -54,7 +55,8 @@ async function init_tools() { // 参数优先级:模块参数 > BoxJs 参数 $.jd_unionId = argObj["jd_union_id"] || $.getdata("jd_unionId") || ""; - $.jd_positionId = argObj["jd_position_id"] || $.getdata("jd_positionId") || ""; + $.jd_positionId = + argObj["jd_position_id"] || $.getdata("jd_positionId") || ""; $.jtt_appid = argObj["jtt_appid"] || $.getdata("jtt_appid") || ""; $.jtt_appkey = argObj["jtt_appkey"] || $.getdata("jtt_appkey") || ""; @@ -76,7 +78,8 @@ async function init_tools() { if (helperConfig.gwd !== "false") $.button.push("gwd"); if (helperConfig.copy !== "false") $.button.push("copy"); - $.buy_helper_LR = argObj["buy_helper_LR"] || $.getdata("buy_helper_LR") || "left"; + $.buy_helper_LR = + argObj["buy_helper_LR"] || $.getdata("buy_helper_LR") || "left"; let url = $request.url; $.appType = url.includes("lite-in.m.jd.com") ? "jdtj" : "jd"; @@ -92,32 +95,37 @@ async function init_tools() { // 京推推转链 async function jingfenJingTuiTui() { - $.log('转链开始'); + $.log("转链开始"); return new Promise((resolve) => { const options = { url: `http://japi.jingtuitui.com/api/universal?appid=${$.jtt_appid}&appkey=${$.jtt_appkey}&v=v3&unionid=${$.jd_unionId}&positionid=${$.jd_positionId}&content=https://item.jd.com/${$.sku}.html`, timeout: 100 * 1000, headers: { - 'Content-Type': 'application/json;charset=utf-8', + "Content-Type": "application/json;charset=utf-8", }, - } + }; $.get(options, async (err, resp, data) => { try { if (err) { $.log(`京推推 universal 请求失败:${$.toStr(err)}\n`); } else { data = JSON.parse(data); - if (data['return'] == 0) { + if (data["return"] == 0) { const { chain_link, goods_info } = data?.result?.link_date?.[0]; - const { skuName = chain_link, imageInfo, commissionInfo, priceInfo } = goods_info || {}; - $.commissionShare = commissionInfo.commissionShare; // 佣金比例 - $.commission = commissionInfo.couponCommission; // 券后佣金 - $.shortUrl = chain_link; // 二合一短链 - $.price = priceInfo.lowestPrice; // 商品原价 - $.skuName = skuName; // 商品名称 - $.skuImg = imageInfo.imageList[0].url; // 商品主图 + const { + skuName = chain_link, + imageInfo, + commissionInfo, + priceInfo, + } = goods_info || {}; + $.commissionShare = commissionInfo.commissionShare; // 佣金比例 + $.commission = commissionInfo.couponCommission; // 券后佣金 + $.shortUrl = chain_link; // 二合一短链 + $.price = priceInfo.lowestPrice; // 商品原价 + $.skuName = skuName; // 商品名称 + $.skuImg = imageInfo.imageList[0].url; // 商品主图 $.log(`短链地址 ${$.shortUrl}`); - $.log('转链完成'); + $.log("转链完成"); } else { console.log($.toStr(data)); } @@ -127,51 +135,78 @@ async function jingfenJingTuiTui() { } finally { resolve(); } - }) - }) + }); + }); } // 获取比价信息 async function get_price_comparison() { return new Promise((resolve) => { - const options = { - url: "https://apapia-history.manmanbuy.com/ChromeWidgetServices/WidgetServices.ashx", // 新接口URL - headers: { - "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", - "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios" - }, - body: 'methodName=getHistoryTrend&p_url=' + encodeURIComponent(`https://item.m.jd.com/product/${$.sku}.html`) + const options = (share_url) => { + const rest_body = { + methodName: "getHistoryTrend", + p_url: encodeURIComponent(share_url), + t: Date.now().toString(), + c_appver: "4.0.10", + }; + rest_body.token = md5( + encodeURIComponent( + "3E41D1331F5DDAFCD0A38FE2D52FF66F" + + jsonToCustomString(rest_body) + + "3E41D1331F5DDAFCD0A38FE2D52FF66F" + ) + ).toUpperCase(); + return { + method: "post", + url: "https://apapia-history.manmanbuy.com/ChromeWidgetServices/WidgetServices.ashx", + headers: { + "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", + "User-Agent": + "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios", + }, + body: jsonToQueryString(rest_body), + }; }; - $.post(options, (error, response, data) => { - try { - data = JSON.parse(data); - if (data?.ok == 1 && data?.single && data?.PriceRemark?.ListPriceDetail) { - const ListPriceDetail = data?.PriceRemark?.ListPriceDetail; - - // 使用 find() 方法找到历史最低对象 - const lower_data = ListPriceDetail.find(item => item.ShowName == "历史最低"); - if (lower_data) { - const { extraPrice, Price, Difference, Date } = lower_data; - $.Difference = Difference; - $.desc = `历史最低: ${Price || `¥${extraPrice}`} (${Date})`; + + $.post( + options(`https://item.m.jd.com/product/${$.sku}.html`), + (error, response, data) => { + try { + data = JSON.parse(data); + if ( + data?.ok == 1 && + data?.single && + data?.PriceRemark?.ListPriceDetail + ) { + const ListPriceDetail = data?.PriceRemark?.ListPriceDetail; + + // 使用 find() 方法找到历史最低对象 + const lower_data = ListPriceDetail.find( + (item) => item.ShowName == "历史最低" + ); + if (lower_data) { + const { extraPrice, Price, Difference, Date } = lower_data; + $.Difference = Difference; + $.desc = `历史最低: ${Price || `¥${extraPrice}`} (${Date})`; + } else { + $.desc = `历史最低: 暂无`; // 如果未找到历史最低价,初始化 $.desc + } + + // 获取当前到手价和商品信息 + $.price = data?.recentlyZK?.currentprice || $.price; + $.skuName = data?.single?.title || $.skuName; + $.skuImg = data?.single?.smallpic || $.skuImg; } else { - $.desc = `历史最低: 暂无`; // 如果未找到历史最低价,初始化 $.desc + $.desc = `历史最低: 暂无`; // 如果获取比价信息失败,初始化 $.desc + $.log(`获取比价信息失败`); } - - // 获取当前到手价和商品信息 - $.price = data?.recentlyZK?.currentprice || $.price; - $.skuName = data?.single?.title || $.skuName; - $.skuImg = data?.single?.smallpic || $.skuImg; - } else { - $.desc = `历史最低: 暂无`; // 如果获取比价信息失败,初始化 $.desc - $.log(`获取比价信息失败`); + } catch (e) { + $.logErr(e, response); + } finally { + resolve(); } - } catch (e) { - $.logErr(e, response); - } finally { - resolve(); } - }); + ); }); } @@ -182,7 +217,7 @@ async function notice() { // 定义 opts 对象 $.opts = { - 'auto-dismiss': 30 // 30 秒自动删除通知 + "auto-dismiss": 30, // 30 秒自动删除通知 }; // 确保 $.desc 已初始化 @@ -191,8 +226,12 @@ async function notice() { } if (/u\.jd\.com/.test($.shortUrl)) { - $.desc += `\n预计返利: ¥${($.price * $.commissionShare / 100).toFixed(2)} ${$.commissionShare}%`; - $.desc += `\n当前到手: ¥${$.price}${$.Difference ? ` ${$.Difference}` : ``}`; + $.desc += `\n预计返利: ¥${(($.price * $.commissionShare) / 100).toFixed( + 2 + )} ${$.commissionShare}%`; + $.desc += `\n当前到手: ¥${$.price}${ + $.Difference ? ` ${$.Difference}` : `` + }`; // 生成跳转链接 switch ($.appType) { @@ -209,19 +248,21 @@ async function notice() { } // 添加跳转链接 - if ($.jumpUrl) $.opts['$open'] = $.jumpUrl; - + if ($.jumpUrl) $.opts["$open"] = $.jumpUrl; } else { $.desc += `\n预计返利: 暂无`; $.log(`无佣金商品`); } // 添加媒体图片 - if ($.skuImg) $.opts['$media'] = $.skuImg; + if ($.skuImg) $.opts["$media"] = $.skuImg; // 修复 Loon 在 iOS 16 带有媒体导致无法正常通知的 bug if ($.isLoon()) { - $.opts = $loon.split(' ')[1].split('.')[0] === '16' ? { ...$.opts, '$media': undefined } : $.opts; + $.opts = + $loon.split(" ")[1].split(".")[0] === "16" + ? { ...$.opts, $media: undefined } + : $.opts; } // 发送通知 @@ -406,5 +447,16 @@ async function hook_html() { } + +function jsonToQueryString(jsonObject) {return Object.keys(jsonObject).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(jsonObject[key])}`).join('&');} + + +function jsonToCustomString(jsonObject){return Object.keys(jsonObject).filter(key=>jsonObject[key]!==''&&key.toLowerCase()!=='token').sort().map(key=>`${key.toUpperCase()}${jsonObject[key].toUpperCase()}`).join('');} + + +function intCryptoJS(){CryptoJS=function(t,r){var n;if("undefined"!=typeof window&&window.crypto&&(n=window.crypto),"undefined"!=typeof self&&self.crypto&&(n=self.crypto),"undefined"!=typeof globalThis&&globalThis.crypto&&(n=globalThis.crypto),!n&&"undefined"!=typeof window&&window.msCrypto&&(n=window.msCrypto),!n&&"undefined"!=typeof global&&global.crypto&&(n=global.crypto),!n&&"function"==typeof require)try{n=require("crypto")}catch(t){}var e=function(){if(n){if("function"==typeof n.getRandomValues)try{return n.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof n.randomBytes)try{return n.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")},i=Object.create||function(){function t(){}return function(r){var n;return t.prototype=r,n=new t,t.prototype=null,n}}(),o={},a=o.lib={},s=a.Base={extend:function(t){var r=i(this);return t&&r.mixIn(t),r.hasOwnProperty("init")&&this.init!==r.init||(r.init=function(){r.$super.init.apply(this,arguments)}),r.init.prototype=r,r.$super=this,r},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var r in t)t.hasOwnProperty(r)&&(this[r]=t[r]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},c=a.WordArray=s.extend({init:function(t,r){t=this.words=t||[],this.sigBytes=null!=r?r:4*t.length},toString:function(t){return(t||f).stringify(this)},concat:function(t){var r=this.words,n=t.words,e=this.sigBytes,i=t.sigBytes;if(this.clamp(),e%4)for(var o=0;o>>2]>>>24-o%4*8&255;r[e+o>>>2]|=a<<24-(e+o)%4*8}else for(var s=0;s>>2]=n[s>>>2];return this.sigBytes+=i,this},clamp:function(){var r=this.words,n=this.sigBytes;r[n>>>2]&=4294967295<<32-n%4*8,r.length=t.ceil(n/4)},clone:function(){var t=s.clone.call(this);return t.words=this.words.slice(0),t},random:function(r){var n,i=[],o=function(r){r=r;var n=987654321,e=4294967295;return function(){var i=((n=36969*(65535&n)+(n>>16)&e)<<16)+(r=18e3*(65535&r)+(r>>16)&e)&e;return i/=4294967296,(i+=.5)*(t.random()>.5?1:-1)}},a=!1;try{e(),a=!0}catch(t){}for(var s,u=0;u>>2]>>>24-i%4*8&255;e.push((o>>>4).toString(16)),e.push((15&o).toString(16))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>3]|=parseInt(t.substr(e,2),16)<<24-e%8*4;return new c.init(n,r/2)}},h=u.Latin1={stringify:function(t){for(var r=t.words,n=t.sigBytes,e=[],i=0;i>>2]>>>24-i%4*8&255;e.push(String.fromCharCode(o))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>2]|=(255&t.charCodeAt(e))<<24-e%4*8;return new c.init(n,r)}},p=u.Utf8={stringify:function(t){try{return decodeURIComponent(escape(h.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return h.parse(unescape(encodeURIComponent(t)))}},d=a.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new c.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=p.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(r){var n,e=this._data,i=e.words,o=e.sigBytes,a=this.blockSize,s=o/(4*a),u=(s=r?t.ceil(s):t.max((0|s)-this._minBufferSize,0))*a,f=t.min(4*u,o);if(u){for(var h=0;h>>24)|4278255360&(i<<24|i>>>8)}var o=this._hash.words,s=t[r+0],p=t[r+1],d=t[r+2],l=t[r+3],y=t[r+4],v=t[r+5],g=t[r+6],w=t[r+7],_=t[r+8],m=t[r+9],B=t[r+10],b=t[r+11],C=t[r+12],S=t[r+13],x=t[r+14],A=t[r+15],H=o[0],z=o[1],M=o[2],D=o[3];z=h(z=h(z=h(z=h(z=f(z=f(z=f(z=f(z=u(z=u(z=u(z=u(z=c(z=c(z=c(z=c(z,M=c(M,D=c(D,H=c(H,z,M,D,s,7,a[0]),z,M,p,12,a[1]),H,z,d,17,a[2]),D,H,l,22,a[3]),M=c(M,D=c(D,H=c(H,z,M,D,y,7,a[4]),z,M,v,12,a[5]),H,z,g,17,a[6]),D,H,w,22,a[7]),M=c(M,D=c(D,H=c(H,z,M,D,_,7,a[8]),z,M,m,12,a[9]),H,z,B,17,a[10]),D,H,b,22,a[11]),M=c(M,D=c(D,H=c(H,z,M,D,C,7,a[12]),z,M,S,12,a[13]),H,z,x,17,a[14]),D,H,A,22,a[15]),M=u(M,D=u(D,H=u(H,z,M,D,p,5,a[16]),z,M,g,9,a[17]),H,z,b,14,a[18]),D,H,s,20,a[19]),M=u(M,D=u(D,H=u(H,z,M,D,v,5,a[20]),z,M,B,9,a[21]),H,z,A,14,a[22]),D,H,y,20,a[23]),M=u(M,D=u(D,H=u(H,z,M,D,m,5,a[24]),z,M,x,9,a[25]),H,z,l,14,a[26]),D,H,_,20,a[27]),M=u(M,D=u(D,H=u(H,z,M,D,S,5,a[28]),z,M,d,9,a[29]),H,z,w,14,a[30]),D,H,C,20,a[31]),M=f(M,D=f(D,H=f(H,z,M,D,v,4,a[32]),z,M,_,11,a[33]),H,z,b,16,a[34]),D,H,x,23,a[35]),M=f(M,D=f(D,H=f(H,z,M,D,p,4,a[36]),z,M,y,11,a[37]),H,z,w,16,a[38]),D,H,B,23,a[39]),M=f(M,D=f(D,H=f(H,z,M,D,S,4,a[40]),z,M,s,11,a[41]),H,z,l,16,a[42]),D,H,g,23,a[43]),M=f(M,D=f(D,H=f(H,z,M,D,m,4,a[44]),z,M,C,11,a[45]),H,z,A,16,a[46]),D,H,d,23,a[47]),M=h(M,D=h(D,H=h(H,z,M,D,s,6,a[48]),z,M,w,10,a[49]),H,z,x,15,a[50]),D,H,v,21,a[51]),M=h(M,D=h(D,H=h(H,z,M,D,C,6,a[52]),z,M,l,10,a[53]),H,z,B,15,a[54]),D,H,p,21,a[55]),M=h(M,D=h(D,H=h(H,z,M,D,_,6,a[56]),z,M,A,10,a[57]),H,z,g,15,a[58]),D,H,S,21,a[59]),M=h(M,D=h(D,H=h(H,z,M,D,y,6,a[60]),z,M,b,10,a[61]),H,z,d,15,a[62]),D,H,m,21,a[63]),o[0]=o[0]+H|0,o[1]=o[1]+z|0,o[2]=o[2]+M|0,o[3]=o[3]+D|0},_doFinalize:function(){var r=this._data,n=r.words,e=8*this._nDataBytes,i=8*r.sigBytes;n[i>>>5]|=128<<24-i%32;var o=t.floor(e/4294967296),a=e;n[15+(i+64>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),n[14+(i+64>>>9<<4)]=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),r.sigBytes=4*(n.length+1),this._process();for(var s=this._hash,c=s.words,u=0;u<4;u++){var f=c[u];c[u]=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8)}return s},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});function c(t,r,n,e,i,o,a){var s=t+(r&n|~r&e)+i+a;return(s<>>32-o)+r}function u(t,r,n,e,i,o,a){var s=t+(r&e|n&~e)+i+a;return(s<>>32-o)+r}function f(t,r,n,e,i,o,a){var s=t+(r^n^e)+i+a;return(s<>>32-o)+r}function h(t,r,n,e,i,o,a){var s=t+(n^(r|~e))+i+a;return(s<>>32-o)+r}r.MD5=i._createHelper(s),r.HmacMD5=i._createHmacHelper(s)}(Math),function(){var t=CryptoJS,r=t.lib.WordArray;t.enc.Base64={stringify:function(t){var r=t.words,n=t.sigBytes,e=this._map;t.clamp();for(var i=[],o=0;o>>2]>>>24-o%4*8&255)<<16|(r[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|r[o+2>>>2]>>>24-(o+2)%4*8&255,s=0;s<4&&o+.75*s>>6*(3-s)&63));var c=e.charAt(64);if(c)for(;i.length%4;)i.push(c);return i.join("")},parse:function(t){var n=t.length,e=this._map,i=this._reverseMap;if(!i){i=this._reverseMap=[];for(var o=0;o>>6-a%4*2;i[o>>>2]|=(s|c)<<24-o%4*8,o++}return r.create(i,o)}(t,n,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}();}; +function md5(word){return CryptoJS.MD5(word).toString();} + + // prettier-ignore function Env(t, e) { class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise(((e, i) => { s.call(this, t, ((t, s, o) => { t ? i(t) : e(s) })) })) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.logLevels = { debug: 0, info: 1, warn: 2, error: 3 }, this.logLevelPrefixs = { debug: "[DEBUG] ", info: "[INFO] ", warn: "[WARN] ", error: "[ERROR] " }, this.logLevel = "info", this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.encoding = "utf-8", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } getEnv() { return "undefined" != typeof $environment && $environment["surge-version"] ? "Surge" : "undefined" != typeof $environment && $environment["stash-version"] ? "Stash" : "undefined" != typeof module && module.exports ? "Node.js" : "undefined" != typeof $task ? "Quantumult X" : "undefined" != typeof $loon ? "Loon" : "undefined" != typeof $rocket ? "Shadowrocket" : void 0 } isNode() { return "Node.js" === this.getEnv() } isQuanX() { return "Quantumult X" === this.getEnv() } isSurge() { return "Surge" === this.getEnv() } isLoon() { return "Loon" === this.getEnv() } isShadowrocket() { return "Shadowrocket" === this.getEnv() } isStash() { return "Stash" === this.getEnv() } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null, ...s) { try { return JSON.stringify(t, ...s) } catch { return e } } getjson(t, e) { let s = e; if (this.getdata(t)) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise((e => { this.get({ url: t }, ((t, s, i) => e(i))) })) } runScript(t, e) { return new Promise((s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let o = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); o = o ? 1 * o : 20, o = e && e.timeout ? e.timeout : o; const [r, a] = i.split("@"), n = { url: `http://${a}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: o }, headers: { "X-Key": r, Accept: "*/*" }, timeout: o }; this.post(n, ((t, e, i) => s(i))) })).catch((t => this.logErr(t))) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), o = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, o) : i ? this.fs.writeFileSync(e, o) : this.fs.writeFileSync(t, o) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let o = t; for (const t of i) if (o = Object(o)[t], void 0 === o) return s; return o } lodash_set(t, e, s) { return Object(t) !== t || (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce(((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}), t)[e[e.length - 1]] = s), t } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), o = s ? this.getval(s) : ""; if (o) try { const t = JSON.parse(o); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, o] = /^@(.*?)\.(.*?)$/.exec(e), r = this.getval(i), a = i ? "null" === r ? null : r || "{}" : "{}"; try { const e = JSON.parse(a); this.lodash_set(e, o, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const r = {}; this.lodash_set(r, o, t), s = this.setval(JSON.stringify(r), i) } } else s = this.setval(t, e); return s } getval(t) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.read(t); case "Quantumult X": return $prefs.valueForKey(t); case "Node.js": return this.data = this.loaddata(), this.data[t]; default: return this.data && this.data[t] || null } } setval(t, e) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.write(t, e); case "Quantumult X": return $prefs.setValueForKey(t, e); case "Node.js": return this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0; default: return this.data && this.data[e] || null } } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.cookie && void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar))) } get(t, e = (() => { })) { switch (t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"], delete t.headers["content-type"], delete t.headers["content-length"]), t.params && (t.url += "?" + this.queryStr(t.params)), void 0 === t.followRedirect || t.followRedirect || ((this.isSurge() || this.isLoon()) && (t["auto-redirect"] = !1), this.isQuanX() && (t.opts ? t.opts.redirection = !1 : t.opts = { redirection: !1 })), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, ((t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status ? s.status : s.statusCode, s.status = s.statusCode), e(t, s, i) })); break; case "Quantumult X": this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then((t => { const { statusCode: s, statusCode: i, headers: o, body: r, bodyBytes: a } = t; e(null, { status: s, statusCode: i, headers: o, body: r, bodyBytes: a }, r, a) }), (t => e(t && t.error || "UndefinedError"))); break; case "Node.js": let s = require("iconv-lite"); this.initGotEnv(t), this.got(t).on("redirect", ((t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } })).then((t => { const { statusCode: i, statusCode: o, headers: r, rawBody: a } = t, n = s.decode(a, this.encoding); e(null, { status: i, statusCode: o, headers: r, rawBody: a, body: n }, n) }), (t => { const { message: i, response: o } = t; e(i, o, o && s.decode(o.rawBody, this.encoding)) })); break } } post(t, e = (() => { })) { const s = t.method ? t.method.toLocaleLowerCase() : "post"; switch (t.body && t.headers && !t.headers["Content-Type"] && !t.headers["content-type"] && (t.headers["content-type"] = "application/x-www-form-urlencoded"), t.headers && (delete t.headers["Content-Length"], delete t.headers["content-length"]), void 0 === t.followRedirect || t.followRedirect || ((this.isSurge() || this.isLoon()) && (t["auto-redirect"] = !1), this.isQuanX() && (t.opts ? t.opts.redirection = !1 : t.opts = { redirection: !1 })), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient[s](t, ((t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status ? s.status : s.statusCode, s.status = s.statusCode), e(t, s, i) })); break; case "Quantumult X": t.method = s, this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then((t => { const { statusCode: s, statusCode: i, headers: o, body: r, bodyBytes: a } = t; e(null, { status: s, statusCode: i, headers: o, body: r, bodyBytes: a }, r, a) }), (t => e(t && t.error || "UndefinedError"))); break; case "Node.js": let i = require("iconv-lite"); this.initGotEnv(t); const { url: o, ...r } = t; this.got[s](o, r).then((t => { const { statusCode: s, statusCode: o, headers: r, rawBody: a } = t, n = i.decode(a, this.encoding); e(null, { status: s, statusCode: o, headers: r, rawBody: a, body: n }, n) }), (t => { const { message: s, response: o } = t; e(s, o, o && i.decode(o.rawBody, this.encoding)) })); break } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } queryStr(t) { let e = ""; for (const s in t) { let i = t[s]; null != i && "" !== i && ("object" == typeof i && (i = JSON.stringify(i)), e += `${s}=${i}&`) } return e = e.substring(0, e.length - 1), e } msg(e = t, s = "", i = "", o) { const r = t => { const { $open: e, $copy: s, $media: i, $mediaMime: o } = t; switch (typeof t) { case void 0: return t; case "string": switch (this.getEnv()) { case "Surge": case "Stash": default: return { url: t }; case "Loon": case "Shadowrocket": return t; case "Quantumult X": return { "open-url": t }; case "Node.js": return }case "object": switch (this.getEnv()) { case "Surge": case "Stash": case "Shadowrocket": default: { const r = {}; let a = t.openUrl || t.url || t["open-url"] || e; a && Object.assign(r, { action: "open-url", url: a }); let n = t["update-pasteboard"] || t.updatePasteboard || s; if (n && Object.assign(r, { action: "clipboard", text: n }), i) { let t, e, s; if (i.startsWith("http")) t = i; else if (i.startsWith("data:")) { const [t] = i.split(";"), [, o] = i.split(","); e = o, s = t.replace("data:", "") } else { e = i, s = (t => { const e = { JVBERi0: "application/pdf", R0lGODdh: "image/gif", R0lGODlh: "image/gif", iVBORw0KGgo: "image/png", "/9j/": "image/jpg" }; for (var s in e) if (0 === t.indexOf(s)) return e[s]; return null })(i) } Object.assign(r, { "media-url": t, "media-base64": e, "media-base64-mime": o ?? s }) } return Object.assign(r, { "auto-dismiss": t["auto-dismiss"], sound: t.sound }), r } case "Loon": { const s = {}; let i = t.openUrl || t.url || t["open-url"] || e; i && Object.assign(s, { openUrl: i }); let o = t.mediaUrl || t["media-url"]; return o && Object.assign(s, { mediaUrl: o }), s } case "Quantumult X": { const i = {}; let o = t["open-url"] || t.url || t.openUrl || e; o && Object.assign(i, { "open-url": o }); let r = t["media-url"] || t.mediaUrl; r && Object.assign(i, { "media-url": r }); let a = t["update-pasteboard"] || t.updatePasteboard || s; return a && Object.assign(i, { "update-pasteboard": a }), i } case "Node.js": return }default: return } }; if (!this.isMute) switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: $notification.post(e, s, i, r(o)); break; case "Quantumult X": $notify(e, s, i, r(o)); break; case "Node.js": break }if (!this.isMuteLog) { let t = ["", "==============📣系统通知📣=============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } debug(...t) { this.logLevels[this.logLevel] <= this.logLevels.debug && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.debug}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } info(...t) { this.logLevels[this.logLevel] <= this.logLevels.info && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.info}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } warn(...t) { this.logLevels[this.logLevel] <= this.logLevels.warn && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.warn}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } error(...t) { this.logLevels[this.logLevel] <= this.logLevels.error && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.error}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.map((t => t ?? String(t))).join(this.logSeparator)) } logErr(t, e) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": case "Quantumult X": default: this.log("", `❗️${this.name}, 错误!`, e, t); break; case "Node.js": this.log("", `❗️${this.name}, 错误!`, e, void 0 !== t.message ? t.message : t, t.stack); break } } wait(t) { return new Promise((e => setTimeout(e, t))) } done(t = {}) { const e = ((new Date).getTime() - this.startTime) / 1e3; switch (this.log("", `🔔${this.name}, 结束! 🕛 ${e} 秒`), this.log(), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": case "Quantumult X": default: $done(t); break; case "Node.js": process.exit(1) } } }(t, e) } From d395f32575e53a50cb41f387a15500a52e7937a6 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sun, 13 Apr 2025 11:11:48 +0800 Subject: [PATCH 009/109] Hub.sgmodule --- Surge/Hub.sgmodule | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Surge/Hub.sgmodule b/Surge/Hub.sgmodule index 8a1546bd..8803394f 100644 --- a/Surge/Hub.sgmodule +++ b/Surge/Hub.sgmodule @@ -6,11 +6,11 @@ [URL Rewrite] # 转换格式为:Surge -^https:\/\/([a-zA-Z0-9.-]*(git|github|gitlab|gitee|gitcode|kelee)[a-zA-Z0-9.-]*)\/(.*)\/(.*\.(js|conf|snippet|plugin|list|yaml)).*({{{SURGE_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$3/$4/_end_/$4.sgmodule?type=surge-module&target=surge-module&del=true +^https:\/\/([a-zA-Z0-9.-]*(git|github|gitlab|gitee|gitcode)[a-zA-Z0-9.-]*)\/(.*)\/(.*\.(js|conf|snippet|plugin|list|yaml)).*({{{SURGE_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$3/$4/_end_/$4.sgmodule?type=surge-module&target=surge-module&del=true # 转换格式为:Stash -^https:\/\/([a-zA-Z0-9.-]*(git|github|gitlab|gitee|gitcode|kelee)[a-zA-Z0-9.-]*)\/(.*)\/(.*\.(js|conf|snippet|plugin|list|yaml)).*({{{STASH_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$3/$4/_end_/$4.sgmodule?type=qx-rewrite&target=stash-stoverride&del=true +^https:\/\/([a-zA-Z0-9.-]*(git|github|gitlab|gitee|gitcode)[a-zA-Z0-9.-]*)\/(.*)\/(.*\.(js|conf|snippet|plugin|list|yaml)).*({{{STASH_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$3/$4/_end_/$4.sgmodule?type=qx-rewrite&target=stash-stoverride&del=true # 转换格式为:Loon -^https:\/\/([a-zA-Z0-9.-]*(git|github|gitlab|gitee|gitcode|kelee)[a-zA-Z0-9.-]*)\/(.*)\/(.*\.(js|conf|snippet|plugin|list|yaml)).*({{{LOON_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$3/$4/_end_/$4.sgmodule?type=loon-plugin&target=loon-plugin&del=true +^https:\/\/([a-zA-Z0-9.-]*(git|github|gitlab|gitee|gitcode)[a-zA-Z0-9.-]*)\/(.*)\/(.*\.(js|conf|snippet|plugin|list|yaml)).*({{{LOON_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$3/$4/_end_/$4.sgmodule?type=loon-plugin&target=loon-plugin&del=true [MITM] -hostname = %APPEND% raw.githubusercontent.com, gist.github.com, gist.githubusercontent.com, gitlab.com, gitee.com, gitcode.net, github.*, kelee.one +hostname = %APPEND% raw.githubusercontent.com, gist.github.com, gist.githubusercontent.com, gitlab.com, gitee.com, gitcode.net, github.* From c3cf5bff8f8d78d59e5ee57223260d1f429bdad1 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 15 Apr 2025 10:24:09 +0800 Subject: [PATCH 010/109] =?UTF-8?q?jsc=20=E2=86=AA=EF=B8=8E=20webview?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Surge/jd_buy_helper.sgmodule | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Surge/jd_buy_helper.sgmodule b/Surge/jd_buy_helper.sgmodule index dda5ce64..d969409d 100644 --- a/Surge/jd_buy_helper.sgmodule +++ b/Surge/jd_buy_helper.sgmodule @@ -1,11 +1,11 @@ #!name=购物助手 #!desc=京东购物助手,注入跳转、佣金返利、历史价格 #!category=Third Party Module -#!arguments=JD_UNION_ID:京东联盟ID,JD_POSITION_ID:推广位ID,JTT_APPID:京推推AppID,JTT_APPKEY:京推推AppKey,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left -#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nBUY_HELPER_ZDM: 值得买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_MMM: 慢慢买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_GWD: 购物党按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_COPY: 复制短链按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_LR: 按钮位置\n ├ left:左边(默认值)\n └ right:右边 +#!arguments=JD_UNION_ID:京东联盟ID,JD_POSITION_ID:推广位ID,JTT_APPID:京推推AppID,JTT_APPKEY:京推推AppKey,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto +#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nBUY_HELPER_ZDM: 值得买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_MMM: 慢慢买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_GWD: 购物党按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_COPY: 复制短链按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_LR: 按钮位置\n ├ left:左边(默认值)\n └ right:右边\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScript引擎\n └ webview:WebView引擎 [Script] -购物助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_buy_helper.js,argument=jd_union_id={{{JD_UNION_ID}}}&jd_position_id={{{JD_POSITION_ID}}}&jtt_appid={{{JTT_APPID}}}&jtt_appkey={{{JTT_APPKEY}}}&buy_helper_zdm={{{BUY_HELPER_ZDM}}}&buy_helper_mmm={{{BUY_HELPER_MMM}}}&buy_helper_gwd={{{BUY_HELPER_GWD}}}&buy_helper_copy={{{BUY_HELPER_COPY}}}&buy_helper_LR={{{BUY_HELPER_LR}}} +购物助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_buy_helper.js,argument=jd_union_id={{{JD_UNION_ID}}}&jd_position_id={{{JD_POSITION_ID}}}&jtt_appid={{{JTT_APPID}}}&jtt_appkey={{{JTT_APPKEY}}}&buy_helper_zdm={{{BUY_HELPER_ZDM}}}&buy_helper_mmm={{{BUY_HELPER_MMM}}}&buy_helper_gwd={{{BUY_HELPER_GWD}}}&buy_helper_copy={{{BUY_HELPER_COPY}}}&buy_helper_LR={{{BUY_HELPER_LR}}}&engine={{{ENGINE}}} [MITM] -hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com +hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com \ No newline at end of file From dbdedc22ffdf1d93470942e9b685b76dd1e279c4 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 15 Apr 2025 10:34:29 +0800 Subject: [PATCH 011/109] timeout=120 --- Surge/jd_buy_helper.sgmodule | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Surge/jd_buy_helper.sgmodule b/Surge/jd_buy_helper.sgmodule index d969409d..6545ac17 100644 --- a/Surge/jd_buy_helper.sgmodule +++ b/Surge/jd_buy_helper.sgmodule @@ -1,11 +1,11 @@ #!name=购物助手 #!desc=京东购物助手,注入跳转、佣金返利、历史价格 #!category=Third Party Module -#!arguments=JD_UNION_ID:京东联盟ID,JD_POSITION_ID:推广位ID,JTT_APPID:京推推AppID,JTT_APPKEY:京推推AppKey,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto -#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nBUY_HELPER_ZDM: 值得买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_MMM: 慢慢买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_GWD: 购物党按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_COPY: 复制短链按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_LR: 按钮位置\n ├ left:左边(默认值)\n └ right:右边\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScript引擎\n └ webview:WebView引擎 +#!arguments=JD_UNION_ID:京东联盟ID,JD_POSITION_ID:推广位ID,JTT_APPID:京推推AppID,JTT_APPKEY:京推推AppKey,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto,TIMEOUT:120 +#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nBUY_HELPER_ZDM: 值得买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_MMM: 慢慢买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_GWD: 购物党按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_COPY: 复制短链按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_LR: 按钮位置\n ├ left:左边(默认值)\n └ right:右边\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:默认超时(默认值)\n └ 可自定义 [Script] -购物助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_buy_helper.js,argument=jd_union_id={{{JD_UNION_ID}}}&jd_position_id={{{JD_POSITION_ID}}}&jtt_appid={{{JTT_APPID}}}&jtt_appkey={{{JTT_APPKEY}}}&buy_helper_zdm={{{BUY_HELPER_ZDM}}}&buy_helper_mmm={{{BUY_HELPER_MMM}}}&buy_helper_gwd={{{BUY_HELPER_GWD}}}&buy_helper_copy={{{BUY_HELPER_COPY}}}&buy_helper_LR={{{BUY_HELPER_LR}}}&engine={{{ENGINE}}} +购物助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_buy_helper.js,argument=jd_union_id={{{JD_UNION_ID}}}&jd_position_id={{{JD_POSITION_ID}}}&jtt_appid={{{JTT_APPID}}}&jtt_appkey={{{JTT_APPKEY}}}&buy_helper_zdm={{{BUY_HELPER_ZDM}}}&buy_helper_mmm={{{BUY_HELPER_MMM}}}&buy_helper_gwd={{{BUY_HELPER_GWD}}}&buy_helper_copy={{{BUY_HELPER_COPY}}}&buy_helper_LR={{{BUY_HELPER_LR}}}&engine={{{ENGINE}}}&timeout={{{TIMEOUT}}} [MITM] hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com \ No newline at end of file From 253f7e3a95089fb7e47c55b1bde6af592181b751 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Fri, 18 Apr 2025 13:19:51 +0800 Subject: [PATCH 012/109] jd_buy_helper.js --- jd_buy_helper.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/jd_buy_helper.js b/jd_buy_helper.js index 25884776..a336e3fd 100644 --- a/jd_buy_helper.js +++ b/jd_buy_helper.js @@ -53,10 +53,9 @@ async function init_tools() { args.split("&").map((item) => item.split("=").map(decodeURIComponent)) ); - // 参数优先级:模块参数 > BoxJs 参数 - $.jd_unionId = argObj["jd_union_id"] || $.getdata("jd_unionId") || ""; - $.jd_positionId = - argObj["jd_position_id"] || $.getdata("jd_positionId") || ""; + // 参数优先级:模块参数 > BoxJs 数据 + $.jd_unionId = argObj["jd_unionId"] || $.getdata("jd_unionId") || ""; + $.jd_positionId = argObj["jd_positionId"] || $.getdata("jd_positionId") || ""; $.jtt_appid = argObj["jtt_appid"] || $.getdata("jtt_appid") || ""; $.jtt_appkey = argObj["jtt_appkey"] || $.getdata("jtt_appkey") || ""; From a19e8f7178085b20e75ff71e09cc056514ff2071 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 19 Apr 2025 08:05:22 +0800 Subject: [PATCH 013/109] =?UTF-8?q?MmmCK.js=20=E4=BF=AE=E5=A4=8D=E6=AF=94?= =?UTF-8?q?=E4=BB=B7=EF=BC=8C=E5=8F=82=E8=80=83=E7=81=B0=E7=81=B0:new=5Fmo?= =?UTF-8?q?on=5Fwith=5Fface:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MmmCK.js | 36 ++++++++++++++++++++++++++++++++++++ Surge/jd_price2.sgmodule | 10 +++++++--- jd_price.js | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 MmmCK.js diff --git a/MmmCK.js b/MmmCK.js new file mode 100644 index 00000000..ac7dfe28 --- /dev/null +++ b/MmmCK.js @@ -0,0 +1,36 @@ +const $prs = { + get: this.$prefs?.valueForKey ?? $persistentStore.read, + getJson: (key) => JSON.parse($prs.get(key), null, 4), + set: (key, value) => + (this.$prefs?.setValueForKey ?? $persistentStore.write)(value, key), + setJson: (key, obj) => $prs.set(key, JSON.stringify(obj)), +}; + +const $msg = (...a) => { + const { $open, $copy, $media, ...r } = typeof a.at(-1) === "object" && a.pop(); + const [t = "", s = "", b = ""] = a; + (this.$notify ??= $notification.post)(t, s, b, { + action: $copy ? "clipboard" : "open-url", + text: $copy, + "update-pasteboard": $copy, + clipboard: $copy, + "open-url": $open, + openUrl: $open, + url: $open, + mediaUrl: $media, + "media-url": $media, + ...r, + }); +}; + +const params = new URLSearchParams($request.body); +const devId = params.get('c_mmbDevId'); + +if (devId) { + $msg('CK获取成功', devId); + $prs.set('慢慢买CK', devId); +} else { + $msg('CK获取失败', 'c_mmbDevId参数不存在,请重新再试', $request.body); +} + +$done({}); \ No newline at end of file diff --git a/Surge/jd_price2.sgmodule b/Surge/jd_price2.sgmodule index 507b2e0c..a0895d3e 100644 --- a/Surge/jd_price2.sgmodule +++ b/Surge/jd_price2.sgmodule @@ -1,8 +1,12 @@ -#!name= 京东比价 -#!desc= 京东App历史价格(商品详情页面触发) +#!name=京东比价 +#!desc=京东App历史价格(商品详情页面触发) +#!arguments=MMMCK_SCRIPT_NAME:慢慢买CK +#!arguments-desc=[参数设置]\n1. MMMCK_SCRIPT_NAME:慢慢买CK 脚本前往慢慢买App获取Cookie\n2.避免不必要的重写,禁用请设置为"#" [Script] +{{{MMMCK_SCRIPT_NAME}}} = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/MmmCK.js + 京东比价 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/graphext\/\d+\.html,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price.js,timeout=30 [MITM] -hostname = %APPEND% in.m.jd.com \ No newline at end of file +hostname = %APPEND% in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com \ No newline at end of file diff --git a/jd_price.js b/jd_price.js index f8b36253..60485273 100644 --- a/jd_price.js +++ b/jd_price.js @@ -42,6 +42,31 @@ const http = (op) => { return promise.finally(() => clearTimeout(timer)); }; +const $prs = { + get: this.$prefs?.valueForKey ?? $persistentStore.read, + getJson: (key) => JSON.parse($prs.get(key), null, 4), + set: (key, value) => + (this.$prefs?.setValueForKey ?? $persistentStore.write)(value, key), + setJson: (key, obj) => $prs.set(key, JSON.stringify(obj)), +}; + +const $msg = (...a) => { + const { $open, $copy, $media, ...r } = typeof a.at(-1) === "object" && a.pop(); + const [t = "", s = "", b = ""] = a; + (this.$notify ??= $notification.post)(t, s, b, { + action: $copy ? "clipboard" : "open-url", + text: $copy, + "update-pasteboard": $copy, + clipboard: $copy, + "open-url": $open, + openUrl: $open, + url: $open, + mediaUrl: $media, + "media-url": $media, + ...r, + }); +}; + const toDate = (t) => { const d = new Date(t - new Date().getTimezoneOffset() * 60000); return d.toISOString().split("T")[0]; @@ -324,13 +349,20 @@ const getJdData = (body) => { return result; }; +const getmmCK = () => { + const ck = $prs.get("慢慢买CK"); + if (ck) return ck; + throw new Error("未获取ck,请先打开【慢慢买】APP--我的, 获取ck"); +}; + const getPriceData = async () => { const op = (share_url) => { const rest_body = { methodName: "getHistoryTrend", p_url: encodeURIComponent(share_url), t: Date.now().toString(), - c_appver: "4.0.10", + c_appver: "4.8.3.1", + c_mmbDevId: getmmCK(), }; rest_body.token = md5( encodeURIComponent( @@ -374,11 +406,13 @@ getPriceData() }) .catch((e) => { console.log(e.toString()); + $msg(e.toString()); $done({}); }); - +function parseQueryString(queryString) {const jsonObject = {};const pairs = queryString.split('&');pairs.forEach(pair => {const [key, value] = pair.split('=');jsonObject[decodeURIComponent(key)] = decodeURIComponent(value || '');});return jsonObject;} + function jsonToQueryString(jsonObject) {return Object.keys(jsonObject).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(jsonObject[key])}`).join('&');} From 6cab4dbdce4cc040803e770fad52d606650092b6 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 19 Apr 2025 08:33:40 +0800 Subject: [PATCH 014/109] jd_price.js --- jd_price.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jd_price.js b/jd_price.js index 60485273..3cc9bd3c 100644 --- a/jd_price.js +++ b/jd_price.js @@ -406,6 +406,7 @@ getPriceData() }) .catch((e) => { console.log(e.toString()); + console.log(e.stack) $msg(e.toString()); $done({}); }); From a3aee89b58f92c8b5369233cc4e4da7f29fc06de Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 19 Apr 2025 08:50:11 +0800 Subject: [PATCH 015/109] =?UTF-8?q?jd=5Fbuy=5Fhelper.js=20=E5=8F=82?= =?UTF-8?q?=E8=80=83=E7=81=B0=E7=81=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Surge/jd_buy_helper.sgmodule | 8 +++++--- jd_buy_helper.js | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Surge/jd_buy_helper.sgmodule b/Surge/jd_buy_helper.sgmodule index 6545ac17..e11c50ee 100644 --- a/Surge/jd_buy_helper.sgmodule +++ b/Surge/jd_buy_helper.sgmodule @@ -1,11 +1,13 @@ #!name=购物助手 #!desc=京东购物助手,注入跳转、佣金返利、历史价格 #!category=Third Party Module -#!arguments=JD_UNION_ID:京东联盟ID,JD_POSITION_ID:推广位ID,JTT_APPID:京推推AppID,JTT_APPKEY:京推推AppKey,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto,TIMEOUT:120 -#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nBUY_HELPER_ZDM: 值得买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_MMM: 慢慢买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_GWD: 购物党按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_COPY: 复制短链按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_LR: 按钮位置\n ├ left:左边(默认值)\n └ right:右边\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:默认超时(默认值)\n └ 可自定义 +#!arguments=JD_UNION_ID:京东联盟ID,JD_POSITION_ID:推广位ID,JTT_APPID:京推推AppID,JTT_APPKEY:京推推AppKey,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT_NAME:慢慢买CK +#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nBUY_HELPER_ZDM: 值得买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_MMM: 慢慢买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_GWD: 购物党按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_COPY: 复制短链按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_LR: 按钮位置\n ├ left:左边(默认值)\n └ right:右边\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:默认超时(默认值)\n └ 可自定义\nMMMCK_SCRIPT_NAME: 慢慢买 CK 脚本启停\n ├ 慢慢买CK:启用(默认值)\n └ 填入"#":注释停用 [Script] 购物助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_buy_helper.js,argument=jd_union_id={{{JD_UNION_ID}}}&jd_position_id={{{JD_POSITION_ID}}}&jtt_appid={{{JTT_APPID}}}&jtt_appkey={{{JTT_APPKEY}}}&buy_helper_zdm={{{BUY_HELPER_ZDM}}}&buy_helper_mmm={{{BUY_HELPER_MMM}}}&buy_helper_gwd={{{BUY_HELPER_GWD}}}&buy_helper_copy={{{BUY_HELPER_COPY}}}&buy_helper_LR={{{BUY_HELPER_LR}}}&engine={{{ENGINE}}}&timeout={{{TIMEOUT}}} +{{{MMMCK_SCRIPT_NAME}}} = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/MmmCK.js + [MITM] -hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com \ No newline at end of file +hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com \ No newline at end of file diff --git a/jd_buy_helper.js b/jd_buy_helper.js index a336e3fd..e9bb8211 100644 --- a/jd_buy_helper.js +++ b/jd_buy_helper.js @@ -53,9 +53,10 @@ async function init_tools() { args.split("&").map((item) => item.split("=").map(decodeURIComponent)) ); - // 参数优先级:模块参数 > BoxJs 数据 - $.jd_unionId = argObj["jd_unionId"] || $.getdata("jd_unionId") || ""; - $.jd_positionId = argObj["jd_positionId"] || $.getdata("jd_positionId") || ""; + // 参数优先级:模块参数 > BoxJs 参数 + $.jd_unionId = argObj["jd_union_id"] || $.getdata("jd_unionId") || ""; + $.jd_positionId = + argObj["jd_position_id"] || $.getdata("jd_positionId") || ""; $.jtt_appid = argObj["jtt_appid"] || $.getdata("jtt_appid") || ""; $.jtt_appkey = argObj["jtt_appkey"] || $.getdata("jtt_appkey") || ""; @@ -138,6 +139,12 @@ async function jingfenJingTuiTui() { }); } +const getmmCK = () => { + const ck = $.getdata("慢慢买CK"); + if (ck) return ck; + $.msg("未获取ck", "请先打开【慢慢买】APP--我的, 获取ck", "") +}; + // 获取比价信息 async function get_price_comparison() { return new Promise((resolve) => { @@ -146,7 +153,8 @@ async function get_price_comparison() { methodName: "getHistoryTrend", p_url: encodeURIComponent(share_url), t: Date.now().toString(), - c_appver: "4.0.10", + c_appver: "4.8.3.1", + c_mmbDevId: getmmCK(), }; rest_body.token = md5( encodeURIComponent( From e3d05517b0c0423ef044c0564964c4f7d3579aaa Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 19 Apr 2025 10:28:02 +0800 Subject: [PATCH 016/109] jd_buy_helper.sgmodule --- Surge/jd_buy_helper.sgmodule | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Surge/jd_buy_helper.sgmodule b/Surge/jd_buy_helper.sgmodule index e11c50ee..49702706 100644 --- a/Surge/jd_buy_helper.sgmodule +++ b/Surge/jd_buy_helper.sgmodule @@ -1,7 +1,7 @@ #!name=购物助手 #!desc=京东购物助手,注入跳转、佣金返利、历史价格 #!category=Third Party Module -#!arguments=JD_UNION_ID:京东联盟ID,JD_POSITION_ID:推广位ID,JTT_APPID:京推推AppID,JTT_APPKEY:京推推AppKey,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT_NAME:慢慢买CK +#!arguments=JD_UNION_ID:,JD_POSITION_ID:,JTT_APPID:,JTT_APPKEY:,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT_NAME:慢慢买CK #!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nBUY_HELPER_ZDM: 值得买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_MMM: 慢慢买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_GWD: 购物党按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_COPY: 复制短链按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_LR: 按钮位置\n ├ left:左边(默认值)\n └ right:右边\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:默认超时(默认值)\n └ 可自定义\nMMMCK_SCRIPT_NAME: 慢慢买 CK 脚本启停\n ├ 慢慢买CK:启用(默认值)\n └ 填入"#":注释停用 [Script] From af5ed3ad86770141ea8ae1de3ad86d61ed72f344 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 19 Apr 2025 10:29:16 +0800 Subject: [PATCH 017/109] jd_buy_helper.sgmodule --- Surge/jd_buy_helper.sgmodule | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Surge/jd_buy_helper.sgmodule b/Surge/jd_buy_helper.sgmodule index 49702706..321b0291 100644 --- a/Surge/jd_buy_helper.sgmodule +++ b/Surge/jd_buy_helper.sgmodule @@ -1,7 +1,7 @@ #!name=购物助手 #!desc=京东购物助手,注入跳转、佣金返利、历史价格 #!category=Third Party Module -#!arguments=JD_UNION_ID:,JD_POSITION_ID:,JTT_APPID:,JTT_APPKEY:,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT_NAME:慢慢买CK +#!arguments=JD_UNION_ID: ,JD_POSITION_ID: ,JTT_APPID: ,JTT_APPKEY: ,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT_NAME:慢慢买CK #!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nBUY_HELPER_ZDM: 值得买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_MMM: 慢慢买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_GWD: 购物党按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_COPY: 复制短链按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_LR: 按钮位置\n ├ left:左边(默认值)\n └ right:右边\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:默认超时(默认值)\n └ 可自定义\nMMMCK_SCRIPT_NAME: 慢慢买 CK 脚本启停\n ├ 慢慢买CK:启用(默认值)\n └ 填入"#":注释停用 [Script] From b6c4c0934585c8c468a525f00924c0dc20ca323c Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 19 Apr 2025 10:38:00 +0800 Subject: [PATCH 018/109] jd_buy_helper.js --- Surge/jd_buy_helper.sgmodule | 2 +- jd_buy_helper.js | 52 +++++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/Surge/jd_buy_helper.sgmodule b/Surge/jd_buy_helper.sgmodule index 321b0291..6c277a70 100644 --- a/Surge/jd_buy_helper.sgmodule +++ b/Surge/jd_buy_helper.sgmodule @@ -1,7 +1,7 @@ #!name=购物助手 #!desc=京东购物助手,注入跳转、佣金返利、历史价格 #!category=Third Party Module -#!arguments=JD_UNION_ID: ,JD_POSITION_ID: ,JTT_APPID: ,JTT_APPKEY: ,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT_NAME:慢慢买CK +#!arguments=JD_UNION_ID:null,JD_POSITION_ID:null,JTT_APPID:null,JTT_APPKEY:null,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT_NAME:慢慢买CK #!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nBUY_HELPER_ZDM: 值得买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_MMM: 慢慢买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_GWD: 购物党按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_COPY: 复制短链按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_LR: 按钮位置\n ├ left:左边(默认值)\n └ right:右边\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:默认超时(默认值)\n └ 可自定义\nMMMCK_SCRIPT_NAME: 慢慢买 CK 脚本启停\n ├ 慢慢买CK:启用(默认值)\n └ 填入"#":注释停用 [Script] diff --git a/jd_buy_helper.js b/jd_buy_helper.js index e9bb8211..cdb6aca7 100644 --- a/jd_buy_helper.js +++ b/jd_buy_helper.js @@ -46,24 +46,40 @@ let html = $response.body; async function init_tools() { $.log("初始化开始"); - // 从模块传入参数 - const args = typeof $argument !== "undefined" ? $argument : ""; - $.log(`传入的参数: ${args}`); - const argObj = Object.fromEntries( - args.split("&").map((item) => item.split("=").map(decodeURIComponent)) - ); - - // 参数优先级:模块参数 > BoxJs 参数 - $.jd_unionId = argObj["jd_union_id"] || $.getdata("jd_unionId") || ""; - $.jd_positionId = - argObj["jd_position_id"] || $.getdata("jd_positionId") || ""; - $.jtt_appid = argObj["jtt_appid"] || $.getdata("jtt_appid") || ""; - $.jtt_appkey = argObj["jtt_appkey"] || $.getdata("jtt_appkey") || ""; - - $.log(`jd_unionId: ${$.jd_unionId}`); - $.log(`jd_positionId: ${$.jd_positionId}`); - $.log(`jtt_appid: ${$.jtt_appid}`); - $.log(`jtt_appkey: ${$.jtt_appkey}`); +// 从模块传入参数 +const args = typeof $argument !== "undefined" ? $argument : ""; +$.log(`传入的参数: ${args}`); + +const argObj = Object.fromEntries( + args.split("&").map((item) => item.split("=").map(decodeURIComponent)) +); + +// 判断函数:参数为空或为 null 字符串 +function isEmpty(val) { + return !val || val === "null"; +} + +// 参数优先级:模块参数 > BoxJs 参数(但跳过 "null") +$.jd_unionId = !isEmpty(argObj["jd_union_id"]) + ? argObj["jd_union_id"] + : $.getdata("jd_unionId") || ""; + +$.jd_positionId = !isEmpty(argObj["jd_position_id"]) + ? argObj["jd_position_id"] + : $.getdata("jd_positionId") || ""; + +$.jtt_appid = !isEmpty(argObj["jtt_appid"]) + ? argObj["jtt_appid"] + : $.getdata("jtt_appid") || ""; + +$.jtt_appkey = !isEmpty(argObj["jtt_appkey"]) + ? argObj["jtt_appkey"] + : $.getdata("jtt_appkey") || ""; + +$.log(`jd_unionId: ${$.jd_unionId}`); +$.log(`jd_positionId: ${$.jd_positionId}`); +$.log(`jtt_appid: ${$.jtt_appid}`); +$.log(`jtt_appkey: ${$.jtt_appkey}`); $.button = []; const helperConfig = { From ca1183c23b64498d0aa460bf35bb0ce5506b03c7 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 19 Apr 2025 11:10:17 +0800 Subject: [PATCH 019/109] jd_buy_helper.sgmodule --- Surge/jd_buy_helper.sgmodule | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Surge/jd_buy_helper.sgmodule b/Surge/jd_buy_helper.sgmodule index 6c277a70..462985c0 100644 --- a/Surge/jd_buy_helper.sgmodule +++ b/Surge/jd_buy_helper.sgmodule @@ -1,13 +1,13 @@ #!name=购物助手 #!desc=京东购物助手,注入跳转、佣金返利、历史价格 #!category=Third Party Module -#!arguments=JD_UNION_ID:null,JD_POSITION_ID:null,JTT_APPID:null,JTT_APPKEY:null,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT_NAME:慢慢买CK -#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nBUY_HELPER_ZDM: 值得买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_MMM: 慢慢买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_GWD: 购物党按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_COPY: 复制短链按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_LR: 按钮位置\n ├ left:左边(默认值)\n └ right:右边\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:默认超时(默认值)\n └ 可自定义\nMMMCK_SCRIPT_NAME: 慢慢买 CK 脚本启停\n ├ 慢慢买CK:启用(默认值)\n └ 填入"#":注释停用 +#!arguments=JD_UNION_ID:null,JD_POSITION_ID:null,JTT_APPID:null,JTT_APPKEY:null,BUY_HELPER_ZDM:true,BUY_HELPER_MMM:true,BUY_HELPER_GWD:true,BUY_HELPER_COPY:true,BUY_HELPER_LR:left,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT:慢慢买CK +#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nBUY_HELPER_ZDM: 值得买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_MMM: 慢慢买按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_GWD: 购物党按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_COPY: 复制短链按钮\n ├ true:启用(默认值)\n └ false:关闭\nBUY_HELPER_LR: 按钮位置\n ├ left:左边(默认值)\n └ right:右边\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:默认超时(默认值)\n └ 可自定义\nMMMCK_SCRIPT: 慢慢买 CK 脚本启停\n ├ 慢慢买CK:启用(默认值)\n └ 填入"#":注释停用 [Script] 购物助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_buy_helper.js,argument=jd_union_id={{{JD_UNION_ID}}}&jd_position_id={{{JD_POSITION_ID}}}&jtt_appid={{{JTT_APPID}}}&jtt_appkey={{{JTT_APPKEY}}}&buy_helper_zdm={{{BUY_HELPER_ZDM}}}&buy_helper_mmm={{{BUY_HELPER_MMM}}}&buy_helper_gwd={{{BUY_HELPER_GWD}}}&buy_helper_copy={{{BUY_HELPER_COPY}}}&buy_helper_LR={{{BUY_HELPER_LR}}}&engine={{{ENGINE}}}&timeout={{{TIMEOUT}}} -{{{MMMCK_SCRIPT_NAME}}} = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/MmmCK.js +{{{MMMCK_SCRIPT}}} = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/MmmCK.js [MITM] hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com \ No newline at end of file From 501383ce6b8e31c4b44a06046cb1e96b4b3d73b7 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 19 Apr 2025 12:44:45 +0800 Subject: [PATCH 020/109] jd_price2.sgmodule --- Surge/jd_price2.sgmodule | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Surge/jd_price2.sgmodule b/Surge/jd_price2.sgmodule index a0895d3e..9e109513 100644 --- a/Surge/jd_price2.sgmodule +++ b/Surge/jd_price2.sgmodule @@ -1,5 +1,5 @@ #!name=京东比价 -#!desc=京东App历史价格(商品详情页面触发) +#!desc=京东App历史价格(商品详情页面触发)需CK #!arguments=MMMCK_SCRIPT_NAME:慢慢买CK #!arguments-desc=[参数设置]\n1. MMMCK_SCRIPT_NAME:慢慢买CK 脚本前往慢慢买App获取Cookie\n2.避免不必要的重写,禁用请设置为"#" From 8d88e5a7ef8b751a04c86311a92d3f3ad5c85aec Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 19 Apr 2025 16:17:50 +0800 Subject: [PATCH 021/109] jd_price.js --- jd_price.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jd_price.js b/jd_price.js index 3cc9bd3c..feda03ab 100644 --- a/jd_price.js +++ b/jd_price.js @@ -6,9 +6,10 @@ [Script] 京东比价 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/graphext\/\d+\.html,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price.js,timeout=60 +慢慢买CK = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/MmmCK.js [MITM] -hostname = %APPEND% in.m.jd.com +hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com */ From ccfcf06b12eb498212d0ef6ce0e1dd50884827cc Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sat, 19 Apr 2025 16:23:17 +0800 Subject: [PATCH 022/109] jd_buy_helper.js --- jd_buy_helper.js | 3 ++- jd_price.js | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/jd_buy_helper.js b/jd_buy_helper.js index cdb6aca7..40a0ef27 100644 --- a/jd_buy_helper.js +++ b/jd_buy_helper.js @@ -5,8 +5,9 @@ [Script] # > 京东购物助手 购物助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_buy_helper.js +慢慢买CK = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/MmmCK.js [MITM] -hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com +hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com * 添加脚本后依赖BoxJs使用 https://raw.githubusercontent.com/FoKit/Scripts/main/boxjs/fokit.boxjs.json diff --git a/jd_price.js b/jd_price.js index feda03ab..08fd9d07 100644 --- a/jd_price.js +++ b/jd_price.js @@ -6,11 +6,9 @@ [Script] 京东比价 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/graphext\/\d+\.html,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price.js,timeout=60 -慢慢买CK = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/MmmCK.js [MITM] hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com - */ intCryptoJS(); From 9b220d3943a5039ed65bd5457b19dae5b005e342 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Sun, 20 Apr 2025 19:35:19 +0800 Subject: [PATCH 023/109] =?UTF-8?q?jd=5Fbuy=5Fhelper.js=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=87=8F=E5=B0=91=E5=BC=80?= =?UTF-8?q?=E9=94=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jd_buy_helper.js | 535 +++++++++++++++++------------------------------ 1 file changed, 193 insertions(+), 342 deletions(-) diff --git a/jd_buy_helper.js b/jd_buy_helper.js index 40a0ef27..4f31e0be 100644 --- a/jd_buy_helper.js +++ b/jd_buy_helper.js @@ -14,73 +14,74 @@ hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com, apapia-sqk-weblogic.manmanbuy * Surge可填写模块参数使用 https://raw.githubusercontent.com/githubdulong/Script/master/Surge/jd_buy_helper.sgmodule */ + const $ = new Env("购物助手"); intCryptoJS(); let html = $response.body; -!(async () => { +(async () => { if (!html || !html.includes("")) { $.log("找不到标签,结束执行"); $.done({ body: html }); + return; + } + $.log("已开始执行"); + + // 初始化参数与环境变量 + await init_tools(); + + if ($.jd_unionId && $.jtt_appid && $.jtt_appkey) { + + await jingfenJingTuiTui(); } else { - $.log("已开始执行"); - await init_tools(); // 初始化 - if ($.jd_unionId && $.jtt_appid && $.jtt_appkey) { - await jingfenJingTuiTui(); // 京推推转链 - } else { - $.msg($.name, ``, `请检查配置是否正确 ❌`); - $.done({ body: html }); - } - await get_price_comparison(); // 获取比价信息 - await notice(); // 通知 - await hook_html(); // 注入 + $.msg($.name, "", "请检查配置是否正确 ❌"); + $.done({ body: html }); + return; } + + await get_price_comparison(); + + await notice(); + + await hook_html(); })() .catch((e) => { - $.log($.name, ``, `出错了: ${e}❌`); + $.log($.name, "", "出错了: " + e + "❌"); }) .finally(() => { $.done({ body: html }); }); -// 初始化 +/** 初始化:读取模块参数和本地存储参数,设置全局变量 */ async function init_tools() { $.log("初始化开始"); -// 从模块传入参数 -const args = typeof $argument !== "undefined" ? $argument : ""; -$.log(`传入的参数: ${args}`); - -const argObj = Object.fromEntries( - args.split("&").map((item) => item.split("=").map(decodeURIComponent)) -); - -// 判断函数:参数为空或为 null 字符串 -function isEmpty(val) { - return !val || val === "null"; -} - -// 参数优先级:模块参数 > BoxJs 参数(但跳过 "null") -$.jd_unionId = !isEmpty(argObj["jd_union_id"]) - ? argObj["jd_union_id"] - : $.getdata("jd_unionId") || ""; - -$.jd_positionId = !isEmpty(argObj["jd_position_id"]) - ? argObj["jd_position_id"] - : $.getdata("jd_positionId") || ""; - -$.jtt_appid = !isEmpty(argObj["jtt_appid"]) - ? argObj["jtt_appid"] - : $.getdata("jtt_appid") || ""; - -$.jtt_appkey = !isEmpty(argObj["jtt_appkey"]) - ? argObj["jtt_appkey"] - : $.getdata("jtt_appkey") || ""; - -$.log(`jd_unionId: ${$.jd_unionId}`); -$.log(`jd_positionId: ${$.jd_positionId}`); -$.log(`jtt_appid: ${$.jtt_appid}`); -$.log(`jtt_appkey: ${$.jtt_appkey}`); + // 获取模块传入参数 + const args = typeof $argument !== "undefined" ? $argument : ""; + $.log(`传入的参数: ${args}`); + const argObj = Object.fromEntries( + args.split("&").map(item => item.split("=").map(decodeURIComponent)) + ); + const isEmpty = (val) => !val || val === "null"; + + // 参数优先级:模块参数 > BoxJs 本地存储 + $.jd_unionId = !isEmpty(argObj["jd_union_id"]) + ? argObj["jd_union_id"] + : $.getdata("jd_unionId") || ""; + $.jd_positionId = !isEmpty(argObj["jd_position_id"]) + ? argObj["jd_position_id"] + : $.getdata("jd_positionId") || ""; + $.jtt_appid = !isEmpty(argObj["jtt_appid"]) + ? argObj["jtt_appid"] + : $.getdata("jtt_appid") || ""; + $.jtt_appkey = !isEmpty(argObj["jtt_appkey"]) + ? argObj["jtt_appkey"] + : $.getdata("jtt_appkey") || ""; + + $.log(`jd_unionId: ${$.jd_unionId}`); + $.log(`jd_positionId: ${$.jd_positionId}`); + $.log(`jtt_appid: ${$.jtt_appid}`); + $.log(`jtt_appkey: ${$.jtt_appkey}`); $.button = []; const helperConfig = { @@ -89,18 +90,16 @@ $.log(`jtt_appkey: ${$.jtt_appkey}`); gwd: argObj["buy_helper_gwd"] || $.getdata("buy_helper_gwd") || "false", copy: argObj["buy_helper_copy"] || $.getdata("buy_helper_copy") || "true", }; - if (helperConfig.zdm !== "false") $.button.push("smzdm"); if (helperConfig.mmm !== "false") $.button.push("mmm"); if (helperConfig.gwd !== "false") $.button.push("gwd"); if (helperConfig.copy !== "false") $.button.push("copy"); - $.buy_helper_LR = - argObj["buy_helper_LR"] || $.getdata("buy_helper_LR") || "left"; + $.buy_helper_LR = argObj["buy_helper_LR"] || $.getdata("buy_helper_LR") || "left"; let url = $request.url; $.appType = url.includes("lite-in.m.jd.com") ? "jdtj" : "jd"; - $.sku = url.match(/\/(\d+)\.html/)?.[1] || ""; + $.sku = (url.match(/\/(\d+)\.html/) || [])[1] || ""; $.shortUrl = `https://item.jd.com/${$.sku}.html`; $.log("初始化完成"); @@ -110,41 +109,36 @@ $.log(`jtt_appkey: ${$.jtt_appkey}`); $.log(`appkey: ${$.jtt_appkey}`); } -// 京推推转链 +/** 京推推转链 */ async function jingfenJingTuiTui() { $.log("转链开始"); return new Promise((resolve) => { const options = { url: `http://japi.jingtuitui.com/api/universal?appid=${$.jtt_appid}&appkey=${$.jtt_appkey}&v=v3&unionid=${$.jd_unionId}&positionid=${$.jd_positionId}&content=https://item.jd.com/${$.sku}.html`, timeout: 100 * 1000, - headers: { - "Content-Type": "application/json;charset=utf-8", - }, + headers: { "Content-Type": "application/json;charset=utf-8" }, }; - $.get(options, async (err, resp, data) => { + $.get(options, (err, resp, data) => { try { if (err) { - $.log(`京推推 universal 请求失败:${$.toStr(err)}\n`); + $.log("京推推 universal 请求失败:" + $.toStr(err)); } else { data = JSON.parse(data); if (data["return"] == 0) { - const { chain_link, goods_info } = data?.result?.link_date?.[0]; - const { - skuName = chain_link, - imageInfo, - commissionInfo, - priceInfo, - } = goods_info || {}; - $.commissionShare = commissionInfo.commissionShare; // 佣金比例 - $.commission = commissionInfo.couponCommission; // 券后佣金 - $.shortUrl = chain_link; // 二合一短链 - $.price = priceInfo.lowestPrice; // 商品原价 - $.skuName = skuName; // 商品名称 - $.skuImg = imageInfo.imageList[0].url; // 商品主图 - $.log(`短链地址 ${$.shortUrl}`); - $.log("转链完成"); + const linkData = data?.result?.link_date?.[0] || {}; + const { chain_link, goods_info } = linkData; + if (goods_info) { + const { skuName = chain_link, imageInfo, commissionInfo, priceInfo } = goods_info; + $.commissionShare = commissionInfo.commissionShare; + $.commission = commissionInfo.couponCommission; + $.price = priceInfo.lowestPrice; + $.skuName = skuName; + $.skuImg = imageInfo.imageList?.[0]?.url; + } + $.shortUrl = chain_link; + $.log("转链完成,短链地址:" + $.shortUrl); } else { - console.log($.toStr(data)); + $.log("转链返回异常:" + $.toStr(data)); } } } catch (e) { @@ -156,322 +150,179 @@ async function jingfenJingTuiTui() { }); } +/** 获取慢慢买 CK 的封装 */ const getmmCK = () => { - const ck = $.getdata("慢慢买CK"); - if (ck) return ck; - $.msg("未获取ck", "请先打开【慢慢买】APP--我的, 获取ck", "") + const ck = $.getdata("慢慢买CK"); + if (!ck) { + $.msg("未获取ck", "请先打开【慢慢买】APP--我的, 获取ck", ""); + } + return ck; }; -// 获取比价信息 +/** 获取比价信息 */ async function get_price_comparison() { return new Promise((resolve) => { - const options = (share_url) => { - const rest_body = { - methodName: "getHistoryTrend", - p_url: encodeURIComponent(share_url), - t: Date.now().toString(), - c_appver: "4.8.3.1", - c_mmbDevId: getmmCK(), - }; - rest_body.token = md5( - encodeURIComponent( - "3E41D1331F5DDAFCD0A38FE2D52FF66F" + - jsonToCustomString(rest_body) + - "3E41D1331F5DDAFCD0A38FE2D52FF66F" - ) - ).toUpperCase(); - return { - method: "post", - url: "https://apapia-history.manmanbuy.com/ChromeWidgetServices/WidgetServices.ashx", - headers: { - "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", - "User-Agent": - "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios", - }, - body: jsonToQueryString(rest_body), - }; + const shareUrl = `https://item.m.jd.com/product/${$.sku}.html`; + const rest_body = { + methodName: "getHistoryTrend", + p_url: encodeURIComponent(shareUrl), + t: Date.now().toString(), + c_appver: "4.8.3.1", + c_mmbDevId: getmmCK(), }; + rest_body.token = md5( + encodeURIComponent( + "3E41D1331F5DDAFCD0A38FE2D52FF66F" + + jsonToCustomString(rest_body) + + "3E41D1331F5DDAFCD0A38FE2D52FF66F" + ) + ).toUpperCase(); - $.post( - options(`https://item.m.jd.com/product/${$.sku}.html`), - (error, response, data) => { - try { - data = JSON.parse(data); - if ( - data?.ok == 1 && - data?.single && - data?.PriceRemark?.ListPriceDetail - ) { - const ListPriceDetail = data?.PriceRemark?.ListPriceDetail; - - // 使用 find() 方法找到历史最低对象 - const lower_data = ListPriceDetail.find( - (item) => item.ShowName == "历史最低" - ); - if (lower_data) { - const { extraPrice, Price, Difference, Date } = lower_data; - $.Difference = Difference; - $.desc = `历史最低: ${Price || `¥${extraPrice}`} (${Date})`; - } else { - $.desc = `历史最低: 暂无`; // 如果未找到历史最低价,初始化 $.desc - } + const options = { + method: "post", + url: "https://apapia-history.manmanbuy.com/ChromeWidgetServices/WidgetServices.ashx", + headers: { + "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios" + }, + body: jsonToQueryString(rest_body) + }; - // 获取当前到手价和商品信息 - $.price = data?.recentlyZK?.currentprice || $.price; - $.skuName = data?.single?.title || $.skuName; - $.skuImg = data?.single?.smallpic || $.skuImg; + $.post(options, (error, response, data) => { + try { + data = JSON.parse(data); + if (data?.ok == 1 && data?.single && data?.PriceRemark?.ListPriceDetail) { + const lowerItem = data.PriceRemark.ListPriceDetail.find(item => item.ShowName === "历史最低"); + if (lowerItem) { + const { extraPrice, Price, Difference, Date } = lowerItem; + $.Difference = Difference; + $.desc = `历史最低: ${Price || `¥${extraPrice}`} (${Date})`; } else { - $.desc = `历史最低: 暂无`; // 如果获取比价信息失败,初始化 $.desc - $.log(`获取比价信息失败`); + $.desc = "历史最低: 暂无"; } - } catch (e) { - $.logErr(e, response); - } finally { - resolve(); + $.price = data?.recentlyZK?.currentprice || $.price; + $.skuName = data?.single?.title || $.skuName; + $.skuImg = data?.single?.smallpic || $.skuImg; + } else { + $.desc = "历史最低: 暂无"; + $.log("获取比价信息失败"); } + } catch (e) { + $.logErr(e, response); + } finally { + resolve(); } - ); + }); }); } -// 通知 +/** 发送通知 */ async function notice() { - $.log(`发送通知`); - $.title = $.skuName; - - // 定义 opts 对象 - $.opts = { - "auto-dismiss": 30, // 30 秒自动删除通知 - }; - - // 确保 $.desc 已初始化 - if (!$.desc) { - $.desc = ""; // 如果 $.desc 未初始化,设置为空字符串 - } + $.log("发送通知"); + $.title = $.skuName || "商品信息"; + $.opts = { "auto-dismiss": 30 }; + $.desc = $.desc || ""; if (/u\.jd\.com/.test($.shortUrl)) { - $.desc += `\n预计返利: ¥${(($.price * $.commissionShare) / 100).toFixed( - 2 - )} ${$.commissionShare}%`; - $.desc += `\n当前到手: ¥${$.price}${ - $.Difference ? ` ${$.Difference}` : `` - }`; - - // 生成跳转链接 - switch ($.appType) { - case "jdtj": - $.jumpUrl = `openjdlite://virtual?params=${encodeURIComponent( - `{"category":"jump","des":"m","url":"${$.shortUrl}"}` - )}`; - break; - default: - $.jumpUrl = `openApp.jdMobile://virtual?params=${encodeURIComponent( - `{"category":"jump","des":"m","sourceValue":"babel-act","sourceType":"babel","url":"${$.shortUrl}"}` - )}`; - break; + $.desc += `\n预计返利: ¥${(($.price * $.commissionShare) / 100).toFixed(2)} ${$.commissionShare}%`; + $.desc += `\n当前到手: ¥${$.price}${$.Difference ? " " + $.Difference : ""}`; + + // 根据平台生成跳转链接 + if ($.appType === "jdtj") { + $.jumpUrl = `openjdlite://virtual?params=${encodeURIComponent( + '{"category":"jump","des":"m","url":"' + $.shortUrl + '"}' + )}`; + } else { + $.jumpUrl = `openApp.jdMobile://virtual?params=${encodeURIComponent( + '{"category":"jump","des":"m","sourceValue":"babel-act","sourceType":"babel","url":"' + $.shortUrl + '"}' + )}`; } - - // 添加跳转链接 - if ($.jumpUrl) $.opts["$open"] = $.jumpUrl; + $.opts["$open"] = $.jumpUrl; } else { - $.desc += `\n预计返利: 暂无`; - $.log(`无佣金商品`); + $.desc += "\n预计返利: 暂无"; + $.log("无佣金商品"); } - - // 添加媒体图片 if ($.skuImg) $.opts["$media"] = $.skuImg; - - // 修复 Loon 在 iOS 16 带有媒体导致无法正常通知的 bug - if ($.isLoon()) { - $.opts = - $loon.split(" ")[1].split(".")[0] === "16" - ? { ...$.opts, $media: undefined } - : $.opts; + if ($.isLoon() && $loon.split(" ")[1].split(".")[0] === "16") { + $.opts["$media"] = undefined; } - - // 发送通知 $.msg($.title, $.subt, $.desc, $.opts); } -// 注入html +/** 注入 HTML */ async function hook_html() { $.log("开始注入html"); - const buttons = [ - { - key: "mmm", - icon: "https://raw.githubusercontent.com/FoKit/Scripts/main/images/icon/mmm.png", - }, - { - key: "smzdm", - icon: "https://raw.githubusercontent.com/FoKit/Scripts/main/images/icon/zdm.png", - }, - { - key: "gwd", - icon: "https://raw.githubusercontent.com/FoKit/Scripts/main/images/icon/gwd.png", - }, - { - key: "jf", - icon: "https://raw.githubusercontent.com/FoKit/Scripts/main/images/icon/jf.png", - }, - { - key: "copy", - icon: "https://raw.githubusercontent.com/FoKit/Scripts/main/images/icon/copy.png", - }, - ].filter((item) => $.button.includes(item.key) && $.sku); - - $.hook = ` - -
- ${buttons - .map((item) => { - return ``; - }) - .join(`\n`)} + ${buttons.map(item => ``).join("\n")}
- `; - html = html.replace(/(<\/html>)/g, $.hook); + + html = html.replace(/<\/html>/, hookContent); $.log("注入html完成"); $.done({ body: html }); } - function jsonToQueryString(jsonObject) {return Object.keys(jsonObject).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(jsonObject[key])}`).join('&');} From da2f3c01077151d8eadc5061d23ee650eaa0fc81 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Mon, 21 Apr 2025 14:05:22 +0800 Subject: [PATCH 024/109] =?UTF-8?q?jd=5Fprice.js=20=E5=86=8D=E6=AC=A1?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jd_price.js | 330 +++++++++++++++++++++++++++------------------------- 1 file changed, 170 insertions(+), 160 deletions(-) diff --git a/jd_price.js b/jd_price.js index 08fd9d07..bb4f8c9d 100644 --- a/jd_price.js +++ b/jd_price.js @@ -22,21 +22,34 @@ Promise.withResolvers ||= function () { return { promise, resolve, reject }; }; -const http = (op) => { +const $http = (op, t = 4) => { const { promise, resolve, reject } = Promise.withResolvers(); + const HTTPError = (e, req, res) => + Object.assign(new Error(e), { + name: "HTTPError", + request: req, + response: res, + }); + + const handleRes = ({ bodyBytes, ...res }) => { + res.status ??= res.statusCode; + res.json = () => JSON.parse(res.body); + if (res.headers?.["binary-mode"] && bodyBytes) + res.body = new Uint8Array(bodyBytes); + + res.error || res.status < 200 || res.status > 307 + ? reject(HTTPError(res.error, op, res)) + : resolve(res); + }; - this.$httpClient?.[op.method || "get"](op, (err, resp, data) => - err ? reject(err) : resolve(JSON.parse(data)) - ); - - this.$task?.fetch(op).then( - ({ body }) => resolve(JSON.parse(body)), - ({ error }) => reject(error) + const timer = setTimeout( + () => reject(HTTPError("timeout", op)), + op.$timeout ?? t * 1000 ); - - const timer = setTimeout(() => { - reject(new Error("你超时了呀,我来盲猜一波,你没开直连")); - }, 4 * 1000); + this.$httpClient?.[op.method || "get"](op, (error, resp, body) => { + handleRes({ error, ...resp, body }); + }); + this.$task?.fetch({ url: op, ...op }).then(handleRes, handleRes); return promise.finally(() => clearTimeout(timer)); }; @@ -50,7 +63,8 @@ const $prs = { }; const $msg = (...a) => { - const { $open, $copy, $media, ...r } = typeof a.at(-1) === "object" && a.pop(); + const { $open, $copy, $media, ...r } = + typeof a.at(-1) === "object" && a.pop(); const [t = "", s = "", b = ""] = a; (this.$notify ??= $notification.post)(t, s, b, { action: $copy ? "clipboard" : "open-url", @@ -66,36 +80,32 @@ const $msg = (...a) => { }); }; -const toDate = (t) => { - const d = new Date(t - new Date().getTimezoneOffset() * 60000); - return d.toISOString().split("T")[0]; -}; - -const parseNumber = (input) => { - const cleaned = `${input}`.replace(/[^0-9.-]/g, ""); - return parseFloat(cleaned); -}; - -const formatNumber = (num) => (Number.isInteger(num) ? num : num.toFixed(2)); - -const comparePrices = (a, b) => { - const diff = formatNumber(parseNumber(a) - parseNumber(b)); +const $log = new Proxy((...args) => args.forEach((i) => console.log( + i?.stack + ? `${i.toString()}\n${i.stack}` + : typeof i === "object" + ? JSON.stringify(i, null, 4) + : String(i) + )), { + get(target) { + if (!target.init) { + target.time = (id) => (target.time[id] = Date.now()); + target.timeEnd = (id) => target(Date.now() - target.time[id]); + target.show = (...a) => (b) => b && target(...a); + target.init = true; + } - if (diff > 0) return `↑${diff}`; - if (diff < 0) return `↓${-diff}`; - return "●"; -}; + return Reflect.get(...arguments); + }, +}); const priceHistoryTable = (data) => { - if (data.err) return `

${data.msg}

`; - const themeDetection = ` +`; +} + +function get_options(extraParams = {}, url) { + const sourceParams = $.manmanbuy; + const SECRET_KEY = '3E41D1331F5DDAFCD0A38FE2D52FF66F'; + const baseParams = { + t: "", jsoncallback: "?", c_individ: "", c_appver: "", c_ostype: "", c_osver: "", + c_devid: "", c_mmbDevId: "", c_systemDevId: "", c_fixDevId: "", c_devmodel: "", c_brand: "", + c_operator: "", c_engine: "", c_session: "", c_ddToken: "", c_ctrl: "", c_win: "", c_dp: "", + c_safearea: "", c_firstchannel: "", c_firstquerendate: "", c_fristversion: "", c_channel: "", + c_uuid: "", c_ssid: "", c_did: "", c_theme: "", c_jpush: "", c_mmbncid: "", sm_deviceid: "" + }; + + const mergedParams = { + ...baseParams, + ...Object.fromEntries(Object.entries(sourceParams).filter(([key]) => key in baseParams)), + t: Date.now().toString(), + ...extraParams + }; + + const requestBody = { ...mergedParams }; + requestBody.token = md5(encodeURIComponent(SECRET_KEY + jsonToCustomString(requestBody) + SECRET_KEY)).toUpperCase(); + + return { + url, + headers: { + "Content-Type": "application/x-www-form-urlencoded;charset=utf-8", + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios" + }, + body: jsonToQueryString(requestBody) + }; +} + +async function SiteCommand_parse(searchKey) { + const url = 'https://apapia-common.manmanbuy.com/SiteCommand/parse'; + const payload = { methodName: "commonMethod", searchKey }; + const opt = get_options(payload, url); + return await httpRequest(opt); +} + +async function getItemBasicInfo(stteId, link) { + const url = 'https://apapia-history-weblogic.manmanbuy.com/basic/v2/getItemBasicInfo'; + const payload = { methodName: "getHistoryInfoJava", searchKey: link, stteId }; + const opt = get_options(payload, url); + return await httpRequest(opt); +} + +async function share(spbh, jf_url) { + const url = 'https://apapia-history-weblogic.manmanbuy.com/app/share'; + const payload = { methodName: "trendJava", spbh, url: jf_url }; + const opt = get_options(payload, url); + return await httpRequest(opt); +} + +async function trendData(body) { + const opt = { + url: "https://apapia-history-weblogic.manmanbuy.com/h5/share/trendData", + headers: { + "Content-Type": "application/x-www-form-urlencoded;charset=utf-8", + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios" + }, + body + }; + return await httpRequest(opt); +} + +function getck() { + const ck = $.getdata(manmanbuy_key); + if (!ck) { + $.msg($.name, '请先打开【慢慢买】APP', '请确保已成功获取ck'); + return null; + } + const Params = parseQueryString(ck); + if (!Params?.c_mmbDevId) { + $.msg($.name, '数据异常', '请联系脚本作者检查ck格式'); + return null; + } + $.log('慢慢买 c_mmbDevId:', Params.c_mmbDevId); + return Params; +} + +async function httpRequest(options) { + try { + options = options.url ? options : { url: options }; + const _method = options?._method || ('body' in options ? 'post' : 'get'); + const _respType = options?._respType || 'body'; + const _timeout = options?._timeout || 15000; + const _http = [ + new Promise((_, reject) => setTimeout(() => reject(`⛔️ 请求超时: ${options['url']}`), _timeout)), + new Promise((resolve, reject) => { + $[_method.toLowerCase()](options, (error, response, data) => { + error && $.log($.toStr(error)); + if (_respType !== 'all') { + resolve($.toObj(response?.[_respType], response?.[_respType])); + } else { + resolve(response); + } + }); + }) + ]; + return await Promise.race(_http); + } catch (err) { + $.logErr(err); + } +} + +function getParam(queryStr, paramName) { + const params = new URLSearchParams(queryStr); + return params.get(paramName); +} + +function parseQueryString(queryString) { + const jsonObject = {}; + const pairs = queryString.split('&'); + pairs.forEach(pair => { + const [key, value] = pair.split('='); + jsonObject[decodeURIComponent(key)] = decodeURIComponent(value || ''); + }); + return jsonObject; +} + +function jsonToQueryString(jsonObject) { + return Object.keys(jsonObject).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(jsonObject[key])}`).join('&'); +} + +function jsonToCustomString(jsonObject) { + return Object.keys(jsonObject) + .filter(key => jsonObject[key] !== '' && key.toLowerCase() !== 'token') + .sort() + .map(key => `${key.toUpperCase()}${jsonObject[key].toUpperCase()}`) + .join(''); +} + +function intCryptoJS(){CryptoJS=function(t,r){var n;if("undefined"!=typeof window&&window.crypto&&(n=window.crypto),"undefined"!=typeof self&&self.crypto&&(n=self.crypto),"undefined"!=typeof globalThis&&globalThis.crypto&&(n=globalThis.crypto),!n&&"undefined"!=typeof window&&window.msCrypto&&(n=window.msCrypto),!n&&"undefined"!=typeof global&&global.crypto&&(n=global.crypto),!n&&"function"==typeof require)try{n=require("crypto")}catch(t){}var e=function(){if(n){if("function"==typeof n.getRandomValues)try{return n.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof n.randomBytes)try{return n.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")},i=Object.create||function(){function t(){}return function(r){var n;return t.prototype=r,n=new t,t.prototype=null,n}}(),o={},a=o.lib={},s=a.Base={extend:function(t){var r=i(this);return t&&r.mixIn(t),r.hasOwnProperty("init")&&this.init!==r.init||(r.init=function(){r.$super.init.apply(this,arguments)}),r.init.prototype=r,r.$super=this,r},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var r in t)t.hasOwnProperty(r)&&(this[r]=t[r]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},c=a.WordArray=s.extend({init:function(t,r){t=this.words=t||[],this.sigBytes=null!=r?r:4*t.length},toString:function(t){return(t||f).stringify(this)},concat:function(t){var r=this.words,n=t.words,e=this.sigBytes,i=t.sigBytes;if(this.clamp(),e%4)for(var o=0;o>>2]>>>24-o%4*8&255;r[e+o>>>2]|=a<<24-(e+o)%4*8}else for(var s=0;s>>2]=n[s>>>2];return this.sigBytes+=i,this},clamp:function(){var r=this.words,n=this.sigBytes;r[n>>>2]&=4294967295<<32-n%4*8,r.length=t.ceil(n/4)},clone:function(){var t=s.clone.call(this);return t.words=this.words.slice(0),t},random:function(r){var n,i=[],o=function(r){r=r;var n=987654321,e=4294967295;return function(){var i=((n=36969*(65535&n)+(n>>16)&e)<<16)+(r=18e3*(65535&r)+(r>>16)&e)&e;return i/=4294967296,(i+=.5)*(t.random()>.5?1:-1)}},a=!1;try{e(),a=!0}catch(t){}for(var s,u=0;u>>2]>>>24-i%4*8&255;e.push((o>>>4).toString(16)),e.push((15&o).toString(16))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>3]|=parseInt(t.substr(e,2),16)<<24-e%8*4;return new c.init(n,r/2)}},h=u.Latin1={stringify:function(t){for(var r=t.words,n=t.sigBytes,e=[],i=0;i>>2]>>>24-i%4*8&255;e.push(String.fromCharCode(o))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>2]|=(255&t.charCodeAt(e))<<24-e%4*8;return new c.init(n,r)}},p=u.Utf8={stringify:function(t){try{return decodeURIComponent(escape(h.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return h.parse(unescape(encodeURIComponent(t)))}},d=a.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new c.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=p.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(r){var n,e=this._data,i=e.words,o=e.sigBytes,a=this.blockSize,s=o/(4*a),u=(s=r?t.ceil(s):t.max((0|s)-this._minBufferSize,0))*a,f=t.min(4*u,o);if(u){for(var h=0;h>>24)|4278255360&(i<<24|i>>>8)}var o=this._hash.words,s=t[r+0],p=t[r+1],d=t[r+2],l=t[r+3],y=t[r+4],v=t[r+5],g=t[r+6],w=t[r+7],_=t[r+8],m=t[r+9],B=t[r+10],b=t[r+11],C=t[r+12],S=t[r+13],x=t[r+14],A=t[r+15],H=o[0],z=o[1],M=o[2],D=o[3];z=h(z=h(z=h(z=h(z=f(z=f(z=f(z=f(z=u(z=u(z=u(z=u(z=c(z=c(z=c(z=c(z,M=c(M,D=c(D,H=c(H,z,M,D,s,7,a[0]),z,M,p,12,a[1]),H,z,d,17,a[2]),D,H,l,22,a[3]),M=c(M,D=c(D,H=c(H,z,M,D,y,7,a[4]),z,M,v,12,a[5]),H,z,g,17,a[6]),D,H,w,22,a[7]),M=c(M,D=c(D,H=c(H,z,M,D,_,7,a[8]),z,M,m,12,a[9]),H,z,B,17,a[10]),D,H,b,22,a[11]),M=c(M,D=c(D,H=c(H,z,M,D,C,7,a[12]),z,M,S,12,a[13]),H,z,x,17,a[14]),D,H,A,22,a[15]),M=u(M,D=u(D,H=u(H,z,M,D,p,5,a[16]),z,M,g,9,a[17]),H,z,b,14,a[18]),D,H,s,20,a[19]),M=u(M,D=u(D,H=u(H,z,M,D,v,5,a[20]),z,M,B,9,a[21]),H,z,A,14,a[22]),D,H,y,20,a[23]),M=u(M,D=u(D,H=u(H,z,M,D,m,5,a[24]),z,M,x,9,a[25]),H,z,l,14,a[26]),D,H,_,20,a[27]),M=u(M,D=u(D,H=u(H,z,M,D,S,5,a[28]),z,M,d,9,a[29]),H,z,w,14,a[30]),D,H,C,20,a[31]),M=f(M,D=f(D,H=f(H,z,M,D,v,4,a[32]),z,M,_,11,a[33]),H,z,b,16,a[34]),D,H,x,23,a[35]),M=f(M,D=f(D,H=f(H,z,M,D,p,4,a[36]),z,M,y,11,a[37]),H,z,w,16,a[38]),D,H,B,23,a[39]),M=f(M,D=f(D,H=f(H,z,M,D,S,4,a[40]),z,M,s,11,a[41]),H,z,l,16,a[42]),D,H,g,23,a[43]),M=f(M,D=f(D,H=f(H,z,M,D,m,4,a[44]),z,M,C,11,a[45]),H,z,A,16,a[46]),D,H,d,23,a[47]),M=h(M,D=h(D,H=h(H,z,M,D,s,6,a[48]),z,M,w,10,a[49]),H,z,x,15,a[50]),D,H,v,21,a[51]),M=h(M,D=h(D,H=h(H,z,M,D,C,6,a[52]),z,M,l,10,a[53]),H,z,B,15,a[54]),D,H,p,21,a[55]),M=h(M,D=h(D,H=h(H,z,M,D,_,6,a[56]),z,M,A,10,a[57]),H,z,g,15,a[58]),D,H,S,21,a[59]),M=h(M,D=h(D,H=h(H,z,M,D,y,6,a[60]),z,M,b,10,a[61]),H,z,d,15,a[62]),D,H,m,21,a[63]),o[0]=o[0]+H|0,o[1]=o[1]+z|0,o[2]=o[2]+M|0,o[3]=o[3]+D|0},_doFinalize:function(){var r=this._data,n=r.words,e=8*this._nDataBytes,i=8*r.sigBytes;n[i>>>5]|=128<<24-i%32;var o=t.floor(e/4294967296),a=e;n[15+(i+64>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),n[14+(i+64>>>9<<4)]=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),r.sigBytes=4*(n.length+1),this._process();for(var s=this._hash,c=s.words,u=0;u<4;u++){var f=c[u];c[u]=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8)}return s},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});function c(t,r,n,e,i,o,a){var s=t+(r&n|~r&e)+i+a;return(s<>>32-o)+r}function u(t,r,n,e,i,o,a){var s=t+(r&e|n&~e)+i+a;return(s<>>32-o)+r}function f(t,r,n,e,i,o,a){var s=t+(r^n^e)+i+a;return(s<>>32-o)+r}function h(t,r,n,e,i,o,a){var s=t+(n^(r|~e))+i+a;return(s<>>32-o)+r}r.MD5=i._createHelper(s),r.HmacMD5=i._createHmacHelper(s)}(Math),function(){var t=CryptoJS,r=t.lib.WordArray;t.enc.Base64={stringify:function(t){var r=t.words,n=t.sigBytes,e=this._map;t.clamp();for(var i=[],o=0;o>>2]>>>24-o%4*8&255)<<16|(r[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|r[o+2>>>2]>>>24-(o+2)%4*8&255,s=0;s<4&&o+.75*s>>6*(3-s)&63));var c=e.charAt(64);if(c)for(;i.length%4;)i.push(c);return i.join("")},parse:function(t){var n=t.length,e=this._map,i=this._reverseMap;if(!i){i=this._reverseMap=[];for(var o=0;o>>6-a%4*2;i[o>>>2]|=(s|c)<<24-o%4*8,o++}return r.create(i,o)}(t,n,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}();};function md5(word){return CryptoJS.MD5(word).toString();} + +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;"POST"===e&&(s=this.post);const i=new Promise(((e,i)=>{s.call(this,t,((t,s,o)=>{t?i(t):e(s)}))}));return t.timeout?((t,e=1e3)=>Promise.race([t,new Promise(((t,s)=>{setTimeout((()=>{s(new Error("请求超时"))}),e)}))]))(i,t.timeout):i}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.logLevels={debug:0,info:1,warn:2,error:3},this.logLevelPrefixs={debug:"[DEBUG] ",info:"[INFO] ",warn:"[WARN] ",error:"[ERROR] "},this.logLevel="info",this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null,...s){try{return JSON.stringify(t,...s)}catch{return e}}getjson(t,e){let s=e;if(this.getdata(t))try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise((e=>{this.get({url:t},((t,s,i)=>e(i)))}))}runScript(t,e){return new Promise((s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let o=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");o=o?1*o:20,o=e&&e.timeout?e.timeout:o;const[r,a]=i.split("@"),n={url:`http://${a}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:o},headers:{"X-Key":r,Accept:"*/*"},policy:"DIRECT",timeout:o};this.post(n,((t,e,i)=>s(i)))})).catch((t=>this.logErr(t)))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),o=JSON.stringify(this.data);s?this.fs.writeFileSync(t,o):i?this.fs.writeFileSync(e,o):this.fs.writeFileSync(t,o)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let o=t;for(const t of i)if(o=Object(o)[t],void 0===o)return s;return o}lodash_set(t,e,s){return Object(t)!==t||(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce(((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{}),t)[e[e.length-1]]=s),t}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),o=s?this.getval(s):"";if(o)try{const t=JSON.parse(o);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,o]=/^@(.*?)\.(.*?)$/.exec(e),r=this.getval(i),a=i?"null"===r?null:r||"{}":"{}";try{const e=JSON.parse(a);this.lodash_set(e,o,t),s=this.setval(JSON.stringify(e),i)}catch(e){const r={};this.lodash_set(r,o,t),s=this.setval(JSON.stringify(r),i)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.cookie&&void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar)))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),t.params&&(t.url+="?"+this.queryStr(t.params)),void 0===t.followRedirect||t.followRedirect||((this.isSurge()||this.isLoon())&&(t["auto-redirect"]=!1),this.isQuanX()&&(t.opts?t.opts.redirection=!1:t.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,((t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)}));break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then((t=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=t;e(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)}),(t=>e(t&&t.error||"UndefinedError")));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",((t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}})).then((t=>{const{statusCode:i,statusCode:o,headers:r,rawBody:a}=t,n=s.decode(a,this.encoding);e(null,{status:i,statusCode:o,headers:r,rawBody:a,body:n},n)}),(t=>{const{message:i,response:o}=t;e(i,o,o&&s.decode(o.rawBody,this.encoding))}));break}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),void 0===t.followRedirect||t.followRedirect||((this.isSurge()||this.isLoon())&&(t["auto-redirect"]=!1),this.isQuanX()&&(t.opts?t.opts.redirection=!1:t.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,((t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)}));break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then((t=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=t;e(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)}),(t=>e(t&&t.error||"UndefinedError")));break;case"Node.js":let i=require("iconv-lite");this.initGotEnv(t);const{url:o,...r}=t;this.got[s](o,r).then((t=>{const{statusCode:s,statusCode:o,headers:r,rawBody:a}=t,n=i.decode(a,this.encoding);e(null,{status:s,statusCode:o,headers:r,rawBody:a,body:n},n)}),(t=>{const{message:s,response:o}=t;e(s,o,o&&i.decode(o.rawBody,this.encoding))}));break}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}queryStr(t){let e="";for(const s in t){let i=t[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),e+=`${s}=${i}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",i="",o={}){const r=t=>{const{$open:e,$copy:s,$media:i,$mediaMime:o}=t;switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{const r={};let a=t.openUrl||t.url||t["open-url"]||e;a&&Object.assign(r,{action:"open-url",url:a});let n=t["update-pasteboard"]||t.updatePasteboard||s;if(n&&Object.assign(r,{action:"clipboard",text:n}),i){let t,e,s;if(i.startsWith("http"))t=i;else if(i.startsWith("data:")){const[t]=i.split(";"),[,o]=i.split(",");e=o,s=t.replace("data:","")}else{e=i,s=(t=>{const e={JVBERi0:"application/pdf",R0lGODdh:"image/gif",R0lGODlh:"image/gif",iVBORw0KGgo:"image/png","/9j/":"image/jpg"};for(var s in e)if(0===t.indexOf(s))return e[s];return null})(i)}Object.assign(r,{"media-url":t,"media-base64":e,"media-base64-mime":o??s})}return Object.assign(r,{"auto-dismiss":t["auto-dismiss"],sound:t.sound}),r}case"Loon":{const s={};let o=t.openUrl||t.url||t["open-url"]||e;o&&Object.assign(s,{openUrl:o});let r=t.mediaUrl||t["media-url"];return i?.startsWith("http")&&(r=i),r&&Object.assign(s,{mediaUrl:r}),console.log(JSON.stringify(s)),s}case"Quantumult X":{const o={};let r=t["open-url"]||t.url||t.openUrl||e;r&&Object.assign(o,{"open-url":r});let a=t["media-url"]||t.mediaUrl;i?.startsWith("http")&&(a=i),a&&Object.assign(o,{"media-url":a});let n=t["update-pasteboard"]||t.updatePasteboard||s;return n&&Object.assign(o,{"update-pasteboard":n}),console.log(JSON.stringify(o)),o}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,i,r(o));break;case"Quantumult X":$notify(e,s,i,r(o));break;case"Node.js":break}if(!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}debug(...t){this.logLevels[this.logLevel]<=this.logLevels.debug&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`${this.logLevelPrefixs.debug}${t.map((t=>t??String(t))).join(this.logSeparator)}`))}info(...t){this.logLevels[this.logLevel]<=this.logLevels.info&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`${this.logLevelPrefixs.info}${t.map((t=>t??String(t))).join(this.logSeparator)}`))}warn(...t){this.logLevels[this.logLevel]<=this.logLevels.warn&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`${this.logLevelPrefixs.warn}${t.map((t=>t??String(t))).join(this.logSeparator)}`))}error(...t){this.logLevels[this.logLevel]<=this.logLevels.error&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`${this.logLevelPrefixs.error}${t.map((t=>t??String(t))).join(this.logSeparator)}`))}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.map((t=>t??String(t))).join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,e,t);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,e,void 0!==t.message?t.message:t,t.stack);break}}wait(t){return new Promise((e=>setTimeout(e,t)))}done(t={}){const e=((new Date).getTime()-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${e} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} \ No newline at end of file From 613b367800e8e06634da9bcdabd7f54c1274decd Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 22 Apr 2025 00:24:12 +0800 Subject: [PATCH 030/109] jd_price1.sgmodule --- Surge/jd_price1.sgmodule | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Surge/jd_price1.sgmodule b/Surge/jd_price1.sgmodule index f28738a2..262b306c 100644 --- a/Surge/jd_price1.sgmodule +++ b/Surge/jd_price1.sgmodule @@ -1,5 +1,5 @@ #!name=京东比价 -#!desc=京东App历史价格(商品详情页面触发)表格折线版 +#!desc=京东App历史价格(商品详情页面)表格折线版 #!arguments=MMMCK_SCRIPT:慢慢买CK #!arguments-desc=[参数设置]\n1. MMMCK_SCRIPT:慢慢买CK 脚本前往慢慢买App获取Cookie\n2.避免不必要的重写,禁用请设置为"#" From 2eddc4f8f50c07adabe3ec855ca38d1e7b182869 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 22 Apr 2025 00:39:23 +0800 Subject: [PATCH 031/109] =?UTF-8?q?jd=5Fprice2.sgmodule=20=E7=81=B0?= =?UTF-8?q?=E7=81=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Surge/jd_price2.sgmodule | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Surge/jd_price2.sgmodule b/Surge/jd_price2.sgmodule index 9e109513..30eece2c 100644 --- a/Surge/jd_price2.sgmodule +++ b/Surge/jd_price2.sgmodule @@ -1,12 +1,13 @@ #!name=京东比价 -#!desc=京东App历史价格(商品详情页面触发)需CK -#!arguments=MMMCK_SCRIPT_NAME:慢慢买CK -#!arguments-desc=[参数设置]\n1. MMMCK_SCRIPT_NAME:慢慢买CK 脚本前往慢慢买App获取Cookie\n2.避免不必要的重写,禁用请设置为"#" +#!desc=京东App历史价格(商品详情页面触发)表格 +#!arguments=MMMCK_SCRIPT:慢慢买CK +#!arguments-desc=[参数设置]\n1. MMMCK_SCRIPT:慢慢买CK 脚本前往慢慢买App获取Cookie\n2.避免不必要的重写,禁用请设置为"#" [Script] -{{{MMMCK_SCRIPT_NAME}}} = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/MmmCK.js +{{{MMMCK_SCRIPT}}} = type=http-request, pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com\/baoliao\/center\/menu$, script-path=https://raw.githubusercontent.com/wf021325/qx/master/js/jd_price.js, requires-body=true, max-size=-1, timeout=60 + +京东比价 = type=http-response, pattern=^https?:\/\/in\.m\.jd\.com\/product\/graphext\/\d+\.html, script-path=https://raw.githubusercontent.com/wf021325/qx/master/js/jd_price.js, requires-body=true, max-size=-1, timeout=60 -京东比价 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/graphext\/\d+\.html,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price.js,timeout=30 [MITM] hostname = %APPEND% in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com \ No newline at end of file From 2a1972899999c9aacf26b6e728f43e3d7675744b Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 22 Apr 2025 12:11:25 +0800 Subject: [PATCH 032/109] =?UTF-8?q?=E5=8E=9F=E4=BD=9C=E8=80=85@=E8=8B=8D?= =?UTF-8?q?=E4=BA=95=E7=81=B0=E7=81=B0=EF=BC=8C=E4=BB=85=E5=9C=A8=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E4=B8=8A=E5=A2=9E=E5=8A=A0=E6=8A=98=E7=BA=BF=E5=9B=BE?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=EF=BC=8C=E9=80=82=E9=85=8D=E6=9A=97=E9=BB=91?= =?UTF-8?q?=E4=B8=8E=E6=98=8E=E4=BA=AE=E6=A8=A1=E5=BC=8F=EF=BC=88=E6=97=A9?= =?UTF-8?q?7=E7=82=B9=E3=80=81=E6=99=9A19=E7=82=B9=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=88=87=E6=8D=A2=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jd_price1.js | 214 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 154 insertions(+), 60 deletions(-) diff --git a/jd_price1.js b/jd_price1.js index 735dde6f..86fadb45 100644 --- a/jd_price1.js +++ b/jd_price1.js @@ -1,32 +1,13 @@ /* -# 2024-09-16 -# 京东比价 -# 仅适用于京东App版本≤V12.4.3 -# 2024-12-22 -# 发现13.8.3又支持此脚本了 -# 脚本修改来源 https://raw.githubusercontent.com/githubdulong/Script/master/jd_price2.sgmodule -# 1. 修复比价接口 -# 2. 之前只能QX,Surge,更换为Env,兼容Loon等,仅测试QX -2025-01-04 -# 脚本抄袭来源 https://raw.githubusercontent.com/mw418/Loon/main/script/jd_price.js -# 1. 京东很奇怪,标题下面的比价时有时无 所以增加点击【详情】显示比价(显示在页内) -# 2. 抄袭上面的部分代码,让显示格式尽量对其 -2025-04-10 -# 修复比价接口 -2025-04-18 -# 修复比价接口 -# 首次使用请打开【慢慢买】APP,点击【我的】,提示【获取ck成功🎉】即可正常比价 -2025-04-21 -# 修复比价接口,显示为表格 - -[rewrite_local] -^https?:\/\/in\.m\.jd\.com\/product\/graphext\/\d+\.html url script-response-body https://raw.githubusercontent.com/wf021325/qx/master/js/jd_price.js -^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com\/baoliao\/center\/menu$ url script-request-body https://raw.githubusercontent.com/wf021325/qx/master/js/jd_price.js - -# ^https?:\/\/in\.m\.jd\.com\/product\/graphext\/\d+\.html url script-response-body http://192.168.2.170:8080/jd_price.js -# ^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com\/baoliao\/center\/menu$ url script-request-body http://192.168.2.170:8080/jd_price.js -[mitm] -hostname = in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com + +# 2025-04-22 12:09 +# 京东比价脚本,图表+折线 +# 更新内容:原作者@苍井灰灰,仅在基础上增加折线图显示,适配暗黑与明亮模式(早7点、晚19点自动切换) + +# 模块链接:https://raw.githubusercontent.com/githubdulong/Script/master/Surge/jd_price1.sgmodule + +# 原始链接:https://raw.githubusercontent.com/wf021325/qx/master/js/jd_price.js + */ const path1 = '/product/graphext/'; @@ -80,7 +61,7 @@ if (url.includes(path1)) { })(); } -// ================ 工具函数区域 ================ +// ============= 工具函数区域 ============= function checkRes(res, desc = '') { if (res.code !== 2000 || !res.result && !res.data) { @@ -90,10 +71,23 @@ function checkRes(res, desc = '') { } function buildPriceTableHTML(priceList) { + // 校验 priceList + if (!Array.isArray(priceList) || priceList.length === 0) { + console.warn('priceList is empty or invalid, returning empty table'); + return ` +
+ + + +
类型日期价格差价
暂无数据
+
`; + } + const rows = priceList.map(item => { let { Name: name, Date: date, Price: price = '', Difference: diff = '' } = item; if (name === '当前到手价') { - date = $.time('yyyy-MM-dd'); + // 容错处理 $.time + date = typeof $.time === 'function' ? $.time('yyyy-MM-dd') : new Date().toISOString().split('T')[0]; diff = '仅供参考'; } else { date = date || '-'; @@ -108,7 +102,7 @@ function buildPriceTableHTML(priceList) { const chartData = priceList .filter(i => i.Price && !isNaN(parseFloat(String(i.Price).replace(/[¥\s]/g, '')))) .map(i => ({ - date: i.Name === '当前到手价' ? $.time('yyyy-MM-dd') : (i.Date || '-'), + date: i.Name === '当前到手价' ? (typeof $.time === 'function' ? $.time('yyyy-MM-dd') : new Date().toISOString().split('T')[0]) : (i.Date || '-'), price: parseFloat(String(i.Price).replace(/[¥\s]/g, '')) })) .sort((a, b) => new Date(a.date) - new Date(b.date)); @@ -116,6 +110,7 @@ function buildPriceTableHTML(priceList) { const labels = chartData.map(i => i.date); const prices = chartData.map(i => i.price); + // 仅返回 HTML 结构,CSS 和 JS 逻辑分离 return `
@@ -125,21 +120,40 @@ function buildPriceTableHTML(priceList) { -`; + observer.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] }); +}); + +`; } function get_options(extraParams = {}, url) { From ab0f9a9eebdeadf8deeef2e211dc201529192ba3 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 22 Apr 2025 13:00:55 +0800 Subject: [PATCH 033/109] jd_price1.js --- jd_price1.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jd_price1.js b/jd_price1.js index 86fadb45..58741cea 100644 --- a/jd_price1.js +++ b/jd_price1.js @@ -144,7 +144,7 @@ body, table { max-width: 800px; margin: 10px auto; padding: 10px; - font-size: 14px; + font-size: 13px; font-weight: bold; background: var(--background-color); color: var(--text-color); From ed5c73c268c5aebb8cce8040748144ea801c533d Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 22 Apr 2025 16:42:26 +0800 Subject: [PATCH 034/109] =?UTF-8?q?JD=5FHelper.sgmodule=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BA=AC=E6=8E=A8=E6=8E=A8=E8=BF=94=E5=88=A9=EF=BC=8C?= =?UTF-8?q?UI=20=E7=BB=86=E8=8A=82=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Surge/JD_Helper.sgmodule | 12 ++++ jd_price1.js | 122 +++++++++++++++++++++++++++++++++++---- 2 files changed, 123 insertions(+), 11 deletions(-) create mode 100644 Surge/JD_Helper.sgmodule diff --git a/Surge/JD_Helper.sgmodule b/Surge/JD_Helper.sgmodule new file mode 100644 index 00000000..c709ece7 --- /dev/null +++ b/Surge/JD_Helper.sgmodule @@ -0,0 +1,12 @@ +#!name=京东助手 +#!desc=京东助手 点击详情页面触发佣金返利和历史价格 +#!arguments=JD_UNION_ID:null,JD_POSITION_ID:null,JTT_APPID:null,JTT_APPKEY:null,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT:慢慢买CK,DISABLE_NOTICE:true +#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:默认超时(默认值)\n └ 可自定义\nMMMCK_SCRIPT: 慢慢买 CK 脚本启停\n ├ 慢慢买CK:启用(默认值)\n └ 填入"#":注释停用\nDISABLE_NOTICE: 是否启用转链及通知功能\n ├ true:启用转链与通知功能(默认)\n └ false:禁用转链与通知,仅显示比价图表 + +[Script] +京东助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price1.js,argument=jd_union_id={{{JD_UNION_ID}}}&jd_position_id={{{JD_POSITION_ID}}}&jtt_appid={{{JTT_APPID}}}&jtt_appkey={{{JTT_APPKEY}}}&engine={{{ENGINE}}}&timeout={{{TIMEOUT}}}&disable_notice={{{DISABLE_NOTICE}}} + +{{{MMMCK_SCRIPT}}} = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price1.js.js + +[MITM] +hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com \ No newline at end of file diff --git a/jd_price1.js b/jd_price1.js index 58741cea..a1dfdb5c 100644 --- a/jd_price1.js +++ b/jd_price1.js @@ -1,12 +1,15 @@ /* -# 2025-04-22 12:09 -# 京东比价脚本,图表+折线 -# 更新内容:原作者@苍井灰灰,仅在基础上增加折线图显示,适配暗黑与明亮模式(早7点、晚19点自动切换) +# 2025-04-22 16:40 +# 京东购物助手,京推推转链+比价图表 + +# 更新内容: +# 比价脚本原作者@苍井灰灰,在基础上增加京推推商品返利转链(点通知)+比价折线图表格显示,适配暗黑与明亮模式(早7点、晚19点自动切换) + +# Surge模块设置参数,或自己折腾Boxjs配置京推推参数 # 模块链接:https://raw.githubusercontent.com/githubdulong/Script/master/Surge/jd_price1.sgmodule -# 原始链接:https://raw.githubusercontent.com/wf021325/qx/master/js/jd_price.js */ @@ -15,6 +18,20 @@ const path2 = '/baoliao/center/menu' const manmanbuy_key = 'manmanbuy_val'; const url = $request.url; const $ = new Env("京东比价"); +// 获取模块传入参数 +const args = typeof $argument !== "undefined" ? $argument : ""; +$.log(`读取参数: ${args}`); +const argObj = Object.fromEntries( +args.split("&").map(item => item.split("=").map(decodeURIComponent)) +); +const isEmpty = (val) => !val || val === "null"; + +// 参数优先级:模块参数 > BoxJs 本地存储 +$.jd_unionId = !isEmpty(argObj["jd_union_id"]) ? argObj["jd_union_id"] : $.getdata("jd_unionId") || ""; +$.jd_positionId = !isEmpty(argObj["jd_position_id"]) ? argObj["jd_position_id"] : $.getdata("jd_positionId") || ""; +$.jtt_appid = !isEmpty(argObj["jtt_appid"]) ? argObj["jtt_appid"] : $.getdata("jtt_appid") || ""; +$.jtt_appkey = !isEmpty(argObj["jtt_appkey"]) ? argObj["jtt_appkey"] : $.getdata("jtt_appkey") || ""; +$.disableNotice = argObj["disable_notice"] === "false" ? false : true; if (url.includes(path2)) { const reqbody = $request.body; @@ -25,6 +42,8 @@ if (url.includes(path2)) { if (url.includes(path1)) { intCryptoJS(); $.manmanbuy = getck(); + let url = $request.url; + $.appType = url.includes("lite-in.m.jd.com") ? "jdtj" : "jd"; (async () => { const match = url.match(/product\/graphext\/(\d+)\.html/); @@ -35,6 +54,13 @@ if (url.includes(path1)) { const shareUrl = `https://item.jd.com/${match[1]}.html`; try { + if ($.disableNotice && $.jd_unionId && $.jtt_appid && $.jtt_appkey) { + $.sku = match[1]; + await jingfenJingTuiTui(); + await notice(); +} else if (!$.disableNotice) { + $.log("已禁用京推推返利和通知,仅显示比价图表"); +} const parseRes = await SiteCommand_parse(shareUrl); const parse = checkRes(parseRes, '获取 stteId'); @@ -61,8 +87,77 @@ if (url.includes(path1)) { })(); } -// ============= 工具函数区域 ============= - +/** 京推推转链 */ +async function jingfenJingTuiTui() { + $.log("转链开始"); + return new Promise((resolve) => { + const options = { + url: `http://japi.jingtuitui.com/api/universal?appid=${$.jtt_appid}&appkey=${$.jtt_appkey}&v=v3&unionid=${$.jd_unionId}&positionid=${$.jd_positionId}&content=https://item.jd.com/${$.sku}.html`, + timeout: 5000, + headers: { "Content-Type": "application/json;charset=utf-8" }, + }; + $.get(options, (err, resp, data) => { + try { + if (err) { + $.log("京推推 universal 请求失败:" + $.toStr(err)); + } else { + data = JSON.parse(data); + if (data["return"] == 0) { + const linkData = data?.result?.link_date?.[0] || {}; + const { chain_link, goods_info } = linkData; + if (goods_info) { + const { skuName = chain_link, imageInfo, commissionInfo, priceInfo } = goods_info; + $.commissionShare = commissionInfo.commissionShare; + $.commission = commissionInfo.couponCommission; + $.price = priceInfo.lowestPrice; + $.skuName = skuName; + $.skuImg = imageInfo.imageList?.[0]?.url; + } + $.shortUrl = chain_link; + $.log("转链完成,短链地址:" + $.shortUrl); + } else { + $.log("转链返回异常:" + $.toStr(data)); + } + } + } catch (e) { + $.logErr(e, resp); + } finally { + resolve(); + } + }); + }); +} +/** 发送通知 */ +async function notice() { + $.log("发送通知"); + $.title = $.skuName || "商品信息"; + $.opts = { "auto-dismiss": 30 }; + + $.desc = $.desc || ""; + if (/u\.jd\.com/.test($.shortUrl)) { + $.desc += `预计返利: ¥${(($.price * $.commissionShare) / 100).toFixed(2)} ${$.commissionShare}%`; + + // 根据平台生成跳转链接 + if ($.appType === "jdtj") { + $.jumpUrl = `openjdlite://virtual?params=${encodeURIComponent( + '{"category":"jump","des":"m","url":"' + $.shortUrl + '"}' + )}`; + } else { + $.jumpUrl = `openApp.jdMobile://virtual?params=${encodeURIComponent( + '{"category":"jump","des":"m","sourceValue":"babel-act","sourceType":"babel","url":"' + $.shortUrl + '"}' + )}`; + } + $.opts["$open"] = $.jumpUrl; + } else { + $.desc += "\n预计返利: 暂无"; + $.log("无佣金商品"); + } + if ($.skuImg) $.opts["$media"] = $.skuImg; + if ($.isLoon() && $loon.split(" ")[1].split(".")[0] === "16") { + $.opts["$media"] = undefined; + } + $.msg($.title, $.subt, $.desc, $.opts); +} function checkRes(res, desc = '') { if (res.code !== 2000 || !res.result && !res.data) { throw new Error(`慢慢买提示您:${res.msg || `${desc}失败`}`); @@ -126,7 +221,7 @@ body, table { /* 主题变量 */ :root { - --background-color: #FFF9F9; + --background-color: #FEFEFE; --text-color: #333; --border-color: #EEE; --shadow-color: rgba(0,0,0,0.05); @@ -134,7 +229,7 @@ body, table { /* 暗黑模式变量 */ [data-theme="dark"] { - --background-color: #2a2a2a; + --background-color: #1a1a1a; --text-color: #f0f0f0; --border-color: #444; --shadow-color: rgba(0,0,0,0.2); @@ -156,18 +251,23 @@ body, table { .price-table { width: 100%; - border-collapse: separate; + border-collapse: collapse; border-spacing: 0; border-radius: 8px; overflow: hidden; } +.price-table thead tr { + background: linear-gradient(to right, #ff6666, #e61a23); +} + .price-table th { - background: #e61a23; + background: none; color: #fff; padding: 12px; text-align: left; font-weight: bold; + border: none; } .price-table td { @@ -394,7 +494,7 @@ function getck() { $.msg($.name, '数据异常', '请联系脚本作者检查ck格式'); return null; } - $.log('慢慢买 c_mmbDevId:', Params.c_mmbDevId); + $.log('慢慢买CK:', Params.c_mmbDevId); return Params; } From c38b7c077ba8af50f2fd832bffd65e623b9883b5 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 22 Apr 2025 16:44:18 +0800 Subject: [PATCH 035/109] jd_price1.sgmodule --- Surge/jd_price1.sgmodule | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 Surge/jd_price1.sgmodule diff --git a/Surge/jd_price1.sgmodule b/Surge/jd_price1.sgmodule deleted file mode 100644 index 262b306c..00000000 --- a/Surge/jd_price1.sgmodule +++ /dev/null @@ -1,13 +0,0 @@ -#!name=京东比价 -#!desc=京东App历史价格(商品详情页面)表格折线版 -#!arguments=MMMCK_SCRIPT:慢慢买CK -#!arguments-desc=[参数设置]\n1. MMMCK_SCRIPT:慢慢买CK 脚本前往慢慢买App获取Cookie\n2.避免不必要的重写,禁用请设置为"#" - -[Script] -{{{MMMCK_SCRIPT}}} = type=http-request, pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com\/baoliao\/center\/menu$, script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price1.js, requires-body=true, max-size=-1, timeout=60 - -京东比价 = type=http-response, pattern=^https?:\/\/in\.m\.jd\.com\/product\/graphext\/\d+\.html, script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price1.js, requires-body=true, max-size=-1, timeout=60 - - -[MITM] -hostname = %APPEND% in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com \ No newline at end of file From ece637acc891fb9684096d74b044d1395ff29370 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 22 Apr 2025 16:45:38 +0800 Subject: [PATCH 036/109] JD_Helper.sgmodule --- Surge/JD_Helper.sgmodule | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Surge/JD_Helper.sgmodule b/Surge/JD_Helper.sgmodule index c709ece7..ae972422 100644 --- a/Surge/JD_Helper.sgmodule +++ b/Surge/JD_Helper.sgmodule @@ -6,7 +6,7 @@ [Script] 京东助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price1.js,argument=jd_union_id={{{JD_UNION_ID}}}&jd_position_id={{{JD_POSITION_ID}}}&jtt_appid={{{JTT_APPID}}}&jtt_appkey={{{JTT_APPKEY}}}&engine={{{ENGINE}}}&timeout={{{TIMEOUT}}}&disable_notice={{{DISABLE_NOTICE}}} -{{{MMMCK_SCRIPT}}} = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price1.js.js +{{{MMMCK_SCRIPT}}} = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price1.js [MITM] hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com \ No newline at end of file From 7b26e7d57bad9b5bebfe5a4f7c40fe5dd403d4d5 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 22 Apr 2025 17:04:08 +0800 Subject: [PATCH 037/109] jd_price1.js --- jd_price1.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jd_price1.js b/jd_price1.js index a1dfdb5c..b59788d6 100644 --- a/jd_price1.js +++ b/jd_price1.js @@ -8,7 +8,7 @@ # Surge模块设置参数,或自己折腾Boxjs配置京推推参数 -# 模块链接:https://raw.githubusercontent.com/githubdulong/Script/master/Surge/jd_price1.sgmodule +# 模块链接:https://raw.githubusercontent.com/githubdulong/Script/master/Surge/JD_Helper.sgmodule */ From 8ef2bdda5d27a9de540924df3a098da1411bf360 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 22 Apr 2025 18:37:33 +0800 Subject: [PATCH 038/109] jd_price1.js --- jd_price1.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jd_price1.js b/jd_price1.js index b59788d6..65704c5e 100644 --- a/jd_price1.js +++ b/jd_price1.js @@ -17,7 +17,7 @@ const path1 = '/product/graphext/'; const path2 = '/baoliao/center/menu' const manmanbuy_key = 'manmanbuy_val'; const url = $request.url; -const $ = new Env("京东比价"); +const $ = new Env("京东助手"); // 获取模块传入参数 const args = typeof $argument !== "undefined" ? $argument : ""; $.log(`读取参数: ${args}`); From a2ad606a7f58ed80d8b30ed592a1b8ba5f1fcf4a Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 22 Apr 2025 19:04:48 +0800 Subject: [PATCH 039/109] JD_Helper.sgmodule --- Surge/JD_Helper.sgmodule | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Surge/JD_Helper.sgmodule b/Surge/JD_Helper.sgmodule index ae972422..c6ad7021 100644 --- a/Surge/JD_Helper.sgmodule +++ b/Surge/JD_Helper.sgmodule @@ -1,7 +1,7 @@ #!name=京东助手 #!desc=京东助手 点击详情页面触发佣金返利和历史价格 #!arguments=JD_UNION_ID:null,JD_POSITION_ID:null,JTT_APPID:null,JTT_APPKEY:null,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT:慢慢买CK,DISABLE_NOTICE:true -#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:默认超时(默认值)\n └ 可自定义\nMMMCK_SCRIPT: 慢慢买 CK 脚本启停\n ├ 慢慢买CK:启用(默认值)\n └ 填入"#":注释停用\nDISABLE_NOTICE: 是否启用转链及通知功能\n ├ true:启用转链与通知功能(默认)\n └ false:禁用转链与通知,仅显示比价图表 +#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:脚本超时(默认值)\n └ 可自定义\nMMMCK_SCRIPT: 慢慢买 CK 脚本启停\n ├ 慢慢买CK:启用(默认值)\n └ 填入"#":获取后注释停用\nDISABLE_NOTICE: 是否启用转链及通知功能\n ├ true:启用转链与通知功能(默认)\n └ false:禁用转链与通知,仅显示比价图表 [Script] 京东助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price1.js,argument=jd_union_id={{{JD_UNION_ID}}}&jd_position_id={{{JD_POSITION_ID}}}&jtt_appid={{{JTT_APPID}}}&jtt_appkey={{{JTT_APPKEY}}}&engine={{{ENGINE}}}&timeout={{{TIMEOUT}}}&disable_notice={{{DISABLE_NOTICE}}} From a50f4fd31cee70ea0b07c5da76ee7586d9efefcc Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Tue, 22 Apr 2025 20:38:12 +0800 Subject: [PATCH 040/109] =?UTF-8?q?jd=5Fprice1.js=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=8F=82=E6=95=B0=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E6=98=8E=E4=BA=AE=E3=80=81=E6=9A=97=E9=BB=91=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Surge/JD_Helper.sgmodule | 6 +++--- jd_price1.js | 13 ++++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Surge/JD_Helper.sgmodule b/Surge/JD_Helper.sgmodule index c6ad7021..3b659e69 100644 --- a/Surge/JD_Helper.sgmodule +++ b/Surge/JD_Helper.sgmodule @@ -1,10 +1,10 @@ #!name=京东助手 #!desc=京东助手 点击详情页面触发佣金返利和历史价格 -#!arguments=JD_UNION_ID:null,JD_POSITION_ID:null,JTT_APPID:null,JTT_APPKEY:null,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT:慢慢买CK,DISABLE_NOTICE:true -#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:脚本超时(默认值)\n └ 可自定义\nMMMCK_SCRIPT: 慢慢买 CK 脚本启停\n ├ 慢慢买CK:启用(默认值)\n └ 填入"#":获取后注释停用\nDISABLE_NOTICE: 是否启用转链及通知功能\n ├ true:启用转链与通知功能(默认)\n └ false:禁用转链与通知,仅显示比价图表 +#!arguments=JD_UNION_ID:null,JD_POSITION_ID:null,JTT_APPID:null,JTT_APPKEY:null,ENGINE:auto,TIMEOUT:120,MMMCK_SCRIPT:慢慢买CK,DISABLE_NOTICE:true,THEME_TIME:7-19 +#!arguments-desc=[参数设置]\nJD_UNION_ID: 填写京东联盟ID\n ├ 获取方式:登录京东联盟官网https://union.jd.com/index\n └ 参考格式:12345678\nJD_POSITION_ID: 填写推广位ID\n ├ 获取方式:在京东联盟后台创建推广位\n └ 参考格式:1234567890\nJTT_APPID: 填写京推推AppID\n ├ 获取方式:登录京推推官网https://www.jingtuitui.com/user/login\n └ 参考格式:1234567890123456\nJTT_APPKEY: 填写京推推AppKey\n ├ 获取方式:登录京推推官网\n └ 参考格式:b123456ce90123456lk890126789012\nENGINE: 脚本执行引擎\n ├ auto:自动选择(默认值)\n ├ jsc:JavaScriptCore 引擎\n └ webview:WebView 引擎\nTIMEOUT: 脚本超时(单位:秒)\n ├ 120:脚本超时(默认值)\n └ 可自定义\nMMMCK_SCRIPT: 慢慢买 CK 脚本启停\n ├ 慢慢买CK:启用(默认值)\n └ 填入"#":获取后注释停用\nDISABLE_NOTICE: 是否启用转链及通知功能\n ├ true:启用转链与通知功能(默认)\n └ false:禁用转链与通知,仅显示比价图表\nTHEME_TIME: 自定义暗黑模式时间范围\n ├ 格式:起始小时-结束小时(默认 7~19为明亮模式)\n └ 示例:6-22 表示每天 22:00~6:00 为暗黑模式时间段 [Script] -京东助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price1.js,argument=jd_union_id={{{JD_UNION_ID}}}&jd_position_id={{{JD_POSITION_ID}}}&jtt_appid={{{JTT_APPID}}}&jtt_appkey={{{JTT_APPKEY}}}&engine={{{ENGINE}}}&timeout={{{TIMEOUT}}}&disable_notice={{{DISABLE_NOTICE}}} +京东助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price1.js,argument=jd_union_id={{{JD_UNION_ID}}}&jd_position_id={{{JD_POSITION_ID}}}&jtt_appid={{{JTT_APPID}}}&jtt_appkey={{{JTT_APPKEY}}}&engine={{{ENGINE}}}&timeout={{{TIMEOUT}}}&disable_notice={{{DISABLE_NOTICE}}}&theme_time={{{THEME_TIME}}} {{{MMMCK_SCRIPT}}} = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_price1.js diff --git a/jd_price1.js b/jd_price1.js index 65704c5e..13c40cd5 100644 --- a/jd_price1.js +++ b/jd_price1.js @@ -1,10 +1,10 @@ /* -# 2025-04-22 16:40 +# 2025-04-22 20:37 # 京东购物助手,京推推转链+比价图表 # 更新内容: -# 比价脚本原作者@苍井灰灰,在基础上增加京推推商品返利转链(点通知)+比价折线图表格显示,适配暗黑与明亮模式(早7点、晚19点自动切换) +# 比价脚本原作者@苍井灰灰,在基础上增加京推推商品返利转链(点通知)+比价折线图表格显示,适配暗黑与明亮模式(自定义切换) # Surge模块设置参数,或自己折腾Boxjs配置京推推参数 @@ -32,6 +32,10 @@ $.jd_positionId = !isEmpty(argObj["jd_position_id"]) ? argObj["jd_position_id"] $.jtt_appid = !isEmpty(argObj["jtt_appid"]) ? argObj["jtt_appid"] : $.getdata("jtt_appid") || ""; $.jtt_appkey = !isEmpty(argObj["jtt_appkey"]) ? argObj["jtt_appkey"] : $.getdata("jtt_appkey") || ""; $.disableNotice = argObj["disable_notice"] === "false" ? false : true; +const defaultThemeTime = "7-19"; +$.themeTime = !isEmpty(argObj["theme_time"]) + ? argObj["theme_time"] + : $.getdata("theme_time") || defaultThemeTime; if (url.includes(path2)) { const reqbody = $request.body; @@ -287,8 +291,11 @@ body, table { + + +
+
+

价格走势

+
+
+
+ + `; +}; + + + +const getMMdata = (id) => { + const getmmCK = () => { + const ck = $prs.get("慢慢买CK"); + if (ck) return ck; + throw new Error("未获取 ck,请先打开【慢慢买】APP→我的,获取 ck"); + }; + + const reqOpts = ({ url, buildBody, ...op }) => { + const opt = { + method: "post", + url, + headers: { + "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", + "User-Agent": + "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios", + }, + ...op, + }; + const cb = (args) => { + const reqBody = { + t: Date.now().toString(), + c_appver: "4.8.3.1", + c_mmbDevId: getmmCK(), + ...args, }; + reqBody.token = md5( + encodeURIComponent( + "3E41D1331F5DDAFCD0A38FE2D52FF66F" + + jsonToCustomString(reqBody) + + "3E41D1331F5DDAFCD0A38FE2D52FF66F" + ) + ).toUpperCase(); + return jsonToQueryString(reqBody); + }; + return { ...opt, body: buildBody(cb) }; + }; - return $http(reqTrendData); - }) - .then((res) => res.json()); + const apiCall = (url, buildBody) => + $http(reqOpts({ url, buildBody })) + .then((resp) => { + const body = resp.json(); + if (!url.endsWith("trendData") && body.code !== 2000) throw new Error(`${url}:${body.msg}`); + return body; + }); + + return apiCall( + "https://apapia-common.manmanbuy.com/SiteCommand/parse", + (set) => + set({ + methodName: "commonMethod", + searchKey: `https://item.jd.com/${id}.html`, + }) + ) + .then(({ result: { stteId, link } }) => + apiCall( + "https://apapia-history-weblogic.manmanbuy.com/basic/v2/getItemBasicInfo", + (set) => + set({ + methodName: "getHistoryInfoJava", + searchKey: link, + stteId, + }) + ) + ) + .then(({ result: { spbh, url } }) => + apiCall( + "https://apapia-history-weblogic.manmanbuy.com/app/share", + (set) => + set({ + methodName: "trendJava", + spbh, + url, + }) + ) + ) + .then(({ data }) => + apiCall( + "https://apapia-history-weblogic.manmanbuy.com/h5/share/trendData", + () => data.split("?")[1] + ) + ) }; const Render = { @@ -413,10 +655,18 @@ const main = async () => { Render.inject(`

${msg}

`).done(); return; } - - Render.inject(Table(result)).done(); + + const hour = new Date().getHours(); + const isDark = hour >= 20 || hour < 6; + + Render + .inject(Table(result)) + .inject(JdLine(result)) + .inject(``) + .done(); } catch (e) { $log(e); + $msg(e); $done({}); } }; @@ -424,11 +674,119 @@ const main = async () => { main(); + + +function init(){CryptoJS=function(t,r){var n;if("undefined"!=typeof window&&window.crypto&&(n=window.crypto),"undefined"!=typeof self&&self.crypto&&(n=self.crypto),"undefined"!=typeof globalThis&&globalThis.crypto&&(n=globalThis.crypto),!n&&"undefined"!=typeof window&&window.msCrypto&&(n=window.msCrypto),!n&&"undefined"!=typeof global&&global.crypto&&(n=global.crypto),!n&&"function"==typeof require)try{n=require("crypto")}catch(t){}var e=function(){if(n){if("function"==typeof n.getRandomValues)try{return n.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof n.randomBytes)try{return n.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")},i=Object.create||function(){function t(){}return function(r){var n;return t.prototype=r,n=new t,t.prototype=null,n}}(),o={},a=o.lib={},s=a.Base={extend:function(t){var r=i(this);return t&&r.mixIn(t),r.hasOwnProperty("init")&&this.init!==r.init||(r.init=function(){r.$super.init.apply(this,arguments)}),r.init.prototype=r,r.$super=this,r},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var r in t)t.hasOwnProperty(r)&&(this[r]=t[r]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},c=a.WordArray=s.extend({init:function(t,r){t=this.words=t||[],this.sigBytes=null!=r?r:4*t.length},toString:function(t){return(t||f).stringify(this)},concat:function(t){var r=this.words,n=t.words,e=this.sigBytes,i=t.sigBytes;if(this.clamp(),e%4)for(var o=0;o>>2]>>>24-o%4*8&255;r[e+o>>>2]|=a<<24-(e+o)%4*8}else for(var s=0;s>>2]=n[s>>>2];return this.sigBytes+=i,this},clamp:function(){var r=this.words,n=this.sigBytes;r[n>>>2]&=4294967295<<32-n%4*8,r.length=t.ceil(n/4)},clone:function(){var t=s.clone.call(this);return t.words=this.words.slice(0),t},random:function(r){var n,i=[],o=function(r){r=r;var n=987654321,e=4294967295;return function(){var i=((n=36969*(65535&n)+(n>>16)&e)<<16)+(r=18e3*(65535&r)+(r>>16)&e)&e;return i/=4294967296,(i+=.5)*(t.random()>.5?1:-1)}},a=!1;try{e(),a=!0}catch(t){}for(var s,u=0;u>>2]>>>24-i%4*8&255;e.push((o>>>4).toString(16)),e.push((15&o).toString(16))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>3]|=parseInt(t.substr(e,2),16)<<24-e%8*4;return new c.init(n,r/2)}},h=u.Latin1={stringify:function(t){for(var r=t.words,n=t.sigBytes,e=[],i=0;i>>2]>>>24-i%4*8&255;e.push(String.fromCharCode(o))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>2]|=(255&t.charCodeAt(e))<<24-e%4*8;return new c.init(n,r)}},p=u.Utf8={stringify:function(t){try{return decodeURIComponent(escape(h.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return h.parse(unescape(encodeURIComponent(t)))}},d=a.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new c.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=p.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(r){var n,e=this._data,i=e.words,o=e.sigBytes,a=this.blockSize,s=o/(4*a),u=(s=r?t.ceil(s):t.max((0|s)-this._minBufferSize,0))*a,f=t.min(4*u,o);if(u){for(var h=0;h>>24)|4278255360&(i<<24|i>>>8)}var o=this._hash.words,s=t[r+0],p=t[r+1],d=t[r+2],l=t[r+3],y=t[r+4],v=t[r+5],g=t[r+6],w=t[r+7],_=t[r+8],m=t[r+9],B=t[r+10],b=t[r+11],C=t[r+12],S=t[r+13],x=t[r+14],A=t[r+15],H=o[0],z=o[1],M=o[2],D=o[3];z=h(z=h(z=h(z=h(z=f(z=f(z=f(z=f(z=u(z=u(z=u(z=u(z=c(z=c(z=c(z=c(z,M=c(M,D=c(D,H=c(H,z,M,D,s,7,a[0]),z,M,p,12,a[1]),H,z,d,17,a[2]),D,H,l,22,a[3]),M=c(M,D=c(D,H=c(H,z,M,D,y,7,a[4]),z,M,v,12,a[5]),H,z,g,17,a[6]),D,H,w,22,a[7]),M=c(M,D=c(D,H=c(H,z,M,D,_,7,a[8]),z,M,m,12,a[9]),H,z,B,17,a[10]),D,H,b,22,a[11]),M=c(M,D=c(D,H=c(H,z,M,D,C,7,a[12]),z,M,S,12,a[13]),H,z,x,17,a[14]),D,H,A,22,a[15]),M=u(M,D=u(D,H=u(H,z,M,D,p,5,a[16]),z,M,g,9,a[17]),H,z,b,14,a[18]),D,H,s,20,a[19]),M=u(M,D=u(D,H=u(H,z,M,D,v,5,a[20]),z,M,B,9,a[21]),H,z,A,14,a[22]),D,H,y,20,a[23]),M=u(M,D=u(D,H=u(H,z,M,D,m,5,a[24]),z,M,x,9,a[25]),H,z,l,14,a[26]),D,H,_,20,a[27]),M=u(M,D=u(D,H=u(H,z,M,D,S,5,a[28]),z,M,d,9,a[29]),H,z,w,14,a[30]),D,H,C,20,a[31]),M=f(M,D=f(D,H=f(H,z,M,D,v,4,a[32]),z,M,_,11,a[33]),H,z,b,16,a[34]),D,H,x,23,a[35]),M=f(M,D=f(D,H=f(H,z,M,D,p,4,a[36]),z,M,y,11,a[37]),H,z,w,16,a[38]),D,H,B,23,a[39]),M=f(M,D=f(D,H=f(H,z,M,D,S,4,a[40]),z,M,s,11,a[41]),H,z,l,16,a[42]),D,H,g,23,a[43]),M=f(M,D=f(D,H=f(H,z,M,D,m,4,a[44]),z,M,C,11,a[45]),H,z,A,16,a[46]),D,H,d,23,a[47]),M=h(M,D=h(D,H=h(H,z,M,D,s,6,a[48]),z,M,w,10,a[49]),H,z,x,15,a[50]),D,H,v,21,a[51]),M=h(M,D=h(D,H=h(H,z,M,D,C,6,a[52]),z,M,l,10,a[53]),H,z,B,15,a[54]),D,H,p,21,a[55]),M=h(M,D=h(D,H=h(H,z,M,D,_,6,a[56]),z,M,A,10,a[57]),H,z,g,15,a[58]),D,H,S,21,a[59]),M=h(M,D=h(D,H=h(H,z,M,D,y,6,a[60]),z,M,b,10,a[61]),H,z,d,15,a[62]),D,H,m,21,a[63]),o[0]=o[0]+H|0,o[1]=o[1]+z|0,o[2]=o[2]+M|0,o[3]=o[3]+D|0},_doFinalize:function(){var r=this._data,n=r.words,e=8*this._nDataBytes,i=8*r.sigBytes;n[i>>>5]|=128<<24-i%32;var o=t.floor(e/4294967296),a=e;n[15+(i+64>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),n[14+(i+64>>>9<<4)]=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),r.sigBytes=4*(n.length+1),this._process();for(var s=this._hash,c=s.words,u=0;u<4;u++){var f=c[u];c[u]=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8)}return s},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});function c(t,r,n,e,i,o,a){var s=t+(r&n|~r&e)+i+a;return(s<>>32-o)+r}function u(t,r,n,e,i,o,a){var s=t+(r&e|n&~e)+i+a;return(s<>>32-o)+r}function f(t,r,n,e,i,o,a){var s=t+(r^n^e)+i+a;return(s<>>32-o)+r}function h(t,r,n,e,i,o,a){var s=t+(n^(r|~e))+i+a;return(s<>>32-o)+r}r.MD5=i._createHelper(s),r.HmacMD5=i._createHmacHelper(s)}(Math),function(){var t=CryptoJS,r=t.lib.WordArray;t.enc.Base64={stringify:function(t){var r=t.words,n=t.sigBytes,e=this._map;t.clamp();for(var i=[],o=0;o>>2]>>>24-o%4*8&255)<<16|(r[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|r[o+2>>>2]>>>24-(o+2)%4*8&255,s=0;s<4&&o+.75*s>>6*(3-s)&63));var c=e.charAt(64);if(c)for(;i.length%4;)i.push(c);return i.join("")},parse:function(t){var n=t.length,e=this._map,i=this._reverseMap;if(!i){i=this._reverseMap=[];for(var o=0;o>>6-a%4*2;i[o>>>2]|=(s|c)<<24-o%4*8,o++}return r.create(i,o)}(t,n,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}(); + +function md5(word){return CryptoJS.MD5(word).toString();} + function jsonToQueryString(jsonObject) {return Object.keys(jsonObject).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(jsonObject[key])}`).join('&');} function jsonToCustomString(jsonObject){return Object.keys(jsonObject).filter(key=>jsonObject[key]!==''&&key.toLowerCase()!=='token').sort().map(key=>`${key.toUpperCase()}${jsonObject[key].toUpperCase()}`).join('');} + Promise.withResolvers ||= function () { + let resolve, reject; + const promise = new this((res, rej) => { + resolve = res; + reject = rej; + }); + return { promise, resolve, reject }; + }; + + const $http = (op, t = 4) => { + const { promise, resolve, reject } = Promise.withResolvers(); + const HTTPError = (e, req, res) => + Object.assign(new Error(e), { + name: "HTTPError", + request: req, + response: res, + }); + + const handleRes = ({ bodyBytes, ...res }) => { + res.status ??= res.statusCode; + res.json = () => JSON.parse(res.body); + if (res.headers?.["binary-mode"] && bodyBytes) + res.body = new Uint8Array(bodyBytes); + + res.error || res.status < 200 || res.status > 307 + ? reject(HTTPError(res.error, op, res)) + : resolve(res); + }; + + const timer = setTimeout( + () => reject(HTTPError("timeout", op)), + op.$timeout ?? t * 1000 + ); + this.$httpClient?.[op.method || "get"](op, (error, resp, body) => { + handleRes({ error, ...resp, body }); + }); + this.$task?.fetch({ url: op, ...op }).then(handleRes, handleRes); + + return promise.finally(() => clearTimeout(timer)); + }; -function intCryptoJS(){CryptoJS=function(t,r){var n;if("undefined"!=typeof window&&window.crypto&&(n=window.crypto),"undefined"!=typeof self&&self.crypto&&(n=self.crypto),"undefined"!=typeof globalThis&&globalThis.crypto&&(n=globalThis.crypto),!n&&"undefined"!=typeof window&&window.msCrypto&&(n=window.msCrypto),!n&&"undefined"!=typeof global&&global.crypto&&(n=global.crypto),!n&&"function"==typeof require)try{n=require("crypto")}catch(t){}var e=function(){if(n){if("function"==typeof n.getRandomValues)try{return n.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof n.randomBytes)try{return n.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")},i=Object.create||function(){function t(){}return function(r){var n;return t.prototype=r,n=new t,t.prototype=null,n}}(),o={},a=o.lib={},s=a.Base={extend:function(t){var r=i(this);return t&&r.mixIn(t),r.hasOwnProperty("init")&&this.init!==r.init||(r.init=function(){r.$super.init.apply(this,arguments)}),r.init.prototype=r,r.$super=this,r},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var r in t)t.hasOwnProperty(r)&&(this[r]=t[r]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},c=a.WordArray=s.extend({init:function(t,r){t=this.words=t||[],this.sigBytes=null!=r?r:4*t.length},toString:function(t){return(t||f).stringify(this)},concat:function(t){var r=this.words,n=t.words,e=this.sigBytes,i=t.sigBytes;if(this.clamp(),e%4)for(var o=0;o>>2]>>>24-o%4*8&255;r[e+o>>>2]|=a<<24-(e+o)%4*8}else for(var s=0;s>>2]=n[s>>>2];return this.sigBytes+=i,this},clamp:function(){var r=this.words,n=this.sigBytes;r[n>>>2]&=4294967295<<32-n%4*8,r.length=t.ceil(n/4)},clone:function(){var t=s.clone.call(this);return t.words=this.words.slice(0),t},random:function(r){var n,i=[],o=function(r){r=r;var n=987654321,e=4294967295;return function(){var i=((n=36969*(65535&n)+(n>>16)&e)<<16)+(r=18e3*(65535&r)+(r>>16)&e)&e;return i/=4294967296,(i+=.5)*(t.random()>.5?1:-1)}},a=!1;try{e(),a=!0}catch(t){}for(var s,u=0;u>>2]>>>24-i%4*8&255;e.push((o>>>4).toString(16)),e.push((15&o).toString(16))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>3]|=parseInt(t.substr(e,2),16)<<24-e%8*4;return new c.init(n,r/2)}},h=u.Latin1={stringify:function(t){for(var r=t.words,n=t.sigBytes,e=[],i=0;i>>2]>>>24-i%4*8&255;e.push(String.fromCharCode(o))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>2]|=(255&t.charCodeAt(e))<<24-e%4*8;return new c.init(n,r)}},p=u.Utf8={stringify:function(t){try{return decodeURIComponent(escape(h.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return h.parse(unescape(encodeURIComponent(t)))}},d=a.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new c.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=p.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(r){var n,e=this._data,i=e.words,o=e.sigBytes,a=this.blockSize,s=o/(4*a),u=(s=r?t.ceil(s):t.max((0|s)-this._minBufferSize,0))*a,f=t.min(4*u,o);if(u){for(var h=0;h>>24)|4278255360&(i<<24|i>>>8)}var o=this._hash.words,s=t[r+0],p=t[r+1],d=t[r+2],l=t[r+3],y=t[r+4],v=t[r+5],g=t[r+6],w=t[r+7],_=t[r+8],m=t[r+9],B=t[r+10],b=t[r+11],C=t[r+12],S=t[r+13],x=t[r+14],A=t[r+15],H=o[0],z=o[1],M=o[2],D=o[3];z=h(z=h(z=h(z=h(z=f(z=f(z=f(z=f(z=u(z=u(z=u(z=u(z=c(z=c(z=c(z=c(z,M=c(M,D=c(D,H=c(H,z,M,D,s,7,a[0]),z,M,p,12,a[1]),H,z,d,17,a[2]),D,H,l,22,a[3]),M=c(M,D=c(D,H=c(H,z,M,D,y,7,a[4]),z,M,v,12,a[5]),H,z,g,17,a[6]),D,H,w,22,a[7]),M=c(M,D=c(D,H=c(H,z,M,D,_,7,a[8]),z,M,m,12,a[9]),H,z,B,17,a[10]),D,H,b,22,a[11]),M=c(M,D=c(D,H=c(H,z,M,D,C,7,a[12]),z,M,S,12,a[13]),H,z,x,17,a[14]),D,H,A,22,a[15]),M=u(M,D=u(D,H=u(H,z,M,D,p,5,a[16]),z,M,g,9,a[17]),H,z,b,14,a[18]),D,H,s,20,a[19]),M=u(M,D=u(D,H=u(H,z,M,D,v,5,a[20]),z,M,B,9,a[21]),H,z,A,14,a[22]),D,H,y,20,a[23]),M=u(M,D=u(D,H=u(H,z,M,D,m,5,a[24]),z,M,x,9,a[25]),H,z,l,14,a[26]),D,H,_,20,a[27]),M=u(M,D=u(D,H=u(H,z,M,D,S,5,a[28]),z,M,d,9,a[29]),H,z,w,14,a[30]),D,H,C,20,a[31]),M=f(M,D=f(D,H=f(H,z,M,D,v,4,a[32]),z,M,_,11,a[33]),H,z,b,16,a[34]),D,H,x,23,a[35]),M=f(M,D=f(D,H=f(H,z,M,D,p,4,a[36]),z,M,y,11,a[37]),H,z,w,16,a[38]),D,H,B,23,a[39]),M=f(M,D=f(D,H=f(H,z,M,D,S,4,a[40]),z,M,s,11,a[41]),H,z,l,16,a[42]),D,H,g,23,a[43]),M=f(M,D=f(D,H=f(H,z,M,D,m,4,a[44]),z,M,C,11,a[45]),H,z,A,16,a[46]),D,H,d,23,a[47]),M=h(M,D=h(D,H=h(H,z,M,D,s,6,a[48]),z,M,w,10,a[49]),H,z,x,15,a[50]),D,H,v,21,a[51]),M=h(M,D=h(D,H=h(H,z,M,D,C,6,a[52]),z,M,l,10,a[53]),H,z,B,15,a[54]),D,H,p,21,a[55]),M=h(M,D=h(D,H=h(H,z,M,D,_,6,a[56]),z,M,A,10,a[57]),H,z,g,15,a[58]),D,H,S,21,a[59]),M=h(M,D=h(D,H=h(H,z,M,D,y,6,a[60]),z,M,b,10,a[61]),H,z,d,15,a[62]),D,H,m,21,a[63]),o[0]=o[0]+H|0,o[1]=o[1]+z|0,o[2]=o[2]+M|0,o[3]=o[3]+D|0},_doFinalize:function(){var r=this._data,n=r.words,e=8*this._nDataBytes,i=8*r.sigBytes;n[i>>>5]|=128<<24-i%32;var o=t.floor(e/4294967296),a=e;n[15+(i+64>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),n[14+(i+64>>>9<<4)]=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),r.sigBytes=4*(n.length+1),this._process();for(var s=this._hash,c=s.words,u=0;u<4;u++){var f=c[u];c[u]=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8)}return s},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});function c(t,r,n,e,i,o,a){var s=t+(r&n|~r&e)+i+a;return(s<>>32-o)+r}function u(t,r,n,e,i,o,a){var s=t+(r&e|n&~e)+i+a;return(s<>>32-o)+r}function f(t,r,n,e,i,o,a){var s=t+(r^n^e)+i+a;return(s<>>32-o)+r}function h(t,r,n,e,i,o,a){var s=t+(n^(r|~e))+i+a;return(s<>>32-o)+r}r.MD5=i._createHelper(s),r.HmacMD5=i._createHmacHelper(s)}(Math),function(){var t=CryptoJS,r=t.lib.WordArray;t.enc.Base64={stringify:function(t){var r=t.words,n=t.sigBytes,e=this._map;t.clamp();for(var i=[],o=0;o>>2]>>>24-o%4*8&255)<<16|(r[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|r[o+2>>>2]>>>24-(o+2)%4*8&255,s=0;s<4&&o+.75*s>>6*(3-s)&63));var c=e.charAt(64);if(c)for(;i.length%4;)i.push(c);return i.join("")},parse:function(t){var n=t.length,e=this._map,i=this._reverseMap;if(!i){i=this._reverseMap=[];for(var o=0;o>>6-a%4*2;i[o>>>2]|=(s|c)<<24-o%4*8,o++}return r.create(i,o)}(t,n,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}();}; -function md5(word){return CryptoJS.MD5(word).toString();} \ No newline at end of file + const $prs = { + get: this.$prefs?.valueForKey ?? $persistentStore.read, + getJson: (key) => JSON.parse($prs.get(key), null, 4), + set: (key, value) => + (this.$prefs?.setValueForKey ?? $persistentStore.write)(value, key), + setJson: (key, obj) => $prs.set(key, JSON.stringify(obj)), + }; + + const $msg = (...a) => { + const { $open, $copy, $media, ...r } = + typeof a.at(-1) === "object" && a.pop(); + const [t = "", s = "", b = ""] = a; + (this.$notify ??= $notification.post)(t, s, b, { + action: $copy ? "clipboard" : "open-url", + text: $copy, + "update-pasteboard": $copy, + clipboard: $copy, + "open-url": $open, + openUrl: $open, + url: $open, + mediaUrl: $media, + "media-url": $media, + ...r, + }); + }; + + const $log = new Proxy( + (...args) => + args.forEach((i) => + console.log( + i?.stack + ? `${i.toString()}\n${i.stack}` + : typeof i === "object" + ? JSON.stringify(i, null, 4) + : String(i) + ) + ), + { + get(target) { + if (!target.init) { + target.time = (id) => (target.time[id] = Date.now()); + target.timeEnd = (id) => target(Date.now() - target.time[id]); + target.show = + (...a) => + (b) => + b && target(...a); + target.init = true; + } + + return Reflect.get(...arguments); + }, + } + ); + + return { + $log, + $msg, + $prs, + $http, + md5, + jsonToCustomString, + jsonToQueryString, + }; +}; From 39a941c5e9a60d9638466e0065fd866622000174 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Wed, 23 Apr 2025 20:13:07 +0800 Subject: [PATCH 043/109] =?UTF-8?q?jd=5Fprice.js=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jd_price.js | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/jd_price.js b/jd_price.js index 08641bef..cc54c400 100644 --- a/jd_price.js +++ b/jd_price.js @@ -223,8 +223,6 @@ const Table = (result) => { const JdLine = (data) => { return ` - - +
+ ${buttons.map(item => ``).join("\n")} +
+ + `; + + html = html.replace(/<\/html>/, hookContent); + $.log("注入html完成"); + $.done({ body: html }); +} + + +function jsonToQueryString(jsonObject) {return Object.keys(jsonObject).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(jsonObject[key])}`).join('&');} + + +function jsonToCustomString(jsonObject){return Object.keys(jsonObject).filter(key=>jsonObject[key]!==''&&key.toLowerCase()!=='token').sort().map(key=>`${key.toUpperCase()}${jsonObject[key].toUpperCase()}`).join('');} + + +function intCryptoJS(){CryptoJS=function(t,r){var n;if("undefined"!=typeof window&&window.crypto&&(n=window.crypto),"undefined"!=typeof self&&self.crypto&&(n=self.crypto),"undefined"!=typeof globalThis&&globalThis.crypto&&(n=globalThis.crypto),!n&&"undefined"!=typeof window&&window.msCrypto&&(n=window.msCrypto),!n&&"undefined"!=typeof global&&global.crypto&&(n=global.crypto),!n&&"function"==typeof require)try{n=require("crypto")}catch(t){}var e=function(){if(n){if("function"==typeof n.getRandomValues)try{return n.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof n.randomBytes)try{return n.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")},i=Object.create||function(){function t(){}return function(r){var n;return t.prototype=r,n=new t,t.prototype=null,n}}(),o={},a=o.lib={},s=a.Base={extend:function(t){var r=i(this);return t&&r.mixIn(t),r.hasOwnProperty("init")&&this.init!==r.init||(r.init=function(){r.$super.init.apply(this,arguments)}),r.init.prototype=r,r.$super=this,r},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var r in t)t.hasOwnProperty(r)&&(this[r]=t[r]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},c=a.WordArray=s.extend({init:function(t,r){t=this.words=t||[],this.sigBytes=null!=r?r:4*t.length},toString:function(t){return(t||f).stringify(this)},concat:function(t){var r=this.words,n=t.words,e=this.sigBytes,i=t.sigBytes;if(this.clamp(),e%4)for(var o=0;o>>2]>>>24-o%4*8&255;r[e+o>>>2]|=a<<24-(e+o)%4*8}else for(var s=0;s>>2]=n[s>>>2];return this.sigBytes+=i,this},clamp:function(){var r=this.words,n=this.sigBytes;r[n>>>2]&=4294967295<<32-n%4*8,r.length=t.ceil(n/4)},clone:function(){var t=s.clone.call(this);return t.words=this.words.slice(0),t},random:function(r){var n,i=[],o=function(r){r=r;var n=987654321,e=4294967295;return function(){var i=((n=36969*(65535&n)+(n>>16)&e)<<16)+(r=18e3*(65535&r)+(r>>16)&e)&e;return i/=4294967296,(i+=.5)*(t.random()>.5?1:-1)}},a=!1;try{e(),a=!0}catch(t){}for(var s,u=0;u>>2]>>>24-i%4*8&255;e.push((o>>>4).toString(16)),e.push((15&o).toString(16))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>3]|=parseInt(t.substr(e,2),16)<<24-e%8*4;return new c.init(n,r/2)}},h=u.Latin1={stringify:function(t){for(var r=t.words,n=t.sigBytes,e=[],i=0;i>>2]>>>24-i%4*8&255;e.push(String.fromCharCode(o))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>2]|=(255&t.charCodeAt(e))<<24-e%4*8;return new c.init(n,r)}},p=u.Utf8={stringify:function(t){try{return decodeURIComponent(escape(h.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return h.parse(unescape(encodeURIComponent(t)))}},d=a.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new c.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=p.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(r){var n,e=this._data,i=e.words,o=e.sigBytes,a=this.blockSize,s=o/(4*a),u=(s=r?t.ceil(s):t.max((0|s)-this._minBufferSize,0))*a,f=t.min(4*u,o);if(u){for(var h=0;h>>24)|4278255360&(i<<24|i>>>8)}var o=this._hash.words,s=t[r+0],p=t[r+1],d=t[r+2],l=t[r+3],y=t[r+4],v=t[r+5],g=t[r+6],w=t[r+7],_=t[r+8],m=t[r+9],B=t[r+10],b=t[r+11],C=t[r+12],S=t[r+13],x=t[r+14],A=t[r+15],H=o[0],z=o[1],M=o[2],D=o[3];z=h(z=h(z=h(z=h(z=f(z=f(z=f(z=f(z=u(z=u(z=u(z=u(z=c(z=c(z=c(z=c(z,M=c(M,D=c(D,H=c(H,z,M,D,s,7,a[0]),z,M,p,12,a[1]),H,z,d,17,a[2]),D,H,l,22,a[3]),M=c(M,D=c(D,H=c(H,z,M,D,y,7,a[4]),z,M,v,12,a[5]),H,z,g,17,a[6]),D,H,w,22,a[7]),M=c(M,D=c(D,H=c(H,z,M,D,_,7,a[8]),z,M,m,12,a[9]),H,z,B,17,a[10]),D,H,b,22,a[11]),M=c(M,D=c(D,H=c(H,z,M,D,C,7,a[12]),z,M,S,12,a[13]),H,z,x,17,a[14]),D,H,A,22,a[15]),M=u(M,D=u(D,H=u(H,z,M,D,p,5,a[16]),z,M,g,9,a[17]),H,z,b,14,a[18]),D,H,s,20,a[19]),M=u(M,D=u(D,H=u(H,z,M,D,v,5,a[20]),z,M,B,9,a[21]),H,z,A,14,a[22]),D,H,y,20,a[23]),M=u(M,D=u(D,H=u(H,z,M,D,m,5,a[24]),z,M,x,9,a[25]),H,z,l,14,a[26]),D,H,_,20,a[27]),M=u(M,D=u(D,H=u(H,z,M,D,S,5,a[28]),z,M,d,9,a[29]),H,z,w,14,a[30]),D,H,C,20,a[31]),M=f(M,D=f(D,H=f(H,z,M,D,v,4,a[32]),z,M,_,11,a[33]),H,z,b,16,a[34]),D,H,x,23,a[35]),M=f(M,D=f(D,H=f(H,z,M,D,p,4,a[36]),z,M,y,11,a[37]),H,z,w,16,a[38]),D,H,B,23,a[39]),M=f(M,D=f(D,H=f(H,z,M,D,S,4,a[40]),z,M,s,11,a[41]),H,z,l,16,a[42]),D,H,g,23,a[43]),M=f(M,D=f(D,H=f(H,z,M,D,m,4,a[44]),z,M,C,11,a[45]),H,z,A,16,a[46]),D,H,d,23,a[47]),M=h(M,D=h(D,H=h(H,z,M,D,s,6,a[48]),z,M,w,10,a[49]),H,z,x,15,a[50]),D,H,v,21,a[51]),M=h(M,D=h(D,H=h(H,z,M,D,C,6,a[52]),z,M,l,10,a[53]),H,z,B,15,a[54]),D,H,p,21,a[55]),M=h(M,D=h(D,H=h(H,z,M,D,_,6,a[56]),z,M,A,10,a[57]),H,z,g,15,a[58]),D,H,S,21,a[59]),M=h(M,D=h(D,H=h(H,z,M,D,y,6,a[60]),z,M,b,10,a[61]),H,z,d,15,a[62]),D,H,m,21,a[63]),o[0]=o[0]+H|0,o[1]=o[1]+z|0,o[2]=o[2]+M|0,o[3]=o[3]+D|0},_doFinalize:function(){var r=this._data,n=r.words,e=8*this._nDataBytes,i=8*r.sigBytes;n[i>>>5]|=128<<24-i%32;var o=t.floor(e/4294967296),a=e;n[15+(i+64>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),n[14+(i+64>>>9<<4)]=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),r.sigBytes=4*(n.length+1),this._process();for(var s=this._hash,c=s.words,u=0;u<4;u++){var f=c[u];c[u]=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8)}return s},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});function c(t,r,n,e,i,o,a){var s=t+(r&n|~r&e)+i+a;return(s<>>32-o)+r}function u(t,r,n,e,i,o,a){var s=t+(r&e|n&~e)+i+a;return(s<>>32-o)+r}function f(t,r,n,e,i,o,a){var s=t+(r^n^e)+i+a;return(s<>>32-o)+r}function h(t,r,n,e,i,o,a){var s=t+(n^(r|~e))+i+a;return(s<>>32-o)+r}r.MD5=i._createHelper(s),r.HmacMD5=i._createHmacHelper(s)}(Math),function(){var t=CryptoJS,r=t.lib.WordArray;t.enc.Base64={stringify:function(t){var r=t.words,n=t.sigBytes,e=this._map;t.clamp();for(var i=[],o=0;o>>2]>>>24-o%4*8&255)<<16|(r[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|r[o+2>>>2]>>>24-(o+2)%4*8&255,s=0;s<4&&o+.75*s>>6*(3-s)&63));var c=e.charAt(64);if(c)for(;i.length%4;)i.push(c);return i.join("")},parse:function(t){var n=t.length,e=this._map,i=this._reverseMap;if(!i){i=this._reverseMap=[];for(var o=0;o>>6-a%4*2;i[o>>>2]|=(s|c)<<24-o%4*8,o++}return r.create(i,o)}(t,n,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}();}; +function md5(word){return CryptoJS.MD5(word).toString();} + + +// prettier-ignore +function Env(t, e) { class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise(((e, i) => { s.call(this, t, ((t, s, o) => { t ? i(t) : e(s) })) })) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.logLevels = { debug: 0, info: 1, warn: 2, error: 3 }, this.logLevelPrefixs = { debug: "[DEBUG] ", info: "[INFO] ", warn: "[WARN] ", error: "[ERROR] " }, this.logLevel = "info", this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.encoding = "utf-8", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } getEnv() { return "undefined" != typeof $environment && $environment["surge-version"] ? "Surge" : "undefined" != typeof $environment && $environment["stash-version"] ? "Stash" : "undefined" != typeof module && module.exports ? "Node.js" : "undefined" != typeof $task ? "Quantumult X" : "undefined" != typeof $loon ? "Loon" : "undefined" != typeof $rocket ? "Shadowrocket" : void 0 } isNode() { return "Node.js" === this.getEnv() } isQuanX() { return "Quantumult X" === this.getEnv() } isSurge() { return "Surge" === this.getEnv() } isLoon() { return "Loon" === this.getEnv() } isShadowrocket() { return "Shadowrocket" === this.getEnv() } isStash() { return "Stash" === this.getEnv() } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null, ...s) { try { return JSON.stringify(t, ...s) } catch { return e } } getjson(t, e) { let s = e; if (this.getdata(t)) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise((e => { this.get({ url: t }, ((t, s, i) => e(i))) })) } runScript(t, e) { return new Promise((s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let o = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); o = o ? 1 * o : 20, o = e && e.timeout ? e.timeout : o; const [r, a] = i.split("@"), n = { url: `http://${a}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: o }, headers: { "X-Key": r, Accept: "*/*" }, timeout: o }; this.post(n, ((t, e, i) => s(i))) })).catch((t => this.logErr(t))) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), o = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, o) : i ? this.fs.writeFileSync(e, o) : this.fs.writeFileSync(t, o) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let o = t; for (const t of i) if (o = Object(o)[t], void 0 === o) return s; return o } lodash_set(t, e, s) { return Object(t) !== t || (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce(((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}), t)[e[e.length - 1]] = s), t } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), o = s ? this.getval(s) : ""; if (o) try { const t = JSON.parse(o); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, o] = /^@(.*?)\.(.*?)$/.exec(e), r = this.getval(i), a = i ? "null" === r ? null : r || "{}" : "{}"; try { const e = JSON.parse(a); this.lodash_set(e, o, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const r = {}; this.lodash_set(r, o, t), s = this.setval(JSON.stringify(r), i) } } else s = this.setval(t, e); return s } getval(t) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.read(t); case "Quantumult X": return $prefs.valueForKey(t); case "Node.js": return this.data = this.loaddata(), this.data[t]; default: return this.data && this.data[t] || null } } setval(t, e) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.write(t, e); case "Quantumult X": return $prefs.setValueForKey(t, e); case "Node.js": return this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0; default: return this.data && this.data[e] || null } } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.cookie && void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar))) } get(t, e = (() => { })) { switch (t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"], delete t.headers["content-type"], delete t.headers["content-length"]), t.params && (t.url += "?" + this.queryStr(t.params)), void 0 === t.followRedirect || t.followRedirect || ((this.isSurge() || this.isLoon()) && (t["auto-redirect"] = !1), this.isQuanX() && (t.opts ? t.opts.redirection = !1 : t.opts = { redirection: !1 })), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, ((t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status ? s.status : s.statusCode, s.status = s.statusCode), e(t, s, i) })); break; case "Quantumult X": this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then((t => { const { statusCode: s, statusCode: i, headers: o, body: r, bodyBytes: a } = t; e(null, { status: s, statusCode: i, headers: o, body: r, bodyBytes: a }, r, a) }), (t => e(t && t.error || "UndefinedError"))); break; case "Node.js": let s = require("iconv-lite"); this.initGotEnv(t), this.got(t).on("redirect", ((t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } })).then((t => { const { statusCode: i, statusCode: o, headers: r, rawBody: a } = t, n = s.decode(a, this.encoding); e(null, { status: i, statusCode: o, headers: r, rawBody: a, body: n }, n) }), (t => { const { message: i, response: o } = t; e(i, o, o && s.decode(o.rawBody, this.encoding)) })); break } } post(t, e = (() => { })) { const s = t.method ? t.method.toLocaleLowerCase() : "post"; switch (t.body && t.headers && !t.headers["Content-Type"] && !t.headers["content-type"] && (t.headers["content-type"] = "application/x-www-form-urlencoded"), t.headers && (delete t.headers["Content-Length"], delete t.headers["content-length"]), void 0 === t.followRedirect || t.followRedirect || ((this.isSurge() || this.isLoon()) && (t["auto-redirect"] = !1), this.isQuanX() && (t.opts ? t.opts.redirection = !1 : t.opts = { redirection: !1 })), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient[s](t, ((t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status ? s.status : s.statusCode, s.status = s.statusCode), e(t, s, i) })); break; case "Quantumult X": t.method = s, this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then((t => { const { statusCode: s, statusCode: i, headers: o, body: r, bodyBytes: a } = t; e(null, { status: s, statusCode: i, headers: o, body: r, bodyBytes: a }, r, a) }), (t => e(t && t.error || "UndefinedError"))); break; case "Node.js": let i = require("iconv-lite"); this.initGotEnv(t); const { url: o, ...r } = t; this.got[s](o, r).then((t => { const { statusCode: s, statusCode: o, headers: r, rawBody: a } = t, n = i.decode(a, this.encoding); e(null, { status: s, statusCode: o, headers: r, rawBody: a, body: n }, n) }), (t => { const { message: s, response: o } = t; e(s, o, o && i.decode(o.rawBody, this.encoding)) })); break } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } queryStr(t) { let e = ""; for (const s in t) { let i = t[s]; null != i && "" !== i && ("object" == typeof i && (i = JSON.stringify(i)), e += `${s}=${i}&`) } return e = e.substring(0, e.length - 1), e } msg(e = t, s = "", i = "", o) { const r = t => { const { $open: e, $copy: s, $media: i, $mediaMime: o } = t; switch (typeof t) { case void 0: return t; case "string": switch (this.getEnv()) { case "Surge": case "Stash": default: return { url: t }; case "Loon": case "Shadowrocket": return t; case "Quantumult X": return { "open-url": t }; case "Node.js": return }case "object": switch (this.getEnv()) { case "Surge": case "Stash": case "Shadowrocket": default: { const r = {}; let a = t.openUrl || t.url || t["open-url"] || e; a && Object.assign(r, { action: "open-url", url: a }); let n = t["update-pasteboard"] || t.updatePasteboard || s; if (n && Object.assign(r, { action: "clipboard", text: n }), i) { let t, e, s; if (i.startsWith("http")) t = i; else if (i.startsWith("data:")) { const [t] = i.split(";"), [, o] = i.split(","); e = o, s = t.replace("data:", "") } else { e = i, s = (t => { const e = { JVBERi0: "application/pdf", R0lGODdh: "image/gif", R0lGODlh: "image/gif", iVBORw0KGgo: "image/png", "/9j/": "image/jpg" }; for (var s in e) if (0 === t.indexOf(s)) return e[s]; return null })(i) } Object.assign(r, { "media-url": t, "media-base64": e, "media-base64-mime": o ?? s }) } return Object.assign(r, { "auto-dismiss": t["auto-dismiss"], sound: t.sound }), r } case "Loon": { const s = {}; let i = t.openUrl || t.url || t["open-url"] || e; i && Object.assign(s, { openUrl: i }); let o = t.mediaUrl || t["media-url"]; return o && Object.assign(s, { mediaUrl: o }), s } case "Quantumult X": { const i = {}; let o = t["open-url"] || t.url || t.openUrl || e; o && Object.assign(i, { "open-url": o }); let r = t["media-url"] || t.mediaUrl; r && Object.assign(i, { "media-url": r }); let a = t["update-pasteboard"] || t.updatePasteboard || s; return a && Object.assign(i, { "update-pasteboard": a }), i } case "Node.js": return }default: return } }; if (!this.isMute) switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: $notification.post(e, s, i, r(o)); break; case "Quantumult X": $notify(e, s, i, r(o)); break; case "Node.js": break }if (!this.isMuteLog) { let t = ["", "==============📣系统通知📣=============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } debug(...t) { this.logLevels[this.logLevel] <= this.logLevels.debug && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.debug}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } info(...t) { this.logLevels[this.logLevel] <= this.logLevels.info && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.info}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } warn(...t) { this.logLevels[this.logLevel] <= this.logLevels.warn && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.warn}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } error(...t) { this.logLevels[this.logLevel] <= this.logLevels.error && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.error}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.map((t => t ?? String(t))).join(this.logSeparator)) } logErr(t, e) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": case "Quantumult X": default: this.log("", `❗️${this.name}, 错误!`, e, t); break; case "Node.js": this.log("", `❗️${this.name}, 错误!`, e, void 0 !== t.message ? t.message : t, t.stack); break } } wait(t) { return new Promise((e => setTimeout(e, t))) } done(t = {}) { const e = ((new Date).getTime() - this.startTime) / 1e3; switch (this.log("", `🔔${this.name}, 结束! 🕛 ${e} 秒`), this.log(), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": case "Quantumult X": default: $done(t); break; case "Node.js": process.exit(1) } } }(t, e) } From 7a01f31a53123d974f727576b7f81bf8880307e1 Mon Sep 17 00:00:00 2001 From: MuTu <59136159+githubdulong@users.noreply.github.com> Date: Sun, 29 Jun 2025 01:33:32 +0800 Subject: [PATCH 088/109] =?UTF-8?q?=E5=B7=B2=E7=94=B1=20www.SourceFiles.ap?= =?UTF-8?q?p=20=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jd_buy_helper.js | 415 ----------------------------------------------- 1 file changed, 415 deletions(-) delete mode 100644 jd_buy_helper.js diff --git a/jd_buy_helper.js b/jd_buy_helper.js deleted file mode 100644 index d5173438..00000000 --- a/jd_buy_helper.js +++ /dev/null @@ -1,415 +0,0 @@ -/** - * 脚本名称:京东购物助手 - * 使用说明:进入APP商品详情页触发,支持京东下单返利和慢慢买、购物党和什么值得买跳转比价领券以及慢慢买接口历史价格。 - -[Script] -# > 京东购物助手 -购物助手 = type=http-response,pattern=^https:\/\/in\.m\.jd\.com\/product\/.+?\.html,requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/jd_buy_helper.js -慢慢买CK = type=http-request,pattern=^https?:\/\/apapia-sqk-weblogic\.manmanbuy\.com/baoliao\/center\/menu,requires-body=1,max-size=0,binary-body-mode=0,script-path=https://raw.githubusercontent.com/githubdulong/Script/master/MmmCK.js -[MITM] -hostname = %APPEND% in.m.jd.com, lite-in.m.jd.com, apapia-sqk-weblogic.manmanbuy.com - - * 添加脚本后依赖BoxJs使用 https://raw.githubusercontent.com/FoKit/Scripts/main/boxjs/fokit.boxjs.json - - * Surge可填写模块参数使用 https://raw.githubusercontent.com/githubdulong/Script/master/Surge/jd_buy_helper.sgmodule - - */ - -const $ = new Env("购物助手"); -intCryptoJS(); -let html = $response.body; - -(async () => { - if (!html || !html.includes("")) { - $.log("找不到标签,结束执行"); - $.done({ body: html }); - return; - } - $.log("已开始执行"); - - // 初始化参数与环境变量 - await init_tools(); - - if ($.jd_unionId && $.jtt_appid && $.jtt_appkey) { - - await jingfenJingTuiTui(); - } else { - $.msg($.name, "", "请检查配置是否正确 ❌"); - $.done({ body: html }); - return; - } - - await get_price_comparison(); - - await notice(); - - await hook_html(); -})() - .catch((e) => { - $.log($.name, "", "出错了: " + e + "❌"); - }) - .finally(() => { - $.done({ body: html }); - }); - -/** 初始化:读取模块参数和本地存储参数,设置全局变量 */ -async function init_tools() { - $.log("初始化开始"); - - // 获取模块传入参数 - const args = typeof $argument !== "undefined" ? $argument : ""; - $.log(`传入的参数: ${args}`); - const argObj = Object.fromEntries( - args.split("&").map(item => item.split("=").map(decodeURIComponent)) - ); - const isEmpty = (val) => !val || val === "null"; - - // 参数优先级:模块参数 > BoxJs 本地存储 - $.jd_unionId = !isEmpty(argObj["jd_union_id"]) - ? argObj["jd_union_id"] - : $.getdata("jd_unionId") || ""; - $.jd_positionId = !isEmpty(argObj["jd_position_id"]) - ? argObj["jd_position_id"] - : $.getdata("jd_positionId") || ""; - $.jtt_appid = !isEmpty(argObj["jtt_appid"]) - ? argObj["jtt_appid"] - : $.getdata("jtt_appid") || ""; - $.jtt_appkey = !isEmpty(argObj["jtt_appkey"]) - ? argObj["jtt_appkey"] - : $.getdata("jtt_appkey") || ""; - - $.log(`jd_unionId: ${$.jd_unionId}`); - $.log(`jd_positionId: ${$.jd_positionId}`); - $.log(`jtt_appid: ${$.jtt_appid}`); - $.log(`jtt_appkey: ${$.jtt_appkey}`); - - $.button = []; - const helperConfig = { - zdm: argObj["buy_helper_zdm"] || $.getdata("buy_helper_zdm") || "true", - mmm: argObj["buy_helper_mmm"] || $.getdata("buy_helper_mmm") || "true", - gwd: argObj["buy_helper_gwd"] || $.getdata("buy_helper_gwd") || "false", - copy: argObj["buy_helper_copy"] || $.getdata("buy_helper_copy") || "true", - }; - if (helperConfig.zdm !== "false") $.button.push("smzdm"); - if (helperConfig.mmm !== "false") $.button.push("mmm"); - if (helperConfig.gwd !== "false") $.button.push("gwd"); - if (helperConfig.copy !== "false") $.button.push("copy"); - - $.buy_helper_LR = argObj["buy_helper_LR"] || $.getdata("buy_helper_LR") || "left"; - - let url = $request.url; - $.appType = url.includes("lite-in.m.jd.com") ? "jdtj" : "jd"; - $.sku = (url.match(/\/(\d+)\.html/) || [])[1] || ""; - $.shortUrl = `https://item.jd.com/${$.sku}.html`; - - $.log("初始化完成"); - $.log(`类型: ${$.appType}`); - $.log(`商品: ${$.sku}`); - $.log(`appId: ${$.jtt_appid}`); - $.log(`appkey: ${$.jtt_appkey}`); -} - -/** 京推推转链 */ -async function jingfenJingTuiTui() { - $.log("转链开始"); - return new Promise((resolve) => { - const options = { - url: `http://japi.jingtuitui.com/api/universal?appid=${$.jtt_appid}&appkey=${$.jtt_appkey}&v=v3&unionid=${$.jd_unionId}&positionid=${$.jd_positionId}&content=https://item.jd.com/${$.sku}.html`, - timeout: 100 * 1000, - headers: { "Content-Type": "application/json;charset=utf-8" }, - }; - $.get(options, (err, resp, data) => { - try { - if (err) { - $.log("京推推 universal 请求失败:" + $.toStr(err)); - } else { - data = JSON.parse(data); - if (data["return"] == 0) { - const linkData = data?.result?.link_date?.[0] || {}; - const { chain_link, goods_info } = linkData; - if (goods_info) { - const { skuName = chain_link, imageInfo, commissionInfo, priceInfo } = goods_info; - $.commissionShare = commissionInfo.commissionShare; - $.commission = commissionInfo.couponCommission; - $.price = priceInfo.lowestPrice; - $.skuName = skuName; - $.skuImg = imageInfo.imageList?.[0]?.url; - } - $.shortUrl = chain_link; - $.log("转链完成,短链地址:" + $.shortUrl); - } else { - $.log("转链返回异常:" + $.toStr(data)); - } - } - } catch (e) { - $.logErr(e, resp); - } finally { - resolve(); - } - }); - }); -} - -/** 获取慢慢买 CK 的封装 */ -const getmmCK = () => { - const ck = $.getdata("慢慢买CK"); - if (!ck) { - $.msg("未获取ck", "请先打开【慢慢买】APP--我的, 获取ck", ""); - } - return ck; -}; - -const $http = (op, t = 4) => { - const { promise, resolve, reject } = Promise.withResolvers(); - const HTTPError = (e, req, res) => - Object.assign(new Error(e), { - name: "HTTPError", - request: req, - response: res, - }); - - const handleRes = ({ bodyBytes, ...res }) => { - res.status ??= res.statusCode; - res.json = () => JSON.parse(res.body); - if (res.headers?.["binary-mode"] && bodyBytes) - res.body = new Uint8Array(bodyBytes); - - res.error || res.status < 200 || res.status > 307 - ? reject(HTTPError(res.error, op, res)) - : resolve(res); - }; - - const timer = setTimeout( - () => reject(HTTPError("timeout", op)), - op.$timeout ?? t * 1000 - ); - this.$httpClient?.[op.method || "get"](op, (error, resp, body) => { - handleRes({ error, ...resp, body }); - }); - this.$task?.fetch({ url: op, ...op }).then(handleRes, handleRes); - - return promise.finally(() => clearTimeout(timer)); -}; - -const getMMdata = (id) => { - const buildMultipart = (fields) => { - const boundary = - "----WebKitFormBoundary" + Math.random().toString(36).substr(2); - let body = ""; - - for (const [name, value] of Object.entries(fields)) { - body += `--${boundary}\r\n`; - body += `Content-Disposition: form-data; name="${name}"\r\n\r\n`; - body += `${value}\r\n`; - } - body += `--${boundary}--\r\n`; - - return { body, boundary }; - }; - - const shareBody = { - methodName: "trendJava", - spbh: `1|${id}`, - url: `https://item.jd.com/${id}.html`, - t: Date.now().toString(), - c_appver: "4.8.3.1", - c_mmbDevId: getmmCK(), - }; - - shareBody.token = md5( - encodeURIComponent( - "3E41D1331F5DDAFCD0A38FE2D52FF66F" + - jsonToCustomString(shareBody) + - "3E41D1331F5DDAFCD0A38FE2D52FF66F" - ) - ).toUpperCase(); - - const headers = { - "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", - "User-Agent": - "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios", - }; - - const reqShare = { - method: "post", - url: "https://apapia-history-weblogic.manmanbuy.com/app/share", - headers, - body: jsonToQueryString(shareBody), - }; - - return $http(reqShare) - .then((res) => { - const { msg, code, data } = res.json(); - if (code !== 2000) throw new Error(msg); - if (!data) throw new Error(`${reqShare.url}: 无效数据`); - - return new URL(data).searchParams; - }) - .then((params) => { - const fields = { - shareId: params.get("shareId"), - sign: params.get("sign"), - spbh: params.get("spbh"), - url: params.get("url"), - }; - - const { body, boundary } = buildMultipart(fields); - - const reqTrendData = { - method: "post", - url: "https://apapia-history-weblogic.manmanbuy.com/h5/share/trendData", - headers: { - "content-type": `multipart/form-data; boundary=${boundary}`, - }, - body, - }; - - return $http(reqTrendData); - }) - .then((res) => res.json()); -}; - -/** 获取比价信息 */ -async function get_price_comparison() { - try { - const data = await getMMdata($.sku); - if (data?.ok && data?.result?.priceRemark?.ListPriceDetail) { - const lowerItem = data?.result?.priceRemark?.ListPriceDetail.find(item => item.ShowName === "历史最低"); - if (lowerItem) { - const { extraPrice, Price, Difference, Date } = lowerItem; - $.Difference = Difference; - $.desc = `历史最低: ${Price || `¥${extraPrice}`} (${Date})`; - } else { - $.desc = "历史最低: 暂无"; - } - $.price = data?.recentlyZK?.currentprice || $.price; - $.skuName = data?.single?.title || $.skuName; - $.skuImg = data?.single?.smallpic || $.skuImg; - } else { - $.desc = "历史最低: 暂无"; - $.log("获取比价信息失败"); - } - } catch (e) { - $.logErr(e); - } -} - -/** 发送通知 */ -async function notice() { - $.log("发送通知"); - $.title = $.skuName || "商品信息"; - $.opts = { "auto-dismiss": 30 }; - - $.desc = $.desc || ""; - if (/u\.jd\.com/.test($.shortUrl)) { - $.desc += `\n预计返利: ¥${(($.price * $.commissionShare) / 100).toFixed(2)} ${$.commissionShare}%`; - $.desc += `\n当前到手: ¥${$.price}${$.Difference ? " " + $.Difference : ""}`; - - // 根据平台生成跳转链接 - if ($.appType === "jdtj") { - $.jumpUrl = `openjdlite://virtual?params=${encodeURIComponent( - '{"category":"jump","des":"m","url":"' + $.shortUrl + '"}' - )}`; - } else { - $.jumpUrl = `openApp.jdMobile://virtual?params=${encodeURIComponent( - '{"category":"jump","des":"m","sourceValue":"babel-act","sourceType":"babel","url":"' + $.shortUrl + '"}' - )}`; - } - $.opts["$open"] = $.jumpUrl; - } else { - $.desc += "\n预计返利: 暂无"; - $.log("无佣金商品"); - } - if ($.skuImg) $.opts["$media"] = $.skuImg; - if ($.isLoon() && $loon.split(" ")[1].split(".")[0] === "16") { - $.opts["$media"] = undefined; - } - $.msg($.title, $.subt, $.desc, $.opts); -} - -/** 注入 HTML */ -async function hook_html() { - $.log("开始注入html"); - const buttons = [ - { key: "mmm", icon: "https://raw.githubusercontent.com/FoKit/Scripts/main/images/icon/mmm.png" }, - { key: "smzdm", icon: "https://raw.githubusercontent.com/FoKit/Scripts/main/images/icon/zdm.png" }, - { key: "gwd", icon: "https://raw.githubusercontent.com/FoKit/Scripts/main/images/icon/gwd.png" }, - { key: "jf", icon: "https://raw.githubusercontent.com/FoKit/Scripts/main/images/icon/jf.png" }, - { key: "copy", icon: "https://raw.githubusercontent.com/FoKit/Scripts/main/images/icon/copy.png" } - ].filter(item => $.button.includes(item.key) && $.sku); - - - const hookContent = ` - -
- ${buttons.map(item => ``).join("\n")} -
- - `; - - html = html.replace(/<\/html>/, hookContent); - $.log("注入html完成"); - $.done({ body: html }); -} - - -function jsonToQueryString(jsonObject) {return Object.keys(jsonObject).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(jsonObject[key])}`).join('&');} - - -function jsonToCustomString(jsonObject){return Object.keys(jsonObject).filter(key=>jsonObject[key]!==''&&key.toLowerCase()!=='token').sort().map(key=>`${key.toUpperCase()}${jsonObject[key].toUpperCase()}`).join('');} - - -function intCryptoJS(){CryptoJS=function(t,r){var n;if("undefined"!=typeof window&&window.crypto&&(n=window.crypto),"undefined"!=typeof self&&self.crypto&&(n=self.crypto),"undefined"!=typeof globalThis&&globalThis.crypto&&(n=globalThis.crypto),!n&&"undefined"!=typeof window&&window.msCrypto&&(n=window.msCrypto),!n&&"undefined"!=typeof global&&global.crypto&&(n=global.crypto),!n&&"function"==typeof require)try{n=require("crypto")}catch(t){}var e=function(){if(n){if("function"==typeof n.getRandomValues)try{return n.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof n.randomBytes)try{return n.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")},i=Object.create||function(){function t(){}return function(r){var n;return t.prototype=r,n=new t,t.prototype=null,n}}(),o={},a=o.lib={},s=a.Base={extend:function(t){var r=i(this);return t&&r.mixIn(t),r.hasOwnProperty("init")&&this.init!==r.init||(r.init=function(){r.$super.init.apply(this,arguments)}),r.init.prototype=r,r.$super=this,r},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var r in t)t.hasOwnProperty(r)&&(this[r]=t[r]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},c=a.WordArray=s.extend({init:function(t,r){t=this.words=t||[],this.sigBytes=null!=r?r:4*t.length},toString:function(t){return(t||f).stringify(this)},concat:function(t){var r=this.words,n=t.words,e=this.sigBytes,i=t.sigBytes;if(this.clamp(),e%4)for(var o=0;o>>2]>>>24-o%4*8&255;r[e+o>>>2]|=a<<24-(e+o)%4*8}else for(var s=0;s>>2]=n[s>>>2];return this.sigBytes+=i,this},clamp:function(){var r=this.words,n=this.sigBytes;r[n>>>2]&=4294967295<<32-n%4*8,r.length=t.ceil(n/4)},clone:function(){var t=s.clone.call(this);return t.words=this.words.slice(0),t},random:function(r){var n,i=[],o=function(r){r=r;var n=987654321,e=4294967295;return function(){var i=((n=36969*(65535&n)+(n>>16)&e)<<16)+(r=18e3*(65535&r)+(r>>16)&e)&e;return i/=4294967296,(i+=.5)*(t.random()>.5?1:-1)}},a=!1;try{e(),a=!0}catch(t){}for(var s,u=0;u>>2]>>>24-i%4*8&255;e.push((o>>>4).toString(16)),e.push((15&o).toString(16))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>3]|=parseInt(t.substr(e,2),16)<<24-e%8*4;return new c.init(n,r/2)}},h=u.Latin1={stringify:function(t){for(var r=t.words,n=t.sigBytes,e=[],i=0;i>>2]>>>24-i%4*8&255;e.push(String.fromCharCode(o))}return e.join("")},parse:function(t){for(var r=t.length,n=[],e=0;e>>2]|=(255&t.charCodeAt(e))<<24-e%4*8;return new c.init(n,r)}},p=u.Utf8={stringify:function(t){try{return decodeURIComponent(escape(h.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return h.parse(unescape(encodeURIComponent(t)))}},d=a.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new c.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=p.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(r){var n,e=this._data,i=e.words,o=e.sigBytes,a=this.blockSize,s=o/(4*a),u=(s=r?t.ceil(s):t.max((0|s)-this._minBufferSize,0))*a,f=t.min(4*u,o);if(u){for(var h=0;h>>24)|4278255360&(i<<24|i>>>8)}var o=this._hash.words,s=t[r+0],p=t[r+1],d=t[r+2],l=t[r+3],y=t[r+4],v=t[r+5],g=t[r+6],w=t[r+7],_=t[r+8],m=t[r+9],B=t[r+10],b=t[r+11],C=t[r+12],S=t[r+13],x=t[r+14],A=t[r+15],H=o[0],z=o[1],M=o[2],D=o[3];z=h(z=h(z=h(z=h(z=f(z=f(z=f(z=f(z=u(z=u(z=u(z=u(z=c(z=c(z=c(z=c(z,M=c(M,D=c(D,H=c(H,z,M,D,s,7,a[0]),z,M,p,12,a[1]),H,z,d,17,a[2]),D,H,l,22,a[3]),M=c(M,D=c(D,H=c(H,z,M,D,y,7,a[4]),z,M,v,12,a[5]),H,z,g,17,a[6]),D,H,w,22,a[7]),M=c(M,D=c(D,H=c(H,z,M,D,_,7,a[8]),z,M,m,12,a[9]),H,z,B,17,a[10]),D,H,b,22,a[11]),M=c(M,D=c(D,H=c(H,z,M,D,C,7,a[12]),z,M,S,12,a[13]),H,z,x,17,a[14]),D,H,A,22,a[15]),M=u(M,D=u(D,H=u(H,z,M,D,p,5,a[16]),z,M,g,9,a[17]),H,z,b,14,a[18]),D,H,s,20,a[19]),M=u(M,D=u(D,H=u(H,z,M,D,v,5,a[20]),z,M,B,9,a[21]),H,z,A,14,a[22]),D,H,y,20,a[23]),M=u(M,D=u(D,H=u(H,z,M,D,m,5,a[24]),z,M,x,9,a[25]),H,z,l,14,a[26]),D,H,_,20,a[27]),M=u(M,D=u(D,H=u(H,z,M,D,S,5,a[28]),z,M,d,9,a[29]),H,z,w,14,a[30]),D,H,C,20,a[31]),M=f(M,D=f(D,H=f(H,z,M,D,v,4,a[32]),z,M,_,11,a[33]),H,z,b,16,a[34]),D,H,x,23,a[35]),M=f(M,D=f(D,H=f(H,z,M,D,p,4,a[36]),z,M,y,11,a[37]),H,z,w,16,a[38]),D,H,B,23,a[39]),M=f(M,D=f(D,H=f(H,z,M,D,S,4,a[40]),z,M,s,11,a[41]),H,z,l,16,a[42]),D,H,g,23,a[43]),M=f(M,D=f(D,H=f(H,z,M,D,m,4,a[44]),z,M,C,11,a[45]),H,z,A,16,a[46]),D,H,d,23,a[47]),M=h(M,D=h(D,H=h(H,z,M,D,s,6,a[48]),z,M,w,10,a[49]),H,z,x,15,a[50]),D,H,v,21,a[51]),M=h(M,D=h(D,H=h(H,z,M,D,C,6,a[52]),z,M,l,10,a[53]),H,z,B,15,a[54]),D,H,p,21,a[55]),M=h(M,D=h(D,H=h(H,z,M,D,_,6,a[56]),z,M,A,10,a[57]),H,z,g,15,a[58]),D,H,S,21,a[59]),M=h(M,D=h(D,H=h(H,z,M,D,y,6,a[60]),z,M,b,10,a[61]),H,z,d,15,a[62]),D,H,m,21,a[63]),o[0]=o[0]+H|0,o[1]=o[1]+z|0,o[2]=o[2]+M|0,o[3]=o[3]+D|0},_doFinalize:function(){var r=this._data,n=r.words,e=8*this._nDataBytes,i=8*r.sigBytes;n[i>>>5]|=128<<24-i%32;var o=t.floor(e/4294967296),a=e;n[15+(i+64>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),n[14+(i+64>>>9<<4)]=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),r.sigBytes=4*(n.length+1),this._process();for(var s=this._hash,c=s.words,u=0;u<4;u++){var f=c[u];c[u]=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8)}return s},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});function c(t,r,n,e,i,o,a){var s=t+(r&n|~r&e)+i+a;return(s<>>32-o)+r}function u(t,r,n,e,i,o,a){var s=t+(r&e|n&~e)+i+a;return(s<>>32-o)+r}function f(t,r,n,e,i,o,a){var s=t+(r^n^e)+i+a;return(s<>>32-o)+r}function h(t,r,n,e,i,o,a){var s=t+(n^(r|~e))+i+a;return(s<>>32-o)+r}r.MD5=i._createHelper(s),r.HmacMD5=i._createHmacHelper(s)}(Math),function(){var t=CryptoJS,r=t.lib.WordArray;t.enc.Base64={stringify:function(t){var r=t.words,n=t.sigBytes,e=this._map;t.clamp();for(var i=[],o=0;o>>2]>>>24-o%4*8&255)<<16|(r[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|r[o+2>>>2]>>>24-(o+2)%4*8&255,s=0;s<4&&o+.75*s>>6*(3-s)&63));var c=e.charAt(64);if(c)for(;i.length%4;)i.push(c);return i.join("")},parse:function(t){var n=t.length,e=this._map,i=this._reverseMap;if(!i){i=this._reverseMap=[];for(var o=0;o>>6-a%4*2;i[o>>>2]|=(s|c)<<24-o%4*8,o++}return r.create(i,o)}(t,n,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}();}; -function md5(word){return CryptoJS.MD5(word).toString();} - - -// prettier-ignore -function Env(t, e) { class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise(((e, i) => { s.call(this, t, ((t, s, o) => { t ? i(t) : e(s) })) })) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.logLevels = { debug: 0, info: 1, warn: 2, error: 3 }, this.logLevelPrefixs = { debug: "[DEBUG] ", info: "[INFO] ", warn: "[WARN] ", error: "[ERROR] " }, this.logLevel = "info", this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.encoding = "utf-8", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } getEnv() { return "undefined" != typeof $environment && $environment["surge-version"] ? "Surge" : "undefined" != typeof $environment && $environment["stash-version"] ? "Stash" : "undefined" != typeof module && module.exports ? "Node.js" : "undefined" != typeof $task ? "Quantumult X" : "undefined" != typeof $loon ? "Loon" : "undefined" != typeof $rocket ? "Shadowrocket" : void 0 } isNode() { return "Node.js" === this.getEnv() } isQuanX() { return "Quantumult X" === this.getEnv() } isSurge() { return "Surge" === this.getEnv() } isLoon() { return "Loon" === this.getEnv() } isShadowrocket() { return "Shadowrocket" === this.getEnv() } isStash() { return "Stash" === this.getEnv() } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null, ...s) { try { return JSON.stringify(t, ...s) } catch { return e } } getjson(t, e) { let s = e; if (this.getdata(t)) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise((e => { this.get({ url: t }, ((t, s, i) => e(i))) })) } runScript(t, e) { return new Promise((s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let o = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); o = o ? 1 * o : 20, o = e && e.timeout ? e.timeout : o; const [r, a] = i.split("@"), n = { url: `http://${a}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: o }, headers: { "X-Key": r, Accept: "*/*" }, timeout: o }; this.post(n, ((t, e, i) => s(i))) })).catch((t => this.logErr(t))) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), o = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, o) : i ? this.fs.writeFileSync(e, o) : this.fs.writeFileSync(t, o) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let o = t; for (const t of i) if (o = Object(o)[t], void 0 === o) return s; return o } lodash_set(t, e, s) { return Object(t) !== t || (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce(((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}), t)[e[e.length - 1]] = s), t } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), o = s ? this.getval(s) : ""; if (o) try { const t = JSON.parse(o); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, o] = /^@(.*?)\.(.*?)$/.exec(e), r = this.getval(i), a = i ? "null" === r ? null : r || "{}" : "{}"; try { const e = JSON.parse(a); this.lodash_set(e, o, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const r = {}; this.lodash_set(r, o, t), s = this.setval(JSON.stringify(r), i) } } else s = this.setval(t, e); return s } getval(t) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.read(t); case "Quantumult X": return $prefs.valueForKey(t); case "Node.js": return this.data = this.loaddata(), this.data[t]; default: return this.data && this.data[t] || null } } setval(t, e) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.write(t, e); case "Quantumult X": return $prefs.setValueForKey(t, e); case "Node.js": return this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0; default: return this.data && this.data[e] || null } } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.cookie && void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar))) } get(t, e = (() => { })) { switch (t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"], delete t.headers["content-type"], delete t.headers["content-length"]), t.params && (t.url += "?" + this.queryStr(t.params)), void 0 === t.followRedirect || t.followRedirect || ((this.isSurge() || this.isLoon()) && (t["auto-redirect"] = !1), this.isQuanX() && (t.opts ? t.opts.redirection = !1 : t.opts = { redirection: !1 })), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, ((t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status ? s.status : s.statusCode, s.status = s.statusCode), e(t, s, i) })); break; case "Quantumult X": this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then((t => { const { statusCode: s, statusCode: i, headers: o, body: r, bodyBytes: a } = t; e(null, { status: s, statusCode: i, headers: o, body: r, bodyBytes: a }, r, a) }), (t => e(t && t.error || "UndefinedError"))); break; case "Node.js": let s = require("iconv-lite"); this.initGotEnv(t), this.got(t).on("redirect", ((t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } })).then((t => { const { statusCode: i, statusCode: o, headers: r, rawBody: a } = t, n = s.decode(a, this.encoding); e(null, { status: i, statusCode: o, headers: r, rawBody: a, body: n }, n) }), (t => { const { message: i, response: o } = t; e(i, o, o && s.decode(o.rawBody, this.encoding)) })); break } } post(t, e = (() => { })) { const s = t.method ? t.method.toLocaleLowerCase() : "post"; switch (t.body && t.headers && !t.headers["Content-Type"] && !t.headers["content-type"] && (t.headers["content-type"] = "application/x-www-form-urlencoded"), t.headers && (delete t.headers["Content-Length"], delete t.headers["content-length"]), void 0 === t.followRedirect || t.followRedirect || ((this.isSurge() || this.isLoon()) && (t["auto-redirect"] = !1), this.isQuanX() && (t.opts ? t.opts.redirection = !1 : t.opts = { redirection: !1 })), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient[s](t, ((t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status ? s.status : s.statusCode, s.status = s.statusCode), e(t, s, i) })); break; case "Quantumult X": t.method = s, this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then((t => { const { statusCode: s, statusCode: i, headers: o, body: r, bodyBytes: a } = t; e(null, { status: s, statusCode: i, headers: o, body: r, bodyBytes: a }, r, a) }), (t => e(t && t.error || "UndefinedError"))); break; case "Node.js": let i = require("iconv-lite"); this.initGotEnv(t); const { url: o, ...r } = t; this.got[s](o, r).then((t => { const { statusCode: s, statusCode: o, headers: r, rawBody: a } = t, n = i.decode(a, this.encoding); e(null, { status: s, statusCode: o, headers: r, rawBody: a, body: n }, n) }), (t => { const { message: s, response: o } = t; e(s, o, o && i.decode(o.rawBody, this.encoding)) })); break } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } queryStr(t) { let e = ""; for (const s in t) { let i = t[s]; null != i && "" !== i && ("object" == typeof i && (i = JSON.stringify(i)), e += `${s}=${i}&`) } return e = e.substring(0, e.length - 1), e } msg(e = t, s = "", i = "", o) { const r = t => { const { $open: e, $copy: s, $media: i, $mediaMime: o } = t; switch (typeof t) { case void 0: return t; case "string": switch (this.getEnv()) { case "Surge": case "Stash": default: return { url: t }; case "Loon": case "Shadowrocket": return t; case "Quantumult X": return { "open-url": t }; case "Node.js": return }case "object": switch (this.getEnv()) { case "Surge": case "Stash": case "Shadowrocket": default: { const r = {}; let a = t.openUrl || t.url || t["open-url"] || e; a && Object.assign(r, { action: "open-url", url: a }); let n = t["update-pasteboard"] || t.updatePasteboard || s; if (n && Object.assign(r, { action: "clipboard", text: n }), i) { let t, e, s; if (i.startsWith("http")) t = i; else if (i.startsWith("data:")) { const [t] = i.split(";"), [, o] = i.split(","); e = o, s = t.replace("data:", "") } else { e = i, s = (t => { const e = { JVBERi0: "application/pdf", R0lGODdh: "image/gif", R0lGODlh: "image/gif", iVBORw0KGgo: "image/png", "/9j/": "image/jpg" }; for (var s in e) if (0 === t.indexOf(s)) return e[s]; return null })(i) } Object.assign(r, { "media-url": t, "media-base64": e, "media-base64-mime": o ?? s }) } return Object.assign(r, { "auto-dismiss": t["auto-dismiss"], sound: t.sound }), r } case "Loon": { const s = {}; let i = t.openUrl || t.url || t["open-url"] || e; i && Object.assign(s, { openUrl: i }); let o = t.mediaUrl || t["media-url"]; return o && Object.assign(s, { mediaUrl: o }), s } case "Quantumult X": { const i = {}; let o = t["open-url"] || t.url || t.openUrl || e; o && Object.assign(i, { "open-url": o }); let r = t["media-url"] || t.mediaUrl; r && Object.assign(i, { "media-url": r }); let a = t["update-pasteboard"] || t.updatePasteboard || s; return a && Object.assign(i, { "update-pasteboard": a }), i } case "Node.js": return }default: return } }; if (!this.isMute) switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: $notification.post(e, s, i, r(o)); break; case "Quantumult X": $notify(e, s, i, r(o)); break; case "Node.js": break }if (!this.isMuteLog) { let t = ["", "==============📣系统通知📣=============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } debug(...t) { this.logLevels[this.logLevel] <= this.logLevels.debug && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.debug}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } info(...t) { this.logLevels[this.logLevel] <= this.logLevels.info && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.info}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } warn(...t) { this.logLevels[this.logLevel] <= this.logLevels.warn && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.warn}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } error(...t) { this.logLevels[this.logLevel] <= this.logLevels.error && (t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(`${this.logLevelPrefixs.error}${t.map((t => t ?? String(t))).join(this.logSeparator)}`)) } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.map((t => t ?? String(t))).join(this.logSeparator)) } logErr(t, e) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": case "Quantumult X": default: this.log("", `❗️${this.name}, 错误!`, e, t); break; case "Node.js": this.log("", `❗️${this.name}, 错误!`, e, void 0 !== t.message ? t.message : t, t.stack); break } } wait(t) { return new Promise((e => setTimeout(e, t))) } done(t = {}) { const e = ((new Date).getTime() - this.startTime) / 1e3; switch (this.log("", `🔔${this.name}, 结束! 🕛 ${e} 秒`), this.log(), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": case "Quantumult X": default: $done(t); break; case "Node.js": process.exit(1) } } }(t, e) } From 034535f7654d91a94473a727b12574505d43b650 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Wed, 16 Jul 2025 08:30:24 +0800 Subject: [PATCH 089/109] Hub.sgmodule --- Surge/Hub.sgmodule | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Surge/Hub.sgmodule b/Surge/Hub.sgmodule index b58c5c94..c6d61c16 100644 --- a/Surge/Hub.sgmodule +++ b/Surge/Hub.sgmodule @@ -6,11 +6,11 @@ [URL Rewrite] # Surge 转换 -^https:\/\/((?:[a-zA-Z0-9.-]*(?:git|github|gitlab|gitee|gitcode)[a-zA-Z0-9.-]*|{{{DOMAIN_REGEX}}}))\/(.*)\/(.*\.(?:js|conf|snippet|plugin|list|yaml)).*({{{SURGE_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$2/$3/_end_/$3.sgmodule?type=surge-module&target=surge-module&del=true&jqEnabled={{{JQ_ENABLED}}} +^https:\/\/((?:[a-zA-Z0-9.-]*(?:git|github|gitlab|gitee|gitcode)[a-zA-Z0-9.-]*|{{{DOMAIN_REGEX}}}))\/(.*)\/(.*\.(?:js|conf|snippet|plugin|list|yaml|lpx)).*({{{SURGE_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$2/$3/_end_/$3.sgmodule?type=surge-module&target=surge-module&del=true&jqEnabled={{{JQ_ENABLED}}} # Stash 转换 -^https:\/\/((?:[a-zA-Z0-9.-]*(?:git|github|gitlab|gitee|gitcode)[a-zA-Z0-9.-]*|{{{DOMAIN_REGEX}}}))\/(.*)\/(.*\.(?:js|conf|snippet|plugin|list|yaml)).*({{{STASH_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$2/$3/_end_/$3.sgmodule?type=qx-rewrite&target=stash-stoverride&del=true&jqEnabled={{{JQ_ENABLED}}} +^https:\/\/((?:[a-zA-Z0-9.-]*(?:git|github|gitlab|gitee|gitcode)[a-zA-Z0-9.-]*|{{{DOMAIN_REGEX}}}))\/(.*)\/(.*\.(?:js|conf|snippet|plugin|list|yaml|lpx)).*({{{STASH_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$2/$3/_end_/$3.sgmodule?type=qx-rewrite&target=stash-stoverride&del=true&jqEnabled={{{JQ_ENABLED}}} # Loon 转换 -^https:\/\/((?:[a-zA-Z0-9.-]*(?:git|github|gitlab|gitee|gitcode)[a-zA-Z0-9.-]*|{{{DOMAIN_REGEX}}}))\/(.*)\/(.*\.(?:js|conf|snippet|plugin|list|yaml)).*({{{LOON_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$2/$3/_end_/$3.sgmodule?type=loon-plugin&target=loon-plugin&del=true&jqEnabled={{{JQ_ENABLED}}} +^https:\/\/((?:[a-zA-Z0-9.-]*(?:git|github|gitlab|gitee|gitcode)[a-zA-Z0-9.-]*|{{{DOMAIN_REGEX}}}))\/(.*)\/(.*\.(?:js|conf|snippet|plugin|list|yaml|lpx)).*({{{LOON_SUFFIX}}})$ http://script.hub/file/_start_/https://$1/$2/$3/_end_/$3.sgmodule?type=loon-plugin&target=loon-plugin&del=true&jqEnabled={{{JQ_ENABLED}}} [MITM] hostname = %APPEND% raw.githubusercontent.com, gist.github.com, gist.githubusercontent.com, gitlab.com, gitee.com, gitcode.net, github.*, {{{DOMAIN_HOST}}} \ No newline at end of file From 296f7fc435b6d9a0010ff9056418b42b3d6b5475 Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Fri, 25 Jul 2025 14:24:55 +0800 Subject: [PATCH 090/109] Notification.js --- Notification 2.js => Notification.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Notification 2.js => Notification.js (100%) diff --git a/Notification 2.js b/Notification.js similarity index 100% rename from Notification 2.js rename to Notification.js From 97ad33319e289c90f6c1748e03d29f5af711258a Mon Sep 17 00:00:00 2001 From: Mu Tu Date: Mon, 28 Jul 2025 15:38:40 +0800 Subject: [PATCH 091/109] =?UTF-8?q?jd=5Fprice1.js=20=E5=8F=82=E8=80=83?= =?UTF-8?q?=E7=81=B0=E7=81=B0=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=AF=94=E4=BB=B7?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jd_price1.js | 470 ++++++++++++++++----------------------------------- 1 file changed, 147 insertions(+), 323 deletions(-) diff --git a/jd_price1.js b/jd_price1.js index ebc28170..a081d5f9 100644 --- a/jd_price1.js +++ b/jd_price1.js @@ -1,6 +1,8 @@ /** * 京东购物助手,京推推转链+比价图表 * + * * 2025-07-28 15:38 + * 修复比价,参考灰灰代码 * * 2025-05-29 16:55 * 新增点击"价格趋势"标题,跳转至慢慢买app比价 * * 2025-05-17 07:50 @@ -25,95 +27,95 @@ const manmanbuy_key = "manmanbuy_val"; const requestUrl = $request.url; const $ = new Env("京东助手"); -const getMMdata = async (id) => { - const getmmCK = () => { - if ($.manmanbuy && typeof $.manmanbuy.c_mmbDevId !== 'undefined' && $.manmanbuy.c_mmbDevId !== null && String($.manmanbuy.c_mmbDevId).trim() !== "") { - return $.manmanbuy.c_mmbDevId; - } - }; +function checkRes(res, desc = '') { + if (!res || (typeof res.code !== 'undefined' && res.code !== 2000 && res.code !== 6001)) { + $.log('慢慢买请求异常:' + $.toStr(res)); + throw new Error(`慢慢买提示您:${res.msg || `${desc}失败`}`); + } + return res; +} - const reqOpts = ({ url, buildBody, ...op }) => { - const opt = { - method: "post", - url, - headers: { - "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", - "User-Agent": - "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios", - }, - ...op, - }; - const cb = (args) => { - const reqBody = { +async function mmbRequest(Params, url) { + if (!$.manmanbuy) { + $.manmanbuy = getck(); + } + const SECRET_KEY = '3E41D1331F5DDAFCD0A38FE2D52FF66F'; + const requestBody = { + ...$.manmanbuy, + ...Params, t: Date.now().toString(), - c_appver: "4.8.3.1", - c_mmbDevId: getmmCK(), - ...args, - }; - reqBody.token = md5( - encodeURIComponent( - "3E41D1331F5DDAFCD0A38FE2D52FF66F" + - jsonToCustomString(reqBody) + - "3E41D1331F5DDAFCD0A38FE2D52FF66F" - ) - ).toUpperCase(); - return jsonToQueryString(reqBody); + c_appver: "4.8.3.1" }; - return { ...opt, body: buildBody(cb) }; - }; - - const apiCall = async (url, buildBody) => { - const options = reqOpts({ url, buildBody }); - options._timeout = 4000; - const respBody = await httpRequest(options); - if (!respBody || (typeof respBody.code !== 'undefined' && respBody.code !== 2000 && respBody.code !== 6001)) { - throw new Error(`${url} ${respBody?.msg || '请求失败或响应格式不正确'}`); - } - return respBody; - }; - - const { - result: { spbh, url: itemUrl }, - } = await apiCall( - "https://apapia-history-weblogic.manmanbuy.com/basic/getItemBasicInfo", - (set) => - set({ + delete requestBody.token; + + requestBody.token = md5(encodeURIComponent(SECRET_KEY + jsonToCustomString(requestBody) + SECRET_KEY)).toUpperCase(); + const payloadStr = jsonToQueryString(requestBody); + + const opt = { + url, + method: 'POST', + headers: { + "Content-Type": "application/x-www-form-urlencoded;charset=utf-8", + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 - mmbWebBrowse - ios" + }, + body: payloadStr, + _timeout: 5000 + }; + return await httpRequest(opt); +} + +async function get_spbh(link) { + const url = 'https://apapia-history-weblogic.manmanbuy.com/basic/getItemBasicInfo'; + const payload = { methodName: "getHistoryInfoJava", - searchKey: `https://item.jd.com/${id}.html`, - }) - ); - - const { - result: { trend: jiagequshiyh }, - msg, - } = await apiCall( - "https://apapia-history-weblogic.manmanbuy.com/history/v2/getHistoryTrend", - (set) => - set({ + searchKey: link + }; + return await mmbRequest(payload, url); +} + +async function get_jiagequshi(link, spbh) { + const url = "https://apapia-history-weblogic.manmanbuy.com/history/v2/getHistoryTrend"; + const payload = { methodName: "getHistoryTrend2021", - spbh, - url: itemUrl, - }) - ); - - if (!jiagequshiyh) return { msg, spbh }; - - const { - remark: { ListPriceDetail }, - } = await apiCall( - "https://apapia-history-weblogic.manmanbuy.com/history/priceRemark", - (set) => - set({ + url: link, + spbh: spbh + }; + return await mmbRequest(payload, url); +} + +async function get_priceRemark(jiagequshiyh) { + const url = "https://apapia-history-weblogic.manmanbuy.com/history/priceRemark"; + const payload = { methodName: "priceRemarkJava", + jiagequshiyh: jiagequshiyh + }; + return await mmbRequest(payload, url); +} + + +const getMMdata = async (id) => { + const JD_Url = `https://item.jd.com/${id}.html`; + + const basicInfo = checkRes(await get_spbh(JD_Url), '获取商品编号'); + const spbh = basicInfo?.result?.spbh; + const itemUrl = basicInfo?.result?.url; + if (!spbh || !itemUrl) throw new Error("未能获取到慢慢买商品编号(spbh)"); + + const historyTrend = checkRes(await get_jiagequshi(itemUrl, spbh), '获取价格趋势'); + const jiagequshiyh = historyTrend?.result?.trend; + if (!jiagequshiyh) { + $.log("警告:未能获取到价格趋势图(jiagequshiyh),但仍将尝试获取价格列表。"); + } + + const priceRemark = checkRes(await get_priceRemark(jiagequshiyh), '获取价格详情'); + const ListPriceDetail = priceRemark?.remark?.ListPriceDetail; + if (!ListPriceDetail) throw new Error("未能获取到详细价格列表"); + + return { + ListPriceDetail, jiagequshiyh, - }) - ); - - return { - ListPriceDetail, - jiagequshiyh, - spbh, - }; + spbh, + }; }; let args = @@ -130,23 +132,13 @@ const argObj = Object.fromEntries( ); const isEmpty = (val) => val === undefined || val === null || val === "" || val === "null"; -$.jd_unionId = !isEmpty(argObj["jd_union_id"]) - ? argObj["jd_union_id"] - : $.getdata("jd_unionId") || ""; -$.jd_positionId = !isEmpty(argObj["jd_position_id"]) - ? argObj["jd_position_id"] - : $.getdata("jd_positionId") || ""; -$.jtt_appid = !isEmpty(argObj["jtt_appid"]) - ? argObj["jtt_appid"] - : $.getdata("jtt_appid") || ""; -$.jtt_appkey = !isEmpty(argObj["jtt_appkey"]) - ? argObj["jtt_appkey"] - : $.getdata("jtt_appkey") || ""; -$.disableNotice = argObj["disable_notice"] !== "true"; +$.jd_unionId = !isEmpty(argObj["jd_union_id"]) ? argObj["jd_union_id"] : $.getdata("jd_unionId") || ""; +$.jd_positionId = !isEmpty(argObj["jd_position_id"]) ? argObj["jd_position_id"] : $.getdata("jd_positionId") || ""; +$.jtt_appid = !isEmpty(argObj["jtt_appid"]) ? argObj["jtt_appid"] : $.getdata("jtt_appid") || ""; +$.jtt_appkey = !isEmpty(argObj["jtt_appkey"]) ? argObj["jtt_appkey"] : $.getdata("jtt_appkey") || ""; +$.disableNotice = argObj["disable_notice"] === "false"; const defaultThemeTime = "7-19"; -$.themeTime = !isEmpty(argObj["theme_time"]) - ? argObj["theme_time"] - : $.getdata("theme_time") || defaultThemeTime; +$.themeTime = !isEmpty(argObj["theme_time"]) ? argObj["theme_time"] : $.getdata("theme_time") || defaultThemeTime; if (requestUrl.includes(path2)) { const reqbody = $request.body; @@ -178,6 +170,7 @@ if (requestUrl.includes(path1)) { } const { ListPriceDetail, msg: mmMsg, spbh } = await getMMdata(productId); + if (!ListPriceDetail && !spbh) { throw new Error(mmMsg || '从慢慢买获取价格详情或商品编号失败'); } @@ -196,7 +189,9 @@ if (requestUrl.includes(path1)) { $done({ body: newBody }); } catch (err) { $.logErr(err.message || $.toStr(err)); - $done({}); + const errorHtml = `
比价失败:${err.message || '未知错误'}
`; + const newBody = $response.body.replace(/]*>/, bodyMatch => bodyMatch + errorHtml); + $done({ body: newBody }); } })(); } @@ -213,7 +208,6 @@ async function jingfenJingTuiTui() { $.get(options, (err, resp, data) => { if (err) { $.log("京推推 universal 请求失败:" + $.toStr(err)); - $.logErr("转链过程中的错误: " + $.toStr(err)); } else { try { data = JSON.parse(data); @@ -221,12 +215,7 @@ async function jingfenJingTuiTui() { const linkData = data?.result?.link_date?.[0] || {}; const { chain_link, goods_info } = linkData; if (goods_info) { - const { - skuName = chain_link, - imageInfo, - commissionInfo, - priceInfo, - } = goods_info; + const { skuName, imageInfo, commissionInfo, priceInfo } = goods_info; $.commissionShare = commissionInfo.commissionShare; $.commission = commissionInfo.couponCommission; $.price = priceInfo.lowestPrice; @@ -254,7 +243,6 @@ async function notice() { $.desc = $.desc || ""; if (/u\.jd\.com/.test($.shortUrl)) { $.desc += `预计返利: ¥${(($.price * $.commissionShare) / 100).toFixed(2)} ${$.commissionShare}%`; - if ($.appType === "jdtj") { $.jumpUrl = `openjdlite://virtual?params=${encodeURIComponent('{"category":"jump","des":"m","url":"' + $.shortUrl + '"}')}`; } else { @@ -263,43 +251,26 @@ async function notice() { $.opts["$open"] = $.jumpUrl; } else { $.desc += "\n预计返利: 暂无"; - $.log("无佣金商品"); } if ($.skuImg) $.opts["$media"] = $.skuImg; $.msg($.title, $.subt, $.desc, $.opts); } function buildPriceTableHTML(priceList, productId, spbh) { - const rows = (priceList || []) - .map((item) => { + const rows = (priceList || []).map(item => { let { Name: name, Date: date, Price: price = "", Difference: diff = "" } = item; - date = - name === "当前到手价" - ? typeof $.time === "function" - ? $.time("yyyy-MM-dd") - : new Date().toISOString().split("T")[0] - : date || "-"; + date = name === "当前到手价" ? (typeof $.time === "function" ? $.time("yyyy-MM-dd") : new Date().toISOString().split("T")[0]) : date || "-"; let diffClass = diff.startsWith("↑") ? "up" : diff.startsWith("↓") ? "down" : ""; return `
`; - }) - .join(""); - - const chartData = (priceList || []) - .filter((i) => i.Price && !isNaN(parseFloat(String(i.Price).replace(/[¥\s]/g, "")))) - .map((i) => ({ - date: - i.Name === "当前到手价" - ? typeof $.time === "function" - ? $.time("yyyy-MM-dd") - : new Date().toISOString().split("T")[0] - : i.Date || "-", - price: parseFloat(String(i.Price).replace(/[¥\s]/g, "")), - })) - .sort((a, b) => new Date(a.date) - new Date(b.date)); + }).join(""); - const labels = chartData.map((i) => i.date); - const prices = chartData.map((i) => i.price); + const chartData = (priceList || []).filter(i => i.Price && !isNaN(parseFloat(String(i.Price).replace(/[¥\s]/g, "")))).map(i => ({ + date: i.Name === "当前到手价" ? (typeof $.time === "function" ? $.time("yyyy-MM-dd") : new Date().toISOString().split("T")[0]) : i.Date || "-", + price: parseFloat(String(i.Price).replace(/[¥\s]/g, "")), + })).sort((a, b) => new Date(a.date) - new Date(b.date)); + const labels = chartData.map(i => i.date); + const prices = chartData.map(i => i.price); const sProductId = JSON.stringify(productId); return ` @@ -311,185 +282,70 @@ function buildPriceTableHTML(priceList, productId, spbh) {
${name}${date}${price}${diff}