├── jpg ├── hjbl.png ├── laku.png ├── tz.png ├── 未标题-1.png ├── IMG_1344.JPG ├── Screenshot_2022_0730_200049.jpg ├── A97F963D4799767B81EDDD73A763BF19.jpg ├── C1F26C7C1B84EA696F2F50C5B3AE58FC.jpg └── C1F26C7C1B84EA696F2F50C5B3AE58FC.png ├── 对接傻妞 ├── README.md ├── 教程.txt └── 我在校园.js ├── README.md ├── wzxy_bbfx.js ├── sendNotify.js ├── wzxy_check.js ├── wzxy_qd.js └── wzxy_rjrb.js /jpg/hjbl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/HEAD/jpg/hjbl.png -------------------------------------------------------------------------------- /jpg/laku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/HEAD/jpg/laku.png -------------------------------------------------------------------------------- /jpg/tz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/HEAD/jpg/tz.png -------------------------------------------------------------------------------- /jpg/未标题-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/HEAD/jpg/未标题-1.png -------------------------------------------------------------------------------- /jpg/IMG_1344.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/HEAD/jpg/IMG_1344.JPG -------------------------------------------------------------------------------- /jpg/Screenshot_2022_0730_200049.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/HEAD/jpg/Screenshot_2022_0730_200049.jpg -------------------------------------------------------------------------------- /jpg/A97F963D4799767B81EDDD73A763BF19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/HEAD/jpg/A97F963D4799767B81EDDD73A763BF19.jpg -------------------------------------------------------------------------------- /jpg/C1F26C7C1B84EA696F2F50C5B3AE58FC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/HEAD/jpg/C1F26C7C1B84EA696F2F50C5B3AE58FC.jpg -------------------------------------------------------------------------------- /jpg/C1F26C7C1B84EA696F2F50C5B3AE58FC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/HEAD/jpg/C1F26C7C1B84EA696F2F50C5B3AE58FC.png -------------------------------------------------------------------------------- /对接傻妞/README.md: -------------------------------------------------------------------------------- 1 | #由于傻妞在2022年9月份插件规则更新,因此本插件仅适用于在2022年9月份以前的老傻妞,最新版傻妞不能使用! 2 | 3 | ## 对接傻妞 4 | 目前基本框架已经写完,可能会存在一些小bug(不影响使用)。 5 | ### 已完成功能: 6 | 7 | 1 . 修改密码 ✅ 8 | 9 | 2 . 添加账号 ✅ 10 | 11 | 3 . 删除账号 ✅ 12 | 13 | 4 . 账号统计✅ 14 | 15 | 5 . 教程✅ 16 | 17 | 18 | 19 | ### 计划功能: 20 | 21 | 1 . 执行签到任务 **(摆烂中,不写了... )** 22 | 23 | -------------------------------------------------------------------------------- /对接傻妞/教程.txt: -------------------------------------------------------------------------------- 1 | 关于变量值中各参数的说明: 2 | 3 | username —— “我在校园”的账号,一般是你的手机号码 4 | 5 | password —— “我在校园”的密码,忘记了打开小程序重新设置就行(建议四个英文+四个数字 类似“wzxy1234” 复杂了简单了可能都不行,改完密码运行脚本前不要再登录小程序) 6 | 7 | qd_location —— 签到位置的经纬度(wzxy_qd.js) 8 | 9 | rjrb_answers —— 日检日报的 填空参数(wzxy_rjrb.js) 看下面一些踩坑以及经验的第5条 10 | 11 | rjrb_location —— 日检日报位置的经纬度(wzxy_rjrb.js) 12 | 13 | jkdk_answers —— 健康打卡的 填空参数(wzxy_jkdk.js) 14 | 15 | jkdk_location —— 健康打卡位置的经纬度(wzxy_jkdk.js) 参考下面一些踩坑以及经验的第5条 16 | 17 | mark —— 用户昵称(不一定要真名,随便填都行,便于自己区分打卡用户) 18 | 19 | 一些踩坑以及经验: 20 | 21 | 1.我在校园密码不能太复杂,也不能太简单,推荐使用四个英文+四个数字,例如我用是wzxy1234 22 | 23 | 2.如果第一次使用,即使密码没问题,但是运行脚本时提示密码错误,请去小程序修改密码后重新运行脚本(我在校园本身的bug) 24 | 25 | 3.经纬度获取可以去这个网站获取,一般精确到小数点后六位就差不多了 https://jingweidu.bmcx.com/ 26 | 27 | 4.脚本运行时间采用正则表达式,对此不太熟练的可以去这个在线网站一键生成 http://cron.ciding.cc/ 28 | 29 | 5.这里对这个填空参数说明一下,如果是填空,那么参数就是填空内容;如果是选择题,选项一 参数是0,选项二 参数是1,以此类推···· 30 | 31 | 每一项的参数填入""内,用,隔开,最终的参数再用[]括起来 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 我在校园 青龙面板 2 | 3 | > **开源项目,不接受任何打赏,谢谢!** 4 | 5 | ## 🐧企鹅群 6 | > **不懂的可以加交流群问,发现bug也加群说,看到了就会回,群号:[744087145](https://jq.qq.com/?_wv=1027&k=1deSaQ3X)** 7 | 8 | daka 9 | 10 | 11 | ## 📌须知: 12 | 13 | * 1.只支持青龙面板(推荐使用青龙版本2.10.13),部署教程 ==> [点击查看](https://github.com/whyour/qinglong#%E9%83%A8%E7%BD%B2) 14 | 15 | * 2.本库脚本通用 `wzxy`这一个变量 16 | 17 | * 3.脚本变量只推荐在青龙的【环境变量】页添加,有强迫症在【配置文件】`config.sh`中添加的如果出现问题自己解决 18 | 19 | * 4.支持多用户,每一用户在【环境变量】单独新建变量`wzxy`,切勿一个变量内填写多个用户的参数 20 | 21 | * 5.脚本通知方式采用`青龙面板默认通知`,请在【配置文件】`config.sh`里配置 22 | 23 | * 6.关于各脚本的具体使用方法,请仔细阅读各脚本内的注释! 24 | 25 | daka 26 | 27 | 28 | ## 📍拉库: 29 | 30 | - 2.12.1之前版本青龙拉库: 31 | 32 | ``` 33 | 定时任务——新建任务 34 | 名称:我在校园拉库 35 | 命令:ql repo https://ghproxy.com/https://github.com/zhacha222/wozaixiaoyuan.git "wzxy_|sendNotify" "" "sendNotify" 36 | 定时:0 0 * * * 37 | ``` 38 | 39 | - 2.12.1之后版本青龙拉库: 40 | 41 | ``` 42 | 订阅管理——新建订阅 43 | 名称:我在校园拉库 44 | 类型:公开仓库 45 | 链接:https://ghproxy.com/https://github.com/zhacha222/wozaixiaoyuan.git 46 | 白名单:wzxy_|sendNotify 47 | 定时类型:crontab 48 | 定时:0 0 * * * 49 | 其他不填 50 | ``` 51 | 52 | 53 | daka 54 | 55 | 56 | ## 🔎环境变量: 57 | 58 | **变量名称:** 59 | ``` 60 | wzxy 61 | ``` 62 | **变量值:** 63 | ``` 64 | { 65 | "username": "手机号", 66 | "password": "密码", 67 | "qd_location": "133.333333,33.333333", 68 | "rjrb_answers": ["0","0"], 69 | "rjrb_location": "133.333333,33.333333", 70 | "jkdk_answers": ["0","无","1","0","36.2","没有","1","1","2"], 71 | "jkdk_location": "133.333333,33.333333", 72 | "mark": "用户昵称" 73 | } 74 | ``` 75 | 76 | 77 | daka 78 | 79 | 80 | 81 | **关于变量值中各参数的说明:** 82 | 83 | * `username` —— “我在校园”的账号,一般是你的手机号码 84 | 85 | * `password` —— “我在校园”的密码,忘记了打开小程序重新设置就行(推荐四个英文+四个数字,例如“wzxy1234”,改完密码后,在运行脚本前不要再登录小程序) 86 | 87 | * `qd_location` —— 签到位置的经纬度(wzxy_qd.js) 88 | 89 | * `rjrb_answers` —— 日检日报的 填空参数(wzxy_rjrb.js) 看下面`一些踩坑以及经验`的第6条 90 | 91 | * `rjrb_location` —— 日检日报位置的经纬度(wzxy_rjrb.js) 92 | 93 | * `jkdk_answers` —— 健康打卡的 填空参数(wzxy_jkdk.js) 94 | 95 | * `jkdk_location` —— 健康打卡位置的经纬度(wzxy_jkdk.js) 参考下面`一些踩坑以及经验`的第6条 96 | 97 | * `mark` —— 用户昵称(不一定要真名,随便填都行,便于自己区分打卡用户) 98 | 99 | ## 📝一些踩坑以及经验: 100 | 101 | * 1.我在校园密码不能太复杂,也不能太简单,推荐使用四个英文+四个数字,例如我用是`wzxy1234` 102 | 103 | * 2.如果第一次使用,即使密码没问题,但是运行脚本时提示密码错误,请去小程序修改密码后重新运行脚本(我在校园本身的bug) 104 | 105 | * 3.经纬度获取可以去这个网站获取,一般精确到小数点后六位就差不多了 106 | https://jingweidu.bmcx.com/ 107 | 108 | * 4.脚本运行时间采用Cron表达式,对此不太熟练的可以去这个在线网站一键生成 http://cron.ciding.cc/ 109 | 110 | * 5.可以去这个网站对你的变量值进行格式化检验 https://www.bejson.com/ 111 | 112 | * 6.这里对这个填空参数说明一下: 113 | 114 | > 对于 **旧版日检日报和旧版健康打卡**, 115 | 如果是填空题,那么参数就是要填空的内容; 116 | 如果是选择题,选项一 参数是`0`,选项二 参数是`1`,以此类推···· 117 | 118 | > 但是,对于**新版的健康打卡**,不管选择还是填空题,参数都是选项的 **文字内容**,具体看下面截图演示 119 | 120 | 每一题的参数都要填入`""`内,两两之间用`,`隔开,最终的参数再用`[]`括起来(另外,日检日报的体温体温已内置为36.0不用另填,但是健康打卡的体温需要自己填进填空参数里) 121 | 122 | 123 | daka 124 | 125 | 126 | ## 🔔通知方式: 127 | 128 | **在下面随便选一个自己喜欢的推送方式,在配置文件`config.sh`中的`通知环境变量(大概第41行到121行)`配置** 129 | 130 | 131 | daka 132 | 133 | 134 | 135 | **右图是本人在用的`企业微信应用`通知截图** 136 | 137 | 138 | daka 139 | 140 | |通知名称|通知渠道|推送方式|使用教程| 141 | |:---:|:---:|:---|:---| 142 | |[server酱](https://sct.ftqq.com)|微信(公众号)|一对一|| 143 | |[BARK](https://github.com/Finb/Bark)|iOS(APP)|一对一|| 144 | |[Telegram](https://core.telegram.org/bots/api)|TG(tg机器人)|一对一,一对多|| 145 | |[dingtalk](https://developers.dingtalk.com/document/app/custom-robot-access)|钉钉(群聊机器人)|一对一,一对多|| 146 | |[企业微信群机器人](https://work.weixin.qq.com/api/doc/90000/90136/91770)|企业微信(群聊机器人)|一对多|| 147 | |[企业微信应用消息](http://note.youdao.com/s/HMiudGkb)|企业微信(类似公众号)|一对多|[查看](https://www.zc4g.cn/658.html)| 148 | |[iGot聚合](https://wahao.github.io/Bark-MP-helper)|Bark(ios),邮箱,微信|一对一,一对多|| 149 | |[pushplus](http://www.pushplus.plus)|微信(公众号)|一对一|| 150 | |[go-cqhttp](https://github.com/Mrs4s/go-cqhttp)|QQ(QQ机器人)|一对一,一对多|| 151 | |[gotify](https://gotify.net/docs/)|自建消息推送服务(ws)|一对一,一对多|| 152 | 153 | 154 | 155 | 156 | 157 | 158 | ## 🎉特别鸣谢: 159 | 160 | * [@bean661:wozaixiaoyuanjkdkql](https://github.com/bean661/wozaixiaoyuanjkdkql) 161 | * [@whyour:qinglong](https://github.com/whyour/qinglong) 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /对接傻妞/我在校园.js: -------------------------------------------------------------------------------- 1 | // [rule: 我在校园 ] 2 | // [disable: false] 是否禁用 3 | // [admin: false] 是否只允许管理员使用 4 | 5 | 6 | let su = [] 7 | let str = "" 8 | let msg = "" 9 | let msg1 = "" 10 | let menutext = "" 11 | let j = "" 12 | let n = "" 13 | let h = "" 14 | let username="" 15 | let password="" 16 | let rjrb_answers="" 17 | let rjrb_location="" 18 | let jkdk_answers="" 19 | let jkdk_location="" 20 | let qd_location="" 21 | let mark="" 22 | let delstr = [] 23 | let data = "" 24 | let getToken = "" 25 | let wzxy_disablenum = "" 26 | let wzxy_num="" 27 | 28 | 29 | var user = GetUserID() 30 | var isAdmin = isAdmin() 31 | 32 | try{ 33 | var wzxy = bucketGet("wzxy", user) 34 | str=JSON.parse(wzxy)}catch(e){str=[]} 35 | try{var QL=JSON.parse(bucketGet("wzxy", `QL`))}catch(e){var QL=[]} 36 | try{var ql_host=QL[0].ql_host}catch(e){var ql_host = ``} 37 | try{var ql_client_id=QL[0].ql_client_id}catch(e){var ql_client_id=``} 38 | try{var ql_client_secret=QL[0].ql_client_secret}catch(e){var ql_client_secret=``} 39 | var ql_token=GetToken() 40 | 41 | function mian() { 42 | 43 | if (isAdmin) { 44 | sendText("请在10s内从中选择你要进行的操作:(输入“q”随时退出会话。)\n\n=======用户菜单=======\n\n1 . 账号管理\n2 . 修改密码\n3 . 教程\n\n======管理员菜单======\n\n4 . 青龙绑定"+getToken+"\n5 . 账号统计") 45 | }else{ 46 | sendText("请在10s内从中选择你要进行的操作:(输入“q”随时退出会话。)\n\n=======用户菜单=======\n\n1 . 账号管理\n2 . 修改密码\n3 . 教程") 47 | } 48 | 49 | 50 | iii = input(10000) 51 | if (iii == 1) { //账号管理 52 | myaccount() 53 | return; 54 | }else if (iii == 2) { //修改密码 55 | changePassword() 56 | return; 57 | }else if (iii == 3) { //教程 58 | var jiaocheng = request({url: "https://ghproxy.com/https://github.com/zhacha222/wozaixiaoyuan/blob/main/%E5%AF%B9%E6%8E%A5%E5%82%BB%E5%A6%9E/%E6%95%99%E7%A8%8B.txt"}) 59 | sendText(jiaocheng) 60 | return; 61 | }else if (iii == 4) { //青龙绑定 62 | if (isAdmin) { 63 | qinglong() 64 | return; 65 | }else { 66 | var iii = "qq" 67 | } 68 | 69 | }else if (iii == 5) { //账号统计 70 | if (isAdmin) { 71 | WZXY_NUM() 72 | return; 73 | }else { 74 | var iii = "qq" 75 | } 76 | }else { 77 | var iii = "q" 78 | } 79 | 80 | if (iii == "q" || iii == "Q" || iii == "" ) { 81 | sendText("已退出设置。") 82 | return; 83 | }else { 84 | sendText('指令错误,请重新输入:') 85 | sleep(300) 86 | return mian() 87 | } 88 | } 89 | 90 | 91 | //青龙绑定 92 | function qinglong() { 93 | 94 | WZXYQL ={"ql_host": ql_host,"ql_client_id": ql_client_id,"ql_client_secret": ql_client_secret} 95 | 96 | sendText("请选择要编辑的属性(q退出,wq保存):\n\n1 . 面板地址 -"+ql_host+`\n\n2 . ClientID -`+ql_client_id+ `\n\n3 . ClientSecret -`+ql_client_secret) 97 | 98 | msg=input() 99 | if(msg==1){ 100 | sendText("请输入青龙面板地址:") 101 | ql_host = input() 102 | return qinglong() 103 | }else if(msg==2){ 104 | sendText("请输入ClientID:") 105 | ql_client_id = input() 106 | return qinglong() 107 | }else if(msg==3){ 108 | sendText("请输入ClientSecret:") 109 | ql_client_secret = input() 110 | return qinglong() 111 | }else if (msg == "q" || msg == "Q" || msg == "" ) { 112 | sendText("已退出设置。") 113 | return; 114 | }else if (msg == "wq" ) { 115 | QL.splice(0,1,WZXYQL) 116 | //QL.push(WZXYQL) 117 | bucketSet("wzxy", `QL`,JSON.stringify(QL)) 118 | sendText("已保存") 119 | return; 120 | }else { 121 | sendText('指令错误,请重新输入:') 122 | sleep(300) 123 | menutext = "" 124 | return qinglong() 125 | } 126 | 127 | } 128 | 129 | 130 | //修改密码 131 | function changePassword() { 132 | sendText("请30秒内输入我在校园11位手机号:\n(输入“q”随时退出会话。)") 133 | var phone = input(30000) 134 | 135 | if(!phone || phone == "q" || phone == "Q"){ 136 | sendText("已退出会话。") 137 | return; 138 | } 139 | var result = request({ 140 | url: "https://gw.wozaixiaoyuan.com/basicinfo/mobile/login/getCode?phone=" + phone, 141 | "dataType": "json", 142 | "timeOut": 30000 143 | }) 144 | if (result.code == 0) { 145 | sendText("验证码码获取成功") 146 | } 147 | else { 148 | sendText("验证码获取超时。") 149 | return; 150 | } 151 | sendText("请输入验证码:") 152 | var code = input(30000) 153 | if(!code || code == "q" || code == "Q"){ 154 | sendText("已退出会话。") 155 | return; 156 | } 157 | sendText("请输入想要修改成的密码:") 158 | var newPassword = input(30000) 159 | if(!code || code == "q" || code == "Q"){ 160 | sendText("已退出会话。") 161 | return; 162 | } 163 | var result1 = request({ 164 | url: "https://gw.wozaixiaoyuan.com/basicinfo/mobile/login/changePassword?phone="+phone+"&code="+code+"&password="+newPassword, 165 | "dataType": "json", 166 | "timeOut": 30000 167 | }) 168 | 169 | if (result1.code == 0) { 170 | sendText("密码修改成功") 171 | return; 172 | } 173 | else { 174 | sendText("密码修改失败!") 175 | return; 176 | } 177 | 178 | } 179 | 180 | 181 | //账号管理 182 | function myaccount() { 183 | //var n = str.length 184 | for (var i=0,j=1;imsg&&msg>-j){ 206 | 207 | n = msg.split(`-`)[1] -1 208 | del() 209 | return myaccount() 210 | 211 | }else if (msg == "q" || msg == "Q" || msg == "" ) { 212 | sendText("已退出设置。") 213 | return; 214 | }else if (msg == "wq" ) { 215 | bucketSet("wzxy", user, JSON.stringify(str)) 216 | sendText("已保存修改") 217 | post() 218 | return; 219 | }else { 220 | sendText('指令错误,请重新输入:') 221 | sleep(300) 222 | menutext = "" 223 | return myaccount() 224 | } 225 | 226 | } 227 | 228 | 229 | //添加账号 230 | function add() { 231 | 232 | data ={"username": username,"password": password,"qd_location": qd_location,"rjrb_answers":rjrb_answers,"rjrb_location": rjrb_location,"jkdk_answers": jkdk_answers,"jkdk_location": jkdk_location,"mark": mark} 233 | 234 | sendText(`请选择要编辑的属性(u返回,q退出,wq保存):` + `\n\n1. 姓名 --`+data.mark+`\n\n2. 手机号 --` +data.username+`\n\n3. 密码 --`+data.password+`\n\n4. 日检日报Answers \n-- `+data.rjrb_answers+`\n\n5. 日检日报Location \n-- `+data.rjrb_location+`\n\n6. 健康打卡Answers \n-- `+data.jkdk_answers+`\n\n7. 健康打卡Location \n-- `+data.jkdk_location+`\n\n8. 签到Location \n-- `+data.qd_location) 235 | 236 | msg1=input() 237 | if(msg1==1){ 238 | sendText(`请输入姓名:`) 239 | mark=input() 240 | return add() 241 | }else if(msg1==2){ 242 | sendText(`请输入手机号:`) 243 | username=input() 244 | return add() 245 | }else if(msg1==3){ 246 | sendText(`请输入密码:`) 247 | password=input() 248 | return add() 249 | }else if(msg1==4){ 250 | sendText(`请输入日检日报Answers:`) 251 | sendText(`正确格式示例:["0","0"]`) 252 | //bucketSet("wzxy", user, JSON.stringify(data)) 253 | rjrb_answers=JSON.parse(input()) 254 | return add() 255 | }else if(msg1==5){ 256 | sendText(`请输入日检日报Location:`) 257 | sendText(`正确格式示例:133.333333,33.333333`) 258 | rjrb_location=input() 259 | return add() 260 | }else if(msg1==6){ 261 | sendText(`请输入健康打卡Answers:`) 262 | sendText(`正确格式示例:["0","0"]`) 263 | jkdk_answers=JSON.parse(input()) 264 | return add() 265 | }else if(msg1==7){ 266 | sendText(`请输入健康打卡Location:`) 267 | sendText(`正确格式示例:133.333333,33.333333`) 268 | jkdk_location=input() 269 | return add() 270 | }else if(msg1==8){ 271 | sendText(`请输入签到Location:`) 272 | sendText(`正确格式示例:133.333333,33.333333`) 273 | qd_location=input() 274 | return add() 275 | }else if (msg1 == "q" || msg1== "Q" || msg1 == "" ) { 276 | sendText("已退出设置。") 277 | return; 278 | }else if (msg1 == "wq" ) { 279 | str.push(data) 280 | bucketSet("wzxy", user, JSON.stringify(str)) 281 | sendText("已保存修改") 282 | //sendText(JSON.stringify(bucketGet("wzxy", user))) 283 | post() 284 | return; 285 | }else if (msg1 == "u"||msg1 == "U") { 286 | str.push(data) 287 | menutext = "" 288 | username="" 289 | password="" 290 | rjrb_answers="" 291 | rjrb_location="" 292 | jkdk_answers="" 293 | jkdk_location="" 294 | qd_location="" 295 | mark="" 296 | return myaccount() 297 | }else { 298 | sendText('指令错误,请重新输入:') 299 | sleep(300) 300 | return add() 301 | } 302 | 303 | 304 | } 305 | 306 | 307 | //编辑账号 308 | function edit() { 309 | 310 | data ={"username": username,"password": password,"qd_location": qd_location,"rjrb_answers":rjrb_answers,"rjrb_location": rjrb_location,"jkdk_answers": jkdk_answers,"jkdk_location": jkdk_location,"mark": mark} 311 | 312 | sendText(`请选择要编辑的属性(u返回,q退出,wq保存):` + `\n\n1. 姓名 --`+data.mark+`\n\n2. 手机号 --` +data.username+`\n\n3. 密码 --`+data.password+`\n\n4. 日检日报Answers \n-- `+data.rjrb_answers+`\n\n5. 日检日报Location \n-- `+data.rjrb_location+`\n\n6. 健康打卡Answers \n-- `+data.jkdk_answers+`\n\n7. 健康打卡Location \n-- `+data.jkdk_location+`\n\n8. 签到Location \n-- `+data.qd_location) 313 | 314 | msg1=input() 315 | if(msg1==1){ 316 | sendText(`请输入姓名:`) 317 | mark=input() 318 | return edit() 319 | }else if(msg1==2){ 320 | sendText(`请输入手机号:`) 321 | username=input() 322 | return edit() 323 | }else if(msg1==3){ 324 | sendText(`请输入密码:`) 325 | password=input() 326 | return edit() 327 | }else if(msg1==4){ 328 | sendText(`请输入日检日报Answers:`) 329 | sendText(`正确格式示例:["0","0"]`) 330 | //bucketSet("wzxy", user, JSON.stringify(data)) 331 | rjrb_answers=JSON.parse(input()) 332 | return edit() 333 | }else if(msg1==5){ 334 | sendText(`请输入日检日报Location:`) 335 | sendText(`正确格式示例:133.333333,33.333333`) 336 | rjrb_location=input() 337 | return edit() 338 | }else if(msg1==6){ 339 | sendText(`请输入健康打卡Answers:`) 340 | sendText(`正确格式示例:["0","0"]`) 341 | jkdk_answers=JSON.parse(input()) 342 | return edit() 343 | }else if(msg1==7){ 344 | sendText(`请输入健康打卡Location:`) 345 | sendText(`正确格式示例:133.333333,33.333333`) 346 | jkdk_location=input() 347 | return edit() 348 | }else if(msg1==8){ 349 | sendText(`请输入签到Location:`) 350 | sendText(`正确格式示例:133.333333,33.333333`) 351 | qd_location=input() 352 | return edit() 353 | }else if (msg1 == "q" || msg1== "Q" || msg1 == "" ) { 354 | sendText("已退出设置。") 355 | return; 356 | }else if (msg1 == "wq" ) { 357 | str.splice(h,1,data) 358 | bucketSet("wzxy", user, JSON.stringify(str)) 359 | sendText("已保存修改") 360 | //sendText(JSON.stringify(bucketGet("wzxy", user))) 361 | post() 362 | return; 363 | }else if (msg1 == "u"||msg1 == "U") { 364 | str.splice(h,1,data) 365 | menutext = "" 366 | username="" 367 | password="" 368 | rjrb_answers="" 369 | rjrb_location="" 370 | jkdk_answers="" 371 | jkdk_location="" 372 | qd_location="" 373 | mark="" 374 | return myaccount() 375 | }else { 376 | sendText('指令错误,请重新输入:') 377 | sleep(300) 378 | return edit() 379 | } 380 | 381 | 382 | } 383 | 384 | 385 | //删除账号 386 | function del(){ 387 | 388 | var del = str.splice(n,1) 389 | menutext = "" 390 | delstr.push(del[0]) 391 | //sendText(delstr.length) 392 | } 393 | 394 | 395 | //上传ck 396 | function post() { 397 | try{ 398 | var account= bucketGet("wzxy", user) 399 | var postdata = JSON.parse(account) 400 | 401 | //上传ck 402 | for(let k=0;k { 78 | if (typeof $request !== "undefined") { 79 | await GetRewrite(); 80 | } else { 81 | if (!(await Envs())) 82 | return; 83 | else { 84 | 85 | log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( 86 | new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + 87 | 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); 88 | 89 | await poem(); 90 | await getVersion(); 91 | 92 | log(`\n============ 当前版本:${scriptVersion} 最新版本:${scriptVersionLatest} ============`) 93 | 94 | if(scriptVersionLatest != scriptVersion){ 95 | log(`\n发现新版本,请及时拉库更新!\n${update_data}`) 96 | } 97 | 98 | log(`\n=================== 共找到 ${wzxyArr.length} 个账号 ===================`) 99 | 100 | 101 | for (let index = 0; index < wzxyArr.length; index++) { 102 | 103 | let num = index + 1 104 | if (num >1 && wait == 0){ 105 | log('**********休息10s,防止黑IP**********'); 106 | await $.wait(10 * 1000); 107 | } 108 | log(`\n========= 开始【第 ${num} 个账号】=========\n`) 109 | data = wzxyArr[index]; 110 | content = JSON.parse(data) 111 | username = content.username 112 | password = content.password 113 | mark = content.mark 114 | log(`返校用户:${mark}`) 115 | loginBack = 0; 116 | 117 | log('开始检查jwsession是否存在...'); 118 | await checkJwsession() 119 | await $.wait(2 * 1000); 120 | 121 | if (loginBack > 0) { 122 | PunchInback = 0//重置上个账号的状态码 123 | log('开始获取报备列表...'); 124 | await PunchIn() 125 | await $.wait(2 * 1000); 126 | 127 | if (PunchInback>0) { 128 | log('开始报备返校...'); 129 | await doPunchIn() 130 | await $.wait(2 * 1000); 131 | } 132 | } 133 | var resultlog = getResult() 134 | 135 | if (OnlyfaxiaoNotify>0){ 136 | if (status_code == 1 ){ 137 | msg += `返校用户:${mark}\n返校情况:${resultlog}\n\n` 138 | } 139 | }else { 140 | msg += `返校用户:${mark}\n返校情况:${resultlog}\n\n` 141 | } 142 | 143 | } 144 | 145 | // log(msg); 146 | await SendMsg(msg); 147 | } 148 | } 149 | 150 | })() 151 | .catch((e) => log(e)) 152 | .finally(() => $.done()) 153 | 154 | 155 | 156 | /** 157 | * 判断jwsession是否存在 158 | */ 159 | function checkJwsession() { 160 | 161 | fs.open('.cache/' + username + ".json", 'r+', function(err, fd) { 162 | if (err) { 163 | console.error("找不到cache文件,正在使用账号信息登录...") 164 | login() 165 | return 166 | } 167 | console.log("找到cache文件,正在使用jwsession返校...") 168 | var read = fs.readFileSync('.cache/' + username + ".json") 169 | jwsession = read.toString() 170 | loginBack = 1 171 | 172 | }); 173 | 174 | } 175 | 176 | 177 | /** 178 | * 登录 179 | */ 180 | function login(timeout = 3 * 1000) { 181 | return new Promise((resolve) => { 182 | let url = { 183 | url: `https://gw.wozaixiaoyuan.com/basicinfo/mobile/login/username?username=${username}&password=${password}`, 184 | headers: { 185 | "Accept-Encoding": "gzip, deflate, br", 186 | "Connection": "keep-alive", 187 | "User-Agent": "Mozilla/5.0 (iPad; CPU OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.23(0x1800172f) NetType/WIFI Language/zh_CN miniProgram/wxce6d08f781975d91", 188 | "content-type": "application/json;charset=UTF-8", 189 | "Content-Length": "2", 190 | "Host": "gw.wozaixiaoyuan.com", 191 | "Accept-Language": "en-us,en", 192 | "Accept": "application/json, text/plain, */*" 193 | }, 194 | data: ``, 195 | } 196 | 197 | 198 | request.post(url, async (error, response, data) => { 199 | try { 200 | let result = data == "undefined" ? await login() : JSON.parse(data); 201 | 202 | //登录成功 203 | if (result.code == 0 ) { 204 | 205 | jwsession = response.headers['jwsession'] 206 | //储存jwsession 207 | setJwsession(jwsession) 208 | loginBack = 1; 209 | log(`登录成功`) 210 | 211 | } else { 212 | log(`❌ 登录失败,${result.message}`) 213 | status_code = 5; 214 | loginBack = 0; 215 | } 216 | 217 | } catch (e) { 218 | log(e) 219 | } finally { 220 | resolve(); 221 | } 222 | }, timeout) 223 | }) 224 | } 225 | 226 | 227 | /** 228 | * 存储jwsession 229 | */ 230 | function setJwsession(jwsession) { 231 | 232 | fs.mkdir('.cache',function(err){ 233 | if (err) { 234 | 235 | console.log("找到cache文件"); 236 | } 237 | else console.log("正在创建cache储存目录与文件..."); 238 | }); 239 | 240 | fs.writeFile('.cache/' + username + ".json", jwsession, function(err) { 241 | if (err) { 242 | return console.error(err); 243 | } 244 | console.log("更新jwsession成功"); 245 | }) 246 | 247 | } 248 | 249 | 250 | /** 251 | * 获取报备列表 252 | */ 253 | function PunchIn(timeout = 3 * 1000) { 254 | return new Promise((resolve) => { 255 | 256 | let url = { 257 | url: "https://gw.wozaixiaoyuan.com/out/mobile/out/getOne", 258 | headers: { 259 | 'jwsession': jwsession, 260 | 'Content-Type': 'application/json' 261 | }, 262 | body: `` 263 | } 264 | 265 | $.post(url, async (error, response, data) => { 266 | //log(data) 267 | try { 268 | let result = data == "undefined" ? await PunchIn() : JSON.parse(data); 269 | if (result.code == 103) { 270 | log('jwsession 无效,尝试账号密码登录...') 271 | status_code = 4; 272 | PunchInback = 0; 273 | loginBack = 0; 274 | await login() 275 | await $.wait(2 * 1000); 276 | if (loginBack > 0) { 277 | log('重新获取报备列表...'); 278 | await PunchIn() 279 | await $.wait(2 * 1000) 280 | return 281 | } 282 | } 283 | if (result.code == 0) { 284 | id = result.data.id 285 | endDatetime =result.data.endDatetime 286 | state =result.data.state //state为2表示未返校,为5表示已返校,为4表示当前已超过返校时间 287 | //log(state) 288 | if (state==5){ 289 | log('🈚️ 暂无返校任务,跳过返校...') 290 | wait = 1 291 | status_code = 2 292 | PunchInback = 0 293 | }else if(state==2){ 294 | log("✅ 找到未返校任务,开始返校...") 295 | PunchInback = 1 296 | wait=0 297 | }else if(state==4){ 298 | log("⚠️当前已超过返校时间,开始返校...") 299 | PunchInback = 1 300 | wait=0 301 | } 302 | 303 | } 304 | if (result.code != 0) { 305 | log(`获取失败,原因:${error}`) 306 | PunchInback = 0 307 | } 308 | 309 | } catch (e) { 310 | log(e) 311 | } finally { 312 | resolve(); 313 | } 314 | }, timeout) 315 | }) 316 | } 317 | 318 | 319 | /** 320 | * 开始返校 321 | */ 322 | function doPunchIn(timeout = 3 * 1000) { 323 | return new Promise((resolve) => { 324 | let url = { 325 | url: `https://gw.wozaixiaoyuan.com/out/mobile/out/back?id=${id}`, 326 | headers: { 327 | 'jwsession': jwsession, 328 | 'Content-Type': 'application/json' 329 | }, 330 | body: ``, 331 | 332 | } 333 | 334 | $.post(url, async (error, response, data) => { 335 | 336 | try { 337 | let result = data == "undefined" ? await doPunchIn() : JSON.parse(data); 338 | 339 | //返校情况 340 | if (result.code == 0){ 341 | log("✅ 返校成功") 342 | status_code = 1 343 | } else{ 344 | log("❌ 返校失败") 345 | status_code = 0 346 | } 347 | 348 | } catch (e) { 349 | log(e) 350 | } finally { 351 | resolve(); 352 | } 353 | }, timeout) 354 | }) 355 | } 356 | 357 | 358 | /** 359 | * 获取返校结果 360 | */ 361 | function getResult(timeout = 3 * 1000) { 362 | res = status_code 363 | if (res == 1) return "✅ 返校成功" 364 | if (res == 2) return "🈚️ 当前无返校任务" 365 | if (res == 3) return "❌ 返校失败,当前不在返校时间段内" 366 | if (res == 4) return "❌ 返校失败,jwsession 无效" 367 | if (res == 5) return "❌ 返校失败,登录错误,请检查账号信息" 368 | else return "❌ 返校失败,发生未知错误" 369 | } 370 | 371 | 372 | // ============================================变量检查============================================ \\ 373 | async function Envs() { 374 | if (wzxy) { 375 | if (wzxy.indexOf("@") != -1 || wzxy.indexOf("&") != -1) { 376 | wzxy.split("@"&&"&").forEach((item) => { 377 | wzxyArr.push(item); 378 | }); 379 | } 380 | // else if (wzxy.indexOf("\n") != -1) { 381 | // wzxy.split("\n").forEach((item) => { 382 | // wzxyArr.push(item); 383 | // }); 384 | // } 385 | else { 386 | wzxyArr.push(wzxy); 387 | } 388 | } else { 389 | log(`\n 未填写变量 wzxy`) 390 | return; 391 | } 392 | 393 | return true; 394 | } 395 | // ============================================发送消息============================================ \\ 396 | async function SendMsg(msg) { 397 | if (!msg) 398 | return; 399 | 400 | if (Notify > 0) { 401 | if ($.isNode()) { 402 | var notify = require('./sendNotify'); 403 | await notify.sendNotify($.name, msg+ `\n执行时间:${t()}\n`); 404 | } else { 405 | $.msg(msg); 406 | } 407 | } else { 408 | log(msg); 409 | } 410 | } 411 | 412 | /** 413 | * 随机数生成 414 | */ 415 | function randomString(e) { 416 | e = e || 32; 417 | var t = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890", 418 | a = t.length, 419 | n = ""; 420 | for (i = 0; i < e; i++) 421 | n += t.charAt(Math.floor(Math.random() * a)); 422 | return n 423 | } 424 | 425 | /** 426 | * 随机整数生成 427 | */ 428 | function randomInt(min, max) { 429 | return Math.round(Math.random() * (max - min) + min) 430 | } 431 | 432 | /** 433 | * 获取毫秒时间戳 434 | */ 435 | function timestampMs(){ 436 | return new Date().getTime(); 437 | } 438 | 439 | /** 440 | * 441 | * 获取秒时间戳 442 | */ 443 | function timestampS(){ 444 | return Date.parse(new Date())/1000; 445 | } 446 | 447 | /** 448 | * 获取随机诗词 449 | */ 450 | function poem(timeout = 3 * 1000) { 451 | return new Promise((resolve) => { 452 | let url = { 453 | url: `https://v1.jinrishici.com/all.json` 454 | } 455 | $.get(url, async (err, resp, data) => { 456 | try { 457 | data = JSON.parse(data) 458 | log(`${data.content} \n————《${data.origin}》${data.author}`); 459 | } catch (e) { 460 | log(e, resp); 461 | } finally { 462 | resolve() 463 | } 464 | }, timeout) 465 | }) 466 | } 467 | 468 | /** 469 | * 修改配置文件 470 | */ 471 | function modify() { 472 | 473 | fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ 474 | if(err){ 475 | return log('读取文件失败!'+err) 476 | } 477 | else { 478 | var result = dataStr.replace(/regular/g,string); 479 | fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { 480 | if (err) {return log(err);} 481 | }); 482 | } 483 | }) 484 | } 485 | 486 | /** 487 | * 获取远程版本 488 | */ 489 | function getVersion(timeout = 3 * 1000) { 490 | return new Promise((resolve) => { 491 | let url = { 492 | url: `https://ghproxy.com/https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/main/wzxy_bbfx.js`, 493 | } 494 | $.get(url, async (err, resp, data) => { 495 | try { 496 | scriptVersionLatest = data.match(/scriptVersion = "([\d\.]+)"/)[1] 497 | update_data = data.match(/update_data = "(.*?)"/)[1] 498 | } catch (e) { 499 | $.logErr(e, resp); 500 | } finally { 501 | resolve() 502 | } 503 | }, timeout) 504 | }) 505 | } 506 | 507 | /** 508 | * time 输出格式:1970-01-01 00:00:00 509 | */ 510 | function t() { 511 | var date = new Date(); 512 | // 获取当前月份 513 | var nowMonth = date.getMonth() + 1; 514 | // 获取当前是几号 515 | var strDate = date.getDate(); 516 | //获取当前小时(0-23) 517 | var nowhour = date.getHours() 518 | //获取当前分钟(0-59) 519 | var nowMinute = date.getMinutes() 520 | //获取当前秒数(0-59) 521 | var nowSecond = date.getSeconds(); 522 | // 添加分隔符“-” 523 | var seperator = "-"; 524 | // 添加分隔符“:” 525 | var seperator1 = ":"; 526 | 527 | // 对月份进行处理,1-9月在前面添加一个“0” 528 | if (nowMonth >= 1 && nowMonth <= 9) { 529 | nowMonth = "0" + nowMonth; 530 | } 531 | // 对月份进行处理,1-9号在前面添加一个“0” 532 | if (strDate >= 0 && strDate <= 9) { 533 | strDate = "0" + strDate; 534 | } 535 | // 对小时进行处理,0-9号在前面添加一个“0” 536 | if (nowhour >= 0 && nowhour <= 9) { 537 | nowhour = "0" + nowhour; 538 | } 539 | // 对分钟进行处理,0-9号在前面添加一个“0” 540 | if (nowMinute >= 0 && nowMinute <= 9) { 541 | nowMinute = "0" + nowMinute; 542 | } 543 | // 对秒数进行处理,0-9号在前面添加一个“0” 544 | if (nowSecond >= 0 && nowSecond <= 9) { 545 | nowSecond = "0" + nowSecond; 546 | } 547 | 548 | // 最后拼接字符串,得到一个格式为(yyyy-MM-dd)的日期 549 | var nowDate = date.getFullYear() + seperator + nowMonth + seperator + strDate + ` ` + nowhour + seperator1 + nowMinute + seperator1 + nowSecond 550 | return nowDate 551 | } 552 | 553 | function Env(t, e) { 554 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 555 | class s { 556 | constructor(t) { 557 | this.env = t 558 | } 559 | send(t, e = "GET") { 560 | t = "string" == typeof t ? { 561 | url: t 562 | } : t; 563 | let s = this.get; 564 | return "POST" === e && (s = this.post), new Promise((e, i) => { 565 | s.call(this, t, (t, s, r) => { 566 | t ? i(t) : e(s) 567 | }) 568 | }) 569 | } 570 | get(t) { 571 | return this.send.call(this.env, t) 572 | } 573 | post(t) { 574 | return this.send.call(this.env, t, "POST") 575 | } 576 | } 577 | return new class { 578 | constructor(t, e) { 579 | 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}, 开始!`) 580 | } 581 | isNode() { 582 | return "undefined" != typeof module && !!module.exports 583 | } 584 | isQuanX() { 585 | return "undefined" != typeof $task 586 | } 587 | isSurge() { 588 | return "undefined" != typeof $httpClient && "undefined" == typeof $loon 589 | } 590 | isLoon() { 591 | return "undefined" != typeof $loon 592 | } 593 | toObj(t, e = null) { 594 | try { 595 | return JSON.parse(t) 596 | } catch { 597 | return e 598 | } 599 | } 600 | toStr(t, e = null) { 601 | try { 602 | return JSON.stringify(t) 603 | } catch { 604 | return e 605 | } 606 | } 607 | getjson(t, e) { 608 | let s = e; 609 | const i = this.getdata(t); 610 | if (i) try { 611 | s = JSON.parse(this.getdata(t)) 612 | } catch {} 613 | return s 614 | } 615 | setjson(t, e) { 616 | try { 617 | return this.setdata(JSON.stringify(t), e) 618 | } catch { 619 | return !1 620 | } 621 | } 622 | getScript(t) { 623 | return new Promise(e => { 624 | this.get({ 625 | url: t 626 | }, (t, s, i) => e(i)) 627 | }) 628 | } 629 | runScript(t, e) { 630 | return new Promise(s => { 631 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 632 | i = i ? i.replace(/\n/g, "").trim() : i; 633 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 634 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 635 | const [o, h] = i.split("@"), n = { 636 | url: `http://${h}/v1/scripting/evaluate`, 637 | body: { 638 | script_text: t, 639 | mock_type: "cron", 640 | timeout: r 641 | }, 642 | headers: { 643 | "X-Key": o, 644 | Accept: "*/*" 645 | } 646 | }; 647 | this.post(n, (t, e, i) => s(i)) 648 | }).catch(t => this.logErr(t)) 649 | } 650 | loaddata() { 651 | if (!this.isNode()) return {}; { 652 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 653 | const t = this.path.resolve(this.dataFile), 654 | e = this.path.resolve(process.cwd(), this.dataFile), 655 | s = this.fs.existsSync(t), 656 | i = !s && this.fs.existsSync(e); 657 | if (!s && !i) return {}; { 658 | const i = s ? t : e; 659 | try { 660 | return JSON.parse(this.fs.readFileSync(i)) 661 | } catch (t) { 662 | return {} 663 | } 664 | } 665 | } 666 | } 667 | writedata() { 668 | if (this.isNode()) { 669 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 670 | const t = this.path.resolve(this.dataFile), 671 | e = this.path.resolve(process.cwd(), this.dataFile), 672 | s = this.fs.existsSync(t), 673 | i = !s && this.fs.existsSync(e), 674 | r = JSON.stringify(this.data); 675 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 676 | } 677 | } 678 | lodash_get(t, e, s) { 679 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 680 | let r = t; 681 | for (const t of i) 682 | if (r = Object(r)[t], void 0 === r) return s; 683 | return r 684 | } 685 | lodash_set(t, e, s) { 686 | 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) 687 | } 688 | getdata(t) { 689 | let e = this.getval(t); 690 | if (/^@/.test(t)) { 691 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; 692 | if (r) try { 693 | const t = JSON.parse(r); 694 | e = t ? this.lodash_get(t, i, "") : e 695 | } catch (t) { 696 | e = "" 697 | } 698 | } 699 | return e 700 | } 701 | setdata(t, e) { 702 | let s = !1; 703 | if (/^@/.test(e)) { 704 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; 705 | try { 706 | const e = JSON.parse(h); 707 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) 708 | } catch (e) { 709 | const o = {}; 710 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) 711 | } 712 | } else s = this.setval(t, e); 713 | return s 714 | } 715 | getval(t) { 716 | 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 717 | } 718 | setval(t, e) { 719 | 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 720 | } 721 | initGotEnv(t) { 722 | 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)) 723 | } 724 | get(t, e = (() => {})) { 725 | 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, { 726 | "X-Surge-Skip-Scripting": !1 727 | })), $httpClient.get(t, (t, s, i) => { 728 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 729 | })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 730 | hints: !1 731 | })), $task.fetch(t).then(t => { 732 | const { 733 | statusCode: s, 734 | statusCode: i, 735 | headers: r, 736 | body: o 737 | } = t; 738 | e(null, { 739 | status: s, 740 | statusCode: i, 741 | headers: r, 742 | body: o 743 | }, o) 744 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 745 | try { 746 | if (t.headers["set-cookie"]) { 747 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 748 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar 749 | } 750 | } catch (t) { 751 | this.logErr(t) 752 | } 753 | }).then(t => { 754 | const { 755 | statusCode: s, 756 | statusCode: i, 757 | headers: r, 758 | body: o 759 | } = t; 760 | e(null, { 761 | status: s, 762 | statusCode: i, 763 | headers: r, 764 | body: o 765 | }, o) 766 | }, t => { 767 | const { 768 | message: s, 769 | response: i 770 | } = t; 771 | e(s, i, i && i.body) 772 | })) 773 | } 774 | post(t, e = (() => {})) { 775 | 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, { 776 | "X-Surge-Skip-Scripting": !1 777 | })), $httpClient.post(t, (t, s, i) => { 778 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 779 | }); 780 | else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 781 | hints: !1 782 | })), $task.fetch(t).then(t => { 783 | const { 784 | statusCode: s, 785 | statusCode: i, 786 | headers: r, 787 | body: o 788 | } = t; 789 | e(null, { 790 | status: s, 791 | statusCode: i, 792 | headers: r, 793 | body: o 794 | }, o) 795 | }, t => e(t)); 796 | else if (this.isNode()) { 797 | this.initGotEnv(t); 798 | const { 799 | url: s, 800 | ...i 801 | } = t; 802 | this.got.post(s, i).then(t => { 803 | const { 804 | statusCode: s, 805 | statusCode: i, 806 | headers: r, 807 | body: o 808 | } = t; 809 | e(null, { 810 | status: s, 811 | statusCode: i, 812 | headers: r, 813 | body: o 814 | }, o) 815 | }, t => { 816 | const { 817 | message: s, 818 | response: i 819 | } = t; 820 | e(s, i, i && i.body) 821 | }) 822 | } 823 | } 824 | time(t, e = null) { 825 | const s = e ? new Date(e) : new Date; 826 | let i = { 827 | "M+": s.getMonth() + 1, 828 | "d+": s.getDate(), 829 | "H+": s.getHours(), 830 | "m+": s.getMinutes(), 831 | "s+": s.getSeconds(), 832 | "q+": Math.floor((s.getMonth() + 3) / 3), 833 | S: s.getMilliseconds() 834 | }; 835 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 836 | 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))); 837 | return t 838 | } 839 | msg(e = t, s = "", i = "", r) { 840 | const o = t => { 841 | if (!t) return t; 842 | if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { 843 | "open-url": t 844 | } : this.isSurge() ? { 845 | url: t 846 | } : void 0; 847 | if ("object" == typeof t) { 848 | if (this.isLoon()) { 849 | let e = t.openUrl || t.url || t["open-url"], 850 | s = t.mediaUrl || t["media-url"]; 851 | return { 852 | openUrl: e, 853 | mediaUrl: s 854 | } 855 | } 856 | if (this.isQuanX()) { 857 | let e = t["open-url"] || t.url || t.openUrl, 858 | s = t["media-url"] || t.mediaUrl; 859 | return { 860 | "open-url": e, 861 | "media-url": s 862 | } 863 | } 864 | if (this.isSurge()) { 865 | let e = t.url || t.openUrl || t["open-url"]; 866 | return { 867 | url: e 868 | } 869 | } 870 | } 871 | }; 872 | if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { 873 | let t = ["", "==============📣系统通知📣=============="]; 874 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) 875 | } 876 | } 877 | log(...t) { 878 | t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) 879 | } 880 | logErr(t, e) { 881 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 882 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 883 | } 884 | wait(t) { 885 | return new Promise(e => setTimeout(e, t)) 886 | } 887 | done(t = {}) { 888 | const e = (new Date).getTime(), 889 | s = (e - this.startTime) / 1e3; 890 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 891 | } 892 | }(t, e) 893 | } 894 | -------------------------------------------------------------------------------- /sendNotify.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: lxk0301 https://gitee.com/lxk0301 3 | * @Date: 2020-08-19 16:12:40 4 | * @Last Modified by: whyour 5 | * @Last Modified time: 2021-5-1 15:00:54 6 | * sendNotify 推送通知功能 7 | * @param text 通知头 8 | * @param desp 通知体 9 | * @param params 某些推送通知方式点击弹窗可跳转, 例:{ url: 'https://abc.com' } 10 | * @param author 作者仓库等信息 例:`本通知 By:https://github.com/whyour/qinglong` 11 | */ 12 | 13 | const querystring = require('querystring'); 14 | const $ = new Env(); 15 | const timeout = 15000; //超时时间(单位毫秒) 16 | // =======================================gotify通知设置区域============================================== 17 | //gotify_url 填写gotify地址,如https://push.example.de:8080 18 | //gotify_token 填写gotify的消息应用token 19 | //gotify_priority 填写推送消息优先级,默认为0 20 | let GOTIFY_URL = ''; 21 | let GOTIFY_TOKEN = ''; 22 | let GOTIFY_PRIORITY = 0; 23 | // =======================================go-cqhttp通知设置区域=========================================== 24 | //gobot_url 填写请求地址http://127.0.0.1/send_private_msg 25 | //gobot_token 填写在go-cqhttp文件设置的访问密钥 26 | //gobot_qq 填写推送到个人QQ或者QQ群号 27 | //go-cqhttp相关API https://docs.go-cqhttp.org/api 28 | let GOBOT_URL = ''; // 推送到个人QQ: http://127.0.0.1/send_private_msg 群:http://127.0.0.1/send_group_msg 29 | let GOBOT_TOKEN = ''; //访问密钥 30 | let GOBOT_QQ = ''; // 如果GOBOT_URL设置 /send_private_msg 则需要填入 user_id=个人QQ 相反如果是 /send_group_msg 则需要填入 group_id=QQ群 31 | 32 | // =======================================微信server酱通知设置区域=========================================== 33 | //此处填你申请的SCKEY. 34 | //(环境变量名 PUSH_KEY) 35 | let SCKEY = ''; 36 | 37 | // =======================================Bark App通知设置区域=========================================== 38 | //此处填你BarkAPP的信息(IP/设备码,例如:https://api.day.app/XXXXXXXX) 39 | let BARK_PUSH = ''; 40 | //BARK app推送铃声,铃声列表去APP查看复制填写 41 | let BARK_SOUND = ''; 42 | //BARK app推送消息的分组, 默认为"QingLong" 43 | let BARK_GROUP = 'QingLong'; 44 | 45 | // =======================================telegram机器人通知设置区域=========================================== 46 | //此处填你telegram bot 的Token,telegram机器人通知推送必填项.例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw 47 | //(环境变量名 TG_BOT_TOKEN) 48 | let TG_BOT_TOKEN = ''; 49 | //此处填你接收通知消息的telegram用户的id,telegram机器人通知推送必填项.例如:129xxx206 50 | //(环境变量名 TG_USER_ID) 51 | let TG_USER_ID = ''; 52 | //tg推送HTTP代理设置(不懂可忽略,telegram机器人通知推送功能中非必填) 53 | let TG_PROXY_HOST = ''; //例如:127.0.0.1(环境变量名:TG_PROXY_HOST) 54 | let TG_PROXY_PORT = ''; //例如:1080(环境变量名:TG_PROXY_PORT) 55 | let TG_PROXY_AUTH = ''; //tg代理配置认证参数 56 | //Telegram api自建的反向代理地址(不懂可忽略,telegram机器人通知推送功能中非必填),默认tg官方api(环境变量名:TG_API_HOST) 57 | let TG_API_HOST = 'api.telegram.org'; 58 | // =======================================钉钉机器人通知设置区域=========================================== 59 | //此处填你钉钉 bot 的webhook,例如:5a544165465465645d0f31dca676e7bd07415asdasd 60 | //(环境变量名 DD_BOT_TOKEN) 61 | let DD_BOT_TOKEN = ''; 62 | //密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串 63 | let DD_BOT_SECRET = ''; 64 | 65 | // =======================================企业微信机器人通知设置区域=========================================== 66 | //此处填你企业微信机器人的 webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa 67 | //(环境变量名 QYWX_KEY) 68 | let QYWX_KEY = ''; 69 | 70 | // =======================================企业微信应用消息通知设置区域=========================================== 71 | /* 72 | 此处填你企业微信应用消息的值(详见文档 https://work.weixin.qq.com/api/doc/90000/90135/90236) 73 | 环境变量名 QYWX_AM依次填入 corpid,corpsecret,touser(注:多个成员ID使用|隔开),agentid,消息类型(选填,不填默认文本消息类型) 74 | 注意用,号隔开(英文输入法的逗号),例如:wwcff56746d9adwers,B-791548lnzXBE6_BWfxdf3kSTMJr9vFEPKAbh6WERQ,mingcheng,1000001,2COXgjH2UIfERF2zxrtUOKgQ9XklUqMdGSWLBoW_lSDAdafat 75 | 可选推送消息类型(推荐使用图文消息(mpnews)): 76 | - 文本卡片消息: 0 (数字零) 77 | - 文本消息: 1 (数字一) 78 | - 图文消息(mpnews): 素材库图片id, 可查看此教程(http://note.youdao.com/s/HMiudGkb)或者(https://note.youdao.com/ynoteshare1/index.html?id=1a0c8aff284ad28cbd011b29b3ad0191&type=note) 79 | */ 80 | let QYWX_AM = ''; 81 | 82 | // =======================================iGot聚合推送通知设置区域=========================================== 83 | //此处填您iGot的信息(推送key,例如:https://push.hellyw.com/XXXXXXXX) 84 | let IGOT_PUSH_KEY = ''; 85 | 86 | // =======================================push+设置区域======================================= 87 | //官方文档:http://www.pushplus.plus/ 88 | //PUSH_PLUS_TOKEN:微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送 89 | //PUSH_PLUS_USER: 一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送) 90 | let PUSH_PLUS_TOKEN = ''; 91 | let PUSH_PLUS_USER = ''; 92 | 93 | //==========================云端环境变量的判断与接收========================= 94 | if (process.env.GOTIFY_URL) { 95 | GOTIFY_URL = process.env.GOTIFY_URL; 96 | } 97 | if (process.env.GOTIFY_TOKEN) { 98 | GOTIFY_TOKEN = process.env.GOTIFY_TOKEN; 99 | } 100 | if (process.env.GOTIFY_PRIORITY) { 101 | GOTIFY_PRIORITY = process.env.GOTIFY_PRIORITY; 102 | } 103 | 104 | if (process.env.GOBOT_URL) { 105 | GOBOT_URL = process.env.GOBOT_URL; 106 | } 107 | if (process.env.GOBOT_TOKEN) { 108 | GOBOT_TOKEN = process.env.GOBOT_TOKEN; 109 | } 110 | if (process.env.GOBOT_QQ) { 111 | GOBOT_QQ = process.env.GOBOT_QQ; 112 | } 113 | 114 | if (process.env.PUSH_KEY) { 115 | SCKEY = process.env.PUSH_KEY; 116 | } 117 | 118 | if (process.env.QQ_SKEY) { 119 | QQ_SKEY = process.env.QQ_SKEY; 120 | } 121 | 122 | if (process.env.QQ_MODE) { 123 | QQ_MODE = process.env.QQ_MODE; 124 | } 125 | 126 | if (process.env.BARK_PUSH) { 127 | if ( 128 | process.env.BARK_PUSH.indexOf('https') > -1 || 129 | process.env.BARK_PUSH.indexOf('http') > -1 130 | ) { 131 | //兼容BARK自建用户 132 | BARK_PUSH = process.env.BARK_PUSH; 133 | } else { 134 | BARK_PUSH = `https://api.day.app/${process.env.BARK_PUSH}`; 135 | } 136 | if (process.env.BARK_SOUND) { 137 | BARK_SOUND = process.env.BARK_SOUND; 138 | } 139 | if (process.env.BARK_GROUP) { 140 | BARK_GROUP = process.env.BARK_GROUP; 141 | } 142 | } else { 143 | if ( 144 | BARK_PUSH && 145 | BARK_PUSH.indexOf('https') === -1 && 146 | BARK_PUSH.indexOf('http') === -1 147 | ) { 148 | //兼容BARK本地用户只填写设备码的情况 149 | BARK_PUSH = `https://api.day.app/${BARK_PUSH}`; 150 | } 151 | } 152 | if (process.env.TG_BOT_TOKEN) { 153 | TG_BOT_TOKEN = process.env.TG_BOT_TOKEN; 154 | } 155 | if (process.env.TG_USER_ID) { 156 | TG_USER_ID = process.env.TG_USER_ID; 157 | } 158 | if (process.env.TG_PROXY_AUTH) TG_PROXY_AUTH = process.env.TG_PROXY_AUTH; 159 | if (process.env.TG_PROXY_HOST) TG_PROXY_HOST = process.env.TG_PROXY_HOST; 160 | if (process.env.TG_PROXY_PORT) TG_PROXY_PORT = process.env.TG_PROXY_PORT; 161 | if (process.env.TG_API_HOST) TG_API_HOST = process.env.TG_API_HOST; 162 | 163 | if (process.env.DD_BOT_TOKEN) { 164 | DD_BOT_TOKEN = process.env.DD_BOT_TOKEN; 165 | if (process.env.DD_BOT_SECRET) { 166 | DD_BOT_SECRET = process.env.DD_BOT_SECRET; 167 | } 168 | } 169 | 170 | if (process.env.QYWX_KEY) { 171 | QYWX_KEY = process.env.QYWX_KEY; 172 | } 173 | 174 | if (process.env.QYWX_AM) { 175 | QYWX_AM = process.env.QYWX_AM; 176 | } 177 | 178 | if (process.env.IGOT_PUSH_KEY) { 179 | IGOT_PUSH_KEY = process.env.IGOT_PUSH_KEY; 180 | } 181 | 182 | if (process.env.PUSH_PLUS_TOKEN) { 183 | PUSH_PLUS_TOKEN = process.env.PUSH_PLUS_TOKEN; 184 | } 185 | if (process.env.PUSH_PLUS_USER) { 186 | PUSH_PLUS_USER = process.env.PUSH_PLUS_USER; 187 | } 188 | //==========================云端环境变量的判断与接收========================= 189 | 190 | /** 191 | * sendNotify 推送通知功能 192 | * @param text 通知头 193 | * @param desp 通知体 194 | * @param params 某些推送通知方式点击弹窗可跳转, 例:{ url: 'https://abc.com' } 195 | * @param author 作者仓库等信息 例:`本通知 By:https://github.com/whyour/qinglong` 196 | * @returns {Promise} 197 | */ 198 | async function sendNotify( 199 | text, 200 | desp, 201 | params = {}, 202 | author = '\n\n本通知 By:https://github.com/zhacha222/wozaixiaoyuan', 203 | ) { 204 | //提供6种通知 205 | desp += author; //增加作者信息,防止被贩卖等 206 | await Promise.all([ 207 | serverNotify(text, desp), //微信server酱 208 | pushPlusNotify(text, desp), //pushplus(推送加) 209 | ]); 210 | //由于上述两种微信通知需点击进去才能查看到详情,故text(标题内容)携带了账号序号以及昵称信息,方便不点击也可知道是哪个京东哪个活动 211 | text = text.match(/.*?(?=\s?-)/g) ? text.match(/.*?(?=\s?-)/g)[0] : text; 212 | await Promise.all([ 213 | BarkNotify(text, desp, params), //iOS Bark APP 214 | tgBotNotify(text, desp), //telegram 机器人 215 | ddBotNotify(text, desp), //钉钉机器人 216 | qywxBotNotify(text, desp), //企业微信机器人 217 | qywxamNotify(text, desp), //企业微信应用消息推送 218 | iGotNotify(text, desp, params), //iGot 219 | gobotNotify(text, desp),//go-cqhttp 220 | gotifyNotify(text, desp),//gotify 221 | ]); 222 | } 223 | 224 | function gotifyNotify(text, desp) { 225 | return new Promise((resolve) => { 226 | if (GOTIFY_URL && GOTIFY_TOKEN) { 227 | const options = { 228 | url: `${GOTIFY_URL}/message?token=${GOTIFY_TOKEN}`, 229 | body: `title=${encodeURIComponent(text)}&message=${encodeURIComponent(desp)}&priority=${GOTIFY_PRIORITY}`, 230 | headers: { 231 | 'Content-Type': 'application/x-www-form-urlencoded', 232 | } 233 | }; 234 | $.post(options, (err, resp, data) => { 235 | try { 236 | if (err) { 237 | console.log('gotify发送通知调用API失败!!\n'); 238 | console.log(err); 239 | } else { 240 | data = JSON.parse(data); 241 | if (data.id) { 242 | console.log('gotify发送通知消息成功🎉\n'); 243 | } else { 244 | console.log(`${data.message}\n`); 245 | } 246 | } 247 | } catch (e) { 248 | $.logErr(e, resp); 249 | } finally { 250 | resolve(); 251 | } 252 | }); 253 | } else { 254 | resolve(); 255 | } 256 | }); 257 | } 258 | 259 | function gobotNotify(text, desp, time = 2100) { 260 | return new Promise((resolve) => { 261 | if (GOBOT_URL) { 262 | const options = { 263 | url: `${GOBOT_URL}?access_token=${GOBOT_TOKEN}&${GOBOT_QQ}`, 264 | json: {message:`${text}\n${desp}`}, 265 | headers: { 266 | 'Content-Type': 'application/json', 267 | }, 268 | timeout, 269 | }; 270 | setTimeout(() => { 271 | $.post(options, (err, resp, data) => { 272 | try { 273 | if (err) { 274 | console.log('发送go-cqhttp通知调用API失败!!\n'); 275 | console.log(err); 276 | } else { 277 | data = JSON.parse(data); 278 | if (data.retcode === 0) { 279 | console.log('go-cqhttp发送通知消息成功🎉\n'); 280 | } else if (data.retcode === 100) { 281 | console.log(`go-cqhttp发送通知消息异常: ${data.errmsg}\n`); 282 | } else { 283 | console.log( 284 | `go-cqhttp发送通知消息异常\n${JSON.stringify(data)}`, 285 | ); 286 | } 287 | } 288 | } catch (e) { 289 | $.logErr(e, resp); 290 | } finally { 291 | resolve(data); 292 | } 293 | }); 294 | }, time); 295 | } else { 296 | resolve(); 297 | } 298 | }); 299 | } 300 | 301 | function serverNotify(text, desp, time = 2100) { 302 | return new Promise((resolve) => { 303 | if (SCKEY) { 304 | //微信server酱推送通知一个\n不会换行,需要两个\n才能换行,故做此替换 305 | desp = desp.replace(/[\n\r]/g, '\n\n'); 306 | const options = { 307 | url: SCKEY.includes('SCT') 308 | ? `https://sctapi.ftqq.com/${SCKEY}.send` 309 | : `https://sc.ftqq.com/${SCKEY}.send`, 310 | body: `text=${text}&desp=${desp}`, 311 | headers: { 312 | 'Content-Type': 'application/x-www-form-urlencoded', 313 | }, 314 | timeout, 315 | }; 316 | setTimeout(() => { 317 | $.post(options, (err, resp, data) => { 318 | try { 319 | if (err) { 320 | console.log('发送通知调用API失败!!\n'); 321 | console.log(err); 322 | } else { 323 | data = JSON.parse(data); 324 | //server酱和Server酱·Turbo版的返回json格式不太一样 325 | if (data.errno === 0 || data.data.errno === 0) { 326 | console.log('server酱发送通知消息成功🎉\n'); 327 | } else if (data.errno === 1024) { 328 | // 一分钟内发送相同的内容会触发 329 | console.log(`server酱发送通知消息异常: ${data.errmsg}\n`); 330 | } else { 331 | console.log( 332 | `server酱发送通知消息异常\n${JSON.stringify(data)}`, 333 | ); 334 | } 335 | } 336 | } catch (e) { 337 | $.logErr(e, resp); 338 | } finally { 339 | resolve(data); 340 | } 341 | }); 342 | }, time); 343 | } else { 344 | resolve(); 345 | } 346 | }); 347 | } 348 | 349 | function CoolPush(text, desp) { 350 | return new Promise((resolve) => { 351 | if (QQ_SKEY) { 352 | let options = { 353 | url: `https://push.xuthus.cc/${QQ_MODE}/${QQ_SKEY}`, 354 | headers: { 355 | 'Content-Type': 'application/json', 356 | }, 357 | }; 358 | 359 | // 已知敏感词 360 | text = text.replace(/京豆/g, '豆豆'); 361 | desp = desp.replace(/京豆/g, ''); 362 | desp = desp.replace(/🐶/g, ''); 363 | desp = desp.replace(/红包/g, 'H包'); 364 | 365 | switch (QQ_MODE) { 366 | case 'email': 367 | options.json = { 368 | t: text, 369 | c: desp, 370 | }; 371 | break; 372 | default: 373 | options.body = `${text}\n\n${desp}`; 374 | } 375 | 376 | let pushMode = function (t) { 377 | switch (t) { 378 | case 'send': 379 | return '个人'; 380 | case 'group': 381 | return 'QQ群'; 382 | case 'wx': 383 | return '微信'; 384 | case 'ww': 385 | return '企业微信'; 386 | case 'email': 387 | return '邮件'; 388 | default: 389 | return '未知方式'; 390 | } 391 | }; 392 | 393 | $.post(options, (err, resp, data) => { 394 | try { 395 | if (err) { 396 | console.log(`发送${pushMode(QQ_MODE)}通知调用API失败!!\n`); 397 | console.log(err); 398 | } else { 399 | data = JSON.parse(data); 400 | if (data.code === 200) { 401 | console.log(`酷推发送${pushMode(QQ_MODE)}通知消息成功🎉\n`); 402 | } else if (data.code === 400) { 403 | console.log( 404 | `QQ酷推(Cool Push)发送${pushMode(QQ_MODE)}推送失败:${ 405 | data.msg 406 | }\n`, 407 | ); 408 | } else if (data.code === 503) { 409 | console.log(`QQ酷推出错,${data.message}:${data.data}\n`); 410 | } else { 411 | console.log(`酷推推送异常: ${JSON.stringify(data)}`); 412 | } 413 | } 414 | } catch (e) { 415 | $.logErr(e, resp); 416 | } finally { 417 | resolve(data); 418 | } 419 | }); 420 | } else { 421 | resolve(); 422 | } 423 | }); 424 | } 425 | 426 | function BarkNotify(text, desp, params = {}) { 427 | return new Promise((resolve) => { 428 | if (BARK_PUSH) { 429 | const options = { 430 | url: `${BARK_PUSH}/${encodeURIComponent(text)}/${encodeURIComponent( 431 | desp, 432 | )}?sound=${BARK_SOUND}&group=${BARK_GROUP}&${querystring.stringify(params)}`, 433 | headers: { 434 | 'Content-Type': 'application/x-www-form-urlencoded', 435 | }, 436 | timeout, 437 | }; 438 | $.get(options, (err, resp, data) => { 439 | try { 440 | if (err) { 441 | console.log('Bark APP发送通知调用API失败!!\n'); 442 | console.log(err); 443 | } else { 444 | data = JSON.parse(data); 445 | if (data.code === 200) { 446 | console.log('Bark APP发送通知消息成功🎉\n'); 447 | } else { 448 | console.log(`${data.message}\n`); 449 | } 450 | } 451 | } catch (e) { 452 | $.logErr(e, resp); 453 | } finally { 454 | resolve(); 455 | } 456 | }); 457 | } else { 458 | resolve(); 459 | } 460 | }); 461 | } 462 | 463 | function tgBotNotify(text, desp) { 464 | return new Promise((resolve) => { 465 | if (TG_BOT_TOKEN && TG_USER_ID) { 466 | const options = { 467 | url: `https://${TG_API_HOST}/bot${TG_BOT_TOKEN}/sendMessage`, 468 | body: `chat_id=${TG_USER_ID}&text=${text}\n\n${desp}&disable_web_page_preview=true`, 469 | headers: { 470 | 'Content-Type': 'application/x-www-form-urlencoded', 471 | }, 472 | timeout, 473 | }; 474 | if (TG_PROXY_HOST && TG_PROXY_PORT) { 475 | const tunnel = require('tunnel'); 476 | const agent = { 477 | https: tunnel.httpsOverHttp({ 478 | proxy: { 479 | host: TG_PROXY_HOST, 480 | port: TG_PROXY_PORT * 1, 481 | proxyAuth: TG_PROXY_AUTH, 482 | }, 483 | }), 484 | }; 485 | Object.assign(options, { agent }); 486 | } 487 | $.post(options, (err, resp, data) => { 488 | try { 489 | if (err) { 490 | console.log('telegram发送通知消息失败!!\n'); 491 | console.log(err); 492 | } else { 493 | data = JSON.parse(data); 494 | if (data.ok) { 495 | console.log('Telegram发送通知消息成功🎉。\n'); 496 | } else if (data.error_code === 400) { 497 | console.log( 498 | '请主动给bot发送一条消息并检查接收用户ID是否正确。\n', 499 | ); 500 | } else if (data.error_code === 401) { 501 | console.log('Telegram bot token 填写错误。\n'); 502 | } 503 | } 504 | } catch (e) { 505 | $.logErr(e, resp); 506 | } finally { 507 | resolve(data); 508 | } 509 | }); 510 | } else { 511 | resolve(); 512 | } 513 | }); 514 | } 515 | function ddBotNotify(text, desp) { 516 | return new Promise((resolve) => { 517 | const options = { 518 | url: `https://oapi.dingtalk.com/robot/send?access_token=${DD_BOT_TOKEN}`, 519 | json: { 520 | msgtype: 'text', 521 | text: { 522 | content: ` ${text}\n\n${desp}`, 523 | }, 524 | }, 525 | headers: { 526 | 'Content-Type': 'application/json', 527 | }, 528 | timeout, 529 | }; 530 | if (DD_BOT_TOKEN && DD_BOT_SECRET) { 531 | const crypto = require('crypto'); 532 | const dateNow = Date.now(); 533 | const hmac = crypto.createHmac('sha256', DD_BOT_SECRET); 534 | hmac.update(`${dateNow}\n${DD_BOT_SECRET}`); 535 | const result = encodeURIComponent(hmac.digest('base64')); 536 | options.url = `${options.url}×tamp=${dateNow}&sign=${result}`; 537 | $.post(options, (err, resp, data) => { 538 | try { 539 | if (err) { 540 | console.log('钉钉发送通知消息失败!!\n'); 541 | console.log(err); 542 | } else { 543 | data = JSON.parse(data); 544 | if (data.errcode === 0) { 545 | console.log('钉钉发送通知消息成功🎉。\n'); 546 | } else { 547 | console.log(`${data.errmsg}\n`); 548 | } 549 | } 550 | } catch (e) { 551 | $.logErr(e, resp); 552 | } finally { 553 | resolve(data); 554 | } 555 | }); 556 | } else if (DD_BOT_TOKEN) { 557 | $.post(options, (err, resp, data) => { 558 | try { 559 | if (err) { 560 | console.log('钉钉发送通知消息失败!!\n'); 561 | console.log(err); 562 | } else { 563 | data = JSON.parse(data); 564 | if (data.errcode === 0) { 565 | console.log('钉钉发送通知消息完成。\n'); 566 | } else { 567 | console.log(`${data.errmsg}\n`); 568 | } 569 | } 570 | } catch (e) { 571 | $.logErr(e, resp); 572 | } finally { 573 | resolve(data); 574 | } 575 | }); 576 | } else { 577 | resolve(); 578 | } 579 | }); 580 | } 581 | 582 | function qywxBotNotify(text, desp) { 583 | return new Promise((resolve) => { 584 | const options = { 585 | url: `https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${QYWX_KEY}`, 586 | json: { 587 | msgtype: 'text', 588 | text: { 589 | content: ` ${text}\n\n${desp}`, 590 | }, 591 | }, 592 | headers: { 593 | 'Content-Type': 'application/json', 594 | }, 595 | timeout, 596 | }; 597 | if (QYWX_KEY) { 598 | $.post(options, (err, resp, data) => { 599 | try { 600 | if (err) { 601 | console.log('企业微信发送通知消息失败!!\n'); 602 | console.log(err); 603 | } else { 604 | data = JSON.parse(data); 605 | if (data.errcode === 0) { 606 | console.log('企业微信发送通知消息成功🎉。\n'); 607 | } else { 608 | console.log(`${data.errmsg}\n`); 609 | } 610 | } 611 | } catch (e) { 612 | $.logErr(e, resp); 613 | } finally { 614 | resolve(data); 615 | } 616 | }); 617 | } else { 618 | resolve(); 619 | } 620 | }); 621 | } 622 | 623 | function ChangeUserId(desp) { 624 | const QYWX_AM_AY = QYWX_AM.split(','); 625 | if (QYWX_AM_AY[2]) { 626 | const userIdTmp = QYWX_AM_AY[2].split('|'); 627 | let userId = ''; 628 | for (let i = 0; i < userIdTmp.length; i++) { 629 | const count = '账号' + (i + 1); 630 | const count2 = '签到号 ' + (i + 1); 631 | if (desp.match(count2)) { 632 | userId = userIdTmp[i]; 633 | } 634 | } 635 | if (!userId) userId = QYWX_AM_AY[2]; 636 | return userId; 637 | } else { 638 | return '@all'; 639 | } 640 | } 641 | 642 | function qywxamNotify(text, desp) { 643 | return new Promise((resolve) => { 644 | if (QYWX_AM) { 645 | const QYWX_AM_AY = QYWX_AM.split(','); 646 | const options_accesstoken = { 647 | url: `https://qyapi.weixin.qq.com/cgi-bin/gettoken`, 648 | json: { 649 | corpid: `${QYWX_AM_AY[0]}`, 650 | corpsecret: `${QYWX_AM_AY[1]}`, 651 | }, 652 | headers: { 653 | 'Content-Type': 'application/json', 654 | }, 655 | timeout, 656 | }; 657 | $.post(options_accesstoken, (err, resp, data) => { 658 | html = desp.replace(/\n/g, '
'); 659 | var json = JSON.parse(data); 660 | accesstoken = json.access_token; 661 | let options; 662 | 663 | switch (QYWX_AM_AY[4]) { 664 | case '0': 665 | options = { 666 | msgtype: 'textcard', 667 | textcard: { 668 | title: `${text}`, 669 | description: `${desp}`, 670 | url: 'https://github.com/whyour/qinglong', 671 | btntxt: '更多', 672 | }, 673 | }; 674 | break; 675 | 676 | case '1': 677 | options = { 678 | msgtype: 'text', 679 | text: { 680 | content: `${text}\n\n${desp}`, 681 | }, 682 | }; 683 | break; 684 | 685 | default: 686 | options = { 687 | msgtype: 'mpnews', 688 | mpnews: { 689 | articles: [ 690 | { 691 | title: `${text}`, 692 | thumb_media_id: `${QYWX_AM_AY[4]}`, 693 | author: `智能助手`, 694 | content_source_url: ``, 695 | content: `${html}`, 696 | digest: `${desp}`, 697 | }, 698 | ], 699 | }, 700 | }; 701 | } 702 | if (!QYWX_AM_AY[4]) { 703 | //如不提供第四个参数,则默认进行文本消息类型推送 704 | options = { 705 | msgtype: 'text', 706 | text: { 707 | content: `${text}\n\n${desp}`, 708 | }, 709 | }; 710 | } 711 | options = { 712 | url: `https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${accesstoken}`, 713 | json: { 714 | touser: `${ChangeUserId(desp)}`, 715 | agentid: `${QYWX_AM_AY[3]}`, 716 | safe: '0', 717 | ...options, 718 | }, 719 | headers: { 720 | 'Content-Type': 'application/json', 721 | }, 722 | }; 723 | 724 | $.post(options, (err, resp, data) => { 725 | try { 726 | if (err) { 727 | console.log( 728 | '成员ID:' + 729 | ChangeUserId(desp) + 730 | '企业微信应用消息发送通知消息失败!!\n', 731 | ); 732 | console.log(err); 733 | } else { 734 | data = JSON.parse(data); 735 | if (data.errcode === 0) { 736 | console.log( 737 | '成员ID:' + 738 | ChangeUserId(desp) + 739 | '企业微信应用消息发送通知消息成功🎉。\n', 740 | ); 741 | } else { 742 | console.log(`${data.errmsg}\n`); 743 | } 744 | } 745 | } catch (e) { 746 | $.logErr(e, resp); 747 | } finally { 748 | resolve(data); 749 | } 750 | }); 751 | }); 752 | } else { 753 | resolve(); 754 | } 755 | }); 756 | } 757 | 758 | function iGotNotify(text, desp, params = {}) { 759 | return new Promise((resolve) => { 760 | if (IGOT_PUSH_KEY) { 761 | // 校验传入的IGOT_PUSH_KEY是否有效 762 | const IGOT_PUSH_KEY_REGX = new RegExp('^[a-zA-Z0-9]{24}$'); 763 | if (!IGOT_PUSH_KEY_REGX.test(IGOT_PUSH_KEY)) { 764 | console.log('您所提供的IGOT_PUSH_KEY无效\n'); 765 | resolve(); 766 | return; 767 | } 768 | const options = { 769 | url: `https://push.hellyw.com/${IGOT_PUSH_KEY.toLowerCase()}`, 770 | body: `title=${text}&content=${desp}&${querystring.stringify(params)}`, 771 | headers: { 772 | 'Content-Type': 'application/x-www-form-urlencoded', 773 | }, 774 | timeout, 775 | }; 776 | $.post(options, (err, resp, data) => { 777 | try { 778 | if (err) { 779 | console.log('发送通知调用API失败!!\n'); 780 | console.log(err); 781 | } else { 782 | if (typeof data === 'string') data = JSON.parse(data); 783 | if (data.ret === 0) { 784 | console.log('iGot发送通知消息成功🎉\n'); 785 | } else { 786 | console.log(`iGot发送通知消息失败:${data.errMsg}\n`); 787 | } 788 | } 789 | } catch (e) { 790 | $.logErr(e, resp); 791 | } finally { 792 | resolve(data); 793 | } 794 | }); 795 | } else { 796 | resolve(); 797 | } 798 | }); 799 | } 800 | 801 | function pushPlusNotify(text, desp) { 802 | return new Promise((resolve) => { 803 | if (PUSH_PLUS_TOKEN) { 804 | desp = desp.replace(/[\n\r]/g, '
'); // 默认为html, 不支持plaintext 805 | const body = { 806 | token: `${PUSH_PLUS_TOKEN}`, 807 | title: `${text}`, 808 | content: `${desp}`, 809 | topic: `${PUSH_PLUS_USER}`, 810 | }; 811 | const options = { 812 | url: `https://www.pushplus.plus/send`, 813 | body: JSON.stringify(body), 814 | headers: { 815 | 'Content-Type': ' application/json', 816 | }, 817 | timeout, 818 | }; 819 | $.post(options, (err, resp, data) => { 820 | try { 821 | if (err) { 822 | console.log( 823 | `push+发送${ 824 | PUSH_PLUS_USER ? '一对多' : '一对一' 825 | }通知消息失败!!\n`, 826 | ); 827 | console.log(err); 828 | } else { 829 | data = JSON.parse(data); 830 | if (data.code === 200) { 831 | console.log( 832 | `push+发送${ 833 | PUSH_PLUS_USER ? '一对多' : '一对一' 834 | }通知消息完成。\n`, 835 | ); 836 | } else { 837 | console.log( 838 | `push+发送${ 839 | PUSH_PLUS_USER ? '一对多' : '一对一' 840 | }通知消息失败:${data.msg}\n`, 841 | ); 842 | } 843 | } 844 | } catch (e) { 845 | $.logErr(e, resp); 846 | } finally { 847 | resolve(data); 848 | } 849 | }); 850 | } else { 851 | resolve(); 852 | } 853 | }); 854 | } 855 | 856 | module.exports = { 857 | sendNotify, 858 | BARK_PUSH, 859 | }; 860 | 861 | // prettier-ignore 862 | function Env(t,s){return new class{constructor(t,s){this.name=t,this.data=null,this.dataFile="box.dat",this.logs=[],this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,s),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}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}getScript(t){return new Promise(s=>{$.get({url:t},(t,e,i)=>s(i))})}runScript(t,s){return new Promise(e=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let o=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");o=o?1*o:20,o=s&&s.timeout?s.timeout:o;const[h,a]=i.split("@"),r={url:`http://${a}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:o},headers:{"X-Key":h,Accept:"*/*"}};$.post(r,(t,s,i)=>e(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),s=this.path.resolve(process.cwd(),this.dataFile),e=this.fs.existsSync(t),i=!e&&this.fs.existsSync(s);if(!e&&!i)return{};{const i=e?t:s;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),s=this.path.resolve(process.cwd(),this.dataFile),e=this.fs.existsSync(t),i=!e&&this.fs.existsSync(s),o=JSON.stringify(this.data);e?this.fs.writeFileSync(t,o):i?this.fs.writeFileSync(s,o):this.fs.writeFileSync(t,o)}}lodash_get(t,s,e){const i=s.replace(/\[(\d+)\]/g,".$1").split(".");let o=t;for(const t of i)if(o=Object(o)[t],void 0===o)return e;return o}lodash_set(t,s,e){return Object(t)!==t?t:(Array.isArray(s)||(s=s.toString().match(/[^.[\]]+/g)||[]),s.slice(0,-1).reduce((t,e,i)=>Object(t[e])===t[e]?t[e]:t[e]=Math.abs(s[i+1])>>0==+s[i+1]?[]:{},t)[s[s.length-1]]=e,t)}getdata(t){let s=this.getval(t);if(/^@/.test(t)){const[,e,i]=/^@(.*?)\.(.*?)$/.exec(t),o=e?this.getval(e):"";if(o)try{const t=JSON.parse(o);s=t?this.lodash_get(t,i,""):s}catch(t){s=""}}return s}setdata(t,s){let e=!1;if(/^@/.test(s)){const[,i,o]=/^@(.*?)\.(.*?)$/.exec(s),h=this.getval(i),a=i?"null"===h?null:h||"{}":"{}";try{const s=JSON.parse(a);this.lodash_set(s,o,t),e=this.setval(JSON.stringify(s),i)}catch(s){const h={};this.lodash_set(h,o,t),e=this.setval(JSON.stringify(h),i)}}else e=$.setval(t,s);return e}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,s){return this.isSurge()||this.isLoon()?$persistentStore.write(t,s):this.isQuanX()?$prefs.setValueForKey(t,s):this.isNode()?(this.data=this.loaddata(),this.data[s]=t,this.writedata(),!0):this.data&&this.data[s]||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,s=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?$httpClient.get(t,(t,e,i)=>{!t&&e&&(e.body=i,e.statusCode=e.status),s(t,e,i)}):this.isQuanX()?$task.fetch(t).then(t=>{const{statusCode:e,statusCode:i,headers:o,body:h}=t;s(null,{status:e,statusCode:i,headers:o,body:h},h)},t=>s(t)):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,s)=>{try{const e=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();this.ckjar.setCookieSync(e,null),s.cookieJar=this.ckjar}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:e,statusCode:i,headers:o,body:h}=t;s(null,{status:e,statusCode:i,headers:o,body:h},h)},t=>s(t)))}post(t,s=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),delete t.headers["Content-Length"],this.isSurge()||this.isLoon())$httpClient.post(t,(t,e,i)=>{!t&&e&&(e.body=i,e.statusCode=e.status),s(t,e,i)});else if(this.isQuanX())t.method="POST",$task.fetch(t).then(t=>{const{statusCode:e,statusCode:i,headers:o,body:h}=t;s(null,{status:e,statusCode:i,headers:o,body:h},h)},t=>s(t));else if(this.isNode()){this.initGotEnv(t);const{url:e,...i}=t;this.got.post(e,i).then(t=>{const{statusCode:e,statusCode:i,headers:o,body:h}=t;s(null,{status:e,statusCode:i,headers:o,body:h},h)},t=>s(t))}}time(t){let s={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in s)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?s[e]:("00"+s[e]).substr((""+s[e]).length)));return t}msg(s=t,e="",i="",o){const h=t=>!t||!this.isLoon()&&this.isSurge()?t:"string"==typeof t?this.isLoon()?t:this.isQuanX()?{"open-url":t}:void 0:"object"==typeof t&&(t["open-url"]||t["media-url"])?this.isLoon()?t["open-url"]:this.isQuanX()?t:void 0:void 0;$.isMute||(this.isSurge()||this.isLoon()?$notification.post(s,e,i,h(o)):this.isQuanX()&&$notify(s,e,i,h(o))),this.logs.push("","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="),this.logs.push(s),e&&this.logs.push(e),i&&this.logs.push(i)}log(...t){t.length>0?this.logs=[...this.logs,...t]:console.log(this.logs.join(this.logSeparator))}logErr(t,s){const e=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();e?$.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):$.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(s=>setTimeout(s,t))}done(t={}){const s=(new Date).getTime(),e=(s-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${e} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,s)} 863 | -------------------------------------------------------------------------------- /wzxy_check.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 作者QQ: 1483081359 欢迎前来提交bug 3 | * github仓库:https://github.com/zhacha222/wozaixiaoyuan 4 | * 微信小程序:我在校园 账号检测 5 | * 脚本说明:此脚本用于延长【我在校园】账号的有效时长,防止账号过期(务必启用!务必启用!务必启用!) 6 | * 默认定时:默认每天运行两次,如果你每天都需要频繁登录手机端,也可以自己改定时每天多运行几次防止账号失效 7 | * cron: 15 11,23 * * * 8 | * 变量名称:wzxy 9 | * 变量值: { 10 | "username": "手机号", 11 | "password": "密码", 12 | "qd_location": "133.333333,33.333333", 13 | "rjrb_answers": ["0","0"], 14 | "rjrb_location": "133.333333,33.333333", 15 | "jkdk_answers": ["0","无","1","0","36.2","没有","1","1","2"], 16 | "jkdk_location": "133.333333,33.333333", 17 | "mark": "用户昵称" 18 | } 19 | 20 | ***一些前提说明: 21 | 1.只支持青龙面板(本人青龙版本2.10.13),搭建教程自行百度 22 | 2.本库脚本通用 wzxy这一个变量 23 | 3.脚本变量只推荐在青龙的【环境变量】页添加,有强迫症在【配置文件】config.sh中添加的如果出现问题自己解决 24 | 4.支持多用户,每一用户在【环境变量】单独新建变量wzxy,切勿一个变量内填写多个用户的参数 25 | 5.脚本通知方式采用青龙面板默认通知,请在【配置文件】config.sh里配置 26 | 6.关于各脚本的具体使用方法,请阅读脚本内的注释 27 | 28 | ***关于变量值中各参数的解释: 29 | username ———————— 手机号 30 | password —————————密码 31 | qd_location ————— 签到的`经纬度` (wzxy_qd.js) 32 | rjrb_answers —————日检日报的`填空参数`(wzxy_rjrb.js) 33 | rjrb_location ————日检日报的`经纬度` (wzxy_rjrb.js) 34 | jkdk_answers ———— 健康签到的`填空参数`(wzxy_jkdk.js) 35 | jkdk_location ————健康签到的`经纬度` (wzxy_jkdk.js) 36 | mark —————————————用户昵称(不一定要真名,随便填都行,便于自己区分打卡用户) 37 | 38 | ***更新日志: 39 | 1.0.0 完成账号检测的基本功能:检测,重置密码,更新jwsession 40 | 1.0.1 增加账号失效自动禁用 增加仅账号失效通知 41 | 1.0.2 增加等待15s,防止黑ip 42 | 1.0.5 适配青龙最新版 43 | 1.0.6 优化通知 44 | 1.0.7 log增加新版本内容 45 | 46 | 47 | */ 48 | 49 | //cron: 15 11,23 * * * 50 | //===============通知设置=================// 51 | const Notify = 1; //0为关闭通知,1为打开通知,默认为1 52 | const errorNotify = 0; //0为关闭仅账号失效通知,1为打开仅账号失效通知,默认为0 53 | //////////////////////////////////////////// 54 | const $ = new Env('账号检测'); 55 | const {log} = console; 56 | const notify = $.isNode() ? require('./sendNotify') : ''; 57 | const request = require('request'); 58 | const got = require('got'); 59 | require('dotenv').config(); 60 | const { readFile } = require('fs/promises'); 61 | const path = require('path'); 62 | const qlDir = '/ql'; 63 | const fs = require('fs'); 64 | let Fileexists = fs.existsSync('/ql/data/config/auth.json'); 65 | let authFile=""; 66 | if (Fileexists) 67 | authFile="/ql/data/config/auth.json" 68 | else 69 | authFile="/ql/config/auth.json" 70 | //const authFile = path.join(qlDir, 'config/auth.json'); 71 | 72 | const api = got.extend({ 73 | prefixUrl: 'http://127.0.0.1:5600', 74 | retry: { limit: 0 }, 75 | }); 76 | //我在校园账号数据 77 | let scriptVersion = "1.0.7"; 78 | let scriptVersionLatest = ''; 79 | let update_data = "1.0.7 log增加新版本内容"; //新版本更新内容 80 | let wzxyArr = []; 81 | let wait = 0; 82 | let checkBack = 0; 83 | let passwordchangeBack = 0; 84 | let msg = ''; 85 | let jwsession = ''; 86 | let status_code = 0; 87 | let status_code1 = 0; 88 | let eid = ''; 89 | 90 | 91 | !(async () => { 92 | if (typeof $request !== "undefined") { 93 | await GetRewrite(); 94 | } else { 95 | if (!(await getEnvs())) 96 | return; 97 | else { 98 | 99 | log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( 100 | new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + 101 | 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); 102 | 103 | await poem(); 104 | await getVersion(); 105 | 106 | log(`\n============ 当前版本:${scriptVersion} 最新版本:${scriptVersionLatest} ============`) 107 | 108 | if(scriptVersionLatest != scriptVersion){ 109 | log(`\n发现新版本,请及时拉库更新!\n${update_data}`) 110 | } 111 | 112 | log(`\n=================== 共找到 ${wzxyArr.length} 个账号 ===================`) 113 | //log(wzxyArr[0]) 114 | 115 | 116 | for (let index = 0; index < wzxyArr.length; index++) { 117 | 118 | 119 | let num = index + 1 120 | if (num >1&& wait == 0){ 121 | log('**********休息15s,防止黑IP**********'); 122 | await $.wait(16 * 1000); 123 | } 124 | log(`\n========= 开始检测【第 ${num} 个账号】=========\n`) 125 | eid = wzxyArr[index]._id 126 | status = wzxyArr[index].status 127 | data = JSON.parse(wzxyArr[index].value) 128 | //log(data) 129 | username = data.username 130 | password = data.password 131 | mark = data.mark 132 | 133 | log(`检测用户: ${mark}`) 134 | if (status == 1) { 135 | log(`🚫 账号已禁用`) 136 | status_code = 3 137 | status_code1 = 3 138 | wait = 1 139 | }else{ 140 | wait = 0 141 | checkBack = 0;//置0,防止上一个号影响下一个号 142 | await check() 143 | await $.wait(2 * 1000); 144 | 145 | if (checkBack > 0) { 146 | await passwordchange() 147 | await $.wait(2 * 1000); 148 | 149 | if (passwordchangeBack > 0) { 150 | log(`正在更新jwsession...`) 151 | await login() 152 | await $.wait(2 * 1000); 153 | 154 | } 155 | 156 | } 157 | } 158 | var resultlog = getResult() 159 | var updatelog = getupdateResult() 160 | 161 | if (errorNotify>0){ 162 | if (status_code != 1 || status_code1 !=1){ 163 | msg += `检测用户:${mark}\n${resultlog}\n${updatelog}\n\n` 164 | } 165 | }else { 166 | msg += `检测用户:${mark}\n${resultlog}\n${updatelog}\n\n` 167 | } 168 | 169 | } 170 | // log(msg); 171 | await SendMsg(msg); 172 | } 173 | } 174 | 175 | })() 176 | .catch((e) => log(e)) 177 | .finally(() => $.done()) 178 | 179 | 180 | 181 | 182 | /** 183 | * 检测账号是否失效 184 | */ 185 | function check(timeout = 3 * 1000) { 186 | return new Promise((resolve) => { 187 | let url = { 188 | url: `https://gw.wozaixiaoyuan.com/basicinfo/mobile/login/username?username=${username}&password=${password}`, 189 | headers: { 190 | "Accept-Encoding": "gzip, deflate, br", 191 | "Connection": "keep-alive", 192 | "User-Agent": "Mozilla/5.0 (iPad; CPU OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.23(0x1800172f) NetType/WIFI Language/zh_CN miniProgram/wxce6d08f781975d91", 193 | "content-type": "application/json;charset=UTF-8", 194 | "Content-Length": "2", 195 | "Host": "gw.wozaixiaoyuan.com", 196 | "Accept-Language": "en-us,en", 197 | "Accept": "application/json, text/plain, */*" 198 | }, 199 | data: ``, 200 | } 201 | request.post(url, async (error, response, data) => { 202 | try { 203 | let result = data == "undefined" ? await check() : JSON.parse(data); 204 | 205 | //登录成功 206 | if (result.code == 0 ) { 207 | 208 | jwsession = response.headers['jwsession'] 209 | log(`账号未失效,开始重置密码...`) 210 | checkBack = 1; 211 | status_code = 1; 212 | } 213 | else { 214 | log(`❌ 账号已失效,尝试使用jwsession更新`) 215 | checkJwsession() 216 | status_code = 2; 217 | } 218 | 219 | } catch (e) { 220 | log(e) 221 | } finally { 222 | resolve(); 223 | } 224 | }, timeout) 225 | }) 226 | } 227 | 228 | 229 | /** 230 | * 判断jwsession是否存在 231 | */ 232 | function checkJwsession() { 233 | 234 | fs.open('.cache/' + username + ".json", 'r+', function(err, fd) { 235 | if (err) { 236 | console.error("jwsession不存在,开始禁用账号...") 237 | DisableCk(eid) 238 | return 239 | } 240 | var read = fs.readFileSync('.cache/' + username + ".json") 241 | jwsession = read.toString() 242 | if (jwsession == ``){ 243 | console.log("jwsession不存在,开始禁用账号..." + 244 | "") 245 | DisableCk(eid) 246 | return 247 | }else{ 248 | log(`找到jwsession,正在重置密码...`) 249 | checkBack = 1 250 | } 251 | }); 252 | 253 | } 254 | 255 | 256 | /** 257 | * 重置密码 以延长账号有效期 258 | */ 259 | function passwordchange(timeout = 3 * 1000) { 260 | return new Promise((resolve) => { 261 | let url = { 262 | url: `https://gw.wozaixiaoyuan.com/basicinfo/mobile/my/changePassword?oldPassword=${password}&newPassword=${password}`, 263 | headers: { 264 | "Accept":"application/json, text/plain, */*", 265 | "Accept-Encoding":"gzip, deflate, br", 266 | "Cookie":"JWSESSION=1ed2d1bda1fe4975a4a128acd837b787", 267 | "Content-Type":"application/json;charset=UTF-8", 268 | "Referer":"https://gw.wozaixiaoyuan.com/h5/mobile/basicinfo/index/my/changePassword", 269 | "Host":"gw.wozaixiaoyuan.com", 270 | "User-Agent":"Mozilla/5.0 (iPad; CPU OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.23(0x1800172f) NetType/WIFI Language/zh_CN miniProgram/wxce6d08f781975d91", 271 | "Connection":"keep-alive", 272 | "Accept-Language":"zh-CN,zh-Hans;q=0.9", 273 | "JWSESSION":jwsession, 274 | }, 275 | data: ``, 276 | } 277 | 278 | request.get(url, async (error, response, data) => { 279 | try { 280 | let result = data == "undefined" ? await passwordchange() : JSON.parse(data); 281 | 282 | if (result.code == 0 ) { 283 | log(`✅ 密码重置成功`) 284 | status_code1 = 1 285 | passwordchangeBack = 1 286 | }else{ 287 | log(`❌ jwsession已失效,开始禁用账号...`) 288 | DisableCk(eid) 289 | status_code1 = 2 290 | passwordchangeBack = 0 291 | 292 | } 293 | 294 | } catch (e) { 295 | log(e) 296 | } finally { 297 | resolve(); 298 | } 299 | }, timeout) 300 | }) 301 | } 302 | 303 | 304 | 305 | /** 306 | * 登录 307 | */ 308 | function login(timeout = 3 * 1000) { 309 | return new Promise((resolve) => { 310 | let url = { 311 | url: `https://gw.wozaixiaoyuan.com/basicinfo/mobile/login/username?username=${username}&password=${password}`, 312 | headers: { 313 | "Accept-Encoding": "gzip, deflate, br", 314 | "Connection": "keep-alive", 315 | "User-Agent": "Mozilla/5.0 (iPad; CPU OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.23(0x1800172f) NetType/WIFI Language/zh_CN miniProgram/wxce6d08f781975d91", 316 | "content-type": "application/json;charset=UTF-8", 317 | "Content-Length": "2", 318 | "Host": "gw.wozaixiaoyuan.com", 319 | "Accept-Language": "en-us,en", 320 | "Accept": "application/json, text/plain, */*" 321 | }, 322 | data: ``, 323 | } 324 | 325 | 326 | request.post(url, async (error, response, data) => { 327 | try { 328 | let result = data == "undefined" ? await login() : JSON.parse(data); 329 | 330 | //登录成功 331 | if (result.code == 0 ) { 332 | jwsession = response.headers['jwsession'] 333 | setJwsession(jwsession) 334 | 335 | } else { 336 | log(`❌ 更新失败,${result.message}`) 337 | } 338 | 339 | } catch (e) { 340 | log(e) 341 | } finally { 342 | resolve(); 343 | } 344 | }, timeout) 345 | }) 346 | } 347 | 348 | 349 | /** 350 | * 获取账号检测结果 351 | */ 352 | function getResult(timeout = 3 * 1000) { 353 | res = status_code 354 | if (res == 1) return "✅ 账号未失效" 355 | if (res == 2) return "❌ 账号已失效" 356 | if (res == 3) return "🚫 账号已被禁用,请及时更新" 357 | else return "❌ 发生未知错误" 358 | } 359 | 360 | 361 | /** 362 | * 获取账号更新结果 363 | */ 364 | function getupdateResult(timeout = 3 * 1000) { 365 | res1 = status_code1 366 | if (res1 == 1) return "✅ 账号更新成功" 367 | if (res1 == 2) return "❌ 账号更新失败,请手动更改密码后重新登录" 368 | if (res1 == 3) return "" 369 | if (res1 == 4) return "🚫 账号禁用成功" 370 | else return "❌ 发生未知错误" 371 | } 372 | 373 | 374 | /** 375 | * 存储jwsession 376 | */ 377 | function setJwsession(jwsession) { 378 | 379 | fs.mkdir('.cache',function(err){ 380 | if (err) { 381 | 382 | console.log("找到cache文件"); 383 | } 384 | else console.log("正在创建cache储存目录与文件..."); 385 | }); 386 | 387 | fs.writeFile('.cache/' + username + ".json", jwsession, function(err) { 388 | if (err) { 389 | return console.error(err); 390 | } 391 | console.log("✅ jwsession成功更新"); 392 | 393 | }) 394 | 395 | } 396 | 397 | // ============================================变量检查============================================ \\ 398 | 399 | async function getToken() { 400 | const authConfig = JSON.parse(await readFile(authFile)); 401 | //console.log(authConfig) 402 | return authConfig.token; 403 | } 404 | 405 | 406 | async function getEnvs() { 407 | const token = await getToken(); 408 | const body = await api({ 409 | url: 'api/envs', 410 | searchParams: { 411 | searchValue: 'wzxy', 412 | t: Date.now(), 413 | }, 414 | headers: { 415 | Accept: 'application/json', 416 | authorization: `Bearer ${token}`, 417 | }, 418 | }).json(); 419 | for(var i=0,j=0;i 0) { 456 | if ($.isNode()) { 457 | var notify = require('./sendNotify'); 458 | await notify.sendNotify($.name, msg+ `\n检测时间:${t()}\n`); 459 | } else { 460 | $.msg(msg); 461 | } 462 | } else { 463 | //log(msg); 464 | } 465 | } 466 | 467 | /** 468 | * 随机数生成 469 | */ 470 | function randomString(e) { 471 | e = e || 32; 472 | var t = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890", 473 | a = t.length, 474 | n = ""; 475 | for (i = 0; i < e; i++) 476 | n += t.charAt(Math.floor(Math.random() * a)); 477 | return n 478 | } 479 | 480 | /** 481 | * 随机整数生成 482 | */ 483 | function randomInt(min, max) { 484 | return Math.round(Math.random() * (max - min) + min) 485 | } 486 | 487 | /** 488 | * 获取毫秒时间戳 489 | */ 490 | function timestampMs(){ 491 | return new Date().getTime(); 492 | } 493 | 494 | /** 495 | * 496 | * 获取秒时间戳 497 | */ 498 | function timestampS(){ 499 | return Date.parse(new Date())/1000; 500 | } 501 | 502 | /** 503 | * 获取随机诗词 504 | */ 505 | function poem(timeout = 3 * 1000) { 506 | return new Promise((resolve) => { 507 | let url = { 508 | url: `https://v1.jinrishici.com/all.json` 509 | } 510 | $.get(url, async (err, resp, data) => { 511 | try { 512 | data = JSON.parse(data) 513 | log(`${data.content} \n————《${data.origin}》${data.author}`); 514 | } catch (e) { 515 | log(e, resp); 516 | } finally { 517 | resolve() 518 | } 519 | }, timeout) 520 | }) 521 | } 522 | 523 | /** 524 | * 修改配置文件 525 | */ 526 | function modify() { 527 | 528 | fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ 529 | if(err){ 530 | return log('读取文件失败!'+err) 531 | } 532 | else { 533 | var result = dataStr.replace(/regular/g,string); 534 | fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { 535 | if (err) {return log(err);} 536 | }); 537 | } 538 | }) 539 | } 540 | 541 | /** 542 | * 获取远程版本 543 | */ 544 | function getVersion(timeout = 3 * 1000) { 545 | return new Promise((resolve) => { 546 | let url = { 547 | url: `https://ghproxy.com/https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/main/wzxy_check.js`, 548 | } 549 | $.get(url, async (err, resp, data) => { 550 | try { 551 | scriptVersionLatest = data.match(/scriptVersion = "([\d\.]+)"/)[1] 552 | update_data = data.match(/update_data = "(.*?)"/)[1] 553 | } catch (e) { 554 | $.logErr(e, resp); 555 | } finally { 556 | resolve() 557 | } 558 | }, timeout) 559 | }) 560 | } 561 | 562 | /** 563 | * time 输出格式:1970-01-01 00:00:00 564 | */ 565 | function t() { 566 | var date = new Date(); 567 | // 获取当前月份 568 | var nowMonth = date.getMonth() + 1; 569 | // 获取当前是几号 570 | var strDate = date.getDate(); 571 | //获取当前小时(0-23) 572 | var nowhour = date.getHours() 573 | //获取当前分钟(0-59) 574 | var nowMinute = date.getMinutes() 575 | //获取当前秒数(0-59) 576 | var nowSecond = date.getSeconds(); 577 | // 添加分隔符“-” 578 | var seperator = "-"; 579 | // 添加分隔符“:” 580 | var seperator1 = ":"; 581 | 582 | // 对月份进行处理,1-9月在前面添加一个“0” 583 | if (nowMonth >= 1 && nowMonth <= 9) { 584 | nowMonth = "0" + nowMonth; 585 | } 586 | // 对月份进行处理,1-9号在前面添加一个“0” 587 | if (strDate >= 0 && strDate <= 9) { 588 | strDate = "0" + strDate; 589 | } 590 | // 对小时进行处理,0-9号在前面添加一个“0” 591 | if (nowhour >= 0 && nowhour <= 9) { 592 | nowhour = "0" + nowhour; 593 | } 594 | // 对分钟进行处理,0-9号在前面添加一个“0” 595 | if (nowMinute >= 0 && nowMinute <= 9) { 596 | nowMinute = "0" + nowMinute; 597 | } 598 | // 对秒数进行处理,0-9号在前面添加一个“0” 599 | if (nowSecond >= 0 && nowSecond <= 9) { 600 | nowSecond = "0" + nowSecond; 601 | } 602 | 603 | // 最后拼接字符串,得到一个格式为(yyyy-MM-dd)的日期 604 | var nowDate = date.getFullYear() + seperator + nowMonth + seperator + strDate + ` ` + nowhour + seperator1 + nowMinute + seperator1 + nowSecond 605 | return nowDate 606 | } 607 | 608 | function Env(t, e) { 609 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 610 | class s { 611 | constructor(t) { 612 | this.env = t 613 | } 614 | send(t, e = "GET") { 615 | t = "string" == typeof t ? { 616 | url: t 617 | } : t; 618 | let s = this.get; 619 | return "POST" === e && (s = this.post), new Promise((e, i) => { 620 | s.call(this, t, (t, s, r) => { 621 | t ? i(t) : e(s) 622 | }) 623 | }) 624 | } 625 | get(t) { 626 | return this.send.call(this.env, t) 627 | } 628 | post(t) { 629 | return this.send.call(this.env, t, "POST") 630 | } 631 | } 632 | return new class { 633 | constructor(t, e) { 634 | 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}, 开始!`) 635 | } 636 | isNode() { 637 | return "undefined" != typeof module && !!module.exports 638 | } 639 | isQuanX() { 640 | return "undefined" != typeof $task 641 | } 642 | isSurge() { 643 | return "undefined" != typeof $httpClient && "undefined" == typeof $loon 644 | } 645 | isLoon() { 646 | return "undefined" != typeof $loon 647 | } 648 | toObj(t, e = null) { 649 | try { 650 | return JSON.parse(t) 651 | } catch { 652 | return e 653 | } 654 | } 655 | toStr(t, e = null) { 656 | try { 657 | return JSON.stringify(t) 658 | } catch { 659 | return e 660 | } 661 | } 662 | getjson(t, e) { 663 | let s = e; 664 | const i = this.getdata(t); 665 | if (i) try { 666 | s = JSON.parse(this.getdata(t)) 667 | } catch {} 668 | return s 669 | } 670 | setjson(t, e) { 671 | try { 672 | return this.setdata(JSON.stringify(t), e) 673 | } catch { 674 | return !1 675 | } 676 | } 677 | getScript(t) { 678 | return new Promise(e => { 679 | this.get({ 680 | url: t 681 | }, (t, s, i) => e(i)) 682 | }) 683 | } 684 | runScript(t, e) { 685 | return new Promise(s => { 686 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 687 | i = i ? i.replace(/\n/g, "").trim() : i; 688 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 689 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 690 | const [o, h] = i.split("@"), n = { 691 | url: `http://${h}/v1/scripting/evaluate`, 692 | body: { 693 | script_text: t, 694 | mock_type: "cron", 695 | timeout: r 696 | }, 697 | headers: { 698 | "X-Key": o, 699 | Accept: "*/*" 700 | } 701 | }; 702 | this.post(n, (t, e, i) => s(i)) 703 | }).catch(t => this.logErr(t)) 704 | } 705 | loaddata() { 706 | if (!this.isNode()) return {}; { 707 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 708 | const t = this.path.resolve(this.dataFile), 709 | e = this.path.resolve(process.cwd(), this.dataFile), 710 | s = this.fs.existsSync(t), 711 | i = !s && this.fs.existsSync(e); 712 | if (!s && !i) return {}; { 713 | const i = s ? t : e; 714 | try { 715 | return JSON.parse(this.fs.readFileSync(i)) 716 | } catch (t) { 717 | return {} 718 | } 719 | } 720 | } 721 | } 722 | writedata() { 723 | if (this.isNode()) { 724 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 725 | const t = this.path.resolve(this.dataFile), 726 | e = this.path.resolve(process.cwd(), this.dataFile), 727 | s = this.fs.existsSync(t), 728 | i = !s && this.fs.existsSync(e), 729 | r = JSON.stringify(this.data); 730 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 731 | } 732 | } 733 | lodash_get(t, e, s) { 734 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 735 | let r = t; 736 | for (const t of i) 737 | if (r = Object(r)[t], void 0 === r) return s; 738 | return r 739 | } 740 | lodash_set(t, e, s) { 741 | 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) 742 | } 743 | getdata(t) { 744 | let e = this.getval(t); 745 | if (/^@/.test(t)) { 746 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; 747 | if (r) try { 748 | const t = JSON.parse(r); 749 | e = t ? this.lodash_get(t, i, "") : e 750 | } catch (t) { 751 | e = "" 752 | } 753 | } 754 | return e 755 | } 756 | setdata(t, e) { 757 | let s = !1; 758 | if (/^@/.test(e)) { 759 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; 760 | try { 761 | const e = JSON.parse(h); 762 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) 763 | } catch (e) { 764 | const o = {}; 765 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) 766 | } 767 | } else s = this.setval(t, e); 768 | return s 769 | } 770 | getval(t) { 771 | 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 772 | } 773 | setval(t, e) { 774 | 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 775 | } 776 | initGotEnv(t) { 777 | 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)) 778 | } 779 | get(t, e = (() => {})) { 780 | 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, { 781 | "X-Surge-Skip-Scripting": !1 782 | })), $httpClient.get(t, (t, s, i) => { 783 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 784 | })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 785 | hints: !1 786 | })), $task.fetch(t).then(t => { 787 | const { 788 | statusCode: s, 789 | statusCode: i, 790 | headers: r, 791 | body: o 792 | } = t; 793 | e(null, { 794 | status: s, 795 | statusCode: i, 796 | headers: r, 797 | body: o 798 | }, o) 799 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 800 | try { 801 | if (t.headers["set-cookie"]) { 802 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 803 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar 804 | } 805 | } catch (t) { 806 | this.logErr(t) 807 | } 808 | }).then(t => { 809 | const { 810 | statusCode: s, 811 | statusCode: i, 812 | headers: r, 813 | body: o 814 | } = t; 815 | e(null, { 816 | status: s, 817 | statusCode: i, 818 | headers: r, 819 | body: o 820 | }, o) 821 | }, t => { 822 | const { 823 | message: s, 824 | response: i 825 | } = t; 826 | e(s, i, i && i.body) 827 | })) 828 | } 829 | post(t, e = (() => {})) { 830 | 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, { 831 | "X-Surge-Skip-Scripting": !1 832 | })), $httpClient.post(t, (t, s, i) => { 833 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 834 | }); 835 | else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 836 | hints: !1 837 | })), $task.fetch(t).then(t => { 838 | const { 839 | statusCode: s, 840 | statusCode: i, 841 | headers: r, 842 | body: o 843 | } = t; 844 | e(null, { 845 | status: s, 846 | statusCode: i, 847 | headers: r, 848 | body: o 849 | }, o) 850 | }, t => e(t)); 851 | else if (this.isNode()) { 852 | this.initGotEnv(t); 853 | const { 854 | url: s, 855 | ...i 856 | } = t; 857 | this.got.post(s, i).then(t => { 858 | const { 859 | statusCode: s, 860 | statusCode: i, 861 | headers: r, 862 | body: o 863 | } = t; 864 | e(null, { 865 | status: s, 866 | statusCode: i, 867 | headers: r, 868 | body: o 869 | }, o) 870 | }, t => { 871 | const { 872 | message: s, 873 | response: i 874 | } = t; 875 | e(s, i, i && i.body) 876 | }) 877 | } 878 | } 879 | time(t, e = null) { 880 | const s = e ? new Date(e) : new Date; 881 | let i = { 882 | "M+": s.getMonth() + 1, 883 | "d+": s.getDate(), 884 | "H+": s.getHours(), 885 | "m+": s.getMinutes(), 886 | "s+": s.getSeconds(), 887 | "q+": Math.floor((s.getMonth() + 3) / 3), 888 | S: s.getMilliseconds() 889 | }; 890 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 891 | 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))); 892 | return t 893 | } 894 | msg(e = t, s = "", i = "", r) { 895 | const o = t => { 896 | if (!t) return t; 897 | if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { 898 | "open-url": t 899 | } : this.isSurge() ? { 900 | url: t 901 | } : void 0; 902 | if ("object" == typeof t) { 903 | if (this.isLoon()) { 904 | let e = t.openUrl || t.url || t["open-url"], 905 | s = t.mediaUrl || t["media-url"]; 906 | return { 907 | openUrl: e, 908 | mediaUrl: s 909 | } 910 | } 911 | if (this.isQuanX()) { 912 | let e = t["open-url"] || t.url || t.openUrl, 913 | s = t["media-url"] || t.mediaUrl; 914 | return { 915 | "open-url": e, 916 | "media-url": s 917 | } 918 | } 919 | if (this.isSurge()) { 920 | let e = t.url || t.openUrl || t["open-url"]; 921 | return { 922 | url: e 923 | } 924 | } 925 | } 926 | }; 927 | if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { 928 | let t = ["", "==============📣系统通知📣=============="]; 929 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) 930 | } 931 | } 932 | log(...t) { 933 | t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) 934 | } 935 | logErr(t, e) { 936 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 937 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 938 | } 939 | wait(t) { 940 | return new Promise(e => setTimeout(e, t)) 941 | } 942 | done(t = {}) { 943 | const e = (new Date).getTime(), 944 | s = (e - this.startTime) / 1e3; 945 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 946 | } 947 | }(t, e) 948 | } 949 | -------------------------------------------------------------------------------- /wzxy_qd.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 作者QQ: 1483081359 欢迎前来提交bug 3 | * github仓库:https://github.com/zhacha222/wozaixiaoyuan 4 | * 微信小程序:我在校园 签到 5 | * 脚本说明:适用于我在校园所有类型的签到,包括定位、蓝牙签到等··· 6 | * 默认定时:默认不自动运行,在签到发布后,需要手动运行一次此脚本(当然,如果你有定时的签到,也可以自己去修改定时规则,在签到时间内定时运行该脚本即可) 7 | * cron: 0 8 | * 变量名称:wzxy 9 | * 变量值: { 10 | "username": "手机号", 11 | "password": "密码", 12 | "qd_location": "133.333333,33.333333", 13 | "rjrb_answers": ["0","0"], 14 | "rjrb_location": "133.333333,33.333333", 15 | "jkdk_answers": ["0","无","1","0","36.2","没有","1","1","2"], 16 | "jkdk_location": "133.333333,33.333333", 17 | "mark": "用户昵称" 18 | } 19 | 20 | ***一些前提说明: 21 | 1.只支持青龙面板(本人青龙版本2.10.13),搭建教程自行百度 22 | 2.本库脚本通用 wzxy这一个变量 23 | 3.脚本变量只推荐在青龙的【环境变量】页添加,有强迫症在【配置文件】config.sh中添加的如果出现问题自己解决 24 | 4.支持多用户,每一用户在【环境变量】单独新建变量wzxy,切勿一个变量内填写多个用户的参数 25 | 5.脚本通知方式采用青龙面板默认通知,请在【配置文件】config.sh里配置 26 | 6.关于各脚本的具体使用方法,请阅读脚本内的注释 27 | 28 | ***关于变量值中各参数的解释: 29 | username ———————— 手机号 30 | password —————————密码 31 | qd_location ————— 签到的`经纬度` (wzxy_qd.js) 32 | rjrb_answers —————日检日报的`填空参数`(wzxy_rjrb.js) 33 | rjrb_location ————日检日报的`经纬度` (wzxy_rjrb.js) 34 | jkdk_answers ———— 健康签到的`填空参数`(wzxy_jkdk.js) 35 | jkdk_location ————健康签到的`经纬度` (wzxy_jkdk.js) 36 | mark —————————————用户昵称(不一定要真名,随便填都行,便于自己区分打卡用户) 37 | 38 | 更新日志: 39 | 1.0.0 完成签到的基本功能 40 | 1.0.1 增加等待15s,防止黑ip 41 | 1.0.2 增加完整参数验证 42 | 1.0.5 修复地址信息请求失败的bug 43 | 1.0.6 优化通知 44 | 1.0.7 log增加新版本内容 45 | 1.0.8 增加`仅通知签到失败`模式,在脚本第52行修改开启 46 | 47 | */ 48 | //cron: 0 49 | 50 | //===============通知设置=================// 51 | const Notify = 1; //0为关闭通知,1为打开通知,默认为1 52 | const OnlyErrorNotify = 0; //0为关闭`仅通知签到失败`模式,1为打开`仅通知签到失败`模式,默认为0 53 | //////////////////////////////////////////// 54 | 55 | const $ = new Env('我在校园签到'); 56 | const notify = $.isNode() ? require('./sendNotify') : ''; 57 | const fs = require("fs"); 58 | const request = require('request'); 59 | const {log} = console; 60 | 61 | ////////////////////// 62 | let scriptVersion = "1.0.8"; 63 | let scriptVersionLatest = ''; 64 | let update_data = "1.0.8 增加`仅通知签到失败`模式,可在脚本第52行修改开启"; //新版本更新内容 65 | //我在校园账号数据 66 | let wzxy = ($.isNode() ? process.env.wzxy : $.getdata("wzxy")) || ""; 67 | let wzxyArr = []; 68 | let wait = 0; 69 | let checkBack = 0; 70 | let loginBack = 0; 71 | let PunchInBack = 0; 72 | let requestAddressBack = 0; 73 | let msg = ''; 74 | let jwsession = ''; 75 | let location = ''; 76 | let signId = ''; 77 | let id = ''; 78 | let sign_data = ''; 79 | let status_code = 0; 80 | let locat = ''; 81 | let fail = 0; 82 | 83 | !(async () => { 84 | if (typeof $request !== "undefined") { 85 | await GetRewrite(); 86 | } else { 87 | if (!(await Envs())) 88 | return; 89 | else { 90 | 91 | log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( 92 | new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + 93 | 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); 94 | 95 | await poem(); 96 | await getVersion(); 97 | 98 | log(`\n============ 当前版本:${scriptVersion} 最新版本:${scriptVersionLatest} ============`) 99 | 100 | if(scriptVersionLatest != scriptVersion){ 101 | log(`\n发现新版本,请及时拉库更新!\n${update_data}`) 102 | } 103 | 104 | log(`\n=================== 共找到 ${wzxyArr.length} 个账号 ===================`) 105 | 106 | 107 | for (let index = 0; index < wzxyArr.length; index++) { 108 | 109 | 110 | let num = index + 1 111 | if (num >1 && wait == 0){ 112 | log('**********休息15s,防止黑IP**********'); 113 | await $.wait(16 * 1000); 114 | } 115 | log(`\n========= 开始【第 ${num} 个账号】=========\n`) 116 | data = wzxyArr[index]; 117 | content = JSON.parse(data) 118 | username = content.username 119 | password = content.password 120 | location = content.qd_location 121 | mark = content.mark 122 | 123 | log(`签到用户:${mark}`) 124 | var checkBack = 0; 125 | loginBack = 0; 126 | locat = location.split(',') 127 | if (!locat[0] || !locat[1]){ 128 | log('未填写qd_location,跳过打卡'); 129 | var checkBack = 1 130 | status_code = 6 131 | wait = 1 132 | } 133 | if (checkBack == 0) { 134 | log('开始检查jwsession是否存在...'); 135 | await checkJwsession() 136 | await $.wait(2 * 1000); 137 | 138 | if (loginBack) { 139 | 140 | log('开始获取签到列表...'); 141 | await PunchIn() 142 | await $.wait(2 * 1000); 143 | 144 | if (PunchInBack > 0) { 145 | log('正在请求地址信息...'); 146 | await requestAddress() 147 | await $.wait(2 * 1000); 148 | 149 | if (requestAddressBack) { 150 | log('开始签到...'); 151 | await doPunchIn() 152 | await $.wait(2 * 1000); 153 | 154 | } 155 | 156 | } 157 | 158 | } 159 | } 160 | var resultlog = getResult() 161 | 162 | if (OnlyErrorNotify>0){ 163 | if (status_code != 1 ){ 164 | msg += `签到用户:${mark}\n签到情况:${resultlog}\n\n` 165 | fail=fail+1 166 | } 167 | }else { 168 | msg += `签到用户:${mark}\n签到情况:${resultlog}\n\n` 169 | } 170 | 171 | } 172 | if (OnlyErrorNotify>0){ 173 | 174 | if(fail==0){ 175 | msg=`共${wzxyArr.length}个用户,全部签到成功 ✅ ` 176 | }else{ 177 | msg=`共${wzxyArr.length}个用户,❌ 失败${fail}个\n\n===========失败详情=============\n\n`+msg 178 | } 179 | } 180 | 181 | // log(msg); 182 | await SendMsg(msg); 183 | } 184 | } 185 | 186 | })() 187 | .catch((e) => log(e)) 188 | .finally(() => $.done()) 189 | 190 | /** 191 | * 判断jwsession是否存在 192 | */ 193 | function checkJwsession() { 194 | 195 | fs.open('.cache/' + username + ".json", 'r+', function(err, fd) { 196 | if (err) { 197 | console.error("找不到cache文件,正在使用账号信息登录...") 198 | login() 199 | return 200 | } 201 | console.log("找到cache文件,正在使用jwsession签到...") 202 | var read = fs.readFileSync('.cache/' + username + ".json") 203 | jwsession = read.toString() 204 | loginBack = 1 205 | 206 | }); 207 | 208 | } 209 | 210 | 211 | /** 212 | * 登录 213 | */ 214 | function login(timeout = 3 * 1000) { 215 | return new Promise((resolve) => { 216 | let url = { 217 | url: `https://gw.wozaixiaoyuan.com/basicinfo/mobile/login/username?username=${username}&password=${password}`, 218 | headers: { 219 | "Accept-Encoding": "gzip, deflate, br", 220 | "Connection": "keep-alive", 221 | "User-Agent": "Mozilla/5.0 (iPad; CPU OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.23(0x1800172f) NetType/WIFI Language/zh_CN miniProgram/wxce6d08f781975d91", 222 | "content-type": "application/json;charset=UTF-8", 223 | "Content-Length": "2", 224 | "Host": "gw.wozaixiaoyuan.com", 225 | "Accept-Language": "en-us,en", 226 | "Accept": "application/json, text/plain, */*" 227 | }, 228 | data: ``, 229 | } 230 | request.post(url, async (error, response, data) => { 231 | try { 232 | let result = data == "undefined" ? await login() : JSON.parse(data); 233 | //登录成功 234 | if (result.code == 0 ) { 235 | jwsession = response.headers['jwsession'] 236 | //储存jwsession 237 | setJwsession(jwsession) 238 | loginBack = 1; 239 | log(`登录成功`) 240 | 241 | } else { 242 | log(`❌ 登录失败,${result.message}`) 243 | status_code = 5; 244 | loginBack = 0; 245 | } 246 | 247 | } catch (e) { 248 | log(e) 249 | } finally { 250 | resolve(); 251 | } 252 | }, timeout) 253 | }) 254 | } 255 | 256 | 257 | /** 258 | * 存储jwsession 259 | */ 260 | function setJwsession(jwsession) { 261 | 262 | fs.mkdir('.cache',function(err){ 263 | if (err) { 264 | 265 | console.log("找到cache文件"); 266 | } 267 | else console.log("正在创建cache储存目录与文件..."); 268 | }); 269 | 270 | fs.writeFile('.cache/' + username + ".json", jwsession, function(err) { 271 | if (err) { 272 | return console.error(err); 273 | } 274 | console.log("更新jwsession成功"); 275 | }) 276 | 277 | } 278 | 279 | 280 | /** 281 | * 获取签到列表,符合条件则自动进行签到 282 | */ 283 | function PunchIn(timeout = 3 * 1000) { 284 | return new Promise((resolve) => { 285 | 286 | let url = { 287 | url: "https://student.wozaixiaoyuan.com/sign/getSignMessage.json", 288 | headers: { 289 | 'jwsession': jwsession, 290 | }, 291 | body: 'page=1&size=5' 292 | } 293 | 294 | $.post(url, async (error, response, data) => { 295 | 296 | try { 297 | let result = data == "undefined" ? await PunchIn() : JSON.parse(data); 298 | 299 | if (result.code == -10) { 300 | log('jwsession 无效,尝试账号密码签到') 301 | status_code = 4; 302 | PunchInBack = 0; 303 | loginBack = 0; 304 | await login() 305 | await $.wait(2 * 1000); 306 | if (loginBack > 0) { 307 | log('重新获取签到列表...'); 308 | await PunchIn() 309 | await $.wait(2 * 1000) 310 | return 311 | } 312 | } 313 | if (result.code == 0) { 314 | sign_message = result.data[0] 315 | id= sign_message.logId 316 | signId= sign_message.id 317 | log("获取成功,开始签到") 318 | PunchInBack = 1 319 | } 320 | 321 | } catch (e) { 322 | log(e) 323 | } finally { 324 | resolve(); 325 | } 326 | }, timeout) 327 | }) 328 | } 329 | 330 | 331 | /** 332 | * 请求地址信息 333 | */ 334 | function requestAddress(timeout = 3 * 1000) { 335 | return new Promise((resolve) => { 336 | location = location.split(',') 337 | let url = { 338 | url: `https://apis.map.qq.com/ws/geocoder/v1/?key=A3YBZ-NC5RU-MFYVV-BOHND-RO3OT-ABFCR&location=${location[1]},${location[0]}`, 339 | } 340 | $.get(url, async (error, response, data) => { 341 | try { 342 | let result = data == "undefined" ? await requestAddress() : JSON.parse(data); 343 | if (result.status == 0) { 344 | log(`地址信息获取成功`); 345 | try {town=result.result.address_reference.town.title}catch (e) {town=``} 346 | try {street=result.result.address_reference.street.title}catch (e) {street=``} 347 | data = { 348 | "latitude": location[1], 349 | "longitude": location[0], 350 | "country": encodeURI('中国'), 351 | "district": encodeURI(result.result.address_component.district), 352 | "province": encodeURI(result.result.address_component.province), 353 | "township": encodeURI(town), 354 | "towncode": "0", 355 | "citycode": "0", 356 | "street": encodeURI(street), 357 | "id": id, 358 | "signId": signId, 359 | } 360 | sign_data = JSON.stringify(data) 361 | requestAddressBack = 1 362 | } else { 363 | log(`❌ 地址信息获取失败`) 364 | requestAddressBack = 0 365 | } 366 | 367 | } catch (e) { 368 | log(e) 369 | } finally { 370 | resolve(); 371 | } 372 | }, timeout) 373 | }) 374 | } 375 | 376 | 377 | /** 378 | * 开始签到 379 | */ 380 | function doPunchIn(timeout = 3 * 1000) { 381 | return new Promise((resolve) => { 382 | let url = { 383 | url: "https://student.wozaixiaoyuan.com/sign/doSign.json", 384 | headers: { 385 | 'jwsession': jwsession, 386 | 'Content-Type': 'application/json' 387 | }, 388 | body: sign_data, 389 | } 390 | 391 | $.post(url, async (error, response, data) => { 392 | try { 393 | let result = data == "undefined" ? await doPunchIn() : JSON.parse(data); 394 | if (result.code == 0){ 395 | log("✅ 签到成功") 396 | status_code = 1 397 | } 398 | else { 399 | log("❌ 签到失败,原因:"+data) 400 | } 401 | 402 | } catch (e) { 403 | log(e) 404 | } finally { 405 | resolve(); 406 | } 407 | }, timeout) 408 | }) 409 | } 410 | 411 | 412 | /** 413 | * 获取签到结果 414 | */ 415 | function getResult(timeout = 3 * 1000) { 416 | res = status_code 417 | if (res == 1) return "✅ 签到成功" 418 | if (res == 2) return "✅ 你已经签过到了,无需重复签到" 419 | if (res == 3) return "❌ 签到失败,当前不在签到时间段内" 420 | if (res == 4) return "❌ 签到失败,jwsession 无效" 421 | if (res == 5) return "❌ 签到失败,登录错误,请检查账号信息" 422 | if (res == 6) return "❌ 跳过打卡,变量参数不完整" 423 | else return "❌ 签到失败,发生未知错误" 424 | } 425 | 426 | 427 | // ============================================变量检查============================================ \\ 428 | async function Envs() { 429 | if (wzxy) { 430 | if (wzxy.indexOf("@") != -1 || wzxy.indexOf("&") != -1) { 431 | wzxy.split("@"&&"&").forEach((item) => { 432 | wzxyArr.push(item); 433 | }); 434 | } 435 | // else if (wzxy.indexOf("\n") != -1) { 436 | // wzxy.split("\n").forEach((item) => { 437 | // wzxyArr.push(item); 438 | // }); 439 | // } 440 | else { 441 | wzxyArr.push(wzxy); 442 | } 443 | } else { 444 | log(`\n 未填写变量 wzxy`) 445 | return; 446 | } 447 | 448 | return true; 449 | } 450 | // ============================================发送消息============================================ \\ 451 | async function SendMsg(msg) { 452 | if (!msg) 453 | return; 454 | 455 | if (Notify > 0) { 456 | if ($.isNode()) { 457 | var notify = require('./sendNotify'); 458 | await notify.sendNotify($.name, msg+ `\n签到时间:${t()}\n`); 459 | } else { 460 | $.msg(msg); 461 | } 462 | } else { 463 | //log(msg); 464 | } 465 | } 466 | 467 | 468 | 469 | /** 470 | * 获取当前小时数 471 | */ 472 | function local_hours() { 473 | let myDate = new Date(); 474 | let h = myDate.getHours(); 475 | return h; 476 | } 477 | 478 | /** 479 | * 获取当前分钟数 480 | */ 481 | function local_minutes() { 482 | let myDate = new Date(); 483 | let m = myDate.getMinutes(); 484 | return m; 485 | } 486 | 487 | /** 488 | * 随机数生成 489 | */ 490 | function randomString(e) { 491 | e = e || 32; 492 | var t = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890", 493 | a = t.length, 494 | n = ""; 495 | for (i = 0; i < e; i++) 496 | n += t.charAt(Math.floor(Math.random() * a)); 497 | return n 498 | } 499 | 500 | /** 501 | * 随机整数生成 502 | */ 503 | function randomInt(min, max) { 504 | return Math.round(Math.random() * (max - min) + min) 505 | } 506 | 507 | /** 508 | * 获取毫秒时间戳 509 | */ 510 | function timestampMs(){ 511 | return new Date().getTime(); 512 | } 513 | 514 | /** 515 | * 516 | * 获取秒时间戳 517 | */ 518 | function timestampS(){ 519 | return Date.parse(new Date())/1000; 520 | } 521 | 522 | /** 523 | * 获取随机诗词 524 | */ 525 | function poem(timeout = 3 * 1000) { 526 | return new Promise((resolve) => { 527 | let url = { 528 | url: `https://v1.jinrishici.com/all.json` 529 | } 530 | $.get(url, async (err, resp, data) => { 531 | try { 532 | data = JSON.parse(data) 533 | log(`${data.content} \n————《${data.origin}》${data.author}`); 534 | } catch (e) { 535 | log(e, resp); 536 | } finally { 537 | resolve() 538 | } 539 | }, timeout) 540 | }) 541 | } 542 | 543 | /** 544 | * 修改配置文件 545 | */ 546 | function modify() { 547 | 548 | fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ 549 | if(err){ 550 | return log('读取文件失败!'+err) 551 | } 552 | else { 553 | var result = dataStr.replace(/regular/g,string); 554 | fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { 555 | if (err) {return log(err);} 556 | }); 557 | } 558 | }) 559 | } 560 | 561 | /** 562 | * 获取远程版本 563 | */ 564 | function getVersion(timeout = 3 * 1000) { 565 | return new Promise((resolve) => { 566 | let url = { 567 | url: `https://ghproxy.com/https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/main/wzxy_qd.js`, 568 | } 569 | $.get(url, async (err, resp, data) => { 570 | try { 571 | scriptVersionLatest = data.match(/scriptVersion = "([\d\.]+)"/)[1] 572 | update_data = data.match(/update_data = "(.*?)"/)[1] 573 | } catch (e) { 574 | $.logErr(e, resp); 575 | } finally { 576 | resolve() 577 | } 578 | }, timeout) 579 | }) 580 | } 581 | 582 | /** 583 | * time 输出格式:1970-01-01 00:00:00 584 | */ 585 | function t() { 586 | var date = new Date(); 587 | // 获取当前月份 588 | var nowMonth = date.getMonth() + 1; 589 | // 获取当前是几号 590 | var strDate = date.getDate(); 591 | //获取当前小时(0-23) 592 | var nowhour = date.getHours() 593 | //获取当前分钟(0-59) 594 | var nowMinute = date.getMinutes() 595 | //获取当前秒数(0-59) 596 | var nowSecond = date.getSeconds(); 597 | // 添加分隔符“-” 598 | var seperator = "-"; 599 | // 添加分隔符“:” 600 | var seperator1 = ":"; 601 | 602 | // 对月份进行处理,1-9月在前面添加一个“0” 603 | if (nowMonth >= 1 && nowMonth <= 9) { 604 | nowMonth = "0" + nowMonth; 605 | } 606 | // 对月份进行处理,1-9号在前面添加一个“0” 607 | if (strDate >= 0 && strDate <= 9) { 608 | strDate = "0" + strDate; 609 | } 610 | // 对小时进行处理,0-9号在前面添加一个“0” 611 | if (nowhour >= 0 && nowhour <= 9) { 612 | nowhour = "0" + nowhour; 613 | } 614 | // 对分钟进行处理,0-9号在前面添加一个“0” 615 | if (nowMinute >= 0 && nowMinute <= 9) { 616 | nowMinute = "0" + nowMinute; 617 | } 618 | // 对秒数进行处理,0-9号在前面添加一个“0” 619 | if (nowSecond >= 0 && nowSecond <= 9) { 620 | nowSecond = "0" + nowSecond; 621 | } 622 | 623 | // 最后拼接字符串,得到一个格式为(yyyy-MM-dd)的日期 624 | var nowDate = date.getFullYear() + seperator + nowMonth + seperator + strDate + ` ` + nowhour + seperator1 + nowMinute + seperator1 + nowSecond 625 | return nowDate 626 | } 627 | 628 | function Env(t, e) { 629 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 630 | class s { 631 | constructor(t) { 632 | this.env = t 633 | } 634 | send(t, e = "GET") { 635 | t = "string" == typeof t ? { 636 | url: t 637 | } : t; 638 | let s = this.get; 639 | return "POST" === e && (s = this.post), new Promise((e, i) => { 640 | s.call(this, t, (t, s, r) => { 641 | t ? i(t) : e(s) 642 | }) 643 | }) 644 | } 645 | get(t) { 646 | return this.send.call(this.env, t) 647 | } 648 | post(t) { 649 | return this.send.call(this.env, t, "POST") 650 | } 651 | } 652 | return new class { 653 | constructor(t, e) { 654 | 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}, 开始!`) 655 | } 656 | isNode() { 657 | return "undefined" != typeof module && !!module.exports 658 | } 659 | isQuanX() { 660 | return "undefined" != typeof $task 661 | } 662 | isSurge() { 663 | return "undefined" != typeof $httpClient && "undefined" == typeof $loon 664 | } 665 | isLoon() { 666 | return "undefined" != typeof $loon 667 | } 668 | toObj(t, e = null) { 669 | try { 670 | return JSON.parse(t) 671 | } catch { 672 | return e 673 | } 674 | } 675 | toStr(t, e = null) { 676 | try { 677 | return JSON.stringify(t) 678 | } catch { 679 | return e 680 | } 681 | } 682 | getjson(t, e) { 683 | let s = e; 684 | const i = this.getdata(t); 685 | if (i) try { 686 | s = JSON.parse(this.getdata(t)) 687 | } catch {} 688 | return s 689 | } 690 | setjson(t, e) { 691 | try { 692 | return this.setdata(JSON.stringify(t), e) 693 | } catch { 694 | return !1 695 | } 696 | } 697 | getScript(t) { 698 | return new Promise(e => { 699 | this.get({ 700 | url: t 701 | }, (t, s, i) => e(i)) 702 | }) 703 | } 704 | runScript(t, e) { 705 | return new Promise(s => { 706 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 707 | i = i ? i.replace(/\n/g, "").trim() : i; 708 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 709 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 710 | const [o, h] = i.split("@"), n = { 711 | url: `http://${h}/v1/scripting/evaluate`, 712 | body: { 713 | script_text: t, 714 | mock_type: "cron", 715 | timeout: r 716 | }, 717 | headers: { 718 | "X-Key": o, 719 | Accept: "*/*" 720 | } 721 | }; 722 | this.post(n, (t, e, i) => s(i)) 723 | }).catch(t => this.logErr(t)) 724 | } 725 | loaddata() { 726 | if (!this.isNode()) return {}; { 727 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 728 | const t = this.path.resolve(this.dataFile), 729 | e = this.path.resolve(process.cwd(), this.dataFile), 730 | s = this.fs.existsSync(t), 731 | i = !s && this.fs.existsSync(e); 732 | if (!s && !i) return {}; { 733 | const i = s ? t : e; 734 | try { 735 | return JSON.parse(this.fs.readFileSync(i)) 736 | } catch (t) { 737 | return {} 738 | } 739 | } 740 | } 741 | } 742 | writedata() { 743 | if (this.isNode()) { 744 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 745 | const t = this.path.resolve(this.dataFile), 746 | e = this.path.resolve(process.cwd(), this.dataFile), 747 | s = this.fs.existsSync(t), 748 | i = !s && this.fs.existsSync(e), 749 | r = JSON.stringify(this.data); 750 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 751 | } 752 | } 753 | lodash_get(t, e, s) { 754 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 755 | let r = t; 756 | for (const t of i) 757 | if (r = Object(r)[t], void 0 === r) return s; 758 | return r 759 | } 760 | lodash_set(t, e, s) { 761 | 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) 762 | } 763 | getdata(t) { 764 | let e = this.getval(t); 765 | if (/^@/.test(t)) { 766 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; 767 | if (r) try { 768 | const t = JSON.parse(r); 769 | e = t ? this.lodash_get(t, i, "") : e 770 | } catch (t) { 771 | e = "" 772 | } 773 | } 774 | return e 775 | } 776 | setdata(t, e) { 777 | let s = !1; 778 | if (/^@/.test(e)) { 779 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; 780 | try { 781 | const e = JSON.parse(h); 782 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) 783 | } catch (e) { 784 | const o = {}; 785 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) 786 | } 787 | } else s = this.setval(t, e); 788 | return s 789 | } 790 | getval(t) { 791 | 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 792 | } 793 | setval(t, e) { 794 | 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 795 | } 796 | initGotEnv(t) { 797 | 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)) 798 | } 799 | get(t, e = (() => {})) { 800 | 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, { 801 | "X-Surge-Skip-Scripting": !1 802 | })), $httpClient.get(t, (t, s, i) => { 803 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 804 | })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 805 | hints: !1 806 | })), $task.fetch(t).then(t => { 807 | const { 808 | statusCode: s, 809 | statusCode: i, 810 | headers: r, 811 | body: o 812 | } = t; 813 | e(null, { 814 | status: s, 815 | statusCode: i, 816 | headers: r, 817 | body: o 818 | }, o) 819 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 820 | try { 821 | if (t.headers["set-cookie"]) { 822 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 823 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar 824 | } 825 | } catch (t) { 826 | this.logErr(t) 827 | } 828 | }).then(t => { 829 | const { 830 | statusCode: s, 831 | statusCode: i, 832 | headers: r, 833 | body: o 834 | } = t; 835 | e(null, { 836 | status: s, 837 | statusCode: i, 838 | headers: r, 839 | body: o 840 | }, o) 841 | }, t => { 842 | const { 843 | message: s, 844 | response: i 845 | } = t; 846 | e(s, i, i && i.body) 847 | })) 848 | } 849 | post(t, e = (() => {})) { 850 | 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, { 851 | "X-Surge-Skip-Scripting": !1 852 | })), $httpClient.post(t, (t, s, i) => { 853 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 854 | }); 855 | else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 856 | hints: !1 857 | })), $task.fetch(t).then(t => { 858 | const { 859 | statusCode: s, 860 | statusCode: i, 861 | headers: r, 862 | body: o 863 | } = t; 864 | e(null, { 865 | status: s, 866 | statusCode: i, 867 | headers: r, 868 | body: o 869 | }, o) 870 | }, t => e(t)); 871 | else if (this.isNode()) { 872 | this.initGotEnv(t); 873 | const { 874 | url: s, 875 | ...i 876 | } = t; 877 | this.got.post(s, i).then(t => { 878 | const { 879 | statusCode: s, 880 | statusCode: i, 881 | headers: r, 882 | body: o 883 | } = t; 884 | e(null, { 885 | status: s, 886 | statusCode: i, 887 | headers: r, 888 | body: o 889 | }, o) 890 | }, t => { 891 | const { 892 | message: s, 893 | response: i 894 | } = t; 895 | e(s, i, i && i.body) 896 | }) 897 | } 898 | } 899 | time(t, e = null) { 900 | const s = e ? new Date(e) : new Date; 901 | let i = { 902 | "M+": s.getMonth() + 1, 903 | "d+": s.getDate(), 904 | "H+": s.getHours(), 905 | "m+": s.getMinutes(), 906 | "s+": s.getSeconds(), 907 | "q+": Math.floor((s.getMonth() + 3) / 3), 908 | S: s.getMilliseconds() 909 | }; 910 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 911 | 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))); 912 | return t 913 | } 914 | msg(e = t, s = "", i = "", r) { 915 | const o = t => { 916 | if (!t) return t; 917 | if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { 918 | "open-url": t 919 | } : this.isSurge() ? { 920 | url: t 921 | } : void 0; 922 | if ("object" == typeof t) { 923 | if (this.isLoon()) { 924 | let e = t.openUrl || t.url || t["open-url"], 925 | s = t.mediaUrl || t["media-url"]; 926 | return { 927 | openUrl: e, 928 | mediaUrl: s 929 | } 930 | } 931 | if (this.isQuanX()) { 932 | let e = t["open-url"] || t.url || t.openUrl, 933 | s = t["media-url"] || t.mediaUrl; 934 | return { 935 | "open-url": e, 936 | "media-url": s 937 | } 938 | } 939 | if (this.isSurge()) { 940 | let e = t.url || t.openUrl || t["open-url"]; 941 | return { 942 | url: e 943 | } 944 | } 945 | } 946 | }; 947 | if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { 948 | let t = ["", "==============📣系统通知📣=============="]; 949 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) 950 | } 951 | } 952 | log(...t) { 953 | t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) 954 | } 955 | logErr(t, e) { 956 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 957 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 958 | } 959 | wait(t) { 960 | return new Promise(e => setTimeout(e, t)) 961 | } 962 | done(t = {}) { 963 | const e = (new Date).getTime(), 964 | s = (e - this.startTime) / 1e3; 965 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 966 | } 967 | }(t, e) 968 | } 969 | -------------------------------------------------------------------------------- /wzxy_rjrb.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 作者QQ: 1483081359 欢迎前来提交bug 3 | * github仓库:https://github.com/zhacha222/wozaixiaoyuan 4 | * 微信小程序:我在校园 日检日报 5 | * 脚本说明:如果打卡不止两次,自己去修改改定时,在打卡时间段内运行该脚本即可 6 | * 默认定时:默认每天 8点5分 和 16点5分 运行两次。 7 | * cron: 5 8,16 * * * 8 | * 变量名称:wzxy 9 | * 变量值: { 10 | "username": "手机号", 11 | "password": "密码", 12 | "qd_location": "133.333333,33.333333", 13 | "rjrb_answers": ["0","0"], 14 | "rjrb_location": "133.333333,33.333333", 15 | "jkdk_answers": ["0","无","1","0","36.2","没有","1","1","2"], 16 | "jkdk_location": "133.333333,33.333333", 17 | "mark": "用户昵称" 18 | } 19 | 20 | ***一些前提说明: 21 | 1.只支持青龙面板(本人青龙版本2.10.13),搭建教程自行百度 22 | 2.本库脚本通用 wzxy这一个变量 23 | 3.脚本变量只推荐在青龙的【环境变量】页添加,有强迫症在【配置文件】config.sh中添加的如果出现问题自己解决 24 | 4.支持多用户,每一用户在【环境变量】单独新建变量wzxy,切勿一个变量内填写多个用户的参数 25 | 5.脚本通知方式采用青龙面板默认通知,请在【配置文件】config.sh里配置 26 | 6.关于各脚本的具体使用方法,请阅读脚本内的注释 27 | 28 | ***关于变量值中各参数的解释: 29 | username ———————— 手机号 30 | password —————————密码 31 | qd_location ————— 签到的`经纬度` (wzxy_qd.js) 32 | rjrb_answers —————日检日报的`填空参数`(wzxy_rjrb.js) 33 | rjrb_location ————日检日报的`经纬度` (wzxy_rjrb.js) 34 | jkdk_answers ———— 健康签到的`填空参数`(wzxy_jkdk.js) 35 | jkdk_location ————健康签到的`经纬度` (wzxy_jkdk.js) 36 | mark —————————————用户昵称(不一定要真名,随便填都行,便于自己区分打卡用户) 37 | 38 | 39 | ***更新日志: 40 | 41 | 1.0.0 完成日检日报的基本功能 42 | 1.0.1 修复seq识别出错的bug 43 | 1.0.2 增加等待15s,防止黑ip 44 | 1.0.3 修复打卡通知成功但 实际上没打上卡的bug 45 | 1.0.4 增加完整参数验证 46 | 1.0.6 修复当前时间格式 47 | 1.0.7 增加打卡Content-Type 48 | 1.0.8 修复地址信息请求失败的bug 49 | 1.0.9 优化通知 50 | 1.1.0 log增加新版本内容 51 | 1.1.1 增加`仅通知打卡失败`模式,在脚本第58行修改开启 52 | 53 | */ 54 | //cron: 5 8,16 * * * 55 | 56 | //===============通知设置=================// 57 | const Notify = 1; //0为关闭通知,1为打开通知,默认为1 58 | const OnlyErrorNotify = 0; //0为关闭`仅通知打卡失败`模式,1为打开`仅通知打卡失败`模式,默认为0 59 | //////////////////////////////////////////// 60 | 61 | const $ = new Env('日检日报'); 62 | const notify = $.isNode() ? require('./sendNotify') : ''; 63 | const fs = require("fs"); 64 | const request = require('request'); 65 | const {log} = console; 66 | ////////////////////// 67 | let scriptVersion = "1.1.1"; 68 | let scriptVersionLatest = ''; 69 | let update_data = "1.1.1 增加`仅通知打卡失败`模式,可在脚本第58行修改开启"; //新版本更新内容 70 | //我在校园账号数据 71 | let wzxy = ($.isNode() ? process.env.wzxy : $.getdata("wzxy")) || ""; 72 | let wzxyArr = []; 73 | let wait = 0; 74 | let checkBack = 0; 75 | let loginBack = 0; 76 | let PunchInBack = 0; 77 | let requestAddressBack = 0; 78 | let msg = ''; 79 | let jwsession = ''; 80 | let location = ''; 81 | let sign_data = ''; 82 | let answers = ''; 83 | let status_code = 0; 84 | let startTime = ''; 85 | let endTime = ''; 86 | let seq = ''; 87 | let locat = ''; 88 | let fail = 0; 89 | 90 | !(async () => { 91 | if (typeof $request !== "undefined") { 92 | await GetRewrite(); 93 | } else { 94 | if (!(await Envs())) 95 | return; 96 | else { 97 | 98 | log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( 99 | new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + 100 | 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); 101 | 102 | await poem(); 103 | await getVersion(); 104 | 105 | log(`\n============ 当前版本:${scriptVersion} 最新版本:${scriptVersionLatest} ============`) 106 | 107 | if(scriptVersionLatest != scriptVersion){ 108 | log(`\n发现新版本,请及时拉库更新!\n${update_data}`) 109 | } 110 | 111 | log(`\n=================== 共找到 ${wzxyArr.length} 个账号 ===================`) 112 | 113 | 114 | for (let index = 0; index < wzxyArr.length; index++) { 115 | 116 | 117 | let num = index + 1 118 | if (num >1 && wait == 0){ 119 | log('**********休息15s,防止黑IP**********'); 120 | await $.wait(16 * 1000); 121 | } 122 | log(`\n========= 开始【第 ${num} 个账号】=========\n`) 123 | data = wzxyArr[index]; 124 | content = JSON.parse(data) 125 | username = content.username 126 | password = content.password 127 | location = content.rjrb_location 128 | answers = JSON.stringify(content.rjrb_answers) 129 | mark = content.mark 130 | log(`打卡用户:${mark}`) 131 | var checkBack = 0; 132 | loginBack = 0;//置0,防止上一个号影响下一个号 133 | locat = location.split(',') 134 | if (!locat[0] || !locat[1]){ 135 | log('未填写rjrb_location,跳过打卡'); 136 | var checkBack = 1 137 | status_code = 6 138 | wait = 1 139 | } 140 | if (checkBack == 0) { 141 | log('开始检查jwsession是否存在...'); 142 | await checkJwsession() 143 | await $.wait(2 * 1000); 144 | 145 | if (loginBack) { 146 | 147 | log('开始获取打卡列表...'); 148 | await PunchIn() 149 | await $.wait(2 * 1000); 150 | 151 | if (PunchInBack > 0) { 152 | log('正在请求地址信息...'); 153 | await requestAddress() 154 | await $.wait(2 * 1000); 155 | 156 | if (requestAddressBack) { 157 | log('开始日检日报打卡...'); 158 | await doPunchIn() 159 | await $.wait(2 * 1000); 160 | 161 | } 162 | 163 | } 164 | 165 | } 166 | } 167 | var resultlog = getResult() 168 | 169 | 170 | if (OnlyErrorNotify>0){ 171 | if (status_code != 1 ){ 172 | msg += `打卡用户:${mark}\n打卡情况:${resultlog}\n\n` 173 | fail=fail+1 174 | } 175 | }else { 176 | msg += `打卡用户:${mark}\n打卡情况:${resultlog}\n\n` 177 | } 178 | 179 | } 180 | if (OnlyErrorNotify>0){ 181 | 182 | if(fail==0){ 183 | msg=`共${wzxyArr.length}个用户,全部打卡成功 ✅ ` 184 | }else{ 185 | msg=`共${wzxyArr.length}个用户,❌ 失败${fail}个\n\n===========失败详情=============\n\n`+msg 186 | } 187 | } 188 | // log(msg); 189 | await SendMsg(msg); 190 | } 191 | } 192 | 193 | })() 194 | .catch((e) => log(e)) 195 | .finally(() => $.done()) 196 | 197 | 198 | 199 | /** 200 | * 判断jwsession是否存在 201 | */ 202 | function checkJwsession() { 203 | 204 | fs.open('.cache/' + username + ".json", 'r+', function(err, fd) { 205 | if (err) { 206 | console.error("找不到cache文件,正在使用账号信息登录...") 207 | login() 208 | return 209 | } 210 | console.log("找到cache文件,正在使用jwsession打卡...") 211 | var read = fs.readFileSync('.cache/' + username + ".json") 212 | jwsession = read.toString() 213 | loginBack = 1 214 | 215 | }); 216 | 217 | } 218 | 219 | 220 | /** 221 | * 登录 222 | */ 223 | function login(timeout = 3 * 1000) { 224 | return new Promise((resolve) => { 225 | let url = { 226 | url: `https://gw.wozaixiaoyuan.com/basicinfo/mobile/login/username?username=${username}&password=${password}`, 227 | headers: { 228 | "Accept-Encoding": "gzip, deflate, br", 229 | "Connection": "keep-alive", 230 | "User-Agent": "Mozilla/5.0 (iPad; CPU OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.23(0x1800172f) NetType/WIFI Language/zh_CN miniProgram/wxce6d08f781975d91", 231 | "content-type": "application/json;charset=UTF-8", 232 | "Content-Length": "2", 233 | "Host": "gw.wozaixiaoyuan.com", 234 | "Accept-Language": "en-us,en", 235 | "Accept": "application/json, text/plain, */*" 236 | }, 237 | data: ``, 238 | } 239 | 240 | 241 | request.post(url, async (error, response, data) => { 242 | try { 243 | let result = data == "undefined" ? await login() : JSON.parse(data); 244 | 245 | //登录成功 246 | if (result.code == 0 ) { 247 | 248 | jwsession = response.headers['jwsession'] 249 | //储存jwsession 250 | setJwsession(jwsession) 251 | loginBack = 1; 252 | log(`登录成功`) 253 | 254 | } else { 255 | log(`❌ 登录失败,${result.message}`) 256 | status_code = 5; 257 | loginBack = 0; 258 | } 259 | 260 | } catch (e) { 261 | log(e) 262 | } finally { 263 | resolve(); 264 | } 265 | }, timeout) 266 | }) 267 | } 268 | 269 | 270 | /** 271 | * 存储jwsession 272 | */ 273 | function setJwsession(jwsession) { 274 | 275 | fs.mkdir('.cache',function(err){ 276 | if (err) { 277 | 278 | console.log("找到cache文件"); 279 | } 280 | else console.log("正在创建cache储存目录与文件..."); 281 | }); 282 | 283 | fs.writeFile('.cache/' + username + ".json", jwsession, function(err) { 284 | if (err) { 285 | return console.error(err); 286 | } 287 | console.log("更新jwsession成功"); 288 | }) 289 | 290 | } 291 | 292 | 293 | /** 294 | * 获取打卡列表,判断当前打卡时间段与打卡情况,符合条件则自动进行打卡 295 | */ 296 | function PunchIn(timeout = 3 * 1000) { 297 | return new Promise((resolve) => { 298 | 299 | let url = { 300 | url: "https://student.wozaixiaoyuan.com/heat/getTodayHeatList.json", 301 | headers: { 302 | 'jwsession': jwsession, 303 | }, 304 | body: '' 305 | } 306 | 307 | $.post(url, async (error, response, data) => { 308 | try { 309 | let result = data == "undefined" ? await PunchIn() : JSON.parse(data); 310 | 311 | if (result.code == -10) { 312 | log('jwsession 无效,尝试账号密码登录...') 313 | status_code = 4; 314 | PunchInBack = 0; 315 | loginBack = 0; 316 | await login() 317 | await $.wait(2 * 1000); 318 | if (loginBack > 0) { 319 | log('重新获取打卡列表...'); 320 | await PunchIn() 321 | await $.wait(2 * 1000) 322 | return 323 | } 324 | } 325 | if (result.code == 0) { 326 | 327 | //晨午检判断 328 | for (let i = 0; i < result['data'].length; i++) { 329 | 330 | var d = new Date() 331 | var hour = d.getHours() 332 | hour = hour > 9 ? hour : '0' + hour.toString() 333 | var minute = d.getMinutes() 334 | minute = minute > 9 ? minute : '0' + minute.toString() 335 | now = hour + `:`+minute 336 | 337 | startTime = result['data'][i]['startTime'] 338 | endTime = result['data'][i]['endTime'] 339 | 340 | if(startTime < now && now < endTime){ 341 | 342 | seq = i + 1 343 | // var seq = result['data'][i]['seq'] 344 | // if(!seq) { 345 | // seq = result['data'][i].seq 346 | // } 347 | } 348 | } 349 | if (!seq){ 350 | log("❌ 打卡失败,当前不在打卡时间段内") 351 | PunchInBack = 0; 352 | status_code = 3; 353 | return 354 | } 355 | if (seq > 0){ 356 | log("获取成功,开始打卡") 357 | PunchInBack = 1 358 | } 359 | 360 | } 361 | if (result.code != 0 && result.code != -10) { 362 | log(`❌ 获取失败,原因:${error}`) 363 | PunchInBack = 0 364 | } 365 | 366 | } catch (e) { 367 | log(e) 368 | } finally { 369 | resolve(); 370 | } 371 | }, timeout) 372 | }) 373 | } 374 | 375 | 376 | /** 377 | * 请求地址信息 378 | */ 379 | function requestAddress(timeout = 3 * 1000) { 380 | return new Promise((resolve) => { 381 | location = location.split(',') 382 | let url = { 383 | url: `https://apis.map.qq.com/ws/geocoder/v1/?key=A3YBZ-NC5RU-MFYVV-BOHND-RO3OT-ABFCR&location=${location[1]},${location[0]}`, 384 | } 385 | 386 | $.get(url, async (error, response, data) => { 387 | try { 388 | let result = data == "undefined" ? await requestAddress() : JSON.parse(data); 389 | 390 | if (result.status == 0) { 391 | log(`地址信息获取成功`); 392 | timestampMs() 393 | try {town=result.result.address_reference.town.title}catch (e) {town=``} 394 | try {street=result.result.address_reference.street.title}catch (e) {street=``} 395 | _data =`answers=${answers}&seq=${seq}&temperature=36.0&latitude=${location[1]}&longitude=${location[0]}&country=中国&city=${result.result.address_component.city}&district=${result.result.address_component.district}&province=${result.result.address_component.province}&township=${town}&street=${street}&areacode=${result.result.ad_info.adcode}&towncode=0&citycode=0×tampHeader=${new Date().getTime()}` 396 | sign_data = encodeURI(_data) 397 | requestAddressBack = 1 398 | 399 | } else { 400 | log(`❌ 地址信息获取失败`) 401 | requestAddressBack = 0 402 | } 403 | 404 | } catch (e) { 405 | log(e) 406 | } finally { 407 | resolve(); 408 | } 409 | }, timeout) 410 | }) 411 | } 412 | 413 | 414 | 415 | /** 416 | * 开始打卡 417 | */ 418 | function doPunchIn(timeout = 3 * 1000) { 419 | return new Promise((resolve) => { 420 | let url = { 421 | url: "https://student.wozaixiaoyuan.com/heat/save.json", 422 | headers: { 423 | "Content-Type": "application/x-www-form-urlencoded", 424 | "jwsession": jwsession, 425 | }, 426 | body: sign_data, 427 | 428 | } 429 | 430 | $.post(url, async (error, response, data) => { 431 | try { 432 | let result = data == "undefined" ? await doPunchIn() : JSON.parse(data); 433 | 434 | //打卡情况 435 | if (result.code == 0){ 436 | log("✅ 打卡成功") 437 | status_code = 1 438 | } 439 | if (result.code != 0) { 440 | log("❌ 打卡失败,原因:"+data) 441 | } 442 | 443 | } catch (e) { 444 | log(e) 445 | } finally { 446 | resolve(); 447 | } 448 | }, timeout) 449 | }) 450 | } 451 | 452 | 453 | /** 454 | * 获取打卡结果 455 | */ 456 | function getResult(timeout = 3 * 1000) { 457 | res = status_code 458 | if (res == 1) return "✅ 打卡成功" 459 | if (res == 2) return "✅ 你已经打过卡了,无需重复打卡" 460 | if (res == 3) return "❌ 打卡失败,当前不在打卡时间段内" 461 | if (res == 4) return "❌ 打卡失败,jwsession 无效" 462 | if (res == 5) return "❌ 打卡失败,登录错误,请检查账号信息" 463 | if (res == 6) return "❌ 跳过打卡,变量参数不完整" 464 | else return "❌ 打卡失败,发生未知错误" 465 | } 466 | 467 | 468 | // ============================================变量检查============================================ \\ 469 | async function Envs() { 470 | if (wzxy) { 471 | if (wzxy.indexOf("@") != -1 || wzxy.indexOf("&") != -1) { 472 | wzxy.split("@"&&"&").forEach((item) => { 473 | wzxyArr.push(item); 474 | }); 475 | } 476 | // else if (wzxy.indexOf("\n") != -1) { 477 | // wzxy.split("\n").forEach((item) => { 478 | // wzxyArr.push(item); 479 | // }); 480 | // } 481 | else { 482 | wzxyArr.push(wzxy); 483 | } 484 | } else { 485 | log(`\n 未填写变量 wzxy`) 486 | return; 487 | } 488 | 489 | return true; 490 | } 491 | // ============================================发送消息============================================ \\ 492 | async function SendMsg(msg) { 493 | if (!msg) 494 | return; 495 | 496 | if (Notify > 0) { 497 | if ($.isNode()) { 498 | var notify = require('./sendNotify'); 499 | await notify.sendNotify($.name, msg+ `\n打卡时间:${t()}\n`); 500 | } else { 501 | $.msg(msg); 502 | } 503 | } else { 504 | //log(msg); 505 | } 506 | } 507 | 508 | 509 | 510 | /** 511 | * 获取当前小时数 512 | */ 513 | function local_hours() { 514 | let myDate = new Date(); 515 | let h = myDate.getHours(); 516 | return h; 517 | } 518 | 519 | /** 520 | * 获取当前分钟数 521 | */ 522 | function local_minutes() { 523 | let myDate = new Date(); 524 | let m = myDate.getMinutes(); 525 | return m; 526 | } 527 | 528 | /** 529 | * 随机数生成 530 | */ 531 | function randomString(e) { 532 | e = e || 32; 533 | var t = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890", 534 | a = t.length, 535 | n = ""; 536 | for (i = 0; i < e; i++) 537 | n += t.charAt(Math.floor(Math.random() * a)); 538 | return n 539 | } 540 | 541 | /** 542 | * 随机整数生成 543 | */ 544 | function randomInt(min, max) { 545 | return Math.round(Math.random() * (max - min) + min) 546 | } 547 | 548 | /** 549 | * 获取毫秒时间戳 550 | */ 551 | function timestampMs(){ 552 | return new Date().getTime(); 553 | } 554 | 555 | /** 556 | * 557 | * 获取秒时间戳 558 | */ 559 | function timestampS(){ 560 | return Date.parse(new Date())/1000; 561 | } 562 | 563 | /** 564 | * 获取随机诗词 565 | */ 566 | function poem(timeout = 3 * 1000) { 567 | return new Promise((resolve) => { 568 | let url = { 569 | url: `https://v1.jinrishici.com/all.json` 570 | } 571 | $.get(url, async (err, resp, data) => { 572 | try { 573 | data = JSON.parse(data) 574 | log(`${data.content} \n————《${data.origin}》${data.author}`); 575 | } catch (e) { 576 | log(e, resp); 577 | } finally { 578 | resolve() 579 | } 580 | }, timeout) 581 | }) 582 | } 583 | 584 | /** 585 | * 修改配置文件 586 | */ 587 | function modify() { 588 | 589 | fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ 590 | if(err){ 591 | return log('读取文件失败!'+err) 592 | } 593 | else { 594 | var result = dataStr.replace(/regular/g,string); 595 | fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { 596 | if (err) {return log(err);} 597 | }); 598 | } 599 | }) 600 | } 601 | 602 | /** 603 | * 获取远程版本 604 | */ 605 | function getVersion(timeout = 3 * 1000) { 606 | return new Promise((resolve) => { 607 | let url = { 608 | url: `https://ghproxy.com/https://raw.githubusercontent.com/zhacha222/wozaixiaoyuan/main/wzxy_rjrb.js`, 609 | } 610 | $.get(url, async (err, resp, data) => { 611 | try { 612 | scriptVersionLatest = data.match(/scriptVersion = "([\d\.]+)"/)[1] 613 | update_data = data.match(/update_data = "(.*?)"/)[1] 614 | } catch (e) { 615 | $.logErr(e, resp); 616 | } finally { 617 | resolve() 618 | } 619 | }, timeout) 620 | }) 621 | } 622 | 623 | /** 624 | * time 输出格式:1970-01-01 00:00:00 625 | */ 626 | function t() { 627 | var date = new Date(); 628 | // 获取当前月份 629 | var nowMonth = date.getMonth() + 1; 630 | // 获取当前是几号 631 | var strDate = date.getDate(); 632 | //获取当前小时(0-23) 633 | var nowhour = date.getHours() 634 | //获取当前分钟(0-59) 635 | var nowMinute = date.getMinutes() 636 | //获取当前秒数(0-59) 637 | var nowSecond = date.getSeconds(); 638 | // 添加分隔符“-” 639 | var seperator = "-"; 640 | // 添加分隔符“:” 641 | var seperator1 = ":"; 642 | 643 | // 对月份进行处理,1-9月在前面添加一个“0” 644 | if (nowMonth >= 1 && nowMonth <= 9) { 645 | nowMonth = "0" + nowMonth; 646 | } 647 | // 对月份进行处理,1-9号在前面添加一个“0” 648 | if (strDate >= 0 && strDate <= 9) { 649 | strDate = "0" + strDate; 650 | } 651 | // 对小时进行处理,0-9号在前面添加一个“0” 652 | if (nowhour >= 0 && nowhour <= 9) { 653 | nowhour = "0" + nowhour; 654 | } 655 | // 对分钟进行处理,0-9号在前面添加一个“0” 656 | if (nowMinute >= 0 && nowMinute <= 9) { 657 | nowMinute = "0" + nowMinute; 658 | } 659 | // 对秒数进行处理,0-9号在前面添加一个“0” 660 | if (nowSecond >= 0 && nowSecond <= 9) { 661 | nowSecond = "0" + nowSecond; 662 | } 663 | 664 | // 最后拼接字符串,得到一个格式为(yyyy-MM-dd)的日期 665 | var nowDate = date.getFullYear() + seperator + nowMonth + seperator + strDate + ` ` + nowhour + seperator1 + nowMinute + seperator1 + nowSecond 666 | return nowDate 667 | } 668 | 669 | function Env(t, e) { 670 | "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); 671 | class s { 672 | constructor(t) { 673 | this.env = t 674 | } 675 | send(t, e = "GET") { 676 | t = "string" == typeof t ? { 677 | url: t 678 | } : t; 679 | let s = this.get; 680 | return "POST" === e && (s = this.post), new Promise((e, i) => { 681 | s.call(this, t, (t, s, r) => { 682 | t ? i(t) : e(s) 683 | }) 684 | }) 685 | } 686 | get(t) { 687 | return this.send.call(this.env, t) 688 | } 689 | post(t) { 690 | return this.send.call(this.env, t, "POST") 691 | } 692 | } 693 | return new class { 694 | constructor(t, e) { 695 | 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}, 开始!`) 696 | } 697 | isNode() { 698 | return "undefined" != typeof module && !!module.exports 699 | } 700 | isQuanX() { 701 | return "undefined" != typeof $task 702 | } 703 | isSurge() { 704 | return "undefined" != typeof $httpClient && "undefined" == typeof $loon 705 | } 706 | isLoon() { 707 | return "undefined" != typeof $loon 708 | } 709 | toObj(t, e = null) { 710 | try { 711 | return JSON.parse(t) 712 | } catch { 713 | return e 714 | } 715 | } 716 | toStr(t, e = null) { 717 | try { 718 | return JSON.stringify(t) 719 | } catch { 720 | return e 721 | } 722 | } 723 | getjson(t, e) { 724 | let s = e; 725 | const i = this.getdata(t); 726 | if (i) try { 727 | s = JSON.parse(this.getdata(t)) 728 | } catch {} 729 | return s 730 | } 731 | setjson(t, e) { 732 | try { 733 | return this.setdata(JSON.stringify(t), e) 734 | } catch { 735 | return !1 736 | } 737 | } 738 | getScript(t) { 739 | return new Promise(e => { 740 | this.get({ 741 | url: t 742 | }, (t, s, i) => e(i)) 743 | }) 744 | } 745 | runScript(t, e) { 746 | return new Promise(s => { 747 | let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); 748 | i = i ? i.replace(/\n/g, "").trim() : i; 749 | let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); 750 | r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; 751 | const [o, h] = i.split("@"), n = { 752 | url: `http://${h}/v1/scripting/evaluate`, 753 | body: { 754 | script_text: t, 755 | mock_type: "cron", 756 | timeout: r 757 | }, 758 | headers: { 759 | "X-Key": o, 760 | Accept: "*/*" 761 | } 762 | }; 763 | this.post(n, (t, e, i) => s(i)) 764 | }).catch(t => this.logErr(t)) 765 | } 766 | loaddata() { 767 | if (!this.isNode()) return {}; { 768 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 769 | const t = this.path.resolve(this.dataFile), 770 | e = this.path.resolve(process.cwd(), this.dataFile), 771 | s = this.fs.existsSync(t), 772 | i = !s && this.fs.existsSync(e); 773 | if (!s && !i) return {}; { 774 | const i = s ? t : e; 775 | try { 776 | return JSON.parse(this.fs.readFileSync(i)) 777 | } catch (t) { 778 | return {} 779 | } 780 | } 781 | } 782 | } 783 | writedata() { 784 | if (this.isNode()) { 785 | this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); 786 | const t = this.path.resolve(this.dataFile), 787 | e = this.path.resolve(process.cwd(), this.dataFile), 788 | s = this.fs.existsSync(t), 789 | i = !s && this.fs.existsSync(e), 790 | r = JSON.stringify(this.data); 791 | s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) 792 | } 793 | } 794 | lodash_get(t, e, s) { 795 | const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); 796 | let r = t; 797 | for (const t of i) 798 | if (r = Object(r)[t], void 0 === r) return s; 799 | return r 800 | } 801 | lodash_set(t, e, s) { 802 | 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) 803 | } 804 | getdata(t) { 805 | let e = this.getval(t); 806 | if (/^@/.test(t)) { 807 | const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; 808 | if (r) try { 809 | const t = JSON.parse(r); 810 | e = t ? this.lodash_get(t, i, "") : e 811 | } catch (t) { 812 | e = "" 813 | } 814 | } 815 | return e 816 | } 817 | setdata(t, e) { 818 | let s = !1; 819 | if (/^@/.test(e)) { 820 | const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; 821 | try { 822 | const e = JSON.parse(h); 823 | this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) 824 | } catch (e) { 825 | const o = {}; 826 | this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) 827 | } 828 | } else s = this.setval(t, e); 829 | return s 830 | } 831 | getval(t) { 832 | 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 833 | } 834 | setval(t, e) { 835 | 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 836 | } 837 | initGotEnv(t) { 838 | 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)) 839 | } 840 | get(t, e = (() => {})) { 841 | 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, { 842 | "X-Surge-Skip-Scripting": !1 843 | })), $httpClient.get(t, (t, s, i) => { 844 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 845 | })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 846 | hints: !1 847 | })), $task.fetch(t).then(t => { 848 | const { 849 | statusCode: s, 850 | statusCode: i, 851 | headers: r, 852 | body: o 853 | } = t; 854 | e(null, { 855 | status: s, 856 | statusCode: i, 857 | headers: r, 858 | body: o 859 | }, o) 860 | }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { 861 | try { 862 | if (t.headers["set-cookie"]) { 863 | const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); 864 | s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar 865 | } 866 | } catch (t) { 867 | this.logErr(t) 868 | } 869 | }).then(t => { 870 | const { 871 | statusCode: s, 872 | statusCode: i, 873 | headers: r, 874 | body: o 875 | } = t; 876 | e(null, { 877 | status: s, 878 | statusCode: i, 879 | headers: r, 880 | body: o 881 | }, o) 882 | }, t => { 883 | const { 884 | message: s, 885 | response: i 886 | } = t; 887 | e(s, i, i && i.body) 888 | })) 889 | } 890 | post(t, e = (() => {})) { 891 | 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, { 892 | "X-Surge-Skip-Scripting": !1 893 | })), $httpClient.post(t, (t, s, i) => { 894 | !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) 895 | }); 896 | else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { 897 | hints: !1 898 | })), $task.fetch(t).then(t => { 899 | const { 900 | statusCode: s, 901 | statusCode: i, 902 | headers: r, 903 | body: o 904 | } = t; 905 | e(null, { 906 | status: s, 907 | statusCode: i, 908 | headers: r, 909 | body: o 910 | }, o) 911 | }, t => e(t)); 912 | else if (this.isNode()) { 913 | this.initGotEnv(t); 914 | const { 915 | url: s, 916 | ...i 917 | } = t; 918 | this.got.post(s, i).then(t => { 919 | const { 920 | statusCode: s, 921 | statusCode: i, 922 | headers: r, 923 | body: o 924 | } = t; 925 | e(null, { 926 | status: s, 927 | statusCode: i, 928 | headers: r, 929 | body: o 930 | }, o) 931 | }, t => { 932 | const { 933 | message: s, 934 | response: i 935 | } = t; 936 | e(s, i, i && i.body) 937 | }) 938 | } 939 | } 940 | time(t, e = null) { 941 | const s = e ? new Date(e) : new Date; 942 | let i = { 943 | "M+": s.getMonth() + 1, 944 | "d+": s.getDate(), 945 | "H+": s.getHours(), 946 | "m+": s.getMinutes(), 947 | "s+": s.getSeconds(), 948 | "q+": Math.floor((s.getMonth() + 3) / 3), 949 | S: s.getMilliseconds() 950 | }; 951 | /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); 952 | 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))); 953 | return t 954 | } 955 | msg(e = t, s = "", i = "", r) { 956 | const o = t => { 957 | if (!t) return t; 958 | if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { 959 | "open-url": t 960 | } : this.isSurge() ? { 961 | url: t 962 | } : void 0; 963 | if ("object" == typeof t) { 964 | if (this.isLoon()) { 965 | let e = t.openUrl || t.url || t["open-url"], 966 | s = t.mediaUrl || t["media-url"]; 967 | return { 968 | openUrl: e, 969 | mediaUrl: s 970 | } 971 | } 972 | if (this.isQuanX()) { 973 | let e = t["open-url"] || t.url || t.openUrl, 974 | s = t["media-url"] || t.mediaUrl; 975 | return { 976 | "open-url": e, 977 | "media-url": s 978 | } 979 | } 980 | if (this.isSurge()) { 981 | let e = t.url || t.openUrl || t["open-url"]; 982 | return { 983 | url: e 984 | } 985 | } 986 | } 987 | }; 988 | if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { 989 | let t = ["", "==============📣系统通知📣=============="]; 990 | t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) 991 | } 992 | } 993 | log(...t) { 994 | t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) 995 | } 996 | logErr(t, e) { 997 | const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); 998 | s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) 999 | } 1000 | wait(t) { 1001 | return new Promise(e => setTimeout(e, t)) 1002 | } 1003 | done(t = {}) { 1004 | const e = (new Date).getTime(), 1005 | s = (e - this.startTime) / 1e3; 1006 | this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) 1007 | } 1008 | }(t, e) 1009 | } 1010 | --------------------------------------------------------------------------------