├── .env ├── .gitignore ├── README.md ├── leaf大佬教程 ├── 基础.js └── 进阶.js ├── package-lock.json ├── package.json ├── 旧 ├── jc-old2.js └── jiaocheng_old1.js ├── 毛1 ├── esljsb.js ├── ql.js └── sendNotify.js └── 毛2 ├── ql.js └── sendNotify.js /.env: -------------------------------------------------------------------------------- 1 | # 二三里 2 | export esljsb="153xxxx683#xxxxxx" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # template 2 | 3 | #教程专用仓库(环境) 4 | 5 | ### 使用步骤 6 | 7 | 1. clong 本仓库,vscode 打开 8 | 2. 运行 `npm install` 安装 package.json 中的模块 (运行 `npm install`, 运行 `npm install`) 9 | 3. 学习并修改教程模版即可, 10 | 1. 详细注释请参考 leaf 大佬教程, 11 | 2. 我的模版为 毛 1 文件夹中 12 | 3. 本仓库主要是搭建 vscode 等 idea 本地运行环境(青龙环境变量就是根目录 .env) 13 | 4. leaf 大佬教程: @maomaoNote 我的频道: @yml2213_tg 脚本讨论: https://t.me/yml_scripts 14 | 5. 欢迎各位大佬与小白一起交流, 进步 15 | -------------------------------------------------------------------------------- /leaf大佬教程/基础.js: -------------------------------------------------------------------------------- 1 | /* 2 | 微信小程序 zippo会员中心 3 | 以下都以青龙或nodejs环境为准 4 | 5 | 下面一行是建议定时,青龙拉库会自动读取 6 | cron: 24 7,19 * * * 7 | */ 8 | /* 9 | const和let的区别: 10 | 用const定义的变量以后不能再更改 11 | 用let定义的变量可以改 12 | 进阶内容: const 对象本身不可更改,但是对象里面的属性可以改,与指针有关 13 | */ 14 | 15 | const $ = new Env('微信小程序') //青龙拉库会把 new Env('qwerty') 里面的名字qwerty作为定时任务名 16 | const got = require('got') //青龙发包依赖 17 | 18 | const env_name = 'zippoCookie' //环境变量名字 19 | const env = process.env[env_name] || '' //或 process.env.zippoCookie, node读取变量方法. 后面的 || 表示如果前面结果为false或者空字符串或者null或者undifined, 就取后面的值 20 | 21 | //got的基本用法, 封装一下方便之后直接调用, 新手可以不动他直接用就行 22 | async function request(opt) { 23 | const DEFAULT_RETRY = 3 //请求出错重试三次 24 | var resp = null, count = 0 25 | var fn = opt.fn || opt.url 26 | opt.method = opt?.method?.toUpperCase() || 'GET' 27 | while (count++ < DEFAULT_RETRY) { 28 | try { 29 | var err = null 30 | const errcodes = ['ECONNRESET', 'EADDRINUSE', 'ENOTFOUND', 'EAI_AGAIN'] 31 | await got(opt).then(t => { 32 | resp = t 33 | }, e => { 34 | err = e 35 | resp = e.response 36 | }) 37 | if (err) { 38 | if (err.name == 'TimeoutError') { 39 | console.log(`[${fn}]请求超时(${err.code}),重试第${count}次`) 40 | } else if (errcodes.includes(err.code)) { 41 | console.log(`[${fn}]请求错误(${err.code}),重试第${count}次`) 42 | } else { 43 | let statusCode = resp?.statusCode || -1 44 | console.log(`[${fn}]请求错误(${err.message}), 返回[${statusCode}]`) 45 | break 46 | } 47 | } else { 48 | break 49 | } 50 | } catch (e) { 51 | console.log(`[${fn}]请求错误(${e.message}),重试第${count}次`) 52 | }; 53 | } 54 | let { statusCode = -1, headers = null, body = null } = resp 55 | if (body) try { body = JSON.parse(body) } catch { }; 56 | return { statusCode, headers, result: body } 57 | } 58 | 59 | //脚本入口函数main() 60 | async function main() { 61 | if (env == '') { 62 | //没有设置变量,直接退出 63 | console.log(`没有填写变量: ${env_name}`) 64 | return 65 | } 66 | //多账号分割,这里默认是换行(\n)分割,其他情况自己实现 67 | //split('\n')会把字符串按照换行符分割, 并把结果存在user_ck数组里 68 | let user_ck = env.split('\n') 69 | 70 | let index = 1 //用来给账号标记序号, 从1开始 71 | //循环遍历每个账号 72 | for (let ck of user_ck) { 73 | if (!ck) continue //跳过空行 74 | //默认用#分割openid和session_key, 前面是 openid 后面是 session_key 75 | let ck_info = ck.split('#') 76 | let openid = ck_info[0] 77 | let session_key = ck_info[1] //其实session_key要不要都行, 这里为了教学就填上去 78 | //用一个对象代表账号, 里面存放账号信息 79 | let user = { 80 | index: index, 81 | openid, //简写法, 效果等同于 openid: openid, 82 | session_key: decodeURIComponent(session_key), //注意请求里的session_key是编码后的, 我们先解码一次 83 | } 84 | index = index + 1 //每次用完序号+1 85 | //开始账号任务 86 | await userTask(user) 87 | //每个账号之间等1~5秒随机时间 88 | let rnd_time = Math.floor(Math.random() * 4000) + 1000 89 | console.log(`账号[${user.index}]随机等待${rnd_time / 1000}秒...`) 90 | await $.wait(rnd_time) 91 | } 92 | } 93 | 94 | async function userTask(user) { 95 | //任务逻辑都放这里了, 与脚本入口分开, 方便分类控制并模块化 96 | console.log(`\n============= 账号[${user.index}]开始任务 =============`) 97 | await ininttask(user) 98 | //后面可以自己加任务, 比如查看账户积分啥的 99 | //await chakanjifen(user); 100 | //await tom_niubi(user); 101 | } 102 | 103 | //任务列表 104 | async function ininttask(user) { 105 | //user: 用户参数, 里面存放ck和账户信息啥的. 进阶可以用类(class)的方法的代替, 效率更高 106 | //养成良好习惯, 每个方法里面都用try catch包起来, 这样出错了也不影响下一个步骤进行 107 | try { 108 | //请求: https://membercenter.zippo.com.cn/s2/interface/data.aspx?action=ininttask 109 | let urlObject = { 110 | fn: 'ininttask', //调用方法名, 方便debug时候看是哪个方法出问题 111 | 112 | method: 'post', //post方法 113 | 114 | //url问号前面的地址 115 | url: 'https://membercenter.zippo.com.cn/s2/interface/data.aspx', 116 | //url问号后面的参数, 字典形式 117 | searchParams: { 118 | action: 'ininttask', 119 | }, 120 | 121 | //请求头 122 | //got会自动填入url的host部分, 不需要手动设置host 123 | //如果是post,put,delete, got也会自动计算Content-Length 124 | //后面使用form/json的话, got会自动设置content-type 125 | //所以上面三个都可以省略 126 | headers: { 127 | Connection: 'keep-alive', 128 | //参数名字中间带-的需要用引号包起来, 不能直接写, 其他的可以省略引号 129 | 'Accept-Encoding': 'gzip,compress,br,deflate', //这个一般来说不重要, 可以省却 130 | 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.32(0x1800202f) NetType/WIFI Language/zh_CN', //简称UA 131 | Referer: 'https://servicewechat.com/wxaa75ffd8c2d75da7/56/page-frame.html', 132 | }, 133 | 134 | //请求体部分,注意get方法没有请求体 135 | //form对应application/x-www-form-urlencoded 136 | //json对应application/json 137 | //注意form会自动对内容进行编码, 不需要自己再手动编码 138 | form: { 139 | openid: user.openid, 140 | session_key: user.session_key, 141 | unionid: '', 142 | appid: 'wxaa75ffd8c2d75da7', 143 | }, 144 | 145 | //超时设置, 超过15000毫秒自动停止请求 146 | timeout: 15000, 147 | } 148 | 149 | //解构返回, 只需要result也可以这样: 150 | // const {result} = await request(urlObject); 151 | const { statusCode, headers, result } = await request(urlObject) 152 | // ?.语法: 前面的结果为null/undefined的时候不再执行后面操作, 可以简单的防止出错 153 | if (result?.errcode == 0) { 154 | //errcode==0的时候表示请求正常 155 | let tasklist = result?.data?.task || [] //取task数组,如果取不到就取空数组防止下面出错 156 | //遍历tasklist里面的元素, 也就是每个任务 157 | for (let task of tasklist) { 158 | //判断不同任务类型做不同请求 159 | switch (task.title) { 160 | //签到任务调用签到接口 161 | case '签到': 162 | if (task.task_status == 0) { 163 | //task_status是0的时候代表未签到,这时候才去签到 164 | let rnd_time = Math.floor(Math.random() * 1000) + 1000 165 | console.log(`账号[${user.index}]随机等待${rnd_time / 1000}秒...`) 166 | await $.wait(rnd_time) //随机等待 167 | await signin(user) 168 | } else { 169 | console.log(`账号[${user.index}]今天已签到`) 170 | } 171 | break 172 | //其他任务调用通用任务接口 173 | default: 174 | if (task.task_status == 0) { 175 | //task_status是0代表未完成 176 | console.log(`账号[${user.index}]任务[${task.title}]未完成, 去做任务`) 177 | let rnd_time = Math.floor(Math.random() * 1000) + 1000 178 | console.log(`账号[${user.index}]随机等待${rnd_time / 1000}秒...`) 179 | await $.wait(rnd_time) //随机等待 180 | await dotask(user, task, 1) //做任务 181 | rnd_time = Math.floor(Math.random() * 1000) + 1000 //前面已经用过let定义rnd_time了,这里直接复用不要再let一次,不然会出错 182 | console.log(`账号[${user.index}]随机等待${rnd_time / 1000}秒...`) 183 | await $.wait(rnd_time) //随机等待 184 | await dotask(user, task, 2) //领奖励 185 | } else if (task.task_status == 1) { 186 | //task_status是1代表已完成未领取奖励 187 | console.log(`账号[${user.index}]任务[${task.title}]已完成, 未领取奖励, 去领取`) 188 | let rnd_time = Math.floor(Math.random() * 1000) + 1000 189 | console.log(`账号[${user.index}]随机等待${rnd_time / 1000}秒...`) 190 | await $.wait(rnd_time) //随机等待 191 | await dotask(user, task, 2) //领奖励 192 | } else { 193 | //task_status是2代表已领取奖励 194 | console.log(`账号[${user.index}]任务[${task.title}]已领取奖励`) 195 | } 196 | break 197 | } 198 | } 199 | } else { 200 | //打印请求错误信息 201 | console.log(`账号[${user.index}]请求任务列表出错[${result?.errcode}]: ${result?.errmsg}`) 202 | } 203 | } catch (e) { 204 | //打印错误信息 205 | console.log(e) 206 | } 207 | } 208 | 209 | //签到接口 210 | async function signin(user) { 211 | try { 212 | //请求: https://membercenter.zippo.com.cn/s2/interface/data.aspx?action=signin 213 | let urlObject = { 214 | fn: 'signin', 215 | method: 'post', //post方法 216 | 217 | //url问号前面的地址 218 | url: 'https://membercenter.zippo.com.cn/s2/interface/data.aspx', 219 | //url问号后面的参数, 字典形式, 其实我们可以发现这个小程序不同接口的区别, 就是action和请求体参数不一样 220 | searchParams: { 221 | action: 'signin', 222 | }, 223 | 224 | //请求头, 所有接口通用 225 | headers: { 226 | Connection: 'keep-alive', 227 | 'Accept-Encoding': 'gzip,compress,br,deflate', 228 | 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.32(0x1800202f) NetType/WIFI Language/zh_CN', 229 | Referer: 'https://servicewechat.com/wxaa75ffd8c2d75da7/56/page-frame.html', 230 | }, 231 | 232 | //请求体 233 | form: { 234 | daykey: $.time('yyyyMMdd'), //封装在Env()里面的方法, 生成当时的时间格式 235 | openid: user.openid, 236 | session_key: user.session_key, 237 | unionid: '', 238 | appid: 'wxaa75ffd8c2d75da7', 239 | }, 240 | 241 | //超时设置 242 | timeout: 15000, 243 | } 244 | 245 | //解构返回 246 | const { statusCode, headers, result } = await request(urlObject) 247 | if (result?.errcode == 0) { 248 | console.log(`账号[${user.index}]签到成功`) 249 | } else { 250 | //打印请求错误信息 251 | console.log(`账号[${user.index}]签到失败[${result?.errcode}]: ${result?.errmsg}`) 252 | } 253 | } catch (e) { 254 | //打印错误信息 255 | console.log(e) 256 | } 257 | } 258 | 259 | //任务接口 260 | async function dotask(user, task, acttype) { 261 | try { 262 | //请求: https://membercenter.zippo.com.cn/s2/interface/data.aspx?action=signin 263 | let urlObject = { 264 | fn: 'dotask', 265 | method: 'post', //post方法 266 | 267 | //url问号前面的地址 268 | url: 'https://membercenter.zippo.com.cn/s2/interface/data.aspx', 269 | //url问号后面的参数, 字典形式 270 | searchParams: { 271 | action: 'dotask', 272 | }, 273 | 274 | //请求头, 所有接口通用 275 | headers: { 276 | Connection: 'keep-alive', 277 | 'Accept-Encoding': 'gzip,compress,br,deflate', 278 | 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.32(0x1800202f) NetType/WIFI Language/zh_CN', 279 | Referer: 'https://servicewechat.com/wxaa75ffd8c2d75da7/56/page-frame.html', 280 | }, 281 | 282 | //请求体 283 | form: { 284 | taskid: task.taskid, //任务id 285 | acttype: acttype, //任务操作, 1代表完成任务, 2代表领取奖励, 这个靠自己理解 286 | openid: user.openid, 287 | session_key: user.session_key, 288 | unionid: '', 289 | appid: 'wxaa75ffd8c2d75da7', 290 | }, 291 | 292 | //超时设置 293 | timeout: 15000, 294 | } 295 | 296 | //看是做任务还是领取任务 297 | let str = acttype == 1 ? '完成任务' : '领取奖励' 298 | 299 | //解构返回 300 | const { statusCode, headers, result } = await request(urlObject) 301 | if (result?.errcode == 0) { 302 | console.log(`账号[${user.index}]${str}[${task.title}]成功`) 303 | } else { 304 | //打印请求错误信息 305 | console.log(`账号[${user.index}]${str}[${task.title}]失败[${result?.errcode}]: ${result?.errmsg}`) 306 | } 307 | } catch (e) { 308 | //打印错误信息 309 | console.log(e) 310 | } 311 | } 312 | 313 | //调用main() 314 | main() 315 | 316 | function Env(name) { 317 | return new class { 318 | constructor(name) { 319 | this.name = name 320 | this.startTime = Date.now() 321 | this.log(`[${this.name}]开始运行\n`, { time: true }) 322 | this.notifyStr = [] 323 | this.notifyFlag = true 324 | this.userIdx = 0 325 | this.userList = [] 326 | this.userCount = 0 327 | } 328 | log(msg, options = {}) { 329 | let opt = { console: true } 330 | Object.assign(opt, options) 331 | if (opt.time) { 332 | let fmt = opt.fmt || 'hh:mm:ss' 333 | msg = `[${this.time(fmt)}]` + msg 334 | } 335 | if (opt.notify) this.notifyStr.push(msg) 336 | if (opt.console) console.log(msg) 337 | } 338 | read_env(Class) { 339 | let envStrList = ckNames.map(x => process.env[x]) 340 | for (let env_str of envStrList.filter(x => !!x)) { 341 | let sp = envSplitor.filter(x => env_str.includes(x)) 342 | let splitor = sp.length > 0 ? sp[0] : envSplitor[0] 343 | for (let ck of env_str.split(splitor).filter(x => !!x)) { 344 | this.userList.push(new Class(ck)) 345 | } 346 | } 347 | this.userCount = this.userList.length 348 | if (!this.userCount) { 349 | this.log(`未找到变量,请检查变量${ckNames.map(x => '[' + x + ']').join('或')}`, { notify: true }) 350 | return false 351 | } 352 | this.log(`共找到${this.userCount}个账号`) 353 | return true 354 | } 355 | async threads(taskName, conf, opt = {}) { 356 | while (conf.idx < $.userList.length) { 357 | let user = $.userList[conf.idx++] 358 | if (!user.valid) continue 359 | await user[taskName](opt) 360 | } 361 | } 362 | async threadTask(taskName, thread) { 363 | let taskAll = [] 364 | let taskConf = { idx: 0 } 365 | while (thread--) taskAll.push(this.threads(taskName, taskConf)) 366 | await Promise.all(taskAll) 367 | } 368 | time(t, x = null) { 369 | let xt = x ? new Date(x) : new Date 370 | let e = { 371 | "M+": xt.getMonth() + 1, 372 | "d+": xt.getDate(), 373 | "h+": xt.getHours(), 374 | "m+": xt.getMinutes(), 375 | "s+": xt.getSeconds(), 376 | "q+": Math.floor((xt.getMonth() + 3) / 3), 377 | S: this.padStr(xt.getMilliseconds(), 3) 378 | }; 379 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (xt.getFullYear() + "").substr(4 - RegExp.$1.length))) 380 | for (let s in e) new RegExp("(" + s + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? e[s] : ("00" + e[s]).substr(("" + e[s]).length))) 381 | return t 382 | } 383 | async showmsg() { 384 | if (!this.notifyFlag) return 385 | if (!this.notifyStr.length) return 386 | var notify = require('./sendNotify') 387 | this.log('\n============== 推送 ==============') 388 | await notify.sendNotify(this.name, this.notifyStr.join('\n')) 389 | } 390 | padStr(num, length, opt = {}) { 391 | let padding = opt.padding || '0' 392 | let mode = opt.mode || 'l' 393 | let numStr = String(num) 394 | let numPad = (length > numStr.length) ? (length - numStr.length) : 0 395 | let pads = '' 396 | for (let i = 0; i < numPad; i++) { 397 | pads += padding 398 | } 399 | if (mode == 'r') { 400 | numStr = numStr + pads 401 | } else { 402 | numStr = pads + numStr 403 | } 404 | return numStr 405 | } 406 | json2str(obj, c, encode = false) { 407 | let ret = [] 408 | for (let keys of Object.keys(obj).sort()) { 409 | let v = obj[keys] 410 | if (v && encode) v = encodeURIComponent(v) 411 | ret.push(keys + '=' + v) 412 | } 413 | return ret.join(c) 414 | } 415 | str2json(str, decode = false) { 416 | let ret = {} 417 | for (let item of str.split('&')) { 418 | if (!item) continue 419 | let idx = item.indexOf('=') 420 | if (idx == -1) continue 421 | let k = item.substr(0, idx) 422 | let v = item.substr(idx + 1) 423 | if (decode) v = decodeURIComponent(v) 424 | ret[k] = v 425 | } 426 | return ret 427 | } 428 | randomPattern(pattern, charset = 'abcdef0123456789') { 429 | let str = '' 430 | for (let chars of pattern) { 431 | if (chars == 'x') { 432 | str += charset.charAt(Math.floor(Math.random() * charset.length)) 433 | } else if (chars == 'X') { 434 | str += charset.charAt(Math.floor(Math.random() * charset.length)).toUpperCase() 435 | } else { 436 | str += chars 437 | } 438 | } 439 | return str 440 | } 441 | randomString(len, charset = 'abcdef0123456789') { 442 | let str = '' 443 | for (let i = 0; i < len; i++) { 444 | str += charset.charAt(Math.floor(Math.random() * charset.length)) 445 | } 446 | return str 447 | } 448 | randomList(a) { 449 | let idx = Math.floor(Math.random() * a.length) 450 | return a[idx] 451 | } 452 | wait(t) { 453 | return new Promise(e => setTimeout(e, t)) 454 | } 455 | async exitNow() { 456 | await this.showmsg() 457 | let e = Date.now() 458 | let s = (e - this.startTime) / 1000 459 | this.log('') 460 | this.log(`[${this.name}]运行结束,共运行了${s}秒`, { time: true }) 461 | process.exit(0) 462 | } 463 | } 464 | (name) 465 | } -------------------------------------------------------------------------------- /leaf大佬教程/进阶.js: -------------------------------------------------------------------------------- 1 | /* 2 | 微信小程序 zippo会员中心 3 | 4 | 使用类来实现的版本, 包含了简单的类继承 5 | 6 | cron: 24 7,19 * * * 7 | */ 8 | const $ = new Env('zippo会员中心') 9 | const got = require('got') 10 | 11 | const envPrefix = 'zippo' 12 | const envSplitor = ['\n', '&', '@'] //支持多种分割,但要保证变量里不存在这个字符 13 | const ckNames = [envPrefix + 'Cookie'] //可以支持多变量 14 | 15 | const MAX_THREAD = parseInt(process.env[envPrefix + 'Thread']) || 50 //默认最大并发数 16 | const DEFAULT_TIMEOUT = 8000, DEFAULT_RETRY = 3 17 | 18 | //这里配置了一些常量, 不需要后面每次重新写了 19 | const default_UA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.32(0x1800202f) NetType/WIFI Language/zh_CN' 20 | const Referer = 'https://servicewechat.com/wxaa75ffd8c2d75da7/56/page-frame.html' 21 | const appid = 'wxaa75ffd8c2d75da7' 22 | 23 | class BasicClass { 24 | constructor() { 25 | this.index = $.userIdx++ 26 | this.name = '' 27 | this.valid = true 28 | 29 | //设置got的默认超时等参数 30 | this.got = got.extend({ 31 | retry: { limit: 0 }, 32 | timeout: DEFAULT_TIMEOUT, 33 | followRedirect: false, 34 | }) 35 | } 36 | //给每个账户打印前面加上自己的名字 37 | log(msg, opt = {}) { 38 | var m = '', n = $.userCount.toString().length;; 39 | if (this.index) m += `账号[${$.padStr(this.index, n)}]` 40 | if (this.name) m += `[${this.name}]` 41 | $.log(m + msg, opt) 42 | } 43 | //使用自己的got实例发包,可以实现设置每个账号自己的默认UA等 44 | async request(opt) { 45 | var resp = null, count = 0 46 | var fn = opt.fn || opt.url 47 | opt.method = opt?.method?.toUpperCase() || 'GET' 48 | while (count++ < DEFAULT_RETRY) { 49 | try { 50 | var err = null 51 | const errcodes = ['ECONNRESET', 'EADDRINUSE', 'ENOTFOUND', 'EAI_AGAIN'] 52 | await this.got(opt).then(t => { 53 | resp = t 54 | }, e => { 55 | err = e 56 | resp = e.response 57 | }) 58 | if (err) { 59 | if (err.name == 'TimeoutError') { 60 | this.log(`[${fn}]请求超时(${err.code}),重试第${count}次`) 61 | } else if (errcodes.includes(err.code)) { 62 | this.log(`[${fn}]请求错误(${err.code}),重试第${count}次`) 63 | } else { 64 | let statusCode = resp?.statusCode || -1 65 | this.log(`[${fn}]请求错误(${err.message}), 返回[${statusCode}]`) 66 | break 67 | } 68 | } else { 69 | break 70 | } 71 | } catch (e) { 72 | this.log(`[${fn}]请求错误(${e.message}),重试第${count}次`) 73 | }; 74 | } 75 | let { statusCode = -1, headers = null, body = null } = resp 76 | if (body) try { body = JSON.parse(body) } catch { }; 77 | return { statusCode, headers, result: body } 78 | } 79 | } 80 | let http = new BasicClass() 81 | 82 | class UserClass extends BasicClass { 83 | constructor(ck) { 84 | super() 85 | let info = ck.split('#') 86 | this.openid = info[0] 87 | this.session_key = decodeURIComponent(info[1]) 88 | this.point = 0 89 | 90 | this.got = this.got.extend({ 91 | headers: { 92 | Connection: 'keep-alive', 93 | 'User-Agent': default_UA, 94 | Referer, 95 | }, 96 | }) 97 | } 98 | 99 | async ininttask() { 100 | this.valid = false 101 | try { 102 | let options = { 103 | fn: 'ininttask', 104 | method: 'post', 105 | url: `https://membercenter.zippo.com.cn/s2/interface/data.aspx`, 106 | searchParams: { 107 | action: 'ininttask', 108 | }, 109 | form: { 110 | openid: this.openid, 111 | session_key: this.session_key, 112 | unionid: '', 113 | appid, 114 | }, 115 | } 116 | let { result } = await this.request(options) 117 | if (result?.errcode == 0) { 118 | this.valid = true 119 | for (let task of (result?.data?.task || [])) { 120 | switch (task.title) { 121 | case '签到': 122 | this.log(`今天${task.task_status == 0 ? '未' : '已'}签到`) 123 | if (task.task_status == 0) { 124 | await this.signin() 125 | } 126 | break 127 | default: 128 | let str = task.task_status == 0 ? '未完成' : (task.task_status == 1 ? '已完成未领取奖励' : '已领取奖励') 129 | this.log(`任务[${task.title}] -- ${str}`) 130 | switch (Number(task.task_status)) { 131 | case 0: 132 | await this.dotask(task, 1) 133 | //注意这里没有了break, 那么脚本会继续往下走直至遇到break, 也就是会自动执行 await this.dotask(task,2) 134 | case 1: 135 | await this.dotask(task, 2) 136 | break 137 | default: 138 | break 139 | } 140 | break 141 | } 142 | } 143 | } else { 144 | this.log(`查询账号任务失败`) 145 | } 146 | } catch (e) { 147 | console.log(e) 148 | } 149 | } 150 | 151 | async signin() { 152 | try { 153 | let options = { 154 | fn: 'signin', 155 | method: 'post', 156 | url: `https://membercenter.zippo.com.cn/s2/interface/data.aspx`, 157 | searchParams: { 158 | action: 'signin', 159 | }, 160 | form: { 161 | daykey: $.time('yyyyMMdd'), 162 | openid: this.openid, 163 | session_key: this.session_key, 164 | unionid: '', 165 | appid, 166 | }, 167 | } 168 | let { result } = await this.request(options) 169 | if (result?.errcode == 0) { 170 | this.log(`签到成功`) 171 | } else { 172 | this.log(`签到失败[${result?.errcode}]: ${result?.errmsg}`) 173 | } 174 | } catch (e) { 175 | console.log(e) 176 | } 177 | } 178 | 179 | async dotask(task, acttype) { 180 | try { 181 | let str = acttype == 1 ? '完成' : '领取奖励' 182 | let options = { 183 | fn: 'dotask', 184 | method: 'post', 185 | url: `https://membercenter.zippo.com.cn/s2/interface/data.aspx`, 186 | searchParams: { 187 | action: 'dotask', 188 | }, 189 | form: { 190 | taskid: task.taskid, 191 | acttype, 192 | openid: this.openid, 193 | session_key: this.session_key, 194 | unionid: '', 195 | appid, 196 | }, 197 | } 198 | let { result } = await this.request(options) 199 | if (result?.errcode == 0) { 200 | this.log(`任务[${task.title}]${str}成功`) 201 | } else { 202 | this.log(`任务[${task.title}]${str}失败[${result?.errcode}]: ${result?.errmsg}`) 203 | } 204 | } catch (e) { 205 | console.log(e) 206 | } 207 | } 208 | 209 | async inintmembers() { 210 | this.valid = false 211 | try { 212 | let options = { 213 | fn: 'inintmembers', 214 | method: 'post', 215 | url: `https://membercenter.zippo.com.cn/s2/interface/data.aspx`, 216 | searchParams: { 217 | action: 'inintmembers', 218 | }, 219 | form: { 220 | openid: this.openid, 221 | session_key: this.session_key, 222 | unionid: '', 223 | appid, 224 | }, 225 | } 226 | let { result } = await this.request(options) 227 | if (result?.errcode == 0) { 228 | this.valid = true 229 | let info = result?.data?.[0] 230 | if (info) { 231 | this.name = info.Mobile__c || '' 232 | this.point = info.AvailablePoints__c || 0 233 | } 234 | } else { 235 | this.log(`查询账号失败[${result?.errcode}]: ${result?.errmsg}`) 236 | } 237 | } catch (e) { 238 | console.log(e) 239 | } 240 | } 241 | 242 | //做任务逻辑 243 | async userTask() { 244 | $.log(`\n============= 账号[${this.index}] =============`) 245 | await this.inintmembers() 246 | if (!this.valid) return 247 | await this.ininttask() 248 | await this.inintmembers() 249 | this.log(`积分: ${this.point}`) 250 | } 251 | } 252 | 253 | !(async () => { 254 | $.log(`最大并发数: ${MAX_THREAD}`) 255 | $.log('') 256 | 257 | //封装的读取变量方法, 可以自己另外写也可以直接用, 读取到的账号会存入 $.userList 中 258 | $.read_env(UserClass) 259 | 260 | //正常的做任务流程 261 | for (let user of $.userList) { 262 | await user.userTask() 263 | } 264 | 265 | //封装的并发方法, 想试的把下面的//删掉 266 | //await $.threadTask('userTask',MAX_THREAD); 267 | 268 | })() 269 | .catch((e) => $.log(e)) 270 | .finally(() => $.exitNow()) 271 | 272 | function Env(name) { 273 | return new class { 274 | constructor(name) { 275 | this.name = name 276 | this.startTime = Date.now() 277 | this.log(`[${this.name}]开始运行\n`, { time: true }) 278 | this.notifyStr = [] 279 | this.notifyFlag = true 280 | this.userIdx = 0 281 | this.userList = [] 282 | this.userCount = 0 283 | } 284 | log(msg, options = {}) { 285 | let opt = { console: true } 286 | Object.assign(opt, options) 287 | if (opt.time) { 288 | let fmt = opt.fmt || 'hh:mm:ss' 289 | msg = `[${this.time(fmt)}]` + msg 290 | } 291 | if (opt.notify) this.notifyStr.push(msg) 292 | if (opt.console) console.log(msg) 293 | } 294 | read_env(Class) { 295 | let envStrList = ckNames.map(x => process.env[x]) 296 | for (let env_str of envStrList.filter(x => !!x)) { 297 | let sp = envSplitor.filter(x => env_str.includes(x)) 298 | let splitor = sp.length > 0 ? sp[0] : envSplitor[0] 299 | for (let ck of env_str.split(splitor).filter(x => !!x)) { 300 | this.userList.push(new Class(ck)) 301 | } 302 | } 303 | this.userCount = this.userList.length 304 | if (!this.userCount) { 305 | this.log(`未找到变量,请检查变量${ckNames.map(x => '[' + x + ']').join('或')}`, { notify: true }) 306 | return false 307 | } 308 | this.log(`共找到${this.userCount}个账号`) 309 | return true 310 | } 311 | async threads(taskName, conf, opt = {}) { 312 | while (conf.idx < $.userList.length) { 313 | let user = $.userList[conf.idx++] 314 | if (!user.valid) continue 315 | await user[taskName](opt) 316 | } 317 | } 318 | async threadTask(taskName, thread) { 319 | let taskAll = [] 320 | let taskConf = { idx: 0 } 321 | while (thread--) taskAll.push(this.threads(taskName, taskConf)) 322 | await Promise.all(taskAll) 323 | } 324 | time(t, x = null) { 325 | let xt = x ? new Date(x) : new Date 326 | let e = { 327 | "M+": xt.getMonth() + 1, 328 | "d+": xt.getDate(), 329 | "h+": xt.getHours(), 330 | "m+": xt.getMinutes(), 331 | "s+": xt.getSeconds(), 332 | "q+": Math.floor((xt.getMonth() + 3) / 3), 333 | S: this.padStr(xt.getMilliseconds(), 3) 334 | }; 335 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (xt.getFullYear() + "").substr(4 - RegExp.$1.length))) 336 | for (let s in e) new RegExp("(" + s + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? e[s] : ("00" + e[s]).substr(("" + e[s]).length))) 337 | return t 338 | } 339 | async showmsg() { 340 | if (!this.notifyFlag) return 341 | if (!this.notifyStr.length) return 342 | var notify = require('./sendNotify') 343 | this.log('\n============== 推送 ==============') 344 | await notify.sendNotify(this.name, this.notifyStr.join('\n')) 345 | } 346 | padStr(num, length, opt = {}) { 347 | let padding = opt.padding || '0' 348 | let mode = opt.mode || 'l' 349 | let numStr = String(num) 350 | let numPad = (length > numStr.length) ? (length - numStr.length) : 0 351 | let pads = '' 352 | for (let i = 0; i < numPad; i++) { 353 | pads += padding 354 | } 355 | if (mode == 'r') { 356 | numStr = numStr + pads 357 | } else { 358 | numStr = pads + numStr 359 | } 360 | return numStr 361 | } 362 | json2str(obj, c, encode = false) { 363 | let ret = [] 364 | for (let keys of Object.keys(obj).sort()) { 365 | let v = obj[keys] 366 | if (v && encode) v = encodeURIComponent(v) 367 | ret.push(keys + '=' + v) 368 | } 369 | return ret.join(c) 370 | } 371 | str2json(str, decode = false) { 372 | let ret = {} 373 | for (let item of str.split('&')) { 374 | if (!item) continue 375 | let idx = item.indexOf('=') 376 | if (idx == -1) continue 377 | let k = item.substr(0, idx) 378 | let v = item.substr(idx + 1) 379 | if (decode) v = decodeURIComponent(v) 380 | ret[k] = v 381 | } 382 | return ret 383 | } 384 | randomPattern(pattern, charset = 'abcdef0123456789') { 385 | let str = '' 386 | for (let chars of pattern) { 387 | if (chars == 'x') { 388 | str += charset.charAt(Math.floor(Math.random() * charset.length)) 389 | } else if (chars == 'X') { 390 | str += charset.charAt(Math.floor(Math.random() * charset.length)).toUpperCase() 391 | } else { 392 | str += chars 393 | } 394 | } 395 | return str 396 | } 397 | randomString(len, charset = 'abcdef0123456789') { 398 | let str = '' 399 | for (let i = 0; i < len; i++) { 400 | str += charset.charAt(Math.floor(Math.random() * charset.length)) 401 | } 402 | return str 403 | } 404 | randomList(a) { 405 | let idx = Math.floor(Math.random() * a.length) 406 | return a[idx] 407 | } 408 | wait(t) { 409 | return new Promise(e => setTimeout(e, t)) 410 | } 411 | async exitNow() { 412 | await this.showmsg() 413 | let e = Date.now() 414 | let s = (e - this.startTime) / 1000 415 | this.log('') 416 | this.log(`[${this.name}]运行结束,共运行了${s}秒`, { time: true }) 417 | process.exit(0) 418 | } 419 | } 420 | (name) 421 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "template", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "name": "template", 8 | "license": "ISC", 9 | "dependencies": { 10 | "crypto-js": "^4.0.0", 11 | "dotenv": "^16.0.0", 12 | "got": "^11.5.1", 13 | "tough-cookie": "^4.0.0" 14 | } 15 | }, 16 | "node_modules/@sindresorhus/is": { 17 | "version": "4.6.0", 18 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", 19 | "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", 20 | "engines": { 21 | "node": ">=10" 22 | }, 23 | "funding": { 24 | "url": "https://github.com/sindresorhus/is?sponsor=1" 25 | } 26 | }, 27 | "node_modules/@szmarczak/http-timer": { 28 | "version": "4.0.6", 29 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", 30 | "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", 31 | "dependencies": { 32 | "defer-to-connect": "^2.0.0" 33 | }, 34 | "engines": { 35 | "node": ">=10" 36 | } 37 | }, 38 | "node_modules/@types/cacheable-request": { 39 | "version": "6.0.3", 40 | "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", 41 | "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", 42 | "dependencies": { 43 | "@types/http-cache-semantics": "*", 44 | "@types/keyv": "^3.1.4", 45 | "@types/node": "*", 46 | "@types/responselike": "^1.0.0" 47 | } 48 | }, 49 | "node_modules/@types/http-cache-semantics": { 50 | "version": "4.0.1", 51 | "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", 52 | "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" 53 | }, 54 | "node_modules/@types/keyv": { 55 | "version": "3.1.4", 56 | "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", 57 | "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", 58 | "dependencies": { 59 | "@types/node": "*" 60 | } 61 | }, 62 | "node_modules/@types/node": { 63 | "version": "18.11.19", 64 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.19.tgz", 65 | "integrity": "sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw==" 66 | }, 67 | "node_modules/@types/responselike": { 68 | "version": "1.0.0", 69 | "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", 70 | "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", 71 | "dependencies": { 72 | "@types/node": "*" 73 | } 74 | }, 75 | "node_modules/cacheable-lookup": { 76 | "version": "5.0.4", 77 | "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", 78 | "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", 79 | "engines": { 80 | "node": ">=10.6.0" 81 | } 82 | }, 83 | "node_modules/cacheable-request": { 84 | "version": "7.0.2", 85 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", 86 | "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", 87 | "dependencies": { 88 | "clone-response": "^1.0.2", 89 | "get-stream": "^5.1.0", 90 | "http-cache-semantics": "^4.0.0", 91 | "keyv": "^4.0.0", 92 | "lowercase-keys": "^2.0.0", 93 | "normalize-url": "^6.0.1", 94 | "responselike": "^2.0.0" 95 | }, 96 | "engines": { 97 | "node": ">=8" 98 | } 99 | }, 100 | "node_modules/clone-response": { 101 | "version": "1.0.3", 102 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", 103 | "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", 104 | "dependencies": { 105 | "mimic-response": "^1.0.0" 106 | }, 107 | "funding": { 108 | "url": "https://github.com/sponsors/sindresorhus" 109 | } 110 | }, 111 | "node_modules/crypto-js": { 112 | "version": "4.1.1", 113 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", 114 | "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" 115 | }, 116 | "node_modules/decompress-response": { 117 | "version": "6.0.0", 118 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", 119 | "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", 120 | "dependencies": { 121 | "mimic-response": "^3.1.0" 122 | }, 123 | "engines": { 124 | "node": ">=10" 125 | }, 126 | "funding": { 127 | "url": "https://github.com/sponsors/sindresorhus" 128 | } 129 | }, 130 | "node_modules/decompress-response/node_modules/mimic-response": { 131 | "version": "3.1.0", 132 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", 133 | "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", 134 | "engines": { 135 | "node": ">=10" 136 | }, 137 | "funding": { 138 | "url": "https://github.com/sponsors/sindresorhus" 139 | } 140 | }, 141 | "node_modules/defer-to-connect": { 142 | "version": "2.0.1", 143 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", 144 | "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", 145 | "engines": { 146 | "node": ">=10" 147 | } 148 | }, 149 | "node_modules/dotenv": { 150 | "version": "16.0.3", 151 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", 152 | "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", 153 | "engines": { 154 | "node": ">=12" 155 | } 156 | }, 157 | "node_modules/end-of-stream": { 158 | "version": "1.4.4", 159 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 160 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 161 | "dependencies": { 162 | "once": "^1.4.0" 163 | } 164 | }, 165 | "node_modules/get-stream": { 166 | "version": "5.2.0", 167 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 168 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 169 | "dependencies": { 170 | "pump": "^3.0.0" 171 | }, 172 | "engines": { 173 | "node": ">=8" 174 | }, 175 | "funding": { 176 | "url": "https://github.com/sponsors/sindresorhus" 177 | } 178 | }, 179 | "node_modules/got": { 180 | "version": "11.8.6", 181 | "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", 182 | "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", 183 | "dependencies": { 184 | "@sindresorhus/is": "^4.0.0", 185 | "@szmarczak/http-timer": "^4.0.5", 186 | "@types/cacheable-request": "^6.0.1", 187 | "@types/responselike": "^1.0.0", 188 | "cacheable-lookup": "^5.0.3", 189 | "cacheable-request": "^7.0.2", 190 | "decompress-response": "^6.0.0", 191 | "http2-wrapper": "^1.0.0-beta.5.2", 192 | "lowercase-keys": "^2.0.0", 193 | "p-cancelable": "^2.0.0", 194 | "responselike": "^2.0.0" 195 | }, 196 | "engines": { 197 | "node": ">=10.19.0" 198 | }, 199 | "funding": { 200 | "url": "https://github.com/sindresorhus/got?sponsor=1" 201 | } 202 | }, 203 | "node_modules/http-cache-semantics": { 204 | "version": "4.1.1", 205 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", 206 | "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" 207 | }, 208 | "node_modules/http2-wrapper": { 209 | "version": "1.0.3", 210 | "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", 211 | "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", 212 | "dependencies": { 213 | "quick-lru": "^5.1.1", 214 | "resolve-alpn": "^1.0.0" 215 | }, 216 | "engines": { 217 | "node": ">=10.19.0" 218 | } 219 | }, 220 | "node_modules/json-buffer": { 221 | "version": "3.0.1", 222 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", 223 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" 224 | }, 225 | "node_modules/keyv": { 226 | "version": "4.5.2", 227 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", 228 | "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", 229 | "dependencies": { 230 | "json-buffer": "3.0.1" 231 | } 232 | }, 233 | "node_modules/lowercase-keys": { 234 | "version": "2.0.0", 235 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 236 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", 237 | "engines": { 238 | "node": ">=8" 239 | } 240 | }, 241 | "node_modules/mimic-response": { 242 | "version": "1.0.1", 243 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 244 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 245 | "engines": { 246 | "node": ">=4" 247 | } 248 | }, 249 | "node_modules/normalize-url": { 250 | "version": "6.1.0", 251 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", 252 | "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", 253 | "engines": { 254 | "node": ">=10" 255 | }, 256 | "funding": { 257 | "url": "https://github.com/sponsors/sindresorhus" 258 | } 259 | }, 260 | "node_modules/once": { 261 | "version": "1.4.0", 262 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 263 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 264 | "dependencies": { 265 | "wrappy": "1" 266 | } 267 | }, 268 | "node_modules/p-cancelable": { 269 | "version": "2.1.1", 270 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", 271 | "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", 272 | "engines": { 273 | "node": ">=8" 274 | } 275 | }, 276 | "node_modules/psl": { 277 | "version": "1.9.0", 278 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", 279 | "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" 280 | }, 281 | "node_modules/pump": { 282 | "version": "3.0.0", 283 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 284 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 285 | "dependencies": { 286 | "end-of-stream": "^1.1.0", 287 | "once": "^1.3.1" 288 | } 289 | }, 290 | "node_modules/punycode": { 291 | "version": "2.3.0", 292 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 293 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", 294 | "engines": { 295 | "node": ">=6" 296 | } 297 | }, 298 | "node_modules/querystringify": { 299 | "version": "2.2.0", 300 | "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", 301 | "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" 302 | }, 303 | "node_modules/quick-lru": { 304 | "version": "5.1.1", 305 | "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", 306 | "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", 307 | "engines": { 308 | "node": ">=10" 309 | }, 310 | "funding": { 311 | "url": "https://github.com/sponsors/sindresorhus" 312 | } 313 | }, 314 | "node_modules/requires-port": { 315 | "version": "1.0.0", 316 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 317 | "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" 318 | }, 319 | "node_modules/resolve-alpn": { 320 | "version": "1.2.1", 321 | "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", 322 | "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" 323 | }, 324 | "node_modules/responselike": { 325 | "version": "2.0.1", 326 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", 327 | "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", 328 | "dependencies": { 329 | "lowercase-keys": "^2.0.0" 330 | }, 331 | "funding": { 332 | "url": "https://github.com/sponsors/sindresorhus" 333 | } 334 | }, 335 | "node_modules/tough-cookie": { 336 | "version": "4.1.2", 337 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", 338 | "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", 339 | "dependencies": { 340 | "psl": "^1.1.33", 341 | "punycode": "^2.1.1", 342 | "universalify": "^0.2.0", 343 | "url-parse": "^1.5.3" 344 | }, 345 | "engines": { 346 | "node": ">=6" 347 | } 348 | }, 349 | "node_modules/universalify": { 350 | "version": "0.2.0", 351 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", 352 | "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", 353 | "engines": { 354 | "node": ">= 4.0.0" 355 | } 356 | }, 357 | "node_modules/url-parse": { 358 | "version": "1.5.10", 359 | "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", 360 | "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", 361 | "dependencies": { 362 | "querystringify": "^2.1.1", 363 | "requires-port": "^1.0.0" 364 | } 365 | }, 366 | "node_modules/wrappy": { 367 | "version": "1.0.2", 368 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 369 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 370 | } 371 | }, 372 | "dependencies": { 373 | "@sindresorhus/is": { 374 | "version": "4.6.0", 375 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", 376 | "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==" 377 | }, 378 | "@szmarczak/http-timer": { 379 | "version": "4.0.6", 380 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", 381 | "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", 382 | "requires": { 383 | "defer-to-connect": "^2.0.0" 384 | } 385 | }, 386 | "@types/cacheable-request": { 387 | "version": "6.0.3", 388 | "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", 389 | "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", 390 | "requires": { 391 | "@types/http-cache-semantics": "*", 392 | "@types/keyv": "^3.1.4", 393 | "@types/node": "*", 394 | "@types/responselike": "^1.0.0" 395 | } 396 | }, 397 | "@types/http-cache-semantics": { 398 | "version": "4.0.1", 399 | "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", 400 | "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" 401 | }, 402 | "@types/keyv": { 403 | "version": "3.1.4", 404 | "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", 405 | "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", 406 | "requires": { 407 | "@types/node": "*" 408 | } 409 | }, 410 | "@types/node": { 411 | "version": "18.11.19", 412 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.19.tgz", 413 | "integrity": "sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw==" 414 | }, 415 | "@types/responselike": { 416 | "version": "1.0.0", 417 | "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", 418 | "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", 419 | "requires": { 420 | "@types/node": "*" 421 | } 422 | }, 423 | "cacheable-lookup": { 424 | "version": "5.0.4", 425 | "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", 426 | "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==" 427 | }, 428 | "cacheable-request": { 429 | "version": "7.0.2", 430 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", 431 | "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", 432 | "requires": { 433 | "clone-response": "^1.0.2", 434 | "get-stream": "^5.1.0", 435 | "http-cache-semantics": "^4.0.0", 436 | "keyv": "^4.0.0", 437 | "lowercase-keys": "^2.0.0", 438 | "normalize-url": "^6.0.1", 439 | "responselike": "^2.0.0" 440 | } 441 | }, 442 | "clone-response": { 443 | "version": "1.0.3", 444 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", 445 | "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", 446 | "requires": { 447 | "mimic-response": "^1.0.0" 448 | } 449 | }, 450 | "crypto-js": { 451 | "version": "4.1.1", 452 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", 453 | "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" 454 | }, 455 | "decompress-response": { 456 | "version": "6.0.0", 457 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", 458 | "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", 459 | "requires": { 460 | "mimic-response": "^3.1.0" 461 | }, 462 | "dependencies": { 463 | "mimic-response": { 464 | "version": "3.1.0", 465 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", 466 | "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" 467 | } 468 | } 469 | }, 470 | "defer-to-connect": { 471 | "version": "2.0.1", 472 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", 473 | "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" 474 | }, 475 | "dotenv": { 476 | "version": "16.0.3", 477 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", 478 | "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" 479 | }, 480 | "end-of-stream": { 481 | "version": "1.4.4", 482 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 483 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 484 | "requires": { 485 | "once": "^1.4.0" 486 | } 487 | }, 488 | "get-stream": { 489 | "version": "5.2.0", 490 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 491 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 492 | "requires": { 493 | "pump": "^3.0.0" 494 | } 495 | }, 496 | "got": { 497 | "version": "11.8.6", 498 | "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", 499 | "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", 500 | "requires": { 501 | "@sindresorhus/is": "^4.0.0", 502 | "@szmarczak/http-timer": "^4.0.5", 503 | "@types/cacheable-request": "^6.0.1", 504 | "@types/responselike": "^1.0.0", 505 | "cacheable-lookup": "^5.0.3", 506 | "cacheable-request": "^7.0.2", 507 | "decompress-response": "^6.0.0", 508 | "http2-wrapper": "^1.0.0-beta.5.2", 509 | "lowercase-keys": "^2.0.0", 510 | "p-cancelable": "^2.0.0", 511 | "responselike": "^2.0.0" 512 | } 513 | }, 514 | "http-cache-semantics": { 515 | "version": "4.1.1", 516 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", 517 | "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" 518 | }, 519 | "http2-wrapper": { 520 | "version": "1.0.3", 521 | "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", 522 | "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", 523 | "requires": { 524 | "quick-lru": "^5.1.1", 525 | "resolve-alpn": "^1.0.0" 526 | } 527 | }, 528 | "json-buffer": { 529 | "version": "3.0.1", 530 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", 531 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" 532 | }, 533 | "keyv": { 534 | "version": "4.5.2", 535 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", 536 | "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", 537 | "requires": { 538 | "json-buffer": "3.0.1" 539 | } 540 | }, 541 | "lowercase-keys": { 542 | "version": "2.0.0", 543 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 544 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" 545 | }, 546 | "mimic-response": { 547 | "version": "1.0.1", 548 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 549 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" 550 | }, 551 | "normalize-url": { 552 | "version": "6.1.0", 553 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", 554 | "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" 555 | }, 556 | "once": { 557 | "version": "1.4.0", 558 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 559 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 560 | "requires": { 561 | "wrappy": "1" 562 | } 563 | }, 564 | "p-cancelable": { 565 | "version": "2.1.1", 566 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", 567 | "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" 568 | }, 569 | "psl": { 570 | "version": "1.9.0", 571 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", 572 | "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" 573 | }, 574 | "pump": { 575 | "version": "3.0.0", 576 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 577 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 578 | "requires": { 579 | "end-of-stream": "^1.1.0", 580 | "once": "^1.3.1" 581 | } 582 | }, 583 | "punycode": { 584 | "version": "2.3.0", 585 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 586 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" 587 | }, 588 | "querystringify": { 589 | "version": "2.2.0", 590 | "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", 591 | "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" 592 | }, 593 | "quick-lru": { 594 | "version": "5.1.1", 595 | "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", 596 | "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" 597 | }, 598 | "requires-port": { 599 | "version": "1.0.0", 600 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 601 | "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" 602 | }, 603 | "resolve-alpn": { 604 | "version": "1.2.1", 605 | "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", 606 | "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" 607 | }, 608 | "responselike": { 609 | "version": "2.0.1", 610 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", 611 | "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", 612 | "requires": { 613 | "lowercase-keys": "^2.0.0" 614 | } 615 | }, 616 | "tough-cookie": { 617 | "version": "4.1.2", 618 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", 619 | "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", 620 | "requires": { 621 | "psl": "^1.1.33", 622 | "punycode": "^2.1.1", 623 | "universalify": "^0.2.0", 624 | "url-parse": "^1.5.3" 625 | } 626 | }, 627 | "universalify": { 628 | "version": "0.2.0", 629 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", 630 | "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==" 631 | }, 632 | "url-parse": { 633 | "version": "1.5.10", 634 | "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", 635 | "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", 636 | "requires": { 637 | "querystringify": "^2.1.1", 638 | "requires-port": "^1.0.0" 639 | } 640 | }, 641 | "wrappy": { 642 | "version": "1.0.2", 643 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 644 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 645 | } 646 | } 647 | } 648 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "template", 3 | "author": "yml-23/2/5", 4 | "license": "ISC", 5 | "dependencies": { 6 | "crypto-js": "^4.0.0", 7 | "dotenv": "^16.0.0", 8 | "got": "^11.5.1", 9 | "tough-cookie": "^4.0.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /旧/jc-old2.js: -------------------------------------------------------------------------------- 1 | /* 2 | 诗画浦江 app 3 | 4 | cron 10 8,10 * * * shpj.js 5 | 6 | ========= 青龙--配置文件--贴心复制区域 ========= 7 | # 诗画浦江 8 | export shpj=' x-session-id & x-request-id ' 9 | 10 | 11 | 多账号用 换行 或 @ 分割 12 | tg频道: https://t.me/yml2213_tg 13 | */ 14 | 15 | 16 | const utils = require("yml2213-utils") 17 | const $ = new Env("诗画浦江") // 1.名字改了 18 | const ckName = "shpj" // 2. 英文名字改一下 19 | //-------------------- 一般不动变量区域 ------------------------------------- // 3. 不用管 20 | const notify = $.isNode() ? require("../sendNotify") : "" 21 | const Notify = 1 //0为关闭通知,1为打开通知,默认为1 22 | let envSplitor = ["@", "\n"] 23 | let ck = msg = '' 24 | let host, hostname 25 | let userCookie = process.env[ckName] 26 | let userList = [] 27 | let userIdx = 0 28 | let userCount = 0 29 | //---------------------- 自定义变量区域 ----------------------------------- // 4. 要杀变量自己加 30 | 31 | let app_id = 14 32 | let text = sign = '' 33 | //--------------------------------------------------------- 34 | 35 | async function start() { // 5. 开始任务区域 自己按照格式加 36 | 37 | 38 | console.log('\n================== 用户信息 ==================\n') 39 | taskall = [] 40 | for (let user of userList) { 41 | taskall.push(user.user_info('用户信息')) 42 | } 43 | await Promise.all(taskall) 44 | 45 | console.log('\n================== 任务列表 ==================\n') 46 | taskall = [] 47 | for (let user of userList) { 48 | taskall.push(user.task_list('任务列表')) 49 | } 50 | await Promise.all(taskall) 51 | 52 | 53 | 54 | } 55 | 56 | // 6. 一整个class 就是完整的任务 57 | class UserInfo { 58 | constructor(str) { // 7. 构造函数 处理变量等 用 this 挂在对象上 59 | this.index = ++userIdx 60 | this.ck = str.split('&') 61 | this.xs = this.ck[0] 62 | this.xr = this.ck[1] 63 | this.salt = 'FR*r!isE5W' 64 | this.id = app_id 65 | this.ts = utils.ts13() 66 | } 67 | 68 | 69 | // 8. 每个函数实现一个功能 70 | async signin(name) { //签到 71 | let path = '/api/user_mumber/sign' 72 | let sign = this.get_sign(path) 73 | 74 | let options = { //9. 就是组成请求的数据 75 | method: "Get", 76 | url: `https://vapp.tmuyun.com${path}`, // 9. url 77 | headers: { // 9. headers 78 | "X-SESSION-ID": this.xs, 79 | "X-REQUEST-ID": this.xr, 80 | "X-TIMESTAMP": this.ts, 81 | "X-SIGNATURE": sign, 82 | "Cache-Control": `no-cache`, 83 | "X-TENANT-ID": `14`, 84 | 'Host': 'vapp.tmuyun.com', 85 | }, 86 | } 87 | 88 | // console.log(options); 89 | let result = await httpRequest(name, options) // 10. 请求返回 result 90 | 91 | // console.log(result); 92 | if (result.code == 0) { // 11. 返回 result判断 93 | DoubleLog(`账号[${this.index}] ${name}" ${result.data.reason}, 获得积分 ${result.data.signIntegral}`) 94 | await utils.wait(3) 95 | } else DoubleLog(`账号[${this.index}] ${name} 失败❌了呢`), console.log(result) 96 | 97 | 98 | 99 | 100 | } 101 | 102 | 103 | async user_info(name) { // 用户信息 104 | let path = '/api/user_mumber/account_detail' 105 | let sign = this.get_sign(path) 106 | 107 | let options = { 108 | method: "Get", 109 | url: `https://vapp.tmuyun.com${path}`, 110 | headers: { 111 | "X-SESSION-ID": this.xs, 112 | "X-REQUEST-ID": this.xr, 113 | "X-TIMESTAMP": this.ts, 114 | "X-SIGNATURE": sign, 115 | "Cache-Control": `no-cache`, 116 | "X-TENANT-ID": `14`, 117 | 'Host': 'vapp.tmuyun.com', 118 | }, 119 | } 120 | 121 | // console.log(options); 122 | let result = await httpRequest(name, options) 123 | 124 | // console.log(result); 125 | if (result.code == 0) { 126 | DoubleLog(`账号[${this.index}] ${result.data.rst.nick_name}, 手机号: ${utils.phone_num(result.data.rst.mobile)}, 积分 ${result.data.rst.total_integral}, 等级 ${result.data.rst.grade} ${result.data.rst.grade_name}`) 127 | this.nickname = result.data.rst.nick_name 128 | 129 | } else DoubleLog(`账号[${this.index}] ${name} 失败❌了呢`), console.log(result) 130 | 131 | 132 | 133 | 134 | } 135 | 136 | // 任务列表 completed 0 未完成 1 完成 137 | async task_list(name) { 138 | let path = '/api/user_mumber/numberCenter' 139 | let sign = this.get_sign(path) 140 | 141 | let options = { 142 | method: "Get", 143 | url: `https://vapp.tmuyun.com${path}`, 144 | headers: { 145 | "X-SESSION-ID": this.xs, 146 | "X-REQUEST-ID": this.xr, 147 | "X-TIMESTAMP": this.ts, 148 | "X-SIGNATURE": sign, 149 | "Cache-Control": `no-cache`, 150 | "X-TENANT-ID": `14`, 151 | 'Host': 'vapp.tmuyun.com', 152 | }, 153 | } 154 | 155 | // console.log(options); 156 | let result = await httpRequest(name, options) 157 | 158 | // console.log(result); 159 | if (result.code == 0) { 160 | let tasks = result.data.rst.user_task_list 161 | // console.log(tasks); 162 | for (const task of tasks) { // completed 0 未完成 1 完成 163 | this.task_name = task.name 164 | this.finish_times = task.finish_times 165 | this.frequency = task.frequency 166 | if (task.completed == 0) { 167 | if (task.id == 133) { // 每日签到 168 | DoubleLog(`账号 ${this.nickname} : ${this.task_name}----${this.finish_times}/${this.frequency}`) 169 | await this.signin(this.task_name) 170 | } 171 | if (task.id == 134) { // 新闻资讯阅读 172 | DoubleLog(`账号 ${this.nickname} : ${this.task_name}----${this.finish_times}/${this.frequency}`) 173 | let num = this.frequency - this.finish_times 174 | for (let index = 0; index < num; index++) { 175 | await this.read(this.task_name) 176 | } 177 | } 178 | if (task.id == 135) { // 分享资讯给好友 179 | DoubleLog(`账号 ${this.nickname} : ${this.task_name}----${this.finish_times}/${this.frequency}`) 180 | let num = this.frequency - this.finish_times 181 | for (let index = 0; index < num; index++) { 182 | await this.share(this.task_name) 183 | } 184 | } 185 | if (task.id == 136) { // 新闻资讯评论 186 | DoubleLog(`账号 ${this.nickname} : ${this.task_name}----${this.finish_times}/${this.frequency}`) 187 | let num = this.frequency - this.finish_times 188 | for (let index = 0; index < num; index++) { 189 | await this.comment(this.task_name) 190 | } 191 | } 192 | if (task.id == 137) { // 新闻资讯点赞 193 | DoubleLog(`账号 ${this.nickname} : ${this.task_name}----${this.finish_times}/${this.frequency}`) 194 | let num = this.frequency - this.finish_times 195 | for (let index = 0; index < num; index++) { 196 | await this.like(this.task_name) 197 | } 198 | } 199 | if (task.id == 138) { // 使用本地服务 200 | DoubleLog(`账号 ${this.nickname} : ${this.task_name}----${this.finish_times}/${this.frequency}`) 201 | await this.local_srv(this.task_name) 202 | } 203 | 204 | } else DoubleLog(`${this.task_name}: 已完成`) 205 | } 206 | 207 | } else DoubleLog(`账号[${this.index}] ${name} 失败❌了呢`), console.log(result) 208 | } 209 | 210 | 211 | async artic(name) { // 获取文章 212 | let path = '/api/article/channel_list' 213 | let sign = this.get_sign(path) 214 | let a = utils.randomInt(1, 5) 215 | 216 | let options = { 217 | method: "Get", 218 | url: `https://vapp.tmuyun.com${path}?channel_id=5cc2ccbe1b011b18ee37591d&isDiFangHao=false&is_new=true&list_count=${a * 10}&size=10&start=${this.ts}`, 219 | headers: { 220 | "X-SESSION-ID": this.xs, 221 | "X-REQUEST-ID": this.xr, 222 | "X-TIMESTAMP": this.ts, 223 | "X-SIGNATURE": sign, 224 | "Cache-Control": `no-cache`, 225 | "X-TENANT-ID": `14`, 226 | 'Host': 'vapp.tmuyun.com', 227 | }, 228 | } 229 | 230 | // console.log(options); 231 | let result = await httpRequest(name, options) 232 | 233 | // console.log(result); 234 | if (result.code == 0) { 235 | DoubleLog(`账号[${this.index}] ${name}, ok`) 236 | let p = utils.randomInt(0, 9) 237 | this.rid = result.data.article_list[p].id 238 | } else DoubleLog(`账号[${this.index}] ${name} 失败❌了呢`), console.log(result) 239 | } 240 | 241 | async read(name) { // 新闻资讯阅读 242 | await this.artic('获取文章') 243 | 244 | let path = '/api/article/detail' 245 | let sign = this.get_sign(path) 246 | 247 | let options = { 248 | method: "Get", 249 | url: `https://vapp.tmuyun.com${path}?id=${this.rid}`, 250 | headers: { 251 | "X-SESSION-ID": this.xs, 252 | "X-REQUEST-ID": this.xr, 253 | "X-TIMESTAMP": this.ts, 254 | "X-SIGNATURE": sign, 255 | "Cache-Control": `no-cache`, 256 | "X-TENANT-ID": `14`, 257 | 'Host': 'vapp.tmuyun.com', 258 | }, 259 | } 260 | let result = await httpRequest(name, options) 261 | 262 | // console.log(result); 263 | if (result.code == 0) { 264 | DoubleLog(`账号[${this.index}] ${name}, 文章ID${this.rid} ${result.data.article.list_title}`) 265 | await wait(3) 266 | } else DoubleLog(`账号[${this.index}] ${name} 失败❌了呢`), console.log(result) 267 | } 268 | 269 | async share(name) { // 分享资讯给好友 270 | await this.artic('获取文章') 271 | 272 | let path = '/api/user_mumber/doTask' 273 | let sign = this.get_sign(path) 274 | 275 | let options = { 276 | method: "POST", 277 | url: `https://vapp.tmuyun.com${path}`, 278 | headers: { 279 | "X-SESSION-ID": this.xs, 280 | "X-REQUEST-ID": this.xr, 281 | "X-TIMESTAMP": this.ts, 282 | "X-SIGNATURE": sign, 283 | "Cache-Control": `no-cache`, 284 | "X-TENANT-ID": `14`, 285 | 'Host': 'vapp.tmuyun.com', 286 | "Content-Type": `application/x-www-form-urlencoded`, 287 | }, 288 | form: { 289 | 'memberType': '3', 290 | 'member_type': '3' 291 | } 292 | } 293 | let result = await httpRequest(name, options) 294 | 295 | // console.log(result); 296 | if (result.code == 0) { 297 | DoubleLog(`账号[${this.index}] ${name} :文章ID ${this.rid}, ok}`) 298 | await wait(3) 299 | } else DoubleLog(`账号[${this.index}] ${name} 失败❌了呢`), console.log(result) 300 | } 301 | 302 | async comment(name) { // 新闻资讯评论 303 | await this.artic('获取文章') 304 | 305 | let path = '/api/comment/create' 306 | let sign = this.get_sign(path) 307 | 308 | let options = { 309 | method: "POST", 310 | url: `https://vapp.tmuyun.com${path}`, 311 | headers: { 312 | "X-SESSION-ID": this.xs, 313 | "X-REQUEST-ID": this.xr, 314 | "X-TIMESTAMP": this.ts, 315 | "X-SIGNATURE": sign, 316 | "Cache-Control": `no-cache`, 317 | "X-TENANT-ID": `14`, 318 | 'Host': 'vapp.tmuyun.com', 319 | "Content-Type": `application/x-www-form-urlencoded`, 320 | }, 321 | form: { 322 | 'channel_article_id': this.rid, 323 | 'content': 1 324 | } 325 | } 326 | let result = await httpRequest(name, options) 327 | 328 | // console.log(result); 329 | if (result.code == 0) { 330 | DoubleLog(`账号[${this.index}] ${name} :文章ID ${this.rid}, ok}`) 331 | await wait(3) 332 | } else DoubleLog(`账号[${this.index}] ${name} 失败❌了呢`), console.log(result) 333 | } 334 | 335 | async like(name) { // 新闻资讯点赞 336 | await this.artic('获取文章') 337 | 338 | let path = '/api/favorite/like' 339 | let sign = this.get_sign(path) 340 | 341 | let options = { 342 | method: "POST", 343 | url: `https://vapp.tmuyun.com${path}`, 344 | headers: { 345 | "X-SESSION-ID": this.xs, 346 | "X-REQUEST-ID": this.xr, 347 | "X-TIMESTAMP": this.ts, 348 | "X-SIGNATURE": sign, 349 | "Cache-Control": `no-cache`, 350 | "X-TENANT-ID": `14`, 351 | 'Host': 'vapp.tmuyun.com', 352 | "Content-Type": `application/x-www-form-urlencoded`, 353 | }, 354 | form: { 355 | 'id': this.rid, 356 | 'action': true 357 | } 358 | } 359 | let result = await httpRequest(name, options) 360 | 361 | // console.log(result); 362 | if (result.code == 0) { 363 | DoubleLog(`账号[${this.index}] ${name} :文章ID ${this.rid}, ok}`) 364 | await wait(3) 365 | } else DoubleLog(`账号[${this.index}] ${name} 失败❌了呢`), console.log(result) 366 | } 367 | 368 | async local_srv(name) { // 使用本地服务 369 | await this.artic('获取文章') 370 | 371 | let path = '/api/user_mumber/doTas' 372 | let sign = this.get_sign(path) 373 | 374 | let options = { 375 | method: "POST", 376 | url: `https://vapp.tmuyun.com${path}`, 377 | headers: { 378 | "X-SESSION-ID": this.xs, 379 | "X-REQUEST-ID": this.xr, 380 | "X-TIMESTAMP": this.ts, 381 | "X-SIGNATURE": sign, 382 | "Cache-Control": `no-cache`, 383 | "X-TENANT-ID": `14`, 384 | 'Host': 'vapp.tmuyun.com', 385 | "Content-Type": `application/x-www-form-urlencoded`, 386 | }, 387 | form: { 388 | 'memberType': 6, 389 | 'member_type': 6 390 | } 391 | } 392 | let result = await httpRequest(name, options) 393 | 394 | // console.log(result); 395 | if (result.code == 0) { 396 | DoubleLog(`账号[${this.index}] ${name} : 成功 获得 ${result.data.score_notify.integral} 积分`) 397 | await wait(3) 398 | } else DoubleLog(`账号[${this.index}] ${name} 失败❌了呢`), console.log(result) 399 | } 400 | 401 | 402 | 403 | get_sign(path) { 404 | let _data = `${path}&&${this.xs}&&${this.xr}&&${this.ts}&&${this.salt}&&${this.id}` 405 | // console.log('_data: ', _data); 406 | sign = utils.SHA256_Encrypt(_data) 407 | return sign 408 | } 409 | 410 | 411 | 412 | 413 | } 414 | 415 | !(async () => { 416 | if (!(await checkEnv())) return 417 | if (userList.length > 0) { 418 | await start() 419 | } 420 | await SendMsg(msg) 421 | })() 422 | .catch((e) => console.log(e)) 423 | .finally(() => $.done()) 424 | 425 | 426 | 427 | // 下面的不用管了 全默认就行 记得装 yml2213-utils 依赖 428 | // #region ******************************************************** 固定代码 ******************************************************** 429 | 430 | 431 | // 变量检查与处理 432 | async function checkEnv() { 433 | if (userCookie) { 434 | // console.log(userCookie); 435 | let e = envSplitor[0] 436 | for (let o of envSplitor) 437 | if (userCookie.indexOf(o) > -1) { 438 | e = o 439 | break 440 | } 441 | for (let n of userCookie.split(e)) n && userList.push(new UserInfo(n)) 442 | userCount = userList.length 443 | } else { 444 | console.log("未找到CK") 445 | return 446 | } 447 | return console.log(`共找到${userCount}个账号`), !0 448 | } 449 | 450 | 451 | 452 | // =========================================== 不懂不要动 ========================================================= 453 | function Env(name, e) { class s { constructor(name) { this.env = name } } return new (class { constructor(name) { (this.name = name), (this.logs = []), (this.startTime = new Date().getTime()), this.log(`\n🔔${this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } log(...name) { name.length > 0 && (this.logs = [...this.logs, ...name]), console.log(name.join(this.logSeparator)) } done() { const e = new Date().getTime(), s = (e - this.startTime) / 1e3; this.log(`\n🔔${this.name}, 结束! 🕛 ${s} 秒`) } })(name, e) } async function httpRequest(name, options) { if (!name) { name = /function\s*(\w*)/i.exec(arguments.callee.toString())[1] } try { let result = await utils.httpRequest(name, options); if (result) { return result } { DoubleLog(`未知错误(1)`) } } catch (error) { console.log(error) } } async function SendMsg(message) { if (!message) return; if (Notify > 0) { if ($.isNode()) { var notify = require("../sendNotify"); await notify.sendNotify($.name, message) } else { console.log($.name, "", message) } } else { console.log(message) } } function wait(n) { return new Promise(function (resolve) { setTimeout(resolve, n * 1000) }) } function DoubleLog(data) { console.log(` ${data}`); msg += `\n ${data}` } 454 | 455 | -------------------------------------------------------------------------------- /旧/jiaocheng_old1.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 教程 3 | * 地址: https://raw.githubusercontent.com/yml2213/template/master/jiaocheng.js 4 | * 5 | * 教程 这里是写脚本说明的地方 6 | * 本脚本仅用于学习使用请勿直接运行 7 | * 8 | * ========= 青龙 ========= 9 | * 变量格式:export jiaocheng_data=' xxxx & xxx @ xxxx & xxx ' 多个账号用 @分割 10 | * 11 | */ 12 | 13 | const jsname = "教程"; 14 | const $ = Env(jsname); 15 | const notify = $.isNode() ? require('./sendNotify') : ''; // 这里是 node(青龙属于node环境)通知相关的 16 | const Notify = 1; //0为关闭通知,1为打开通知,默认为1 17 | const debug = 1; //0为关闭调试,1为打开调试,默认为0 18 | ////////////////////// 19 | let jiaocheng_data = process.env.jiaocheng_data; // 这里是 从青龙的 配置文件 读取你写的变量 20 | let jiaocheng_dataArr = []; 21 | let data = ''; 22 | let msg = ''; 23 | 24 | 25 | !(async () => { 26 | 27 | if (!(await Envs())) //多账号分割 判断变量是否为空 初步处理多账号 28 | return; 29 | else { 30 | 31 | console.log(`本地脚本4-11 )`); // console.log是输出信息的,可以在脚本日志中看到输出(打印)的信息 32 | 33 | console.log(`\n\n========================================= \n脚本执行 - 北京时间(UTC+8):${new Date( 34 | new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + 35 | 8 * 60 * 60 * 1000).toLocaleString()} \n=========================================\n`); 36 | 37 | await wyy(); 38 | 39 | console.log(`\n=================== 共找到 ${jiaocheng_dataArr.length} 个账号 ===================`) 40 | 41 | if (debug) { 42 | console.log(`【debug】 这是你的全部账号数组:\n ${jiaocheng_dataArr}`); 43 | } 44 | 45 | 46 | for (let index = 0; index < jiaocheng_dataArr.length; index++) { 47 | 48 | 49 | let num = index + 1 50 | console.log(`\n========= 开始【第 ${num} 个账号】=========\n`) 51 | 52 | data = jiaocheng_dataArr[index].split('&'); // 这里是分割你每个账号的每个小项 53 | 54 | if (debug) { 55 | console.log(`\n 【debug】 这是你第 ${num} 账号信息:\n ${data}\n`); 56 | } 57 | 58 | 59 | // 这里是开始做任务 需要注意的点 60 | // 1. await只能运行与async函数中 61 | // 2. 函数的名字不可以相同 62 | // 3. 不够可以自己复制 63 | 64 | console.log('开始 xx'); 65 | await signin(); 66 | await $.wait(2 * 1000); 67 | 68 | // 这里是开始做任务 69 | console.log('开始 yy'); 70 | await yyyy(); 71 | await $.wait(2 * 1000); 72 | 73 | 74 | // 这里是开始做任务 75 | console.log('开始 zz'); 76 | await zzzzz(); 77 | await $.wait(2 * 1000); 78 | 79 | 80 | 81 | await SendMsg(msg); // 与发送通知有关系 82 | } 83 | } 84 | 85 | })() 86 | .catch((e) => console.logErr(e)) 87 | .finally(() => $.done()) 88 | 89 | 90 | 91 | 92 | 93 | 94 | /** 95 | * 签到 骁友会 96 | * 下面我们来看看函数需要注意的东西吧 97 | */ 98 | function signin(timeout = 3 * 1000) { 99 | return new Promise((resolve) => { 100 | let url = { 101 | url: `https://qualcomm.growthideadata.com/qualcomm-app/api/user/signIn?userId=${data[1]}`, // 这是请求的 url 可以直接用我们抓包、精简后的URL 102 | headers: { // headers 是请求体 可以直接用精简后的 hd 也就是服务器校验的部分,他需要啥,我们就给他啥 103 | 104 | "userId": data[1], 105 | "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", 106 | "Host": "qualcomm.growthideadata.com", 107 | "User-Agent": UA, 108 | "sessionKey": data[0], 109 | "Referer": "https://servicewechat.com/wx026c06df6adc5d06/176/page-frame.html", 110 | "Connection": "keep-alive" 111 | }, 112 | // body: '', // 这是一个 get 请求,没有请求体 body 如果是 post 不要忘记他鸭! 113 | 114 | } 115 | 116 | if (debug) { 117 | console.log(`\n【debug】=============== 这是 签到 请求 url ===============`); 118 | console.log(JSON.stringify(url)); 119 | } 120 | 121 | $.get(url, async (error, response, data) => { // 这是一个 get 请求 , 如果是 post 记得把这里改了 122 | try { 123 | if (debug) { 124 | console.log(`\n\n【debug】===============这是 签到 返回data==============`); 125 | console.log(data) 126 | } 127 | 128 | let result = JSON.parse(data); 129 | if (result.code == 200) { // 这里是根据服务器返回的数据做判断 方便我们知道任务是否完成了 130 | 131 | console.log(`【签到】${result.message} 🎉 `) 132 | msg += `\n【签到】${result.message} 🎉` 133 | 134 | } else if (result.code === 1) { // 这里是根据服务器返回的数据做判断 方便我们知道任务是否完成了 135 | 136 | console.log(`\n【签到】 失败 ,可能是:${result.message}!\n `) 137 | 138 | 139 | } else if (result.code === 40001) { // 这里是根据服务器返回的数据做判断 方便我们知道任务是否完成了 140 | 141 | console.log(`\n【签到】 失败 ,可能是:${result.message}!\n `) 142 | 143 | 144 | } else { // 这里是根据服务器返回的数据做判断 方便我们知道任务是否完成了 145 | 146 | console.log(`\n【签到】 失败 ❌ 了呢,可能是网络被外星人抓走了!\n `) 147 | 148 | 149 | } 150 | 151 | } catch (e) { 152 | console.log(e) 153 | } finally { 154 | resolve(); 155 | } 156 | }, timeout) 157 | }) 158 | } 159 | 160 | 161 | 162 | 163 | // 如果有更多的需求,直接复制上一个函数,改个名 然后稍微更改一下内容 就可以用了 164 | // 不要忘记与上面的 函数调用对应起来鸭 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | //#region 固定代码 可以不管他 180 | // ============================================变量检查============================================ \\ 181 | async function Envs() { 182 | if (jiaocheng_data) { 183 | if (jiaocheng_data.indexOf("@") != -1) { 184 | jiaocheng_data.split("@").forEach((item) => { 185 | jiaocheng_dataArr.push(item); 186 | }); 187 | } else { 188 | jiaocheng_dataArr.push(jiaocheng_data); 189 | } 190 | } else { 191 | console.log(`\n 【${$.name}】:未填写变量 jiaocheng_data`) 192 | return; 193 | } 194 | 195 | return true; 196 | } 197 | 198 | // ============================================发送消息============================================ \\ 199 | async function SendMsg(message) { 200 | if (!message) 201 | return; 202 | 203 | if (Notify > 0) { 204 | if ($.isNode()) { 205 | var notify = require('./sendNotify'); 206 | await notify.sendNotify($.name, message); 207 | } else { 208 | $.msg(message); 209 | } 210 | } else { 211 | console.log(message); 212 | } 213 | } 214 | 215 | /** 216 | * 随机数生成 217 | */ 218 | function randomString(e) { 219 | e = e || 32; 220 | var t = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890", 221 | a = t.length, 222 | n = ""; 223 | for (i = 0; i < e; i++) 224 | n += t.charAt(Math.floor(Math.random() * a)); 225 | return n 226 | } 227 | 228 | /** 229 | * 随机整数生成 230 | */ 231 | function randomInt(min, max) { 232 | return Math.round(Math.random() * (max - min) + min) 233 | } 234 | 235 | //每日网抑云 236 | function wyy(timeout = 3 * 1000) { 237 | return new Promise((resolve) => { 238 | let url = { 239 | url: `https://keai.icu/apiwyy/api` 240 | } 241 | $.get(url, async (err, resp, data) => { 242 | try { 243 | data = JSON.parse(data) 244 | console.log(`\n 【网抑云时间】: ${data.content} by--${data.music}`); 245 | 246 | } catch (e) { 247 | console.logErr(e, resp); 248 | } finally { 249 | resolve() 250 | } 251 | }, timeout) 252 | }) 253 | } 254 | 255 | //#endregion 256 | 257 | 258 | // prettier-ignore 固定代码 不用管他 259 | function Env(t, e) { "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise((e, i) => { s.call(this, t, (t, s, r) => { t ? i(t) : e(s) }) }) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const i = this.getdata(t); if (i) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise(e => { this.get({ url: t }, (t, s, i) => e(i)) }) } runScript(t, e) { return new Promise(s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; const [o, h] = i.split("@"), n = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; this.post(n, (t, e, i) => s(i)) }).catch(t => this.logErr(t)) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let r = t; for (const t of i) if (r = Object(r)[t], void 0 === r) return s; return r } lodash_set(t, e, s) { return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t) } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; try { const e = JSON.parse(h); this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const o = {}; this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) } } else s = this.setval(t, e); return s } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, e) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } }).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) })) } post(t, e = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.post(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) }); else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: s, ...i } = t; this.got.post(s, i).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) }) } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } msg(e = t, s = "", i = "", r) { const o = t => { if (!t) return t; if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; if ("object" == typeof t) { if (this.isLoon()) { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } if (this.isQuanX()) { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; return { "open-url": e, "media-url": s } } if (this.isSurge()) { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } } }; if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { let t = ["", "==============📣系统通知📣=============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) } 260 | -------------------------------------------------------------------------------- /毛1/esljsb.js: -------------------------------------------------------------------------------- 1 | /* 2 | 二三里极速版 app cron 25 6-23 * * * esljsb.js 3 | 4 | 5 | 23/1/30 基本任务 6 | 7 | ------------------- 青龙-配置文件-复制区域 ------------------- 8 | # 二三里极速版 9 | export esljsb=" phone # pwd @ phone # pwd " 10 | 11 | 多账号用 换行 或 @ 分割 12 | tg频道: https://t.me/yml2213_tg 13 | */ 14 | const $ = Env('二三里极速版') 15 | const notify = require('./sendNotify') 16 | const crypto = require('crypto-js') 17 | 18 | const envSplitor = ['\n', '&', '@'] //支持多种分割,但要保证变量里不存在这个字符 19 | const ckNames = ['esljsb'] //支持多变量 20 | //==================================================================================================== 21 | let DEFAULT_RETRY = 1 // 默认重试次数 22 | //==================================================================================================== 23 | 24 | 25 | 26 | 27 | async function userTasks() { 28 | 29 | $.log('用户信息', { sp: true, console: false }) // 带分割的打印 30 | list = [] 31 | for (let user of $.userList) { 32 | list.push(user.login()) 33 | } await Promise.all(list) 34 | 35 | 36 | $.log('任务列表', { sp: true, console: false }) 37 | list = [] 38 | for (let user of $.userList) { 39 | if (user.ckFlog) { 40 | list.push(user.tasklist()) 41 | // list.push(user.sleep()) 42 | } 43 | } await Promise.all(list) 44 | 45 | $.log('走路赚豆', { sp: true, console: false }) 46 | list = [] 47 | if ($.ts('h') == 18) { 48 | for (let user of $.userList) { 49 | if (user.ckFlog) { 50 | let a = ['10', '1000', '3000', '5000', '7000', '10000'] 51 | for (let index = 0; index < a.length; index++) { 52 | list.push(user.lifeTask(a[index])) 53 | } 54 | } 55 | } await Promise.all(list) 56 | } else $.log(`走路赚豆--时间不对, 跳过!`) 57 | 58 | $.log('吃饭赚豆', { sp: true, console: false }) 59 | list = [] 60 | for (let user of $.userList) { 61 | if (user.ckFlog) { 62 | list.push(user.eat()) 63 | } 64 | } await Promise.all(list) 65 | 66 | 67 | $.log('睡觉赚豆', { sp: true, console: false }) 68 | list = [] 69 | for (let user of $.userList) { 70 | if (user.ckFlog) { 71 | list.push(user.sleep()) 72 | } 73 | } await Promise.all(list) 74 | 75 | $.log('开宝箱', { sp: true, console: false }) 76 | list = [] 77 | for (let user of $.userList) { 78 | if (user.ckFlog) { 79 | list.push(user.openBox()) 80 | } 81 | } await Promise.all(list) 82 | 83 | 84 | $.log('里豆查询', { sp: true, console: false }) 85 | list = [] 86 | for (let user of $.userList) { 87 | if (user.ckFlog) { 88 | list.push(user.check()) 89 | } 90 | } await Promise.all(list) 91 | 92 | 93 | 94 | } 95 | 96 | 97 | class UserClass { 98 | constructor(ck) { 99 | this.idx = `账号[${++$.userIdx}]` 100 | this.ckFlog = true 101 | this.ck = ck.split('#') 102 | this.phone = this.ck[0] 103 | this.pwd = crypto.MD5(crypto.MD5(this.ck[1]).toString()).toString() 104 | this.rs = `${$.randomString(8)}-${$.randomString(4)}-${$.randomString(4)}-${$.randomString(4)}-${$.randomString(12)}` 105 | this.hd = { 'User-Agent': 'oke/3.2.8' } 106 | 107 | this.appVersion = '3.2.8' // 3.2.8 极速版 7.2.9 正式版 108 | this.ts = $.ts(10) 109 | this.salt = 'x3pbkWjH4EiBPbRi1DYKgIiuS9ehOCOk0DkqREOIvffOYtAOQvRXkvmvhe9j13QoT3aOsTP/Y6wLlDhg97RhYnt4y23zgd5AV+UiNgerlmwCjWclOwwf1IvZYX4nAjOdCkGgRAboiU+Gh+UvW+CnXjjFx26vk4Y91Mztq8SjCvCwoaQGHXxfy0VxmsS85BBV3E39Ak12n/EcV+/ihk9uIQwqc3BlvR8miZTGh2EesqSqKm+RiwWAQpYrhaWuN9Zc' 110 | this.deviceId = 'cf873feaf4509842ae76beec9df158f973633ad268db50cbc22206ba1f98185d' 111 | this.appId = '2' // 2 极速版 1 正式版 112 | this.location = '371681' // 371681 极速版 371601 正式版 113 | 114 | } 115 | 116 | 117 | async login() { // 登录 118 | let params = { 119 | 'name': this.phone, 120 | 'password': this.pwd, 121 | 'clientType': '3', 122 | 'deviceId': this.deviceId, 123 | 'appId': this.appId, 124 | 'appVersion': this.appVersion, 125 | 'osVersion': '12', 126 | 'timestamp': this.ts, 127 | 'nonce_str': this.rs, 128 | 'location': this.location, 129 | } 130 | params.sign = await this.getSign(params) 131 | // console.log(params) 132 | 133 | let options = { 134 | fn: '登录', 135 | method: 'post', 136 | url: `https://api.ersanli.cn/kilos/apis/passport/login.action`, 137 | headers: this.hd, 138 | form: params 139 | } 140 | // console.log(options) 141 | let resp = await $.request(options) 142 | // console.log(resp) 143 | if (resp.code == 'A00000') { 144 | this.userCookie = resp.data.userCookie 145 | this.nickname = resp.data.userInfo.name 146 | $.log(`${this.idx}: ${options.fn} ${resp.msg}, ${this.nickname}, 手机号 ${$.phoneNum(resp.data.userInfo.mobile)}`, { notify: true }) 147 | this.ckFlog = true 148 | await $.wait(2) 149 | } else console.log(`${options.fn}: 失败, ${JSON.stringify(resp)}`), this.ckFlog = false 150 | 151 | } 152 | 153 | async tasklist() { // 任务列表 154 | let params = { 155 | 'userCookie': this.userCookie, 156 | 'clientType': '3', 157 | 'deviceId': this.deviceId, 158 | 'appId': this.appId, 159 | 'appVersion': this.appVersion, 160 | 'osVersion': '12', 161 | 'timestamp': this.ts, 162 | 'nonce_str': this.rs, 163 | 'location': this.location, 164 | } 165 | params.sign = await this.getSign(params) 166 | 167 | let options = { 168 | fn: '任务列表', 169 | method: 'post', 170 | url: `https://api.ersanli.cn/kilos/apis/user/task.action`, 171 | headers: this.hd, 172 | form: params 173 | } 174 | // console.log(options) 175 | let resp = await $.request(options) 176 | // console.log(resp) 177 | if (resp.code == 'A00000') { 178 | 179 | let tasks = resp.taskList 180 | for (const task of tasks) { 181 | // console.log(task) 182 | let { taskId, taskName, currentCount, maxCount } = task 183 | 184 | if (currentCount < maxCount) { 185 | if (taskId == 1) $.log(`${this.idx}: ${taskName}--${currentCount}/${maxCount}`), await this.doSign() // 每日签到 186 | if (taskId == 11) $.log(`${this.idx}: ${taskName}--${currentCount}/${maxCount}`), await this.jsb(taskName) // 往正式版 - 领取100里豆 187 | if (taskId == 2) { // 浏览文章 188 | let n = maxCount - currentCount 189 | $.log(`${this.idx}: ${taskName}--${currentCount}/${maxCount}`) 190 | for (let index = 0; index < n; index++) await this.read(taskName) 191 | } 192 | 193 | } else { 194 | $.log(`${this.idx}: ${taskName} 已完成`) 195 | } 196 | } 197 | 198 | } else console.log(`${options.fn}: 失败, ${JSON.stringify(resp)}`) 199 | 200 | } 201 | 202 | async doSign() { // 签到 203 | let params = { 204 | 'userCookie': this.userCookie, 205 | 'areaCode': this.location, 206 | 'clientType': '3', 207 | 'deviceId': this.deviceId, 208 | 'appId': this.appId, 209 | 'appVersion': this.appVersion, 210 | 'osVersion': '12', 211 | 'timestamp': this.ts, 212 | 'nonce_str': this.rs, 213 | 'location': this.location, 214 | } 215 | params.sign = await this.getSign(params) 216 | let options = { 217 | fn: '签到', 218 | method: 'post', 219 | url: `https://api.ersanli.cn/kilos/apis/user/sign.action`, 220 | headers: this.hd, 221 | form: params 222 | } 223 | // console.log(options) 224 | let resp = await $.request(options) 225 | // console.log(resp) 226 | if (resp.code == 'A00000') { 227 | $.log(`${this.idx}: ${resp.msg}, 签到第 ${resp.data.sign} 天, 获得里豆 ${resp.data.money}`) 228 | } else if (resp.code == 'A00007') { 229 | $.log(`${this.idx}: ${resp.msg}`) 230 | } else console.log(`${options.fn}: 失败, ${JSON.stringify(resp)}`) 231 | 232 | } 233 | 234 | async jsb(name) { // 正式版 235 | let params = { 236 | 'userCookie': this.userCookie, 237 | 'areaCode': this.location, 238 | 'from': 'jsb', 239 | 'clientType': '3', 240 | 'deviceId': this.deviceId, 241 | 'appId': this.appId, 242 | 'appVersion': this.appVersion, 243 | 'osVersion': '12', 244 | 'timestamp': this.ts, 245 | 'nonce_str': this.rs, 246 | 'location': this.location, 247 | } 248 | params.sign = await this.getSign(params) 249 | let options = { 250 | fn: '正式版', 251 | method: 'post', 252 | url: `https://api.ersanli.cn/kilos/apis/user/sign.action`, 253 | headers: this.hd, 254 | form: params 255 | } 256 | // console.log(options) 257 | let resp = await $.request(options) 258 | // console.log(resp) 259 | if (resp.code == 'A00000') { 260 | $.log(`${this.idx}: ${name}${resp.msg}`) 261 | } else console.log(`${options.fn}: 失败, ${JSON.stringify(resp)}`) 262 | 263 | } 264 | 265 | async read(name) { // 阅读 266 | let newsId = $.randomInt(123870142596668, 123870142599999) 267 | let params = { 268 | 'userCookie': this.userCookie, 269 | 'newsId': newsId, 270 | 'clientType': '3', 271 | 'deviceId': this.deviceId, 272 | 'appId': this.appId, 273 | 'appVersion': this.appVersion, 274 | 'osVersion': '12', 275 | 'timestamp': this.ts, 276 | 'nonce_str': this.rs, 277 | 'location': this.location, 278 | } 279 | params.sign = await this.getSign(params) 280 | 281 | let options = { 282 | fn: '阅读', 283 | method: 'post', 284 | url: `https://api.ersanli.cn/kilos/apis/news/read.action`, 285 | headers: this.hd, 286 | form: params 287 | } 288 | // console.log(options) 289 | let resp = await $.request(options) 290 | // console.log(resp) 291 | if (resp.code == 'A00000') { 292 | $.log(`${this.idx}: ${name} ${newsId}--${resp.msg}`) 293 | await $.wait($.randomInt(3, 6)) 294 | } else console.log(`${options.fn}: 失败, ${JSON.stringify(resp)}`) 295 | 296 | } 297 | 298 | async openBox() { // 开宝箱 299 | let params = { 300 | 'userCookie': this.userCookie, 301 | 'clientType': '3', 302 | 'deviceId': this.deviceId, 303 | 'appId': this.appId, 304 | 'appVersion': this.appVersion, 305 | 'osVersion': '12', 306 | 'timestamp': this.ts, 307 | 'nonce_str': this.rs, 308 | 'location': this.location, 309 | } 310 | params.sign = await this.getSign(params) 311 | 312 | let options = { 313 | fn: '开宝箱', 314 | method: 'post', 315 | url: `https://api.ersanli.cn/kilos/apis/user/teapot_open.action`, 316 | headers: this.hd, 317 | form: params 318 | } 319 | // console.log(options) 320 | let resp = await $.request(options) 321 | // console.log(resp) 322 | if (resp.code == 'A00000') { 323 | $.log(`${this.idx}: ${options.fn}, ${resp.msg}`) 324 | } else if (resp.code == 'E00003') { 325 | $.log(`${this.idx}: ${resp.msg}`) 326 | } else console.log(`${options.fn}: 失败, ${JSON.stringify(resp)}`) 327 | 328 | } 329 | 330 | async lifeTask(names) { // 走路赚豆 331 | let params = { 332 | 'userCookie': this.userCookie, 333 | 'names': names, 334 | 'type': '3', 335 | 'clientType': '3', 336 | 'deviceId': this.deviceId, 337 | 'appId': this.appId, 338 | 'appVersion': this.appVersion, 339 | 'osVersion': '12', 340 | 'timestamp': this.ts, 341 | 'nonce_str': this.rs, 342 | 'location': this.location, 343 | } 344 | params.sign = await this.getSign(params) 345 | let options = { 346 | fn: '走路赚豆', 347 | method: 'post', 348 | url: `https://api.ersanli.cn/kilos/apis/user/life_task.action`, 349 | headers: this.hd, 350 | form: params 351 | } 352 | // console.log(options) 353 | let resp = await $.request(options) 354 | // console.log(resp) 355 | if (resp.code == 'A00000') { 356 | $.log(`${this.idx}: ${options.fn} 领取 ${names} 步--${resp.msg}`) 357 | await $.wait($.randomInt(5, 10)) 358 | } else if (resp.code == 'E00001') { 359 | $.log(`${this.idx}: 领取 ${names} 步--${resp.msg}`) 360 | } else console.log(`${options.fn}: 失败, ${JSON.stringify(resp)}`) 361 | 362 | } 363 | 364 | async eat() { // 吃饭赚豆调度 365 | let h = $.ts('h') 366 | if (h >= 7 && h < 10) { 367 | await this.life_eat('早餐补贴') 368 | } else if (h >= 12 && h < 14) { 369 | await this.life_eat('午餐补贴') 370 | } else if (h >= 18 && h < 19) { 371 | await this.life_eat('晚餐补贴') 372 | } else if (h >= 22 && h < 23) { 373 | await this.life_eat('夜宵补贴') 374 | } else { 375 | $.log(`${this.idx}: 吃饭赚豆--时间不对, 跳过!`) 376 | } 377 | 378 | } 379 | 380 | async life_eat(name) { // 吃饭赚豆 381 | let params = { 382 | 'userCookie': this.userCookie, 383 | 'name': name, 384 | 'type': '1', 385 | 'clientType': '3', 386 | 'deviceId': this.deviceId, 387 | 'appId': this.appId, 388 | 'appVersion': this.appVersion, 389 | 'osVersion': '12', 390 | 'timestamp': this.ts, 391 | 'nonce_str': this.rs, 392 | 'location': this.location, 393 | } 394 | params.sign = await this.getSign(params) 395 | params.name = encodeURI(name) 396 | 397 | let options = { 398 | fn: '吃饭赚豆', 399 | method: 'post', 400 | url: `https://api.ersanli.cn/kilos/apis/user/life_task.action`, 401 | headers: this.hd, 402 | form: params 403 | } 404 | console.log(options) 405 | let resp = await $.request(options) 406 | console.log(resp) 407 | if (resp.code == 'A00000') { 408 | $.log(`${this.idx}: ${options.fn} 领取 ${name} --${resp.msg}`) 409 | await $.wait($.randomInt(5, 10)) 410 | } else if (resp.code == 'E00001' || resp.code == 'E00002') { 411 | $.log(`${this.idx}: 领取 ${name} 步--${resp.msg}`) 412 | } else console.log(`${options.fn}: 失败, ${JSON.stringify(resp)}`) 413 | 414 | } 415 | 416 | async sleep() { // 睡觉赚豆调度 417 | let h = $.ts('h') 418 | if (h >= 20 && h < 4) { 419 | $.log(`${this.idx}: 休息时间, 检查是否 休息!`) 420 | await this.sleepCheck('休息') 421 | 422 | } else if (h >= 12 && h < 14) { 423 | $.log(`${this.idx}: 午休时间, 检查是否 午休!`) 424 | await this.sleepCheck('午休') 425 | } else { 426 | $.log(`${this.idx}: 不在午休或睡觉时间, 跳过!`) 427 | } 428 | if (h == 8) { 429 | await this.sleepCheck('休息') 430 | } 431 | 432 | } 433 | 434 | async sleepCheck(name) { // 睡觉检查 435 | let params = { 436 | 'userCookie': this.userCookie, 437 | 'type': '2', 438 | 'clientType': '3', 439 | 'deviceId': this.deviceId, 440 | 'appId': this.appId, 441 | 'appVersion': this.appVersion, 442 | 'osVersion': '12', 443 | 'timestamp': this.ts, 444 | 'nonce_str': this.rs, 445 | 'location': this.location, 446 | } 447 | params.sign = await this.getSign(params) 448 | 449 | 450 | let options = { 451 | fn: '睡觉检查', 452 | method: 'post', 453 | url: `https://api.ersanli.cn/kilos/apis/user/life_task.action`, 454 | headers: this.hd, 455 | form: params 456 | } 457 | // console.log(options) 458 | let resp = await $.request(options) 459 | // console.log(resp) 460 | if (resp.code == 'A00000') { 461 | if (name == '休息') { 462 | if (!resp.data[0].sleepStatus) await this.doSleep(name) 463 | } 464 | if (name == '午休') { 465 | if (!resp.data[1].sleepStatus) await this.doSleep(name) 466 | } 467 | 468 | } else console.log(`${options.fn}: 失败, ${JSON.stringify(resp)}`) 469 | 470 | } 471 | 472 | async doSleep(name) { // 睡觉 -- 休息 473 | let params = { 474 | 'userCookie': this.userCookie, 475 | 'name': name, 476 | 'type': '2', 477 | 'clientType': '3', 478 | 'deviceId': this.deviceId, 479 | 'appId': this.appId, 480 | 'appVersion': this.appVersion, 481 | 'osVersion': '12', 482 | 'timestamp': this.ts, 483 | 'nonce_str': this.rs, 484 | 'location': this.location, 485 | } 486 | params.sign = await this.getSign(params) 487 | params.name = encodeURI(name) 488 | 489 | let options = { 490 | fn: '休息', 491 | method: 'post', 492 | url: `https://api.ersanli.cn/kilos/apis/user/life_task.action`, 493 | headers: this.hd, 494 | form: params 495 | } 496 | // console.log(options) 497 | let resp = await $.request(options) 498 | // console.log(resp) 499 | if (resp.code == 'A00000') { 500 | $.log(`${this.idx}: ${name}--${resp.msg}`) 501 | await $.wait($.randomInt(5, 10)) 502 | } else console.log(`${options.fn}: 失败, ${JSON.stringify(resp)}`) 503 | 504 | } 505 | 506 | async check() { // 查询 507 | let params = { 508 | 'userCookie': this.userCookie, 509 | 'clientType': '3', 510 | 'deviceId': this.deviceId, 511 | 'appId': this.appId, 512 | 'appVersion': this.appVersion, 513 | 'osVersion': '12', 514 | 'timestamp': this.ts, 515 | 'nonce_str': this.rs, 516 | 'location': this.location, 517 | } 518 | params.sign = await this.getSign(params) 519 | 520 | let options = { 521 | fn: '查询', 522 | method: 'post', 523 | url: `https://api.ersanli.cn/kilos/apis/user/wallet.action`, 524 | headers: this.hd, 525 | form: params 526 | } 527 | // console.log(options) 528 | let resp = await $.request(options) 529 | // console.log(resp) 530 | if (resp.code == 'A00000') { 531 | $.log(`${this.idx}: ${this.nickname}, 共有豆豆 ${resp.data.gold}个, 今天获得 ${resp.data.withdrawToday}`, { notify: true }) 532 | } else console.log(`${options.fn}: 失败, ${JSON.stringify(resp)}`) 533 | 534 | } 535 | 536 | 537 | 538 | async getSign(params) { 539 | delete params.sign 540 | let a = new URLSearchParams(Object.entries(params)).toString() 541 | let sign = crypto.MD5(`${crypto.MD5(a).toString()}${this.salt}`).toString() 542 | return sign 543 | } 544 | 545 | 546 | } 547 | 548 | 549 | !(async () => { 550 | console.log(await $.yiyan()) 551 | $.read_env(UserClass) 552 | 553 | await userTasks() 554 | 555 | })() 556 | .catch((e) => $.log(e)) 557 | .finally(() => $.exitNow()) 558 | 559 | 560 | 561 | //=============================================================== 562 | function Env(name) { 563 | return new class { 564 | constructor(name) { 565 | this.name = name 566 | this.startTime = Date.now() 567 | this.log(`[${this.name}]开始运行`, { time: true }) 568 | 569 | this.notifyStr = [] 570 | this.notifyFlag = true 571 | 572 | this.userIdx = 0 573 | this.userList = [] 574 | this.userCount = 0 575 | } 576 | async request(opt) { 577 | const got = require('got') 578 | let DEFAULT_TIMEOUT = 8000 // 默认超时时间 579 | let resp = null, count = 0 580 | let fn = opt.fn || opt.url 581 | let resp_opt = opt.resp_opt || 'body' 582 | opt.timeout = opt.timeout || DEFAULT_TIMEOUT 583 | opt.retry = opt.retry || { limit: 0 } 584 | opt.method = opt?.method?.toUpperCase() || 'GET' 585 | while (count++ < DEFAULT_RETRY) { 586 | try { 587 | resp = await got(opt) 588 | break 589 | } catch (e) { 590 | if (e.name == 'TimeoutError') { 591 | this.log(`[${fn}]请求超时,重试第${count}次`) 592 | } else { 593 | this.log(`[${fn}]请求错误(${e.message}),重试第${count}次`) 594 | } 595 | } 596 | } 597 | if (resp == null) return Promise.resolve({ statusCode: 'timeout', headers: null, body: null }) 598 | let { statusCode, headers, body } = resp 599 | if (body) try { body = JSON.parse(body) } catch { } 600 | if (resp_opt == 'body') { 601 | return Promise.resolve(body) 602 | } else if (resp_opt == 'hd') { 603 | return Promise.resolve(headers) 604 | } else if (resp_opt == 'statusCode') { 605 | return Promise.resolve(statusCode) 606 | } 607 | 608 | } 609 | 610 | log(msg, options = {}) { 611 | let opt = { console: true } 612 | Object.assign(opt, options) 613 | 614 | if (opt.time) { 615 | let fmt = opt.fmt || 'hh:mm:ss' 616 | msg = `[${this.time(fmt)}]` + msg 617 | } 618 | if (opt.notify) { 619 | this.notifyStr.push(msg) 620 | } 621 | if (opt.console) { 622 | console.log(msg) 623 | } 624 | if (opt.sp) { 625 | console.log(`\n-------------- ${msg} --------------`) 626 | } 627 | } 628 | read_env(Class) { 629 | let envStrList = ckNames.map(x => process.env[x]) 630 | for (let env_str of envStrList.filter(x => !!x)) { 631 | let sp = envSplitor.filter(x => env_str.includes(x)) 632 | let splitor = sp.length > 0 ? sp[0] : envSplitor[0] 633 | for (let ck of env_str.split(splitor).filter(x => !!x)) { 634 | this.userList.push(new Class(ck)) 635 | } 636 | } 637 | this.userCount = this.userList.length 638 | if (!this.userCount) { 639 | this.log(`未找到变量,请检查变量${ckNames.map(x => '[' + x + ']').join('或')}`, { notify: true }) 640 | return false 641 | } 642 | this.log(`共找到${this.userCount}个账号`) 643 | return true 644 | } 645 | async taskThread(taskName, conf, opt = {}) { 646 | while (conf.idx < $.userList.length) { 647 | let user = $.userList[conf.idx++] 648 | await user[taskName](opt) 649 | } 650 | } 651 | async threadManager(taskName, thread) { 652 | let taskAll = [] 653 | let taskConf = { idx: 0 } 654 | while (thread--) { 655 | taskAll.push(this.taskThread(taskName, taskConf)) 656 | } 657 | await Promise.all(taskAll) 658 | } 659 | time(t, x = null) { 660 | let xt = x ? new Date(x) : new Date 661 | let e = { 662 | "M+": xt.getMonth() + 1, 663 | "d+": xt.getDate(), 664 | "h+": xt.getHours(), 665 | "m+": xt.getMinutes(), 666 | "s+": xt.getSeconds(), 667 | "q+": Math.floor((xt.getMonth() + 3) / 3), 668 | S: this.padStr(xt.getMilliseconds(), 3) 669 | }; 670 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (xt.getFullYear() + "").substr(4 - RegExp.$1.length))) 671 | for (let s in e) 672 | new RegExp("(" + s + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? e[s] : ("00" + e[s]).substr(("" + e[s]).length))) 673 | return t 674 | } 675 | async showmsg() { 676 | if (!this.notifyFlag) return 677 | if (!this.notifyStr) return 678 | let notify = require('./sendNotify') 679 | this.log('\n============== 推送 ==============') 680 | await notify.sendNotify(this.name, this.notifyStr.join('\n')) 681 | } 682 | padStr(num, length, opt = {}) { 683 | let padding = opt.padding || '0' 684 | let mode = opt.mode || 'l' 685 | let numStr = String(num) 686 | let numPad = (length > numStr.length) ? (length - numStr.length) : 0 687 | let pads = '' 688 | for (let i = 0; i < numPad; i++) { 689 | pads += padding 690 | } 691 | if (mode == 'r') { 692 | numStr = numStr + pads 693 | } else { 694 | numStr = pads + numStr 695 | } 696 | return numStr 697 | } 698 | json2str(obj, c, encode = false) { 699 | let ret = [] 700 | for (let keys of Object.keys(obj).sort()) { 701 | let v = obj[keys] 702 | if (v && encode) v = encodeURIComponent(v) 703 | ret.push(keys + '=' + v) 704 | } 705 | return ret.join(c) 706 | } 707 | str2json(str, decode = false) { 708 | let ret = {} 709 | for (let item of str.split('&')) { 710 | if (!item) continue 711 | let idx = item.indexOf('=') 712 | if (idx == -1) continue 713 | let k = item.substr(0, idx) 714 | let v = item.substr(idx + 1) 715 | if (decode) v = decodeURIComponent(v) 716 | ret[k] = v 717 | } 718 | return ret 719 | } 720 | phoneNum(phone_num) { 721 | if (phone_num.length == 11) { 722 | let data = phone_num.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2") 723 | return data 724 | } else { 725 | return phone_num 726 | } 727 | } 728 | randomInt(min, max) { 729 | return Math.round(Math.random() * (max - min) + min) 730 | } 731 | async yiyan() { 732 | const got = require('got') 733 | return new Promise((resolve) => { 734 | (async () => { 735 | try { 736 | const response = await got('https://v1.hitokoto.cn') 737 | // console.log(response.body) 738 | let data = JSON.parse(response.body) 739 | let data_ = `[一言]: ${data.hitokoto} by--${data.from}` 740 | // console.log(data_) 741 | resolve(data_) 742 | } catch (error) { 743 | console.log(error.response.body) 744 | } 745 | })() 746 | }) 747 | } 748 | ts(type = false, _data = "") { 749 | let myDate = new Date() 750 | let a = "" 751 | switch (type) { 752 | case 10: 753 | a = Math.round(new Date().getTime() / 1000).toString() 754 | break 755 | case 13: 756 | a = Math.round(new Date().getTime()).toString() 757 | break 758 | case "h": 759 | a = myDate.getHours() 760 | break 761 | case "m": 762 | a = myDate.getMinutes() 763 | break 764 | case "y": 765 | a = myDate.getFullYear() 766 | break 767 | case "h": 768 | a = myDate.getHours() 769 | break 770 | case "mo": 771 | a = myDate.getMonth() 772 | break 773 | case "d": 774 | a = myDate.getDate() 775 | break 776 | case "ts2Data": 777 | if (_data != "") { 778 | time = _data 779 | if (time.toString().length == 13) { 780 | let date = new Date(time + 8 * 3600 * 1000) 781 | a = date.toJSON().substr(0, 19).replace("T", " ") 782 | } else if (time.toString().length == 10) { 783 | time = time * 1000 784 | let date = new Date(time + 8 * 3600 * 1000) 785 | a = date.toJSON().substr(0, 19).replace("T", " ") 786 | } 787 | } 788 | break 789 | default: 790 | a = "未知错误,请检查" 791 | break 792 | } 793 | return a 794 | } 795 | randomPattern(pattern, charset = 'abcdef0123456789') { 796 | let str = '' 797 | for (let chars of pattern) { 798 | if (chars == 'x') { 799 | str += charset.charAt(Math.floor(Math.random() * charset.length)) 800 | } else if (chars == 'X') { 801 | str += charset.charAt(Math.floor(Math.random() * charset.length)).toUpperCase() 802 | } else { 803 | str += chars 804 | } 805 | } 806 | return str 807 | } 808 | randomString(len, charset = 'abcdef0123456789') { 809 | let str = '' 810 | for (let i = 0; i < len; i++) { 811 | str += charset.charAt(Math.floor(Math.random() * charset.length)) 812 | } 813 | return str 814 | } 815 | randomList(a) { 816 | let idx = Math.floor(Math.random() * a.length) 817 | return a[idx] 818 | } 819 | wait(t) { 820 | return new Promise(e => setTimeout(e, t * 1000)) 821 | } 822 | async exitNow() { 823 | await this.showmsg() 824 | let e = Date.now() 825 | let s = (e - this.startTime) / 1000 826 | this.log(`[${this.name}]运行结束,共运行了${s}秒`) 827 | process.exit(0) 828 | } 829 | }(name) 830 | } -------------------------------------------------------------------------------- /毛1/ql.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const got = require('got'); 4 | require('dotenv').config(); 5 | const { readFile } = require('fs/promises'); 6 | const path = require('path'); 7 | 8 | const qlDir = '/ql'; 9 | const authFile = path.join(qlDir, 'config/auth.json'); 10 | 11 | const api = got.extend({ 12 | prefixUrl: 'http://127.0.0.1:5600', 13 | retry: { limit: 0 }, 14 | }); 15 | 16 | async function getToken() { 17 | const authConfig = JSON.parse(await readFile(authFile)); 18 | return authConfig.token; 19 | } 20 | 21 | module.exports.getEnvs = async () => { 22 | const token = await getToken(); 23 | const body = await api({ 24 | url: 'api/envs', 25 | searchParams: { 26 | searchValue: 'JD_COOKIE', 27 | t: Date.now(), 28 | }, 29 | headers: { 30 | Accept: 'application/json', 31 | authorization: `Bearer ${token}`, 32 | }, 33 | }).json(); 34 | return body.data; 35 | }; 36 | 37 | module.exports.getEnvsCount = async () => { 38 | const data = await this.getEnvs(); 39 | return data.length; 40 | }; 41 | 42 | module.exports.addEnv = async (cookie, remarks) => { 43 | const token = await getToken(); 44 | const body = await api({ 45 | method: 'post', 46 | url: 'api/envs', 47 | params: { t: Date.now() }, 48 | json: [{ 49 | name: 'JD_COOKIE', 50 | value: cookie, 51 | remarks, 52 | }], 53 | headers: { 54 | Accept: 'application/json', 55 | authorization: `Bearer ${token}`, 56 | 'Content-Type': 'application/json;charset=UTF-8', 57 | }, 58 | }).json(); 59 | return body; 60 | }; 61 | 62 | module.exports.updateEnv = async (cookie, eid, remarks) => { 63 | const token = await getToken(); 64 | const body = await api({ 65 | method: 'put', 66 | url: 'api/envs', 67 | params: { t: Date.now() }, 68 | json: { 69 | name: 'JD_COOKIE', 70 | value: cookie, 71 | _id: eid, 72 | remarks, 73 | }, 74 | headers: { 75 | Accept: 'application/json', 76 | authorization: `Bearer ${token}`, 77 | 'Content-Type': 'application/json;charset=UTF-8', 78 | }, 79 | }).json(); 80 | return body; 81 | }; 82 | 83 | module.exports.DisableCk = async (eid) => { 84 | const token = await getToken(); 85 | const body = await api({ 86 | method: 'put', 87 | url: 'api/envs/disable', 88 | params: { t: Date.now() }, 89 | body: JSON.stringify([eid]), 90 | headers: { 91 | Accept: 'application/json', 92 | authorization: `Bearer ${token}`, 93 | 'Content-Type': 'application/json;charset=UTF-8', 94 | }, 95 | }).json(); 96 | return body; 97 | }; 98 | 99 | module.exports.EnableCk = async (eid) => { 100 | const token = await getToken(); 101 | const body = await api({ 102 | method: 'put', 103 | url: 'api/envs/enable', 104 | params: { t: Date.now() }, 105 | body: JSON.stringify([eid]), 106 | headers: { 107 | Accept: 'application/json', 108 | authorization: `Bearer ${token}`, 109 | 'Content-Type': 'application/json;charset=UTF-8', 110 | }, 111 | }).json(); 112 | return body; 113 | }; 114 | 115 | module.exports.getstatus = async (eid) => { 116 | const envs = await this.getEnvs(); 117 | for (let i = 0; i < envs.length; i++) { 118 | if(envs[i]._id==eid){ 119 | return envs[i].status; 120 | } 121 | } 122 | return 99; 123 | }; 124 | 125 | module.exports.getEnvById = async (eid) => { 126 | const envs = await this.getEnvs(); 127 | for (let i = 0; i < envs.length; i++) { 128 | if(envs[i]._id==eid){ 129 | return envs[i].value; 130 | } 131 | } 132 | return ""; 133 | }; 134 | 135 | module.exports.getEnvByPtPin = async (Ptpin) => { 136 | const envs = await this.getEnvs(); 137 | for (let i = 0; i < envs.length; i++) { 138 | var tempptpin = decodeURIComponent(envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/) && envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 139 | if(tempptpin==Ptpin){ 140 | return envs[i]; 141 | } 142 | } 143 | return ""; 144 | }; 145 | 146 | module.exports.delEnv = async (eid) => { 147 | const token = await getToken(); 148 | const body = await api({ 149 | method: 'delete', 150 | url: 'api/envs', 151 | params: { t: Date.now() }, 152 | body: JSON.stringify([eid]), 153 | headers: { 154 | Accept: 'application/json', 155 | authorization: `Bearer ${token}`, 156 | 'Content-Type': 'application/json;charset=UTF-8', 157 | }, 158 | }).json(); 159 | return body; 160 | }; 161 | -------------------------------------------------------------------------------- /毛2/ql.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const got = require('got'); 4 | require('dotenv').config(); 5 | const { readFile } = require('fs/promises'); 6 | const path = require('path'); 7 | 8 | const qlDir = '/ql'; 9 | const authFile = path.join(qlDir, 'config/auth.json'); 10 | 11 | const api = got.extend({ 12 | prefixUrl: 'http://127.0.0.1:5600', 13 | retry: { limit: 0 }, 14 | }); 15 | 16 | async function getToken() { 17 | const authConfig = JSON.parse(await readFile(authFile)); 18 | return authConfig.token; 19 | } 20 | 21 | module.exports.getEnvs = async () => { 22 | const token = await getToken(); 23 | const body = await api({ 24 | url: 'api/envs', 25 | searchParams: { 26 | searchValue: 'JD_COOKIE', 27 | t: Date.now(), 28 | }, 29 | headers: { 30 | Accept: 'application/json', 31 | authorization: `Bearer ${token}`, 32 | }, 33 | }).json(); 34 | return body.data; 35 | }; 36 | 37 | module.exports.getEnvsCount = async () => { 38 | const data = await this.getEnvs(); 39 | return data.length; 40 | }; 41 | 42 | module.exports.addEnv = async (cookie, remarks) => { 43 | const token = await getToken(); 44 | const body = await api({ 45 | method: 'post', 46 | url: 'api/envs', 47 | params: { t: Date.now() }, 48 | json: [{ 49 | name: 'JD_COOKIE', 50 | value: cookie, 51 | remarks, 52 | }], 53 | headers: { 54 | Accept: 'application/json', 55 | authorization: `Bearer ${token}`, 56 | 'Content-Type': 'application/json;charset=UTF-8', 57 | }, 58 | }).json(); 59 | return body; 60 | }; 61 | 62 | module.exports.updateEnv = async (cookie, eid, remarks) => { 63 | const token = await getToken(); 64 | const body = await api({ 65 | method: 'put', 66 | url: 'api/envs', 67 | params: { t: Date.now() }, 68 | json: { 69 | name: 'JD_COOKIE', 70 | value: cookie, 71 | _id: eid, 72 | remarks, 73 | }, 74 | headers: { 75 | Accept: 'application/json', 76 | authorization: `Bearer ${token}`, 77 | 'Content-Type': 'application/json;charset=UTF-8', 78 | }, 79 | }).json(); 80 | return body; 81 | }; 82 | 83 | module.exports.DisableCk = async (eid) => { 84 | const token = await getToken(); 85 | const body = await api({ 86 | method: 'put', 87 | url: 'api/envs/disable', 88 | params: { t: Date.now() }, 89 | body: JSON.stringify([eid]), 90 | headers: { 91 | Accept: 'application/json', 92 | authorization: `Bearer ${token}`, 93 | 'Content-Type': 'application/json;charset=UTF-8', 94 | }, 95 | }).json(); 96 | return body; 97 | }; 98 | 99 | module.exports.EnableCk = async (eid) => { 100 | const token = await getToken(); 101 | const body = await api({ 102 | method: 'put', 103 | url: 'api/envs/enable', 104 | params: { t: Date.now() }, 105 | body: JSON.stringify([eid]), 106 | headers: { 107 | Accept: 'application/json', 108 | authorization: `Bearer ${token}`, 109 | 'Content-Type': 'application/json;charset=UTF-8', 110 | }, 111 | }).json(); 112 | return body; 113 | }; 114 | 115 | module.exports.getstatus = async (eid) => { 116 | const envs = await this.getEnvs(); 117 | for (let i = 0; i < envs.length; i++) { 118 | if(envs[i]._id==eid){ 119 | return envs[i].status; 120 | } 121 | } 122 | return 99; 123 | }; 124 | 125 | module.exports.getEnvById = async (eid) => { 126 | const envs = await this.getEnvs(); 127 | for (let i = 0; i < envs.length; i++) { 128 | if(envs[i]._id==eid){ 129 | return envs[i].value; 130 | } 131 | } 132 | return ""; 133 | }; 134 | 135 | module.exports.getEnvByPtPin = async (Ptpin) => { 136 | const envs = await this.getEnvs(); 137 | for (let i = 0; i < envs.length; i++) { 138 | var tempptpin = decodeURIComponent(envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/) && envs[i].value.match(/pt_pin=([^; ]+)(?=;?)/)[1]); 139 | if(tempptpin==Ptpin){ 140 | return envs[i]; 141 | } 142 | } 143 | return ""; 144 | }; 145 | 146 | module.exports.delEnv = async (eid) => { 147 | const token = await getToken(); 148 | const body = await api({ 149 | method: 'delete', 150 | url: 'api/envs', 151 | params: { t: Date.now() }, 152 | body: JSON.stringify([eid]), 153 | headers: { 154 | Accept: 'application/json', 155 | authorization: `Bearer ${token}`, 156 | 'Content-Type': 'application/json;charset=UTF-8', 157 | }, 158 | }).json(); 159 | return body; 160 | }; 161 | --------------------------------------------------------------------------------