├── README.md ├── jdCookie_xh.js ├── jd_bean_change_xh.js ├── jd_car_exchange_xh.js ├── jd_cleancart.js ├── jd_islogin_xh.js ├── jd_jin_tie_xh.js ├── jd_ljd_xh.js ├── jd_superMarket_xh.js ├── jd_try_xh.js └── jd_unsubscribe_xh.js /README.md: -------------------------------------------------------------------------------- 1 | # 免责声明:仓库内所有文件仅供学习使用,请在24小时后删除 2 | # Fixlog & Updatelog 3 | - 2022-05-25 20:20 Update [jd_cleancart.js](https://github.com/X1a0He/jd/blob/main/jd_cleancart.js) 4 | ``` 5 | 测试了一下,青龙能跑,我自己的号也能跑,部分号出现JSON问题,佛系修 6 | ``` 7 | - 2022-02-11 02:10 Update [jd_unsubscribe_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_unsubscribe_xh.js) 8 | ``` 9 | 增加401 Authorization Required的检测,当遇到此问题时,将不再进行json数据解析 10 | 修复提示json解析错误的问题,若多次出现,请设置环境变量JD_USER_AGENT来控制脚本User-Agent的提交 11 | ``` 12 | - 2022-02-03 15:55 Update [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 13 | ``` 14 | 当统一试用组启用时,无论是否已满,第二个账号开始均不会进行试用组的再次添加 15 | ``` 16 | - 2022-01-30 14:15 Update [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 17 | ``` 18 | 新增环境变量 XH_TRY_EXCEPT 以控制跳过某个指定账号 19 | 新增环境变量 XH_TRY_ENV 以控制是否输出查看环境变量 20 | ``` 21 | - 2022-01-30 14:10 Update [jd_unsubscribe_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_unsubscribe_xh.js) 22 | ``` 23 | 新增环境变量 XH_UNSUB_EXCEPT 以控制跳过某个指定账号 24 | 修改了部分地方写错注释的问题 25 | ``` 26 | - 2022-01-30 03:10 Fix [jd_cleancart.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_cleancart.js) 27 | ``` 28 | 修复了删除失败不会停止的问题 29 | ``` 30 | - 2022-01-29 22:50 Update [jd_cleancart.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_cleancart.js) 31 | ``` 32 | 新增环境变量 XH_CLEAN_EXCEPT 以控制跳过某个指定账号 33 | 修改环境变量 JD_CART_REMOVESIZE -> XH_CLEAN_REMOVESIZE 34 | 修改环境变量 JD_CART_KEYWORDS -> XH_CLEAN_KEYWORDS 35 | 移除环境变量 JD_CART_REMOVEALL 36 | 整合了需要读取环境变量的内部变量,并显示出已经设置的环境变量 37 | ``` 38 | - 2022-01-29 16:45 Fix [jd_unsubscribe_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_unsubscribe_xh.js) 39 | ``` 40 | 再次修复了获取数据失败的问题 41 | 再次修复了取消关注或取消收藏失败的问题 42 | ``` 43 | - 2022-01-25 16:05 Fix [jd_cleancart.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_cleancart.js) 44 | ``` 45 | 修复了获取购物车失败的问题 46 | 修复了删除购物车数据失败的问题 47 | ``` 48 | - 2022-01-25 16:05 Fix [jd_unsubscribe_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_unsubscribe_xh.js) 49 | ``` 50 | 修复了获取数据失败的问题 51 | 修复了取消关注或取消收藏失败的问题 52 | ``` 53 | - 2022-01-25 15:42 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 54 | ``` 55 | 新增环境变量 JD_TRY_TOTALPAGES 用于指定每页遍历的最大页数 56 | 新增环境变量 JD_TRY_UNIFIED 用于指定是否采用统一试用组,详情请看脚本 args_xh 下的注释 57 | 修复了获取tabList失败的问题 58 | 修复了无法获取试用申请成功的问题 59 | ``` 60 | - 2021-12-26 15:00 Fix [jd_unsubscribe_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_unsubscribe_xh.js) 61 | ``` 62 | 修复了获取数据失败的问题 63 | ``` 64 | - 2021-11-11 13:16 Fix [jd_unsubscribe_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_unsubscribe_xh.js) 65 | ``` 66 | 昨天上传那个忘记加break了,这个加回来了 67 | 新增JD_UNSUB_FAILTIMES环境变量,用于控制失败次数,防止死循环 68 | 如果无效,带上你的日志tg找我 69 | ``` 70 | - 2021-09-14 23:02 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 71 | ``` 72 | 修复当环境变量 JD_TRY_SENDNUM 大于已有账号数会发送多条通知的问题 73 | 修复设定了环境变量 JD_TRY_SENDNUM 但不生效的问题 74 | ``` 75 | - 2021-09-14 22:57 Fix [jd_bean_change_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_bean_change_xh.js) 76 | ``` 77 | 修复当环境变量 JD_BEAN_CHANGE_SENDNUM 大于已有账号数会发送多条通知的问题 78 | ``` 79 | - 2021-09-13 14:15 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 80 | ``` 81 | 修复上次修改出现逻辑错误导致无法运行的问题 82 | 修复 notify 错误导致不发通知的问题 83 | 修复请求页数自增逻辑导致显示请求页数错误的问题 84 | ``` 85 | - 2021-09-13 11:32 Fix [jd_ljd_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_ljd_xh.js) 86 | ``` 87 | 修复通知中 [本次执行] 所获取到的成长值计算错误的问题 88 | ``` 89 | - 2021-09-13 11:22 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 90 | ``` 91 | 修复了因 cookiesArr 错误导致不发通知的问题 92 | 可能修复了请求页数错误后直接停止不运行的问题 93 | ``` 94 | - 2021-09-10 10:24 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 95 | ``` 96 | 内置成人类用品,老人,幼儿,饲料的关键词,无论有无设置环境变量,内置关键词永远存在 97 | 增加指定账号数量发送通知 98 | 修复一旦遇到有上限账号或风控账号就不发通知的问题 99 | 更详细的脚本注释 100 | ``` 101 | - 2021-09-12 09:09 Fix [jd_ljd_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_ljd_xh.js) 102 | ``` 103 | 领京豆脚本,有问题直接提issues 104 | 修复死循环 105 | 修复有部分任务不做的问题 106 | ``` 107 | - 2021-09-10 12:20 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 108 | ``` 109 | 更加精确识别出 申请成功但未领取 申请成功已领取 申请已完成 已放弃 的类型 110 | ``` 111 | - 2021-09-09 21:34 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 112 | ``` 113 | 增加了几个默认的关键词,用于屏蔽成人类商品 114 | 取消默认不运行,现在默认运行了,毕竟脚本稳定了 115 | 调整默认单次运行申请的商品为100个 116 | 调整默认的tabList为1到10 117 | ``` 118 | - 2021-09-09 13:52 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 119 | ``` 120 | 修复试用成功的商品推送里面还是显示0的问题 121 | 如果上述问题没有被修复,还是显示0,请带上你的cookie私聊tg找我 122 | ``` 123 | - 2021-09-08 17:24 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 124 | ``` 125 | 支持黑名单过滤关键词时 输出对应关键词 126 | 对应账号遇到403风控后将不会再执行 127 | 未到申请时间的商品会自动跳过 128 | 修复当tabId组遍历完毕后tabId变成undefined的问题 129 | 为了防止风控,将遍历数据的默认间隔提升到2000毫秒 130 | 调整默认试用组长度为50 131 | ``` 132 | - 2021-09-07 12:15 Fix [jd_islogin_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_islogin_xh.js) 133 | ``` 134 | 修复了没有通知的问题 135 | ``` 136 | - 2021-09-06 22:03 Fix [jd_car_exchange_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_car_exchange_xh.js) 137 | ``` 138 | 修复兑换api 139 | ``` 140 | - 2021-09-06 20:08 Fix [jd_unsubscribe_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_unsubscribe_xh.js) 141 | ``` 142 | 修复取关店铺遇到关键字会进入死循环的问题 143 | 重写所有变量,支持环境变量控制内部变量 144 | 不在支持QuantumultX或其他,支持且仅支持Node.js 145 | ``` 146 | - 2021-09-06 20:08 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 147 | ``` 148 | 修复不存在布尔型环境变量时,内部读取类型错误且相关默认值不生效的问题 149 | 新增白名单功能,详情请查看脚本内注释 150 | ``` 151 | - 2021-09-06 16:47 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 152 | ``` 153 | 修复trialActivityIdList和trialActivityTitleList忘记重置导致部分情况执行后下一账号无法执行的问题 154 | 修复无法读取或读取环境变量错误的问题 155 | 日志新增了各个环境变量的类型,有问题请带日志反馈 156 | ``` 157 | - 2021-09-06 15:58 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 158 | ``` 159 | 修复tabList函数无法输出tabId和对应tabName的问题 160 | 修复因$.isPush未提前定义导致过滤时提醒skuTitle解析异常的问题 161 | 修复当达到申请次数上限300次的时候不会自动停止的问题 162 | ``` 163 | - 2021-09-06 14:20 Fix [jd_try_xh.js](https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js) 164 | ``` 165 | 更改tabId的类型为数组 166 | 增加种草官过滤规则 167 | 增加是否输出到日志 168 | 修复当maxLength过大的时候,会出现自动停止的问题 169 | ``` 170 | -------------------------------------------------------------------------------- /jdCookie_xh.js: -------------------------------------------------------------------------------- 1 | /* 2 | 此文件为Node.js专用。其他用户请忽略 3 | */ 4 | //此处填写京东账号cookie。 5 | let CookieJDs = [''] 6 | // 判断环境变量里面是否有京东ck 7 | if(process.env.JD_COOKIE){ 8 | if(process.env.JD_COOKIE.indexOf('&') > -1){ 9 | CookieJDs = process.env.JD_COOKIE.split('&'); 10 | } else if(process.env.JD_COOKIE.indexOf('\n') > -1){ 11 | CookieJDs = process.env.JD_COOKIE.split('\n'); 12 | } else { 13 | CookieJDs = [process.env.JD_COOKIE]; 14 | } 15 | } 16 | if(JSON.stringify(process.env).indexOf('GITHUB') > -1){ 17 | console.log(`请勿使用github action运行此脚本,无论你是从你自己的私库还是其他哪里拉取的源代码,都会导致我被封号\n`); 18 | !(async() => { 19 | await require('./sendNotify').sendNotify('提醒', `请勿使用github action、滥用github资源会封我仓库以及账号`) 20 | await process.exit(0); 21 | })() 22 | } 23 | CookieJDs = [...new Set(CookieJDs.filter(item => !!item))] 24 | console.log(`\n[${getTime()}] 读取到${CookieJDs.length}个京东账号Cookie\n`); 25 | if(process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => {}; 26 | for(let i = 0; i < CookieJDs.length; i++){ 27 | if(!CookieJDs[i].match(/pt_pin=(.+?);/) || !CookieJDs[i].match(/pt_key=(.+?);/)) console.log(`\n提示:京东cookie 【${CookieJDs[i]}】填写不规范,可能会影响部分脚本正常使用。正确格式为: pt_key=xxx;pt_pin=xxx;(分号;不可少)\n`); 28 | const index = (i + 1 === 1) ? '' : (i + 1); 29 | exports['CookieJD' + index] = CookieJDs[i].trim(); 30 | } 31 | 32 | function getTime(){ 33 | let date = new Date(), 34 | year = date.getFullYear(), 35 | month = (date.getMonth() + 1) < 10 ? `0${date.getMonth() + 1}` : date.getMonth() + 1, 36 | day = date.getDate() < 10 ? `0${date.getDate()}` : date.getDate(), 37 | hours = date.getHours() < 10 ? `0${date.getHours()}` : date.getHours(), 38 | minutes = date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes(), 39 | seconds = date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds(); 40 | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; 41 | } 42 | -------------------------------------------------------------------------------- /jd_bean_change_xh.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 简化版京东日资产变动通知 3 | * 支持环境变量控制每次发送的账号个数,默认为2 4 | * 环境变量为:JD_BEAN_CHANGE_SENDNUM 5 | * By X1a0He 6 | * https://github.com/X1a0He/jd_scripts_fixed 7 | * */ 8 | const $ = new Env("京东日资产变动"); 9 | const jdCookieNode = $.isNode() ? require("./jdCookie.js") : ""; 10 | const notify = $.isNode() ? require('./sendNotify') : ''; 11 | let cookiesArr = [], cookie = "", message = ``; 12 | const JD_API_HOST = 'https://api.m.jd.com/client.action'; 13 | $.todayIncome = 0 14 | $.todayExpenditure = 0 15 | $.yestodayIncome = 0 16 | $.yestodayExpenditure = 0 17 | $.beanCount = 0; 18 | $.beanFlag = true; 19 | $.jdName = `` 20 | $.sendNum = process.env.JD_BEAN_CHANGE_SENDNUM * 1 || 2 21 | $.sentNum = 0; 22 | if($.isNode()){ 23 | Object.keys(jdCookieNode).forEach((item) => {cookiesArr.push(jdCookieNode[item]);}); 24 | if(process.env.JD_DEBUG && process.env.JD_DEBUG === "false") console.log = () => {}; 25 | } else cookiesArr = [$.getdata("CookieJD"), $.getdata("CookieJD2"), ...$.toObj($.getdata("CookiesJD") || "[]").map((item) => item.cookie),].filter((item) => !!item); 26 | !(async() => { 27 | if(!cookiesArr[0]){ 28 | $.msg($.name, "【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取", "https://bean.m.jd.com/", { "open-url": "https://bean.m.jd.com/" }); 29 | return; 30 | } 31 | console.log('=====环境变量配置如下=====') 32 | console.log(`sendNum: ${typeof $.sendNum}, ${$.sendNum}`) 33 | console.log('=======================') 34 | for(let i = 0; i < cookiesArr.length; i++){ 35 | if(cookiesArr[i]){ 36 | cookie = cookiesArr[i]; 37 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 38 | $.index = i + 1; 39 | $.jdSpeedGoldBalance = 0; 40 | $.jdzzNum = 0; 41 | console.log(`[京东账号${$.index} ${$.UserName}] 获取数据中...`) 42 | await bean(); 43 | await totalBean(); 44 | message += `[京东账号${$.index}]\n` 45 | console.log(`[京东账号${$.index}]`) 46 | message += `👤账号名称:${$.jdName}\n` 47 | console.log(`👤账号名称:${$.jdName}`) 48 | message += `🥔今日收支:${$.todayIncome}京豆 | ${$.todayExpenditure}京豆\n` 49 | console.log(`🥔今日收支:${$.todayIncome}京豆 | ${$.todayExpenditure}京豆`) 50 | message += `🥔昨日收支:${$.yestodayIncome}京豆 | ${$.yestodayExpenditure}京豆\n` 51 | console.log(`🥔昨日收支:${$.yestodayIncome}京豆 | ${$.yestodayExpenditure}京豆`) 52 | message += `🥔当前京豆:${$.beanCount}京豆\n` 53 | console.log(`🥔当前京豆:${$.beanCount}京豆`) 54 | await cash(); 55 | typeof $.jdSpeedGoldBalance !== "undefined" ? message += `💰极速金币:${$.jdSpeedGoldBalance}金币 ≈ ${($.jdSpeedGoldBalance / 10000).toFixed(2)}元\n` : '' 56 | typeof $.jdSpeedGoldBalance !== "undefined" ? console.log(`💰极速金币:${$.jdSpeedGoldBalance}金币 ≈ ${($.jdSpeedGoldBalance / 10000).toFixed(2)}元`) : '' 57 | await getJdzz(); 58 | typeof $.jdzzNum !== "undefined" ? message += `💰京东赚赚:${$.jdzzNum}金币 ≈ ${($.jdzzNum / 10000).toFixed(2)}元\n` : '' 59 | typeof $.jdzzNum !== "undefined" ? console.log(`💰京东赚赚:${$.jdzzNum}金币 ≈ ${($.jdzzNum / 10000).toFixed(2)}元`) : '' 60 | $.JdMsScore = 0; 61 | await getMs(); 62 | $.JdMsScore !== 0 ? message += `💰京东秒杀:${$.JdMsScore}秒币 ≈ ${($.JdMsScore / 1000).toFixed(2)}元\n` : '' 63 | $.JdMsScore !== 0 ? console.log(`💰京东秒杀:${$.JdMsScore}秒币 ≈ ${($.JdMsScore / 1000).toFixed(2)}元`) : '' 64 | await redPacket(); 65 | if($.index % $.sendNum === 0 || (cookiesArr.length - ($.sentNum * $.sendNum)) < $.sendNum){ 66 | message += `[京东账号${$.index}]\n` 67 | } else { 68 | message += `[京东账号${$.index}]\n\n` 69 | } 70 | console.log(`[京东账号${$.index}]`) 71 | console.log(`[京东账号${$.index} ${$.UserName}] 结束\n`) 72 | if($.isNode()){ 73 | if($.index % $.sendNum === 0){ 74 | $.sentNum++; 75 | console.log(`正在进行第 ${$.sentNum} 次发送通知,发送数量:${$.sendNum}`) 76 | await notify.sendNotify(`${$.name}`, `${message}`) 77 | message = ""; 78 | } 79 | } 80 | } 81 | } 82 | if($.isNode()){ 83 | if((cookiesArr.length - ($.sentNum * $.sendNum)) < $.sendNum){ 84 | console.log(`正在进行最后一次发送通知,发送数量:${(cookiesArr.length - ($.sentNum * $.sendNum))}`) 85 | await notify.sendNotify(`${$.name}`, `${message}`) 86 | message = ""; 87 | } 88 | } 89 | })().catch((e) => { 90 | $.log("", `❌ ${$.name}, 失败! 原因: ${e}!`, ""); 91 | }).finally(() => { 92 | $.done(); 93 | }); 94 | 95 | async function bean(){ 96 | $.beanPage = 1; 97 | $.todayIncome = 0 98 | $.todayExpenditure = 0 99 | $.yestodayIncome = 0 100 | $.yestodayExpenditure = 0 101 | $.beanFlag = true; 102 | $.beanCount = 0; 103 | do { 104 | getJingBeanBalanceDetail($.beanPage); 105 | await $.wait(500) 106 | } while($.beanFlag === true) 107 | } 108 | 109 | //获取京豆数据 110 | function getJingBeanBalanceDetail(page){ 111 | // 前一天的0:0:0时间戳 112 | const yesterdayTimeStamp = parseInt((Date.now() + 28800000) / 86400000) * 86400000 - 28800000 - (24 * 60 * 60 * 1000); 113 | // 今天0:0:0时间戳 114 | const todayTimeStamp = parseInt((Date.now() + 28800000) / 86400000) * 86400000 - 28800000; 115 | return new Promise((resolve) => { 116 | const options = { 117 | url: 'https://api.m.jd.com/client.action?functionId=getJingBeanBalanceDetail', 118 | body: `body=%7B%22pageSize%22%3A%2220%22%2C%22page%22%3A%22${page}%22%7D&appid=ld`, 119 | headers: { 120 | "Cookie": cookie, 121 | Connection: "keep-alive", 122 | "User-Agent": "jdapp;iPhone;10.1.2;15.0;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 123 | }, 124 | } 125 | $.post(options, (err, resp, data) => { 126 | try{ 127 | if(err){ 128 | if(JSON.stringify(err) !== `\"read ECONNRESET\"`){ 129 | console.log(JSON.stringify(err)) 130 | console.log(`${$.name} API请求失败,请检查网路重试`) 131 | } 132 | } else { 133 | if(data){ 134 | data = JSON.parse(data); 135 | if(data.code === "0"){ 136 | $.beanPage++; 137 | let detailList = data.detailList; 138 | if(detailList && detailList.length > 0){ 139 | for(let item of detailList){ 140 | const date = item.date.replace(/-/g, '/') + "+08:00"; 141 | if(new Date(date).getTime() >= todayTimeStamp && (!item['eventMassage'].includes("退还") && !item['eventMassage'].includes('扣赠'))){ 142 | Number(item.amount) > 0 ? $.todayIncome += Number(item.amount) : $.todayExpenditure += Number(item.amount); 143 | } else if(yesterdayTimeStamp <= new Date(date).getTime() && new Date(date).getTime() < todayTimeStamp && (!item['eventMassage'].includes("退还") && !item['eventMassage'].includes('扣赠'))){ 144 | Number(item.amount) > 0 ? $.yestodayIncome += Number(item.amount) : $.yestodayExpenditure += Number(item.amount) 145 | } else if(yesterdayTimeStamp > new Date(date).getTime()){ 146 | $.beanFlag = false; 147 | break; 148 | } 149 | } 150 | } else $.beanFlag = false; 151 | } else if(data && data.code === "3"){ 152 | console.log(`cookie已过期,或者填写不规范`) 153 | $.beanFlag = false; 154 | } else { 155 | console.log(`未知情况:${JSON.stringify(data)}`); 156 | console.log(`未知情况,跳出`) 157 | $.beanFlag = false; 158 | } 159 | } else { 160 | console.log(`京东服务器返回空数据`) 161 | } 162 | } 163 | } catch(e){ 164 | $.logErr(e, resp) 165 | } finally{ 166 | resolve(data); 167 | } 168 | }); 169 | }); 170 | } 171 | 172 | function totalBean(){ 173 | $.jdName = `` 174 | return new Promise(async resolve => { 175 | const options = { 176 | url: "https://me-api.jd.com/user_new/info/GetJDUserInfoUnion", 177 | headers: { 178 | Cookie: cookie, 179 | "User-Agent": "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", 180 | } 181 | // "Referer": "https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&", 182 | } 183 | $.get(options, (err, resp, data) => { 184 | try{ 185 | if(err){ 186 | $.logErr(err) 187 | } else { 188 | if(data){ 189 | data = JSON.parse(data); 190 | if(data.retcode === "1001"){ 191 | $.isLogin = false; //cookie过期 192 | return; 193 | } 194 | if(data.retcode === "0" && data.data && data.data.hasOwnProperty("userInfo")){ 195 | $.jdName = `${data.data.userInfo.baseInfo.nickname} ${data.data.userInfo.baseInfo.levelName}` 196 | } 197 | if(data.retcode === '0' && data.data && data.data.assetInfo){ 198 | $.beanCount = data.data && data.data.assetInfo.beanNum; 199 | } 200 | } else { 201 | $.log('京东服务器返回空数据'); 202 | } 203 | } 204 | } catch(e){ 205 | $.logErr(e) 206 | } finally{ 207 | resolve(); 208 | } 209 | }) 210 | }) 211 | } 212 | 213 | function cash(){ 214 | return new Promise(resolve => { 215 | $.get(taskcashUrl('MyAssetsService.execute', 216 | { "method": "userCashRecord", "data": { "channel": 1, "pageNum": 1, "pageSize": 20 } }), 217 | async(err, resp, data) => { 218 | try{ 219 | if(err){ 220 | console.log(`${JSON.stringify(err)}`) 221 | console.log(`${$.name} API请求失败,请检查网路重试`) 222 | } else { 223 | if(safeGet(data)){ 224 | data = JSON.parse(data); 225 | $.jdSpeedGoldBalance = data.data.goldBalance; 226 | } 227 | } 228 | } catch(e){ 229 | $.logErr(e, resp) 230 | } finally{ 231 | resolve(data); 232 | } 233 | }) 234 | }) 235 | } 236 | 237 | var __Oxb24bc = ["lite-android&", "stringify", "&android&3.1.0&", "&", "&846c4c32dae910ef", "12aea658f76e453faf803d15c40a72e0", "isNode", "crypto-js", "", "api?functionId=", "&body=", "&appid=lite-android&client=android&uuid=846c4c32dae910ef&clientVersion=3.1.0&t=", "&sign=", "api.m.jd.com", "*/*", "RN", "JDMobileLite/3.1.0 (iPad; iOS 14.4; Scale/2.00)", "zh-Hans-CN;q=1, ja-CN;q=0.9", "undefined", "log", "", "", "", "", "jsjia", "mi.com"]; 238 | 239 | function taskcashUrl(_0x7683x2, _0x7683x3 = {}){ 240 | let _0x7683x4 = +new Date(); 241 | let _0x7683x5 = `${__Oxb24bc[0x0]}${JSON[__Oxb24bc[0x1]](_0x7683x3)}${__Oxb24bc[0x2]}${_0x7683x2}${__Oxb24bc[0x3]}${_0x7683x4}${__Oxb24bc[0x4]}`; 242 | let _0x7683x6 = __Oxb24bc[0x5]; 243 | const _0x7683x7 = $[__Oxb24bc[0x6]]() ? require(__Oxb24bc[0x7]) : CryptoJS; 244 | let _0x7683x8 = _0x7683x7.HmacSHA256(_0x7683x5, _0x7683x6).toString(); 245 | return { 246 | url: `${__Oxb24bc[0x8]}${JD_API_HOST}${__Oxb24bc[0x9]}${_0x7683x2}${__Oxb24bc[0xa]}${escape(JSON[__Oxb24bc[0x1]](_0x7683x3))}${__Oxb24bc[0xb]}${_0x7683x4}${__Oxb24bc[0xc]}${_0x7683x8}${__Oxb24bc[0x8]}`, 247 | headers: { 248 | 'Host': __Oxb24bc[0xd], 249 | 'accept': __Oxb24bc[0xe], 250 | 'kernelplatform': __Oxb24bc[0xf], 251 | 'user-agent': __Oxb24bc[0x10], 252 | 'accept-language': __Oxb24bc[0x11], 253 | 'Cookie': cookie 254 | } 255 | } 256 | } 257 | 258 | function getJdzz(){ 259 | return new Promise(resolve => { 260 | $.get(taskJDZZUrl("interactTaskIndex"), async(err, resp, data) => { 261 | try{ 262 | if(err){ 263 | console.log(`${JSON.stringify(err)}`) 264 | console.log(`${$.name} API请求失败,请检查网路重试`) 265 | } else { 266 | if(safeGet(data)){ 267 | data = JSON.parse(data); 268 | $.jdzzNum = data.data.totalNum 269 | } 270 | } 271 | } catch(e){ 272 | $.logErr(e, resp) 273 | } finally{ 274 | resolve(data); 275 | } 276 | }) 277 | }) 278 | } 279 | 280 | function taskJDZZUrl(functionId, body = {}){ 281 | return { 282 | url: `${JD_API_HOST}?functionId=${functionId}&body=${escape(JSON.stringify(body))}&client=wh5&clientVersion=9.1.0`, 283 | headers: { 284 | 'Cookie': cookie, 285 | 'Host': 'api.m.jd.com', 286 | 'Connection': 'keep-alive', 287 | 'Content-Type': 'application/json', 288 | 'Referer': 'http://wq.jd.com/wxapp/pages/hd-interaction/index/index', 289 | 'User-Agent': "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", 290 | 'Accept-Language': 'zh-cn', 291 | 'Accept-Encoding': 'gzip, deflate, br', 292 | } 293 | } 294 | } 295 | 296 | function getMs(){ 297 | return new Promise(resolve => { 298 | $.post(taskMsPostUrl('homePageV2', {}, 'appid=SecKill2020'), (err, resp, data) => { 299 | try{ 300 | if(err){ 301 | console.log(`${err},${jsonParse(resp.body)['message']}`) 302 | console.log(`${$.name} API请求失败,请检查网路重试`) 303 | } else { 304 | if(safeGet(data)){ 305 | data = JSON.parse(data) 306 | if(data.code === 2041){ 307 | $.JdMsScore = data.result.assignment.assignmentPoints || 0 308 | } 309 | } 310 | } 311 | } catch(e){ 312 | $.logErr(e, resp) 313 | } finally{ 314 | resolve(data); 315 | } 316 | }) 317 | }) 318 | } 319 | 320 | function taskMsPostUrl(function_id, body = {}, extra = '', function_id2){ 321 | let url = `${JD_API_HOST}`; 322 | function_id2 ? url += `?functionId=${function_id2}` : '' 323 | return { 324 | url, 325 | body: `functionId=${function_id}&body=${escape(JSON.stringify(body))}&client=wh5&clientVersion=1.0.0&${extra}`, 326 | headers: { 327 | "Cookie": cookie, 328 | "origin": "https://h5.m.jd.com", 329 | "referer": "https://h5.m.jd.com/babelDiy/Zeus/2NUvze9e1uWf4amBhe1AV6ynmSuH/index.html", 330 | 'Content-Type': 'application/x-www-form-urlencoded', 331 | "User-Agent": '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', 332 | } 333 | } 334 | } 335 | 336 | function redPacket(){ 337 | return new Promise(async resolve => { 338 | const options = { 339 | "url": `https://m.jingxi.com/user/info/QueryUserRedEnvelopesV2?type=1&orgFlag=JD_PinGou_New&page=1&cashRedType=1&redBalanceFlag=1&channel=1&_=${+new Date()}&sceneval=2&g_login_type=1&g_ty=ls`, 340 | "headers": { 341 | 'Host': 'm.jingxi.com', 342 | 'Accept': '*/*', 343 | 'Connection': 'keep-alive', 344 | 'Accept-Language': 'zh-cn', 345 | 'Referer': 'https://st.jingxi.com/my/redpacket.shtml?newPg=App&jxsid=16156262265849285961', 346 | 'Accept-Encoding': 'gzip, deflate, br', 347 | "Cookie": cookie, 348 | 'User-Agent': "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" 349 | } 350 | } 351 | $.get(options, (err, resp, data) => { 352 | try{ 353 | if(err){ 354 | console.log(`${JSON.stringify(err)}`) 355 | console.log(`${$.name} API请求失败,请检查网路重试`) 356 | } else { 357 | if(data){ 358 | data = JSON.parse(data).data 359 | $.jxRed = 0, $.jsRed = 0, $.jdRed = 0, $.jdhRed = 0, $.jxRedExpire = 0, $.jsRedExpire = 0, $.jdRedExpire = 0, $.jdhRedExpire = 0; 360 | let t = new Date() 361 | t.setDate(t.getDate() + 1) 362 | t.setHours(0, 0, 0, 0) 363 | t = parseInt((t - 1) / 1000) 364 | for(let vo of data.useRedInfo.redList || []){ 365 | if(vo.orgLimitStr && vo.orgLimitStr.includes("京喜")){ 366 | $.jxRed += parseFloat(vo.balance) 367 | if(vo['endTime'] === t){ 368 | $.jxRedExpire += parseFloat(vo.balance) 369 | } 370 | } else if(vo.activityName.includes("极速版")){ 371 | $.jsRed += parseFloat(vo.balance) 372 | if(vo['endTime'] === t){ 373 | $.jsRedExpire += parseFloat(vo.balance) 374 | } 375 | } else if(vo.orgLimitStr && vo.orgLimitStr.includes("京东健康")){ 376 | $.jdhRed += parseFloat(vo.balance) 377 | if(vo['endTime'] === t){ 378 | $.jdhRedExpire += parseFloat(vo.balance) 379 | } 380 | } else { 381 | $.jdRed += parseFloat(vo.balance) 382 | if(vo['endTime'] === t){ 383 | $.jdRedExpire += parseFloat(vo.balance) 384 | } 385 | } 386 | } 387 | $.jxRed = $.jxRed.toFixed(2) 388 | $.jsRed = $.jsRed.toFixed(2) 389 | $.jdRed = $.jdRed.toFixed(2) 390 | $.jdhRed = $.jdhRed.toFixed(2) 391 | $.balance = data.balance 392 | $.expiredBalance = ($.jxRedExpire + $.jsRedExpire + $.jdRedExpire).toFixed(2) 393 | message += `🧧京喜红包:${$.jxRed}元 今天总过期 ${$.jxRedExpire.toFixed(2)} 元\n` 394 | console.log(`🧧京喜红包:${$.jxRed}元 今天总过期 ${$.jxRedExpire.toFixed(2)} 元`) 395 | message += `🧧极速红包:${$.jsRed}元 今天总过期 ${$.jsRedExpire.toFixed(2)} 元\n` 396 | console.log(`🧧极速红包:${$.jsRed}元 今天总过期 ${$.jsRedExpire.toFixed(2)} 元`) 397 | message += `🧧京东红包:${$.jdRed}元 今天总过期 ${$.jdRedExpire.toFixed(2)} 元\n` 398 | console.log(`🧧京东红包:${$.jdRed}元 今天总过期 ${$.jdRedExpire.toFixed(2)} 元`) 399 | message += `🧧健康红包:${$.jdhRed}元 今天总过期 ${$.jdhRedExpire.toFixed(2)} 元\n` 400 | console.log(`🧧健康红包:${$.jdhRed}元 今天总过期 ${$.jdhRedExpire.toFixed(2)} 元`) 401 | message += `🧧当前红包:${$.balance}元 今天总过期 ${$.expiredBalance} 元\n` 402 | console.log(`🧧当前红包:${$.balance}元 今天总过期 ${$.expiredBalance} 元`) 403 | } else { 404 | console.log(`京东服务器返回空数据`) 405 | } 406 | } 407 | } catch(e){ 408 | $.logErr(e, resp) 409 | } finally{ 410 | resolve(data); 411 | } 412 | }) 413 | }) 414 | } 415 | 416 | function safeGet(data){ 417 | try{ 418 | if(typeof JSON.parse(data) == "object"){ 419 | return true; 420 | } 421 | } catch(e){ 422 | console.log(e); 423 | console.log(`京东服务器访问数据为空,请检查自身设备网络情况`); 424 | return false; 425 | } 426 | } 427 | 428 | // prettier-ignore 429 | function Env(t, e){ 430 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 431 | 432 | class s{ 433 | constructor(t){this.env = t} 434 | 435 | send(t, e = "GET"){ 436 | t = "string" == typeof t ? { url: t } : t; 437 | let s = this.get; 438 | return "POST" === e && (s = this.post), new Promise((e, i) => {s.call(this, t, (t, s, r) => {t ? i(t) : e(s)})}) 439 | } 440 | 441 | get(t){return this.send.call(this.env, t)} 442 | 443 | post(t){return this.send.call(this.env, t, "POST")} 444 | } 445 | 446 | return new class{ 447 | 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}, 开始!`)} 448 | 449 | isNode(){return "undefined" != typeof module && !!module.exports} 450 | 451 | isQuanX(){return "undefined" != typeof $task} 452 | 453 | isSurge(){return "undefined" != typeof $httpClient && "undefined" == typeof $loon} 454 | 455 | isLoon(){return "undefined" != typeof $loon} 456 | 457 | toObj(t, e = null){try{return JSON.parse(t)} catch{return e}} 458 | 459 | toStr(t, e = null){try{return JSON.stringify(t)} catch{return e}} 460 | 461 | getjson(t, e){ 462 | let s = e; 463 | const i = this.getdata(t); 464 | if(i) try{s = JSON.parse(this.getdata(t))} catch{} 465 | return s 466 | } 467 | 468 | setjson(t, e){try{return this.setdata(JSON.stringify(t), e)} catch{return !1}} 469 | 470 | getScript(t){return new Promise(e => {this.get({ url: t }, (t, s, i) => e(i))})} 471 | 472 | runScript(t, e){ 473 | return new Promise(s => { 474 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 475 | i = i ? i.replace(/\n/g, "").trim() : i; 476 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 477 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 478 | const [o, h] = i.split("@"), n = { 479 | url: `http://${h}/v1/scripting/evaluate`, 480 | body: { script_text: t, mock_type: "cron", timeout: r }, 481 | headers: { "X-Key": o, Accept: "*/*" } 482 | }; 483 | this.post(n, (t, e, i) => s(i)) 484 | }).catch(t => this.logErr(t)) 485 | } 486 | 487 | loaddata(){ 488 | if(!this.isNode()) return {}; 489 | { 490 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 491 | const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), 492 | s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); 493 | if(!s && !i) return {}; 494 | { 495 | const i = s ? t : e; 496 | try{return JSON.parse(this.fs.readFileSync(i))} catch(t){return {}} 497 | } 498 | } 499 | } 500 | 501 | writedata(){ 502 | if(this.isNode()){ 503 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 504 | const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), 505 | s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); 506 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 507 | } 508 | } 509 | 510 | lodash_get(t, e, s){ 511 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 512 | let r = t; 513 | for(const t of i) if(r = Object(r)[t], void 0 === r) return s; 514 | return r 515 | } 516 | 517 | 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)} 518 | 519 | getdata(t){ 520 | let e = this.getval(t); 521 | if(/^@/.test(t)){ 522 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; 523 | if(r) try{ 524 | const t = JSON.parse(r); 525 | e = t ? this.lodash_get(t, i, "") : e 526 | } catch(t){e = ""} 527 | } 528 | return e 529 | } 530 | 531 | setdata(t, e){ 532 | let s = !1; 533 | if(/^@/.test(e)){ 534 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), 535 | h = i ? "null" === o ? null : o || "{}" : "{}"; 536 | try{ 537 | const e = JSON.parse(h); 538 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) 539 | } catch(e){ 540 | const o = {}; 541 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) 542 | } 543 | } else s = this.setval(t, e); 544 | return s 545 | } 546 | 547 | 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} 548 | 549 | 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} 550 | 551 | 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))} 552 | 553 | get(t, e = (() => {})){ 554 | 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 => { 555 | const { 556 | statusCode: s, 557 | statusCode: i, 558 | headers: r, 559 | body: o 560 | } = t; 561 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 562 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 563 | try{ 564 | if(t.headers["set-cookie"]){ 565 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 566 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar 567 | } 568 | } catch(t){this.logErr(t)} 569 | }).then(t => { 570 | const { statusCode: s, statusCode: i, headers: r, body: o } = t; 571 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 572 | }, t => { 573 | const { message: s, response: i } = t; 574 | e(s, i, i && i.body) 575 | })) 576 | } 577 | 578 | post(t, e = (() => {})){ 579 | 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 => { 580 | const { 581 | statusCode: s, 582 | statusCode: i, 583 | headers: r, 584 | body: o 585 | } = t; 586 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 587 | }, t => e(t)); else if(this.isNode()){ 588 | this.initGotEnv(t); 589 | const { url: s, ...i } = t; 590 | this.got.post(s, i).then(t => { 591 | const { statusCode: s, statusCode: i, headers: r, body: o } = t; 592 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 593 | }, t => { 594 | const { message: s, response: i } = t; 595 | e(s, i, i && i.body) 596 | }) 597 | } 598 | } 599 | 600 | time(t, e = null){ 601 | const s = e ? new Date(e) : new Date; 602 | let i = { 603 | "M+": s.getMonth() + 1, 604 | "d+": s.getDate(), 605 | "H+": s.getHours(), 606 | "m+": s.getMinutes(), 607 | "s+": s.getSeconds(), 608 | "q+": Math.floor((s.getMonth() + 3) / 3), 609 | S: s.getMilliseconds() 610 | }; 611 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 612 | 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))); 613 | return t 614 | } 615 | 616 | msg(e = t, s = "", i = "", r){ 617 | const o = t => { 618 | if(!t) return t; 619 | if("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; 620 | if("object" == typeof t){ 621 | if(this.isLoon()){ 622 | let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; 623 | return { openUrl: e, mediaUrl: s } 624 | } 625 | if(this.isQuanX()){ 626 | let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; 627 | return { "open-url": e, "media-url": s } 628 | } 629 | if(this.isSurge()){ 630 | let e = t.url || t.openUrl || t["open-url"]; 631 | return { url: e } 632 | } 633 | } 634 | }; 635 | if(this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog){ 636 | let t = ["", "==============📣系统通知📣=============="]; 637 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) 638 | } 639 | } 640 | 641 | log(...t){t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator))} 642 | 643 | logErr(t, e){ 644 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 645 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 646 | } 647 | 648 | wait(t){return new Promise(e => setTimeout(e, t))} 649 | 650 | done(t = {}){ 651 | const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; 652 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 653 | } 654 | }(t, e) 655 | } 656 | -------------------------------------------------------------------------------- /jd_car_exchange_xh.js: -------------------------------------------------------------------------------- 1 | /* 2 | 京东汽车兑换,500赛点兑换500京豆长期活动 3 | 活动入口:京东APP首页-京东汽车-屏幕右中部,车主福利 4 | 更新地址:https://github.com/X1a0He/jd_scripts_fixed/ 5 | 已支持IOS, Node.js支持N个京东账号 6 | 脚本兼容: Node.js 7 | 修复兑换api,Fix time:2021-09-06 22:02 8 | */ 9 | const $ = new Env('京东汽车兑换'); 10 | //Node.js用户请在jdCookie.js处填写京东ck; 11 | const jdCookieNode = $.isNode() ? require('./jdCookie.js') : ''; 12 | //IOS等用户直接用NobyDa的jd cookie 13 | let cookiesArr = [], cookie = '', message; 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 | }; 20 | } else { 21 | cookiesArr = [$.getdata('CookieJD'), $.getdata('CookieJD2'), ...jsonParse($.getdata('CookiesJD') || "[]").map(item => item.cookie)].filter(item => !!item); 22 | } 23 | const JD_API_HOST = 'https://car-member.jd.com/api/'; 24 | !(async() => { 25 | if(!cookiesArr[0]){ 26 | $.msg($.name, '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/bean/signIndex.action', { "open-url": "https://bean.m.jd.com/bean/signIndex.action" }); 27 | return; 28 | } 29 | for(let i = 0; i < cookiesArr.length; i++){ 30 | if(cookiesArr[i]){ 31 | cookie = cookiesArr[i]; 32 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]) 33 | $.index = i + 1; 34 | $.isLogin = true; 35 | $.nickName = ''; 36 | message = ''; 37 | console.log(`=====京东账号${$.index} ${$.UserName}=====`) 38 | for(let j = 0; j < 10; ++j){ 39 | await exchange(); 40 | } 41 | } 42 | } 43 | })().catch((e) => { 44 | $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') 45 | }).finally(() => { 46 | $.done(); 47 | }) 48 | 49 | function exchange(){ 50 | return new Promise(resolve => { 51 | $.get(taskUrl('v1/user/exchange/bean/check'), (err, resp, data) => { 52 | try{ 53 | if(err){ 54 | console.log(`${JSON.stringify(err)}`) 55 | console.log(`${$.name} API请求失败,请检查网路重试\n`) 56 | } else { 57 | if(safeGet(data)){ 58 | data = JSON.parse(data); 59 | if(data.status) console.log(`兑换结果:${data.data.reason}`); 60 | } 61 | } 62 | } catch(e){ 63 | $.logErr(e, resp) 64 | } finally{ 65 | resolve(); 66 | } 67 | }) 68 | }) 69 | } 70 | 71 | function taskUrl(function_id, body = {}){ 72 | return { 73 | url: `${JD_API_HOST}${function_id}?timestamp=${new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + 8 * 60 * 60 * 1000}`, 74 | headers: { 75 | "Accept": "*/*", 76 | "Accept-Encoding": "gzip, deflate, br", 77 | "Accept-Language": "zh-cn", 78 | "Connection": "keep-alive", 79 | "Host": "car-member.jd.com", 80 | 'origin': 'https://h5.m.jd.com', 81 | "Referer": "https://h5.m.jd.com/", 82 | "Cookie": cookie, 83 | "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"), 84 | } 85 | } 86 | } 87 | 88 | function safeGet(data){ 89 | try{ 90 | if(typeof JSON.parse(data) == "object"){ 91 | return true; 92 | } 93 | } catch(e){ 94 | console.log(e); 95 | console.log(`京东服务器访问数据为空,请检查自身设备网络情况`); 96 | return false; 97 | } 98 | } 99 | 100 | function jsonParse(str){ 101 | if(typeof str == "string"){ 102 | try{ 103 | return JSON.parse(str); 104 | } catch(e){ 105 | console.log(e); 106 | $.msg($.name, '', '请勿随意在BoxJs输入框修改内容\n建议通过脚本去获取cookie') 107 | return []; 108 | } 109 | } 110 | } 111 | 112 | // prettier-ignore 113 | function Env(t, e){ 114 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 115 | 116 | class s{ 117 | constructor(t){this.env = t} 118 | 119 | send(t, e = "GET"){ 120 | t = "string" == typeof t ? { url: t } : t; 121 | let s = this.get; 122 | return "POST" === e && (s = this.post), new Promise((e, i) => {s.call(this, t, (t, s, r) => {t ? i(t) : e(s)})}) 123 | } 124 | 125 | get(t){return this.send.call(this.env, t)} 126 | 127 | post(t){return this.send.call(this.env, t, "POST")} 128 | } 129 | 130 | return new class{ 131 | 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}, 开始!`)} 132 | 133 | isNode(){return "undefined" != typeof module && !!module.exports} 134 | 135 | isQuanX(){return "undefined" != typeof $task} 136 | 137 | isSurge(){return "undefined" != typeof $httpClient && "undefined" == typeof $loon} 138 | 139 | isLoon(){return "undefined" != typeof $loon} 140 | 141 | toObj(t, e = null){try{return JSON.parse(t)} catch{return e}} 142 | 143 | toStr(t, e = null){try{return JSON.stringify(t)} catch{return e}} 144 | 145 | getjson(t, e){ 146 | let s = e; 147 | const i = this.getdata(t); 148 | if(i) try{s = JSON.parse(this.getdata(t))} catch{} 149 | return s 150 | } 151 | 152 | setjson(t, e){try{return this.setdata(JSON.stringify(t), e)} catch{return !1}} 153 | 154 | getScript(t){return new Promise(e => {this.get({ url: t }, (t, s, i) => e(i))})} 155 | 156 | runScript(t, e){ 157 | return new Promise(s => { 158 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 159 | i = i ? i.replace(/\n/g, "").trim() : i; 160 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 161 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 162 | const [o, h] = i.split("@"), n = { 163 | url: `http://${h}/v1/scripting/evaluate`, 164 | body: { script_text: t, mock_type: "cron", timeout: r }, 165 | headers: { "X-Key": o, Accept: "*/*" } 166 | }; 167 | this.post(n, (t, e, i) => s(i)) 168 | }).catch(t => this.logErr(t)) 169 | } 170 | 171 | loaddata(){ 172 | if(!this.isNode()) return {}; 173 | { 174 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 175 | const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), 176 | s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); 177 | if(!s && !i) return {}; 178 | { 179 | const i = s ? t : e; 180 | try{return JSON.parse(this.fs.readFileSync(i))} catch(t){return {}} 181 | } 182 | } 183 | } 184 | 185 | writedata(){ 186 | if(this.isNode()){ 187 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 188 | const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), 189 | s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); 190 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 191 | } 192 | } 193 | 194 | lodash_get(t, e, s){ 195 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 196 | let r = t; 197 | for(const t of i) if(r = Object(r)[t], void 0 === r) return s; 198 | return r 199 | } 200 | 201 | 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)} 202 | 203 | getdata(t){ 204 | let e = this.getval(t); 205 | if(/^@/.test(t)){ 206 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; 207 | if(r) try{ 208 | const t = JSON.parse(r); 209 | e = t ? this.lodash_get(t, i, "") : e 210 | } catch(t){e = ""} 211 | } 212 | return e 213 | } 214 | 215 | setdata(t, e){ 216 | let s = !1; 217 | if(/^@/.test(e)){ 218 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), 219 | h = i ? "null" === o ? null : o || "{}" : "{}"; 220 | try{ 221 | const e = JSON.parse(h); 222 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) 223 | } catch(e){ 224 | const o = {}; 225 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) 226 | } 227 | } else s = this.setval(t, e); 228 | return s 229 | } 230 | 231 | 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} 232 | 233 | 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} 234 | 235 | 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))} 236 | 237 | get(t, e = (() => {})){ 238 | 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 => { 239 | const { 240 | statusCode: s, 241 | statusCode: i, 242 | headers: r, 243 | body: o 244 | } = t; 245 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 246 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 247 | try{ 248 | if(t.headers["set-cookie"]){ 249 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 250 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar 251 | } 252 | } catch(t){this.logErr(t)} 253 | }).then(t => { 254 | const { statusCode: s, statusCode: i, headers: r, body: o } = t; 255 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 256 | }, t => { 257 | const { message: s, response: i } = t; 258 | e(s, i, i && i.body) 259 | })) 260 | } 261 | 262 | post(t, e = (() => {})){ 263 | 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 => { 264 | const { 265 | statusCode: s, 266 | statusCode: i, 267 | headers: r, 268 | body: o 269 | } = t; 270 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 271 | }, t => e(t)); else if(this.isNode()){ 272 | this.initGotEnv(t); 273 | const { url: s, ...i } = t; 274 | this.got.post(s, i).then(t => { 275 | const { statusCode: s, statusCode: i, headers: r, body: o } = t; 276 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 277 | }, t => { 278 | const { message: s, response: i } = t; 279 | e(s, i, i && i.body) 280 | }) 281 | } 282 | } 283 | 284 | time(t, e = null){ 285 | const s = e ? new Date(e) : new Date; 286 | let i = { 287 | "M+": s.getMonth() + 1, 288 | "d+": s.getDate(), 289 | "H+": s.getHours(), 290 | "m+": s.getMinutes(), 291 | "s+": s.getSeconds(), 292 | "q+": Math.floor((s.getMonth() + 3) / 3), 293 | S: s.getMilliseconds() 294 | }; 295 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 296 | 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))); 297 | return t 298 | } 299 | 300 | msg(e = t, s = "", i = "", r){ 301 | const o = t => { 302 | if(!t) return t; 303 | if("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; 304 | if("object" == typeof t){ 305 | if(this.isLoon()){ 306 | let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; 307 | return { openUrl: e, mediaUrl: s } 308 | } 309 | if(this.isQuanX()){ 310 | let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; 311 | return { "open-url": e, "media-url": s } 312 | } 313 | if(this.isSurge()){ 314 | let e = t.url || t.openUrl || t["open-url"]; 315 | return { url: e } 316 | } 317 | } 318 | }; 319 | if(this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog){ 320 | let t = ["", "==============📣系统通知📣=============="]; 321 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) 322 | } 323 | } 324 | 325 | log(...t){t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator))} 326 | 327 | logErr(t, e){ 328 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 329 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 330 | } 331 | 332 | wait(t){return new Promise(e => setTimeout(e, t))} 333 | 334 | done(t = {}){ 335 | const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; 336 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 337 | } 338 | }(t, e) 339 | } 340 | -------------------------------------------------------------------------------- /jd_cleancart.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: X1a0He 3 | * @Contact: https://t.me/X1a0He 4 | * @Github: https://github.com/X1a0He/jd_scripts_fixed 5 | * 清空购物车,支持环境变量设置关键字,用@分隔,使用前请认真看对应注释 6 | * 由于不是用app来进行购物车删除,所以可能会出现部分购物车数据无法删除的问题,例如预购商品,属于正常 7 | */ 8 | const $ = new Env('清空购物车'); 9 | //Node.js用户请在jdCookie.js处填写京东ck; 10 | const jdCookieNode = $.isNode() ? require('./jdCookie.js') : ''; 11 | const notify = $.isNode() ? require('./sendNotify') : ''; 12 | let cookiesArr = [], cookie = '', postBody = '', venderCart, error = false; 13 | let args_xh = { 14 | /* 15 | * 跳过某个指定账号,默认为全部账号清空 16 | * 填写规则:例如当前Cookie1为pt_key=key; pt_pin=pin1;则环境变量填写pin1即可,此时pin1的购物车将不会被清空 17 | * 若有更多,则按照pin1@pin2@pin3进行填写 18 | * 环境变量名称:XH_CLEAN_EXCEPT 19 | */ 20 | except: process.env.XH_CLEAN_EXCEPT && process.env.XH_CLEAN_EXCEPT.split('@') || [], 21 | /* 22 | * 控制脚本是否执行,设置为true时才会执行删除购物车 23 | * 环境变量名称:JD_CART 24 | */ 25 | clean: process.env.JD_CART === 'true' || false, 26 | /* 27 | * 控制脚本运行一次取消多少条购物车数据,为0则不删除,默认为100 28 | * 环境变量名称:XH_CLEAN_REMOVESIZE 29 | */ 30 | removeSize: process.env.XH_CLEAN_REMOVESIZE * 1 || 100, 31 | /* 32 | * 关键字/关键词设置,当购物车商品标题包含关键字/关键词时,跳过该条数据,多个则用@分隔,例如 旺仔牛奶@红外线@紫光 33 | * 环境变量名称:XH_CLEAN_KEYWORDS 34 | */ 35 | keywords: process.env.XH_CLEAN_KEYWORDS && process.env.XH_CLEAN_KEYWORDS.split('@') || [], 36 | } 37 | console.log('使用前请确保你认真看了注释,看完注释有问题就带着你的问题来找我') 38 | console.log('tg: https://t.me/X1a0He') 39 | console.log('=====环境变量配置如下=====') 40 | console.log(`except: ${typeof args_xh.except}, ${args_xh.except}`) 41 | console.log(`clean: ${typeof args_xh.clean}, ${args_xh.clean}`) 42 | console.log(`removeSize: ${typeof args_xh.removeSize}, ${args_xh.removeSize}`) 43 | console.log(`keywords: ${typeof args_xh.keywords}, ${args_xh.keywords}`) 44 | console.log('=======================') 45 | console.log() 46 | if ($.isNode()) { 47 | Object.keys(jdCookieNode).forEach((item) => { 48 | cookiesArr.push(jdCookieNode[item]) 49 | }) 50 | if (process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => { }; 51 | } else cookiesArr = [$.getdata('CookieJD'), $.getdata('CookieJD2'), ...jsonParse($.getdata('CookiesJD') || "[]").map(item => item.cookie)].filter(item => !!item); 52 | !(async () => { 53 | if (args_xh.clean) { 54 | if (!cookiesArr[0]) { 55 | $.msg('【京东账号一】移除购物车失败', '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/bean/signIndex.action', { 56 | "open-url": "https://bean.m.jd.com/bean/signIndex.action" 57 | }); 58 | } 59 | for (let i = 0; i < cookiesArr.length; i++) { 60 | if (cookiesArr[i]) { 61 | cookie = cookiesArr[i]; 62 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]) 63 | $.index = i + 1; 64 | $.isLogin = true; 65 | $.nickName = ''; 66 | $.error = false; 67 | await TotalBean(); 68 | console.log(`****开始【京东账号${$.index}】${$.nickName || $.UserName}****`); 69 | if (args_xh.except.includes($.UserName)) { 70 | console.log(`跳过账号:${$.nickName || $.UserName}`) 71 | continue 72 | } 73 | if (!$.isLogin) { 74 | $.msg($.name, `【提示】cookie已失效`, `京东账号${$.index} ${$.nickName || $.UserName}\n请重新登录获取\nhttps://bean.m.jd.com/bean/signIndex.action`, { 75 | "open-url": "https://bean.m.jd.com/bean/signIndex.action" 76 | }); 77 | if ($.isNode()) { 78 | await notify.sendNotify(`${$.name}cookie已失效 - ${$.UserName}`, `京东账号${$.index} ${$.UserName}\n请重新登录获取cookie`); 79 | } 80 | continue 81 | } 82 | if (args_xh.removeSize === 0) continue; 83 | do { 84 | await getCart_xh(); 85 | $.keywordsNum = 0 86 | if ($.beforeRemove !== "0") { 87 | await cartFilter_xh(venderCart); 88 | if (parseInt($.beforeRemove) !== $.keywordsNum) await removeCart(); 89 | else { 90 | console.log('\n由于购物车内的商品均包含关键字,本次执行将不删除购物车数据') 91 | break; 92 | } 93 | } else break; 94 | } while (!$.error && $.keywordsNum !== parseInt($.beforeRemove)) 95 | } 96 | } 97 | } else { 98 | console.log("你设置了不删除购物车数据,要删除请设置环境变量 JD_CART 为 true") 99 | } 100 | })().catch((e) => { 101 | $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') 102 | }).finally(() => { 103 | $.done(); 104 | }) 105 | 106 | function getCart_xh() { 107 | console.log('正在获取购物车数据...') 108 | return new Promise((resolve) => { 109 | const option = { 110 | url: 'https://p.m.jd.com/cart/cart.action?fromnav=1&sceneval=2', 111 | headers: { 112 | "Cookie": cookie, 113 | "User-Agent": "jdapp;JD4iPhone/167724 (iPhone; iOS 15.0; Scale/3.00)", 114 | }, 115 | } 116 | $.get(option, async (err, resp, data) => { 117 | try { 118 | data = JSON.parse(data.match(/window\.cartData = ([^;]*)/)[1]) 119 | $.areaId = data.areaId; // locationId的传值 120 | $.traceId = data.traceId; // traceid的传值 121 | venderCart = data.cart.venderCart; 122 | postBody = 'pingouchannel=0&commlist='; 123 | $.beforeRemove = data.cart.currentCount ? data.cart.currentCount : 0; 124 | console.log(`获取到购物车数据 ${$.beforeRemove} 条`) 125 | } catch (e) { 126 | $.logErr(e, resp); 127 | } finally { 128 | resolve(data); 129 | } 130 | }); 131 | }) 132 | } 133 | 134 | function cartFilter_xh(cartData) { 135 | console.log("正在整理数据...") 136 | let pid; 137 | $.pushed = 0 138 | for (let cartJson of cartData) { 139 | if ($.pushed === args_xh.removeSize) break; 140 | for (let sortedItem of cartJson.sortedItems) { 141 | if ($.pushed === args_xh.removeSize) break; 142 | pid = typeof (sortedItem.polyItem.promotion) !== "undefined" ? sortedItem.polyItem.promotion.pid : "" 143 | for (let product of sortedItem.polyItem.products) { 144 | if ($.pushed === args_xh.removeSize) break; 145 | let mainSkuName = product.mainSku.name 146 | $.isKeyword = false 147 | $.isPush = true 148 | for (let keyword of args_xh.keywords) { 149 | if (mainSkuName.indexOf(keyword) !== -1) { 150 | $.keywordsNum += 1 151 | $.isPush = false 152 | $.keyword = keyword; 153 | break; 154 | } else $.isPush = true 155 | } 156 | if ($.isPush) { 157 | let skuUuid = product.skuUuid; 158 | let mainSkuId = product.mainSku.id 159 | if (pid === "") postBody += `${mainSkuId},,1,${mainSkuId},1,,0,skuUuid:${skuUuid}@@useUuid:0$` 160 | else postBody += `${mainSkuId},,1,${mainSkuId},11,${pid},0,skuUuid:${skuUuid}@@useUuid:0$` 161 | $.pushed += 1; 162 | } else { 163 | console.log(`\n${mainSkuName}`) 164 | console.log(`商品已被过滤,原因:包含关键字 ${$.keyword}`) 165 | $.isKeyword = true 166 | } 167 | } 168 | } 169 | } 170 | postBody += `&type=0&checked=0&locationid=${$.areaId}&templete=1®=1&scene=0&version=20190418&traceid=${$.traceId}&tabMenuType=1&sceneval=2` 171 | } 172 | 173 | function removeCart() { 174 | console.log('正在删除购物车数据...') 175 | return new Promise((resolve) => { 176 | const option = { 177 | url: 'https://wq.jd.com/deal/mshopcart/rmvCmdy?sceneval=2&g_login_type=1&g_ty=ajax', 178 | body: postBody, 179 | headers: { 180 | "Cookie": cookie, 181 | "User-Agent": "jdapp;JD4iPhone/167724 (iPhone; iOS 15.0; Scale/3.00)", 182 | "referer": "https://p.m.jd.com/", 183 | "origin": "https://p.m.jd.com/" 184 | }, 185 | } 186 | $.post(option, async (err, resp, data) => { 187 | try { 188 | data = JSON.parse(data); 189 | $.afterRemove = data.cartJson.num 190 | if ($.afterRemove < $.beforeRemove) { 191 | console.log(`删除成功,当前购物车剩余数据 ${$.afterRemove} 条\n`) 192 | $.beforeRemove = $.afterRemove 193 | } else { 194 | console.log('删除失败') 195 | console.log(data.errMsg) 196 | $.error = true; 197 | } 198 | } catch (e) { 199 | $.logErr(e, resp); 200 | } finally { 201 | resolve(data); 202 | } 203 | }); 204 | }) 205 | } 206 | 207 | function TotalBean() { 208 | return new Promise(async resolve => { 209 | const options = { 210 | "url": `https://wq.jd.com/user/info/QueryJDUserInfo?sceneval=2`, 211 | "headers": { 212 | "Accept": "application/json,text/plain, */*", 213 | "Content-Type": "application/x-www-form-urlencoded", 214 | "Accept-Encoding": "gzip, deflate, br", 215 | "Accept-Language": "zh-cn", 216 | "Connection": "keep-alive", 217 | "Cookie": cookie, 218 | "Referer": "https://wqs.jd.com/my/jingdou/my.shtml?sceneval=2", 219 | "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") 220 | } 221 | } 222 | $.post(options, (err, resp, data) => { 223 | try { 224 | if (err) { 225 | console.log(`${JSON.stringify(err)}`) 226 | console.log(`${$.name} API请求失败,请检查网路重试`) 227 | } else { 228 | if (data) { 229 | data = JSON.parse(data); 230 | if (data['retcode'] === 13) { 231 | $.isLogin = false; //cookie过期 232 | return 233 | } 234 | if (data['retcode'] === 0) { 235 | $.nickName = (data['base'] && data['base'].nickname) || $.UserName; 236 | } else { 237 | $.nickName = $.UserName 238 | } 239 | } else { 240 | console.log(`京东服务器返回空数据`) 241 | } 242 | } 243 | } catch (e) { 244 | $.logErr(e, resp) 245 | } finally { 246 | resolve(); 247 | } 248 | }) 249 | }) 250 | } 251 | 252 | function jsonParse(str) { 253 | if (typeof str == "string") { 254 | try { 255 | return JSON.parse(str); 256 | } catch (e) { 257 | console.log(e); 258 | $.msg($.name, '', '请勿随意在BoxJs输入框修改内容\n建议通过脚本去获取cookie') 259 | return []; 260 | } 261 | } 262 | } 263 | 264 | // prettier-ignore 265 | function Env(t, e) { 266 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 267 | 268 | class s { 269 | constructor(t) { 270 | this.env = t 271 | } 272 | 273 | send(t, e = "GET") { 274 | t = "string" == typeof t ? { 275 | url: t 276 | } : t; 277 | let s = this.get; 278 | return "POST" === e && (s = this.post), new Promise((e, i) => { 279 | s.call(this, t, (t, s, r) => { 280 | t ? i(t) : e(s) 281 | }) 282 | }) 283 | } 284 | 285 | get(t) { 286 | return this.send.call(this.env, t) 287 | } 288 | 289 | post(t) { 290 | return this.send.call(this.env, t, "POST") 291 | } 292 | } 293 | 294 | return new class { 295 | constructor(t, e) { 296 | 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}, 开始!`) 297 | } 298 | 299 | isNode() { 300 | return "undefined" != typeof module && !!module.exports 301 | } 302 | 303 | isQuanX() { 304 | return "undefined" != typeof $task 305 | } 306 | 307 | isSurge() { 308 | return "undefined" != typeof $httpClient && "undefined" == typeof $loon 309 | } 310 | 311 | isLoon() { 312 | return "undefined" != typeof $loon 313 | } 314 | 315 | toObj(t, e = null) { 316 | try { 317 | return JSON.parse(t) 318 | } catch { 319 | return e 320 | } 321 | } 322 | 323 | toStr(t, e = null) { 324 | try { 325 | return JSON.stringify(t) 326 | } catch { 327 | return e 328 | } 329 | } 330 | 331 | getjson(t, e) { 332 | let s = e; 333 | const i = this.getdata(t); 334 | if (i) try { 335 | s = JSON.parse(this.getdata(t)) 336 | } catch { } 337 | return s 338 | } 339 | 340 | setjson(t, e) { 341 | try { 342 | return this.setdata(JSON.stringify(t), e) 343 | } catch { 344 | return !1 345 | } 346 | } 347 | 348 | getScript(t) { 349 | return new Promise(e => { 350 | this.get({ 351 | url: t 352 | }, (t, s, i) => e(i)) 353 | }) 354 | } 355 | 356 | runScript(t, e) { 357 | return new Promise(s => { 358 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 359 | i = i ? i.replace(/\n/g, "").trim() : i; 360 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 361 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 362 | const [o, h] = i.split("@"), n = { 363 | url: `http://${h}/v1/scripting/evaluate`, 364 | body: { 365 | script_text: t, 366 | mock_type: "cron", 367 | timeout: r 368 | }, 369 | headers: { 370 | "X-Key": o, 371 | Accept: "*/*" 372 | } 373 | }; 374 | this.post(n, (t, e, i) => s(i)) 375 | }).catch(t => this.logErr(t)) 376 | } 377 | 378 | loaddata() { 379 | if (!this.isNode()) return {}; 380 | { 381 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 382 | const t = this.path.resolve(this.dataFile), 383 | e = this.path.resolve(process.cwd(), this.dataFile), 384 | s = this.fs.existsSync(t), 385 | i = !s && this.fs.existsSync(e); 386 | if (!s && !i) return {}; 387 | { 388 | const i = s ? t : e; 389 | try { 390 | return JSON.parse(this.fs.readFileSync(i)) 391 | } catch (t) { 392 | return {} 393 | } 394 | } 395 | } 396 | } 397 | 398 | writedata() { 399 | if (this.isNode()) { 400 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 401 | const t = this.path.resolve(this.dataFile), 402 | e = this.path.resolve(process.cwd(), this.dataFile), 403 | s = this.fs.existsSync(t), 404 | i = !s && this.fs.existsSync(e), 405 | r = JSON.stringify(this.data); 406 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 407 | } 408 | } 409 | 410 | lodash_get(t, e, s) { 411 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 412 | let r = t; 413 | for (const t of i) 414 | if (r = Object(r)[t], void 0 === r) return s; 415 | return r 416 | } 417 | 418 | lodash_set(t, e, s) { 419 | 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) 420 | } 421 | 422 | getdata(t) { 423 | let e = this.getval(t); 424 | if (/^@/.test(t)) { 425 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; 426 | if (r) try { 427 | const t = JSON.parse(r); 428 | e = t ? this.lodash_get(t, i, "") : e 429 | } catch (t) { 430 | e = "" 431 | } 432 | } 433 | return e 434 | } 435 | 436 | setdata(t, e) { 437 | let s = !1; 438 | if (/^@/.test(e)) { 439 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), 440 | h = i ? "null" === o ? null : o || "{}" : "{}"; 441 | try { 442 | const e = JSON.parse(h); 443 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) 444 | } catch (e) { 445 | const o = {}; 446 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) 447 | } 448 | } else s = this.setval(t, e); 449 | return s 450 | } 451 | 452 | getval(t) { 453 | 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 454 | } 455 | 456 | setval(t, e) { 457 | 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 458 | } 459 | 460 | initGotEnv(t) { 461 | 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)) 462 | } 463 | 464 | get(t, e = (() => { })) { 465 | 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, { 466 | "X-Surge-Skip-Scripting": !1 467 | })), $httpClient.get(t, (t, s, i) => { 468 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 469 | })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 470 | hints: !1 471 | })), $task.fetch(t).then(t => { 472 | const { 473 | statusCode: s, 474 | statusCode: i, 475 | headers: r, 476 | body: o 477 | } = t; 478 | e(null, { 479 | status: s, 480 | statusCode: i, 481 | headers: r, 482 | body: o 483 | }, o) 484 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 485 | try { 486 | if (t.headers["set-cookie"]) { 487 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 488 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar 489 | } 490 | } catch (t) { 491 | this.logErr(t) 492 | } 493 | }).then(t => { 494 | const { 495 | statusCode: s, 496 | statusCode: i, 497 | headers: r, 498 | body: o 499 | } = t; 500 | e(null, { 501 | status: s, 502 | statusCode: i, 503 | headers: r, 504 | body: o 505 | }, o) 506 | }, t => { 507 | const { 508 | message: s, 509 | response: i 510 | } = t; 511 | e(s, i, i && i.body) 512 | })) 513 | } 514 | 515 | post(t, e = (() => { })) { 516 | 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, { 517 | "X-Surge-Skip-Scripting": !1 518 | })), $httpClient.post(t, (t, s, i) => { 519 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 520 | }); 521 | else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 522 | hints: !1 523 | })), $task.fetch(t).then(t => { 524 | const { 525 | statusCode: s, 526 | statusCode: i, 527 | headers: r, 528 | body: o 529 | } = t; 530 | e(null, { 531 | status: s, 532 | statusCode: i, 533 | headers: r, 534 | body: o 535 | }, o) 536 | }, t => e(t)); 537 | else if (this.isNode()) { 538 | this.initGotEnv(t); 539 | const { 540 | url: s, 541 | ...i 542 | } = t; 543 | this.got.post(s, i).then(t => { 544 | const { 545 | statusCode: s, 546 | statusCode: i, 547 | headers: r, 548 | body: o 549 | } = t; 550 | e(null, { 551 | status: s, 552 | statusCode: i, 553 | headers: r, 554 | body: o 555 | }, o) 556 | }, t => { 557 | const { 558 | message: s, 559 | response: i 560 | } = t; 561 | e(s, i, i && i.body) 562 | }) 563 | } 564 | } 565 | 566 | time(t, e = null) { 567 | const s = e ? new Date(e) : new Date; 568 | let i = { 569 | "M+": s.getMonth() + 1, 570 | "d+": s.getDate(), 571 | "H+": s.getHours(), 572 | "m+": s.getMinutes(), 573 | "s+": s.getSeconds(), 574 | "q+": Math.floor((s.getMonth() + 3) / 3), 575 | S: s.getMilliseconds() 576 | }; 577 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 578 | 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))); 579 | return t 580 | } 581 | 582 | msg(e = t, s = "", i = "", r) { 583 | const o = t => { 584 | if (!t) return t; 585 | if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { 586 | "open-url": t 587 | } : this.isSurge() ? { 588 | url: t 589 | } : void 0; 590 | if ("object" == typeof t) { 591 | if (this.isLoon()) { 592 | let e = t.openUrl || t.url || t["open-url"], 593 | s = t.mediaUrl || t["media-url"]; 594 | return { 595 | openUrl: e, 596 | mediaUrl: s 597 | } 598 | } 599 | if (this.isQuanX()) { 600 | let e = t["open-url"] || t.url || t.openUrl, 601 | s = t["media-url"] || t.mediaUrl; 602 | return { 603 | "open-url": e, 604 | "media-url": s 605 | } 606 | } 607 | if (this.isSurge()) { 608 | let e = t.url || t.openUrl || t["open-url"]; 609 | return { 610 | url: e 611 | } 612 | } 613 | } 614 | }; 615 | if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { 616 | let t = ["", "==============📣系统通知📣=============="]; 617 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) 618 | } 619 | } 620 | 621 | log(...t) { 622 | t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) 623 | } 624 | 625 | logErr(t, e) { 626 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 627 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 628 | } 629 | 630 | wait(t) { 631 | return new Promise(e => setTimeout(e, t)) 632 | } 633 | 634 | done(t = {}) { 635 | const e = (new Date).getTime(), 636 | s = (e - this.startTime) / 1e3; 637 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 638 | } 639 | }(t, e) 640 | } 641 | -------------------------------------------------------------------------------- /jd_islogin_xh.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 检测账号是否已登录,换个角度应该可以检测Cookie是否失效吧 3 | * By X1a0He 4 | * https://github.com/X1a0He/jd_scripts_fixed 5 | * */ 6 | const $ = new Env("京东检测Cookie是否有效"); 7 | const jdCookieNode = $.isNode() ? require("./jdCookie.js") : ""; 8 | const notify = $.isNode() ? require('./sendNotify') : ''; 9 | let cookiesArr = [], cookie = "", message; 10 | $.context = ``; 11 | if($.isNode()){ 12 | Object.keys(jdCookieNode).forEach((item) => {cookiesArr.push(jdCookieNode[item]);}); 13 | if(process.env.JD_DEBUG && process.env.JD_DEBUG === "false") console.log = () => {}; 14 | } else cookiesArr = [$.getdata("CookieJD"), $.getdata("CookieJD2"), ...$.toObj($.getdata("CookiesJD") || "[]").map((item) => item.cookie),].filter((item) => !!item); 15 | !(async() => { 16 | if(!cookiesArr[0]){ 17 | $.msg($.name, "【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取", "https://bean.m.jd.com/", { "open-url": "https://bean.m.jd.com/" }); 18 | return; 19 | } 20 | for(let i = 0; i < cookiesArr.length; i++){ 21 | if(cookiesArr[i]){ 22 | cookie = cookiesArr[i]; 23 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 24 | $.index = i + 1; 25 | message = ""; 26 | console.log(`[京东账号${$.index} ${$.UserName}] 正在检测...`); 27 | await isLogin(); 28 | await $.wait(1000); 29 | } 30 | } 31 | if($.isNode()){ 32 | console.log('正在发送通知...') 33 | await notify.sendNotify(`${$.name}`, `${$.context}`) 34 | } 35 | })().catch((e) => { 36 | $.log("", `❌ ${$.name}, 失败! 原因: ${e}!`, ""); 37 | }).finally(() => { 38 | $.done(); 39 | }); 40 | 41 | function isLogin(){ 42 | return new Promise((resolve) => { 43 | const options = { 44 | url: 'https://plogin.m.jd.com/cgi-bin/ml/islogin', 45 | headers: { 46 | "Cookie": cookie, 47 | "referer": "https://h5.m.jd.com/", 48 | "User-Agent": "jdapp;iPhone;10.1.2;15.0;network/wifi;Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1", 49 | }, 50 | } 51 | $.get(options, (err, resp, data) => { 52 | try{ 53 | if(safeGet(data)){ 54 | data = JSON.parse(data); 55 | if(data.islogin === "1"){ 56 | console.log(`[京东账号${$.index} ${$.UserName}] ✅Cookie有效\n`) 57 | $.context += `[京东账号${$.index} ${$.UserName}] ✅Cookie有效\n` 58 | } else if(data.islogin === "0"){ 59 | console.log(`[京东账号${$.index} ${$.UserName}] ❌Cookie失效了...\n`) 60 | $.context += `[京东账号${$.index} ${$.UserName}] ❌Cookie失效了...\n` 61 | } else { 62 | console.log(`[京东账号${$.index} ${$.UserName}] ⚠️未知返回...\n`) 63 | $.context += `[京东账号${$.index} ${$.UserName}] ⚠️未知返回...\n` 64 | } 65 | } 66 | } catch(e){ 67 | console.log(e); 68 | } finally{ 69 | resolve(); 70 | } 71 | }); 72 | }); 73 | } 74 | 75 | function safeGet(data){ 76 | try{ 77 | if(typeof JSON.parse(data) == "object"){ 78 | return true; 79 | } 80 | } catch(e){ 81 | console.log(e); 82 | console.log(`京东服务器访问数据为空,请检查自身设备网络情况`); 83 | return false; 84 | } 85 | } 86 | 87 | // prettier-ignore 88 | function Env(t, e){ 89 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 90 | 91 | class s{ 92 | constructor(t){this.env = t} 93 | 94 | send(t, e = "GET"){ 95 | t = "string" == typeof t ? { url: t } : t; 96 | let s = this.get; 97 | return "POST" === e && (s = this.post), new Promise((e, i) => {s.call(this, t, (t, s, r) => {t ? i(t) : e(s)})}) 98 | } 99 | 100 | get(t){return this.send.call(this.env, t)} 101 | 102 | post(t){return this.send.call(this.env, t, "POST")} 103 | } 104 | 105 | return new class{ 106 | 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}, 开始!`)} 107 | 108 | isNode(){return "undefined" != typeof module && !!module.exports} 109 | 110 | isQuanX(){return "undefined" != typeof $task} 111 | 112 | isSurge(){return "undefined" != typeof $httpClient && "undefined" == typeof $loon} 113 | 114 | isLoon(){return "undefined" != typeof $loon} 115 | 116 | toObj(t, e = null){try{return JSON.parse(t)} catch{return e}} 117 | 118 | toStr(t, e = null){try{return JSON.stringify(t)} catch{return e}} 119 | 120 | getjson(t, e){ 121 | let s = e; 122 | const i = this.getdata(t); 123 | if(i) try{s = JSON.parse(this.getdata(t))} catch{} 124 | return s 125 | } 126 | 127 | setjson(t, e){try{return this.setdata(JSON.stringify(t), e)} catch{return !1}} 128 | 129 | getScript(t){return new Promise(e => {this.get({ url: t }, (t, s, i) => e(i))})} 130 | 131 | runScript(t, e){ 132 | return new Promise(s => { 133 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 134 | i = i ? i.replace(/\n/g, "").trim() : i; 135 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 136 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 137 | const [o, h] = i.split("@"), n = { 138 | url: `http://${h}/v1/scripting/evaluate`, 139 | body: { script_text: t, mock_type: "cron", timeout: r }, 140 | headers: { "X-Key": o, Accept: "*/*" } 141 | }; 142 | this.post(n, (t, e, i) => s(i)) 143 | }).catch(t => this.logErr(t)) 144 | } 145 | 146 | loaddata(){ 147 | if(!this.isNode()) return {}; 148 | { 149 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 150 | const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), 151 | s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); 152 | if(!s && !i) return {}; 153 | { 154 | const i = s ? t : e; 155 | try{return JSON.parse(this.fs.readFileSync(i))} catch(t){return {}} 156 | } 157 | } 158 | } 159 | 160 | writedata(){ 161 | if(this.isNode()){ 162 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 163 | const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), 164 | s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); 165 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 166 | } 167 | } 168 | 169 | lodash_get(t, e, s){ 170 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 171 | let r = t; 172 | for(const t of i) if(r = Object(r)[t], void 0 === r) return s; 173 | return r 174 | } 175 | 176 | 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)} 177 | 178 | getdata(t){ 179 | let e = this.getval(t); 180 | if(/^@/.test(t)){ 181 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; 182 | if(r) try{ 183 | const t = JSON.parse(r); 184 | e = t ? this.lodash_get(t, i, "") : e 185 | } catch(t){e = ""} 186 | } 187 | return e 188 | } 189 | 190 | setdata(t, e){ 191 | let s = !1; 192 | if(/^@/.test(e)){ 193 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), 194 | h = i ? "null" === o ? null : o || "{}" : "{}"; 195 | try{ 196 | const e = JSON.parse(h); 197 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) 198 | } catch(e){ 199 | const o = {}; 200 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) 201 | } 202 | } else s = this.setval(t, e); 203 | return s 204 | } 205 | 206 | 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} 207 | 208 | 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} 209 | 210 | 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))} 211 | 212 | get(t, e = (() => {})){ 213 | 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 => { 214 | const { 215 | statusCode: s, 216 | statusCode: i, 217 | headers: r, 218 | body: o 219 | } = t; 220 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 221 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 222 | try{ 223 | if(t.headers["set-cookie"]){ 224 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 225 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar 226 | } 227 | } catch(t){this.logErr(t)} 228 | }).then(t => { 229 | const { statusCode: s, statusCode: i, headers: r, body: o } = t; 230 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 231 | }, t => { 232 | const { message: s, response: i } = t; 233 | e(s, i, i && i.body) 234 | })) 235 | } 236 | 237 | post(t, e = (() => {})){ 238 | 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 => { 239 | const { 240 | statusCode: s, 241 | statusCode: i, 242 | headers: r, 243 | body: o 244 | } = t; 245 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 246 | }, t => e(t)); else if(this.isNode()){ 247 | this.initGotEnv(t); 248 | const { url: s, ...i } = t; 249 | this.got.post(s, i).then(t => { 250 | const { statusCode: s, statusCode: i, headers: r, body: o } = t; 251 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 252 | }, t => { 253 | const { message: s, response: i } = t; 254 | e(s, i, i && i.body) 255 | }) 256 | } 257 | } 258 | 259 | time(t, e = null){ 260 | const s = e ? new Date(e) : new Date; 261 | let i = { 262 | "M+": s.getMonth() + 1, 263 | "d+": s.getDate(), 264 | "H+": s.getHours(), 265 | "m+": s.getMinutes(), 266 | "s+": s.getSeconds(), 267 | "q+": Math.floor((s.getMonth() + 3) / 3), 268 | S: s.getMilliseconds() 269 | }; 270 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 271 | 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))); 272 | return t 273 | } 274 | 275 | msg(e = t, s = "", i = "", r){ 276 | const o = t => { 277 | if(!t) return t; 278 | if("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; 279 | if("object" == typeof t){ 280 | if(this.isLoon()){ 281 | let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; 282 | return { openUrl: e, mediaUrl: s } 283 | } 284 | if(this.isQuanX()){ 285 | let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; 286 | return { "open-url": e, "media-url": s } 287 | } 288 | if(this.isSurge()){ 289 | let e = t.url || t.openUrl || t["open-url"]; 290 | return { url: e } 291 | } 292 | } 293 | }; 294 | if(this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog){ 295 | let t = ["", "==============📣系统通知📣=============="]; 296 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) 297 | } 298 | } 299 | 300 | log(...t){t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator))} 301 | 302 | logErr(t, e){ 303 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 304 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 305 | } 306 | 307 | wait(t){return new Promise(e => setTimeout(e, t))} 308 | 309 | done(t = {}){ 310 | const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; 311 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 312 | } 313 | }(t, e) 314 | } 315 | -------------------------------------------------------------------------------- /jd_jin_tie_xh.js: -------------------------------------------------------------------------------- 1 | /* 2 | 领金贴(只签到) Fixed By X1a0He 3 | Last Modified time: 2022-05-28 15:00:00 4 | Last Modified By X1a0He 5 | 活动入口:京东APP首页-领金贴,[活动地址](https://active.jd.com/forever/cashback/index/) 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 | //IOS等用户直接用NobyDa的jd cookie 12 | let cookiesArr = [], 13 | cookie = '', 14 | message; 15 | if ($.isNode()) { 16 | Object.keys(jdCookieNode).forEach((item) => { 17 | cookiesArr.push(jdCookieNode[item]); 18 | }); 19 | if (process.env.JD_DEBUG && process.env.JD_DEBUG === "false") console.log = () => {}; 20 | } else { 21 | cookiesArr = [ 22 | $.getdata("CookieJD"), 23 | $.getdata("CookieJD2"), 24 | ...$.toObj($.getdata("CookiesJD") || "[]").map((item) => item.cookie)].filter((item) => !!item); 25 | } 26 | !(async () => { 27 | if (!cookiesArr[0]) { 28 | $.msg($.name, '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/bean/signIndex.action', { "open-url": "https://bean.m.jd.com/bean/signIndex.action" }); 29 | return; 30 | } 31 | for (let i = 0; i < cookiesArr.length; i++) { 32 | if (cookiesArr[i]) { 33 | cookie = cookiesArr[i]; 34 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 35 | $.index = i + 1; 36 | $.isLogin = true; 37 | $.nickName = ''; 38 | message = ''; 39 | await TotalBean(); 40 | console.log(`\n******开始【京东账号${$.index}】${$.nickName || $.UserName}*********\n`); 41 | if (!$.isLogin) { 42 | $.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" }); 43 | if ($.isNode()) { 44 | await notify.sendNotify(`${$.name}cookie已失效 - ${$.UserName}`, `京东账号${$.index} ${$.UserName}\n请重新登录获取cookie`); 45 | } 46 | continue; 47 | } 48 | await main(); 49 | } 50 | } 51 | })().catch((e) => { 52 | $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, ''); 53 | }).finally(() => { 54 | $.done(); 55 | }); 56 | 57 | async function main() { 58 | try { 59 | await channelUserSignInfo_xh(); 60 | await channelUserSubsidyInfo_xh(); 61 | } catch (e) { 62 | $.logErr(e); 63 | } 64 | } 65 | 66 | function channelUserSignInfo_xh() { 67 | return new Promise((resolve) => { 68 | const body = JSON.stringify({ 69 | "source": "JD_JR_APP", 70 | "channel": "default", 71 | "channelLv": "", 72 | "apiVersion": "4.0.0", 73 | "riskDeviceParam": "{}", 74 | "others": { "shareId": "" } 75 | }); 76 | const options = taskUrl_xh('channelUserSignInfo', body, 'jrm'); 77 | $.get(options, async (err, resp, data) => { 78 | try { 79 | if (err) { 80 | console.log(`${JSON.stringify(err)}`); 81 | console.log(`${$.name} API请求失败,请检查网路重试`); 82 | } else { 83 | data = JSON.parse(data); 84 | if (data.resultCode === 0) { 85 | if (data.resultData.code === '000') { 86 | $.keepSigned = 0; 87 | let state = false; 88 | for (let i in data.resultData.data.signDetail) { 89 | if (data.resultData.data.signDetail[i].signed) $.keepSigned += 1; 90 | if (data.resultData.data.dayId === data.resultData.data.signDetail[i].id) { 91 | state = data.resultData.data.signDetail[i].signed; 92 | console.log('获取签到状态成功', state ? '今日已签到' : '今日未签到', '连续签到', $.keepSigned, '天\n'); 93 | } 94 | } 95 | if (!state) await channelSignInSubsidy_xh(); 96 | } else { 97 | console.log('获取签到状态失败', data.resultData.msg); 98 | } 99 | } else { 100 | console.log('获取签到状态失败', data.resultMsg); 101 | } 102 | } 103 | } catch (e) { 104 | $.logErr(e, resp); 105 | } finally { 106 | resolve(data); 107 | } 108 | }); 109 | }); 110 | } 111 | 112 | function channelSignInSubsidy_xh() { 113 | return new Promise((resolve) => { 114 | const body = JSON.stringify({ 115 | "source": "JD_JR_APP", 116 | "channel": "default", 117 | "channelLv": "", 118 | "apiVersion": "4.0.0", 119 | "riskDeviceParam": "{}", 120 | "others": { "shareId": "", "token": "" } 121 | }); 122 | const options = taskUrl_xh('channelSignInSubsidy', body, 'jrm'); 123 | $.post(options, async (err, resp, data) => { 124 | try { 125 | if (err) { 126 | console.log(`${JSON.stringify(err)}`); 127 | console.log(`${$.name} API请求失败,请检查网路重试`); 128 | } else { 129 | data = JSON.parse(data); 130 | if (data.resultCode === 0) { 131 | if (data.resultData.code === '000') { 132 | if (data.resultData.data.signSuccess) { 133 | console.log(`签到成功,获得 0.0${data.resultData.data.rewardAmount}元`); 134 | } 135 | } else if (data.resultData.code === '001') { 136 | console.log(`签到失败,可能今天已签到`); 137 | } else { 138 | // console.log(data) 139 | console.log("签到失败"); 140 | } 141 | } else { 142 | // console.log(data) 143 | console.log("签到失败"); 144 | } 145 | } 146 | } catch (e) { 147 | $.logErr(e, resp); 148 | } finally { 149 | resolve(data); 150 | } 151 | }); 152 | }); 153 | } 154 | 155 | function channelUserSubsidyInfo_xh() { 156 | return new Promise((resolve) => { 157 | const body = JSON.stringify({ 158 | "source": "JD_JR_APP", 159 | "channel": "default", 160 | "channelLv": "", 161 | "apiVersion": "4.0.0", 162 | "riskDeviceParam": "{}", 163 | "others": { "shareId": "" } 164 | }); 165 | const options = taskUrl_xh('channelUserSubsidyInfo', body, 'jrm'); 166 | $.get(options, async (err, resp, data) => { 167 | try { 168 | if (err) { 169 | console.log(`${JSON.stringify(err)}`); 170 | console.log(`${$.name} API请求失败,请检查网路重试`); 171 | } else { 172 | data = JSON.parse(data); 173 | if (data.resultCode === 0) { 174 | if (data.resultData.code === '000') { 175 | console.log(`\n京东账号${$.index} ${$.nickName || $.UserName} 当前总金贴:${data.resultData.data.availableAmount}元`); 176 | } else { 177 | console.log('获取当前总金贴失败', data); 178 | } 179 | } else { 180 | console.log('获取当前总金贴失败', data); 181 | } 182 | } 183 | } catch (e) { 184 | $.logErr(e, resp); 185 | } finally { 186 | resolve(data); 187 | } 188 | }); 189 | }); 190 | } 191 | 192 | function taskUrl_xh(function_id, body, type = 'mission') { 193 | return { 194 | url: `https://ms.jr.jd.com/gw/generic/${type}/h5/m/${function_id}?reqData=${encodeURIComponent(body)}`, 195 | headers: { 196 | 'Accept': `*/*`, 197 | 'Origin': `https://u.jr.jd.com`, 198 | 'Accept-Encoding': `gzip, deflate, br`, 199 | 'Cookie': cookie, 200 | 'Content-Type': `application/x-www-form-urlencoded;charset=UTF-8`, 201 | 'Host': `ms.jr.jd.com`, 202 | 'Connection': `keep-alive`, 203 | "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"), 204 | 'Referer': `https://u.jr.jd.com`, 205 | 'Accept-Language': `zh-cn` 206 | } 207 | }; 208 | } 209 | 210 | function TotalBean() { 211 | return new Promise(async resolve => { 212 | const options = { 213 | url: "https://me-api.jd.com/user_new/info/GetJDUserInfoUnion", 214 | headers: { 215 | Host: "me-api.jd.com", 216 | Accept: "*/*", 217 | Connection: "keep-alive", 218 | Cookie: cookie, 219 | "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"), 220 | "Accept-Language": "zh-cn", 221 | "Referer": "https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&", 222 | "Accept-Encoding": "gzip, deflate, br" 223 | } 224 | }; 225 | $.get(options, (err, resp, data) => { 226 | try { 227 | if (err) { 228 | $.logErr(err); 229 | } else { 230 | if (data) { 231 | data = JSON.parse(data); 232 | if (data['retcode'] === "1001") { 233 | $.isLogin = false; //cookie过期 234 | return; 235 | } 236 | if (data['retcode'] === "0" && data.data && data.data.hasOwnProperty("userInfo")) { 237 | $.nickName = data.data.userInfo.baseInfo.nickname; 238 | } 239 | } else { 240 | $.log('京东服务器返回空数据'); 241 | } 242 | } 243 | } catch (e) { 244 | $.logErr(e); 245 | } finally { 246 | resolve(); 247 | } 248 | }); 249 | }); 250 | } 251 | 252 | // prettier-ignore 253 | function Env(t, e) { 254 | class s { 255 | constructor(t) { this.env = t; } 256 | 257 | send(t, e = "GET") { 258 | t = "string" == typeof t ? { url: t } : t; 259 | let s = this.get; 260 | return "POST" === e && (s = this.post), new Promise((e, i) => {s.call(this, t, (t, s, r) => {t ? i(t) : e(s);});}); 261 | } 262 | 263 | get(t) {return this.send.call(this.env, t);} 264 | 265 | post(t) {return this.send.call(this.env, t, "POST");} 266 | } 267 | 268 | return new class { 269 | 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}, 开始!`);} 270 | 271 | isNode() {return "undefined" != typeof module && !!module.exports;} 272 | 273 | isQuanX() {return "undefined" != typeof $task;} 274 | 275 | isSurge() {return "undefined" != typeof $httpClient && "undefined" == typeof $loon;} 276 | 277 | isLoon() {return "undefined" != typeof $loon;} 278 | 279 | toObj(t, e = null) {try {return JSON.parse(t);} catch {return e;}} 280 | 281 | toStr(t, e = null) {try {return JSON.stringify(t);} catch {return e;}} 282 | 283 | getjson(t, e) { 284 | let s = e; 285 | const i = this.getdata(t); 286 | if (i) try {s = JSON.parse(this.getdata(t));} catch {} 287 | return s; 288 | } 289 | 290 | setjson(t, e) {try {return this.setdata(JSON.stringify(t), e);} catch {return !1;}} 291 | 292 | getScript(t) {return new Promise(e => {this.get({ url: t }, (t, s, i) => e(i));});} 293 | 294 | runScript(t, e) { 295 | return new Promise(s => { 296 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 297 | i = i ? i.replace(/\n/g, "").trim() : i; 298 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 299 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 300 | const [o, h] = i.split("@"), 301 | n = { 302 | url: `http://${h}/v1/scripting/evaluate`, 303 | body: { script_text: t, mock_type: "cron", timeout: r }, 304 | headers: { "X-Key": o, Accept: "*/*" } 305 | }; 306 | this.post(n, (t, e, i) => s(i)); 307 | }).catch(t => this.logErr(t)); 308 | } 309 | 310 | loaddata() { 311 | if (!this.isNode()) return {}; 312 | { 313 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 314 | const t = this.path.resolve(this.dataFile), 315 | e = this.path.resolve(process.cwd(), this.dataFile), 316 | s = this.fs.existsSync(t), 317 | i = !s && this.fs.existsSync(e); 318 | if (!s && !i) return {}; 319 | { 320 | const i = s ? t : e; 321 | try {return JSON.parse(this.fs.readFileSync(i));} catch (t) {return {};} 322 | } 323 | } 324 | } 325 | 326 | writedata() { 327 | if (this.isNode()) { 328 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 329 | const t = this.path.resolve(this.dataFile), 330 | e = this.path.resolve(process.cwd(), this.dataFile), 331 | s = this.fs.existsSync(t), 332 | i = !s && this.fs.existsSync(e), 333 | r = JSON.stringify(this.data); 334 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r); 335 | } 336 | } 337 | 338 | lodash_get(t, e, s) { 339 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 340 | let r = t; 341 | for (const t of i) if (r = Object(r)[t], void 0 === r) return s; 342 | return r; 343 | } 344 | 345 | 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);} 346 | 347 | getdata(t) { 348 | let e = this.getval(t); 349 | if (/^@/.test(t)) { 350 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), 351 | r = s ? this.getval(s) : ""; 352 | if (r) try { 353 | const t = JSON.parse(r); 354 | e = t ? this.lodash_get(t, i, "") : e; 355 | } catch (t) {e = "";} 356 | } 357 | return e; 358 | } 359 | 360 | setdata(t, e) { 361 | let s = !1; 362 | if (/^@/.test(e)) { 363 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), 364 | o = this.getval(i), 365 | h = i ? "null" === o ? null : o || "{}" : "{}"; 366 | try { 367 | const e = JSON.parse(h); 368 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i); 369 | } catch (e) { 370 | const o = {}; 371 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i); 372 | } 373 | } else s = this.setval(t, e); 374 | return s; 375 | } 376 | 377 | 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;} 378 | 379 | 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;} 380 | 381 | 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));} 382 | 383 | get(t, e = (() => {})) { 384 | 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 => { 385 | const { 386 | statusCode: s, 387 | statusCode: i, 388 | headers: r, 389 | body: o 390 | } = t; 391 | e(null, { status: s, statusCode: i, headers: r, body: o }, o); 392 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 393 | try { 394 | if (t.headers["set-cookie"]) { 395 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 396 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar; 397 | } 398 | } catch (t) {this.logErr(t);} 399 | }).then(t => { 400 | const { statusCode: s, statusCode: i, headers: r, body: o } = t; 401 | e(null, { status: s, statusCode: i, headers: r, body: o }, o); 402 | }, t => { 403 | const { message: s, response: i } = t; 404 | e(s, i, i && i.body); 405 | })); 406 | } 407 | 408 | post(t, e = (() => {})) { 409 | 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 => { 410 | const { 411 | statusCode: s, 412 | statusCode: i, 413 | headers: r, 414 | body: o 415 | } = t; 416 | e(null, { status: s, statusCode: i, headers: r, body: o }, o); 417 | }, t => e(t)); else if (this.isNode()) { 418 | this.initGotEnv(t); 419 | const { url: s, ...i } = t; 420 | this.got.post(s, i).then(t => { 421 | const { statusCode: s, statusCode: i, headers: r, body: o } = t; 422 | e(null, { status: s, statusCode: i, headers: r, body: o }, o); 423 | }, t => { 424 | const { message: s, response: i } = t; 425 | e(s, i, i && i.body); 426 | }); 427 | } 428 | } 429 | 430 | time(t, e = null) { 431 | const s = e ? new Date(e) : new Date; 432 | let i = { 433 | "M+": s.getMonth() + 1, 434 | "d+": s.getDate(), 435 | "H+": s.getHours(), 436 | "m+": s.getMinutes(), 437 | "s+": s.getSeconds(), 438 | "q+": Math.floor((s.getMonth() + 3) / 3), 439 | S: s.getMilliseconds() 440 | }; 441 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 442 | 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))); 443 | return t; 444 | } 445 | 446 | msg(e = t, s = "", i = "", r) { 447 | const o = t => { 448 | if (!t) return t; 449 | if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; 450 | if ("object" == typeof t) { 451 | if (this.isLoon()) { 452 | let e = t.openUrl || t.url || t["open-url"], 453 | s = t.mediaUrl || t["media-url"]; 454 | return { openUrl: e, mediaUrl: s }; 455 | } 456 | if (this.isQuanX()) { 457 | let e = t["open-url"] || t.url || t.openUrl, 458 | s = t["media-url"] || t.mediaUrl; 459 | return { "open-url": e, "media-url": s }; 460 | } 461 | if (this.isSurge()) { 462 | let e = t.url || t.openUrl || t["open-url"]; 463 | return { url: e }; 464 | } 465 | } 466 | }; 467 | if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { 468 | let t = ["", "==============📣系统通知📣=============="]; 469 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t); 470 | } 471 | } 472 | 473 | log(...t) {t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator));} 474 | 475 | logErr(t, e) { 476 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 477 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t); 478 | } 479 | 480 | wait(t) {return new Promise(e => setTimeout(e, t));} 481 | 482 | done(t = {}) { 483 | const e = (new Date).getTime(), 484 | s = (e - this.startTime) / 1e3; 485 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t); 486 | } 487 | }(t, e); 488 | } 489 | -------------------------------------------------------------------------------- /jd_ljd_xh.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 领京豆,修复死循环 3 | * By X1a0He 4 | * https://github.com/X1a0He/jd_scripts_fixed 5 | * */ 6 | const $ = new Env("领京豆"); 7 | const jdCookieNode = $.isNode() ? require("./jdCookie.js") : ""; 8 | const notify = $.isNode() ? require('./sendNotify') : ''; 9 | let cookiesArr = [], cookie = "", message = ``; 10 | $.taskInfos = []; 11 | $.viewAppHome = false; 12 | $.isLogin = true; 13 | $.addedGrowth = 0; 14 | if($.isNode()){ 15 | Object.keys(jdCookieNode).forEach((item) => {cookiesArr.push(jdCookieNode[item]);}); 16 | if(process.env.JD_DEBUG && process.env.JD_DEBUG === "false") console.log = () => {}; 17 | } else cookiesArr = [$.getdata("CookieJD"), $.getdata("CookieJD2"), ...$.toObj($.getdata("CookiesJD") || "[]").map((item) => item.cookie),].filter((item) => !!item); 18 | !(async() => { 19 | if(!cookiesArr[0]){ 20 | $.msg($.name, "【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取", "https://bean.m.jd.com/", { "open-url": "https://bean.m.jd.com/" }); 21 | return; 22 | } 23 | for(let i = 0; i < cookiesArr.length; i++){ 24 | if(cookiesArr[i]){ 25 | cookie = cookiesArr[i]; 26 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 27 | $.index = i + 1; 28 | message += `[京东账号${$.index} ${$.UserName}] \n`; 29 | console.log(`[京东账号${$.index} ${$.UserName}] 正在执行...`); 30 | await main(); 31 | message += `\n` 32 | await $.wait(1000); 33 | } 34 | } 35 | if($.isNode()){ 36 | console.log('正在发送通知...') 37 | await notify.sendNotify(`${$.name}`, `${message}`) 38 | } 39 | })().catch((e) => { 40 | $.log("", `❌ ${$.name}, 失败! 原因: ${e}!`, ""); 41 | }).finally(() => { 42 | $.done(); 43 | }); 44 | 45 | function taskUrl_xh(functionId, body){ 46 | return { 47 | "url": `https://api.m.jd.com/client.action?functionId=${functionId}&body=${encodeURIComponent(body)}&appid=ld&client=m&clientVersion=9.4.4`, 48 | 'headers': { 49 | 'Cookie': cookie, 50 | 'UserAgent': 'User-Agent: jdapp;JD4iPhone/167724 (iPhone; iOS 15.0; Scale/3.00)', 51 | }, 52 | } 53 | } 54 | 55 | async function main(){ 56 | $.addedGrowth = 0; 57 | $.isLogin = true; 58 | // 先领取早起福利 59 | console.log(`尝试领取早起福利...`) 60 | await taskRequest("morningGetBean", `{"fp":"-1","shshshfp":"-1","shshshfpa":"-1","referUrl":"-1","userAgent":"-1","jda":"-1","rnVersion":"3.9"}`) 61 | // 获取任务列表 62 | if($.isLogin){ 63 | do { 64 | $.taskInfos = [] 65 | await taskRequest("beanTaskList", `{"viewChannel":"AppHome"}`) 66 | // 获取完任务列表就开始做任务了 67 | for(let task of $.taskInfos){ 68 | // 任务未完成 69 | if(task.status === 1){ 70 | for(let subTask of task.subTaskVOS){ 71 | if(subTask.status === 1){ 72 | console.log(`[${task.taskName}] 正在做任务...`) 73 | if(task.waitDuration !== 0){ 74 | await taskRequest("beanDoTask", `{"actionType":1,"taskToken":"${subTask.taskToken}"}`) 75 | console.log(`[${task.taskName}] 等待 ${task.waitDuration} 秒`) 76 | await $.wait(task.waitDuration * 1000) 77 | await taskRequest("beanDoTask", `{"actionType":0,"taskToken":"${subTask.taskToken}"}`) 78 | } else await taskRequest("beanDoTask", `{"actionType":0,"taskToken":"${subTask.taskToken}"}`) 79 | } 80 | await $.wait(3000) 81 | } 82 | } 83 | } 84 | } while($.taskInfos.length !== 0); 85 | // 从京东首页领京豆进入 86 | if(!$.viewAppHome){ 87 | console.log(`[从京东首页领京豆进入] 正在做任务...`) 88 | await taskRequest("beanHomeIconDoTask", `{"flag":"0","viewChannel":"AppHome"}`) 89 | if(!$.viewAppHome){ 90 | await $.wait(2000) 91 | await taskRequest("beanHomeIconDoTask", `{"flag":"1","viewChannel":"AppHome"}`) 92 | } 93 | } 94 | message += `[本次执行] 获得成长值:${$.addedGrowth}\n` 95 | } 96 | } 97 | 98 | function taskRequest(functionId, body){ 99 | return new Promise((resolve) => { 100 | let options = taskUrl_xh(functionId, body); 101 | $.get(options, (err, resp, data) => { 102 | try{ 103 | if(safeGet(data)){ 104 | data = JSON.parse(data); 105 | if(data.code === "3"){ 106 | console.log(`用户未登录`) 107 | message += `用户未登录` 108 | $.isLogin = false; 109 | return; 110 | } 111 | if(data.code === "0"){ 112 | switch(functionId){ 113 | case "morningGetBean": 114 | if(data.data.awardResultFlag === "1"){ 115 | console.log(`${data.data.bizMsg}, 获得京豆 ${data.data.beanNum} 个\n`) 116 | message += `[早起福利] 获得京豆 ${data.data.beanNum} 个\n` 117 | } else { 118 | console.log(`执行失败,原因:${data.data.bizMsg}\n`) 119 | message += `[早起福利] ${data.data.bizMsg} \n` 120 | } 121 | break; 122 | case "beanTaskList" : 123 | for(let task of data.data.taskInfos) task.status === 1 ? $.taskInfos.push(task) : '' 124 | $.viewAppHome = data.data.viewAppHome.doneTask 125 | break; 126 | case "beanDoTask" : 127 | if(typeof data.errorCode === "undefined"){ 128 | if(data.data.taskStatus === 1 || data.data.taskStatus === 2){ 129 | console.log(`${data.data.bizMsg}\n`) 130 | $.addedGrowth += data.data.growthResult.addedGrowth 131 | } 132 | } else console.log(`${data.data.errorMessage}\n`) 133 | break; 134 | case "beanHomeIconDoTask": 135 | if(typeof data.errorCode === "undefined"){ 136 | $.addedGrowth += 50; 137 | console.log(`${data.data.remindMsg}\n`) 138 | } else console.log(`${data.errorMessage}`) 139 | } 140 | } 141 | } 142 | } catch(e){ 143 | console.log(e); 144 | } finally{ 145 | resolve(); 146 | } 147 | }); 148 | }); 149 | } 150 | 151 | function safeGet(data){ 152 | try{ 153 | if(typeof JSON.parse(data) == "object"){ 154 | return true; 155 | } 156 | } catch(e){ 157 | console.log(e); 158 | console.log(`京东服务器访问数据为空,请检查自身设备网络情况`); 159 | return false; 160 | } 161 | } 162 | 163 | // prettier-ignore 164 | function Env(t, e){ 165 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 166 | 167 | class s{ 168 | constructor(t){this.env = t} 169 | 170 | send(t, e = "GET"){ 171 | t = "string" == typeof t ? { url: t } : t; 172 | let s = this.get; 173 | return "POST" === e && (s = this.post), new Promise((e, i) => {s.call(this, t, (t, s, r) => {t ? i(t) : e(s)})}) 174 | } 175 | 176 | get(t){return this.send.call(this.env, t)} 177 | 178 | post(t){return this.send.call(this.env, t, "POST")} 179 | } 180 | 181 | return new class{ 182 | 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}, 开始!`)} 183 | 184 | isNode(){return "undefined" != typeof module && !!module.exports} 185 | 186 | isQuanX(){return "undefined" != typeof $task} 187 | 188 | isSurge(){return "undefined" != typeof $httpClient && "undefined" == typeof $loon} 189 | 190 | isLoon(){return "undefined" != typeof $loon} 191 | 192 | toObj(t, e = null){try{return JSON.parse(t)} catch{return e}} 193 | 194 | toStr(t, e = null){try{return JSON.stringify(t)} catch{return e}} 195 | 196 | getjson(t, e){ 197 | let s = e; 198 | const i = this.getdata(t); 199 | if(i) try{s = JSON.parse(this.getdata(t))} catch{} 200 | return s 201 | } 202 | 203 | setjson(t, e){try{return this.setdata(JSON.stringify(t), e)} catch{return !1}} 204 | 205 | getScript(t){return new Promise(e => {this.get({ url: t }, (t, s, i) => e(i))})} 206 | 207 | runScript(t, e){ 208 | return new Promise(s => { 209 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 210 | i = i ? i.replace(/\n/g, "").trim() : i; 211 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 212 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 213 | const [o, h] = i.split("@"), n = { 214 | url: `http://${h}/v1/scripting/evaluate`, 215 | body: { script_text: t, mock_type: "cron", timeout: r }, 216 | headers: { "X-Key": o, Accept: "*/*" } 217 | }; 218 | this.post(n, (t, e, i) => s(i)) 219 | }).catch(t => this.logErr(t)) 220 | } 221 | 222 | loaddata(){ 223 | if(!this.isNode()) return {}; 224 | { 225 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 226 | const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), 227 | s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); 228 | if(!s && !i) return {}; 229 | { 230 | const i = s ? t : e; 231 | try{return JSON.parse(this.fs.readFileSync(i))} catch(t){return {}} 232 | } 233 | } 234 | } 235 | 236 | writedata(){ 237 | if(this.isNode()){ 238 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 239 | const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), 240 | s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); 241 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 242 | } 243 | } 244 | 245 | lodash_get(t, e, s){ 246 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 247 | let r = t; 248 | for(const t of i) if(r = Object(r)[t], void 0 === r) return s; 249 | return r 250 | } 251 | 252 | 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)} 253 | 254 | getdata(t){ 255 | let e = this.getval(t); 256 | if(/^@/.test(t)){ 257 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; 258 | if(r) try{ 259 | const t = JSON.parse(r); 260 | e = t ? this.lodash_get(t, i, "") : e 261 | } catch(t){e = ""} 262 | } 263 | return e 264 | } 265 | 266 | setdata(t, e){ 267 | let s = !1; 268 | if(/^@/.test(e)){ 269 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), 270 | h = i ? "null" === o ? null : o || "{}" : "{}"; 271 | try{ 272 | const e = JSON.parse(h); 273 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) 274 | } catch(e){ 275 | const o = {}; 276 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) 277 | } 278 | } else s = this.setval(t, e); 279 | return s 280 | } 281 | 282 | 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} 283 | 284 | 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} 285 | 286 | 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))} 287 | 288 | get(t, e = (() => {})){ 289 | 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 => { 290 | const { 291 | statusCode: s, 292 | statusCode: i, 293 | headers: r, 294 | body: o 295 | } = t; 296 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 297 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 298 | try{ 299 | if(t.headers["set-cookie"]){ 300 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 301 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar 302 | } 303 | } catch(t){this.logErr(t)} 304 | }).then(t => { 305 | const { statusCode: s, statusCode: i, headers: r, body: o } = t; 306 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 307 | }, t => { 308 | const { message: s, response: i } = t; 309 | e(s, i, i && i.body) 310 | })) 311 | } 312 | 313 | post(t, e = (() => {})){ 314 | 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 => { 315 | const { 316 | statusCode: s, 317 | statusCode: i, 318 | headers: r, 319 | body: o 320 | } = t; 321 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 322 | }, t => e(t)); else if(this.isNode()){ 323 | this.initGotEnv(t); 324 | const { url: s, ...i } = t; 325 | this.got.post(s, i).then(t => { 326 | const { statusCode: s, statusCode: i, headers: r, body: o } = t; 327 | e(null, { status: s, statusCode: i, headers: r, body: o }, o) 328 | }, t => { 329 | const { message: s, response: i } = t; 330 | e(s, i, i && i.body) 331 | }) 332 | } 333 | } 334 | 335 | time(t, e = null){ 336 | const s = e ? new Date(e) : new Date; 337 | let i = { 338 | "M+": s.getMonth() + 1, 339 | "d+": s.getDate(), 340 | "H+": s.getHours(), 341 | "m+": s.getMinutes(), 342 | "s+": s.getSeconds(), 343 | "q+": Math.floor((s.getMonth() + 3) / 3), 344 | S: s.getMilliseconds() 345 | }; 346 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 347 | 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))); 348 | return t 349 | } 350 | 351 | msg(e = t, s = "", i = "", r){ 352 | const o = t => { 353 | if(!t) return t; 354 | if("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; 355 | if("object" == typeof t){ 356 | if(this.isLoon()){ 357 | let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; 358 | return { openUrl: e, mediaUrl: s } 359 | } 360 | if(this.isQuanX()){ 361 | let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; 362 | return { "open-url": e, "media-url": s } 363 | } 364 | if(this.isSurge()){ 365 | let e = t.url || t.openUrl || t["open-url"]; 366 | return { url: e } 367 | } 368 | } 369 | }; 370 | if(this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog){ 371 | let t = ["", "==============📣系统通知📣=============="]; 372 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) 373 | } 374 | } 375 | 376 | log(...t){t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator))} 377 | 378 | logErr(t, e){ 379 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 380 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 381 | } 382 | 383 | wait(t){return new Promise(e => setTimeout(e, t))} 384 | 385 | done(t = {}){ 386 | const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; 387 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 388 | } 389 | }(t, e) 390 | } 391 | -------------------------------------------------------------------------------- /jd_try_xh.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 如需运行请自行添加环境变量:JD_TRY,值填 true 即可运行 3 | * 脚本兼容: Node.js 4 | * X1a0He留 5 | * 脚本是否耗时只看args_xh.maxLength的大小 6 | * 上一作者说了每天最多300个商店,总上限为500个,jd_unsubscribe.js我已更新为批量取关版 7 | * 请提前取关至少250个商店确保京东试用脚本正常运行 8 | * 9 | * @Address: https://github.com/X1a0He/jd_scripts_fixed/blob/main/jd_try_xh.js 10 | * @LastEditors: X1a0He 11 | */ 12 | const $ = new Env('京东试用') 13 | const URL = 'https://api.m.jd.com/client.action' 14 | let trialActivityIdList = [] 15 | let trialActivityTitleList = [] 16 | let notifyMsg = '' 17 | let size = 1; 18 | $.isPush = true; 19 | $.isLimit = false; 20 | $.isForbidden = false; 21 | $.wrong = false; 22 | $.giveupNum = 0; 23 | $.successNum = 0; 24 | $.completeNum = 0; 25 | $.getNum = 0; 26 | $.try = true; 27 | $.sentNum = 0; 28 | $.cookiesArr = [] 29 | $.innerKeyWords = 30 | [ 31 | "幼儿园", "教程", "英语", "辅导", "培训", 32 | "孩子", "小学", "成人用品", "套套", "情趣", 33 | "自慰", "阳具", "飞机杯", "男士用品", "女士用品", 34 | "内衣", "高潮", "避孕", "乳腺", "肛塞", "肛门", 35 | "宝宝", "玩具", "芭比", "娃娃", "男用", 36 | "女用", "神油", "足力健", "老年", "老人", 37 | "宠物", "饲料", "丝袜", "黑丝", "磨脚", 38 | "脚皮", "除臭", "性感", "内裤", "跳蛋", 39 | "安全套", "龟头", "阴道", "阴部" 40 | ] 41 | //下面很重要,遇到问题请把下面注释看一遍再来问 42 | let args_xh = { 43 | /* 44 | * 控制是否输出当前环境变量设置,默认为false 45 | * 环境变量名称:XH_TRY_ENV 46 | */ 47 | env: process.env.XH_TRY_ENV === 'true' || false, 48 | /* 49 | * 跳过某个指定账号,默认为全部账号清空 50 | * 填写规则:例如当前Cookie1为pt_key=key; pt_pin=pin1;则环境变量填写pin1即可,此时pin1的购物车将不会被清空 51 | * 若有更多,则按照pin1@pin2@pin3进行填写 52 | * 环境变量名称:XH_TRY_EXCEPT 53 | */ 54 | except: process.env.XH_TRY_EXCEPT && process.env.XH_TRY_EXCEPT.split('@') || [], 55 | //以上环境变量新增于2022.01.30 56 | /* 57 | * 每个Tab页要便遍历的申请页数,由于京东试用又改了,获取不到每一个Tab页的总页数了(显示null),所以特定增加一个环境变了以控制申请页数 58 | * 例如设置 JD_TRY_PRICE 为 30,假如现在正在遍历tab1,那tab1就会被遍历到30页,到31页就会跳到tab2,或下一个预设的tab页继续遍历到30页 59 | * 默认为20 60 | */ 61 | totalPages: process.env.JD_TRY_TOTALPAGES * 1 || 20, 62 | /* 63 | * 由于每个账号每次获取的试用产品都不一样,所以为了保证每个账号都能试用到不同的商品,之前的脚本都不支持采用统一试用组的 64 | * 以下环境变量是用于指定是否采用统一试用组的 65 | * 例如当 JD_TRY_UNIFIED 为 true时,有3个账号,第一个账号跑脚本的时候,试用组是空的 66 | * 而当第一个账号跑完试用组后,第二个,第三个账号所采用的试用组默认采用的第一个账号的试用组 67 | * 优点:减少除第一个账号外的所有账号遍历,以减少每个账号的遍历时间 68 | * 缺点:A账号能申请的东西,B账号不一定有 69 | * 提示:想每个账号独立不同的试用产品的,请设置为false,想减少脚本运行时间的,请设置为true 70 | * 默认为false 71 | */ 72 | unified: process.env.JD_TRY_UNIFIED === 'true' || false, 73 | //以上环境变量新增于2022.01.25 74 | /* 75 | * 商品原价,低于这个价格都不会试用,意思是 76 | * A商品原价49元,试用价1元,如果下面设置为50,那么A商品不会被加入到待提交的试用组 77 | * B商品原价99元,试用价0元,如果下面设置为50,那么B商品将会被加入到待提交的试用组 78 | * C商品原价99元,试用价1元,如果下面设置为50,那么C商品将会被加入到待提交的试用组 79 | * 默认为0 80 | * */ 81 | jdPrice: process.env.JD_TRY_PRICE * 1 || 0, 82 | /* 83 | * 获取试用商品类型,默认为1 84 | * 下面有一个function是可以获取所有tabId的,名为try_tabList 85 | * 可设置环境变量:JD_TRY_TABID,用@进行分隔 86 | * 默认为 1 到 10 87 | * */ 88 | tabId: process.env.JD_TRY_TABID && process.env.JD_TRY_TABID.split('@').map(Number) || [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 89 | /* 90 | * 试用商品标题过滤,黑名单,当标题存在关键词时,则不加入试用组 91 | * 当白名单和黑名单共存时,黑名单会自动失效,优先匹配白名单,匹配完白名单后不会再匹配黑名单,望周知 92 | * 例如A商品的名称为『旺仔牛奶48瓶特价』,设置了匹配白名单,白名单关键词为『牛奶』,但黑名单关键词存在『旺仔』 93 | * 这时,A商品还是会被添加到待提交试用组,白名单优先于黑名单 94 | * 已内置对应的 成人类 幼儿类 宠物 老年人类关键词,请勿重复添加 95 | * 可设置环境变量:JD_TRY_TITLEFILTERS,关键词与关键词之间用@分隔 96 | * */ 97 | titleFilters: process.env.JD_TRY_TITLEFILTERS && process.env.JD_TRY_TITLEFILTERS.split('@') || [], 98 | /* 99 | * 试用价格(中了要花多少钱),高于这个价格都不会试用,小于等于才会试用,意思就是 100 | * A商品原价49元,现在试用价1元,如果下面设置为10,那A商品将会被添加到待提交试用组,因为1 < 10 101 | * B商品原价49元,现在试用价2元,如果下面设置为1,那B商品将不会被添加到待提交试用组,因为2 > 1 102 | * C商品原价49元,现在试用价1元,如果下面设置为1,那C商品也会被添加到带提交试用组,因为1 = 1 103 | * 可设置环境变量:JD_TRY_TRIALPRICE,默认为0 104 | * */ 105 | trialPrice: process.env.JD_TRY_TRIALPRICE * 1 || 0, 106 | /* 107 | * 最小提供数量,例如试用商品只提供2份试用资格,当前设置为1,则会进行申请 108 | * 若只提供5分试用资格,当前设置为10,则不会申请 109 | * 可设置环境变量:JD_TRY_MINSUPPLYNUM 110 | * */ 111 | minSupplyNum: process.env.JD_TRY_MINSUPPLYNUM * 1 || 1, 112 | /* 113 | * 过滤大于设定值的已申请人数,例如下面设置的1000,A商品已经有1001人申请了,则A商品不会进行申请,会被跳过 114 | * 可设置环境变量:JD_TRY_APPLYNUMFILTER 115 | * */ 116 | applyNumFilter: process.env.JD_TRY_APPLYNUMFILTER * 1 || 10000, 117 | /* 118 | * 商品试用之间和获取商品之间的间隔, 单位:毫秒(1秒=1000毫秒) 119 | * 可设置环境变量:JD_TRY_APPLYINTERVAL 120 | * 默认为3000,也就是3秒 121 | * */ 122 | applyInterval: process.env.JD_TRY_APPLYINTERVAL * 1 || 5000, 123 | /* 124 | * 商品数组的最大长度,通俗来说就是即将申请的商品队列长度 125 | * 例如设置为20,当第一次获取后获得12件,过滤后剩下5件,将会进行第二次获取,过滤后加上第一次剩余件数 126 | * 例如是18件,将会进行第三次获取,直到过滤完毕后为20件才会停止,不建议设置太大 127 | * 可设置环境变量:JD_TRY_MAXLENGTH 128 | * */ 129 | maxLength: process.env.JD_TRY_MAXLENGTH * 1 || 100, 130 | /* 131 | * 过滤种草官类试用,某些试用商品是专属官专属,考虑到部分账号不是种草官账号 132 | * 例如A商品是种草官专属试用商品,下面设置为true,而你又不是种草官账号,那A商品将不会被添加到待提交试用组 133 | * 例如B商品是种草官专属试用商品,下面设置为false,而你是种草官账号,那A商品将会被添加到待提交试用组 134 | * 例如B商品是种草官专属试用商品,下面设置为true,即使你是种草官账号,A商品也不会被添加到待提交试用组 135 | * 可设置环境变量:JD_TRY_PASSZC,默认为true 136 | * */ 137 | passZhongCao: process.env.JD_TRY_PASSZC === 'true' || true, 138 | /* 139 | * 是否打印输出到日志,考虑到如果试用组长度过大,例如100以上,如果每个商品检测都打印一遍,日志长度会非常长 140 | * 打印的优点:清晰知道每个商品为什么会被过滤,哪个商品被添加到了待提交试用组 141 | * 打印的缺点:会使日志变得很长 142 | * 143 | * 不打印的优点:简短日志长度 144 | * 不打印的缺点:无法清晰知道每个商品为什么会被过滤,哪个商品被添加到了待提交试用组 145 | * 可设置环境变量:JD_TRY_PLOG,默认为true 146 | * */ 147 | printLog: process.env.JD_TRY_PLOG === 'true' || true, 148 | /* 149 | * 白名单,是否打开,如果下面为true,那么黑名单会自动失效 150 | * 白名单和黑名单无法共存,白名单永远优先于黑名单 151 | * 可通过环境变量控制:JD_TRY_WHITELIST,默认为false 152 | * */ 153 | whiteList: process.env.JD_TRY_WHITELIST === 'true' || false, 154 | /* 155 | * 白名单关键词,当标题存在关键词时,加入到试用组 156 | * 例如A商品的名字为『旺仔牛奶48瓶特价』,白名单其中一个关键词是『牛奶』,那么A将会直接被添加到待提交试用组,不再进行另外判断 157 | * 就算设置了黑名单也不会判断,希望这种写得那么清楚的脑瘫问题就别提issues了 158 | * 可通过环境变量控制:JD_TRY_WHITELIST,用@分隔 159 | * */ 160 | whiteListKeywords: process.env.JD_TRY_WHITELISTKEYWORDS && process.env.JD_TRY_WHITELISTKEYWORDS.split('@') || [], 161 | /* 162 | * 每多少个账号发送一次通知,默认为4 163 | * 可通过环境变量控制 JD_TRY_SENDNUM 164 | * */ 165 | sendNum: process.env.JD_TRY_SENDNUM * 1 || 4, 166 | } 167 | //上面很重要,遇到问题请把上面注释看一遍再来问 168 | !(async() => { 169 | console.log('X1a0He留:遇到问题请把脚本内的注释看一遍再来问,谢谢') 170 | console.log('X1a0He留:遇到问题请把脚本内的注释看一遍再来问,谢谢') 171 | console.log('X1a0He留:遇到问题请把脚本内的注释看一遍再来问,谢谢') 172 | await $.wait(500) 173 | // 如果你要运行京东试用这个脚本,麻烦你把环境变量 JD_TRY 设置为 true 174 | if(process.env.JD_TRY && process.env.JD_TRY === 'true'){ 175 | await requireConfig() 176 | if(!$.cookiesArr[0]){ 177 | $.msg($.name, '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/', { 178 | "open-url": "https://bean.m.jd.com/" 179 | }) 180 | return 181 | } 182 | for(let i = 0; i < $.cookiesArr.length; i++){ 183 | if($.cookiesArr[i]){ 184 | $.cookie = $.cookiesArr[i]; 185 | $.UserName = decodeURIComponent($.cookie.match(/pt_pin=(.+?);/) && $.cookie.match(/pt_pin=(.+?);/)[1]) 186 | $.index = i + 1; 187 | $.isLogin = true; 188 | $.nickName = ''; 189 | await totalBean(); 190 | console.log(`\n开始【京东账号${$.index}】${$.nickName || $.UserName}\n`); 191 | $.except = false; 192 | if(args_xh.except.includes($.UserName)){ 193 | console.log(`跳过账号:${$.nickName || $.UserName}`) 194 | $.except = true; 195 | continue 196 | } 197 | if(!$.isLogin){ 198 | $.msg($.name, `【提示】cookie已失效`, `京东账号${$.index} ${$.nickName || $.UserName}\n请重新登录获取\nhttps://bean.m.jd.com/bean/signIndex.action`, { 199 | "open-url": "https://bean.m.jd.com/bean/signIndex.action" 200 | }); 201 | await $.notify.sendNotify(`${$.name}cookie已失效 - ${$.UserName}`, `京东账号${$.index} ${$.UserName}\n请重新登录获取cookie`); 202 | continue 203 | } 204 | $.totalTry = 0 205 | $.totalSuccess = 0 206 | $.nowTabIdIndex = 0; 207 | $.nowPage = 1; 208 | $.nowItem = 1; 209 | if(!args_xh.unified){ 210 | trialActivityIdList = [] 211 | trialActivityTitleList = [] 212 | } 213 | $.isLimit = false; 214 | // 获取tabList的,不知道有哪些的把这里的注释解开跑一遍就行了 215 | // await try_tabList(); 216 | // return; 217 | $.isForbidden = false 218 | $.wrong = false 219 | size = 1 220 | while(trialActivityIdList.length < args_xh.maxLength && $.isForbidden === false){ 221 | if(args_xh.unified && trialActivityIdList.length !== 0) break; 222 | if($.nowTabIdIndex === args_xh.tabId.length){ 223 | console.log(`tabId组已遍历完毕,不在获取商品\n`); 224 | break; 225 | } else { 226 | await try_feedsList(args_xh.tabId[$.nowTabIdIndex], $.nowPage) //获取对应tabId的试用页面 227 | } 228 | if(trialActivityIdList.length < args_xh.maxLength){ 229 | console.log(`间隔等待中,请等待 3 秒\n`) 230 | await $.wait(3000); 231 | } 232 | } 233 | if($.isForbidden === false && $.isLimit === false){ 234 | console.log(`稍后将执行试用申请,请等待 2 秒\n`) 235 | await $.wait(2000); 236 | for(let i = 0; i < trialActivityIdList.length && $.isLimit === false; i++){ 237 | if($.isLimit){ 238 | console.log("试用上限") 239 | break 240 | } 241 | await try_apply(trialActivityTitleList[i], trialActivityIdList[i]) 242 | console.log(`间隔等待中,请等待 ${args_xh.applyInterval} ms\n`) 243 | await $.wait(args_xh.applyInterval); 244 | } 245 | console.log("试用申请执行完毕...") 246 | // await try_MyTrials(1, 1) //申请中的商品 247 | $.giveupNum = 0; 248 | $.successNum = 0; 249 | $.getNum = 0; 250 | $.completeNum = 0; 251 | await try_MyTrials(1, 2) //申请成功的商品 252 | // await try_MyTrials(1, 3) //申请失败的商品 253 | await showMsg() 254 | } 255 | } 256 | if($.isNode()){ 257 | if($.index % args_xh.sendNum === 0){ 258 | $.sentNum++; 259 | console.log(`正在进行第 ${$.sentNum} 次发送通知,发送数量:${args_xh.sendNum}`) 260 | await $.notify.sendNotify(`${$.name}`, `${notifyMsg}`) 261 | notifyMsg = ""; 262 | } 263 | } 264 | } 265 | if($.isNode() && $.except === false){ 266 | if(($.cookiesArr.length - ($.sentNum * args_xh.sendNum)) < args_xh.sendNum){ 267 | console.log(`正在进行最后一次发送通知,发送数量:${($.cookiesArr.length - ($.sentNum * args_xh.sendNum))}`) 268 | await $.notify.sendNotify(`${$.name}`, `${notifyMsg}`) 269 | notifyMsg = ""; 270 | } 271 | } 272 | } else { 273 | console.log(`\n您未设置运行【京东试用】脚本,结束运行!\n`) 274 | } 275 | })().catch((e) => { 276 | console.error(`❗️ ${$.name} 运行错误!\n${e}`) 277 | }).finally(() => $.done()) 278 | 279 | function requireConfig(){ 280 | return new Promise(resolve => { 281 | console.log('开始获取配置文件\n') 282 | $.notify = $.isNode() ? require('./sendNotify') : { sendNotify: async() => { } } 283 | //获取 Cookies 284 | $.cookiesArr = [] 285 | if($.isNode()){ 286 | //Node.js用户请在jdCookie.js处填写京东ck; 287 | const jdCookieNode = require('./jdCookie.js'); 288 | Object.keys(jdCookieNode).forEach((item) => { 289 | if(jdCookieNode[item]) $.cookiesArr.push(jdCookieNode[item]) 290 | }) 291 | if(process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => { }; 292 | } else { 293 | //IOS等用户直接用NobyDa的jd $.cookie 294 | $.cookiesArr = [$.getdata('CookieJD'), $.getdata('CookieJD2'), ...jsonParse($.getdata('CookiesJD') || "[]").map(item => item.cookie)].filter(item => !!item); 295 | } 296 | for(let keyWord of $.innerKeyWords) args_xh.titleFilters.push(keyWord) 297 | console.log(`共${$.cookiesArr.length}个京东账号\n`) 298 | if(args_xh.env){ 299 | console.log('=====环境变量配置如下=====') 300 | console.log(`env: ${typeof args_xh.env}, ${args_xh.env}`) 301 | console.log(`except: ${typeof args_xh.except}, ${args_xh.except}`) 302 | console.log(`totalPages: ${typeof args_xh.totalPages}, ${args_xh.totalPages}`) 303 | console.log(`unified: ${typeof args_xh.unified}, ${args_xh.unified}`) 304 | console.log(`jdPrice: ${typeof args_xh.jdPrice}, ${args_xh.jdPrice}`) 305 | console.log(`tabId: ${typeof args_xh.tabId}, ${args_xh.tabId}`) 306 | console.log(`titleFilters: ${typeof args_xh.titleFilters}, ${args_xh.titleFilters}`) 307 | console.log(`trialPrice: ${typeof args_xh.trialPrice}, ${args_xh.trialPrice}`) 308 | console.log(`minSupplyNum: ${typeof args_xh.minSupplyNum}, ${args_xh.minSupplyNum}`) 309 | console.log(`applyNumFilter: ${typeof args_xh.applyNumFilter}, ${args_xh.applyNumFilter}`) 310 | console.log(`applyInterval: ${typeof args_xh.applyInterval}, ${args_xh.applyInterval}`) 311 | console.log(`maxLength: ${typeof args_xh.maxLength}, ${args_xh.maxLength}`) 312 | console.log(`passZhongCao: ${typeof args_xh.passZhongCao}, ${args_xh.passZhongCao}`) 313 | console.log(`printLog: ${typeof args_xh.printLog}, ${args_xh.printLog}`) 314 | console.log(`whiteList: ${typeof args_xh.whiteList}, ${args_xh.whiteList}`) 315 | console.log(`whiteListKeywords: ${typeof args_xh.whiteListKeywords}, ${args_xh.whiteListKeywords}`) 316 | console.log('=======================') 317 | } 318 | resolve() 319 | }) 320 | } 321 | 322 | //获取tabList的,如果不知道tabList有哪些,跑一遍这个function就行了 323 | function try_tabList(){ 324 | return new Promise((resolve, reject) => { 325 | console.log(`获取tabList中...`) 326 | const body = JSON.stringify({ 327 | "version": 2, 328 | "previewTime": "" 329 | }); 330 | let option = taskurl_xh('newtry', 'try_tabList', body) 331 | $.get(option, (err, resp, data) => { 332 | try{ 333 | if(err){ 334 | if(JSON.stringify(err) === `\"Response code 403 (Forbidden)\"`){ 335 | $.isForbidden = true 336 | console.log('账号被京东服务器风控,不再请求该帐号') 337 | } else { 338 | console.log(JSON.stringify(err)) 339 | console.log(`${$.name} API请求失败,请检查网路重试`) 340 | } 341 | } else { 342 | data = JSON.parse(data) 343 | if(data.success){ 344 | for(let tabId of data.data.tabList) console.log(`${tabId.tabName} - ${tabId.tabId}`) 345 | } else { 346 | console.log("获取失败", data) 347 | } 348 | } 349 | } catch(e){ 350 | reject(`⚠️ ${arguments.callee.name.toString()} API返回结果解析出错\n${e}\n${JSON.stringify(data)}`) 351 | } finally{ 352 | resolve() 353 | } 354 | }) 355 | }) 356 | } 357 | 358 | //获取商品列表并且过滤 By X1a0He 359 | function try_feedsList(tabId, page){ 360 | return new Promise((resolve, reject) => { 361 | const body = JSON.stringify({ 362 | "tabId": `${tabId}`, 363 | "page": page, 364 | "version": 2, 365 | "source": "default", 366 | "client": "app", 367 | "previewTime": "" 368 | }); 369 | let option = taskurl_xh('newtry', 'try_feedsList', body) 370 | $.get(option, (err, resp, data) => { 371 | try{ 372 | if(err){ 373 | if(JSON.stringify(err) === `\"Response code 403 (Forbidden)\"`){ 374 | $.isForbidden = true 375 | console.log('账号被京东服务器风控,不再请求该帐号') 376 | } else { 377 | console.log(JSON.stringify(err)) 378 | console.log(`${$.name} API请求失败,请检查网路重试`) 379 | } 380 | } else { 381 | data = JSON.parse(data) 382 | let tempKeyword = ``; 383 | if(data.success){ 384 | $.nowPage === args_xh.totalPages ? $.nowPage = 1 : $.nowPage++; 385 | console.log(`第 ${size++} 次获取试用商品成功,tabId:${args_xh.tabId[$.nowTabIdIndex]} 的 第 ${page}/${args_xh.totalPages} 页`) 386 | console.log(`获取到商品 ${data.data.feedList.length} 条`) 387 | for(let item of data.data.feedList){ 388 | if(item.applyNum === null){ 389 | args_xh.printLog ? console.log(`商品未到申请时间:${item.skuTitle}\n`) : '' 390 | continue 391 | } 392 | if(trialActivityIdList.length >= args_xh.maxLength){ 393 | console.log('商品列表长度已满.结束获取') 394 | break 395 | } 396 | if(item.applyState === 1){ 397 | args_xh.printLog ? console.log(`商品已申请试用:${item.skuTitle}\n`) : '' 398 | continue 399 | } 400 | if(item.applyState !== null){ 401 | args_xh.printLog ? console.log(`商品状态异常,未找到skuTitle\n`) : '' 402 | continue 403 | } 404 | if(args_xh.passZhongCao){ 405 | $.isPush = true; 406 | if(item.tagList.length !== 0){ 407 | for(let itemTag of item.tagList){ 408 | if(itemTag.tagType === 3){ 409 | args_xh.printLog ? console.log('商品被过滤,该商品是种草官专属') : '' 410 | $.isPush = false; 411 | break; 412 | } else if(itemTag.tagType === 5){ 413 | args_xh.printLog ? console.log('商品被跳过,该商品是付费试用!') : '' 414 | $.isPush = false; 415 | break; 416 | } 417 | } 418 | } 419 | } 420 | if(item.skuTitle && $.isPush){ 421 | args_xh.printLog ? console.log(`检测 tabId:${args_xh.tabId[$.nowTabIdIndex]} 的 第 ${page}/${args_xh.totalPages} 页 第 ${$.nowItem++ + 1} 个商品\n${item.skuTitle}`) : '' 422 | if(args_xh.whiteList){ 423 | if(args_xh.whiteListKeywords.some(fileter_word => item.skuTitle.includes(fileter_word))){ 424 | args_xh.printLog ? console.log(`商品白名单通过,将加入试用组,trialActivityId为${item.trialActivityId}\n`) : '' 425 | trialActivityIdList.push(item.trialActivityId) 426 | trialActivityTitleList.push(item.skuTitle) 427 | } 428 | } else { 429 | tempKeyword = ``; 430 | if(parseFloat(item.jdPrice) <= args_xh.jdPrice){ 431 | args_xh.printLog ? console.log(`商品被过滤,${item.jdPrice} < ${args_xh.jdPrice} \n`) : '' 432 | } else if(parseFloat(item.supplyNum) < args_xh.minSupplyNum && item.supplyNum !== null){ 433 | args_xh.printLog ? console.log(`商品被过滤,提供申请的份数小于预设申请的份数 \n`) : '' 434 | } else if(parseFloat(item.applyNum) > args_xh.applyNumFilter && item.applyNum !== null){ 435 | args_xh.printLog ? console.log(`商品被过滤,已申请试用人数大于预设人数 \n`) : '' 436 | } else if(parseFloat(item.jdPrice) < args_xh.jdPrice){ 437 | args_xh.printLog ? console.log(`商品被过滤,商品原价低于预设商品原价 \n`) : '' 438 | } else if(args_xh.titleFilters.some(fileter_word => item.skuTitle.includes(fileter_word) ? tempKeyword = fileter_word : '')){ 439 | args_xh.printLog ? console.log(`商品被过滤,含有关键词 ${tempKeyword}\n`) : '' 440 | } else { 441 | args_xh.printLog ? console.log(`商品通过,将加入试用组,trialActivityId为${item.trialActivityId}\n`) : '' 442 | trialActivityIdList.push(item.trialActivityId) 443 | trialActivityTitleList.push(item.skuTitle) 444 | } 445 | } 446 | } else if($.isPush !== false){ 447 | console.error('skuTitle解析异常') 448 | return 449 | } 450 | } 451 | console.log(`当前试用组长度为:${trialActivityIdList.length}`) 452 | args_xh.printLog ? console.log(`${trialActivityIdList}`) : '' 453 | if(page >= args_xh.totalPages && $.nowTabIdIndex < args_xh.tabId.length){ 454 | //这个是因为每一个tab都会有对应的页数,获取完如果还不够的话,就获取下一个tab 455 | $.nowTabIdIndex++; 456 | $.nowPage = 1; 457 | $.nowItem = 1; 458 | } 459 | } else { 460 | console.log(`💩 获得试用列表失败: ${data.message}`) 461 | } 462 | } 463 | } catch(e){ 464 | reject(`⚠️ ${arguments.callee.name.toString()} API返回结果解析出错\n${e}\n${JSON.stringify(data)}`) 465 | } finally{ 466 | resolve() 467 | } 468 | }) 469 | }) 470 | } 471 | 472 | function try_apply(title, activityId){ 473 | return new Promise((resolve, reject) => { 474 | console.log(`申请试用商品提交中...`) 475 | args_xh.printLog ? console.log(`商品:${title}`) : '' 476 | args_xh.printLog ? console.log(`id为:${activityId}`) : '' 477 | const body = JSON.stringify({ 478 | "activityId": activityId, 479 | "previewTime": "" 480 | }); 481 | let option = taskurl_xh('newtry', 'try_apply', body) 482 | $.get(option, (err, resp, data) => { 483 | try{ 484 | if(err){ 485 | if(JSON.stringify(err) === `\"Response code 403 (Forbidden)\"`){ 486 | $.isForbidden = true 487 | console.log('账号被京东服务器风控,不再请求该帐号') 488 | } else { 489 | console.log(JSON.stringify(err)) 490 | console.log(`${$.name} API请求失败,请检查网路重试`) 491 | } 492 | } else { 493 | $.totalTry++ 494 | data = JSON.parse(data) 495 | if(data.success && data.code === "1"){ // 申请成功 496 | console.log("申请提交成功") 497 | $.totalSuccess++ 498 | } else if(data.code === "-106"){ 499 | console.log(data.message) // 未在申请时间内! 500 | } else if(data.code === "-110"){ 501 | console.log(data.message) // 您的申请已成功提交,请勿重复申请… 502 | } else if(data.code === "-120"){ 503 | console.log(data.message) // 您还不是会员,本品只限会员申请试用,请注册会员后申请! 504 | } else if(data.code === "-167"){ 505 | console.log(data.message) // 抱歉,此试用需为种草官才能申请。查看下方详情了解更多。 506 | } else if(data.code === "-131"){ 507 | console.log(data.message) // 申请次数上限。 508 | $.isLimit = true; 509 | } else if(data.code === "-113"){ 510 | console.log(data.message) // 操作不要太快哦! 511 | } else { 512 | console.log("申请失败", data) 513 | } 514 | } 515 | } catch(e){ 516 | reject(`⚠️ ${arguments.callee.name.toString()} API返回结果解析出错\n${e}\n${JSON.stringify(data)}`) 517 | } finally{ 518 | resolve() 519 | } 520 | }) 521 | }) 522 | } 523 | 524 | function try_MyTrials(page, selected){ 525 | return new Promise((resolve, reject) => { 526 | switch(selected){ 527 | case 1: 528 | console.log('正在获取已申请的商品...') 529 | break; 530 | case 2: 531 | console.log('正在获取申请成功的商品...') 532 | break; 533 | case 3: 534 | console.log('正在获取申请失败的商品...') 535 | break; 536 | default: 537 | console.log('selected错误') 538 | } 539 | let options = { 540 | url: URL, 541 | body: `appid=newtry&functionId=try_MyTrials&clientVersion=10.3.4&client=wh5&body=%7B%22page%22%3A${page}%2C%22selected%22%3A${selected}%2C%22previewTime%22%3A%22%22%7D`, 542 | headers: { 543 | 'origin': 'https://prodev.m.jd.com', 544 | 'User-Agent': 'jdapp;iPhone;10.3.4;;;M/5.0;appBuild/167945;jdSupportDarkMode/1;;;Mozilla/5.0 (iPhone; CPU iPhone OS 15_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1;', 545 | 'referer': 'https://prodev.m.jd.com/', 546 | 'cookie': $.cookie 547 | }, 548 | } 549 | $.post(options, (err, resp, data) => { 550 | try{ 551 | if(err){ 552 | console.log(`🚫 ${arguments.callee.name.toString()} API请求失败,请检查网路\n${JSON.stringify(err)}`) 553 | } else { 554 | data = JSON.parse(data) 555 | if(data.success){ 556 | //temp adjustment 557 | if(selected === 2){ 558 | if(data.success && data.data){ 559 | for(let item of data.data.list){ 560 | item.status === 4 || item.text.text.includes('已放弃') ? $.giveupNum += 1 : '' 561 | item.status === 2 && item.text.text.includes('试用资格将保留') ? $.successNum += 1 : '' 562 | item.status === 2 && item.text.text.includes('请收货后尽快提交报告') ? $.getNum += 1 : '' 563 | item.status === 2 && item.text.text.includes('试用已完成') ? $.completeNum += 1 : '' 564 | } 565 | console.log(`待领取 | 已领取 | 已完成 | 已放弃:${$.successNum} | ${$.getNum} | ${$.completeNum} | ${$.giveupNum}`) 566 | } else { 567 | console.log(`获得成功列表失败: ${data.message}`) 568 | } 569 | } 570 | } else { 571 | console.error(`ERROR:try_MyTrials`) 572 | } 573 | } 574 | } catch(e){ 575 | reject(`⚠️ ${arguments.callee.name.toString()} API返回结果解析出错\n${e}\n${JSON.stringify(data)}`) 576 | } finally{ 577 | resolve() 578 | } 579 | }) 580 | }) 581 | } 582 | 583 | function taskurl_xh(appid, functionId, body = JSON.stringify({})){ 584 | return { 585 | "url": `${URL}?appid=${appid}&functionId=${functionId}&clientVersion=10.3.4&client=wh5&body=${encodeURIComponent(body)}`, 586 | 'headers': { 587 | 'Cookie': $.cookie, 588 | 'UserAgent': 'jdapp;iPhone;10.1.2;15.0;ff2caa92a8529e4788a34b3d8d4df66d9573f499;network/wifi;model/iPhone13,4;addressid/2074196292;appBuild/167802;jdSupportDarkMode/1;Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1', 589 | 'Referer': 'https://prodev.m.jd.com/' 590 | }, 591 | } 592 | } 593 | 594 | async function showMsg(){ 595 | let message = ``; 596 | message += `👤 京东账号${$.index} ${$.nickName || $.UserName}\n`; 597 | if($.totalSuccess !== 0 && $.totalTry !== 0){ 598 | message += `🎉 本次提交申请:${$.totalSuccess}/${$.totalTry}个商品🛒\n`; 599 | message += `🎉 ${$.successNum}个商品待领取\n`; 600 | message += `🎉 ${$.getNum}个商品已领取\n`; 601 | message += `🎉 ${$.completeNum}个商品已完成\n`; 602 | message += `🗑 ${$.giveupNum}个商品已放弃\n\n`; 603 | } else { 604 | message += `⚠️ 本次执行没有申请试用商品\n`; 605 | message += `🎉 ${$.successNum}个商品待领取\n`; 606 | message += `🎉 ${$.getNum}个商品已领取\n`; 607 | message += `🎉 ${$.completeNum}个商品已完成\n`; 608 | message += `🗑 ${$.giveupNum}个商品已放弃\n\n`; 609 | } 610 | if(!args_xh.jdNotify || args_xh.jdNotify === 'false'){ 611 | $.msg($.name, ``, message, { 612 | "open-url": 'https://try.m.jd.com/user' 613 | }) 614 | if($.isNode()) 615 | notifyMsg += `${message}` 616 | } else { 617 | console.log(message) 618 | } 619 | } 620 | 621 | function totalBean(){ 622 | return new Promise(async resolve => { 623 | const options = { 624 | "url": `https://wq.jd.com/user/info/QueryJDUserInfo?sceneval=2`, 625 | "headers": { 626 | "Accept": "application/json,text/plain, */*", 627 | "Content-Type": "application/x-www-form-urlencoded", 628 | "Accept-Encoding": "gzip, deflate, br", 629 | "Accept-Language": "zh-cn", 630 | "Connection": "keep-alive", 631 | "Cookie": $.cookie, 632 | "Referer": "https://wqs.jd.com/my/jingdou/my.shtml?sceneval=2", 633 | "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") 634 | }, 635 | "timeout": 10000, 636 | } 637 | $.post(options, (err, resp, data) => { 638 | try{ 639 | if(err){ 640 | console.log(`${JSON.stringify(err)}`) 641 | console.log(`${$.name} API请求失败,请检查网路重试`) 642 | } else { 643 | if(data){ 644 | data = JSON.parse(data); 645 | if(data['retcode'] === 13){ 646 | $.isLogin = false; //cookie过期 647 | return 648 | } 649 | if(data['retcode'] === 0){ 650 | $.nickName = (data['base'] && data['base'].nickname) || $.UserName; 651 | } else { 652 | $.nickName = $.UserName 653 | } 654 | } else { 655 | console.log(`京东服务器返回空数据`) 656 | } 657 | } 658 | } catch(e){ 659 | $.logErr(e, resp) 660 | } finally{ 661 | resolve(); 662 | } 663 | }) 664 | }) 665 | } 666 | 667 | function jsonParse(str){ 668 | if(typeof str == "string"){ 669 | try{ 670 | return JSON.parse(str); 671 | } catch(e){ 672 | console.log(e); 673 | $.msg($.name, '', '请勿随意在BoxJs输入框修改内容\n建议通过脚本去获取cookie') 674 | return []; 675 | } 676 | } 677 | } 678 | 679 | function Env(name, opts){ 680 | class Http{ 681 | constructor(env){ 682 | this.env = env 683 | } 684 | 685 | send(opts, method = 'GET'){ 686 | opts = typeof opts === 'string' ? { 687 | url: opts 688 | } : opts 689 | let sender = this.get 690 | if(method === 'POST'){ 691 | sender = this.post 692 | } 693 | return new Promise((resolve, reject) => { 694 | sender.call(this, opts, (err, resp, body) => { 695 | if(err) reject(err) 696 | else resolve(resp) 697 | }) 698 | }) 699 | } 700 | 701 | get(opts){ 702 | return this.send.call(this.env, opts) 703 | } 704 | 705 | post(opts){ 706 | return this.send.call(this.env, opts, 'POST') 707 | } 708 | } 709 | 710 | return new (class{ 711 | constructor(name, opts){ 712 | this.name = name 713 | this.http = new Http(this) 714 | this.data = null 715 | this.dataFile = 'box.dat' 716 | this.logs = [] 717 | this.isMute = false 718 | this.isNeedRewrite = false 719 | this.logSeparator = '\n' 720 | this.startTime = new Date().getTime() 721 | Object.assign(this, opts) 722 | this.log('', `🔔${this.name}, 开始!`) 723 | } 724 | 725 | isNode(){ 726 | return 'undefined' !== typeof module && !!module.exports 727 | } 728 | 729 | isQuanX(){ 730 | return 'undefined' !== typeof $task 731 | } 732 | 733 | isSurge(){ 734 | return 'undefined' !== typeof $httpClient && 'undefined' === typeof $loon 735 | } 736 | 737 | isLoon(){ 738 | return 'undefined' !== typeof $loon 739 | } 740 | 741 | toObj(str, defaultValue = null){ 742 | try{ 743 | return JSON.parse(str) 744 | } catch{ 745 | return defaultValue 746 | } 747 | } 748 | 749 | toStr(obj, defaultValue = null){ 750 | try{ 751 | return JSON.stringify(obj) 752 | } catch{ 753 | return defaultValue 754 | } 755 | } 756 | 757 | getjson(key, defaultValue){ 758 | let json = defaultValue 759 | const val = this.getdata(key) 760 | if(val){ 761 | try{ 762 | json = JSON.parse(this.getdata(key)) 763 | } catch{ } 764 | } 765 | return json 766 | } 767 | 768 | setjson(val, key){ 769 | try{ 770 | return this.setdata(JSON.stringify(val), key) 771 | } catch{ 772 | return false 773 | } 774 | } 775 | 776 | getScript(url){ 777 | return new Promise((resolve) => { 778 | this.get({ 779 | url 780 | }, (err, resp, body) => resolve(body)) 781 | }) 782 | } 783 | 784 | runScript(script, runOpts){ 785 | return new Promise((resolve) => { 786 | let httpapi = this.getdata('@chavy_boxjs_userCfgs.httpapi') 787 | httpapi = httpapi ? httpapi.replace(/\n/g, '').trim() : httpapi 788 | let httpapi_timeout = this.getdata('@chavy_boxjs_userCfgs.httpapi_timeout') 789 | httpapi_timeout = httpapi_timeout ? httpapi_timeout * 1 : 20 790 | httpapi_timeout = runOpts && runOpts.timeout ? runOpts.timeout : httpapi_timeout 791 | const [key, addr] = httpapi.split('@') 792 | const opts = { 793 | url: `http://${addr}/v1/scripting/evaluate`, 794 | body: { 795 | script_text: script, 796 | mock_type: 'cron', 797 | timeout: httpapi_timeout 798 | }, 799 | headers: { 800 | 'X-Key': key, 801 | 'Accept': '*/*' 802 | } 803 | } 804 | this.post(opts, (err, resp, body) => resolve(body)) 805 | }).catch((e) => this.logErr(e)) 806 | } 807 | 808 | loaddata(){ 809 | if(this.isNode()){ 810 | this.fs = this.fs ? this.fs : require('fs') 811 | this.path = this.path ? this.path : require('path') 812 | const curDirDataFilePath = this.path.resolve(this.dataFile) 813 | const rootDirDataFilePath = this.path.resolve(process.cwd(), this.dataFile) 814 | const isCurDirDataFile = this.fs.existsSync(curDirDataFilePath) 815 | const isRootDirDataFile = !isCurDirDataFile && this.fs.existsSync(rootDirDataFilePath) 816 | if(isCurDirDataFile || isRootDirDataFile){ 817 | const datPath = isCurDirDataFile ? curDirDataFilePath : rootDirDataFilePath 818 | try{ 819 | return JSON.parse(this.fs.readFileSync(datPath)) 820 | } catch(e){ 821 | return {} 822 | } 823 | } else return {} 824 | } else return {} 825 | } 826 | 827 | writedata(){ 828 | if(this.isNode()){ 829 | this.fs = this.fs ? this.fs : require('fs') 830 | this.path = this.path ? this.path : require('path') 831 | const curDirDataFilePath = this.path.resolve(this.dataFile) 832 | const rootDirDataFilePath = this.path.resolve(process.cwd(), this.dataFile) 833 | const isCurDirDataFile = this.fs.existsSync(curDirDataFilePath) 834 | const isRootDirDataFile = !isCurDirDataFile && this.fs.existsSync(rootDirDataFilePath) 835 | const jsondata = JSON.stringify(this.data) 836 | if(isCurDirDataFile){ 837 | this.fs.writeFileSync(curDirDataFilePath, jsondata) 838 | } else if(isRootDirDataFile){ 839 | this.fs.writeFileSync(rootDirDataFilePath, jsondata) 840 | } else { 841 | this.fs.writeFileSync(curDirDataFilePath, jsondata) 842 | } 843 | } 844 | } 845 | 846 | lodash_get(source, path, defaultValue = undefined){ 847 | const paths = path.replace(/\[(\d+)\]/g, '.$1').split('.') 848 | let result = source 849 | for(const p of paths){ 850 | result = Object(result)[p] 851 | if(result === undefined){ 852 | return defaultValue 853 | } 854 | } 855 | return result 856 | } 857 | 858 | lodash_set(obj, path, value){ 859 | if(Object(obj) !== obj) return obj 860 | if(!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [] 861 | path.slice(0, -1).reduce((a, c, i) => (Object(a[c]) === a[c] ? a[c] : (a[c] = Math.abs(path[i + 1]) >> 0 === +path[i + 1] ? [] : {})), obj)[ 862 | path[path.length - 1] 863 | ] = value 864 | return obj 865 | } 866 | 867 | getdata(key){ 868 | let val = this.getval(key) 869 | // 如果以 @ 870 | if(/^@/.test(key)){ 871 | const [, objkey, paths] = /^@(.*?)\.(.*?)$/.exec(key) 872 | const objval = objkey ? this.getval(objkey) : '' 873 | if(objval){ 874 | try{ 875 | const objedval = JSON.parse(objval) 876 | val = objedval ? this.lodash_get(objedval, paths, '') : val 877 | } catch(e){ 878 | val = '' 879 | } 880 | } 881 | } 882 | return val 883 | } 884 | 885 | setdata(val, key){ 886 | let issuc = false 887 | if(/^@/.test(key)){ 888 | const [, objkey, paths] = /^@(.*?)\.(.*?)$/.exec(key) 889 | const objdat = this.getval(objkey) 890 | const objval = objkey ? (objdat === 'null' ? null : objdat || '{}') : '{}' 891 | try{ 892 | const objedval = JSON.parse(objval) 893 | this.lodash_set(objedval, paths, val) 894 | issuc = this.setval(JSON.stringify(objedval), objkey) 895 | } catch(e){ 896 | const objedval = {} 897 | this.lodash_set(objedval, paths, val) 898 | issuc = this.setval(JSON.stringify(objedval), objkey) 899 | } 900 | } else { 901 | issuc = this.setval(val, key) 902 | } 903 | return issuc 904 | } 905 | 906 | getval(key){ 907 | if(this.isSurge() || this.isLoon()){ 908 | return $persistentStore.read(key) 909 | } else if(this.isQuanX()){ 910 | return $prefs.valueForKey(key) 911 | } else if(this.isNode()){ 912 | this.data = this.loaddata() 913 | return this.data[key] 914 | } else { 915 | return (this.data && this.data[key]) || null 916 | } 917 | } 918 | 919 | setval(val, key){ 920 | if(this.isSurge() || this.isLoon()){ 921 | return $persistentStore.write(val, key) 922 | } else if(this.isQuanX()){ 923 | return $prefs.setValueForKey(val, key) 924 | } else if(this.isNode()){ 925 | this.data = this.loaddata() 926 | this.data[key] = val 927 | this.writedata() 928 | return true 929 | } else { 930 | return (this.data && this.data[key]) || null 931 | } 932 | } 933 | 934 | initGotEnv(opts){ 935 | this.got = this.got ? this.got : require('got') 936 | this.cktough = this.cktough ? this.cktough : require('tough-cookie') 937 | this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar() 938 | if(opts){ 939 | opts.headers = opts.headers ? opts.headers : {} 940 | if(undefined === opts.headers.Cookie && undefined === opts.cookieJar){ 941 | opts.cookieJar = this.ckjar 942 | } 943 | } 944 | } 945 | 946 | get(opts, callback = () => { }){ 947 | if(opts.headers){ 948 | delete opts.headers['Content-Type'] 949 | delete opts.headers['Content-Length'] 950 | } 951 | if(this.isSurge() || this.isLoon()){ 952 | if(this.isSurge() && this.isNeedRewrite){ 953 | opts.headers = opts.headers || {} 954 | Object.assign(opts.headers, { 955 | 'X-Surge-Skip-Scripting': false 956 | }) 957 | } 958 | $httpClient.get(opts, (err, resp, body) => { 959 | if(!err && resp){ 960 | resp.body = body 961 | resp.statusCode = resp.status 962 | } 963 | callback(err, resp, body) 964 | }) 965 | } else if(this.isQuanX()){ 966 | if(this.isNeedRewrite){ 967 | opts.opts = opts.opts || {} 968 | Object.assign(opts.opts, { 969 | hints: false 970 | }) 971 | } 972 | $task.fetch(opts).then( 973 | (resp) => { 974 | const { 975 | statusCode: status, 976 | statusCode, 977 | headers, 978 | body 979 | } = resp 980 | callback(null, { 981 | status, 982 | statusCode, 983 | headers, 984 | body 985 | }, body) 986 | }, 987 | (err) => callback(err) 988 | ) 989 | } else if(this.isNode()){ 990 | this.initGotEnv(opts) 991 | this.got(opts).on('redirect', (resp, nextOpts) => { 992 | try{ 993 | if(resp.headers['set-cookie']){ 994 | const ck = resp.headers['set-cookie'].map(this.cktough.Cookie.parse).toString() 995 | if(ck){ 996 | this.ckjar.setCookieSync(ck, null) 997 | } 998 | nextOpts.cookieJar = this.ckjar 999 | } 1000 | } catch(e){ 1001 | this.logErr(e) 1002 | } 1003 | // this.ckjar.setCookieSync(resp.headers['set-cookie'].map(Cookie.parse).toString()) 1004 | }).then( 1005 | (resp) => { 1006 | const { 1007 | statusCode: status, 1008 | statusCode, 1009 | headers, 1010 | body 1011 | } = resp 1012 | callback(null, { 1013 | status, 1014 | statusCode, 1015 | headers, 1016 | body 1017 | }, body) 1018 | }, 1019 | (err) => { 1020 | const { 1021 | message: error, 1022 | response: resp 1023 | } = err 1024 | callback(error, resp, resp && resp.body) 1025 | } 1026 | ) 1027 | } 1028 | } 1029 | 1030 | post(opts, callback = () => { }){ 1031 | // 如果指定了请求体, 但没指定`Content-Type`, 则自动生成 1032 | if(opts.body && opts.headers && !opts.headers['Content-Type']){ 1033 | opts.headers['Content-Type'] = 'application/x-www-form-urlencoded' 1034 | } 1035 | if(opts.headers) delete opts.headers['Content-Length'] 1036 | if(this.isSurge() || this.isLoon()){ 1037 | if(this.isSurge() && this.isNeedRewrite){ 1038 | opts.headers = opts.headers || {} 1039 | Object.assign(opts.headers, { 1040 | 'X-Surge-Skip-Scripting': false 1041 | }) 1042 | } 1043 | $httpClient.post(opts, (err, resp, body) => { 1044 | if(!err && resp){ 1045 | resp.body = body 1046 | resp.statusCode = resp.status 1047 | } 1048 | callback(err, resp, body) 1049 | }) 1050 | } else if(this.isQuanX()){ 1051 | opts.method = 'POST' 1052 | if(this.isNeedRewrite){ 1053 | opts.opts = opts.opts || {} 1054 | Object.assign(opts.opts, { 1055 | hints: false 1056 | }) 1057 | } 1058 | $task.fetch(opts).then( 1059 | (resp) => { 1060 | const { 1061 | statusCode: status, 1062 | statusCode, 1063 | headers, 1064 | body 1065 | } = resp 1066 | callback(null, { 1067 | status, 1068 | statusCode, 1069 | headers, 1070 | body 1071 | }, body) 1072 | }, 1073 | (err) => callback(err) 1074 | ) 1075 | } else if(this.isNode()){ 1076 | this.initGotEnv(opts) 1077 | const { 1078 | url, 1079 | ..._opts 1080 | } = opts 1081 | this.got.post(url, _opts).then( 1082 | (resp) => { 1083 | const { 1084 | statusCode: status, 1085 | statusCode, 1086 | headers, 1087 | body 1088 | } = resp 1089 | callback(null, { 1090 | status, 1091 | statusCode, 1092 | headers, 1093 | body 1094 | }, body) 1095 | }, 1096 | (err) => { 1097 | const { 1098 | message: error, 1099 | response: resp 1100 | } = err 1101 | callback(error, resp, resp && resp.body) 1102 | } 1103 | ) 1104 | } 1105 | } 1106 | 1107 | /** 1108 | * 1109 | * 示例:$.time('yyyy-MM-dd qq HH:mm:ss.S') 1110 | * :$.time('yyyyMMddHHmmssS') 1111 | * y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒 1112 | * 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符 1113 | * @param {*} fmt 格式化参数 1114 | * 1115 | */ 1116 | time(fmt){ 1117 | let o = { 1118 | 'M+': new Date().getMonth() + 1, 1119 | 'd+': new Date().getDate(), 1120 | 'H+': new Date().getHours(), 1121 | 'm+': new Date().getMinutes(), 1122 | 's+': new Date().getSeconds(), 1123 | 'q+': Math.floor((new Date().getMonth() + 3) / 3), 1124 | 'S': new Date().getMilliseconds() 1125 | } 1126 | if(/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (new Date().getFullYear() + '').substr(4 - RegExp.$1.length)) 1127 | for(let k in o) 1128 | if(new RegExp('(' + k + ')').test(fmt)) 1129 | fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)) 1130 | return fmt 1131 | } 1132 | 1133 | /** 1134 | * 系统通知 1135 | * 1136 | * > 通知参数: 同时支持 QuanX 和 Loon 两种格式, EnvJs根据运行环境自动转换, Surge 环境不支持多媒体通知 1137 | * 1138 | * 示例: 1139 | * $.msg(title, subt, desc, 'twitter://') 1140 | * $.msg(title, subt, desc, { 'open-url': 'twitter://', 'media-url': 'https://github.githubassets.com/images/modules/open_graph/github-mark.png' }) 1141 | * $.msg(title, subt, desc, { 'open-url': 'https://bing.com', 'media-url': 'https://github.githubassets.com/images/modules/open_graph/github-mark.png' }) 1142 | * 1143 | * @param {*} title 标题 1144 | * @param {*} subt 副标题 1145 | * @param {*} desc 通知详情 1146 | * @param {*} opts 通知参数 1147 | * 1148 | */ 1149 | msg(title = name, subt = '', desc = '', opts){ 1150 | const toEnvOpts = (rawopts) => { 1151 | if(!rawopts) return rawopts 1152 | if(typeof rawopts === 'string'){ 1153 | if(this.isLoon()) return rawopts 1154 | else if(this.isQuanX()) return { 1155 | 'open-url': rawopts 1156 | } 1157 | else if(this.isSurge()) return { 1158 | url: rawopts 1159 | } 1160 | else return undefined 1161 | } else if(typeof rawopts === 'object'){ 1162 | if(this.isLoon()){ 1163 | let openUrl = rawopts.openUrl || rawopts.url || rawopts['open-url'] 1164 | let mediaUrl = rawopts.mediaUrl || rawopts['media-url'] 1165 | return { 1166 | openUrl, 1167 | mediaUrl 1168 | } 1169 | } else if(this.isQuanX()){ 1170 | let openUrl = rawopts['open-url'] || rawopts.url || rawopts.openUrl 1171 | let mediaUrl = rawopts['media-url'] || rawopts.mediaUrl 1172 | return { 1173 | 'open-url': openUrl, 1174 | 'media-url': mediaUrl 1175 | } 1176 | } else if(this.isSurge()){ 1177 | let openUrl = rawopts.url || rawopts.openUrl || rawopts['open-url'] 1178 | return { 1179 | url: openUrl 1180 | } 1181 | } 1182 | } else { 1183 | return undefined 1184 | } 1185 | } 1186 | if(!this.isMute){ 1187 | if(this.isSurge() || this.isLoon()){ 1188 | $notification.post(title, subt, desc, toEnvOpts(opts)) 1189 | } else if(this.isQuanX()){ 1190 | $notify(title, subt, desc, toEnvOpts(opts)) 1191 | } 1192 | } 1193 | if(!this.isMuteLog){ 1194 | let logs = ['', '==============📣系统通知📣=============='] 1195 | logs.push(title) 1196 | subt ? logs.push(subt) : '' 1197 | desc ? logs.push(desc) : '' 1198 | console.log(logs.join('\n')) 1199 | this.logs = this.logs.concat(logs) 1200 | } 1201 | } 1202 | 1203 | log(...logs){ 1204 | if(logs.length > 0){ 1205 | this.logs = [...this.logs, ...logs] 1206 | } 1207 | console.log(logs.join(this.logSeparator)) 1208 | } 1209 | 1210 | logErr(err, msg){ 1211 | const isPrintSack = !this.isSurge() && !this.isQuanX() && !this.isLoon() 1212 | if(!isPrintSack){ 1213 | this.log('', `❗️${this.name}, 错误!`, err) 1214 | } else { 1215 | this.log('', `❗️${this.name}, 错误!`, err.stack) 1216 | } 1217 | } 1218 | 1219 | wait(time){ 1220 | return new Promise((resolve) => setTimeout(resolve, time)) 1221 | } 1222 | 1223 | done(val = {}){ 1224 | const endTime = new Date().getTime() 1225 | const costTime = (endTime - this.startTime) / 1000 1226 | this.log('', `🔔${this.name}, 结束! 🕛 ${costTime} 秒`) 1227 | this.log() 1228 | if(this.isSurge() || this.isQuanX() || this.isLoon()){ 1229 | $done(val) 1230 | } 1231 | } 1232 | })(name, opts) 1233 | } 1234 | -------------------------------------------------------------------------------- /jd_unsubscribe_xh.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: X1a0He 3 | * @LastEditors: X1a0He 4 | * @Description: 批量取关京东店铺和商品 5 | * @Fixed: 不再支持Qx,仅支持Node.js 6 | */ 7 | const $ = new Env('批量取关店铺和商品'); 8 | //Node.js用户请在jdCookie.js处填写京东ck; 9 | const jdCookieNode = $.isNode() ? require('./jdCookie.js') : ''; 10 | const notify = $.isNode() ? require('./sendNotify') : ''; 11 | //IOS等用户直接用NobyDa的jd cookie 12 | let cookiesArr = [], cookie = ''; 13 | if($.isNode()){ 14 | Object.keys(jdCookieNode).forEach((item) => { 15 | cookiesArr.push(jdCookieNode[item]) 16 | }) 17 | if(process.env.JD_DEBUG && process.env.JD_DEBUG === 'false') console.log = () => {}; 18 | } else { 19 | cookiesArr = [$.getdata('CookieJD'), $.getdata('CookieJD2'), ...jsonParse($.getdata('CookiesJD') || "[]").map(item => item.cookie)].filter(item => !!item); 20 | } 21 | let args_xh = { 22 | /* 23 | * 跳过某个指定账号,默认为全部账号清空 24 | * 填写规则:例如当前Cookie1为pt_key=key; pt_pin=pin1;则环境变量填写pin1即可,此时pin1的购物车将不会被清空 25 | * 若有更多,则按照pin1@pin2@pin3进行填写 26 | * 环境变量名称:XH_UNSUB_EXCEPT 27 | */ 28 | except: process.env.XH_UNSUB_EXCEPT && process.env.XH_UNSUB_EXCEPT.split('@') || [], 29 | /* 30 | * 是否执行取消关注,默认true 31 | * 可通过环境变量控制:JD_UNSUB 32 | * */ 33 | isRun: process.env.JD_UNSUB === 'true' || true, 34 | /* 35 | * 执行完毕是否进行通知,默认false 36 | * 可用环境变量控制:JD_UNSUB_NOTIFY 37 | * */ 38 | isNotify: process.env.JD_UNSUB_NOTIFY === 'true' || false, 39 | /* 40 | * 每次获取已关注的商品数 41 | * 可设置环境变量:JD_UNSUB_GPAGESIZE,默认为20,不建议超过20 42 | * */ 43 | goodPageSize: process.env.JD_UNSUB_GPAGESIZE * 1 || 20, 44 | /* 45 | * 每次获取已关注的店铺数 46 | * 可设置环境变量:JD_UNSUB_SPAGESIZE,默认为20,不建议超过20 47 | * */ 48 | shopPageSize: process.env.JD_UNSUB_SPAGESIZE * 1 || 20, 49 | /* 50 | * 商品类过滤关键词,只要商品名内包含关键词,则不会被取消关注 51 | * 可设置环境变量:JD_UNSUB_GKEYWORDS,用@分隔 52 | * */ 53 | goodsKeyWords: process.env.JD_UNSUB_GKEYWORDS && process.env.JD_UNSUB_GKEYWORDS.split('@') || [], 54 | /* 55 | * 店铺类过滤关键词,只要店铺名内包含关键词,则不会被取消关注 56 | * 可设置环境变量:JD_UNSUB_SKEYWORDS,用@分隔 57 | * */ 58 | shopKeyWords: process.env.JD_UNSUB_SKEYWORDS && process.env.JD_UNSUB_SKEYWORDS.split('@') || [], 59 | /* 60 | * 间隔,防止提示操作频繁,单位毫秒(1秒 = 1000毫秒) 61 | * 可用环境变量控制:JD_UNSUB_INTERVAL,默认为3000毫秒 62 | * */ 63 | unSubscribeInterval: process.env.JD_UNSUB_INTERVAL * 1 || 1000, 64 | /* 65 | * 是否打印日志 66 | * 可用环境变量控制:JD_UNSUB_PLOG,默认为true 67 | * */ 68 | printLog: process.env.JD_UNSUB_PLOG === 'true' || true, 69 | /* 70 | * 失败次数,当取关商品或店铺时,如果连续 x 次失败,则结束本次取关,防止死循环 71 | * 可用环境变量控制:JD_UNSUB_FAILTIMES,默认为3次 72 | * */ 73 | failTimes: process.env.JD_UNSUB_FAILTIMES || 3 74 | } 75 | !(async() => { 76 | console.log('X1a0He留:运行前请看好脚本内的注释,日志已经很清楚了,有问题带着日志来问') 77 | if(args_xh.isRun){ 78 | if(!cookiesArr[0]){ 79 | $.msg('【京东账号一】取关京东店铺商品失败', '【提示】请先获取京东账号一cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/bean/signIndex.action', { 80 | "open-url": "https://bean.m.jd.com/bean/signIndex.action" 81 | }); 82 | } 83 | await requireConfig(); 84 | for(let i = 0; i < cookiesArr.length; i++){ 85 | if(cookiesArr[i]){ 86 | cookie = cookiesArr[i]; 87 | $.UserName = decodeURIComponent(cookie.match(/pt_pin=([^; ]+)(?=;?)/) && cookie.match(/pt_pin=([^; ]+)(?=;?)/)[1]) 88 | $.index = i + 1; 89 | $.isLogin = true; 90 | $.nickName = ''; 91 | await TotalBean(); 92 | console.log(`\n****开始【京东账号${$.index}】${$.nickName || $.UserName}*****\n`); 93 | if(args_xh.except.includes($.UserName)){ 94 | console.log(`跳过账号:${$.nickName || $.UserName}`) 95 | continue 96 | } 97 | if(!$.isLogin){ 98 | $.msg($.name, `【提示】cookie已失效`, `京东账号${$.index} ${$.nickName || $.UserName}\n请重新登录获取\nhttps://bean.m.jd.com/bean/signIndex.action`, { 99 | "open-url": "https://bean.m.jd.com/bean/signIndex.action" 100 | }); 101 | if($.isNode()){ 102 | await notify.sendNotify(`${$.name}cookie已失效 - ${$.UserName}`, `京东账号${$.index} ${$.UserName}\n请重新登录获取cookie`); 103 | } 104 | continue 105 | } 106 | $.shopsKeyWordsNum = 0; 107 | $.goodsKeyWordsNum = 0; 108 | $.unsubscribeGoodsNum = 0; 109 | $.unsubscribeShopsNum = 0; 110 | $.goodsTotalNum = 0 //记录当前总共关注了多少商品 111 | $.shopsTotalNum = 0; //记录当前总共关注了多少店铺 112 | $.commIdList = ``; 113 | $.shopIdList = ``; 114 | $.endGoods = $.endShops = false; 115 | $.failTimes = 0; 116 | // console.log(`=====京东账号${$.index} ${$.nickName || $.UserName}内部变量=====`) 117 | // console.log(`$.unsubscribeGoodsNum: ${$.unsubscribeGoodsNum}`) 118 | // console.log(`$.unsubscribeShopsNum: ${$.unsubscribeShopsNum}`) 119 | // console.log(`$.goodsTotalNum: ${$.goodsTotalNum}`) 120 | // console.log(`$.shopsTotalNum: ${$.shopsTotalNum}`) 121 | // console.log(`$.commIdList: ${$.commIdList}`) 122 | // console.log(`$.shopIdList: ${$.shopIdList}`) 123 | // console.log(`$.failTimes: ${$.failTimes}`) 124 | // console.log(`================`) 125 | await favCommQueryFilter(); //获取商品并过滤 126 | await $.wait(args_xh.unSubscribeInterval) 127 | if(!$.endGoods && parseInt($.goodsTotalNum) !== parseInt($.goodsKeyWordsNum)) await favCommBatchDel();//取关商品 128 | else console.log("不执行取消收藏商品\n") 129 | await $.wait(args_xh.unSubscribeInterval) 130 | await queryShopFavList(); //获取店铺并过滤 131 | await $.wait(args_xh.unSubscribeInterval) 132 | if(!$.endShops && parseInt($.shopsTotalNum) !== parseInt($.shopsKeyWordsNum)) await batchunfollow(); //取关店铺 133 | else console.log("不执行取消收藏店铺\n") 134 | do { 135 | //如果商品总数和店铺总数都为0则已清空,跳出循环 136 | if(parseInt($.goodsTotalNum) === 0 && parseInt($.shopsTotalNum) === 0) break; 137 | else { 138 | //如果商品总数或店铺总数有一个不为0的话,先判断是哪个不为0 139 | if(parseInt($.goodsTotalNum) !== 0){ 140 | if(parseInt($.goodsTotalNum) === parseInt($.goodsKeyWordsNum)) break; 141 | else { 142 | $.commIdList = `` 143 | await favCommQueryFilter(); //获取商品并过滤 144 | await $.wait(args_xh.unSubscribeInterval) 145 | if(!$.endGoods && parseInt($.goodsTotalNum) !== parseInt($.goodsKeyWordsNum)) await favCommBatchDel(); //取关商品 146 | else console.log("不执行取消收藏商品\n") 147 | } 148 | } else if(parseInt($.shopsTotalNum) !== 0){ 149 | if(parseInt($.shopsTotalNum) === parseInt($.shopsKeyWordsNum)) break; 150 | else { 151 | $.shopIdList = `` 152 | await queryShopFavList(); //获取店铺并过滤 153 | await $.wait(args_xh.unSubscribeInterval) 154 | if(!$.endShops && parseInt($.shopsTotalNum) !== parseInt($.shopsKeyWordsNum)) await batchunfollow(); //取关店铺 155 | else console.log("不执行取消收藏店铺\n") 156 | } 157 | } 158 | } 159 | if($.failTimes >= args_xh.failTimes){ 160 | console.log('失败次数到达设定值,触发防死循环机制,该帐号已跳过'); 161 | break; 162 | } 163 | } while(true) 164 | await showMsg_xh(); 165 | } 166 | } 167 | } 168 | })().catch((e) => { 169 | $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') 170 | }).finally(() => { 171 | $.done(); 172 | }) 173 | 174 | function requireConfig(){ 175 | return new Promise(resolve => { 176 | if($.isNode() && process.env.JD_UNSUB){ 177 | console.log('=====环境变量配置如下=====') 178 | console.log(`except: ${typeof args_xh.except}, ${args_xh.except}`) 179 | console.log(`isNotify: ${typeof args_xh.isNotify}, ${args_xh.isNotify}`) 180 | console.log(`goodPageSize: ${typeof args_xh.goodPageSize}, ${args_xh.goodPageSize}`) 181 | console.log(`shopPageSize: ${typeof args_xh.shopPageSize}, ${args_xh.shopPageSize}`) 182 | console.log(`goodsKeyWords: ${typeof args_xh.goodsKeyWords}, ${args_xh.goodsKeyWords}`) 183 | console.log(`shopKeyWords: ${typeof args_xh.shopKeyWords}, ${args_xh.shopKeyWords}`) 184 | console.log(`unSubscribeInterval: ${typeof args_xh.unSubscribeInterval}, ${args_xh.unSubscribeInterval}`) 185 | console.log(`printLog: ${typeof args_xh.printLog}, ${args_xh.printLog}`) 186 | console.log(`failTimes: ${typeof args_xh.failTimes}, ${args_xh.failTimes}`) 187 | console.log('=======================') 188 | } 189 | resolve() 190 | }) 191 | } 192 | 193 | function showMsg_xh(){ 194 | if(args_xh.isNotify){ 195 | $.msg($.name, ``, `【京东账号${$.index}】${$.nickName}\n【还剩关注店铺】${$.shopsTotalNum}个\n【还剩关注商品】${$.goodsTotalNum}个`); 196 | } else { 197 | $.log(`【京东账号${$.index}】${$.nickName}\n【还剩关注店铺】${$.shopsTotalNum}个\n【还剩关注商品】${$.goodsTotalNum}个`); 198 | } 199 | } 200 | 201 | function getSubstr(str, leftStr, rightStr){ 202 | let left = str.indexOf(leftStr); 203 | let right = str.indexOf(rightStr, left); 204 | if(left < 0 || right < left) return ''; 205 | return str.substring(left + leftStr.length, right); 206 | } 207 | 208 | function favCommQueryFilter(){ 209 | return new Promise((resolve) => { 210 | console.log('正在获取已关注的商品...') 211 | const option = { 212 | url: `https://wq.jd.com/fav/comm/FavCommQueryFilter?cp=1&pageSize=${args_xh.goodPageSize}&category=0&promote=0&cutPrice=0&coupon=0&stock=0&sceneval=2`, 213 | headers: { 214 | "Cookie": cookie, 215 | "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"), 216 | "Referer": "https://wqs.jd.com/" 217 | }, 218 | } 219 | $.get(option, async(err, resp, data) => { 220 | try{ 221 | if(data.indexOf("Authorization") !== -1){ 222 | console.log("获取数据失败,401 Authorization Required,可能是User-Agent的问题") 223 | return; 224 | } 225 | data = JSON.parse(getSubstr(data, "try{(", ");}catch(e){}")); 226 | if(data.iRet === '0'){ 227 | $.goodsTotalNum = parseInt(data.totalNum); 228 | console.log(`当前已关注商品:${$.goodsTotalNum}个`) 229 | $.goodsKeyWordsNum = 0; 230 | for(let item of data.data){ 231 | if(args_xh.goodsKeyWords.some(keyword => item.commTitle.includes(keyword))){ 232 | args_xh.printLog ? console.log(`${item.commTitle} `) : '' 233 | args_xh.printLog ? console.log('商品被过滤,含有关键词\n') : '' 234 | $.goodsKeyWordsNum += 1; 235 | } else { 236 | $.commIdList += item.commId + ","; 237 | $.unsubscribeGoodsNum++; 238 | } 239 | } 240 | } else { 241 | $.endGoods = true; 242 | console.log("无商品可取消收藏\n"); 243 | } 244 | } catch(e){ 245 | $.logErr(e, resp); 246 | } finally{ 247 | resolve(data); 248 | } 249 | }); 250 | }) 251 | } 252 | 253 | function favCommBatchDel(){ 254 | return new Promise(resolve => { 255 | console.log("正在取消收藏商品...") 256 | const option = { 257 | url: `https://wq.jd.com/fav/comm/FavCommBatchDel?commId=${$.commIdList}&sceneval=2&g_login_type=1`, 258 | headers: { 259 | "Cookie": cookie, 260 | "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"), 261 | "Referer": "https://wqs.jd.com/" 262 | }, 263 | } 264 | $.get(option, (err, resp, data) => { 265 | try{ 266 | if(data.indexOf("Authorization") !== -1){ 267 | console.log("获取数据失败,401 Authorization Required,可能是User-Agent的问题") 268 | return; 269 | } 270 | data = JSON.parse(data); 271 | if(data.iRet === "0" && data.errMsg === "success"){ 272 | console.log(`成功取消收藏商品:${$.unsubscribeGoodsNum}个\n`) 273 | $.failTimes = 0; 274 | } else { 275 | console.log(`批量取消收藏商品失败,失败次数:${++$.failTimes}\n`, data) 276 | } 277 | } catch(e){ 278 | $.logErr(e, resp); 279 | } finally{ 280 | resolve(data); 281 | } 282 | }); 283 | }) 284 | } 285 | 286 | function queryShopFavList(){ 287 | return new Promise((resolve) => { 288 | console.log("正在获取已关注的店铺...") 289 | const option = { 290 | url: `https://wq.jd.com/fav/shop/QueryShopFavList?cp=1&pageSize=${args_xh.shopPageSize}&sceneval=2&g_login_type=1&callback=jsonpCBKA`, 291 | headers: { 292 | "Cookie": cookie, 293 | "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"), 294 | "Referer": "https://wqs.jd.com/" 295 | }, 296 | } 297 | $.get(option, (err, resp, data) => { 298 | try{ 299 | if(data.indexOf("Authorization") !== -1){ 300 | console.log("获取数据失败,401 Authorization Required,可能是User-Agent的问题") 301 | return; 302 | } 303 | data = JSON.parse(getSubstr(data, "try{jsonpCBKA(", ");}catch(e){}")); 304 | if(data.iRet === '0'){ 305 | $.shopsTotalNum = parseInt(data.totalNum); 306 | console.log(`当前已关注店铺:${$.shopsTotalNum}个`) 307 | if(data.data.length > 0){ 308 | $.shopsKeyWordsNum = 0; 309 | for(let item of data.data){ 310 | if(args_xh.shopKeyWords.some(keyword => item.shopName.includes(keyword))){ 311 | args_xh.printLog ? console.log('店铺被过滤,含有关键词') : '' 312 | args_xh.printLog ? console.log(`${item.shopName}\n`) : '' 313 | $.shopsKeyWordsNum += 1; 314 | } else { 315 | $.shopIdList += item.shopId + ","; 316 | $.unsubscribeShopsNum++; 317 | } 318 | } 319 | } else { 320 | $.endShops = true; 321 | console.log("无店铺可取消关注\n"); 322 | } 323 | } else console.log(`获取已关注店铺失败:${JSON.stringify(data)}`) 324 | } catch(e){ 325 | $.logErr(e, resp); 326 | } finally{ 327 | resolve(data); 328 | } 329 | }); 330 | }) 331 | } 332 | 333 | function batchunfollow(){ 334 | return new Promise(resolve => { 335 | console.log('正在执行批量取消关注店铺...') 336 | const option = { 337 | url: `https://wq.jd.com/fav/shop/batchunfollow?shopId=${$.shopIdList}&sceneval=2&g_login_type=1`, 338 | headers: { 339 | "Cookie": cookie, 340 | "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"), 341 | "Referer": "https://wqs.jd.com/" 342 | }, 343 | } 344 | $.get(option, (err, resp, data) => { 345 | try{ 346 | if(data.indexOf("Authorization") !== -1){ 347 | console.log("获取数据失败,401 Authorization Required,可能是User-Agent的问题") 348 | return; 349 | } 350 | data = JSON.parse(data); 351 | if(data.iRet === "0"){ 352 | console.log(`已成功取消关注店铺:${$.unsubscribeShopsNum}个\n`) 353 | $.failTimes = 0; 354 | } else { 355 | console.log(`批量取消关注店铺失败,失败次数:${++$.failTimes}\n`) 356 | } 357 | } catch(e){ 358 | $.logErr(e, resp); 359 | } finally{ 360 | resolve(data); 361 | } 362 | }); 363 | }) 364 | } 365 | 366 | function TotalBean(){ 367 | return new Promise(async resolve => { 368 | const options = { 369 | "url": `https://wq.jd.com/user/info/QueryJDUserInfo?sceneval=2`, 370 | "headers": { 371 | "Accept": "application/json,text/plain, */*", 372 | "Content-Type": "application/x-www-form-urlencoded", 373 | "Accept-Encoding": "gzip, deflate, br", 374 | "Accept-Language": "zh-cn", 375 | "Connection": "keep-alive", 376 | "Cookie": cookie, 377 | "Referer": "https://wqs.jd.com/my/jingdou/my.shtml?sceneval=2", 378 | "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") 379 | } 380 | } 381 | $.post(options, (err, resp, data) => { 382 | try{ 383 | if(err){ 384 | console.log(`${JSON.stringify(err)}`) 385 | console.log(`${$.name} API请求失败,请检查网路重试`) 386 | } else { 387 | if(data){ 388 | data = JSON.parse(data); 389 | if(data['retcode'] === 13){ 390 | $.isLogin = false; //cookie过期 391 | return 392 | } 393 | if(data['retcode'] === 0){ 394 | $.nickName = (data['base'] && data['base'].nickname) || $.UserName; 395 | } else { 396 | $.nickName = $.UserName 397 | } 398 | } else { 399 | console.log(`京东服务器返回空数据`) 400 | } 401 | } 402 | } catch(e){ 403 | $.logErr(e, resp) 404 | } finally{ 405 | resolve(); 406 | } 407 | }) 408 | }) 409 | } 410 | 411 | function jsonParse(str){ 412 | if(typeof str == "string"){ 413 | try{ 414 | return JSON.parse(str); 415 | } catch(e){ 416 | console.log(e); 417 | $.msg($.name, '', '请勿随意在BoxJs输入框修改内容\n建议通过脚本去获取cookie') 418 | return []; 419 | } 420 | } 421 | } 422 | 423 | // prettier-ignore 424 | function Env(t, e){ 425 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 426 | 427 | class s{ 428 | constructor(t){ 429 | this.env = t 430 | } 431 | 432 | send(t, e = "GET"){ 433 | t = "string" == typeof t ? { 434 | url: t 435 | } : t; 436 | let s = this.get; 437 | return "POST" === e && (s = this.post), new Promise((e, i) => { 438 | s.call(this, t, (t, s, r) => { 439 | t ? i(t) : e(s) 440 | }) 441 | }) 442 | } 443 | 444 | get(t){ 445 | return this.send.call(this.env, t) 446 | } 447 | 448 | post(t){ 449 | return this.send.call(this.env, t, "POST") 450 | } 451 | } 452 | 453 | return new class{ 454 | constructor(t, e){ 455 | 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}, 开始!`) 456 | } 457 | 458 | isNode(){ 459 | return "undefined" != typeof module && !!module.exports 460 | } 461 | 462 | isQuanX(){ 463 | return "undefined" != typeof $task 464 | } 465 | 466 | isSurge(){ 467 | return "undefined" != typeof $httpClient && "undefined" == typeof $loon 468 | } 469 | 470 | isLoon(){ 471 | return "undefined" != typeof $loon 472 | } 473 | 474 | toObj(t, e = null){ 475 | try{ 476 | return JSON.parse(t) 477 | } catch{ 478 | return e 479 | } 480 | } 481 | 482 | toStr(t, e = null){ 483 | try{ 484 | return JSON.stringify(t) 485 | } catch{ 486 | return e 487 | } 488 | } 489 | 490 | getjson(t, e){ 491 | let s = e; 492 | const i = this.getdata(t); 493 | if(i) try{ 494 | s = JSON.parse(this.getdata(t)) 495 | } catch{} 496 | return s 497 | } 498 | 499 | setjson(t, e){ 500 | try{ 501 | return this.setdata(JSON.stringify(t), e) 502 | } catch{ 503 | return !1 504 | } 505 | } 506 | 507 | getScript(t){ 508 | return new Promise(e => { 509 | this.get({ 510 | url: t 511 | }, (t, s, i) => e(i)) 512 | }) 513 | } 514 | 515 | runScript(t, e){ 516 | return new Promise(s => { 517 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 518 | i = i ? i.replace(/\n/g, "").trim() : i; 519 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 520 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 521 | const [o, h] = i.split("@"), n = { 522 | url: `http://${h}/v1/scripting/evaluate`, 523 | body: { 524 | script_text: t, 525 | mock_type: "cron", 526 | timeout: r 527 | }, 528 | headers: { 529 | "X-Key": o, 530 | Accept: "*/*" 531 | } 532 | }; 533 | this.post(n, (t, e, i) => s(i)) 534 | }).catch(t => this.logErr(t)) 535 | } 536 | 537 | loaddata(){ 538 | if(!this.isNode()) return {}; 539 | { 540 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 541 | const t = this.path.resolve(this.dataFile), 542 | e = this.path.resolve(process.cwd(), this.dataFile), 543 | s = this.fs.existsSync(t), 544 | i = !s && this.fs.existsSync(e); 545 | if(!s && !i) return {}; 546 | { 547 | const i = s ? t : e; 548 | try{ 549 | return JSON.parse(this.fs.readFileSync(i)) 550 | } catch(t){ 551 | return {} 552 | } 553 | } 554 | } 555 | } 556 | 557 | writedata(){ 558 | if(this.isNode()){ 559 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 560 | const t = this.path.resolve(this.dataFile), 561 | e = this.path.resolve(process.cwd(), this.dataFile), 562 | s = this.fs.existsSync(t), 563 | i = !s && this.fs.existsSync(e), 564 | r = JSON.stringify(this.data); 565 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 566 | } 567 | } 568 | 569 | lodash_get(t, e, s){ 570 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 571 | let r = t; 572 | for(const t of i) 573 | if(r = Object(r)[t], void 0 === r) return s; 574 | return r 575 | } 576 | 577 | lodash_set(t, e, s){ 578 | 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) 579 | } 580 | 581 | getdata(t){ 582 | let e = this.getval(t); 583 | if(/^@/.test(t)){ 584 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; 585 | if(r) try{ 586 | const t = JSON.parse(r); 587 | e = t ? this.lodash_get(t, i, "") : e 588 | } catch(t){ 589 | e = "" 590 | } 591 | } 592 | return e 593 | } 594 | 595 | setdata(t, e){ 596 | let s = !1; 597 | if(/^@/.test(e)){ 598 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), 599 | h = i ? "null" === o ? null : o || "{}" : "{}"; 600 | try{ 601 | const e = JSON.parse(h); 602 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) 603 | } catch(e){ 604 | const o = {}; 605 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) 606 | } 607 | } else s = this.setval(t, e); 608 | return s 609 | } 610 | 611 | getval(t){ 612 | 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 613 | } 614 | 615 | setval(t, e){ 616 | 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 617 | } 618 | 619 | initGotEnv(t){ 620 | 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)) 621 | } 622 | 623 | get(t, e = (() => {})){ 624 | 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, { 625 | "X-Surge-Skip-Scripting": !1 626 | })), $httpClient.get(t, (t, s, i) => { 627 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 628 | })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 629 | hints: !1 630 | })), $task.fetch(t).then(t => { 631 | const { 632 | statusCode: s, 633 | statusCode: i, 634 | headers: r, 635 | body: o 636 | } = t; 637 | e(null, { 638 | status: s, 639 | statusCode: i, 640 | headers: r, 641 | body: o 642 | }, o) 643 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 644 | try{ 645 | if(t.headers["set-cookie"]){ 646 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 647 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar 648 | } 649 | } catch(t){ 650 | this.logErr(t) 651 | } 652 | }).then(t => { 653 | const { 654 | statusCode: s, 655 | statusCode: i, 656 | headers: r, 657 | body: o 658 | } = t; 659 | e(null, { 660 | status: s, 661 | statusCode: i, 662 | headers: r, 663 | body: o 664 | }, o) 665 | }, t => { 666 | const { 667 | message: s, 668 | response: i 669 | } = t; 670 | e(s, i, i && i.body) 671 | })) 672 | } 673 | 674 | post(t, e = (() => {})){ 675 | 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, { 676 | "X-Surge-Skip-Scripting": !1 677 | })), $httpClient.post(t, (t, s, i) => { 678 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 679 | }); 680 | else if(this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 681 | hints: !1 682 | })), $task.fetch(t).then(t => { 683 | const { 684 | statusCode: s, 685 | statusCode: i, 686 | headers: r, 687 | body: o 688 | } = t; 689 | e(null, { 690 | status: s, 691 | statusCode: i, 692 | headers: r, 693 | body: o 694 | }, o) 695 | }, t => e(t)); 696 | else if(this.isNode()){ 697 | this.initGotEnv(t); 698 | const { 699 | url: s, 700 | ...i 701 | } = t; 702 | this.got.post(s, i).then(t => { 703 | const { 704 | statusCode: s, 705 | statusCode: i, 706 | headers: r, 707 | body: o 708 | } = t; 709 | e(null, { 710 | status: s, 711 | statusCode: i, 712 | headers: r, 713 | body: o 714 | }, o) 715 | }, t => { 716 | const { 717 | message: s, 718 | response: i 719 | } = t; 720 | e(s, i, i && i.body) 721 | }) 722 | } 723 | } 724 | 725 | time(t, e = null){ 726 | const s = e ? new Date(e) : new Date; 727 | let i = { 728 | "M+": s.getMonth() + 1, 729 | "d+": s.getDate(), 730 | "H+": s.getHours(), 731 | "m+": s.getMinutes(), 732 | "s+": s.getSeconds(), 733 | "q+": Math.floor((s.getMonth() + 3) / 3), 734 | S: s.getMilliseconds() 735 | }; 736 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 737 | 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))); 738 | return t 739 | } 740 | 741 | msg(e = t, s = "", i = "", r){ 742 | const o = t => { 743 | if(!t) return t; 744 | if("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { 745 | "open-url": t 746 | } : this.isSurge() ? { 747 | url: t 748 | } : void 0; 749 | if("object" == typeof t){ 750 | if(this.isLoon()){ 751 | let e = t.openUrl || t.url || t["open-url"], 752 | s = t.mediaUrl || t["media-url"]; 753 | return { 754 | openUrl: e, 755 | mediaUrl: s 756 | } 757 | } 758 | if(this.isQuanX()){ 759 | let e = t["open-url"] || t.url || t.openUrl, 760 | s = t["media-url"] || t.mediaUrl; 761 | return { 762 | "open-url": e, 763 | "media-url": s 764 | } 765 | } 766 | if(this.isSurge()){ 767 | let e = t.url || t.openUrl || t["open-url"]; 768 | return { 769 | url: e 770 | } 771 | } 772 | } 773 | }; 774 | if(this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog){ 775 | let t = ["", "==============📣系统通知📣=============="]; 776 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) 777 | } 778 | } 779 | 780 | log(...t){ 781 | t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) 782 | } 783 | 784 | logErr(t, e){ 785 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 786 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 787 | } 788 | 789 | wait(t){ 790 | return new Promise(e => setTimeout(e, t)) 791 | } 792 | 793 | done(t = {}){ 794 | const e = (new Date).getTime(), 795 | s = (e - this.startTime) / 1e3; 796 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 797 | } 798 | }(t, e) 799 | } 800 | --------------------------------------------------------------------------------