├── CK_WxPusherUid.json ├── JS_USER_AGENTS.js ├── ModScript ├── jd_gua_MMdou_Mod.js ├── jd_insight_Mod.js └── jd_speed_sign_new.js ├── NoUsed ├── NoUsed_jd_DailyBonus_Mod.js ├── NoUsed_jd_big_winner_Mod.js ├── NoUsed_jd_cash_Mod.js ├── NoUsed_jd_dreamFactory_Mod.js ├── NoUsed_jd_fanli_Mod.js ├── NoUsed_jd_fruit_Mod.js ├── NoUsed_jd_gua_cleancart.js ├── NoUsed_jd_health_Mod.js ├── NoUsed_jd_jdfactory_Mod.js ├── NoUsed_jd_joy_park_Mod.js ├── NoUsed_jd_joy_park_task_Mod.js ├── NoUsed_jd_joy_reward_Mod.js ├── NoUsed_jd_medal_Mod.js ├── NoUsed_jd_pet_Mod.js ├── NoUsed_jd_plantBean_Mod.js ├── NoUsed_jd_priceProtect_Mod.js ├── NoUsed_jd_sgmh_Mod.js ├── NoUsed_jd_speed_sign_Part1.js ├── NoUsed_jd_speed_sign_Part2.js ├── NoUsed_jd_speed_sign_Part3.js ├── NoUsed_jd_speed_signfree_Mod.js └── NoUsed_jd_syj_Mod.js ├── README.md ├── USER_AGENTS.js ├── bot_jd_CkSeq.js ├── bot_jd_bean_change.js ├── bot_jd_bean_change_QL.js ├── bot_jd_bean_info.js ├── bot_jd_bean_info_QL.js ├── jdCookie.js ├── jd_CheckCK.js ├── jd_CkSeq.js ├── jd_UpdateUIDtoRemark.js ├── jd_bean_change.js ├── jd_notify.js ├── ql.js ├── sendNotify.js └── utils ├── JDJRValidator_Pure.js └── USER_AGENTS.js /CK_WxPusherUid.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "pt_pin": "ptpin1", 4 | "Uid": "UID_AAAAAAAAAAAA" 5 | }, 6 | { 7 | "pt_pin": "ptpin2", 8 | "Uid": "UID_BBBBBBBBBB" 9 | }, 10 | { 11 | "pt_pin": "ptpin3", 12 | "Uid": "UID_CCCCCCCCC" 13 | } 14 | ] -------------------------------------------------------------------------------- /ModScript/jd_insight_Mod.js: -------------------------------------------------------------------------------- 1 | /* 2 | cron "35 9,15,20 * * *" jd_insight.js, tag:京洞察问卷通知 3 | */ 4 | 5 | const $ = new Env('京洞察问卷通知'); 6 | const notify = $.isNode() ? require('./sendNotify') : ''; 7 | //Node.js用户请在jdCookie.js处填写京东ck; 8 | const jdCookieNode = $.isNode() ? require('./jdCookie.js') : ''; 9 | //IOS等用户直接用NobyDa的jd cookie 10 | let cookiesArr = [], 11 | cookie = ''; 12 | let allnotify=""; 13 | let WP_APP_TOKEN_ONE = ""; 14 | 15 | if ($.isNode()) { 16 | if (process.env.WP_APP_TOKEN_ONE) { 17 | WP_APP_TOKEN_ONE = process.env.WP_APP_TOKEN_ONE; 18 | } 19 | 20 | Object.keys(jdCookieNode) 21 | .forEach((item) => { 22 | cookiesArr.push(jdCookieNode[item]) 23 | }) 24 | if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => {}; 25 | } else { 26 | cookiesArr = [$.getdata('CookieJD'), $.getdata('CookieJD2'), ...jsonParse($.getdata('CookiesJD') || "[]") 27 | .map(item => item.cookie) 28 | ].filter(item => !!item); 29 | } 30 | 31 | !(async () => { 32 | if (!cookiesArr[0]) { 33 | $.msg($.name, '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/bean/signIndex.action', { 34 | "open-url": "https://bean.m.jd.com/bean/signIndex.action" 35 | }); 36 | return; 37 | } 38 | UUID = getUUID('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); 39 | for (let i = 0; i < cookiesArr.length; i++) { 40 | UA = `jdapp;iPhone;10.0.8;14.6;${UUID};network/wifi;JDEbook/openapp.jdreader;model/iPhone9,2;addressid/2214222493;appBuild/168841;jdSupportDarkMode/0;Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16E158;supportJDSHWK/1`; 41 | if (cookiesArr[i]) { 42 | cookie = cookiesArr[i]; 43 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 44 | $.index = i + 1; 45 | $.isLogin = true; 46 | $.nickName = ''; 47 | $.maxPage = '1'; 48 | message = ''; 49 | await TotalBean(); 50 | console.log(`******开始查询【京东账号${$.index}】${$.nickName || $.UserName}*********\n`); 51 | if (!$.isLogin) { 52 | $.msg($.name, `【提示】cookie已失效`, `京东账号${$.index} ${$.nickName || $.UserName}\n请重新登录获取\nhttps://bean.m.jd.com/bean/signIndex.action`, { 53 | "open-url": "https://bean.m.jd.com/bean/signIndex.action" 54 | }); 55 | 56 | if ($.isNode()) { 57 | await notify.sendNotify(`${$.name}cookie已失效 - ${$.UserName}`, `京东账号${$.index} ${$.UserName}\n请重新登录获取cookie`); 58 | } 59 | continue 60 | } 61 | await main() 62 | } 63 | } 64 | 65 | if ($.isNode() && allnotify) { 66 | await notify.sendNotify(`${$.name}`, allnotify); 67 | } 68 | 69 | })() 70 | .catch((e) => { 71 | $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') 72 | }) 73 | .finally(() => { 74 | $.done(); 75 | }) 76 | 77 | async function main() { 78 | console.log(`开始获取京洞察调研列表...\n`) 79 | let data= await GetSurveyList(); 80 | if(data.result){ 81 | let list=data.messages.list 82 | if(list.length>0){ 83 | let AccTitle=`账号${$.index} ${$.nickName || $.UserName} `; 84 | let msg = AccTitle+`共${list.length}个类型调查问卷\n`; 85 | for (let index = 0; index < list.length; index++) { 86 | const item = list[index].surveyList; 87 | //msg += `类型:${list[index].type}\n`; 88 | for (let index = 0; index < item.length; index++) { 89 | let surveyItem = item[index]; 90 | let title = surveyItem.title 91 | let subTitle = surveyItem.subTitle 92 | let answerUrl = surveyItem.answerUrl 93 | msg += `${index+1}.【${title}】 ${subTitle}\n点击这里开启问卷\n` 94 | } 95 | } 96 | if ($.isNode() && WP_APP_TOKEN_ONE) { 97 | await notify.sendNotifybyWxPucher("京洞察问卷通知", msg, `${$.UserName}`,'\n\n本通知 By ccwav Mod',"您有可以做的调查问卷"); 98 | } 99 | allnotify+=msg 100 | } 101 | }else{ 102 | $.log('当前账户没有京调研问卷') 103 | } 104 | } 105 | 106 | function random(min, max) { 107 | return parseInt((max - min) * Math.random()); 108 | } 109 | // prettier-ignore 110 | function getUUID(x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", t = 0) { 111 | return x.replace(/[xy]/g, function(x) { 112 | var r = 16 * Math.random() | 0, 113 | n = "x" == x ? r : 3 & r | 8; 114 | return uuid = t ? n.toString(36) 115 | .toUpperCase() : n.toString(36), uuid 116 | }) 117 | } 118 | 119 | function GetSurveyList() { 120 | const options = { 121 | "url": 'https://answer.jd.com/community/survey/list', 122 | "headers": { 123 | "Cookie": cookie, 124 | "User-Agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1" 125 | } 126 | }; 127 | return new Promise(resolve => { 128 | $.get(options, async (err, resp, data) => { 129 | try { 130 | if (err) { 131 | console.log(err); 132 | console.log(`${$.name} API请求失败,请检查网路重试`) 133 | } else { 134 | //console.log(data); 135 | if (data) { 136 | data = JSON.parse(data); 137 | } else { 138 | console.log("没有返回数据") 139 | } 140 | } 141 | } catch (e) { 142 | $.logErr(e, resp) 143 | } finally { 144 | resolve(data); 145 | } 146 | }) 147 | }) 148 | } 149 | 150 | function TotalBean() { 151 | return new Promise(async e => { 152 | const n = { 153 | url: "https://wq.jd.com/user_new/info/GetJDUserInfoUnion?sceneval=2", 154 | headers: { 155 | Host: "wq.jd.com", 156 | Accept: "*/*", 157 | Connection: "keep-alive", 158 | Cookie: cookie, 159 | "User-Agent": UA, 160 | "Accept-Language": "zh-cn", 161 | Referer: "https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&", 162 | "Accept-Encoding": "gzip, deflate, br" 163 | } 164 | }; 165 | $.get(n, (n, o, a) => { 166 | try { 167 | if (n) $.logErr(n); 168 | else if (a) { 169 | if (1001 === (a = JSON.parse(a))["retcode"]) return void($.isLogin = !1); 170 | 0 === a["retcode"] && a.data && a.data.hasOwnProperty("userInfo") && ($.nickName = a.data.userInfo.baseInfo.nickname), 0 === a["retcode"] && a.data && a.data["assetInfo"] && ($.beanCount = a.data && a.data["assetInfo"]["beanNum"]) 171 | } else console.log("京东服务器返回空数据") 172 | } catch (e) { 173 | $.logErr(e) 174 | } finally { 175 | e() 176 | } 177 | }) 178 | }) 179 | } 180 | 181 | function Env(t, e) { 182 | "undefined" != typeof process && JSON.stringify(process.env) 183 | .indexOf("GITHUB") > -1 && process.exit(0); 184 | class s { 185 | constructor(t) { 186 | this.env = t 187 | } 188 | send(t, e = "GET") { 189 | t = "string" == typeof t ? { 190 | url: t 191 | } : t; 192 | let s = this.get; 193 | return "POST" === e && (s = this.post), new Promise((e, i) => { 194 | s.call(this, t, (t, s, r) => { 195 | t ? i(t) : e(s) 196 | }) 197 | }) 198 | } 199 | get(t) { 200 | return this.send.call(this.env, t) 201 | } 202 | post(t) { 203 | return this.send.call(this.env, t, "POST") 204 | } 205 | } 206 | return new class { 207 | constructor(t, e) { 208 | 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.startTime = (new Date) 209 | .getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) 210 | } 211 | isNode() { 212 | return "undefined" != typeof module && !!module.exports 213 | } 214 | isQuanX() { 215 | return "undefined" != typeof $task 216 | } 217 | isSurge() { 218 | return "undefined" != typeof $httpClient && "undefined" == typeof $loon 219 | } 220 | isLoon() { 221 | return "undefined" != typeof $loon 222 | } 223 | toObj(t, e = null) { 224 | try { 225 | return JSON.parse(t) 226 | } catch { 227 | return e 228 | } 229 | } 230 | toStr(t, e = null) { 231 | try { 232 | return JSON.stringify(t) 233 | } catch { 234 | return e 235 | } 236 | } 237 | getjson(t, e) { 238 | let s = e; 239 | const i = this.getdata(t); 240 | if (i) try { 241 | s = JSON.parse(this.getdata(t)) 242 | } catch {} 243 | return s 244 | } 245 | setjson(t, e) { 246 | try { 247 | return this.setdata(JSON.stringify(t), e) 248 | } catch { 249 | return !1 250 | } 251 | } 252 | getScript(t) { 253 | return new Promise(e => { 254 | this.get({ 255 | url: t 256 | }, (t, s, i) => e(i)) 257 | }) 258 | } 259 | runScript(t, e) { 260 | return new Promise(s => { 261 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 262 | i = i ? i.replace(/\n/g, "") 263 | .trim() : i; 264 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 265 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 266 | const [o, h] = i.split("@"), n = { 267 | url: `http://${h}/v1/scripting/evaluate`, 268 | body: { 269 | script_text: t, 270 | mock_type: "cron", 271 | timeout: r 272 | }, 273 | headers: { 274 | "X-Key": o, 275 | Accept: "*/*" 276 | } 277 | }; 278 | this.post(n, (t, e, i) => s(i)) 279 | }) 280 | .catch(t => this.logErr(t)) 281 | } 282 | loaddata() { 283 | if (!this.isNode()) return {}; { 284 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 285 | const t = this.path.resolve(this.dataFile), 286 | e = this.path.resolve(process.cwd(), this.dataFile), 287 | s = this.fs.existsSync(t), 288 | i = !s && this.fs.existsSync(e); 289 | if (!s && !i) return {}; { 290 | const i = s ? t : e; 291 | try { 292 | return JSON.parse(this.fs.readFileSync(i)) 293 | } catch (t) { 294 | return {} 295 | } 296 | } 297 | } 298 | } 299 | writedata() { 300 | if (this.isNode()) { 301 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 302 | const t = this.path.resolve(this.dataFile), 303 | e = this.path.resolve(process.cwd(), this.dataFile), 304 | s = this.fs.existsSync(t), 305 | i = !s && this.fs.existsSync(e), 306 | r = JSON.stringify(this.data); 307 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 308 | } 309 | } 310 | lodash_get(t, e, s) { 311 | const i = e.replace(/\[(\d+)\]/g, ".$1") 312 | .split("."); 313 | let r = t; 314 | for (const t of i) 315 | if (r = Object(r)[t], void 0 === r) return s; 316 | return r 317 | } 318 | lodash_set(t, e, s) { 319 | return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString() 320 | .match(/[^.[\]]+/g) || []), e.slice(0, -1) 321 | .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) 322 | } 323 | getdata(t) { 324 | let e = this.getval(t); 325 | if (/^@/.test(t)) { 326 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; 327 | if (r) try { 328 | const t = JSON.parse(r); 329 | e = t ? this.lodash_get(t, i, "") : e 330 | } catch (t) { 331 | e = "" 332 | } 333 | } 334 | return e 335 | } 336 | setdata(t, e) { 337 | let s = !1; 338 | if (/^@/.test(e)) { 339 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; 340 | try { 341 | const e = JSON.parse(h); 342 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) 343 | } catch (e) { 344 | const o = {}; 345 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) 346 | } 347 | } else s = this.setval(t, e); 348 | return s 349 | } 350 | getval(t) { 351 | return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null 352 | } 353 | setval(t, e) { 354 | return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null 355 | } 356 | initGotEnv(t) { 357 | 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 : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) 358 | } 359 | get(t, e = (() => {})) { 360 | t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { 361 | "X-Surge-Skip-Scripting": !1 362 | })), $httpClient.get(t, (t, s, i) => { 363 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 364 | })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 365 | hints: !1 366 | })), $task.fetch(t) 367 | .then(t => { 368 | const { 369 | statusCode: s, 370 | statusCode: i, 371 | headers: r, 372 | body: o 373 | } = t; 374 | e(null, { 375 | status: s, 376 | statusCode: i, 377 | headers: r, 378 | body: o 379 | }, o) 380 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t) 381 | .on("redirect", (t, e) => { 382 | try { 383 | if (t.headers["set-cookie"]) { 384 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse) 385 | .toString(); 386 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar 387 | } 388 | } catch (t) { 389 | this.logErr(t) 390 | } 391 | }) 392 | .then(t => { 393 | const { 394 | statusCode: s, 395 | statusCode: i, 396 | headers: r, 397 | body: o 398 | } = t; 399 | e(null, { 400 | status: s, 401 | statusCode: i, 402 | headers: r, 403 | body: o 404 | }, o) 405 | }, t => { 406 | const { 407 | message: s, 408 | response: i 409 | } = t; 410 | e(s, i, i && i.body) 411 | })) 412 | } 413 | post(t, e = (() => {})) { 414 | if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { 415 | "X-Surge-Skip-Scripting": !1 416 | })), $httpClient.post(t, (t, s, i) => { 417 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 418 | }); 419 | else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 420 | hints: !1 421 | })), $task.fetch(t) 422 | .then(t => { 423 | const { 424 | statusCode: s, 425 | statusCode: i, 426 | headers: r, 427 | body: o 428 | } = t; 429 | e(null, { 430 | status: s, 431 | statusCode: i, 432 | headers: r, 433 | body: o 434 | }, o) 435 | }, t => e(t)); 436 | else if (this.isNode()) { 437 | this.initGotEnv(t); 438 | const { 439 | url: s, 440 | ...i 441 | } = t; 442 | this.got.post(s, i) 443 | .then(t => { 444 | const { 445 | statusCode: s, 446 | statusCode: i, 447 | headers: r, 448 | body: o 449 | } = t; 450 | e(null, { 451 | status: s, 452 | statusCode: i, 453 | headers: r, 454 | body: o 455 | }, o) 456 | }, t => { 457 | const { 458 | message: s, 459 | response: i 460 | } = t; 461 | e(s, i, i && i.body) 462 | }) 463 | } 464 | } 465 | time(t, e = null) { 466 | const s = e ? new Date(e) : new Date; 467 | let i = { 468 | "M+": s.getMonth() + 1, 469 | "d+": s.getDate(), 470 | "H+": s.getHours(), 471 | "m+": s.getMinutes(), 472 | "s+": s.getSeconds(), 473 | "q+": Math.floor((s.getMonth() + 3) / 3), 474 | S: s.getMilliseconds() 475 | }; 476 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "") 477 | .substr(4 - RegExp.$1.length))); 478 | for (let e in i) new RegExp("(" + e + ")") 479 | .test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]) 480 | .substr(("" + i[e]) 481 | .length))); 482 | return t 483 | } 484 | msg(e = t, s = "", i = "", r) { 485 | const o = t => { 486 | if (!t) return t; 487 | if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { 488 | "open-url": t 489 | } : this.isSurge() ? { 490 | url: t 491 | } : void 0; 492 | if ("object" == typeof t) { 493 | if (this.isLoon()) { 494 | let e = t.openUrl || t.url || t["open-url"], 495 | s = t.mediaUrl || t["media-url"]; 496 | return { 497 | openUrl: e, 498 | mediaUrl: s 499 | } 500 | } 501 | if (this.isQuanX()) { 502 | let e = t["open-url"] || t.url || t.openUrl, 503 | s = t["media-url"] || t.mediaUrl; 504 | return { 505 | "open-url": e, 506 | "media-url": s 507 | } 508 | } 509 | if (this.isSurge()) { 510 | let e = t.url || t.openUrl || t["open-url"]; 511 | return { 512 | url: e 513 | } 514 | } 515 | } 516 | }; 517 | if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { 518 | let t = ["", "==============📣系统通知📣=============="]; 519 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) 520 | } 521 | } 522 | log(...t) { 523 | t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) 524 | } 525 | logErr(t, e) { 526 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 527 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 528 | } 529 | wait(t) { 530 | return new Promise(e => setTimeout(e, t)) 531 | } 532 | done(t = {}) { 533 | const e = (new Date) 534 | .getTime(), 535 | s = (e - this.startTime) / 1e3; 536 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 537 | } 538 | }(t, e) 539 | } -------------------------------------------------------------------------------- /NoUsed/NoUsed_jd_gua_cleancart.js: -------------------------------------------------------------------------------- 1 | /* 2 | 清空购物车 3 | 更新时间:2022-08-12 4 | 因其他脚本会加入商品到购物车,故此脚本用来清空购物车 5 | 包括预售 6 | 需要算法支持 7 | 默认:不执行 如需要请添加环境变量 8 | gua_cleancart_Run="true" 9 | 10 | —————————————— 11 | 1.@&@ 前面加数字 指定账号pin 12 | 如果有中文请填写中文 13 | 2.|-| 账号之间隔开 14 | 3.英文大小写请填清楚 15 | 4.优先匹配账号再匹配* 16 | 5.定义不清空的[商品]名称支持模糊匹配 17 | 6.pin@&@ 👉 指定账号(后面添加商品 前面账号[pin] *表示所有账号 18 | 7.|-| 👉 账号之间隔开 19 | —————————————— 20 | 21 | 商品名称规则 22 | ——————gua_cleancart_products———————— 23 | pin2@&@商品1,商品2👉该pin这几个商品名不清空 24 | pin5@&@👉该pin全清 25 | pin3@&@不清空👉该pin不清空 26 | *@&@不清空👉所有账号不请空 27 | *@&@👉所有账号清空 28 | 29 | 优先匹配账号再匹配* 30 | |-| 👉 账号之间隔开 31 | 有填帐号pin则*不适配 32 | —————————————— 33 | 如果有不清空的一定要加上"*@&@不清空" 34 | 防止没指定的账号购物车全清空 35 | 36 | */ 37 | let jdSignUrl = 'https://api.nolanstore.cc/sign' 38 | if (process.env.SIGNURL) 39 | jdSignUrl = process.env.SIGNURL; 40 | let cleancartRun = 'false' 41 | let cleancartProducts = '' 42 | const $ = new Env('清空购物车'); 43 | const jdCookieNode = $.isNode() ? require('./jdCookie.js') : ''; 44 | const notify = $.isNode() ? require('./sendNotify') : ''; 45 | //IOS等用户直接用NobyDa的jd cookie 46 | let cookiesArr = [], 47 | cookie = ''; 48 | if ($.isNode()) { 49 | Object.keys(jdCookieNode).forEach((item) => { 50 | cookiesArr.push(jdCookieNode[item]) 51 | }) 52 | if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => {}; 53 | } else { 54 | cookiesArr = [$.getdata('CookieJD'), $.getdata('CookieJD2'), ...jsonParse($.getdata('CookiesJD') || "[]").map(item => item.cookie)].filter(item => !!item); 55 | } 56 | 57 | message = '' 58 | 59 | cleancartRun = $.isNode() ? (process.env.gua_cleancart_Run ? process.env.gua_cleancart_Run : `${cleancartRun}`) : ($.getdata('gua_cleancart_Run') ? $.getdata('gua_cleancart_Run') : `${cleancartRun}`); 60 | 61 | cleancartProducts = $.isNode() ? (process.env.gua_cleancart_products ? process.env.gua_cleancart_products : `${cleancartProducts}`) : ($.getdata('gua_cleancart_products') ? $.getdata('gua_cleancart_products') : `${cleancartProducts}`); 62 | 63 | let productsArr = [] 64 | let cleancartProductsAll = [] 65 | for (let i of cleancartProducts && cleancartProducts.split('|-|')) { 66 | productsArr.push(i) 67 | } 68 | for (let i of cleancartProducts && cleancartProducts.split('|-|')) { 69 | productsArr.push(i) 70 | } 71 | for (let i in productsArr) { 72 | if(productsArr[i].indexOf('@&@') > -1){ 73 | let arr = productsArr[i].split('@&@') 74 | cleancartProductsAll[arr[0]] = arr[1].split(',') 75 | } 76 | } 77 | 78 | !(async () => { 79 | if (!cookiesArr[0]) { 80 | $.msg($.name, '【提示】请先获取cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/', { 81 | "open-url": "https://bean.m.jd.com/" 82 | }); 83 | return; 84 | } 85 | if(cleancartRun !== 'true'){ 86 | console.log('脚本停止\n请添加环境变量[gua_cleancart_Run]为"true"') 87 | return 88 | } 89 | if(!cleancartProducts){ 90 | console.log('脚本停止\n请添加环境变量[gua_cleancart_products]\n清空商品\n内容规则看脚本文件') 91 | return 92 | } 93 | if(jdSignUrl.indexOf("://jd.smiek.tk/") > -1) { 94 | return 95 | } 96 | $.out = false 97 | console.log('\n==此脚本使用的签名接口来自Nolan提供的公益服务,大伙记得给他点赞=='); 98 | for (let i = 0; i < cookiesArr.length; i++) { 99 | cookie = cookiesArr[i]; 100 | if (cookie) { 101 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]) 102 | $.index = i + 1; 103 | console.log(`\n******开始【京东账号${$.index}】${$.nickName || $.UserName}*********\n`); 104 | if(cleancartProductsAll[$.UserName]){ 105 | $.cleancartProductsArr = cleancartProductsAll[$.UserName] 106 | }else if(cleancartProductsAll["*"]){ 107 | $.cleancartProductsArr = cleancartProductsAll["*"] 108 | }else $.cleancartProductsArr = false 109 | if($.cleancartProductsArr) console.log($.cleancartProductsArr) 110 | await run(); 111 | if($.out) break 112 | } 113 | } 114 | if(message){ 115 | $.msg($.name, ``, `${message}`); 116 | if ($.isNode()){ 117 | await notify.sendNotify(`${$.name}`, `${message}`); 118 | } 119 | } 120 | })() 121 | .catch((e) => $.logErr(e)) 122 | .finally(() => $.done()) 123 | 124 | async function run(){ 125 | try{ 126 | let msg = '' 127 | let signBody = `{"homeWishListUserFlag":"1","userType":"0","updateTag":true,"showPlusEntry":"2","hitNewUIStatus":"1","cvhv":"049591","cartuuid":"hjudwgohxzVu96krv/T6Hg==","adid":""}` 128 | let body = await jdSign('cartClearQuery', signBody) 129 | if($.out) return 130 | if(!body){ 131 | console.log('获取不到算法') 132 | return 133 | } 134 | let data = await jdApi('cartClearQuery',body) 135 | let res = $.toObj(data,data); 136 | if(typeof res == 'object' && res){ 137 | if(res.resultCode == 0){ 138 | if(!res.clearCartInfo || !res.subTitle){ 139 | msg += `${res.mainTitle}\n` 140 | console.log(res.mainTitle) 141 | }else{ 142 | let num = 0 143 | if(res.subTitle){ 144 | num = res.subTitle.match(/共(\d+)件商品/).length > 0 && res.subTitle.match(/共(\d+)件商品/)[1] || 0 145 | msg += res.subTitle + "\n" 146 | console.log(res.subTitle) 147 | } 148 | // console.log(`共${num}件商品`) 149 | if(num != 0){ 150 | let operations = [] 151 | let operNum = 0 152 | for(let a of res.clearCartInfo || {}){ 153 | // console.log(a.groupName) 154 | // if(a.groupName.indexOf('7天前加入购物车') > -1){ 155 | for(let s of a.groupDetails || []){ 156 | if(toSDS(s.name) || num>130){ 157 | // console.log(s.unusable,s.skuUuid,s.name) 158 | operNum += s.clearSkus && s.clearSkus.length || 1; 159 | operations.push({ 160 | "itemType": s.itemType+"", 161 | "suitType": s.suitType, 162 | "skuUuid": s.skuUuid+"", 163 | "itemId": s.itemId || s.skuId, 164 | "useUuid": typeof s.useUuid !== 'undefined' && s.useUuid || false 165 | }) 166 | } 167 | } 168 | // } 169 | } 170 | console.log(`准备清空${operNum}件商品`) 171 | if(operations.length == 0){ 172 | console.log(`清空${operNum}件商品|没有找到要清空的商品`) 173 | msg += `清空${operNum}件商品|没有找到要清空的商品\n` 174 | }else{ 175 | let clearBody = `{"homeWishListUserFlag":"1","userType":"0","updateTag":false,"showPlusEntry":"2","hitNewUIStatus":"1","cvhv":"049591","cartuuid":"hjudwgohxzVu96krv/T6Hg==","operations":${$.toStr(operations,operations)},"adid":"","coord_type":"0"}` 176 | clearBody = await jdSign('cartClearRemove', clearBody) 177 | if($.out) return 178 | if(!clearBody){ 179 | console.log('获取不到算法') 180 | }else{ 181 | let clearData = await jdApi('cartClearRemove',clearBody) 182 | let clearRes = $.toObj(clearData,clearData); 183 | if(typeof clearRes == 'object'){ 184 | if(clearRes.resultCode == 0) { 185 | msg += `清空${operNum}件商品|✅\n` 186 | console.log(`清空${operNum}件商品|✅\n`) 187 | }else if(clearRes.mainTitle){ 188 | msg += `清空${operNum}件商品|${clearRes.mainTitle}\n` 189 | console.log(`清空${operNum}件商品|${clearRes.mainTitle}\n`) 190 | }else{ 191 | msg += `清空${operNum}件商品|❌\n` 192 | console.log(`清空${operNum}件商品|❌\n`) 193 | console.log(clearData) 194 | } 195 | }else{ 196 | msg += `清空${operNum}件商品|❌\n` 197 | console.log(`清空${operNum}件商品|❌\n`) 198 | console.log(clearData) 199 | } 200 | } 201 | } 202 | }else if(res.mainTitle){ 203 | msg += `${res.mainTitle}\n` 204 | console.log(res.mainTitle) 205 | }else{ 206 | msg += `未识别到购物车有商品\n` 207 | console.log(data) 208 | } 209 | } 210 | }else{ 211 | console.log(data) 212 | } 213 | }else{ 214 | console.log(data) 215 | } 216 | if(msg){ 217 | message += `【京东账号${$.index}】${$.nickName || $.UserName}\n${msg}\n` 218 | } 219 | await $.wait(parseInt(Math.random() * 2000 + 2000, 10)) 220 | }catch(e){ 221 | console.log(e) 222 | } 223 | } 224 | function toSDS(name){ 225 | let res = true 226 | if($.cleancartProductsArr === false) return false 227 | for(let t of $.cleancartProductsArr || []){ 228 | if(t && name.indexOf(t) > -1 || t == '不清空'){ 229 | res = false 230 | break 231 | } 232 | } 233 | return res 234 | } 235 | function jdApi(functionId,body) { 236 | if(!functionId || !body) return 237 | return new Promise(resolve => { 238 | $.post(taskPostUrl(`/client.action?functionId=${functionId}`, body), async (err, resp, data) => { 239 | try { 240 | if (err) { 241 | console.log(`${$.toStr(err)}`) 242 | console.log(`${$.name} API请求失败,请检查网路重试`) 243 | } else { 244 | let res = $.toObj(data,data); 245 | if(typeof res == 'object'){ 246 | if(res.mainTitle) console.log(res.mainTitle) 247 | if(res.resultCode == 0){ 248 | resolve(res); 249 | } 250 | } 251 | } 252 | } catch (e) { 253 | $.logErr(e, resp) 254 | } finally { 255 | resolve(''); 256 | } 257 | }) 258 | }) 259 | } 260 | 261 | function jdSign(fn, body) { 262 | let sign = ''; 263 | let flag = false; 264 | try { 265 | const fs = require('fs'); 266 | if (fs.existsSync('./gua_encryption_sign.js')) { 267 | const encryptionSign = require('./gua_encryption_sign'); 268 | sign = encryptionSign.getSign(fn, body) 269 | } else { 270 | flag = true 271 | } 272 | sign = sign.data && sign.data.sign && sign.data.sign || '' 273 | } catch (e) { 274 | flag = true 275 | } 276 | if (!flag) 277 | return sign 278 | if (!jdSignUrl.match(/^https?:\/\//)) { 279 | console.log('请填写算法url') 280 | $.out = true 281 | return '' 282 | } 283 | return new Promise((resolve) => { 284 | let url = { 285 | url: jdSignUrl, 286 | body: `{"fn":"${fn}","body":${body}}`, 287 | followRedirect: false, 288 | headers: { 289 | 'Accept': '*/*', 290 | "accept-encoding": "gzip, deflate, br", 291 | 'Content-Type': 'application/json' 292 | }, 293 | timeout: 30000 294 | } 295 | $.post(url, async(err, resp, data) => { 296 | try { 297 | data = JSON.parse(data); 298 | if (data && data.body) { 299 | if (data.body) 300 | sign = data.body || ''; 301 | if (sign != '') 302 | resolve(sign); 303 | else 304 | console.log("签名获取失败."); 305 | } else { 306 | console.log("签名获取失败."); 307 | } 308 | } catch (e) { 309 | $.logErr(e, resp); 310 | } 311 | finally { 312 | resolve('') 313 | } 314 | }) 315 | }) 316 | } 317 | 318 | 319 | function taskPostUrl(url, body) { 320 | return { 321 | url: `https://api.m.jd.com${url}`, 322 | body: body, 323 | headers: { 324 | "Accept": "*/*", 325 | "Accept-Language": "zh-cn", 326 | "Accept-Encoding": "gzip, deflate, br", 327 | "Connection": "keep-alive", 328 | "Content-Type": "application/x-www-form-urlencoded", 329 | 'Cookie': `${cookie}`, 330 | "Host": "api.m.jd.com", 331 | "User-Agent": "JD4iPhone/167853 (iPhone; iOS; Scale/2.00)" , 332 | } 333 | } 334 | } 335 | 336 | function randomString(e) { 337 | e = e || 32; 338 | let t = "abcdef0123456789", a = t.length, n = ""; 339 | for (i = 0; i < e; i++) 340 | n += t.charAt(Math.floor(Math.random() * a)); 341 | return n 342 | } 343 | 344 | function jsonParse(str) { 345 | if (typeof str == "string") { 346 | try { 347 | return JSON.parse(str); 348 | } catch (e) { 349 | console.log(e); 350 | $.msg($.name, '', '请勿随意在BoxJs输入框修改内容\n建议通过脚本去获取cookie') 351 | return []; 352 | } 353 | } 354 | } 355 | 356 | // prettier-ignore 357 | function Env(t,e){"undefined"!=typeof process&&JSON.stringify(process.env).indexOf("GITHUB")>-1&&process.exit(0);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,r)=>{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.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.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)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 r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),n={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};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),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==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),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):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:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(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),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(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:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}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}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!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)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} 358 | 359 | 360 | -------------------------------------------------------------------------------- /NoUsed/NoUsed_jd_priceProtect_Mod.js: -------------------------------------------------------------------------------- 1 | /* 2 | cron "41 11 7,14,21,28 * *" jd_priceProtect_Mod.js, tag:京东价保一对一推送版 3 | */ 4 | //程序员复制粘贴了小小的代码一顿骚操作后加了一对一推送 5 | //原地址: https://raw.githubusercontent.com/Aaron-lv/sync/jd_scripts/jd_price.js 6 | 7 | const $ = new Env('京东价保一对一推送版'); 8 | const notify = $.isNode() ? require('./sendNotify') : ''; 9 | //Node.js用户请在jdCookie.js处填写京东ck; 10 | const jdCookieNode = $.isNode() ? require('./jdCookie.js') : ''; 11 | const jsdom = $.isNode() ? require('jsdom') : ''; 12 | //IOS等用户直接用NobyDa的jd cookie 13 | let cookiesArr = [], cookie = '', message, allMessage = ''; 14 | if ($.isNode()) { 15 | Object.keys(jdCookieNode).forEach((item) => { 16 | cookiesArr.push(jdCookieNode[item]) 17 | }) 18 | if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => {}; 19 | } else { 20 | cookiesArr = [$.getdata('CookieJD'), $.getdata('CookieJD2'), ...jsonParse($.getdata('CookiesJD') || "[]").map(item => item.cookie)].filter(item => !!item); 21 | } 22 | const JD_API_HOST = 'https://api.m.jd.com/'; 23 | 24 | let WP_APP_TOKEN_ONE = ""; 25 | let strmessagebyone=""; 26 | if ($.isNode() && process.env.WP_APP_TOKEN_ONE) { 27 | WP_APP_TOKEN_ONE = process.env.WP_APP_TOKEN_ONE; 28 | } 29 | 30 | !(async () => { 31 | if (!cookiesArr[0]) { 32 | $.msg($.name, '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/bean/signIndex.action', {"open-url": "https://bean.m.jd.com/bean/signIndex.action"}); 33 | return; 34 | } 35 | await jstoken(); 36 | for (let i = 0; i < cookiesArr.length; i++) { 37 | if (cookiesArr[i]) { 38 | cookie = cookiesArr[i]; 39 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]) 40 | $.index = i + 1; 41 | $.isLogin = true; 42 | $.nickName = ''; 43 | $.token = '' 44 | message = ''; 45 | await TotalBean(); 46 | console.log(`\n******开始【京东账号${$.index}】${$.nickName || $.UserName}*********\n`); 47 | if (!$.isLogin) { 48 | $.msg($.name, `【提示】cookie已失效`, `京东账号${$.index} ${$.nickName || $.UserName}\n请重新登录获取\nhttps://bean.m.jd.com/bean/signIndex.action`, {"open-url": "https://bean.m.jd.com/bean/signIndex.action"}); 49 | 50 | if ($.isNode()) { 51 | await notify.sendNotify(`${$.name}cookie已失效 - ${$.UserName}`, `京东账号${$.index} ${$.UserName}\n请重新登录获取cookie`); 52 | } 53 | continue 54 | } 55 | strmessagebyone="" 56 | await price() 57 | if (strmessagebyone && $.isNode() && WP_APP_TOKEN_ONE) { 58 | await notify.sendNotifybyWxPucher("京东保价",strmessagebyone, `${$.UserName}`); 59 | } 60 | await $.wait(2000) 61 | } 62 | } 63 | if (allMessage) { 64 | if ($.isNode()) await notify.sendNotify(`${$.name}`, `${allMessage}`); 65 | } 66 | })() 67 | .catch((e) => { 68 | $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') 69 | }) 70 | .finally(() => { 71 | $.done(); 72 | }) 73 | 74 | async function price() { 75 | let num = 0 76 | do { 77 | $.token = $.jab.getToken() || '' 78 | if ($.token) { 79 | await siteppM_skuOnceApply(); 80 | } 81 | num++ 82 | } while (num < 3 && !$.token) 83 | await showMsg() 84 | } 85 | 86 | async function siteppM_skuOnceApply() { 87 | let body = { 88 | sid: "", 89 | type: "25", 90 | forcebot: "", 91 | token: $.token, 92 | feSt: $.token ? "s" : "f" 93 | } 94 | return new Promise(async resolve => { 95 | $.post(taskUrl("siteppM_skuOnceApply", body), async (err, resp, data) => { 96 | try { 97 | if (err) { 98 | console.log(JSON.stringify(err)) 99 | console.log(`${$.name} siteppM_skuOnceApply API请求失败,请检查网路重试`); 100 | } else { 101 | if (safeGet(data)) { 102 | data = JSON.parse(data) 103 | if (data.flag) { 104 | await $.wait(30 * 1000) 105 | await siteppM_appliedSuccAmount() 106 | } else { 107 | console.log(`保价失败:${data.responseMessage}`) 108 | message += `保价失败:${data.responseMessage}\n` 109 | } 110 | } 111 | } 112 | } catch (e) { 113 | $.logErr(e, resp); 114 | } finally { 115 | resolve(data); 116 | } 117 | }) 118 | }) 119 | } 120 | function siteppM_appliedSuccAmount() { 121 | let body = { 122 | sid: "", 123 | type: "25", 124 | forcebot: "", 125 | num: 15 126 | } 127 | return new Promise(resolve => { 128 | $.post(taskUrl("siteppM_appliedSuccAmount", body), (err, resp, data) => { 129 | try { 130 | if (err) { 131 | console.log(JSON.stringify(err)) 132 | console.log(`${$.name} siteppM_appliedSuccAmount API请求失败,请检查网路重试`) 133 | } else { 134 | if (safeGet(data)) { 135 | data = JSON.parse(data) 136 | if (data.flag) { 137 | console.log(`保价成功:返还${data.succAmount}元`) 138 | message += `保价成功:返还${data.succAmount}元\n` 139 | strmessagebyone=`恭喜保价成功,京东将返还${data.succAmount}元\n`+`查询地址: 京东app->客户服务->价格保护->申请记录`; 140 | } else { 141 | console.log(`保价失败:没有可保价的订单`) 142 | } 143 | } 144 | } 145 | } catch (e) { 146 | $.logErr(e, resp) 147 | } finally { 148 | resolve(data) 149 | } 150 | }) 151 | }) 152 | } 153 | 154 | async function jstoken() { 155 | const { JSDOM } = jsdom; 156 | let resourceLoader = new jsdom.ResourceLoader({ 157 | userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Firefox/91.0', 158 | referrer: "https://msitepp-fm.jd.com/rest/priceprophone/priceProPhoneMenu" 159 | }); 160 | let virtualConsole = new jsdom.VirtualConsole(); 161 | let options = { 162 | url: "https://msitepp-fm.jd.com/rest/priceprophone/priceProPhoneMenu", 163 | referrer: "https://msitepp-fm.jd.com/rest/priceprophone/priceProPhoneMenu", 164 | userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Firefox/91.0', 165 | runScripts: "dangerously", 166 | resources: resourceLoader, 167 | includeNodeLocations: true, 168 | storageQuota: 10000000, 169 | pretendToBeVisual: true, 170 | virtualConsole 171 | }; 172 | const { window } = new JSDOM(``, options); 173 | const jdPriceJs = await downloadUrl("https://js-nocaptcha.jd.com/statics/js/main.min.js") 174 | try { 175 | window.eval(jdPriceJs) 176 | window.HTMLCanvasElement.prototype.getContext = () => { 177 | return {}; 178 | }; 179 | $.jab = new window.JAB({ 180 | bizId: 'jdjiabao', 181 | initCaptcha: false 182 | }) 183 | } catch (e) {} 184 | } 185 | 186 | function downloadUrl(url) { 187 | return new Promise(resolve => { 188 | const options = { url, "timeout": 10000 }; 189 | $.get(options, async (err, resp, data) => { 190 | let res = null 191 | try { 192 | if (err) { 193 | console.log(`⚠️网络请求失败`); 194 | } else { 195 | res = data; 196 | } 197 | } catch (e) { 198 | $.logErr(e, resp) 199 | } finally { 200 | resolve(res); 201 | } 202 | }) 203 | }) 204 | } 205 | 206 | function showMsg() { 207 | return new Promise(resolve => { 208 | if (message) { 209 | allMessage += `【京东账号${$.index}】${$.nickName || $.UserName}\n${message}${$.index !== cookiesArr.length ? '\n\n' : '\n\n'}`; 210 | } 211 | //$.msg($.name, '', `【京东账号${$.index}】${$.nickName}\n${message}`); 212 | resolve() 213 | }) 214 | } 215 | 216 | function taskUrl(functionId, body) { 217 | return { 218 | url: `${JD_API_HOST}api?appid=siteppM&functionId=${functionId}&forcebot=&t=${Date.now()}`, 219 | body: `body=${encodeURIComponent(JSON.stringify(body))}`, 220 | headers: { 221 | "Host": "api.m.jd.com", 222 | "Accept": "application/json", 223 | "Content-Type": "application/x-www-form-urlencoded", 224 | "Origin": "https://msitepp-fm.jd.com", 225 | "Accept-Language": "zh-CN,zh-Hans;q=0.9", 226 | "User-Agent": $.isNode() ? (process.env.JD_USER_AGENT ? process.env.JD_USER_AGENT : (require('./USER_AGENTS').USER_AGENT)) : ($.getdata('JDUA') ? $.getdata('JDUA') : "jdapp;iPhone;9.4.4;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1"), 227 | "Referer": "https://msitepp-fm.jd.com/", 228 | "Accept-Encoding": "gzip, deflate, br", 229 | "Cookie": cookie 230 | } 231 | } 232 | } 233 | 234 | 235 | function TotalBean() { 236 | return new Promise(resolve => { 237 | const options = { 238 | url: "https://me-api.jd.com/user_new/info/GetJDUserInfoUnion", 239 | headers: { 240 | "Host": "me-api.jd.com", 241 | "Accept": "*/*", 242 | "User-Agent": "ScriptableWidgetExtension/185 CFNetwork/1312 Darwin/21.0.0", 243 | "Accept-Language": "zh-CN,zh-Hans;q=0.9", 244 | "Accept-Encoding": "gzip, deflate, br", 245 | "Cookie": cookie 246 | } 247 | } 248 | $.get(options, (err, resp, data) => { 249 | try { 250 | if (err) { 251 | $.logErr(err) 252 | } else { 253 | if (data) { 254 | data = JSON.parse(data); 255 | if (data['retcode'] === "1001") { 256 | $.isLogin = false; //cookie过期 257 | return; 258 | } 259 | if (data['retcode'] === "0" && data.data && data.data.hasOwnProperty("userInfo")) { 260 | $.nickName = data.data.userInfo.baseInfo.nickname; 261 | } 262 | } else { 263 | console.log('京东服务器返回空数据'); 264 | } 265 | } 266 | } catch (e) { 267 | $.logErr(e, resp) 268 | } finally { 269 | resolve() 270 | } 271 | }) 272 | }) 273 | } 274 | function safeGet(data) { 275 | try { 276 | if (typeof JSON.parse(data) == "object") { 277 | return true; 278 | } 279 | } catch (e) { 280 | console.log(e); 281 | console.log(`京东服务器访问数据为空,请检查自身设备网络情况`); 282 | return false; 283 | } 284 | } 285 | function jsonParse(str) { 286 | if (typeof str == "string") { 287 | try { 288 | return JSON.parse(str); 289 | } catch (e) { 290 | console.log(e); 291 | $.msg($.name, '', '请勿随意在BoxJs输入框修改内容\n建议通过脚本去获取cookie') 292 | return []; 293 | } 294 | } 295 | } 296 | // prettier-ignore 297 | function Env(t,e){"undefined"!=typeof process&&JSON.stringify(process.env).indexOf("GITHUB")>-1&&process.exit(0);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,r)=>{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.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.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)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 r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),n={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};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),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==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),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):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:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(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),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(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:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}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}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!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)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} 298 | -------------------------------------------------------------------------------- /NoUsed/NoUsed_jd_speed_signfree_Mod.js: -------------------------------------------------------------------------------- 1 | /* 2 | cron 18 9 * * * jd_speed_signfree_Mod.js 签到免单 3 | */ 4 | const $ = new Env('京东极速签到免单') 5 | const notify = $.isNode() ? require('./sendNotify') : ''; 6 | //Node.js用户请在jdCookie.js处填写京东ck; 7 | const jdCookieNode = $.isNode() ? require('./jdCookie.js') : ''; 8 | //IOS等用户直接用NobyDa的jd cookie 9 | let cookiesArr = [], cookie = ''; 10 | if ($.isNode()) { 11 | Object.keys(jdCookieNode).forEach((item) => { 12 | cookiesArr.push(jdCookieNode[item]) 13 | }) 14 | if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => { }; 15 | } else { 16 | cookiesArr = [$.getdata('CookieJD'), $.getdata('CookieJD2'), ...jsonParse($.getdata('CookiesJD') || "[]").map(item => item.cookie)].filter(item => !!item); 17 | } 18 | $.message = "\n"; 19 | 20 | let WP_APP_TOKEN_ONE = ""; 21 | let strmessagebyone=""; 22 | let strmessage=""; 23 | if ($.isNode() && process.env.WP_APP_TOKEN_ONE) { 24 | WP_APP_TOKEN_ONE = process.env.WP_APP_TOKEN_ONE; 25 | } 26 | 27 | 28 | !(async () => { 29 | if (!cookiesArr[0]) { 30 | $.msg($.name, '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/bean/signIndex.action', { "open-url": "https://bean.m.jd.com/bean/signIndex.action" }); 31 | return; 32 | } 33 | for (let i = 0; i < cookiesArr.length; i++) { 34 | if (cookiesArr[i]) { 35 | cookie = cookiesArr[i]; 36 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]) 37 | $.index = i + 1; 38 | $.isLogin = true; 39 | $.nickName = ''; 40 | $.mian_dan_list = []; 41 | $.mian_Name_list = []; 42 | await TotalBean(); 43 | console.log(`\n开始【京东账号${$.index}】${$.nickName || $.UserName}\n`); 44 | if (!$.isLogin) { 45 | $.msg($.name, `【提示】cookie已失效`, `京东账号${$.index} ${$.nickName || $.UserName}\n请重新登录获取\nhttps://bean.m.jd.com/bean/signIndex.action`, { "open-url": "https://bean.m.jd.com/bean/signIndex.action" }); 46 | 47 | if ($.isNode()) { 48 | await notify.sendNotify(`${$.name}cookie已失效 - ${$.UserName}`, `京东账号${$.index} ${$.UserName}\n请重新登录获取cookie`); 49 | } 50 | continue 51 | } 52 | $.message += `【京东账号】${$.nickName || $.UserName}\n` 53 | strmessagebyone=""; 54 | await get_order_ids(cookie) 55 | if ($.mian_dan_list.length > 0) { 56 | for (let i = 0; i < $.mian_dan_list.length; i++) { 57 | const orderId = $.mian_dan_list[i]; 58 | console.log(`商品名称:`+$.mian_Name_list[i]+`,商品id:${orderId}`); 59 | $.message += `商品名称:`+$.mian_Name_list[i]+`\n`; 60 | strmessagebyone+=`商品名称:`+$.mian_Name_list[i]+`\n`; 61 | await sign(cookie, orderId); 62 | await $.wait(2000) 63 | } 64 | } 65 | if(strmessagebyone) 66 | strmessage+=`【京东账号】${$.nickName || $.UserName}\n`+strmessagebyone+`\n`; 67 | 68 | if (strmessagebyone && $.isNode() && WP_APP_TOKEN_ONE) { 69 | strmessagebyone=`【京东账号】${$.nickName || $.UserName}\n`+strmessagebyone; 70 | await notify.sendNotifybyWxPucher("京东极速版签到免单",strmessagebyone, `${$.UserName}`); 71 | } 72 | 73 | } 74 | } 75 | await notify.sendNotify(`${$.name}`, strmessage); 76 | })() 77 | .catch((e) => { 78 | $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') 79 | }) 80 | .finally(() => { 81 | $.done(); 82 | }) 83 | 84 | function get_order_ids(cookie) { 85 | return new Promise(resolve => { 86 | try { 87 | $.get({ 88 | url: `https://api.m.jd.com/?functionId=signFreeHome&body=%7B%22linkId%22%3A%22PiuLvM8vamONsWzC0wqBGQ%22%7D&_t=${Date.now()}&appid=activities_platform`, 89 | headers: { 90 | 'User-Agent': $.isNode() ? (process.env.JD_USER_AGENT ? process.env.JD_USER_AGENT : (require('./USER_AGENTS').USER_AGENT)) : ($.getdata('JDUA') ? $.getdata('JDUA') : "jdapp;iPhone;9.4.4;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1"), 91 | 'Host': 'api.m.jd.com', 92 | 'accept': 'application/json, text/plain, */*', 93 | 'origin': 'https://signfree.jd.com', 94 | 'sec-fetch-dest': 'empty', 95 | 'x-requested-with': 'com.jd.jdlite', 96 | 'sec-fetch-site': 'same-site', 97 | 'sec-fetch-mode': 'cors', 98 | 'referer': 'https://signfree.jd.com/?activityId=PiuLvM8vamONsWzC0wqBGQ&lng=107.647085&lat=30.280608&sid=2c81fdcf0d34f67bacc5df5b2a4add6w&un_area=4_134_19915_0', 99 | 'accept-encoding': 'gzip, deflate', 100 | 'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7', 101 | 'cookie': cookie 102 | } 103 | }, (err, resp, data) => { 104 | data = JSON.parse(data) 105 | if (data.success == true) { 106 | /* if (data.data.risk == true) { 107 | console.log("风控用户,跳过"); 108 | $.message += "风控用户,跳过\n" 109 | resolve() 110 | return 111 | } */ 112 | if (!data.data.signFreeOrderInfoList) { 113 | console.log("没有需要签到的商品,请到京东极速版[签到免单]购买商品"); 114 | $.message += "没有需要签到的商品,请到京东极速版[签到免单]购买商品\n" 115 | resolve() 116 | } else { 117 | for (let i = 0; i < data.data.signFreeOrderInfoList.length; i++) { 118 | var respdemo = { "success": true, "code": 0, "errMsg": "success", "data": { "newUser": false, "backRecord": false, "risk": false, "surplusCount": 2, "sumTotalFreeAmount": "0.00", "signFreeOrderInfoList": [{ "id": 472, "productName": "百事可乐 300ml*6瓶", "productImg": "jfs/t1/177052/32/20077/117620/611e1a4cE0065cc54/b19fb6ed2ff59493.jpg", "needSignDays": 20, "hasSignDays": 0, "freeAmount": "6.54", "moneyReceiveMode": "3", "orderId": 225947891472, "surplusTime": 0, "combination": 1 }], "interruptInfoList": null } } 119 | const order = data.data.signFreeOrderInfoList[i]; 120 | $.mian_dan_list.push(order.orderId) 121 | $.mian_Name_list.push(order.productName) 122 | } 123 | } 124 | } 125 | resolve() 126 | }) 127 | } catch (error) { 128 | $.logErr(e, resp) 129 | resolve() 130 | } 131 | 132 | 133 | }) 134 | } 135 | function sign(cookie, orderId) { 136 | return new Promise(resolve => { 137 | const options = { 138 | url: `https://api.m.jd.com?functionId=signFreeSignIn&body=%7B%22linkId%22%3A%22PiuLvM8vamONsWzC0wqBGQ%22%2C%22orderId%22%3A${orderId}%7D&_t=${Date.now()}&appid=activities_platform`, 139 | headers: { 140 | 'Host': 'api.m.jd.com', 141 | 'accept': 'application/json, text/plain, */*', 142 | 'origin': 'https://signfree.jd.com', 143 | 'sec-fetch-dest': 'empty', 144 | "User-Agent": $.isNode() ? (process.env.JD_USER_AGENT ? process.env.JD_USER_AGENT : (require('./USER_AGENTS').USER_AGENT)) : ($.getdata('JDUA') ? $.getdata('JDUA') : "jdapp;iPhone;9.4.4;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1"), 145 | 'content-type': 'application/x-www-form-urlencoded', 146 | 'x-requested-with': 'com.jd.jdlite', 147 | 'sec-fetch-site': 'same-site', 148 | 'sec-fetch-mode': 'cors', 149 | 'referer': 'https://signfree.jd.com/?activityId=PiuLvM8vamONsWzC0wqBGQ&lng=107.647085&lat=30.280608&sid=2c81fdcf0d34f67bacc5df5b2a4add6w&un_area=4_134_19915_0', 150 | 'accept-encoding': 'gzip, deflate', 151 | 'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7', 152 | 'cookie': cookie 153 | }, 154 | } 155 | $.post(options, async (err, resp, data) => { 156 | try { 157 | console.log(data); 158 | data = JSON.parse(data) 159 | var dataDemo = { "success": false, "code": 400015, "errMsg": "明日签到", "data": null } 160 | if (data.success == false) { 161 | console.log(data.errMsg); 162 | strmessagebyone+="签到失败:"+data.errMsg+"\n"; 163 | } else { 164 | console.log("签到成功"); 165 | strmessagebyone+="签到成功\n"; 166 | } 167 | } catch (e) { 168 | $.logErr(e, resp); 169 | } finally { 170 | resolve(data || ""); 171 | } 172 | }) 173 | }) 174 | } 175 | 176 | function TotalBean() { 177 | return new Promise(async resolve => { 178 | const options = { 179 | "url": `https://wq.jd.com/user/info/QueryJDUserInfo?sceneval=2`, 180 | "headers": { 181 | "Accept": "application/json,text/plain, */*", 182 | "Content-Type": "application/x-www-form-urlencoded", 183 | "Accept-Encoding": "gzip, deflate, br", 184 | "Accept-Language": "zh-cn", 185 | "Connection": "keep-alive", 186 | "Cookie": cookie, 187 | "Referer": "https://wqs.jd.com/my/jingdou/my.shtml?sceneval=2", 188 | "User-Agent": $.isNode() ? (process.env.JD_USER_AGENT ? process.env.JD_USER_AGENT : (require('./USER_AGENTS').USER_AGENT)) : ($.getdata('JDUA') ? $.getdata('JDUA') : "jdapp;iPhone;9.4.4;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1") 189 | } 190 | } 191 | $.post(options, (err, resp, data) => { 192 | try { 193 | if (err) { 194 | console.log(`${JSON.stringify(err)}`) 195 | console.log(`${$.name} API请求失败,请检查网路重试`) 196 | } else { 197 | if (data) { 198 | data = JSON.parse(data); 199 | if (data['retcode'] === 13) { 200 | $.isLogin = false; //cookie过期 201 | return 202 | } 203 | if (data['retcode'] === 0) { 204 | $.nickName = (data['base'] && data['base'].nickname) || $.UserName; 205 | } else { 206 | $.nickName = $.UserName 207 | } 208 | } else { 209 | console.log(`京东服务器返回空数据`) 210 | } 211 | } 212 | } catch (e) { 213 | $.logErr(e, resp) 214 | } finally { 215 | resolve(); 216 | } 217 | }) 218 | }) 219 | } 220 | 221 | function jsonParse(str) { 222 | if (typeof str == "string") { 223 | try { 224 | return JSON.parse(str); 225 | } catch (e) { 226 | console.log(e); 227 | $.msg($.name, '', '请勿随意在BoxJs输入框修改内容\n建议通过脚本去获取cookie') 228 | return []; 229 | } 230 | } 231 | } 232 | // prettier-ignore 233 | function Env(t, e) { "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 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, r) => { 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.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.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const i = this.getdata(t); if (i) 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 r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; const [o, h] = i.split("@"), n = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; 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), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let r = t; for (const t of i) if (r = Object(r)[t], void 0 === r) return s; return r } lodash_set(t, e, s) { return Object(t) !== 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), r = s ? this.getval(s) : ""; if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; try { const e = JSON.parse(h); this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const o = {}; this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) } } else s = this.setval(t, e); return s } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, e) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : 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 : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (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), e(t, s, i) })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t))) : this.isNode() && (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: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) })) } post(t, e = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.post(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) }); else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: s, ...i } = t; this.got.post(s, i).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) }) } } 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 } msg(e = t, s = "", i = "", r) { const o = t => { if (!t) return t; if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; if ("object" == typeof t) { if (this.isLoon()) { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } if (this.isQuanX()) { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; return { "open-url": e, "media-url": s } } if (this.isSurge()) { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } } }; if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !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) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) } 234 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QLScript_New 2 | 3 | 本库的一对一通知和Nolan的Mark、Ark(原Nvjdc)登录产生的备注格式互相兼容,且只有使用Ark(原Nvjdc)登录的才会在资产查询中显示预计过期时间. 4 | 5 | 如果遇到什么问题先看看,可能有收获: https://www.kejiwanjia.com/jiaocheng/61708.html 6 | 7 | 2.10.3之前版本青龙拉库命令: 8 | 9 | 不包含sendNotify: 10 | 11 | ql repo https://github.com/ccwav/QLScript2.git "jd_" "NoUsed" "ql|utils" 12 | 13 | 包含sendNotify: 14 | 15 | ql repo https://github.com/ccwav/QLScript2.git "jd_" "NoUsed" "ql|sendNotify|utils" 16 | 17 | 18 | 2.10.3之后版本青龙拉库命令: 19 | 20 | 不包含sendNotify: 21 | 22 | ql repo https://github.com/ccwav/QLScript2.git "jd_" "NoUsed" "ql|utils|USER_AGENTS|jdCookie|JS_USER_AGENTS" 23 | 24 | 包含sendNotify: 25 | 26 | ql repo https://github.com/ccwav/QLScript2.git "jd_" "NoUsed" "ql|sendNotify|utils|USER_AGENTS|jdCookie|JS_USER_AGENTS" 27 | 28 | 频道: 29 | 30 | https://t.me/ccwav 31 | 32 | # 特别注意事项: 33 | ql.js 更新,修改获取token的方式 34 | export CHECKCK_CKAUTODEL="true" 为true则自动删除超过10天没有更新的CK 35 | export CHECKCK_STRCLIENTID="" 青龙环境变量的访问id 36 | export CHECKCK_STRCLIENTSECRET="" 青龙环境变量的访问秘钥 37 | export CHECKCK_PORT="5700" 青龙的访问端口,默认是5700 38 | 39 | # 1. 注意事项: 40 | (1)如果发现账户名称不能被正确处理,请手动删除ql\scripts\CKName_cache.json 文件. 41 | 42 | (2)另外某些账号如果服务器返回空有可能不会被正确处理,请知悉. 43 | 44 | (3)ql.js 是jd_CheckCK.js和sendNotify.js的依赖, 只要你使用了这两个脚本就一定保证放在同个文件夹里面. 45 | 46 | (4)使用Ninjia要注意Extra.sh中把 cp sendNotify.js /ql/scripts/sendNotify.js 这一句删除,不然每次重启容器sendNotify.js都会被覆盖. 47 | 48 | (5)如果用不同的通知类型分组,比如TG作为组1,企业微信作为组2,且之前已经设置过企业微信通知的参数QYWX_AM,请先将QYWX_AM置空(export QYWX_AM=""),再设置组2的企业微信参数QYWX_AM2(export QYWX_AM2="abcdef")。否则原有的QYWX_AM参数仍在生效中,导致企业微信仍然接受到组1的通知.(来自Windstill的惨痛经历) 49 | 50 | # 2. 关于群组 51 | 原通知配置变量加上数字,组成新的通知群组.通知脚本目前支援5组变量. 52 | 53 | 例子:企业微信配置了QYWX_AM和QYWX_AM2,兑换通知时推送到的QYWX_AM2配置的企业微信.即群组2. 54 | 55 | (PS:例子使用了企业微信的变量QYWX_AM,实际是所有推送变量后加数字都会有效.) 56 | 57 | # 3. jd_bean_change.js (已添加支持一对一推送) 58 | 京东资产变动 + 白嫖榜 + 京东月资产变动,注意事项: 59 | 60 | 如果你遇到TG Bark报错,那是因为报文过长,请使用分段通知功能. 61 | 62 | CKName_cache.json 跟 CK_WxPusherUid.json 现在写死路径到ql/scripts 63 | 64 | 变量列表: 65 | 66 | (1) EANCHANGE_PERSENT 分段通知 67 | 例子 : export BEANCHANGE_PERSENT="10" 68 | 总共有22个账号,结果会分成3条推送通知,1~10为第一条推送,11~20为第二条推送,剩余的为第三条推送 69 | 70 | (2) BEANCHANGE_USERGP2 BEANCHANGE_USERGP3 BEANCHANGE_USERGP4 根据Pt_Pin的值进行分组通知 71 | 注意:分组通知会强制禁用BEANCHANGE_PERSENT变量! 72 | 分组通知的通知标题为 脚本名+"#"+分组数值 73 | 主要用于搭配通知脚本的分组通知使用. 74 | 75 | (3) BEANCHANGE_ENABLEMONTH (此功能已永久停用) 76 | 每月1号17点后如果执行资产查询,开启京东月资产变动的统计和推送. 77 | 拆分通知和分组通知的变量都可以兼容. 78 | 标题按照分组分别为 京东月资产变动 京东月资产变动#2 京东月资产变动#3 京东月资产变动#4 79 | 开启 : export BEANCHANGE_ENABLEMONTH="true" 80 | 81 | (4) BEANCHANGE_ALLNOTIFY 82 | 设置推送置顶公告,公告会出现在资产通知中(包括一对一),支持html语法. 83 | 例子 : export BEANCHANGE_ALLNOTIFY='ccwav 虽然头发块掉光了 84 | 可是还是很帅啊... 85 | 86 | 不说了,我去哭会....' 87 | 88 | 显示效果: 89 | 90 | 【✨✨✨✨公告✨✨✨✨】 91 | ccwav 虽然头发块掉光了 92 | 可是还是很帅啊... 93 | 94 | 不说了,我去哭会.... 95 | 96 | (5) BEANCHANGE_ExJxBeans 97 | 当设定BEANCHANGE_ExJxBeans="true"且时间在17点之后,会自动将临期京豆兑换成喜豆续命. 98 | 99 | (6) BEANCHANGE_DISABLELIST 100 | 关闭查询列表中的项目,自行删减.(攻略显示就是之前的提醒) 101 | export BEANCHANGE_DISABLELIST="汪汪乐园&汪汪赛跑&京东赚赚&京东秒杀&东东农场&极速金币&京喜牧场&京喜工厂&京东工厂&领现金&喜豆查询&金融养猪&东东萌宠&活动攻略&过期京豆&查优惠券" 102 | 103 | (7) BEANCHANGE_BEANDETAILMODE(默认启用) 104 | 配置BEANCHANGE_BEANDETAILMODE=1,则启用缓存Mode,将使用获取的昨天最后一次资产查询结果比较京豆变更,避免频繁调用详细查询接口导致的403问题,如果需要准确信息,请使用diybot的bd cb等指令查询单个账号. 105 | 配置BEANCHANGE_BEANDETAILMODE=0,则不启用缓存,实时获取,但是现在跑不了几个号就403了,会显示0京豆. 106 | 107 | # 4. jd_CheckCK.js (已添加支持一对一推送) 108 | (最新的通知脚本已经集成自动禁用失效CK,如不需要自动启用CK功能可以直接禁用此脚本.) 109 | 110 | 京东CK检测,不正常的自动禁用,正常的如果是禁用状态则自动启用.配合通知脚本CK触发使用.也可以直接task. 111 | 112 | 兼容jd_bean_change的BEANCHANGE_USERGP2 BEANCHANGE_USERGP3 BEANCHANGE_USERGP4变量. 113 | 114 | 变量列表: 115 | 116 | 显示正常CK: export CHECKCK_SHOWSUCCESSCK="true" 117 | 永远通知CK状态: export CHECKCK_CKALWAYSNOTIFY="true" 118 | 停用自动启用CK: export CHECKCK_CKAUTOENABLE="false" 119 | 服务器空数据等错误不触发通知: export CHECKCK_CKNOWARNERROR="true" 120 | 121 | BEANCHANGE_USERGP2 BEANCHANGE_USERGP3 BEANCHANGE_USERGP4 根据Pt_Pin的值进行分组通知 122 | 分组通知的通知标题为 脚本名+"#"+分组数值 123 | 主要用于搭配通知脚本的分组通知使用. 124 | 125 | 增加CHECKCK_ALLNOTIFY设置温馨提示,推送时在内容末尾添加显示 126 | 一对一推送只有推送账户失效时才会添加.用法参考BEANCHANGE_ALLNOTIFY. 127 | 128 | 129 | # 5. sendNotify.js 130 | 发送通知脚本Pro. 131 | 132 | 集成自动禁用失效CK功能,当NOTIFY_AUTOCHECKCK=“true”时开启,默认关闭,原理是通过捕获任务脚本发送ck失效实现, 133 | 134 | 精准操作,支持一对一推送,通知标题还是以前的"京东CK检测",兼容jd_CheckCK.js的分组设定和CHECKCK_ALLNOTIFY设定. 135 | 136 | 变量列表: 137 | 138 | (1) NOTIFY_SKIP_LIST 139 | 如果通知标题在此变量里面存在(&隔开),则用屏蔽不发送通知.(PS: Ningjia 作者写的功能,继承过来.) 140 | 例子 : export NOTIFY_SKIP_LIST="京东CK检测&京东资产变动" 141 | 142 | (2) NOTIFY_GROUP2_LIST NOTIFY_GROUP3_LIST NOTIFY_GROUP4_LIST NOTIFY_GROUP5_LIST NOTIFY_GROUP6_LIST 143 | 如果通知标题在此变量里面存在(&隔开),则用第2/3/4/5/6套推送变量进行配置. 144 | 145 | (3) NOTIFY_SHOWNAMETYPE 146 | export NOTIFY_SHOWNAMETYPE="1" 不做任何变动 147 | export NOTIFY_SHOWNAMETYPE="2" 效果是 : 账号名称:别名(备注) 148 | export NOTIFY_SHOWNAMETYPE="3" 效果是 : 账号名称:pin(备注) 149 | export NOTIFY_SHOWNAMETYPE="4" 效果是 : 账号名称:备注 150 | 151 | (4) NOTIFY_SKIP_NAMETYPELIST 152 | 单独指定某些脚本不做NOTIFY_SHOWNAMETYPE变量处理 153 | 例子 : export NOTIFY_SKIP_NAMETYPELIST="东东农场&东东工厂" 154 | 155 | (5) 特殊标题控制,可以自行加载到第二点的变量中控制 156 | 东东农场领取 东东萌宠领取 京喜工厂领取 汪汪乐园养joy领取 脚本任务更新 157 | 158 | (6) NOTIFY_NOREMIND 159 | 对 东东农场领取 东东萌宠领取 京喜工厂领取 汪汪乐园养joy领取 脚本任务更新的通知进行屏蔽,可自行删减. 160 | export NOTIFY_NOREMIND="京喜工厂领取&汪汪乐园养joy领取" 161 | 162 | (7) NOTIFY_NOCKFALSE 163 | 屏蔽任务脚本的ck失效通知 164 | export NOTIFY_NOCKFALSE="true" 165 | 166 | (8) NOTIFY_AUTHOR 167 | 指定通知底部显示 本通知 By 后面显示的字符,默认是ccwav Mod 168 | 169 | (9) NOTIFY_NOLOGINSUCCESS 170 | 屏蔽青龙登陆成功通知,登陆失败不屏蔽(新版貌似可以直接设定了) 171 | export NOTIFY_NOLOGINSUCCESS="true" 172 | 173 | (10) NOTIFY_CUSTOMNOTIFY 174 | 强大的自定义通知,格式为 脚本名称&推送组别&推送类型 (推送组别总共5组) 175 | 推送类型: Server酱&pushplus&pushplushxtrip&Bark&TG机器人&钉钉&企业微信机器人&企业微信应用消息&iGotNotify&gobotNotify&WxPusher 176 | export NOTIFY_CUSTOMNOTIFY=["京东资产变动&组1&Server酱&Bark&企业微信应用消息","京东白嫖榜&组2&钉钉&pushplus"] 177 | 178 | (11) NOTIFY_CKTASK 179 | 当接收到发送CK失效通知和Ninja 运行通知时候执行子线程任务,支持js py ts 180 | 例子: export NOTIFY_CKTASK="jd_CheckCK.js" 181 | 182 | (12) PUSH_PLUS_TOKEN_hxtrip 和 PUSH_PLUS_USER_hxtrip 183 | 增加pushplus.hxtrip.com的推送加接口,貌似更稳定,注意这个和PUSHPLUS不是同一家. 184 | 185 | (13) 用 WxPusher 进行一对一推送 186 | 新方案; 187 | 填写变量 WP_APP_TOKEN_ONE,按照备注内容@@WxPusherUid的格式修改备注,例子 萌新cc@@UID_AASDADASDQWEQWDADASDADASDASDSA 188 | 旧方案: 189 | 详细教程有人写了,不知道是幸运还是不幸: https://www.kejiwanjia.com/jiaocheng/27909.html 190 | 填写变量 WP_APP_TOKEN_ONE,可在管理台查看: https://wxpusher.zjiecode.com/admin/main/app/appToken 191 | 手动建立CK_WxPusherUid.json,放通知脚本同级文件夹,可以参考CKName_cache.json,只是nickName改成Uid, 192 | 每个用户的uid可在管理台查看: https://wxpusher.zjiecode.com/admin/main/wxuser/list 193 | CK_WxPusherUid.json 内容(pt_pin 如果是汉字需要填写转码后的!): 194 | [ 195 | { 196 | "pt_pin": "ccwav", 197 | "Uid": "UID_AAAAAAAA" 198 | }, 199 | { 200 | "pt_pin": "中文名", 201 | "Uid": "BBBBBBBBBB" 202 | } 203 | ] 204 | 205 | (14) NOTIFY_SKIP_TEXT 206 | 如果此变量(&隔开)的关键字在通知内容里面存在,则屏蔽不发送通知. 207 | 例子 : export NOTIFY_SKIP_TEXT="忘了种植&异常" 208 | 209 | (15) NOTIFY_AUTHOR_BLANK (tcbaby提交) 210 | 控制不显示推送通知的底部信息 211 | 例子 : export NOTIFY_AUTHOR_BLANK="随便填只要非空即可" 212 | 213 | # 6. jd_speed_sign_Part1~jd_speed_sign_Part3 214 | 简单粗暴的极速版的分任务版,将总ck数除以3后平均分配成三个任务同时执行. 215 | 216 | 如果使用请务必禁用其他库的jd_speed_sign脚本.感谢jd_speed_sign原作者。 217 | 218 | 例子 : 有24个ck,则Part1 执行1~8,Part2 执行9~16,Part3 执行17以后剩下的所有ck. 219 | 220 | # 7. jd_priceProtect_Mod.js (已添加支持一对一推送) 221 | 222 | 京东价格保护一对一通知版,仅仅是保价成功加上了一对一通知,改了执行时间,没有什么技术含量... 223 | 224 | # 8. jd_big_winner_Mod.js (已添加支持一对一推送) 225 | 省钱大赢家之翻翻乐分组版本,兼容资产通知查询的分组变量BEANCHANGE_USERGP2 ~ BEANCHANGE_USERGP4 226 | 227 | 标题为省钱大赢家之翻翻乐 省钱大赢家之翻翻乐#2 省钱大赢家之翻翻乐#3 省钱大赢家之翻翻乐#4 228 | 229 | # 9. jd_joy_reward_Mod.js 230 | 宠汪汪积分兑换有就换版 231 | 232 | 变量列表: 233 | 234 | export JOY_GET20WHEN16="true" 235 | 控制16点才触发20京豆兑换. 236 | 237 | # 10. 互助版脚本 238 | 互助版没有助力池,全部账号内互助,另外,东东农场跟东东萌宠要跑第二次任务才能看到正确的助力结果,请知悉(能改,但是懒,不想动它的顺序逻辑). 239 | 240 | 变量列表: 241 | export CC_NOHELPAFTER8="true" 控制早上9点后时段跳过不必要的互助 242 | 243 | # 11. jd_UpdateUIDtoRemark.js WxPusherUid迁移工具 244 | WxPusherUid迁移工具是给使用nvjdc的用户准备的,没有使用nvjdc的请不要使用。 245 | 246 | 适配nvjdc的备注格式为 : 备注@@账号更新时间数值@@Uid ,脚本会按照这个格式自动更新,其中账号更新时间数值用户使用 nvjdc登录更新ck的时候会自动更新, 247 | 248 | 非nvjdc用户如果不小心使用了迁移工具,请还原env.db或手动更改备注格式为 备注@@Uid 249 | 250 | # 分组应用总结实例: 251 | 252 | ##CK失效时执行脚本 253 | export NOTIFY_CKTASK="ccwav_QLScript2_jd_CheckCK.js" 254 | 255 | ##开启月结资产推送 256 | export BEANCHANGE_ENABLEMONTH="true" 257 | 258 | ##分组2推送 259 | export QYWX_AM2="" 260 | export PUSH_PLUS_TOKEN2="ABCDEFGHIJKLMN" 261 | export PUSH_PLUS_USER2="Group2"; 262 | export BEANCHANGE_USERGP2="账号1pin&账号5pin&账号8pin" 263 | export NOTIFY_GROUP2_LIST="京东资产变动#2&京东白嫖榜#2&京东月资产变动#2&省钱大赢家之翻翻乐#2&京东CK检测#2" 264 | 265 | ##分组3推送 266 | export QYWX_AM3="" 267 | export PUSH_PLUS_TOKEN3="ABCDEFGHIJKLMN" 268 | export PUSH_PLUS_USER3="Group3"; 269 | export BEANCHANGE_USERGP2="账号2pin&账号3pin&账号4pin" 270 | export NOTIFY_GROUP3_LIST="京东资产变动#3&京东白嫖榜#3&京东月资产变动#3&省钱大赢家之翻翻乐#3&京东CK检测#3" 271 | 272 | ##分组4推送 273 | export QYWX_AM4="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxxxxxxx" 274 | export BEANCHANGE_USERGP4="账号10pin&账号11pin&账号12pin" 275 | export NOTIFY_GROUP4_LIST="京东资产变动#4&京东白嫖榜#4&京东月资产变动#4&省钱大赢家之翻翻乐#4&Ninja 运行通知&京东CK检测#4" 276 | 277 | ##分组5推送 278 | export QYWX_AM5="" 279 | export PUSH_PLUS_TOKEN5="ABCDEFGHIJKLMN" 280 | export PUSH_PLUS_USER5="Group5"; 281 | export NOTIFY_GROUP5_LIST="京东资产变动&京东白嫖榜&京东月资产变动&省钱大赢家之翻翻乐&京东CK检测" 282 | 283 | 284 | ##分组6推送 285 | export QYWX_AM6="bbbbbbbbbbbbbbbbbbsccccccccccccccccc" 286 | export NOTIFY_GROUP6_LIST="东东农场领取&东东萌宠领取&汪汪乐园养joy领取&脚本任务更新" 287 | 288 | 289 | -------------------------------------------------------------------------------- /USER_AGENTS.js: -------------------------------------------------------------------------------- 1 | const USER_AGENTS = [ 2 | "jdapp;android;10.1.6;10;network/wifi;Mozilla/5.0 (Linux; Android 10; ONEPLUS A5010 Build/QKQ1.191014.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", 3 | "jdapp;iPhone;10.1.6;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 4 | "jdapp;android;10.1.6;9;network/4g;Mozilla/5.0 (Linux; Android 9; Mi Note 3 Build/PKQ1.181007.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045131 Mobile Safari/537.36", 5 | "jdapp;android;10.1.6;10;network/wifi;Mozilla/5.0 (Linux; Android 10; GM1910 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", 6 | "jdapp;android;10.1.6;9;network/wifi;Mozilla/5.0 (Linux; Android 9; 16T Build/PKQ1.190616.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", 7 | "jdapp;iPhone;10.1.6;13.6;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 8 | "jdapp;iPhone;10.1.6;13.6;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 9 | "jdapp;iPhone;10.1.6;13.5;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 10 | "jdapp;iPhone;10.1.6;14.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 11 | "jdapp;iPhone;10.1.6;13.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 12 | "jdapp;iPhone;10.1.6;13.7;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 13 | "jdapp;iPhone;10.1.6;14.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 14 | "jdapp;iPhone;10.1.6;13.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 15 | "jdapp;iPhone;10.1.6;13.4;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 16 | "jdapp;iPhone;10.1.6;14.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 17 | "jdapp;android;10.1.6;9;network/wifi;Mozilla/5.0 (Linux; Android 9; MI 6 Build/PKQ1.190118.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", 18 | "jdapp;android;10.1.6;11;network/wifi;Mozilla/5.0 (Linux; Android 11; Redmi K30 5G Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045511 Mobile Safari/537.36", 19 | "jdapp;iPhone;10.1.6;11.4;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15F79", 20 | "jdapp;android;10.1.6;10;;network/wifi;Mozilla/5.0 (Linux; Android 10; M2006J10C Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", 21 | "jdapp;android;10.1.6;10;network/wifi;Mozilla/5.0 (Linux; Android 10; M2006J10C Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", 22 | "jdapp;android;10.1.6;10;network/wifi;Mozilla/5.0 (Linux; Android 10; ONEPLUS A6000 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045224 Mobile Safari/537.36", 23 | "jdapp;android;10.1.6;9;network/wifi;Mozilla/5.0 (Linux; Android 9; MHA-AL00 Build/HUAWEIMHA-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", 24 | "jdapp;android;10.1.6;8.1.0;network/wifi;Mozilla/5.0 (Linux; Android 8.1.0; 16 X Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", 25 | "jdapp;android;10.1.6;8.0.0;network/wifi;Mozilla/5.0 (Linux; Android 8.0.0; HTC U-3w Build/OPR6.170623.013; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", 26 | "jdapp;iPhone;10.1.6;14.0.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 27 | "jdapp;android;10.1.6;10;network/wifi;Mozilla/5.0 (Linux; Android 10; LYA-AL00 Build/HUAWEILYA-AL00L; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", 28 | "jdapp;iPhone;10.1.6;14.2;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 29 | "jdapp;iPhone;10.1.6;14.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 30 | "jdapp;iPhone;10.1.6;14.2;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 31 | "jdapp;android;10.1.6;8.1.0;network/wifi;Mozilla/5.0 (Linux; Android 8.1.0; MI 8 Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045131 Mobile Safari/537.36", 32 | "jdapp;android;10.1.6;10;network/wifi;Mozilla/5.0 (Linux; Android 10; Redmi K20 Pro Premium Edition Build/QKQ1.190825.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045227 Mobile Safari/537.36", 33 | "jdapp;iPhone;10.1.6;14.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 34 | "jdapp;iPhone;10.1.6;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 35 | "jdapp;android;10.1.6;11;network/wifi;Mozilla/5.0 (Linux; Android 11; Redmi K20 Pro Premium Edition Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045513 Mobile Safari/537.36", 36 | "jdapp;android;10.1.6;10;network/wifi;Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190828.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045227 Mobile Safari/537.36", 37 | "jdapp;iPhone;10.1.6;14.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 38 | ] 39 | /** 40 | * 生成随机数字 41 | * @param {number} min 最小值(包含) 42 | * @param {number} max 最大值(不包含) 43 | */ 44 | function randomNumber(min = 0, max = 100) { 45 | return Math.min(Math.floor(min + Math.random() * (max - min)), max); 46 | } 47 | const USER_AGENT = USER_AGENTS[randomNumber(0, USER_AGENTS.length)]; 48 | 49 | module.exports = { 50 | USER_AGENT 51 | } 52 | -------------------------------------------------------------------------------- /bot_jd_CkSeq.js: -------------------------------------------------------------------------------- 1 | /* 2 | cron "0 0 * * *" jd_CheckCkSeq.js, tag:CK顺序调试工具by-ccwav 3 | */ 4 | const $ = new Env("机器人专用CK状态工具"); 5 | const { 6 | getEnvs 7 | } = require('./ql'); 8 | const jdCookieNode = $.isNode() ? require("./jdCookie.js") : ""; 9 | let cookiesArr = []; 10 | if ($.isNode()) { 11 | Object.keys(jdCookieNode).forEach((item) => { 12 | cookiesArr.push(jdCookieNode[item]) 13 | }) 14 | } 15 | 16 | let arrCkPtPin = []; 17 | let arrEnvPtPin = []; 18 | let arrEnvStatus = []; 19 | let arrEnvOnebyOne = []; 20 | let arrEnvRemark = []; 21 | let strCk = ""; 22 | let strNoFoundCk = ""; 23 | 24 | const fs = require('fs'); 25 | let TempCKUid = []; 26 | let strUidFile = '/ql/scripts/CK_WxPusherUid.json'; 27 | let UidFileexists = fs.existsSync(strUidFile); 28 | if (UidFileexists) { 29 | console.log("检测到一对一Uid文件WxPusherUid.json,载入..."); 30 | TempCKUid = fs.readFileSync(strUidFile, 'utf-8'); 31 | if (TempCKUid) { 32 | TempCKUid = TempCKUid.toString(); 33 | TempCKUid = JSON.parse(TempCKUid); 34 | } 35 | } 36 | 37 | !(async() => { 38 | 39 | const envs = await getEnvs(); 40 | for (let i = 0; i < envs.length; i++) { 41 | if (envs[i].value) { 42 | var tempptpin = decodeURIComponent(envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/) && envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 43 | arrEnvPtPin.push(tempptpin); 44 | arrEnvStatus.push(envs[i].status); 45 | var struuid=getuuid(envs[i].remarks,tempptpin) 46 | arrEnvOnebyOne.push(struuid); 47 | var strRemark=getRemark(envs[i].remarks) 48 | arrEnvRemark.push(strRemark); 49 | } 50 | } 51 | 52 | for (let i = 0; i < cookiesArr.length; i++) { 53 | if (cookiesArr[i]) { 54 | cookie = cookiesArr[i]; 55 | var tempptpin = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 56 | var intSeq = inArray(tempptpin, arrEnvPtPin); 57 | if (intSeq != -1) { 58 | arrCkPtPin.push(tempptpin); 59 | if (arrEnvRemark[intSeq]) 60 | strCk += "【"+(intSeq+1) + "】" + arrEnvRemark[intSeq]; 61 | else 62 | strCk += "【"+(intSeq+1) + "】" + tempptpin ; 63 | 64 | if (arrEnvOnebyOne[intSeq]) { 65 | strCk += "(一对一)" 66 | } 67 | strCk +="\n"; 68 | } 69 | } 70 | } 71 | 72 | for (let i = 0; i < arrEnvPtPin.length; i++) { 73 | var tempptpin = arrEnvPtPin[i]; 74 | var intSeq = inArray(tempptpin, arrCkPtPin); 75 | if (intSeq == -1) { 76 | if (arrEnvRemark[i]) 77 | strNoFoundCk += "【" + (i + 1) + "】" + arrEnvRemark[i]; 78 | else 79 | strNoFoundCk += "【" + (i + 1) + "】" + tempptpin; 80 | 81 | if (arrEnvStatus[i] == 1) { 82 | strNoFoundCk += "(禁用状态)" 83 | } 84 | if (arrEnvOnebyOne[i]) { 85 | strNoFoundCk += "(一对一)" 86 | } 87 | strNoFoundCk += "\n"; 88 | 89 | } 90 | } 91 | console.log("😀今日正常的账号("+cookiesArr.length+"个):\n" + strCk); 92 | console.log("分割行"); 93 | if (strNoFoundCk) { 94 | console.log("\n😒没有出现在CK队列中的账号("+(arrEnvPtPin.length-cookiesArr.length)+"个):\n" + strNoFoundCk); 95 | } 96 | return; 97 | })() 98 | .catch((e) => $.logErr(e)) 99 | .finally(() => $.done()); 100 | 101 | function inArray(search, array) { 102 | var lnSeq = -1; 103 | for (let i = 0; i < array.length; i++) { 104 | if (array[i] == search) { 105 | lnSeq = i; 106 | } 107 | } 108 | return parseInt(lnSeq); 109 | } 110 | 111 | function getuuid(strRemark, PtPin) { 112 | var strTempuuid = ""; 113 | if (strRemark) { 114 | var Tempindex = strRemark.indexOf("@@"); 115 | if (Tempindex != -1) { 116 | //console.log(PtPin + ": 检测到NVJDC的一对一格式,瑞思拜~!"); 117 | var TempRemarkList = strRemark.split("@@"); 118 | for (let j = 1; j < TempRemarkList.length; j++) { 119 | if (TempRemarkList[j]) { 120 | if (TempRemarkList[j].length > 4) { 121 | if (TempRemarkList[j].substring(0, 4) == "UID_") { 122 | strTempuuid = TempRemarkList[j]; 123 | break; 124 | } 125 | } 126 | } 127 | } 128 | } 129 | } 130 | if (!strTempuuid && TempCKUid) { 131 | //console.log("正在从CK_WxPusherUid文件中检索资料..."); 132 | for (let j = 0; j < TempCKUid.length; j++) { 133 | if (PtPin == decodeURIComponent(TempCKUid[j].pt_pin)) { 134 | strTempuuid = TempCKUid[j].Uid; 135 | break; 136 | } 137 | } 138 | } 139 | return strTempuuid; 140 | } 141 | 142 | function getRemark(strRemark) { 143 | var strTempRemark = ""; 144 | if (strRemark) { 145 | var Tempindex = strRemark.indexOf("@@"); 146 | if (Tempindex != -1) { 147 | var TempRemarkList = strRemark.split("@@"); 148 | strTempRemark=TempRemarkList[0]; 149 | } else{ 150 | strTempRemark=strRemark; 151 | } 152 | } 153 | 154 | return strTempRemark; 155 | } 156 | 157 | // prettier-ignore 158 | function Env(t, e) { 159 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 160 | class s { 161 | constructor(t) { 162 | this.env = t 163 | } 164 | send(t, e = "GET") { 165 | t = "string" == typeof t ? { 166 | url: t 167 | } 168 | : t; 169 | let s = this.get; 170 | return "POST" === e && (s = this.post), 171 | new Promise((e, i) => { 172 | s.call(this, t, (t, s, r) => { 173 | t ? i(t) : e(s) 174 | }) 175 | }) 176 | } 177 | get(t) { 178 | return this.send.call(this.env, t) 179 | } 180 | post(t) { 181 | return this.send.call(this.env, t, "POST") 182 | } 183 | } 184 | return new class { 185 | constructor(t, e) { 186 | this.name = t, 187 | this.http = new s(this), 188 | this.data = null, 189 | this.dataFile = "box.dat", 190 | this.logs = [], 191 | this.isMute = !1, 192 | this.isNeedRewrite = !1, 193 | this.logSeparator = "\n", 194 | this.startTime = (new Date).getTime(), 195 | Object.assign(this, e), 196 | this.log("", `🔔${this.name}, 开始!`) 197 | } 198 | isNode() { 199 | return "undefined" != typeof module && !!module.exports 200 | } 201 | isQuanX() { 202 | return "undefined" != typeof $task 203 | } 204 | isSurge() { 205 | return "undefined" != typeof $httpClient && "undefined" == typeof $loon 206 | } 207 | isLoon() { 208 | return "undefined" != typeof $loon 209 | } 210 | toObj(t, e = null) { 211 | try { 212 | return JSON.parse(t) 213 | } catch { 214 | return e 215 | } 216 | } 217 | toStr(t, e = null) { 218 | try { 219 | return JSON.stringify(t) 220 | } catch { 221 | return e 222 | } 223 | } 224 | getjson(t, e) { 225 | let s = e; 226 | const i = this.getdata(t); 227 | if (i) 228 | try { 229 | s = JSON.parse(this.getdata(t)) 230 | } catch {} 231 | return s 232 | } 233 | setjson(t, e) { 234 | try { 235 | return this.setdata(JSON.stringify(t), e) 236 | } catch { 237 | return !1 238 | } 239 | } 240 | getScript(t) { 241 | return new Promise(e => { 242 | this.get({ 243 | url: t 244 | }, (t, s, i) => e(i)) 245 | }) 246 | } 247 | runScript(t, e) { 248 | return new Promise(s => { 249 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 250 | i = i ? i.replace(/\n/g, "").trim() : i; 251 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 252 | r = r ? 1 * r : 20, 253 | r = e && e.timeout ? e.timeout : r; 254 | const[o, h] = i.split("@"), 255 | n = { 256 | url: `http://${h}/v1/scripting/evaluate`, 257 | body: { 258 | script_text: t, 259 | mock_type: "cron", 260 | timeout: r 261 | }, 262 | headers: { 263 | "X-Key": o, 264 | Accept: "*/*" 265 | } 266 | }; 267 | this.post(n, (t, e, i) => s(i)) 268 | }).catch(t => this.logErr(t)) 269 | } 270 | loaddata() { 271 | if (!this.isNode()) 272 | return {}; { 273 | this.fs = this.fs ? this.fs : require("fs"), 274 | this.path = this.path ? this.path : require("path"); 275 | const t = this.path.resolve(this.dataFile), 276 | e = this.path.resolve(process.cwd(), this.dataFile), 277 | s = this.fs.existsSync(t), 278 | i = !s && this.fs.existsSync(e); 279 | if (!s && !i) 280 | return {}; { 281 | const i = s ? t : e; 282 | try { 283 | return JSON.parse(this.fs.readFileSync(i)) 284 | } catch (t) { 285 | return {} 286 | } 287 | } 288 | } 289 | } 290 | writedata() { 291 | if (this.isNode()) { 292 | this.fs = this.fs ? this.fs : require("fs"), 293 | this.path = this.path ? this.path : require("path"); 294 | const t = this.path.resolve(this.dataFile), 295 | e = this.path.resolve(process.cwd(), this.dataFile), 296 | s = this.fs.existsSync(t), 297 | i = !s && this.fs.existsSync(e), 298 | r = JSON.stringify(this.data); 299 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 300 | } 301 | } 302 | lodash_get(t, e, s) { 303 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 304 | let r = t; 305 | for (const t of i) 306 | if (r = Object(r)[t], void 0 === r) 307 | return s; 308 | return r 309 | } 310 | lodash_set(t, e, s) { 311 | return Object(t) !== 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) 312 | } 313 | getdata(t) { 314 | let e = this.getval(t); 315 | if (/^@/.test(t)) { 316 | const[, s, i] = /^@(.*?)\.(.*?)$/.exec(t), 317 | r = s ? this.getval(s) : ""; 318 | if (r) 319 | try { 320 | const t = JSON.parse(r); 321 | e = t ? this.lodash_get(t, i, "") : e 322 | } catch (t) { 323 | e = "" 324 | } 325 | } 326 | return e 327 | } 328 | setdata(t, e) { 329 | let s = !1; 330 | if (/^@/.test(e)) { 331 | const[, i, r] = /^@(.*?)\.(.*?)$/.exec(e), 332 | o = this.getval(i), 333 | h = i ? "null" === o ? null : o || "{}" : "{}"; 334 | try { 335 | const e = JSON.parse(h); 336 | this.lodash_set(e, r, t), 337 | s = this.setval(JSON.stringify(e), i) 338 | } catch (e) { 339 | const o = {}; 340 | this.lodash_set(o, r, t), 341 | s = this.setval(JSON.stringify(o), i) 342 | } 343 | } else 344 | s = this.setval(t, e); 345 | return s 346 | } 347 | getval(t) { 348 | return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null 349 | } 350 | setval(t, e) { 351 | return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null 352 | } 353 | initGotEnv(t) { 354 | this.got = this.got ? this.got : require("got"), 355 | this.cktough = this.cktough ? this.cktough : require("tough-cookie"), 356 | this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, 357 | t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) 358 | } 359 | get(t, e = (() => {})) { 360 | t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), 361 | this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { 362 | "X-Surge-Skip-Scripting": !1 363 | })), $httpClient.get(t, (t, s, i) => { 364 | !t && s && (s.body = i, s.statusCode = s.status), 365 | e(t, s, i) 366 | })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 367 | hints: !1 368 | })), $task.fetch(t).then(t => { 369 | const { 370 | statusCode: s, 371 | statusCode: i, 372 | headers: r, 373 | body: o 374 | } = t; 375 | e(null, { 376 | status: s, 377 | statusCode: i, 378 | headers: r, 379 | body: o 380 | }, o) 381 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 382 | try { 383 | if (t.headers["set-cookie"]) { 384 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 385 | s && this.ckjar.setCookieSync(s, null), 386 | e.cookieJar = this.ckjar 387 | } 388 | } catch (t) { 389 | this.logErr(t) 390 | } 391 | }).then(t => { 392 | const { 393 | statusCode: s, 394 | statusCode: i, 395 | headers: r, 396 | body: o 397 | } = t; 398 | e(null, { 399 | status: s, 400 | statusCode: i, 401 | headers: r, 402 | body: o 403 | }, o) 404 | }, t => { 405 | const { 406 | message: s, 407 | response: i 408 | } = t; 409 | e(s, i, i && i.body) 410 | })) 411 | } 412 | post(t, e = (() => {})) { 413 | if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) 414 | this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { 415 | "X-Surge-Skip-Scripting": !1 416 | })), $httpClient.post(t, (t, s, i) => { 417 | !t && s && (s.body = i, s.statusCode = s.status), 418 | e(t, s, i) 419 | }); 420 | else if (this.isQuanX()) 421 | t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 422 | hints: !1 423 | })), $task.fetch(t).then(t => { 424 | const { 425 | statusCode: s, 426 | statusCode: i, 427 | headers: r, 428 | body: o 429 | } = t; 430 | e(null, { 431 | status: s, 432 | statusCode: i, 433 | headers: r, 434 | body: o 435 | }, o) 436 | }, t => e(t)); 437 | else if (this.isNode()) { 438 | this.initGotEnv(t); 439 | const { 440 | url: s, 441 | ...i 442 | } = t; 443 | this.got.post(s, i).then(t => { 444 | const { 445 | statusCode: s, 446 | statusCode: i, 447 | headers: r, 448 | body: o 449 | } = t; 450 | e(null, { 451 | status: s, 452 | statusCode: i, 453 | headers: r, 454 | body: o 455 | }, o) 456 | }, t => { 457 | const { 458 | message: s, 459 | response: i 460 | } = t; 461 | e(s, i, i && i.body) 462 | }) 463 | } 464 | } 465 | time(t, e = null) { 466 | const s = e ? new Date(e) : new Date; 467 | let i = { 468 | "M+": s.getMonth() + 1, 469 | "d+": s.getDate(), 470 | "H+": s.getHours(), 471 | "m+": s.getMinutes(), 472 | "s+": s.getSeconds(), 473 | "q+": Math.floor((s.getMonth() + 3) / 3), 474 | S: s.getMilliseconds() 475 | }; 476 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 477 | for (let e in i) 478 | new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); 479 | return t 480 | } 481 | msg(e = t, s = "", i = "", r) { 482 | const o = t => { 483 | if (!t) 484 | return t; 485 | if ("string" == typeof t) 486 | return this.isLoon() ? t : this.isQuanX() ? { 487 | "open-url": t 488 | } 489 | : this.isSurge() ? { 490 | url: t 491 | } 492 | : void 0; 493 | if ("object" == typeof t) { 494 | if (this.isLoon()) { 495 | let e = t.openUrl || t.url || t["open-url"], 496 | s = t.mediaUrl || t["media-url"]; 497 | return { 498 | openUrl: e, 499 | mediaUrl: s 500 | } 501 | } 502 | if (this.isQuanX()) { 503 | let e = t["open-url"] || t.url || t.openUrl, 504 | s = t["media-url"] || t.mediaUrl; 505 | return { 506 | "open-url": e, 507 | "media-url": s 508 | } 509 | } 510 | if (this.isSurge()) { 511 | let e = t.url || t.openUrl || t["open-url"]; 512 | return { 513 | url: e 514 | } 515 | } 516 | } 517 | }; 518 | if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { 519 | let t = ["", "==============📣系统通知📣=============="]; 520 | t.push(e), 521 | s && t.push(s), 522 | i && t.push(i), 523 | console.log(t.join("\n")), 524 | this.logs = this.logs.concat(t) 525 | } 526 | } 527 | log(...t) { 528 | t.length > 0 && (this.logs = [...this.logs, ...t]), 529 | console.log(t.join(this.logSeparator)) 530 | } 531 | logErr(t, e) { 532 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 533 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 534 | } 535 | wait(t) { 536 | return new Promise(e => setTimeout(e, t)) 537 | } 538 | done(t = {}) { 539 | const e = (new Date).getTime(), 540 | s = (e - this.startTime) / 1e3; 541 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), 542 | this.log(), 543 | (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 544 | } 545 | } 546 | (t, e) 547 | } 548 | -------------------------------------------------------------------------------- /bot_jd_bean_info.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 详细版京东京豆统计 3 | 4 | * 默认不发送通知。 5 | 6 | [task_local] 7 | #京豆详情统计 8 | 20 22 * * * jd_bean_info.js, tag=京豆详情统计, img-url=https://raw.githubusercontent.com/Orz-3/mini/master/Color/jd.png, enabled=true 9 | * */ 10 | const $ = new Env('京豆详情统计'); 11 | const jdCookieNode = $.isNode() ? require('./jdCookie.js') : ''; 12 | let allMessage = ''; 13 | let myMap = new Map(); 14 | let allBean = 0; 15 | let JinQibean=""; 16 | //IOS等用户直接用NobyDa的jd cookie 17 | let cookiesArr = [], cookie = ''; 18 | if ($.isNode()) { 19 | Object.keys(jdCookieNode).forEach((item) => { 20 | cookiesArr.push(jdCookieNode[item]) 21 | }) 22 | if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => {}; 23 | } else { 24 | cookiesArr = [$.getdata('CookieJD'), $.getdata('CookieJD2'), ...jsonParse($.getdata('CookiesJD') || "[]").map(item => item.cookie)].filter(item => !!item); 25 | } 26 | 27 | let intcheckckseq=999999; 28 | let strcheckck = process.env.BOTCHECKCODE; 29 | let lnShowTop = 0; 30 | if(!strcheckck){ 31 | console.log("【账号�】没有获取到要查询的账号"); 32 | return 33 | } 34 | if ($.isNode() && process.env.BOTShowTopNum) { 35 | lnShowTop = parseInt(process.env.BOTShowTopNum); 36 | } 37 | let lnShowJinQiNum = 3; 38 | if ($.isNode() && process.env.BOTShowJinQiNum) { 39 | lnShowJinQiNum = parseInt(process.env.BOTShowJinQiNum); 40 | } 41 | 42 | for (i = 0; i < cookiesArr.length; i++) { 43 | if (cookiesArr[i]) { 44 | cookie = cookiesArr[i]; 45 | $.pt_pin = (cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 46 | if (strcheckck == $.pt_pin) { 47 | intcheckckseq = i; 48 | break; 49 | } 50 | } 51 | } 52 | 53 | if (intcheckckseq == 999999) { 54 | if (IsNumber(strcheckck)) { 55 | if (parseInt(strcheckck) > cookiesArr.length) { 56 | console.log('【账号'+strcheckck+'🆔】你哪来那么多账号,没点逼数吗'); 57 | return 58 | } 59 | intcheckckseq = parseInt(strcheckck) - 1; 60 | } 61 | } 62 | console.log("当前查询的CK序号是:"+(intcheckckseq+1)); 63 | 64 | !(async() => { 65 | if (!cookiesArr[intcheckckseq]) { 66 | $.msg($.name, '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/bean/signIndex.action', { 67 | "open-url": "https://bean.m.jd.com/bean/signIndex.action" 68 | }); 69 | return; 70 | } 71 | i = intcheckckseq; 72 | 73 | if (cookiesArr[i]) { 74 | cookie = cookiesArr[i]; 75 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 76 | $.index = i + 1; 77 | $.beanCount = 0; 78 | $.incomeBean = 0; 79 | $.expenseBean = 0; 80 | $.todayIncomeBean = 0; 81 | $.errorMsg = ''; 82 | $.isLogin = true; 83 | $.nickName = ''; 84 | $.message = ''; 85 | $.balance = 0; 86 | $.expiredBalance = 0; 87 | await TotalBean(); 88 | //console.log(`\n********开始【京东账号${$.index}】${$.nickName || $.UserName}******\n`); 89 | if (!$.isLogin) { 90 | console.log(`【提示】cookie已失效,\n请重新登录获取\nhttps://bean.m.jd.com/bean/signIndex.action`); 91 | return; 92 | } 93 | await bean(); 94 | await showMsg(); 95 | 96 | } 97 | allMessage = `【账号🆔${(intcheckckseq+1)}详情统计】收入:${$.todayIncomeBean}京豆\n`+allMessage; 98 | console.log(`${allMessage}`); 99 | 100 | })() 101 | .catch((e) => { 102 | // $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') 103 | }) 104 | .finally(() => { 105 | $.done(); 106 | }) 107 | async function showMsg() { 108 | if ($.errorMsg) return 109 | 110 | var arrayObj=Array.from(myMap); 111 | arrayObj.sort(function(a,b){return a[1]-b[1]}) 112 | if(lnShowTop) 113 | allMessage += "【设定了隐藏" +lnShowTop+"豆以下的信息"+"】 "+'\n' 114 | for (var [key, value] of arrayObj) { 115 | /* allMessage += key + ' ---> ' +myMap.get(key)+'京豆\n' */ 116 | if(lnShowTop && lnShowTop>value) 117 | continue; 118 | allMessage += "【" +value+"豆"+"】 "+key+'\n' 119 | } 120 | if(JinQibean) 121 | allMessage += "\n\n【近期豆子】"+JinQibean; 122 | } 123 | function IsNumber(value) { 124 | intPerSent = parseInt(value); 125 | if (!intPerSent) 126 | return false; 127 | else 128 | return true; 129 | } 130 | async function bean() { 131 | // console.log(`北京时间零点时间戳:${parseInt((Date.now() + 28800000) / 86400000) * 86400000 - 28800000}`); 132 | // console.log(`北京时间2020-10-28 06:16:05::${new Date("2020/10/28 06:16:05+08:00").getTime()}`) 133 | // 不管哪个时区。得到都是当前时刻北京时间的时间戳 new Date().getTime() + new Date().getTimezoneOffset()*60*1000 + 8*60*60*1000 134 | 135 | //前一天的0:0:0时间戳 136 | const tm = parseInt((Date.now() + 28800000) / 86400000) * 86400000 - 28800000 - (24 * 60 * 60 * 1000); 137 | // 今天0:0:0时间戳 138 | const tm1 = parseInt((Date.now() + 28800000) / 86400000) * 86400000 - 28800000; 139 | let page = 1, t = 0, todayArr = []; 140 | var strtemp=""; 141 | do { 142 | let response = await getJingBeanBalanceDetail(page); 143 | //console.log(`第${page}页: ${JSON.stringify(response)}`); 144 | if (response && response.code === "0") { 145 | page++; 146 | let detailList = response.jingDetailList; 147 | if (detailList && detailList.length > 0) { 148 | for (let item of detailList) { 149 | if (lnShowJinQiNum-1>-1){ 150 | lnShowJinQiNum--; 151 | strtemp=adjuststring(item.eventMassage); 152 | JinQibean+="\n"+" "+showtime(new Date(item.date))+" "+"【" +item.amount+"豆"+"】"+strtemp 153 | } 154 | 155 | const date = item.date.replace(/-/g, '/') + "+08:00"; 156 | if (new Date(date).getTime() >= tm1 && (!item['eventMassage'].includes("退还") && !item['eventMassage'].includes("物流") && !item['eventMassage'].includes('扣赠'))) { 157 | todayArr.push(item); 158 | } else if (tm > new Date(date).getTime()) { 159 | t = 1; 160 | break; 161 | } 162 | } 163 | } else { 164 | $.errorMsg = `数据异常`; 165 | // $.msg($.name, ``, `账号${$.index}:${$.nickName}\n${$.errorMsg}`); 166 | t = 1; 167 | } 168 | } else if (response && response.code === "3") { 169 | // console.log(`cookie已过期,或者填写不规范,跳出`) 170 | t = 1; 171 | } else { 172 | // console.log(`未知情况:${JSON.stringify(response)}`); 173 | // console.log(`未知情况,跳出`) 174 | t = 1; 175 | } 176 | } while (t === 0); 177 | 178 | for (let item of todayArr) { 179 | if (Number(item.amount) > 0) { 180 | $.todayIncomeBean += Number(item.amount); 181 | strtemp=adjuststring(item.eventMassage); 182 | myMap.set(strtemp,0) 183 | } 184 | } 185 | for (let item of todayArr) { 186 | if (Number(item.amount) > 0) { 187 | strtemp=adjuststring(item.eventMassage); 188 | myMap.set(strtemp,parseInt(myMap.get(strtemp))+parseInt(item.amount)) 189 | } 190 | } 191 | } 192 | 193 | function showtime(date) { 194 | 195 | var timeString = ""; 196 | 197 | if ((date.getHours()) < 10) 198 | timeString += "0" + date.getHours() + ":"; 199 | else 200 | timeString += date.getHours() + ":"; 201 | 202 | if ((date.getMinutes()) < 10) 203 | timeString += "0" + date.getMinutes()+ ":" ; 204 | else 205 | timeString += date.getMinutes()+ ":" ; 206 | 207 | if ((date.getSeconds()) < 10) 208 | timeString += "0" + date.getSeconds(); 209 | else 210 | timeString += date.getSeconds(); 211 | 212 | return timeString; 213 | } 214 | 215 | function TotalBean() { 216 | return new Promise(async resolve => { 217 | const options = { 218 | url: "https://me-api.jd.com/user_new/info/GetJDUserInfoUnion", 219 | headers: { 220 | Host: "me-api.jd.com", 221 | Accept: "*/*", 222 | Connection: "keep-alive", 223 | Cookie: cookie, 224 | "User-Agent": $.isNode() ? (process.env.JD_USER_AGENT ? process.env.JD_USER_AGENT : (require('./USER_AGENTS').USER_AGENT)) : ($.getdata('JDUA') ? $.getdata('JDUA') : "jdapp;iPhone;9.4.4;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1"), 225 | "Accept-Language": "zh-cn", 226 | "Referer": "https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&", 227 | "Accept-Encoding": "gzip, deflate, br" 228 | } 229 | } 230 | $.get(options, (err, resp, data) => { 231 | try { 232 | if (err) { 233 | // $.logErr(err) 234 | } else { 235 | if (data) { 236 | data = JSON.parse(data); 237 | if (data['retcode'] === "1001") { 238 | $.isLogin = false; //cookie过期 239 | return; 240 | } 241 | if (data['retcode'] === "0" && data.data && data.data.hasOwnProperty("userInfo")) { 242 | $.nickName = data.data.userInfo.baseInfo.nickname; 243 | } 244 | if (data['retcode'] === '0' && data.data && data.data['assetInfo']) { 245 | $.beanCount = data.data && data.data['assetInfo']['beanNum']; 246 | } 247 | } else { 248 | $.log('京东服务器返回空数据'); 249 | } 250 | } 251 | } catch (e) { 252 | // $.logErr(e) 253 | } finally { 254 | resolve(); 255 | } 256 | }) 257 | }) 258 | } 259 | function getJingBeanBalanceDetail(page) { 260 | return new Promise(async resolve => { 261 | const options = { 262 | "url": `https://bean.m.jd.com/beanDetail/detail.json?page=${page}`, 263 | "body": `body=${escape(JSON.stringify({"pageSize": "20", "page": page.toString()}))}&appid=ld`, 264 | "headers": { 265 | 'User-Agent': "Mozilla/5.0 (Linux; Android 12; SM-G9880) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Mobile Safari/537.36 EdgA/106.0.1370.47", 266 | 'Content-Type': 'application/x-www-form-urlencoded', 267 | 'Cookie': cookie, 268 | } 269 | } 270 | $.post(options, (err, resp, data) => { 271 | try { 272 | if (err) { 273 | // console.log(`${JSON.stringify(err)}`) 274 | // console.log(`${$.name} API请求失败,请检查网路重试`) 275 | } else { 276 | if (data) { 277 | data = JSON.parse(data); 278 | // console.log(data) 279 | } else { 280 | // console.log(`京东服务器返回空数据`) 281 | } 282 | } 283 | } catch (e) { 284 | // $.logErr(e, resp) 285 | } finally { 286 | resolve(data); 287 | } 288 | }) 289 | }) 290 | } 291 | function queryexpirejingdou() { 292 | return new Promise(async resolve => { 293 | const options = { 294 | "url": `https://wq.jd.com/activep3/singjd/queryexpirejingdou?_=${Date.now()}&g_login_type=1&sceneval=2`, 295 | "headers": { 296 | "Accept": "*/*", 297 | "Accept-Encoding": "gzip, deflate, br", 298 | "Accept-Language": "zh-cn", 299 | "Connection": "keep-alive", 300 | "Cookie": cookie, 301 | "Host": "wq.jd.com", 302 | "Referer": "https://wqs.jd.com/promote/201801/bean/mybean.html", 303 | "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.1 Mobile/15E148 Safari/604.1" 304 | } 305 | } 306 | $.expirejingdou = 0; 307 | $.get(options, (err, resp, data) => { 308 | try { 309 | if (err) { 310 | // console.log(`${JSON.stringify(err)}`) 311 | // console.log(`${$.name} API请求失败,请检查网路重试`) 312 | } else { 313 | if (data) { 314 | // console.log(data) 315 | data = JSON.parse(data.slice(23, -13)); 316 | // console.log(data) 317 | if (data.ret === 0) { 318 | data['expirejingdou'].map(item => { 319 | // console.log(`${timeFormat(item['time'] * 1000)}日过期京豆:${item['expireamount']}\n`); 320 | $.expirejingdou += item['expireamount']; 321 | }) 322 | // if ($.expirejingdou > 0) { 323 | // $.message += `\n今日将过期:${$.expirejingdou}京豆 🐶`; 324 | // } 325 | } 326 | } else { 327 | // console.log(`京东服务器返回空数据`) 328 | } 329 | } 330 | } catch (e) { 331 | // $.logErr(e, resp) 332 | } finally { 333 | resolve(); 334 | } 335 | }) 336 | }) 337 | } 338 | function jsonParse(str) { 339 | if (typeof str == "string") { 340 | try { 341 | return JSON.parse(str); 342 | } catch (e) { 343 | // console.log(e); 344 | // $.msg($.name, '', '请勿随意在BoxJs输入框修改内容\n建议通过脚本去获取cookie') 345 | return []; 346 | } 347 | } 348 | } 349 | 350 | function adjuststring(streventMassage) { 351 | var strtemp = streventMassage; 352 | strtemp = strtemp.replace("参加[", "").replace("]-奖励", "").replace("]店铺活动-奖励", ""); 353 | strtemp = strtemp.replace("京东自营旗舰店", "(自营)").replace("京东自营官方旗舰店", "(自营官方)"); 354 | strtemp = strtemp.replace("(", "(").replace(")", ")"); 355 | strtemp = strtemp.replace("官方旗舰店", "(官方)"); 356 | strtemp = strtemp.replace("旗舰店", "(旗舰)").replace("专营店", "(专营)").replace("专卖店", "(专卖)"); 357 | strtemp = strtemp.replace("回答京东", "").replace("获取的奖励", ""); 358 | strtemp = strtemp.replace("评价官:", ""); 359 | strtemp = strtemp.replace("商品号:", ""); 360 | strtemp = strtemp.replace("订单号:", ""); 361 | strtemp = strtemp.replace(")奖励京豆", ""); 362 | strtemp = strtemp.replace(")评价官补发奖励京豆", ""); 363 | strtemp = strtemp.replace("PLUS会员使用京东支付银行卡", "PLUS京东支付"); 364 | 365 | return strtemp 366 | } 367 | 368 | function getRemark(strRemark) { 369 | var strTempRemark = ""; 370 | if (strRemark) { 371 | var Tempindex = strRemark.indexOf("@@"); 372 | if (Tempindex != -1) { 373 | var TempRemarkList = strRemark.split("@@"); 374 | strTempRemark=TempRemarkList[0]; 375 | } else{ 376 | strTempRemark=strRemark; 377 | } 378 | } 379 | 380 | return strTempRemark; 381 | } 382 | // prettier-ignore 383 | function Env(t, e) { "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 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, r) => { 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.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.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const i = this.getdata(t); if (i) 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 r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; const [o, h] = i.split("@"), n = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; 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), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let r = t; for (const t of i) if (r = Object(r)[t], void 0 === r) return s; return r } lodash_set(t, e, s) { return Object(t) !== 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), r = s ? this.getval(s) : ""; if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; try { const e = JSON.parse(h); this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const o = {}; this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) } } else s = this.setval(t, e); return s } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, e) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : 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 : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (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), e(t, s, i) })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t))) : this.isNode() && (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: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) })) } post(t, e = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.post(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) }); else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: s, ...i } = t; this.got.post(s, i).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) }) } } 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 } msg(e = t, s = "", i = "", r) { const o = t => { if (!t) return t; if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; if ("object" == typeof t) { if (this.isLoon()) { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } if (this.isQuanX()) { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; return { "open-url": e, "media-url": s } } if (this.isSurge()) { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } } }; if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !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) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) } 384 | -------------------------------------------------------------------------------- /jdCookie.js: -------------------------------------------------------------------------------- 1 | /* 2 | 此文件为Node.js专用。其他用户请忽略 3 | */ 4 | //此处填写京东账号cookie。 5 | let CookieJDs = [ 6 | '',//账号一ck,例:pt_key=XXX;pt_pin=XXX; 7 | '',//账号二ck,例:pt_key=XXX;pt_pin=XXX;如有更多,依次类推 8 | ] 9 | // 判断环境变量里面是否有京东ck 10 | if (process.env.JD_COOKIE) { 11 | if (process.env.JD_COOKIE.indexOf('&') > -1) { 12 | CookieJDs = process.env.JD_COOKIE.split('&'); 13 | } else if (process.env.JD_COOKIE.indexOf('\n') > -1) { 14 | CookieJDs = process.env.JD_COOKIE.split('\n'); 15 | } else { 16 | CookieJDs = [process.env.JD_COOKIE]; 17 | } 18 | } 19 | if (JSON.stringify(process.env).indexOf('GITHUB')>-1) { 20 | console.log(`请勿使用github action运行此脚本,无论你是从你自己的私库还是其他哪里拉取的源代码,都会导致我被封号\n`); 21 | !(async () => { 22 | await require('./sendNotify').sendNotify('提醒', `请勿使用github action、滥用github资源会封我仓库以及账号`) 23 | await process.exit(0); 24 | })() 25 | } 26 | CookieJDs = [...new Set(CookieJDs.filter(item => !!item))] 27 | console.log(`\n===============共${CookieJDs.length}个京东账号Cookie===============\n`); 28 | if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => {}; 29 | for (let i = 0; i < CookieJDs.length; i++) { 30 | if (!CookieJDs[i].match(/pt_pin=(.+?);/) || !CookieJDs[i].match(/pt_key=(.+?);/)) console.log(`\n提示:京东cookie 【${CookieJDs[i]}】填写不规范,可能会影响部分脚本正常使用。正确格式为: pt_key=xxx;pt_pin=xxx;(分号;不可少)\n`); 31 | const index = (i + 1 === 1) ? '' : (i + 1); 32 | exports['CookieJD' + index] = CookieJDs[i].trim(); 33 | } 34 | -------------------------------------------------------------------------------- /jd_CkSeq.js: -------------------------------------------------------------------------------- 1 | /* 2 | cron "0 0 * * *" jd_CheckCkSeq.js, tag:CK顺序调试工具by-ccwav 3 | */ 4 | const $ = new Env("CK顺序调试工具"); 5 | const { 6 | getEnvs 7 | } = require('./ql'); 8 | const notify = $.isNode() ? require('./sendNotify') : ''; 9 | const jdCookieNode = $.isNode() ? require("./jdCookie.js") : ""; 10 | let cookiesArr = []; 11 | if ($.isNode()) { 12 | Object.keys(jdCookieNode).forEach((item) => { 13 | cookiesArr.push(jdCookieNode[item]) 14 | }) 15 | } 16 | let WP_APP_TOKEN_ONE = ""; 17 | if ($.isNode()) { 18 | if (process.env.WP_APP_TOKEN_ONE) { 19 | WP_APP_TOKEN_ONE = process.env.WP_APP_TOKEN_ONE; 20 | } 21 | } 22 | 23 | let arrCkPtPin = []; 24 | let arrEnvPtPin = []; 25 | let arrEnvStatus = []; 26 | let arrEnvOnebyOne = []; 27 | let strCk = ""; 28 | let strNoFoundCk = ""; 29 | let strMessage = ""; 30 | let strNotify = ""; 31 | if ($.isNode() && process.env.SEQCK_DisableCKNOTIFY) { 32 | strNotify=process.env.SEQCK_DisableCKNOTIFY; 33 | console.log(`检测到设定了公告,禁用的CK将推送信息...`); 34 | strNotify = `【✨✨✨✨公告✨✨✨✨】\n`+strNotify; 35 | console.log(strNotify+"\n"); 36 | }else{ 37 | WP_APP_TOKEN_ONE = ""; 38 | } 39 | 40 | const fs = require('fs'); 41 | let TempCKUid = []; 42 | let strUidFile = '/ql/scripts/CK_WxPusherUid.json'; 43 | let UidFileexists = fs.existsSync(strUidFile); 44 | if (UidFileexists) { 45 | console.log("检测到一对一Uid文件WxPusherUid.json,载入..."); 46 | TempCKUid = fs.readFileSync(strUidFile, 'utf-8'); 47 | if (TempCKUid) { 48 | TempCKUid = TempCKUid.toString(); 49 | TempCKUid = JSON.parse(TempCKUid); 50 | } 51 | } 52 | 53 | !(async() => { 54 | 55 | const envs = await getEnvs(); 56 | for (let i = 0; i < envs.length; i++) { 57 | if (envs[i].value) { 58 | var tempptpin = decodeURIComponent(envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/) && envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 59 | arrEnvPtPin.push(tempptpin); 60 | arrEnvStatus.push(envs[i].status); 61 | var struuid=getuuid(envs[i].remarks,tempptpin) 62 | arrEnvOnebyOne.push(struuid); 63 | } 64 | } 65 | 66 | for (let i = 0; i < cookiesArr.length; i++) { 67 | if (cookiesArr[i]) { 68 | cookie = cookiesArr[i]; 69 | var tempptpin = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 70 | var intSeq = inArray(tempptpin, arrEnvPtPin); 71 | if (intSeq != -1) { 72 | arrCkPtPin.push(tempptpin); 73 | strCk += "【"+(intSeq+1) + "】" + tempptpin ; 74 | if (arrEnvOnebyOne[intSeq]) { 75 | strCk += "(已启用一对一推送)" 76 | } 77 | strCk +="\n"; 78 | } 79 | } 80 | } 81 | 82 | for (let i = 0; i < arrEnvPtPin.length; i++) { 83 | var tempptpin = arrEnvPtPin[i]; 84 | var intSeq = inArray(tempptpin, arrCkPtPin); 85 | if (intSeq == -1) { 86 | strNoFoundCk += "【" + (i + 1) + "】" + tempptpin; 87 | if (arrEnvStatus[i] == 1) { 88 | strNoFoundCk += "(已禁用)" 89 | if ($.isNode() && WP_APP_TOKEN_ONE) { 90 | await notify.sendNotifybyWxPucher("账号下线通知", strNotify, tempptpin,'\n\n本通知 By ccwav Mod',"账号下线通知"); 91 | await $.wait(1000); 92 | } 93 | } 94 | if (arrEnvOnebyOne[i]) { 95 | strNoFoundCk += "(已启用一对一推送)" 96 | } 97 | strNoFoundCk += "\n"; 98 | 99 | } 100 | } 101 | 102 | if (strNoFoundCk) { 103 | console.log("没有出现在今日CK队列中的账号: \n" + strNoFoundCk); 104 | strMessage+="没有出现在今日CK队列中的账号: \n" + strNoFoundCk; 105 | } 106 | 107 | console.log("\n今日执行任务的账号顺序: \n" + strCk); 108 | strMessage+="\n今日执行任务的账号顺序: \n" + strCk; 109 | 110 | if ($.isNode()) { 111 | await notify.sendNotify(`${$.name}`, strMessage); 112 | } 113 | return; 114 | })() 115 | .catch((e) => $.logErr(e)) 116 | .finally(() => $.done()); 117 | 118 | function inArray(search, array) { 119 | var lnSeq = -1; 120 | for (let i = 0; i < array.length; i++) { 121 | if (array[i] == search) { 122 | lnSeq = i; 123 | } 124 | } 125 | return parseInt(lnSeq); 126 | } 127 | 128 | 129 | function getuuid(strRemark, PtPin) { 130 | var strTempuuid = ""; 131 | if (strRemark) { 132 | var Tempindex = strRemark.indexOf("@@"); 133 | if (Tempindex != -1) { 134 | //console.log(PtPin + ": 检测到NVJDC的一对一格式,瑞思拜~!"); 135 | var TempRemarkList = strRemark.split("@@"); 136 | for (let j = 1; j < TempRemarkList.length; j++) { 137 | if (TempRemarkList[j]) { 138 | if (TempRemarkList[j].length > 4) { 139 | if (TempRemarkList[j].substring(0, 4) == "UID_") { 140 | strTempuuid = TempRemarkList[j]; 141 | break; 142 | } 143 | } 144 | } 145 | } 146 | } 147 | } 148 | if (!strTempuuid && TempCKUid) { 149 | //console.log("正在从CK_WxPusherUid文件中检索资料..."); 150 | for (let j = 0; j < TempCKUid.length; j++) { 151 | if (PtPin == decodeURIComponent(TempCKUid[j].pt_pin)) { 152 | strTempuuid = TempCKUid[j].Uid; 153 | break; 154 | } 155 | } 156 | } 157 | return strTempuuid; 158 | } 159 | 160 | // prettier-ignore 161 | function Env(t, e) { 162 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 163 | class s { 164 | constructor(t) { 165 | this.env = t 166 | } 167 | send(t, e = "GET") { 168 | t = "string" == typeof t ? { 169 | url: t 170 | } 171 | : t; 172 | let s = this.get; 173 | return "POST" === e && (s = this.post), 174 | new Promise((e, i) => { 175 | s.call(this, t, (t, s, r) => { 176 | t ? i(t) : e(s) 177 | }) 178 | }) 179 | } 180 | get(t) { 181 | return this.send.call(this.env, t) 182 | } 183 | post(t) { 184 | return this.send.call(this.env, t, "POST") 185 | } 186 | } 187 | return new class { 188 | constructor(t, e) { 189 | this.name = t, 190 | this.http = new s(this), 191 | this.data = null, 192 | this.dataFile = "box.dat", 193 | this.logs = [], 194 | this.isMute = !1, 195 | this.isNeedRewrite = !1, 196 | this.logSeparator = "\n", 197 | this.startTime = (new Date).getTime(), 198 | Object.assign(this, e), 199 | this.log("", `🔔${this.name}, 开始!`) 200 | } 201 | isNode() { 202 | return "undefined" != typeof module && !!module.exports 203 | } 204 | isQuanX() { 205 | return "undefined" != typeof $task 206 | } 207 | isSurge() { 208 | return "undefined" != typeof $httpClient && "undefined" == typeof $loon 209 | } 210 | isLoon() { 211 | return "undefined" != typeof $loon 212 | } 213 | toObj(t, e = null) { 214 | try { 215 | return JSON.parse(t) 216 | } catch { 217 | return e 218 | } 219 | } 220 | toStr(t, e = null) { 221 | try { 222 | return JSON.stringify(t) 223 | } catch { 224 | return e 225 | } 226 | } 227 | getjson(t, e) { 228 | let s = e; 229 | const i = this.getdata(t); 230 | if (i) 231 | try { 232 | s = JSON.parse(this.getdata(t)) 233 | } catch {} 234 | return s 235 | } 236 | setjson(t, e) { 237 | try { 238 | return this.setdata(JSON.stringify(t), e) 239 | } catch { 240 | return !1 241 | } 242 | } 243 | getScript(t) { 244 | return new Promise(e => { 245 | this.get({ 246 | url: t 247 | }, (t, s, i) => e(i)) 248 | }) 249 | } 250 | runScript(t, e) { 251 | return new Promise(s => { 252 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 253 | i = i ? i.replace(/\n/g, "").trim() : i; 254 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 255 | r = r ? 1 * r : 20, 256 | r = e && e.timeout ? e.timeout : r; 257 | const[o, h] = i.split("@"), 258 | n = { 259 | url: `http://${h}/v1/scripting/evaluate`, 260 | body: { 261 | script_text: t, 262 | mock_type: "cron", 263 | timeout: r 264 | }, 265 | headers: { 266 | "X-Key": o, 267 | Accept: "*/*" 268 | } 269 | }; 270 | this.post(n, (t, e, i) => s(i)) 271 | }).catch(t => this.logErr(t)) 272 | } 273 | loaddata() { 274 | if (!this.isNode()) 275 | return {}; { 276 | this.fs = this.fs ? this.fs : require("fs"), 277 | this.path = this.path ? this.path : require("path"); 278 | const t = this.path.resolve(this.dataFile), 279 | e = this.path.resolve(process.cwd(), this.dataFile), 280 | s = this.fs.existsSync(t), 281 | i = !s && this.fs.existsSync(e); 282 | if (!s && !i) 283 | return {}; { 284 | const i = s ? t : e; 285 | try { 286 | return JSON.parse(this.fs.readFileSync(i)) 287 | } catch (t) { 288 | return {} 289 | } 290 | } 291 | } 292 | } 293 | writedata() { 294 | if (this.isNode()) { 295 | this.fs = this.fs ? this.fs : require("fs"), 296 | this.path = this.path ? this.path : require("path"); 297 | const t = this.path.resolve(this.dataFile), 298 | e = this.path.resolve(process.cwd(), this.dataFile), 299 | s = this.fs.existsSync(t), 300 | i = !s && this.fs.existsSync(e), 301 | r = JSON.stringify(this.data); 302 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 303 | } 304 | } 305 | lodash_get(t, e, s) { 306 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 307 | let r = t; 308 | for (const t of i) 309 | if (r = Object(r)[t], void 0 === r) 310 | return s; 311 | return r 312 | } 313 | lodash_set(t, e, s) { 314 | return Object(t) !== 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) 315 | } 316 | getdata(t) { 317 | let e = this.getval(t); 318 | if (/^@/.test(t)) { 319 | const[, s, i] = /^@(.*?)\.(.*?)$/.exec(t), 320 | r = s ? this.getval(s) : ""; 321 | if (r) 322 | try { 323 | const t = JSON.parse(r); 324 | e = t ? this.lodash_get(t, i, "") : e 325 | } catch (t) { 326 | e = "" 327 | } 328 | } 329 | return e 330 | } 331 | setdata(t, e) { 332 | let s = !1; 333 | if (/^@/.test(e)) { 334 | const[, i, r] = /^@(.*?)\.(.*?)$/.exec(e), 335 | o = this.getval(i), 336 | h = i ? "null" === o ? null : o || "{}" : "{}"; 337 | try { 338 | const e = JSON.parse(h); 339 | this.lodash_set(e, r, t), 340 | s = this.setval(JSON.stringify(e), i) 341 | } catch (e) { 342 | const o = {}; 343 | this.lodash_set(o, r, t), 344 | s = this.setval(JSON.stringify(o), i) 345 | } 346 | } else 347 | s = this.setval(t, e); 348 | return s 349 | } 350 | getval(t) { 351 | return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null 352 | } 353 | setval(t, e) { 354 | return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null 355 | } 356 | initGotEnv(t) { 357 | this.got = this.got ? this.got : require("got"), 358 | this.cktough = this.cktough ? this.cktough : require("tough-cookie"), 359 | this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, 360 | t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) 361 | } 362 | get(t, e = (() => {})) { 363 | t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), 364 | this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { 365 | "X-Surge-Skip-Scripting": !1 366 | })), $httpClient.get(t, (t, s, i) => { 367 | !t && s && (s.body = i, s.statusCode = s.status), 368 | e(t, s, i) 369 | })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 370 | hints: !1 371 | })), $task.fetch(t).then(t => { 372 | const { 373 | statusCode: s, 374 | statusCode: i, 375 | headers: r, 376 | body: o 377 | } = t; 378 | e(null, { 379 | status: s, 380 | statusCode: i, 381 | headers: r, 382 | body: o 383 | }, o) 384 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 385 | try { 386 | if (t.headers["set-cookie"]) { 387 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 388 | s && this.ckjar.setCookieSync(s, null), 389 | e.cookieJar = this.ckjar 390 | } 391 | } catch (t) { 392 | this.logErr(t) 393 | } 394 | }).then(t => { 395 | const { 396 | statusCode: s, 397 | statusCode: i, 398 | headers: r, 399 | body: o 400 | } = t; 401 | e(null, { 402 | status: s, 403 | statusCode: i, 404 | headers: r, 405 | body: o 406 | }, o) 407 | }, t => { 408 | const { 409 | message: s, 410 | response: i 411 | } = t; 412 | e(s, i, i && i.body) 413 | })) 414 | } 415 | post(t, e = (() => {})) { 416 | if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) 417 | this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { 418 | "X-Surge-Skip-Scripting": !1 419 | })), $httpClient.post(t, (t, s, i) => { 420 | !t && s && (s.body = i, s.statusCode = s.status), 421 | e(t, s, i) 422 | }); 423 | else if (this.isQuanX()) 424 | t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 425 | hints: !1 426 | })), $task.fetch(t).then(t => { 427 | const { 428 | statusCode: s, 429 | statusCode: i, 430 | headers: r, 431 | body: o 432 | } = t; 433 | e(null, { 434 | status: s, 435 | statusCode: i, 436 | headers: r, 437 | body: o 438 | }, o) 439 | }, t => e(t)); 440 | else if (this.isNode()) { 441 | this.initGotEnv(t); 442 | const { 443 | url: s, 444 | ...i 445 | } = t; 446 | this.got.post(s, i).then(t => { 447 | const { 448 | statusCode: s, 449 | statusCode: i, 450 | headers: r, 451 | body: o 452 | } = t; 453 | e(null, { 454 | status: s, 455 | statusCode: i, 456 | headers: r, 457 | body: o 458 | }, o) 459 | }, t => { 460 | const { 461 | message: s, 462 | response: i 463 | } = t; 464 | e(s, i, i && i.body) 465 | }) 466 | } 467 | } 468 | time(t, e = null) { 469 | const s = e ? new Date(e) : new Date; 470 | let i = { 471 | "M+": s.getMonth() + 1, 472 | "d+": s.getDate(), 473 | "H+": s.getHours(), 474 | "m+": s.getMinutes(), 475 | "s+": s.getSeconds(), 476 | "q+": Math.floor((s.getMonth() + 3) / 3), 477 | S: s.getMilliseconds() 478 | }; 479 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 480 | for (let e in i) 481 | new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); 482 | return t 483 | } 484 | msg(e = t, s = "", i = "", r) { 485 | const o = t => { 486 | if (!t) 487 | return t; 488 | if ("string" == typeof t) 489 | return this.isLoon() ? t : this.isQuanX() ? { 490 | "open-url": t 491 | } 492 | : this.isSurge() ? { 493 | url: t 494 | } 495 | : void 0; 496 | if ("object" == typeof t) { 497 | if (this.isLoon()) { 498 | let e = t.openUrl || t.url || t["open-url"], 499 | s = t.mediaUrl || t["media-url"]; 500 | return { 501 | openUrl: e, 502 | mediaUrl: s 503 | } 504 | } 505 | if (this.isQuanX()) { 506 | let e = t["open-url"] || t.url || t.openUrl, 507 | s = t["media-url"] || t.mediaUrl; 508 | return { 509 | "open-url": e, 510 | "media-url": s 511 | } 512 | } 513 | if (this.isSurge()) { 514 | let e = t.url || t.openUrl || t["open-url"]; 515 | return { 516 | url: e 517 | } 518 | } 519 | } 520 | }; 521 | if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { 522 | let t = ["", "==============📣系统通知📣=============="]; 523 | t.push(e), 524 | s && t.push(s), 525 | i && t.push(i), 526 | console.log(t.join("\n")), 527 | this.logs = this.logs.concat(t) 528 | } 529 | } 530 | log(...t) { 531 | t.length > 0 && (this.logs = [...this.logs, ...t]), 532 | console.log(t.join(this.logSeparator)) 533 | } 534 | logErr(t, e) { 535 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 536 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 537 | } 538 | wait(t) { 539 | return new Promise(e => setTimeout(e, t)) 540 | } 541 | done(t = {}) { 542 | const e = (new Date).getTime(), 543 | s = (e - this.startTime) / 1e3; 544 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), 545 | this.log(), 546 | (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 547 | } 548 | } 549 | (t, e) 550 | } 551 | -------------------------------------------------------------------------------- /jd_UpdateUIDtoRemark.js: -------------------------------------------------------------------------------- 1 | /* 2 | cron "30 10 * * *" jd_UpdateUIDtoRemark.js, tag:Uid迁移工具 3 | */ 4 | 5 | const $ = new Env('WxPusherUid迁移工具'); 6 | const notify = $.isNode() ? require('./sendNotify') : ''; 7 | //Node.js用户请在jdCookie.js处填写京东ck; 8 | const jdCookieNode = $.isNode() ? require('./jdCookie.js') : ''; 9 | const got = require('got'); 10 | const { 11 | getEnvs, 12 | getEnvById, 13 | DisableCk, 14 | EnableCk, 15 | updateEnv, 16 | updateEnv11, 17 | getstatus 18 | } = require('./ql'); 19 | 20 | let strUidFile = '/ql/scripts/CK_WxPusherUid.json'; 21 | const fs = require('fs'); 22 | let UidFileexists = fs.existsSync(strUidFile); 23 | let TempCKUid = []; 24 | if (UidFileexists) { 25 | console.log("检测到WxPusherUid文件,载入..."); 26 | TempCKUid = fs.readFileSync(strUidFile, 'utf-8'); 27 | if (TempCKUid) { 28 | TempCKUid = TempCKUid.toString(); 29 | TempCKUid = JSON.parse(TempCKUid); 30 | } 31 | } 32 | 33 | 34 | !(async() => { 35 | const envs = await getEnvs(); 36 | if (!envs[0]) { 37 | $.msg($.name, '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/bean/signIndex.action', { 38 | "open-url": "https://bean.m.jd.com/bean/signIndex.action" 39 | }); 40 | return; 41 | } 42 | var struid = ""; 43 | var strRemark = ""; 44 | for (let i = 0; i < envs.length; i++) { 45 | if (envs[i].value) { 46 | var tempid = 0; 47 | if(envs[i]._id) 48 | tempid = envs[i]._id; 49 | if(envs[i].id) 50 | tempid = envs[i].id; 51 | 52 | cookie = await getEnvById(tempid); 53 | 54 | if(!cookie) 55 | continue; 56 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 57 | $.index = i + 1; 58 | console.log(`\n**********检测【京东账号${$.index}】${$.UserName}**********\n`); 59 | strRemark = envs[i].remarks; 60 | struid = getuuid(strRemark, $.UserName); 61 | if (struid) { 62 | //这是为了处理ninjia的remark格式 63 | strRemark = strRemark.replace("remark=", ""); 64 | strRemark = strRemark.replace(";", ""); 65 | 66 | var Tempindex = strRemark.indexOf("@@"); 67 | if (Tempindex != -1) { 68 | strRemark = strRemark + "@@" + struid; 69 | } else { 70 | var DateTimestamp = new Date(envs[i].timestamp); 71 | strRemark = strRemark + "@@" + DateTimestamp.getTime() + "@@" + struid; 72 | } 73 | 74 | if (envs[i]._id) { 75 | var updateEnvBody = await updateEnv(cookie, envs[i]._id, strRemark); 76 | 77 | if (updateEnvBody.code == 200) 78 | console.log("更新Remark成功!"); 79 | else 80 | console.log("更新Remark失败!"); 81 | } 82 | if (envs[i].id) { 83 | var updateEnvBody = await updateEnv11(cookie, envs[i].id, strRemark); 84 | 85 | if (updateEnvBody.code == 200) 86 | console.log("新版青龙更新Remark成功!"); 87 | else 88 | console.log("新版青龙更新Remark失败!"); 89 | } 90 | 91 | } 92 | } 93 | } 94 | 95 | })() 96 | .catch((e) => $.logErr(e)) 97 | .finally(() => $.done()) 98 | 99 | function getuuid(strRemark, PtPin) { 100 | var strTempuuid = ""; 101 | var strUid = ""; 102 | if (strRemark) { 103 | var Tempindex = strRemark.indexOf("@@"); 104 | if (Tempindex != -1) { 105 | var TempRemarkList = strRemark.split("@@"); 106 | for (let j = 1; j < TempRemarkList.length; j++) { 107 | if (TempRemarkList[j]) { 108 | if (TempRemarkList[j].length > 4) { 109 | if (TempRemarkList[j].substring(0, 4) == "UID_") { 110 | strTempuuid = TempRemarkList[j]; 111 | break; 112 | } 113 | } 114 | } 115 | } 116 | } 117 | } 118 | if (!strTempuuid && TempCKUid) { 119 | console.log(`查询uid`); 120 | for (let j = 0; j < TempCKUid.length; j++) { 121 | if (PtPin == decodeURIComponent(TempCKUid[j].pt_pin)) { 122 | strUid = TempCKUid[j].Uid; 123 | break; 124 | } 125 | } 126 | } 127 | console.log(`uid:`+strUid); 128 | return strUid; 129 | } 130 | 131 | // prettier-ignore 132 | function Env(t, e) { 133 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 134 | class s { 135 | constructor(t) { 136 | this.env = t 137 | } 138 | send(t, e = "GET") { 139 | t = "string" == typeof t ? { 140 | url: t 141 | } 142 | : t; 143 | let s = this.get; 144 | return "POST" === e && (s = this.post), 145 | new Promise((e, i) => { 146 | s.call(this, t, (t, s, r) => { 147 | t ? i(t) : e(s) 148 | }) 149 | }) 150 | } 151 | get(t) { 152 | return this.send.call(this.env, t) 153 | } 154 | post(t) { 155 | return this.send.call(this.env, t, "POST") 156 | } 157 | } 158 | return new class { 159 | constructor(t, e) { 160 | this.name = t, 161 | this.http = new s(this), 162 | this.data = null, 163 | this.dataFile = "box.dat", 164 | this.logs = [], 165 | this.isMute = !1, 166 | this.isNeedRewrite = !1, 167 | this.logSeparator = "\n", 168 | this.startTime = (new Date).getTime(), 169 | Object.assign(this, e), 170 | this.log("", `🔔${this.name}, 开始!`) 171 | } 172 | isNode() { 173 | return "undefined" != typeof module && !!module.exports 174 | } 175 | isQuanX() { 176 | return "undefined" != typeof $task 177 | } 178 | isSurge() { 179 | return "undefined" != typeof $httpClient && "undefined" == typeof $loon 180 | } 181 | isLoon() { 182 | return "undefined" != typeof $loon 183 | } 184 | toObj(t, e = null) { 185 | try { 186 | return JSON.parse(t) 187 | } catch { 188 | return e 189 | } 190 | } 191 | toStr(t, e = null) { 192 | try { 193 | return JSON.stringify(t) 194 | } catch { 195 | return e 196 | } 197 | } 198 | getjson(t, e) { 199 | let s = e; 200 | const i = this.getdata(t); 201 | if (i) 202 | try { 203 | s = JSON.parse(this.getdata(t)) 204 | } catch {} 205 | return s 206 | } 207 | setjson(t, e) { 208 | try { 209 | return this.setdata(JSON.stringify(t), e) 210 | } catch { 211 | return !1 212 | } 213 | } 214 | getScript(t) { 215 | return new Promise(e => { 216 | this.get({ 217 | url: t 218 | }, (t, s, i) => e(i)) 219 | }) 220 | } 221 | runScript(t, e) { 222 | return new Promise(s => { 223 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 224 | i = i ? i.replace(/\n/g, "").trim() : i; 225 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 226 | r = r ? 1 * r : 20, 227 | r = e && e.timeout ? e.timeout : r; 228 | const[o, h] = i.split("@"), 229 | n = { 230 | url: `http://${h}/v1/scripting/evaluate`, 231 | body: { 232 | script_text: t, 233 | mock_type: "cron", 234 | timeout: r 235 | }, 236 | headers: { 237 | "X-Key": o, 238 | Accept: "*/*" 239 | } 240 | }; 241 | this.post(n, (t, e, i) => s(i)) 242 | }).catch(t => this.logErr(t)) 243 | } 244 | loaddata() { 245 | if (!this.isNode()) 246 | return {}; { 247 | this.fs = this.fs ? this.fs : require("fs"), 248 | this.path = this.path ? this.path : require("path"); 249 | const t = this.path.resolve(this.dataFile), 250 | e = this.path.resolve(process.cwd(), this.dataFile), 251 | s = this.fs.existsSync(t), 252 | i = !s && this.fs.existsSync(e); 253 | if (!s && !i) 254 | return {}; { 255 | const i = s ? t : e; 256 | try { 257 | return JSON.parse(this.fs.readFileSync(i)) 258 | } catch (t) { 259 | return {} 260 | } 261 | } 262 | } 263 | } 264 | writedata() { 265 | if (this.isNode()) { 266 | this.fs = this.fs ? this.fs : require("fs"), 267 | this.path = this.path ? this.path : require("path"); 268 | const t = this.path.resolve(this.dataFile), 269 | e = this.path.resolve(process.cwd(), this.dataFile), 270 | s = this.fs.existsSync(t), 271 | i = !s && this.fs.existsSync(e), 272 | r = JSON.stringify(this.data); 273 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 274 | } 275 | } 276 | lodash_get(t, e, s) { 277 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 278 | let r = t; 279 | for (const t of i) 280 | if (r = Object(r)[t], void 0 === r) 281 | return s; 282 | return r 283 | } 284 | lodash_set(t, e, s) { 285 | return Object(t) !== 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) 286 | } 287 | getdata(t) { 288 | let e = this.getval(t); 289 | if (/^@/.test(t)) { 290 | const[, s, i] = /^@(.*?)\.(.*?)$/.exec(t), 291 | r = s ? this.getval(s) : ""; 292 | if (r) 293 | try { 294 | const t = JSON.parse(r); 295 | e = t ? this.lodash_get(t, i, "") : e 296 | } catch (t) { 297 | e = "" 298 | } 299 | } 300 | return e 301 | } 302 | setdata(t, e) { 303 | let s = !1; 304 | if (/^@/.test(e)) { 305 | const[, i, r] = /^@(.*?)\.(.*?)$/.exec(e), 306 | o = this.getval(i), 307 | h = i ? "null" === o ? null : o || "{}" : "{}"; 308 | try { 309 | const e = JSON.parse(h); 310 | this.lodash_set(e, r, t), 311 | s = this.setval(JSON.stringify(e), i) 312 | } catch (e) { 313 | const o = {}; 314 | this.lodash_set(o, r, t), 315 | s = this.setval(JSON.stringify(o), i) 316 | } 317 | } else 318 | s = this.setval(t, e); 319 | return s 320 | } 321 | getval(t) { 322 | return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null 323 | } 324 | setval(t, e) { 325 | return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null 326 | } 327 | initGotEnv(t) { 328 | this.got = this.got ? this.got : require("got"), 329 | this.cktough = this.cktough ? this.cktough : require("tough-cookie"), 330 | this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, 331 | t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) 332 | } 333 | get(t, e = (() => {})) { 334 | t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), 335 | this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { 336 | "X-Surge-Skip-Scripting": !1 337 | })), $httpClient.get(t, (t, s, i) => { 338 | !t && s && (s.body = i, s.statusCode = s.status), 339 | e(t, s, i) 340 | })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 341 | hints: !1 342 | })), $task.fetch(t).then(t => { 343 | const { 344 | statusCode: s, 345 | statusCode: i, 346 | headers: r, 347 | body: o 348 | } = t; 349 | e(null, { 350 | status: s, 351 | statusCode: i, 352 | headers: r, 353 | body: o 354 | }, o) 355 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 356 | try { 357 | if (t.headers["set-cookie"]) { 358 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 359 | s && this.ckjar.setCookieSync(s, null), 360 | e.cookieJar = this.ckjar 361 | } 362 | } catch (t) { 363 | this.logErr(t) 364 | } 365 | }).then(t => { 366 | const { 367 | statusCode: s, 368 | statusCode: i, 369 | headers: r, 370 | body: o 371 | } = t; 372 | e(null, { 373 | status: s, 374 | statusCode: i, 375 | headers: r, 376 | body: o 377 | }, o) 378 | }, t => { 379 | const { 380 | message: s, 381 | response: i 382 | } = t; 383 | e(s, i, i && i.body) 384 | })) 385 | } 386 | post(t, e = (() => {})) { 387 | if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) 388 | this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { 389 | "X-Surge-Skip-Scripting": !1 390 | })), $httpClient.post(t, (t, s, i) => { 391 | !t && s && (s.body = i, s.statusCode = s.status), 392 | e(t, s, i) 393 | }); 394 | else if (this.isQuanX()) 395 | t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 396 | hints: !1 397 | })), $task.fetch(t).then(t => { 398 | const { 399 | statusCode: s, 400 | statusCode: i, 401 | headers: r, 402 | body: o 403 | } = t; 404 | e(null, { 405 | status: s, 406 | statusCode: i, 407 | headers: r, 408 | body: o 409 | }, o) 410 | }, t => e(t)); 411 | else if (this.isNode()) { 412 | this.initGotEnv(t); 413 | const { 414 | url: s, 415 | ...i 416 | } = t; 417 | this.got.post(s, i).then(t => { 418 | const { 419 | statusCode: s, 420 | statusCode: i, 421 | headers: r, 422 | body: o 423 | } = t; 424 | e(null, { 425 | status: s, 426 | statusCode: i, 427 | headers: r, 428 | body: o 429 | }, o) 430 | }, t => { 431 | const { 432 | message: s, 433 | response: i 434 | } = t; 435 | e(s, i, i && i.body) 436 | }) 437 | } 438 | } 439 | time(t, e = null) { 440 | const s = e ? new Date(e) : new Date; 441 | let i = { 442 | "M+": s.getMonth() + 1, 443 | "d+": s.getDate(), 444 | "H+": s.getHours(), 445 | "m+": s.getMinutes(), 446 | "s+": s.getSeconds(), 447 | "q+": Math.floor((s.getMonth() + 3) / 3), 448 | S: s.getMilliseconds() 449 | }; 450 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 451 | for (let e in i) 452 | new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); 453 | return t 454 | } 455 | msg(e = t, s = "", i = "", r) { 456 | const o = t => { 457 | if (!t) 458 | return t; 459 | if ("string" == typeof t) 460 | return this.isLoon() ? t : this.isQuanX() ? { 461 | "open-url": t 462 | } 463 | : this.isSurge() ? { 464 | url: t 465 | } 466 | : void 0; 467 | if ("object" == typeof t) { 468 | if (this.isLoon()) { 469 | let e = t.openUrl || t.url || t["open-url"], 470 | s = t.mediaUrl || t["media-url"]; 471 | return { 472 | openUrl: e, 473 | mediaUrl: s 474 | } 475 | } 476 | if (this.isQuanX()) { 477 | let e = t["open-url"] || t.url || t.openUrl, 478 | s = t["media-url"] || t.mediaUrl; 479 | return { 480 | "open-url": e, 481 | "media-url": s 482 | } 483 | } 484 | if (this.isSurge()) { 485 | let e = t.url || t.openUrl || t["open-url"]; 486 | return { 487 | url: e 488 | } 489 | } 490 | } 491 | }; 492 | if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { 493 | let t = ["", "==============📣系统通知📣=============="]; 494 | t.push(e), 495 | s && t.push(s), 496 | i && t.push(i), 497 | console.log(t.join("\n")), 498 | this.logs = this.logs.concat(t) 499 | } 500 | } 501 | log(...t) { 502 | t.length > 0 && (this.logs = [...this.logs, ...t]), 503 | console.log(t.join(this.logSeparator)) 504 | } 505 | logErr(t, e) { 506 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 507 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 508 | } 509 | wait(t) { 510 | return new Promise(e => setTimeout(e, t)) 511 | } 512 | done(t = {}) { 513 | const e = (new Date).getTime(), 514 | s = (e - this.startTime) / 1e3; 515 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), 516 | this.log(), 517 | (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 518 | } 519 | } 520 | (t, e) 521 | } 522 | -------------------------------------------------------------------------------- /jd_notify.js: -------------------------------------------------------------------------------- 1 | /* 2 | cron "6 6 6 6 6" jd_notify.js, tag:一对一通知工具 3 | */ 4 | const $ = new Env("一对一通知工具"); 5 | const jdCookieNode = $.isNode() ? require('./jdCookie.js') : ''; 6 | const notify = $.isNode() ? require('./sendNotify') : ''; 7 | let cookiesArr = [], cookie = ''; 8 | let WP_APP_TOKEN_ONE=""; 9 | let strNotify=""; 10 | let strTitle=""; 11 | if ($.isNode()) { 12 | if (process.env.WP_APP_TOKEN_ONE) { 13 | WP_APP_TOKEN_ONE = process.env.WP_APP_TOKEN_ONE; 14 | } 15 | } 16 | if(WP_APP_TOKEN_ONE) 17 | console.log(`检测到已配置Wxpusher的Token,启用一对一推送...`); 18 | else{ 19 | console.log(`检测到未配置Wxpusher的Token,退出进程...`); 20 | return 21 | } 22 | 23 | if ($.isNode() && process.env.NOTIFY_TITLE && process.env.NOTIFY_INFO) { 24 | strTitle=process.env.NOTIFY_TITLE; 25 | strNotify=process.env.NOTIFY_INFO; 26 | console.log(`检测到设定了通知...`); 27 | strNotify = `【✨✨✨✨通知✨✨✨✨】\n`+strNotify; 28 | console.log(strNotify+"\n"); 29 | } else { 30 | console.log(`未检测到通知设定,请配置变量NOTIFY_TITLE和NOTIFY_INFO后再执行...`); 31 | return 32 | } 33 | 34 | if ($.isNode()) { 35 | Object.keys(jdCookieNode).forEach((item) => { 36 | cookiesArr.push(jdCookieNode[item]) 37 | }) 38 | if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') 39 | console.log = () => {}; 40 | } else { 41 | cookiesArr = [$.getdata('CookieJD'), $.getdata('CookieJD2'), ...jsonParse($.getdata('CookiesJD') || "[]").map(item => item.cookie)].filter(item => !!item); 42 | } 43 | 44 | 45 | !(async() => { 46 | if (!cookiesArr[0]) { 47 | $.msg($.name, '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/bean/signIndex.action', { 48 | "open-url": "https://bean.m.jd.com/bean/signIndex.action" 49 | }); 50 | return; 51 | } 52 | for (i = 0; i < cookiesArr.length; i++) { 53 | if (cookiesArr[i]) { 54 | cookie = cookiesArr[i]; 55 | $.pt_pin = (cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 56 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 57 | console.log(`******开始发送【京东账号${(i+1)}】${$.UserName}*********`); 58 | if ($.isNode()) { 59 | await notify.sendNotifybyWxPucher("有您的消息,请点击查看", `${strNotify}`, `${$.UserName}`,'\n\n本通知 By ccwav Mod',strTitle); 60 | } 61 | } 62 | } 63 | })() 64 | .catch((e) => { 65 | $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') 66 | }) 67 | .finally(() => { 68 | $.done(); 69 | }) 70 | 71 | // prettier-ignore 72 | function Env(t, e) { 73 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 74 | class s { 75 | constructor(t) { 76 | this.env = t 77 | } 78 | send(t, e = "GET") { 79 | t = "string" == typeof t ? { 80 | url: t 81 | } 82 | : t; 83 | let s = this.get; 84 | return "POST" === e && (s = this.post), 85 | new Promise((e, i) => { 86 | s.call(this, t, (t, s, r) => { 87 | t ? i(t) : e(s) 88 | }) 89 | }) 90 | } 91 | get(t) { 92 | return this.send.call(this.env, t) 93 | } 94 | post(t) { 95 | return this.send.call(this.env, t, "POST") 96 | } 97 | } 98 | return new class { 99 | constructor(t, e) { 100 | this.name = t, 101 | this.http = new s(this), 102 | this.data = null, 103 | this.dataFile = "box.dat", 104 | this.logs = [], 105 | this.isMute = !1, 106 | this.isNeedRewrite = !1, 107 | this.logSeparator = "\n", 108 | this.startTime = (new Date).getTime(), 109 | Object.assign(this, e), 110 | this.log("", `🔔${this.name}, 开始!`) 111 | } 112 | isNode() { 113 | return "undefined" != typeof module && !!module.exports 114 | } 115 | isQuanX() { 116 | return "undefined" != typeof $task 117 | } 118 | isSurge() { 119 | return "undefined" != typeof $httpClient && "undefined" == typeof $loon 120 | } 121 | isLoon() { 122 | return "undefined" != typeof $loon 123 | } 124 | toObj(t, e = null) { 125 | try { 126 | return JSON.parse(t) 127 | } catch { 128 | return e 129 | } 130 | } 131 | toStr(t, e = null) { 132 | try { 133 | return JSON.stringify(t) 134 | } catch { 135 | return e 136 | } 137 | } 138 | getjson(t, e) { 139 | let s = e; 140 | const i = this.getdata(t); 141 | if (i) 142 | try { 143 | s = JSON.parse(this.getdata(t)) 144 | } catch {} 145 | return s 146 | } 147 | setjson(t, e) { 148 | try { 149 | return this.setdata(JSON.stringify(t), e) 150 | } catch { 151 | return !1 152 | } 153 | } 154 | getScript(t) { 155 | return new Promise(e => { 156 | this.get({ 157 | url: t 158 | }, (t, s, i) => e(i)) 159 | }) 160 | } 161 | runScript(t, e) { 162 | return new Promise(s => { 163 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 164 | i = i ? i.replace(/\n/g, "").trim() : i; 165 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 166 | r = r ? 1 * r : 20, 167 | r = e && e.timeout ? e.timeout : r; 168 | const[o, h] = i.split("@"), 169 | n = { 170 | url: `http://${h}/v1/scripting/evaluate`, 171 | body: { 172 | script_text: t, 173 | mock_type: "cron", 174 | timeout: r 175 | }, 176 | headers: { 177 | "X-Key": o, 178 | Accept: "*/*" 179 | } 180 | }; 181 | this.post(n, (t, e, i) => s(i)) 182 | }).catch(t => this.logErr(t)) 183 | } 184 | loaddata() { 185 | if (!this.isNode()) 186 | return {}; { 187 | this.fs = this.fs ? this.fs : require("fs"), 188 | this.path = this.path ? this.path : require("path"); 189 | const t = this.path.resolve(this.dataFile), 190 | e = this.path.resolve(process.cwd(), this.dataFile), 191 | s = this.fs.existsSync(t), 192 | i = !s && this.fs.existsSync(e); 193 | if (!s && !i) 194 | return {}; { 195 | const i = s ? t : e; 196 | try { 197 | return JSON.parse(this.fs.readFileSync(i)) 198 | } catch (t) { 199 | return {} 200 | } 201 | } 202 | } 203 | } 204 | writedata() { 205 | if (this.isNode()) { 206 | this.fs = this.fs ? this.fs : require("fs"), 207 | this.path = this.path ? this.path : require("path"); 208 | const t = this.path.resolve(this.dataFile), 209 | e = this.path.resolve(process.cwd(), this.dataFile), 210 | s = this.fs.existsSync(t), 211 | i = !s && this.fs.existsSync(e), 212 | r = JSON.stringify(this.data); 213 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 214 | } 215 | } 216 | lodash_get(t, e, s) { 217 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 218 | let r = t; 219 | for (const t of i) 220 | if (r = Object(r)[t], void 0 === r) 221 | return s; 222 | return r 223 | } 224 | lodash_set(t, e, s) { 225 | return Object(t) !== 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) 226 | } 227 | getdata(t) { 228 | let e = this.getval(t); 229 | if (/^@/.test(t)) { 230 | const[, s, i] = /^@(.*?)\.(.*?)$/.exec(t), 231 | r = s ? this.getval(s) : ""; 232 | if (r) 233 | try { 234 | const t = JSON.parse(r); 235 | e = t ? this.lodash_get(t, i, "") : e 236 | } catch (t) { 237 | e = "" 238 | } 239 | } 240 | return e 241 | } 242 | setdata(t, e) { 243 | let s = !1; 244 | if (/^@/.test(e)) { 245 | const[, i, r] = /^@(.*?)\.(.*?)$/.exec(e), 246 | o = this.getval(i), 247 | h = i ? "null" === o ? null : o || "{}" : "{}"; 248 | try { 249 | const e = JSON.parse(h); 250 | this.lodash_set(e, r, t), 251 | s = this.setval(JSON.stringify(e), i) 252 | } catch (e) { 253 | const o = {}; 254 | this.lodash_set(o, r, t), 255 | s = this.setval(JSON.stringify(o), i) 256 | } 257 | } else 258 | s = this.setval(t, e); 259 | return s 260 | } 261 | getval(t) { 262 | return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null 263 | } 264 | setval(t, e) { 265 | return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null 266 | } 267 | initGotEnv(t) { 268 | this.got = this.got ? this.got : require("got"), 269 | this.cktough = this.cktough ? this.cktough : require("tough-cookie"), 270 | this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, 271 | t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) 272 | } 273 | get(t, e = (() => {})) { 274 | t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), 275 | this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { 276 | "X-Surge-Skip-Scripting": !1 277 | })), $httpClient.get(t, (t, s, i) => { 278 | !t && s && (s.body = i, s.statusCode = s.status), 279 | e(t, s, i) 280 | })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 281 | hints: !1 282 | })), $task.fetch(t).then(t => { 283 | const { 284 | statusCode: s, 285 | statusCode: i, 286 | headers: r, 287 | body: o 288 | } = t; 289 | e(null, { 290 | status: s, 291 | statusCode: i, 292 | headers: r, 293 | body: o 294 | }, o) 295 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 296 | try { 297 | if (t.headers["set-cookie"]) { 298 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 299 | s && this.ckjar.setCookieSync(s, null), 300 | e.cookieJar = this.ckjar 301 | } 302 | } catch (t) { 303 | this.logErr(t) 304 | } 305 | }).then(t => { 306 | const { 307 | statusCode: s, 308 | statusCode: i, 309 | headers: r, 310 | body: o 311 | } = t; 312 | e(null, { 313 | status: s, 314 | statusCode: i, 315 | headers: r, 316 | body: o 317 | }, o) 318 | }, t => { 319 | const { 320 | message: s, 321 | response: i 322 | } = t; 323 | e(s, i, i && i.body) 324 | })) 325 | } 326 | post(t, e = (() => {})) { 327 | if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) 328 | this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { 329 | "X-Surge-Skip-Scripting": !1 330 | })), $httpClient.post(t, (t, s, i) => { 331 | !t && s && (s.body = i, s.statusCode = s.status), 332 | e(t, s, i) 333 | }); 334 | else if (this.isQuanX()) 335 | t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 336 | hints: !1 337 | })), $task.fetch(t).then(t => { 338 | const { 339 | statusCode: s, 340 | statusCode: i, 341 | headers: r, 342 | body: o 343 | } = t; 344 | e(null, { 345 | status: s, 346 | statusCode: i, 347 | headers: r, 348 | body: o 349 | }, o) 350 | }, t => e(t)); 351 | else if (this.isNode()) { 352 | this.initGotEnv(t); 353 | const { 354 | url: s, 355 | ...i 356 | } = t; 357 | this.got.post(s, i).then(t => { 358 | const { 359 | statusCode: s, 360 | statusCode: i, 361 | headers: r, 362 | body: o 363 | } = t; 364 | e(null, { 365 | status: s, 366 | statusCode: i, 367 | headers: r, 368 | body: o 369 | }, o) 370 | }, t => { 371 | const { 372 | message: s, 373 | response: i 374 | } = t; 375 | e(s, i, i && i.body) 376 | }) 377 | } 378 | } 379 | time(t, e = null) { 380 | const s = e ? new Date(e) : new Date; 381 | let i = { 382 | "M+": s.getMonth() + 1, 383 | "d+": s.getDate(), 384 | "H+": s.getHours(), 385 | "m+": s.getMinutes(), 386 | "s+": s.getSeconds(), 387 | "q+": Math.floor((s.getMonth() + 3) / 3), 388 | S: s.getMilliseconds() 389 | }; 390 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 391 | for (let e in i) 392 | new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); 393 | return t 394 | } 395 | msg(e = t, s = "", i = "", r) { 396 | const o = t => { 397 | if (!t) 398 | return t; 399 | if ("string" == typeof t) 400 | return this.isLoon() ? t : this.isQuanX() ? { 401 | "open-url": t 402 | } 403 | : this.isSurge() ? { 404 | url: t 405 | } 406 | : void 0; 407 | if ("object" == typeof t) { 408 | if (this.isLoon()) { 409 | let e = t.openUrl || t.url || t["open-url"], 410 | s = t.mediaUrl || t["media-url"]; 411 | return { 412 | openUrl: e, 413 | mediaUrl: s 414 | } 415 | } 416 | if (this.isQuanX()) { 417 | let e = t["open-url"] || t.url || t.openUrl, 418 | s = t["media-url"] || t.mediaUrl; 419 | return { 420 | "open-url": e, 421 | "media-url": s 422 | } 423 | } 424 | if (this.isSurge()) { 425 | let e = t.url || t.openUrl || t["open-url"]; 426 | return { 427 | url: e 428 | } 429 | } 430 | } 431 | }; 432 | if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { 433 | let t = ["", "==============📣系统通知📣=============="]; 434 | t.push(e), 435 | s && t.push(s), 436 | i && t.push(i), 437 | console.log(t.join("\n")), 438 | this.logs = this.logs.concat(t) 439 | } 440 | } 441 | log(...t) { 442 | t.length > 0 && (this.logs = [...this.logs, ...t]), 443 | console.log(t.join(this.logSeparator)) 444 | } 445 | logErr(t, e) { 446 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 447 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 448 | } 449 | wait(t) { 450 | return new Promise(e => setTimeout(e, t)) 451 | } 452 | done(t = {}) { 453 | const e = (new Date).getTime(), 454 | s = (e - this.startTime) / 1e3; 455 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), 456 | this.log(), 457 | (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 458 | } 459 | } 460 | (t, e) 461 | } 462 | -------------------------------------------------------------------------------- /ql.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const axios = require('axios'); 3 | const got = require('got'); 4 | 5 | let strclientid= "",strclientsecret= "",strport="5700"; 6 | 7 | if (process.env.CHECKCK_STRCLIENTID) { 8 | strclientid = process.env.CHECKCK_STRCLIENTID; 9 | } 10 | if (process.env.CHECKCK_STRCLIENTSECRET) { 11 | strclientsecret = process.env.CHECKCK_STRCLIENTSECRET; 12 | } 13 | if (process.env.CHECKCK_PORT) { 14 | strport = process.env.CHECKCK_PORT; 15 | } 16 | 17 | const api = got.extend({ 18 | prefixUrl: 'http://127.0.0.1:'+strport, 19 | retry: { limit: 0 }, 20 | }); 21 | async function getToken() { 22 | var token = ""; 23 | const response = await axios.get(`http://127.0.0.1:${strport}/open/auth/token`, { 24 | params: { 25 | client_id: strclientid, 26 | client_secret: strclientsecret 27 | }, 28 | headers: { 29 | 'Accept': 'application/json' 30 | } 31 | }); 32 | 33 | if (response.status === 200) { 34 | token = response.data.data.token; 35 | } else { 36 | console.error("Error: " + response.status); 37 | } 38 | 39 | return token; 40 | 41 | } 42 | 43 | module.exports.getEnvs = async () => { 44 | const token = await getToken(); 45 | const body = await api({ 46 | url: 'open/envs', 47 | searchParams: { 48 | searchValue: 'JD_COOKIE', 49 | t: Date.now(), 50 | }, 51 | headers: { 52 | Accept: 'application/json', 53 | authorization: `Bearer ${token}`, 54 | }, 55 | }).json(); 56 | return body.data; 57 | }; 58 | 59 | module.exports.getEnvsCount = async () => { 60 | const data = await this.getEnvs(); 61 | return data.length; 62 | }; 63 | 64 | module.exports.addEnv = async (cookie, remarks) => { 65 | const token = await getToken(); 66 | const body = await api({ 67 | method: 'post', 68 | url: 'open/envs', 69 | params: { t: Date.now() }, 70 | json: [{ 71 | name: 'JD_COOKIE', 72 | value: cookie, 73 | remarks, 74 | }], 75 | headers: { 76 | Accept: 'application/json', 77 | authorization: `Bearer ${token}`, 78 | 'Content-Type': 'application/json;charset=UTF-8', 79 | }, 80 | }).json(); 81 | return body; 82 | }; 83 | 84 | module.exports.updateEnv = async (cookie, eid, remarks) => { 85 | const token = await getToken(); 86 | const body = await api({ 87 | method: 'put', 88 | url: 'open/envs', 89 | params: { t: Date.now() }, 90 | json: { 91 | name: 'JD_COOKIE', 92 | value: cookie, 93 | _id: eid, 94 | remarks, 95 | }, 96 | headers: { 97 | Accept: 'application/json', 98 | authorization: `Bearer ${token}`, 99 | 'Content-Type': 'application/json;charset=UTF-8', 100 | }, 101 | }).json(); 102 | return body; 103 | }; 104 | 105 | module.exports.updateEnv11 = async (cookie, eid, remarks) => { 106 | const token = await getToken(); 107 | const body = await api({ 108 | method: 'put', 109 | url: 'open/envs', 110 | params: { t: Date.now() }, 111 | json: { 112 | name: 'JD_COOKIE', 113 | value: cookie, 114 | id: eid, 115 | remarks, 116 | }, 117 | headers: { 118 | Accept: 'application/json', 119 | authorization: `Bearer ${token}`, 120 | 'Content-Type': 'application/json;charset=UTF-8', 121 | }, 122 | }).json(); 123 | return body; 124 | }; 125 | 126 | module.exports.DisableCk = async (eid) => { 127 | const token = await getToken(); 128 | const body = await api({ 129 | method: 'put', 130 | url: 'open/envs/disable', 131 | params: { t: Date.now() }, 132 | body: JSON.stringify([eid]), 133 | headers: { 134 | Accept: 'application/json', 135 | authorization: `Bearer ${token}`, 136 | 'Content-Type': 'application/json;charset=UTF-8', 137 | }, 138 | }).json(); 139 | return body; 140 | }; 141 | 142 | module.exports.EnableCk = async (eid) => { 143 | const token = await getToken(); 144 | const body = await api({ 145 | method: 'put', 146 | url: 'open/envs/enable', 147 | params: { t: Date.now() }, 148 | body: JSON.stringify([eid]), 149 | headers: { 150 | Accept: 'application/json', 151 | authorization: `Bearer ${token}`, 152 | 'Content-Type': 'application/json;charset=UTF-8', 153 | }, 154 | }).json(); 155 | return body; 156 | }; 157 | 158 | module.exports.getstatus = async(eid) => { 159 | const envs = await this.getEnvs(); 160 | var tempid = 0; 161 | for (let i = 0; i < envs.length; i++) { 162 | tempid = 0; 163 | if (envs[i]._id) { 164 | tempid = envs[i]._id; 165 | } 166 | if (envs[i].id) { 167 | tempid = envs[i].id; 168 | } 169 | if (tempid == eid) { 170 | return envs[i].status; 171 | } 172 | } 173 | return 99; 174 | }; 175 | 176 | module.exports.getEnvById = async(eid) => { 177 | const envs = await this.getEnvs(); 178 | var tempid = 0; 179 | for (let i = 0; i < envs.length; i++) { 180 | tempid = 0; 181 | if (envs[i]._id) { 182 | tempid = envs[i]._id; 183 | } 184 | if (envs[i].id) { 185 | tempid = envs[i].id; 186 | } 187 | if (tempid == eid) { 188 | return envs[i].value; 189 | } 190 | } 191 | return ""; 192 | }; 193 | 194 | module.exports.getEnvByPtPin = async (Ptpin) => { 195 | const envs = await this.getEnvs(); 196 | for (let i = 0; i < envs.length; i++) { 197 | var tempptpin = decodeURIComponent(envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/) && envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 198 | if(tempptpin==Ptpin){ 199 | return envs[i]; 200 | } 201 | } 202 | return ""; 203 | }; 204 | 205 | module.exports.delEnv = async (eid) => { 206 | const token = await getToken(); 207 | const body = await api({ 208 | method: 'delete', 209 | url: 'open/envs', 210 | params: { t: Date.now() }, 211 | body: JSON.stringify([eid]), 212 | headers: { 213 | Accept: 'application/json', 214 | authorization: `Bearer ${token}`, 215 | 'Content-Type': 'application/json;charset=UTF-8', 216 | }, 217 | }).json(); 218 | return body; 219 | }; 220 | 221 | module.exports.getEnvinfoById = async(eid) => { 222 | const envs = await this.getEnvs(); 223 | var tempid = 0; 224 | for (let i = 0; i < envs.length; i++) { 225 | tempid = 0; 226 | if (envs[i]._id) { 227 | tempid = envs[i]._id; 228 | } 229 | if (envs[i].id) { 230 | tempid = envs[i].id; 231 | } 232 | if (tempid == eid) { 233 | return envs[i]; 234 | } 235 | } 236 | return null; 237 | }; -------------------------------------------------------------------------------- /utils/JDJRValidator_Pure.js: -------------------------------------------------------------------------------- 1 | /* 2 | 由于 canvas 依赖系统底层需要编译且预编译包在 github releases 上,改用另一个纯 js 解码图片。若想继续使用 canvas 可调用 runWithCanvas 。 3 | 4 | 添加 injectToRequest 用以快速修复需验证的请求。eg: $.get=injectToRequest($.get.bind($)) 5 | */ 6 | const https = require('https'); 7 | const http = require('http'); 8 | const stream = require('stream'); 9 | const zlib = require('zlib'); 10 | const vm = require('vm'); 11 | const PNG = require('png-js'); 12 | const UA = require('../USER_AGENTS.js').USER_AGENT; 13 | 14 | 15 | Math.avg = function average() { 16 | var sum = 0; 17 | var len = this.length; 18 | for (var i = 0; i < len; i++) { 19 | sum += this[i]; 20 | } 21 | return sum / len; 22 | }; 23 | 24 | function sleep(timeout) { 25 | return new Promise((resolve) => setTimeout(resolve, timeout)); 26 | } 27 | 28 | class PNGDecoder extends PNG { 29 | constructor(args) { 30 | super(args); 31 | this.pixels = []; 32 | } 33 | 34 | decodeToPixels() { 35 | return new Promise((resolve) => { 36 | try { 37 | this.decode((pixels) => { 38 | this.pixels = pixels; 39 | resolve(); 40 | }); 41 | } catch (e) { 42 | console.info(e) 43 | } 44 | }); 45 | } 46 | 47 | getImageData(x, y, w, h) { 48 | const {pixels} = this; 49 | const len = w * h * 4; 50 | const startIndex = x * 4 + y * (w * 4); 51 | 52 | return {data: pixels.slice(startIndex, startIndex + len)}; 53 | } 54 | } 55 | 56 | const PUZZLE_GAP = 8; 57 | const PUZZLE_PAD = 10; 58 | 59 | class PuzzleRecognizer { 60 | constructor(bg, patch, y) { 61 | // console.log(bg); 62 | const imgBg = new PNGDecoder(Buffer.from(bg, 'base64')); 63 | const imgPatch = new PNGDecoder(Buffer.from(patch, 'base64')); 64 | 65 | // console.log(imgBg); 66 | 67 | this.bg = imgBg; 68 | this.patch = imgPatch; 69 | this.rawBg = bg; 70 | this.rawPatch = patch; 71 | this.y = y; 72 | this.w = imgBg.width; 73 | this.h = imgBg.height; 74 | } 75 | 76 | async run() { 77 | try { 78 | await this.bg.decodeToPixels(); 79 | await this.patch.decodeToPixels(); 80 | 81 | return this.recognize(); 82 | } catch (e) { 83 | console.info(e) 84 | } 85 | } 86 | 87 | recognize() { 88 | const {ctx, w: width, bg} = this; 89 | const {width: patchWidth, height: patchHeight} = this.patch; 90 | const posY = this.y + PUZZLE_PAD + ((patchHeight - PUZZLE_PAD) / 2) - (PUZZLE_GAP / 2); 91 | // const cData = ctx.getImageData(0, a.y + 10 + 20 - 4, 360, 8).data; 92 | const cData = bg.getImageData(0, posY, width, PUZZLE_GAP).data; 93 | const lumas = []; 94 | 95 | for (let x = 0; x < width; x++) { 96 | var sum = 0; 97 | 98 | // y xais 99 | for (let y = 0; y < PUZZLE_GAP; y++) { 100 | var idx = x * 4 + y * (width * 4); 101 | var r = cData[idx]; 102 | var g = cData[idx + 1]; 103 | var b = cData[idx + 2]; 104 | var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; 105 | 106 | sum += luma; 107 | } 108 | 109 | lumas.push(sum / PUZZLE_GAP); 110 | } 111 | 112 | const n = 2; // minium macroscopic image width (px) 113 | const margin = patchWidth - PUZZLE_PAD; 114 | const diff = 20; // macroscopic brightness difference 115 | const radius = PUZZLE_PAD; 116 | for (let i = 0, len = lumas.length - 2 * 4; i < len; i++) { 117 | const left = (lumas[i] + lumas[i + 1]) / n; 118 | const right = (lumas[i + 2] + lumas[i + 3]) / n; 119 | const mi = margin + i; 120 | const mLeft = (lumas[mi] + lumas[mi + 1]) / n; 121 | const mRigth = (lumas[mi + 2] + lumas[mi + 3]) / n; 122 | 123 | if (left - right > diff && mLeft - mRigth < -diff) { 124 | const pieces = lumas.slice(i + 2, margin + i + 2); 125 | const median = pieces.sort((x1, x2) => x1 - x2)[20]; 126 | const avg = Math.avg(pieces); 127 | 128 | // noise reducation 129 | if (median > left || median > mRigth) return; 130 | if (avg > 100) return; 131 | // console.table({left,right,mLeft,mRigth,median}); 132 | // ctx.fillRect(i+n-radius, 0, 1, 360); 133 | // console.log(i+n-radius); 134 | return i + n - radius; 135 | } 136 | } 137 | 138 | // not found 139 | return -1; 140 | } 141 | 142 | runWithCanvas() { 143 | const {createCanvas, Image} = require('canvas'); 144 | const canvas = createCanvas(); 145 | const ctx = canvas.getContext('2d'); 146 | const imgBg = new Image(); 147 | const imgPatch = new Image(); 148 | const prefix = 'data:image/png;base64,'; 149 | 150 | imgBg.src = prefix + this.rawBg; 151 | imgPatch.src = prefix + this.rawPatch; 152 | const {naturalWidth: w, naturalHeight: h} = imgBg; 153 | canvas.width = w; 154 | canvas.height = h; 155 | ctx.clearRect(0, 0, w, h); 156 | ctx.drawImage(imgBg, 0, 0, w, h); 157 | 158 | const width = w; 159 | const {naturalWidth, naturalHeight} = imgPatch; 160 | const posY = this.y + PUZZLE_PAD + ((naturalHeight - PUZZLE_PAD) / 2) - (PUZZLE_GAP / 2); 161 | // const cData = ctx.getImageData(0, a.y + 10 + 20 - 4, 360, 8).data; 162 | const cData = ctx.getImageData(0, posY, width, PUZZLE_GAP).data; 163 | const lumas = []; 164 | 165 | for (let x = 0; x < width; x++) { 166 | var sum = 0; 167 | 168 | // y xais 169 | for (let y = 0; y < PUZZLE_GAP; y++) { 170 | var idx = x * 4 + y * (width * 4); 171 | var r = cData[idx]; 172 | var g = cData[idx + 1]; 173 | var b = cData[idx + 2]; 174 | var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; 175 | 176 | sum += luma; 177 | } 178 | 179 | lumas.push(sum / PUZZLE_GAP); 180 | } 181 | 182 | const n = 2; // minium macroscopic image width (px) 183 | const margin = naturalWidth - PUZZLE_PAD; 184 | const diff = 20; // macroscopic brightness difference 185 | const radius = PUZZLE_PAD; 186 | for (let i = 0, len = lumas.length - 2 * 4; i < len; i++) { 187 | const left = (lumas[i] + lumas[i + 1]) / n; 188 | const right = (lumas[i + 2] + lumas[i + 3]) / n; 189 | const mi = margin + i; 190 | const mLeft = (lumas[mi] + lumas[mi + 1]) / n; 191 | const mRigth = (lumas[mi + 2] + lumas[mi + 3]) / n; 192 | 193 | if (left - right > diff && mLeft - mRigth < -diff) { 194 | const pieces = lumas.slice(i + 2, margin + i + 2); 195 | const median = pieces.sort((x1, x2) => x1 - x2)[20]; 196 | const avg = Math.avg(pieces); 197 | 198 | // noise reducation 199 | if (median > left || median > mRigth) return; 200 | if (avg > 100) return; 201 | // console.table({left,right,mLeft,mRigth,median}); 202 | // ctx.fillRect(i+n-radius, 0, 1, 360); 203 | // console.log(i+n-radius); 204 | return i + n - radius; 205 | } 206 | } 207 | 208 | // not found 209 | return -1; 210 | } 211 | } 212 | 213 | const DATA = { 214 | "appId": "17839d5db83", 215 | "product": "embed", 216 | "lang": "zh_CN", 217 | }; 218 | const SERVER = '61.49.99.122'; 219 | 220 | class JDJRValidator { 221 | constructor() { 222 | this.data = {}; 223 | this.x = 0; 224 | this.t = Date.now(); 225 | } 226 | 227 | async run(scene) { 228 | try { 229 | const tryRecognize = async () => { 230 | const x = await this.recognize(scene); 231 | 232 | if (x > 0) { 233 | return x; 234 | } 235 | // retry 236 | return await tryRecognize(); 237 | }; 238 | const puzzleX = await tryRecognize(); 239 | // console.log(puzzleX); 240 | const pos = new MousePosFaker(puzzleX).run(); 241 | const d = getCoordinate(pos); 242 | 243 | // console.log(pos[pos.length-1][2] -Date.now()); 244 | // await sleep(4500); 245 | await sleep(pos[pos.length - 1][2] - Date.now()); 246 | const result = await JDJRValidator.jsonp('/slide/s.html', {d, ...this.data}, scene); 247 | 248 | if (result.message === 'success') { 249 | // console.log(result); 250 | console.log('JDJR验证用时: %fs', (Date.now() - this.t) / 1000); 251 | return result; 252 | } else { 253 | console.count("验证失败"); 254 | // console.count(JSON.stringify(result)); 255 | await sleep(300); 256 | return await this.run(scene); 257 | } 258 | } catch (e) { 259 | console.info(e) 260 | } 261 | } 262 | 263 | async recognize(scene) { 264 | try { 265 | const data = await JDJRValidator.jsonp('/slide/g.html', {e: ''}, scene); 266 | const {bg, patch, y} = data; 267 | // const uri = 'data:image/png;base64,'; 268 | // const re = new PuzzleRecognizer(uri+bg, uri+patch, y); 269 | const re = new PuzzleRecognizer(bg, patch, y); 270 | const puzzleX = await re.run(); 271 | 272 | if (puzzleX > 0) { 273 | this.data = { 274 | c: data.challenge, 275 | w: re.w, 276 | e: '', 277 | s: '', 278 | o: '', 279 | }; 280 | this.x = puzzleX; 281 | } 282 | return puzzleX; 283 | } catch (e) { 284 | console.info(e) 285 | } 286 | } 287 | 288 | async report(n) { 289 | console.time('PuzzleRecognizer'); 290 | let count = 0; 291 | 292 | for (let i = 0; i < n; i++) { 293 | const x = await this.recognize(); 294 | 295 | if (x > 0) count++; 296 | if (i % 50 === 0) { 297 | // console.log('%f\%', (i / n) * 100); 298 | } 299 | } 300 | 301 | console.log('验证成功: %f\%', (count / n) * 100); 302 | console.timeEnd('PuzzleRecognizer'); 303 | } 304 | 305 | static jsonp(api, data = {}, scene) { 306 | return new Promise((resolve, reject) => { 307 | const fnId = `jsonp_${String(Math.random()).replace('.', '')}`; 308 | const extraData = {callback: fnId}; 309 | const query = new URLSearchParams({...DATA, ...{"scene": scene}, ...extraData, ...data}).toString(); 310 | const url = `http://${SERVER}${api}?${query}`; 311 | const headers = { 312 | 'Accept': '*/*', 313 | 'Accept-Encoding': 'gzip,deflate,br', 314 | 'Accept-Language': 'zh-CN,en-US', 315 | 'Connection': 'keep-alive', 316 | 'Host': SERVER, 317 | 'Proxy-Connection': 'keep-alive', 318 | 'Referer': 'https://h5.m.jd.com/babelDiy/Zeus/2wuqXrZrhygTQzYA7VufBEpj4amH/index.html', 319 | 'User-Agent': UA, 320 | }; 321 | const req = http.get(url, {headers}, (response) => { 322 | let res = response; 323 | if (res.headers['content-encoding'] === 'gzip') { 324 | const unzipStream = new stream.PassThrough(); 325 | stream.pipeline( 326 | response, 327 | zlib.createGunzip(), 328 | unzipStream, 329 | reject, 330 | ); 331 | res = unzipStream; 332 | } 333 | res.setEncoding('utf8'); 334 | 335 | let rawData = ''; 336 | 337 | res.on('data', (chunk) => rawData += chunk); 338 | res.on('end', () => { 339 | try { 340 | const ctx = { 341 | [fnId]: (data) => ctx.data = data, 342 | data: {}, 343 | }; 344 | 345 | vm.createContext(ctx); 346 | vm.runInContext(rawData, ctx); 347 | 348 | // console.log(ctx.data); 349 | res.resume(); 350 | resolve(ctx.data); 351 | } catch (e) { 352 | reject(e); 353 | } 354 | }); 355 | }); 356 | 357 | req.on('error', reject); 358 | req.end(); 359 | }); 360 | } 361 | } 362 | 363 | function getCoordinate(c) { 364 | function string10to64(d) { 365 | var c = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-~".split("") 366 | , b = c.length 367 | , e = +d 368 | , a = []; 369 | do { 370 | mod = e % b; 371 | e = (e - mod) / b; 372 | a.unshift(c[mod]) 373 | } while (e); 374 | return a.join("") 375 | } 376 | 377 | function prefixInteger(a, b) { 378 | return (Array(b).join(0) + a).slice(-b) 379 | } 380 | 381 | function pretreatment(d, c, b) { 382 | var e = string10to64(Math.abs(d)); 383 | var a = ""; 384 | if (!b) { 385 | a += (d > 0 ? "1" : "0") 386 | } 387 | a += prefixInteger(e, c); 388 | return a 389 | } 390 | 391 | var b = new Array(); 392 | for (var e = 0; e < c.length; e++) { 393 | if (e == 0) { 394 | b.push(pretreatment(c[e][0] < 262143 ? c[e][0] : 262143, 3, true)); 395 | b.push(pretreatment(c[e][1] < 16777215 ? c[e][1] : 16777215, 4, true)); 396 | b.push(pretreatment(c[e][2] < 4398046511103 ? c[e][2] : 4398046511103, 7, true)) 397 | } else { 398 | var a = c[e][0] - c[e - 1][0]; 399 | var f = c[e][1] - c[e - 1][1]; 400 | var d = c[e][2] - c[e - 1][2]; 401 | b.push(pretreatment(a < 4095 ? a : 4095, 2, false)); 402 | b.push(pretreatment(f < 4095 ? f : 4095, 2, false)); 403 | b.push(pretreatment(d < 16777215 ? d : 16777215, 4, true)) 404 | } 405 | } 406 | return b.join("") 407 | } 408 | 409 | const HZ = 5; 410 | 411 | class MousePosFaker { 412 | constructor(puzzleX) { 413 | this.x = parseInt(Math.random() * 20 + 20, 10); 414 | this.y = parseInt(Math.random() * 80 + 80, 10); 415 | this.t = Date.now(); 416 | this.pos = [[this.x, this.y, this.t]]; 417 | this.minDuration = parseInt(1000 / HZ, 10); 418 | // this.puzzleX = puzzleX; 419 | this.puzzleX = puzzleX + parseInt(Math.random() * 2 - 1, 10); 420 | 421 | this.STEP = parseInt(Math.random() * 6 + 5, 10); 422 | this.DURATION = parseInt(Math.random() * 7 + 14, 10) * 100; 423 | // [9,1600] [10,1400] 424 | this.STEP = 9; 425 | // this.DURATION = 2000; 426 | // console.log(this.STEP, this.DURATION); 427 | } 428 | 429 | run() { 430 | const perX = this.puzzleX / this.STEP; 431 | const perDuration = this.DURATION / this.STEP; 432 | const firstPos = [this.x - parseInt(Math.random() * 6, 10), this.y + parseInt(Math.random() * 11, 10), this.t]; 433 | 434 | this.pos.unshift(firstPos); 435 | this.stepPos(perX, perDuration); 436 | this.fixPos(); 437 | 438 | const reactTime = parseInt(60 + Math.random() * 100, 10); 439 | const lastIdx = this.pos.length - 1; 440 | const lastPos = [this.pos[lastIdx][0], this.pos[lastIdx][1], this.pos[lastIdx][2] + reactTime]; 441 | 442 | this.pos.push(lastPos); 443 | return this.pos; 444 | } 445 | 446 | stepPos(x, duration) { 447 | let n = 0; 448 | const sqrt2 = Math.sqrt(2); 449 | for (let i = 1; i <= this.STEP; i++) { 450 | n += 1 / i; 451 | } 452 | for (let i = 0; i < this.STEP; i++) { 453 | x = this.puzzleX / (n * (i + 1)); 454 | const currX = parseInt((Math.random() * 30 - 15) + x, 10); 455 | const currY = parseInt(Math.random() * 7 - 3, 10); 456 | const currDuration = parseInt((Math.random() * 0.4 + 0.8) * duration, 10); 457 | 458 | this.moveToAndCollect({ 459 | x: currX, 460 | y: currY, 461 | duration: currDuration, 462 | }); 463 | } 464 | } 465 | 466 | fixPos() { 467 | const actualX = this.pos[this.pos.length - 1][0] - this.pos[1][0]; 468 | const deviation = this.puzzleX - actualX; 469 | 470 | if (Math.abs(deviation) > 4) { 471 | this.moveToAndCollect({ 472 | x: deviation, 473 | y: parseInt(Math.random() * 8 - 3, 10), 474 | duration: 250, 475 | }); 476 | } 477 | } 478 | 479 | moveToAndCollect({x, y, duration}) { 480 | let movedX = 0; 481 | let movedY = 0; 482 | let movedT = 0; 483 | const times = duration / this.minDuration; 484 | let perX = x / times; 485 | let perY = y / times; 486 | let padDuration = 0; 487 | 488 | if (Math.abs(perX) < 1) { 489 | padDuration = duration / Math.abs(x) - this.minDuration; 490 | perX = 1; 491 | perY = y / Math.abs(x); 492 | } 493 | 494 | while (Math.abs(movedX) < Math.abs(x)) { 495 | const rDuration = parseInt(padDuration + Math.random() * 16 - 4, 10); 496 | 497 | movedX += perX + Math.random() * 2 - 1; 498 | movedY += perY; 499 | movedT += this.minDuration + rDuration; 500 | 501 | const currX = parseInt(this.x + movedX, 10); 502 | const currY = parseInt(this.y + movedY, 10); 503 | const currT = this.t + movedT; 504 | 505 | this.pos.push([currX, currY, currT]); 506 | } 507 | 508 | this.x += x; 509 | this.y += y; 510 | this.t += Math.max(duration, movedT); 511 | } 512 | } 513 | 514 | // new JDJRValidator().run(); 515 | // new JDJRValidator().report(1000); 516 | // console.log(getCoordinate(new MousePosFaker(100).run())); 517 | 518 | function injectToRequest2(fn, scene = 'cww') { 519 | return (opts, cb) => { 520 | fn(opts, async (err, resp, data) => { 521 | try { 522 | if (err) { 523 | console.error('验证请求失败.'); 524 | return; 525 | } 526 | if (data.search('验证') > -1) { 527 | console.log('JDJR验证中......'); 528 | const res = await new JDJRValidator().run(scene); 529 | if (res) { 530 | opts.url += `&validate=${res.validate}`; 531 | } 532 | fn(opts, cb); 533 | } else { 534 | cb(err, resp, data); 535 | } 536 | } catch (e) { 537 | console.info(e) 538 | } 539 | }); 540 | }; 541 | } 542 | 543 | async function injectToRequest(scene = 'cww') { 544 | console.log('JDJR验证中......'); 545 | const res = await new JDJRValidator().run(scene); 546 | return `&validate=${res.validate}` 547 | } 548 | 549 | module.exports = { 550 | sleep, 551 | injectToRequest, 552 | injectToRequest2 553 | } 554 | -------------------------------------------------------------------------------- /utils/USER_AGENTS.js: -------------------------------------------------------------------------------- 1 | const USER_AGENTS = [ 2 | "jdapp;android;10.1.0;10;network/wifi;Mozilla/5.0 (Linux; Android 10; ONEPLUS A5010 Build/QKQ1.191014.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", 3 | "jdapp;iPhone;10.1.0;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 4 | "jdapp;android;10.1.0;9;network/4g;Mozilla/5.0 (Linux; Android 9; Mi Note 3 Build/PKQ1.181007.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045131 Mobile Safari/537.36", 5 | "jdapp;android;10.1.0;10;network/wifi;Mozilla/5.0 (Linux; Android 10; GM1910 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", 6 | "jdapp;android;10.1.0;9;network/wifi;Mozilla/5.0 (Linux; Android 9; 16T Build/PKQ1.190616.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", 7 | "jdapp;iPhone;10.1.0;13.6;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 8 | "jdapp;iPhone;10.1.0;13.6;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 9 | "jdapp;iPhone;10.1.0;13.5;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 10 | "jdapp;iPhone;10.1.0;14.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 11 | "jdapp;iPhone;10.1.0;13.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 12 | "jdapp;iPhone;10.1.0;13.7;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 13 | "jdapp;iPhone;10.1.0;14.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 14 | "jdapp;iPhone;10.1.0;13.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 15 | "jdapp;iPhone;10.1.0;13.4;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 13_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 16 | "jdapp;iPhone;10.1.0;14.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 17 | "jdapp;android;10.1.0;9;network/wifi;Mozilla/5.0 (Linux; Android 9; MI 6 Build/PKQ1.190118.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", 18 | "jdapp;android;10.1.0;11;network/wifi;Mozilla/5.0 (Linux; Android 11; Redmi K30 5G Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045511 Mobile Safari/537.36", 19 | "jdapp;iPhone;10.1.0;11.4;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15F79", 20 | "jdapp;android;10.1.0;10;;network/wifi;Mozilla/5.0 (Linux; Android 10; M2006J10C Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", 21 | "jdapp;android;10.1.0;10;network/wifi;Mozilla/5.0 (Linux; Android 10; M2006J10C Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", 22 | "jdapp;android;10.1.0;10;network/wifi;Mozilla/5.0 (Linux; Android 10; ONEPLUS A6000 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045224 Mobile Safari/537.36", 23 | "jdapp;android;10.1.0;9;network/wifi;Mozilla/5.0 (Linux; Android 9; MHA-AL00 Build/HUAWEIMHA-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", 24 | "jdapp;android;10.1.0;8.1.0;network/wifi;Mozilla/5.0 (Linux; Android 8.1.0; 16 X Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", 25 | "jdapp;android;10.1.0;8.0.0;network/wifi;Mozilla/5.0 (Linux; Android 8.0.0; HTC U-3w Build/OPR6.170623.013; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", 26 | "jdapp;iPhone;10.1.0;14.0.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 27 | "jdapp;android;10.1.0;10;network/wifi;Mozilla/5.0 (Linux; Android 10; LYA-AL00 Build/HUAWEILYA-AL00L; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", 28 | "jdapp;iPhone;10.1.0;14.2;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 29 | "jdapp;iPhone;10.1.0;14.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 30 | "jdapp;iPhone;10.1.0;14.2;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 31 | "jdapp;android;10.1.0;8.1.0;network/wifi;Mozilla/5.0 (Linux; Android 8.1.0; MI 8 Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045131 Mobile Safari/537.36", 32 | "jdapp;android;10.1.0;10;network/wifi;Mozilla/5.0 (Linux; Android 10; Redmi K20 Pro Premium Edition Build/QKQ1.190825.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045227 Mobile Safari/537.36", 33 | "jdapp;iPhone;10.1.0;14.3;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 34 | "jdapp;iPhone;10.1.0;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 35 | "jdapp;android;10.1.0;11;network/wifi;Mozilla/5.0 (Linux; Android 11; Redmi K20 Pro Premium Edition Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045513 Mobile Safari/537.36", 36 | "jdapp;android;10.1.0;10;network/wifi;Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190828.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045227 Mobile Safari/537.36", 37 | "jdapp;iPhone;10.1.0;14.1;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 14_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 38 | ] 39 | /** 40 | * 生成随机数字 41 | * @param {number} min 最小值(包含) 42 | * @param {number} max 最大值(不包含) 43 | */ 44 | function randomNumber(min = 0, max = 100) { 45 | return Math.min(Math.floor(min + Math.random() * (max - min)), max); 46 | } 47 | const USER_AGENT = USER_AGENTS[randomNumber(0, USER_AGENTS.length)]; 48 | 49 | module.exports = { 50 | USER_AGENT 51 | } 52 | --------------------------------------------------------------------------------