├── Deprecated
├── qqMusic.js
└── xmSport.js
├── Gallery.json
├── README.md
├── Script
├── boxjs_to_ql.js
├── caixin.js
├── gdong.js
├── iQiYi.py
├── notify.py
├── ql_api.js
├── sendNotify.js
├── tenvideo.js
└── 移动云盘.py
├── WowYiJiu.box.json
├── WowYiJiu.json
├── YiJiu.conf
├── YiJiu_Adblock.conf
├── YiJiu_GetCookie.conf
├── YiJiu_Task.conf
├── icon
├── 10000.png
├── 10010.png
├── 52pj.png
├── 60s.jpg
├── Adblock.png
├── Alpha
│ ├── burning.png
│ ├── gdong.png
│ ├── ql.png
│ ├── qqMusic.png
│ ├── tenvideo.png
│ └── txSports.png
├── Apple.png
├── Color
│ ├── burning.png
│ ├── gdong.png
│ ├── ql.png
│ ├── qqMusic.png
│ ├── tenvideo.png
│ └── txSports.png
├── Final.png
├── HK.png
├── JP.png
├── JiJi.png
├── Netflix.png
├── SG.png
├── StarCharge.png
├── Streaming.png
├── StreamingSE.png
├── TW.png
├── Telegram.png
├── TikTok.png
├── US.png
├── feng.png
├── flyertea.png
├── gaode.jpg
├── hellobike.png
├── iMaoTai.png
├── iQIYI.png
├── iios.jpg
├── ithome.png
├── jParking.png
├── manmanbuy.png
├── meituan.png
├── mgtv.png
├── moyu.png
├── mysl.jpg
├── sfexpress.png
├── smzdm.png
├── v2ex.png
├── weibo.png
├── ximalaya.png
└── xmyd.png
└── rewrite
├── Deprecated
└── get_qqMusic_cookie.conf
├── get_gdong_cookie.conf
└── get_tenvideo_cookie.conf
/Deprecated/xmSport.js:
--------------------------------------------------------------------------------
1 | /*
2 | 小米运动修改微信支付宝运动步数
3 | APP Store下载小米运动APP
4 | 登入小米运动(登录方式必须是手机号码+密码(没有就用手机号码注册),下面的第三方账号(小米账号,Apple,微信)授权登录不行)
5 | 登录成功后在 我的->第三方接入->绑定支付宝,微信
6 | 小米运动只要不退出登录,就会自动获取新的token,即永久有效
7 | [MITM]
8 | hostname = account.huami.com
9 | Surge
10 | [Script]
11 | 小米运动 = type=cron,cronexp="15 17 * * *",wake-system=1,timeout=3600,script-path=xmSports.js
12 | 小米运动获取Token = type=http-response,pattern=^https:\/\/account\.huami\.com\/v2\/client\/login, requires-body=1, max-size=0, script-path=backUp/xmSports.js
13 | 圈X
14 | [task_local]
15 | # 小米运动
16 | 15 17 * * * xmSports.js, tag=小米运动, img-url=https://raw.githubusercontent.com/58xinian/icon/master/xmyd.png, enabled=true
17 | [rewrite_local]
18 | # 小米运动获取Token
19 | ^https:\/\/account\.huami\.com\/v2\/client\/login url script-response-body xmSports.js
20 | Loon
21 | [Script]
22 | cron "15 17 * * *" script-path=xmSports.js, tag=小米运动
23 | http-response ^https:\/\/account\.huami\.com\/v2\/client\/login script-path=xmSports.js, requires-body=true, timeout=3600, tag=小米运动获取Token
24 | */
25 |
26 | const $ = new Env('小米运动');
27 | const isRequest = typeof $request != "undefined"
28 | let dataJSON = "%5B%7B%22data_hr%22%3A%22%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9L%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FVv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0v%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9e%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0n%5C%2Fa%5C%2F%5C%2F%5C%2FS%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0b%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F1FK%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FR%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9PTFFpaf9L%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FR%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0j%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9K%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FOv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fzf%5C%2F%5C%2F%5C%2F86%5C%2Fzr%5C%2FOv88%5C%2Fzf%5C%2FPf%5C%2F%5C%2F%5C%2F0v%5C%2FS%5C%2F8%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FSf%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fz3%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0r%5C%2FOv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FS%5C%2F9L%5C%2Fzb%5C%2FSf9K%5C%2F0v%5C%2FRf9H%5C%2Fzj%5C%2FSf9K%5C%2F0%5C%2F%5C%2FN%5C%2F%5C%2F%5C%2F%5C%2F0D%5C%2FSf83%5C%2Fzr%5C%2FPf9M%5C%2F0v%5C%2FOv9e%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FS%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fzv%5C%2F%5C%2Fz7%5C%2FO%5C%2F83%5C%2Fzv%5C%2FN%5C%2F83%5C%2Fzr%5C%2FN%5C%2F86%5C%2Fz%5C%2F%5C%2FNv83%5C%2Fzn%5C%2FXv84%5C%2Fzr%5C%2FPP84%5C%2Fzj%5C%2FN%5C%2F9e%5C%2Fzr%5C%2FN%5C%2F89%5C%2F03%5C%2FP%5C%2F89%5C%2Fz3%5C%2FQ%5C%2F9N%5C%2F0v%5C%2FTv9C%5C%2F0H%5C%2FOf9D%5C%2Fzz%5C%2FOf88%5C%2Fz%5C%2F%5C%2FPP9A%5C%2Fzr%5C%2FN%5C%2F86%5C%2Fzz%5C%2FNv87%5C%2F0D%5C%2FOv84%5C%2F0v%5C%2FO%5C%2F84%5C%2Fzf%5C%2FMP83%5C%2FzH%5C%2FNv83%5C%2Fzf%5C%2FN%5C%2F84%5C%2Fzf%5C%2FOf82%5C%2Fzf%5C%2FOP83%5C%2Fzb%5C%2FMv81%5C%2FzX%5C%2FR%5C%2F9L%5C%2F0v%5C%2FO%5C%2F9I%5C%2F0T%5C%2FS%5C%2F9A%5C%2Fzn%5C%2FPf89%5C%2Fzn%5C%2FNf9K%5C%2F07%5C%2FN%5C%2F83%5C%2Fzn%5C%2FNv83%5C%2Fzv%5C%2FO%5C%2F9A%5C%2F0H%5C%2FOf8%5C%2F%5C%2Fzj%5C%2FPP83%5C%2Fzj%5C%2FS%5C%2F87%5C%2Fzj%5C%2FNv84%5C%2Fzf%5C%2FOf83%5C%2Fzf%5C%2FOf83%5C%2Fzb%5C%2FNv9L%5C%2Fzj%5C%2FNv82%5C%2Fzb%5C%2FN%5C%2F85%5C%2Fzf%5C%2FN%5C%2F9J%5C%2Fzf%5C%2FNv83%5C%2Fzj%5C%2FNv84%5C%2F0r%5C%2FSv83%5C%2Fzf%5C%2FMP%5C%2F%5C%2F%5C%2Fzb%5C%2FMv82%5C%2Fzb%5C%2FOf85%5C%2Fz7%5C%2FNv8%5C%2F%5C%2F0r%5C%2FS%5C%2F85%5C%2F0H%5C%2FQP9B%5C%2F0D%5C%2FNf89%5C%2Fzj%5C%2FOv83%5C%2Fzv%5C%2FNv8%5C%2F%5C%2F0f%5C%2FSv9O%5C%2F0ZeXv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F1X%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9B%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FTP%5C%2F%5C%2F%5C%2F1b%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9N%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%22%2C%22date%22%3A%222020-08-14%22%2C%22data%22%3A%5B%7B%22start%22%3A0%2C%22stop%22%3A1439%2C%22value%22%3A%22UA8AUBQAUAwAUBoAUAEAYCcAUBkAUB4AUBgAUCAAUAEAUBkAUAwAYAsAYB8AYB0AYBgAYCoAYBgAYB4AUCcAUBsAUB8AUBwAUBIAYBkAYB8AUBoAUBMAUCEAUCIAYBYAUBwAUCAAUBgAUCAAUBcAYBsAYCUAATIPYD0KECQAYDMAYB0AYAsAYCAAYDwAYCIAYB0AYBcAYCQAYB0AYBAAYCMAYAoAYCIAYCEAYCYAYBsAYBUAYAYAYCIAYCMAUB0AUCAAUBYAUCoAUBEAUC8AUB0AUBYAUDMAUDoAUBkAUC0AUBQAUBwAUA0AUBsAUAoAUCEAUBYAUAwAUB4AUAwAUCcAUCYAUCwKYDUAAUUlEC8IYEMAYEgAYDoAYBAAUAMAUBkAWgAAWgAAWgAAWgAAWgAAUAgAWgAAUBAAUAQAUA4AUA8AUAkAUAIAUAYAUAcAUAIAWgAAUAQAUAkAUAEAUBkAUCUAWgAAUAYAUBEAWgAAUBYAWgAAUAYAWgAAWgAAWgAAWgAAUBcAUAcAWgAAUBUAUAoAUAIAWgAAUAQAUAYAUCgAWgAAUAgAWgAAWgAAUAwAWwAAXCMAUBQAWwAAUAIAWgAAWgAAWgAAWgAAWgAAWgAAWgAAWgAAWREAWQIAUAMAWSEAUDoAUDIAUB8AUCEAUC4AXB4AUA4AWgAAUBIAUA8AUBAAUCUAUCIAUAMAUAEAUAsAUAMAUCwAUBYAWgAAWgAAWgAAWgAAWgAAWgAAUAYAWgAAWgAAWgAAUAYAWwAAWgAAUAYAXAQAUAMAUBsAUBcAUCAAWwAAWgAAWgAAWgAAWgAAUBgAUB4AWgAAUAcAUAwAWQIAWQkAUAEAUAIAWgAAUAoAWgAAUAYAUB0AWgAAWgAAUAkAWgAAWSwAUBIAWgAAUC4AWSYAWgAAUAYAUAoAUAkAUAIAUAcAWgAAUAEAUBEAUBgAUBcAWRYAUA0AWSgAUB4AUDQAUBoAXA4AUA8AUBwAUA8AUA4AUA4AWgAAUAIAUCMAWgAAUCwAUBgAUAYAUAAAUAAAUAAAUAAAUAAAUAAAUAAAUAAAUAAAWwAAUAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAeSEAeQ8AcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBcAcAAAcAAAcCYOcBUAUAAAUAAAUAAAUAAAUAUAUAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcCgAeQAAcAAAcAAAcAAAcAAAcAAAcAYAcAAAcBgAeQAAcAAAcAAAegAAegAAcAAAcAcAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcCkAeQAAcAcAcAAAcAAAcAwAcAAAcAAAcAIAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcCIAeQAAcAAAcAAAcAAAcAAAcAAAeRwAeQAAWgAAUAAAUAAAUAAAUAAAUAAAcAAAcAAAcBoAeScAeQAAegAAcBkAeQAAUAAAUAAAUAAAUAAAUAAAUAAAcAAAcAAAcAAAcAAAcAAAcAAAegAAegAAcAAAcAAAcBgAeQAAcAAAcAAAcAAAcAAAcAAAcAkAegAAegAAcAcAcAAAcAcAcAAAcAAAcAAAcAAAcA8AeQAAcAAAcAAAeRQAcAwAUAAAUAAAUAAAUAAAUAAAUAAAcAAAcBEAcA0AcAAAWQsAUAAAUAAAUAAAUAAAUAAAcAAAcAoAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAYAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBYAegAAcAAAcAAAegAAcAcAcAAAcAAAcAAAcAAAcAAAeRkAegAAegAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAEAcAAAcAAAcAAAcAUAcAQAcAAAcBIAeQAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBsAcAAAcAAAcBcAeQAAUAAAUAAAUAAAUAAAUAAAUBQAcBYAUAAAUAAAUAoAWRYAWTQAWQAAUAAAUAAAUAAAcAAAcAAAcAAAcAAAcAAAcAMAcAAAcAQAcAAAcAAAcAAAcDMAeSIAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBQAeQwAcAAAcAAAcAAAcAMAcAAAeSoAcA8AcDMAcAYAeQoAcAwAcFQAcEMAeVIAaTYAbBcNYAsAYBIAYAIAYAIAYBUAYCwAYBMAYDYAYCkAYDcAUCoAUCcAUAUAUBAAWgAAYBoAYBcAYCgAUAMAUAYAUBYAUA4AUBgAUAgAUAgAUAsAUAsAUA4AUAMAUAYAUAQAUBIAASsSUDAAUDAAUBAAYAYAUBAAUAUAUCAAUBoAUCAAUBAAUAoAYAIAUAQAUAgAUCcAUAsAUCIAUCUAUAoAUA4AUB8AUBkAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAA%22%2C%22tz%22%3A32%2C%22did%22%3A%22DA932FFFFE8816E7%22%2C%22src%22%3A24%7D%5D%2C%22summary%22%3A%22%7B%5C%22v%5C%22%3A6%2C%5C%22slp%5C%22%3A%7B%5C%22st%5C%22%3A1597349880%2C%5C%22ed%5C%22%3A1597369860%2C%5C%22dp%5C%22%3A39%2C%5C%22lt%5C%22%3A294%2C%5C%22wk%5C%22%3A0%2C%5C%22usrSt%5C%22%3A-1440%2C%5C%22usrEd%5C%22%3A-1440%2C%5C%22wc%5C%22%3A0%2C%5C%22is%5C%22%3A169%2C%5C%22lb%5C%22%3A10%2C%5C%22to%5C%22%3A23%2C%5C%22dt%5C%22%3A0%2C%5C%22rhr%5C%22%3A58%2C%5C%22ss%5C%22%3A69%2C%5C%22stage%5C%22%3A%5B%7B%5C%22start%5C%22%3A1698%2C%5C%22stop%5C%22%3A1711%2C%5C%22mode%5C%22%3A4%7D%2C%7B%5C%22start%5C%22%3A1712%2C%5C%22stop%5C%22%3A1728%2C%5C%22mode%5C%22%3A5%7D%2C%7B%5C%22start%5C%22%3A1729%2C%5C%22stop%5C%22%3A1818%2C%5C%22mode%5C%22%3A4%7D%2C%7B%5C%22start%5C%22%3A1819%2C%5C%22stop%5C%22%3A1832%2C%5C%22mode%5C%22%3A5%7D%2C%7B%5C%22start%5C%22%3A1833%2C%5C%22stop%5C%22%3A1920%2C%5C%22mode%5C%22%3A4%7D%2C%7B%5C%22start%5C%22%3A1921%2C%5C%22stop%5C%22%3A1928%2C%5C%22mode%5C%22%3A5%7D%2C%7B%5C%22start%5C%22%3A1929%2C%5C%22stop%5C%22%3A2030%2C%5C%22mode%5C%22%3A4%7D%5D%7D%2C%5C%22stp%5C%22%3A%7B%5C%22ttl%5C%22%3A125%2C%5C%22dis%5C%22%3A82%2C%5C%22cal%5C%22%3A5%2C%5C%22wk%5C%22%3A7%2C%5C%22rn%5C%22%3A0%2C%5C%22runDist%5C%22%3A23%2C%5C%22runCal%5C%22%3A3%7D%2C%5C%22goal%5C%22%3A8000%2C%5C%22tz%5C%22%3A%5C%2228800%5C%22%2C%5C%22sn%5C%22%3A%5C%22e716882f93da%5C%22%7D%22%2C%22source%22%3A24%2C%22type%22%3A0%7D%5D";
29 | const headers = {
30 | 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
31 | }
32 | let login_token = '';
33 | //需要修改的运动步数波动范围,脚本默认修改步数范围为1w9到2w5
34 | const step = randomFriendPin($.getdata('xmMinStep')*1 || 19000, $.getdata('xmMaxStep')*1 || 25000);
35 | function getToken() {
36 | if ($response.body) {
37 | const body = JSON.parse($response.body);
38 | const loginToken = body.token_info.login_token;
39 | $.log(`${$.name}token\n${loginToken}\n`)
40 | if ($.getdata('xmSportsToken')) {
41 | $.msg($.name, '更新Token: 成功🎉', ``);
42 | } else {
43 | $.msg($.name, '获取Token: 成功🎉', '');
44 | }
45 | $.setdata(loginToken, 'xmSportsToken');
46 | }
47 | $.done({})
48 | }
49 |
50 | async function start() {
51 | login_token = $.isNode() ? (process.env.XM_SPORT_TOKEN ? process.env.XM_SPORT_TOKEN : login_token) : ($.getdata('xmSportsToken') ? $.getdata('xmSportsToken') : login_token);
52 | // console.log(`login_token:::${login_token}`)
53 | if (login_token) {
54 | await get_app_token(login_token);
55 | // console.log(`$.tokenInfo${JSON.stringify($.tokenInfo)}`)
56 | if ($.tokenInfo && $.tokenInfo.result === 'ok') {
57 | const {app_token, user_id} = $.tokenInfo.token_info;
58 | await get_time();
59 | await change_step(app_token, user_id);
60 | if ($.changeStepRes && $.changeStepRes.code === 1) {
61 | console.log(`步数修改成功:${step}步`);
62 | $.msg($.name, `${step}步🏃修改成功`, `时间:${timeFormat(localtime())}`, { "open-url": "alipays://platformapi/startapp?appId=20000869" })
63 | } else {
64 | console.log(`修改运动步数失败`)
65 | }
66 | } else {
67 | $.msg($.name, '失败', `Token已失效,请重新获取`)
68 | }
69 | } else {
70 | $.log('暂无Token')
71 | $.log(`\n\n获取TOKEN方法:\nAPP Store下载小米运动APP\n登入小米运动(登录方式必须是手机号码+密码(没有就用手机号码注册),下面的第三方账号(小米账号,Apple,微信)授权登录不行)\n登录成功后在 我的->第三方接入->绑定支付宝,微信\n小米运动只要不退出登录,就会自动获取新的token,即永久有效`)
72 | //$.msg($.name, `失败`, '暂无Token')
73 | }
74 | $.done()
75 | }
76 |
77 | function change_step(app_token, user_id) {
78 | const date = dataJSON.match(/.*?date%22%3A%22(.*?)%22%2C%22data.*?/)[1];
79 | const ttf = dataJSON.match(/.*?ttl%5C%22%3A(.*?)%2C%5C%22dis.*?/)[1];
80 | dataJSON = dataJSON.replace(date, timeFormat(localtime()));
81 | dataJSON = dataJSON.replace(ttf, step.toString());
82 | console.log(timeFormat(localtime()))
83 | return new Promise(resolve => {
84 | const options = {
85 | "url": `https://api-mifit-cn2.huami.com/v1/data/band_data.json?&t=${$.t}`,
86 | "body": `userid=${user_id.toString()}&last_sync_data_time=1597306380&device_type=0&last_deviceid=DA932FFFFE8816E7&data_json=${dataJSON}`,
87 | "headers": {
88 | "Content-Type":"application/x-www-form-urlencoded;charset=UTF-8",
89 | "apptoken": app_token,
90 | }
91 | }
92 | $.post(options, (err, resp, data) => {
93 | try {
94 | if (err) {
95 | console.log(`${JSON.stringify(err)}`)
96 | console.log(`${$.name} API请求失败,请检查网路重试`)
97 | } else {
98 | console.log(`修改步数结果:${data}`);
99 | $.changeStepRes = JSON.parse(data);
100 | }
101 | } catch (e) {
102 | $.logErr(e, resp)
103 | } finally {
104 | resolve();
105 | }
106 | })
107 | })
108 | }
109 |
110 | function get_app_token(login_token, headers) {
111 | return new Promise(resolve => {
112 | $.get({url: `https://account-cn.huami.com/v1/client/app_tokens?app_name=com.xiaomi.hm.health&dn=api-user.huami.com%2Capi-mifit.huami.com%2Capp-analytics.huami.com&login_token=${login_token}&os_version=4.1.0`, headers}, (err, resp, data) => {
113 | try {
114 | if (err) {
115 | console.log(`${JSON.stringify(err)}`)
116 | console.log(`${$.name} API请求失败,请检查网路重试`)
117 | } else {
118 | console.log(data)
119 | if (data) {
120 | $.tokenInfo = JSON.parse(data);
121 | }
122 | }
123 | } catch (e) {
124 | $.logErr(e, resp)
125 | } finally {
126 | resolve();
127 | }
128 | })
129 | })
130 | }
131 | function get_time() {
132 | return new Promise(resolve => {
133 | $.get({url: `http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp`}, (err, resp, data) => {
134 | try {
135 | if (err) {
136 | console.log(`${JSON.stringify(err)}`)
137 | console.log(`${$.name} API请求失败,请检查网路重试`)
138 | } else {
139 | console.log(data)
140 | if (data) {
141 | data = JSON.parse(data);
142 | $.t = data.data.t;
143 | }
144 | }
145 | } catch (e) {
146 | $.logErr(e, resp)
147 | } finally {
148 | resolve(data);
149 | }
150 | })
151 | })
152 | }
153 | function localtime() {
154 | return new Date().getTime() + new Date().getTimezoneOffset()*60*1000 + 8*60*60*1000;
155 | }
156 | function timeFormat(time) {
157 | let date;
158 | if (time) {
159 | date = new Date(time)
160 | } else {
161 | date = new Date();
162 | }
163 | return date.getFullYear() + '-' + ((date.getMonth() + 1) >= 10 ? (date.getMonth() + 1) : '0' + (date.getMonth() + 1)) + '-' + (date.getDate() >= 10 ? date.getDate() : '0' + date.getDate());
164 | }
165 | //随机生成m(小)到n(大)的数,包含m和n
166 | function randomFriendPin(m,n) {
167 | return Math.round(Math.random()*(n - m) + m);
168 | }
169 | isRequest ? getToken() : start();
170 | // prettier-ignore
171 | function Env(t,e){"undefined"!=typeof process&&JSON.stringify(process.env).indexOf("GITHUB")>-1&&process.exit(0);class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),n={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(n,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)}
--------------------------------------------------------------------------------
/Gallery.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "WowYiJiu 自用脚本",
3 | "description": "https://github.com/WowYiJiu/Personal",
4 | "task": [
5 | {
6 | "config": "0 0 * * * https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/boxjs_to_ql.js, tag=boxjs_to_ql, img-url=https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/Color/ql.png, enabled=true"
7 | },
8 | {
9 | "config": "10 6 * * * https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/manmanbuy/manmanbuy_checkin.js, tag=慢慢买, img-url=https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/manmanbuy.png, enabled=true"
10 | },
11 | {
12 | "config": "20 6 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.js, tag=威锋网, img-url=https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/feng.png, enabled=true"
13 | },
14 | {
15 | "config": "30 6 * * * https://raw.githubusercontent.com/ClydeTime/Quantumult/main/Script/Task/xmlySign.js, tag=喜马拉雅, img-url=https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/ximalaya.png, enabled=true"
16 | },
17 | {
18 | "config": "40 6 * * * https://raw.githubusercontent.com/wf021325/qx/master/task/ampDache.js, tag=高德地图, img-url=https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/gaode.jpg, enabled=true"
19 | },
20 | {
21 | "config": "45 6 * * * https://raw.githubusercontent.com/FoKit/Scripts/main/scripts/weibo_sign.js, tag=新浪微博, img-url=https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/weibo.png, enabled=true"
22 | },
23 | {
24 | "config": "50 6 * * * https://raw.githubusercontent.com/FoKit/Scripts/main/scripts/jparking_sign.js, tag=捷停车, img-url=https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/jParking.png, enabled=true"
25 | },
26 | {
27 | "config": "5 7 * * * https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/tenvideo.js, tag=腾讯视频, img-url=https://github.com/WowYiJiu/Personal/blob/main/icon/Color/tenvideo.png?raw=true, enabled=true",
28 | "addons": "https://raw.githubusercontent.com/WowYiJiu/Personal/main/rewrite/get_tenvideo_cookie.conf, tag=腾讯视频, update-interval=172800, opt-parser=false, enabled=false"
29 | },
30 | {
31 | "config": "15 7 * * * https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/gdong.js, tag=G动, img-url=https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/Color/gdong.png, enabled=true",
32 | "addons": "https://raw.githubusercontent.com/WowYiJiu/Personal/main/rewrite/get_gdong_cookie.conf, tag=G动, update-interval=172800, opt-parser=false, enabled=false"
33 | },
34 | {
35 | "config": "0 12 * * * https://raw.githubusercontent.com/Yuheng0101/X/main/Tasks/60s.js, tag=每天60s读懂世界, img-url=https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/60s.jpg, enabled=true"
36 | }
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 特别声明
2 |
3 | - 本仓库发布的项目中脚本涉及的任何解锁和解密分析,仅用于测试和学习研究
4 |
5 | - 禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断
6 |
7 | - 禁止任何公众号、自媒体进行任何形式的转载、发布
8 |
9 | - WowYiJiu 对任何脚本问题概不负责,包括但不限于由任何脚本错误导致的任何损失或损害
10 |
11 | - 间接使用脚本的任何用户,包括但不限于建立 VPS 或在某些行为违反国家/地区法律或相关法规的情况下进行传播, WowYiJiu 对于由此引起的任何隐私泄漏或其他后果概不负责
12 |
13 | - 如果任何单位或个人认为该项目的脚本可能涉嫌侵犯其权利,则应及时通知并提供身份证明,所有权证明,我们将在收到认证文件后删除相关脚本
14 |
15 | - WowYiJiu 保留随时更改或补充此免责声明的权利。一旦使用并复制了任何相关脚本,则视为您已接受此免责声明
16 |
17 | **您必须在下载后的 24 小时内从计算机或手机中完全删除以上内容.**
18 |
19 | > **_您使用或者复制了本仓库且本人制作的任何脚本,则视为`已接受`此声明,请仔细阅读_**
20 |
21 | ### Quantumult X 参考
22 |
23 | - [Quantumult X 用户教程](https://www.notion.so/Quantumult-X-1d32ddc6e61c4892ad2ec5ea47f00917)
24 | - [Quantumult X 完整配置解读](https://raw.githubusercontent.com/KOP-XIAO/QuantumultX/master/QuantumultX_Profiles.conf)
25 | - [w37fhy 懒人配置](https://raw.githubusercontent.com/w37fhy/QuantumultX/master/w37fhy_diy.conf)
26 | - [limbopro 懒人配置](https://raw.githubusercontent.com/limbopro/Profiles4limbo/main/full.conf)
27 | - [Orz-3 懒人配置](https://raw.githubusercontent.com/Orz-3/QuantumultX/master/Orz-3.conf)
28 |
29 | ### 特别感谢以下 YouTube 视频作者 (排名不分先后)
30 |
31 | - [@北纬 37 度的大飛](https://www.youtube.com/playlist?list=PLjqZWxLDYP3t12BpTjBvrDCbyJkYNxzwE)
32 | - [@橙子小白技术分享](https://www.youtube.com/playlist?list=PLAwbcHHUuui90hRChtmitMuoDPoNdmYqD)
33 | - [@Hell Cell](https://www.youtube.com/channel/UCgjdfJbXYaFfC3Wxump37Mg)
34 |
35 | ### 特别感谢以下脚本作者以及整合时参考的作者 (排名不分先后)
36 |
37 | - [@NobyDa](https://github.com/NobyDa)
38 | - [@chavyleung](https://github.com/chavyleung)
39 | - [@Sunert](https://github.com/Sunert)
40 | - [@blackmatrix7](https://github.com/blackmatrix7)
41 | - [@yichahucha](https://github.com/yichahucha)
42 | - [@lxk0301](https://github.com/lxk0301)
43 | - [@evilbutcher](https://github.com/evilbutcher)
44 | - [@toulanboy](https://github.com/toulanboy)
45 | - [@Choler](https://github.com/Choler)
46 | - [@nzw9314](https://github.com/nzw9314)
47 | - [@KOP-XIAO](https://github.com/KOP-XIAO)
48 |
49 | ### 分流规则作者 (排名不分先后)
50 |
51 | - [@DivineEngine](https://github.com/DivineEngine)
52 | - [@blackmatrix7](https://github.com/blackmatrix7)
53 | - [@app2smile](https://github.com/app2smile)
54 | - [@RuCu6](https://github.com/RuCu6)
55 | - [@VirgilClyne](https://github.com/VirgilClyne)
56 |
57 | ### 图标作者 (排名不分先后)
58 |
59 | - [@Koolson](https://github.com/Koolson)
60 | - [@Orz-3](https://github.com/Orz-3)
61 | - [@Semporia](https://github.com/Semporia)
62 |
--------------------------------------------------------------------------------
/Script/boxjs_to_ql.js:
--------------------------------------------------------------------------------
1 | /**
2 | *@file boxjs_to_ql
3 | *@desp boxjs同步环境变量到青龙面板
4 | *@env sync_env__key
5 | *@author WowYiJiu
6 | *@updated 2024-4-8
7 | *@link https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/boxjs_to_ql.js
8 | *@thanks @dompling: https://github.com/dompling
9 |
10 | 💬 BoxJs订阅:https://raw.githubusercontent.com/WowYiJiu/Personal/main/WowYiJiu.box.json
11 |
12 | ⚙ 配置 (Quantumult X)
13 | [task_local]
14 | 0 0 * * * https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/boxjs_to_ql.js, tag=boxjs_to_ql, img-url=https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/Color/ql.png, enabled=true
15 | */
16 | const $ = new API("ql", true);
17 |
18 | const title = "🐉 通知提示";
19 | const notifyMsg = [];
20 | let envKeys = $.read("sync_env__key") || "";
21 |
22 | $.getval = (t) => ($.env.isQX ? $prefs.valueForKey(t) : $persistentStore.read(t));
23 |
24 | $.getdata=(t)=>{const lodash_get=(t,s="",e)=>s.split(/[(d+)]/g,".$1").split(".").reduce((res,key)=>res?.[key],t)||e;let s=$.getval(t);if(/^@/.test(t)){const[,e,i]=/^@(.*?).(.*?)$/.exec(t);const r=e?$.getval(e):"";if(r){try{const t=JSON.parse(r);s=t?lodash_get(t,i,""):s}catch(error){s=""}}}return s};
25 |
26 | const syncData = {};
27 | let envsData = envKeys.split('\n');
28 | var syncEnvs = [];
29 | for (var i = 0; i < envsData.length; i++) {
30 | var parts = envsData[i].split('#');
31 | if (parts[0].startsWith('-')) {
32 | $.log(parts[2] + "跳过同步");
33 | continue;
34 | }
35 | var obj = { 'BoxJsKey': parts[0], 'qlEnv': parts[1], 'qlRemark': parts[2] };
36 | syncEnvs.push(obj);
37 | }
38 | function validate(value, pattern) {
39 | var re = new RegExp(pattern);
40 | return re.test(value);
41 | }
42 | syncEnvs.forEach((item) => {
43 | if (!validate(item.qlEnv, '^[a-zA-Z_][0-9a-zA-Z_]*$')) {
44 | return $.error(`${item.qlRemark}:${item.qlEnv}环境变量名格式不正确, 本次不同步`);
45 | }
46 | const qlValue = $.getdata(item.BoxJsKey) || "";
47 | if (!qlValue) return $.error("环境变量值不能为空");
48 | notifyMsg.push(`${item.qlRemark}:${item.qlEnv}`);
49 | syncData[item.BoxJsKey] = {
50 | name: item.qlEnv,
51 | value: qlValue,
52 | remarks: item.qlRemark,
53 | };
54 | });
55 |
56 | async function getScriptUrl() {
57 | const opt = {
58 | url: `https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/ql_api.js`
59 | };
60 | return $.http.get(opt).then((response) => response.body);
61 | }
62 |
63 | !(async () => {
64 | const qlData = Object.values(syncData);
65 | if (!qlData.length) return $.notify(title, "同步失败", "环境变量不能为空");
66 |
67 | const ql_script = (await getScriptUrl()) || "";
68 | eval(ql_script);
69 |
70 | await $.ql.login();
71 |
72 | $.info(`环境变量明细`);
73 | notifyMsg.forEach(msg => {
74 | $.info(msg);
75 | });
76 | $.info(`开始清空环境变量`);
77 | for (let index = 0; index < qlData.length; index++) {
78 | const element = qlData[index];
79 | const response = await $.ql.select(element.name);
80 | const delIds = response.data.map((item) => item.id);
81 | const delNames = response.data.map((item) => item.name);
82 | await $.ql.delete(delIds);
83 | $.log(`清空${element.remarks}环境变量${element.name}成功`);
84 | }
85 |
86 | $.info(`开始同步环境变量`);
87 | const res = await $.ql.add(qlData);
88 | if (res.code === 200) {
89 | $.log(`同步环境变量成功`);
90 | }
91 |
92 | if ($.read("mute") !== "true") {
93 | return $.notify(title, `已同步${notifyMsg.length}条`, notifyMsg.join(`\n`));
94 | }
95 | })()
96 | .catch((e) => $.error(e))
97 | .finally(() => $.done());
98 |
99 | /* prettier-ignore */
100 | function ENV(){const isJSBox=typeof require=="function"&&typeof $jsbox!="undefined";return{isQX:typeof $task!=="undefined",isLoon:typeof $loon!=="undefined",isSurge:typeof $httpClient!=="undefined"&&typeof $utils!=="undefined",isBrowser:typeof document!=="undefined",isNode:typeof require=="function"&&!isJSBox,isJSBox,isRequest:typeof $request!=="undefined",isScriptable:typeof importModule!=="undefined",isShadowrocket:"undefined"!==typeof $rocket,isStash:"undefined"!==typeof $environment&&$environment["stash-version"],}}
101 | /* prettier-ignore */
102 | function HTTP(defaultOptions={baseURL:""}){const{isQX,isLoon,isSurge,isScriptable,isNode,isBrowser,isShadowrocket,isStash,}=ENV();const methods=["GET","POST","PUT","DELETE","HEAD","OPTIONS","PATCH"];const URL_REGEX=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;function send(method,options){options=typeof options==="string"?{url:options}:options;const baseURL=defaultOptions.baseURL;if(baseURL&&!URL_REGEX.test(options.url||"")){options.url=baseURL?baseURL+options.url:options.url}if(options.body&&options.headers&&!options.headers["Content-Type"]){options.headers["Content-Type"]="application/x-www-form-urlencoded"}options={...defaultOptions,...options};const timeout=options.timeout;const events={...{onRequest:()=>{},onResponse:(resp)=>resp,onTimeout:()=>{},},...options.events,};events.onRequest(method,options);let worker;if(isQX){worker=$task.fetch({method,...options})}else if(isLoon||isSurge||isNode||isShadowrocket||isStash){worker=new Promise((resolve,reject)=>{const request=isNode?require("request"):$httpClient;request[method.toLowerCase()](options,(err,response,body)=>{if(err)reject(err);else resolve({statusCode:response.status||response.statusCode,headers:response.headers,body,})})})}else if(isScriptable){const request=new Request(options.url);request.method=method;request.headers=options.headers;request.body=options.body;worker=new Promise((resolve,reject)=>{request.loadString().then((body)=>{resolve({statusCode:request.response.statusCode,headers:request.response.headers,body,})}).catch((err)=>reject(err))})}else if(isBrowser){worker=new Promise((resolve,reject)=>{fetch(options.url,{method,headers:options.headers,body:options.body,}).then((response)=>response.json()).then((response)=>resolve({statusCode:response.status,headers:response.headers,body:response.data,})).catch(reject)})}let timeoutid;const timer=timeout?new Promise((_,reject)=>{timeoutid=setTimeout(()=>{events.onTimeout();return reject(`${method}URL:${options.url}exceeds the timeout ${timeout}ms`)},timeout)}):null;return(timer?Promise.race([timer,worker]).then((res)=>{clearTimeout(timeoutid);return res}):worker).then((resp)=>events.onResponse(resp))}const http={};methods.forEach((method)=>(http[method.toLowerCase()]=(options)=>send(method,options)));return http}
103 | /* prettier-ignore */
104 | function API(name="untitled",debug=false){const{isQX,isLoon,isSurge,isScriptable,isNode,isShadowrocket,isStash,}=ENV();return new(class{constructor(name,debug){this.name=name;this.debug=debug;this.http=HTTP();this.env=ENV();this.node=(()=>{if(isNode){const fs=require("fs");return{fs}}else{return null}})();this.initCache();const delay=(t,v)=>new Promise(function(resolve){setTimeout(resolve.bind(null,v),t)});Promise.prototype.delay=function(t){return this.then(function(v){return delay(t,v)})}}initCache(){if(isQX)this.cache=JSON.parse($prefs.valueForKey(this.name)||"{}");if(isLoon||isSurge)this.cache=JSON.parse($persistentStore.read(this.name)||"{}");if(isNode){let fpath="root.json";if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err))}this.root={};fpath=`${this.name}.json`;if(!this.node.fs.existsSync(fpath)){this.node.fs.writeFileSync(fpath,JSON.stringify({}),{flag:"wx"},(err)=>console.log(err));this.cache={}}else{this.cache=JSON.parse(this.node.fs.readFileSync(`${this.name}.json`))}}}persistCache(){const data=JSON.stringify(this.cache,null,2);if(isQX)$prefs.setValueForKey(data,this.name);if(isLoon||isSurge||isStash||isShadowrocket)$persistentStore.write(data,this.name);if(isNode){this.node.fs.writeFileSync(`${this.name}.json`,data,{flag:"w"},(err)=>console.log(err));this.node.fs.writeFileSync("root.json",JSON.stringify(this.root,null,2),{flag:"w"},(err)=>console.log(err))}}write(data,key){this.log(`SET ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(data,key)}if(isQX){return $prefs.setValueForKey(data,key)}if(isNode){this.root[key]=data}}else{this.cache[key]=data}this.persistCache()}read(key){if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.read(key)}if(isQX){return $prefs.valueForKey(key)}if(isNode){return this.root[key]}}else{return this.cache[key]}}delete(key){this.log(`DELETE ${key}`);if(key.indexOf("#")!==-1){key=key.substr(1);if(isLoon||isSurge||isStash||isShadowrocket){return $persistentStore.write(null,key)}if(isQX){return $prefs.removeValueForKey(key)}if(isNode){delete this.root[key]}}else{delete this.cache[key]}this.persistCache()}notify(title,subtitle="",content="",options={}){const openURL=options["open-url"];const mediaURL=options["media-url"];if(isQX)$notify(title,subtitle,content,options);if(isSurge){$notification.post(title,subtitle,content+`${mediaURL?"\n多媒体:"+mediaURL:""}`,{url:openURL})}if(isLoon||isStash||isShadowrocket){let opts={};if(openURL)opts["openUrl"]=openURL;if(mediaURL)opts["mediaUrl"]=mediaURL;if(JSON.stringify(opts)==="{}"){$notification.post(title,subtitle,content)}else{$notification.post(title,subtitle,content,opts)}}if(isNode||isScriptable){const content_=content+(openURL?`\n点击跳转:${openURL}`:"")+(mediaURL?`\n多媒体:${mediaURL}`:"");if(isJSBox){const push=require("push");push.schedule({title:title,body:(subtitle?subtitle+"\n":"")+content_,})}else{console.log(`${title}\n${subtitle}\n${content_}\n\n`)}}}log(msg){if(this.debug)console.log(`[${this.name}]LOG:${this.stringify(msg)}`)}info(msg){console.log(`[${this.name}]INFO:${this.stringify(msg)}`)}error(msg){console.log(`[${this.name}]ERROR:${this.stringify(msg)}`)}wait(millisec){return new Promise((resolve)=>setTimeout(resolve,millisec))}done(value={}){if(isQX||isLoon||isSurge||isStash||isShadowrocket){$done(value)}else if(isNode&&!isJSBox){if(typeof $context!=="undefined"){$context.headers=value.headers;$context.statusCode=value.statusCode;$context.body=value.body}}}stringify(obj_or_str){if(typeof obj_or_str==="string"||obj_or_str instanceof String)return obj_or_str;else try{return JSON.stringify(obj_or_str,null,2)}catch(err){return"[object Object]"}}})(name,debug)}
--------------------------------------------------------------------------------
/Script/caixin.js:
--------------------------------------------------------------------------------
1 | /*
2 | CaiXinZhouKan Unlock
3 | Quantumult X:
4 | ^http:\/\/ipadcms\.caixin\.com\/tmp\/articles url script-response-body https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/CXZK.js
5 | hostname = ipadcms.caixin.com
6 | */
7 |
8 | var body = $response.body;
9 | body = body.replace(/"isfree":0/g,'"isfree":1');
10 | $done({body});
11 |
12 |
--------------------------------------------------------------------------------
/Script/gdong.js:
--------------------------------------------------------------------------------
1 | /*
2 | 脚本名称:G动签到脚本
3 | 下载地址:https://apps.apple.com/cn/app/g%E5%8A%A8-%E5%87%AF%E6%A0%BC%E5%B0%94%E8%BF%90%E5%8A%A8%E9%94%BB%E7%82%BC%E8%BD%AF%E4%BB%B6/id1096015822
4 | 脚本说明:本脚本仅适用于G动每日签到,仅测试QuantumultX
5 | 环境变量:gdCookie、gd_accessToken
6 | 脚本作者:WowYiJiu
7 | 更新时间:2024-2-16
8 | 脚本来源:https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/gdong.js
9 | ====================================================================================================
10 | 获取Cookie和access_token说明:
11 | 进入G动app,点击底部锻炼和我的两个按钮,看到系统消息提示'获取Cookie成功'和'获取access_token成功'即可
12 | 获取Cookie后, 请将Cookie脚本禁用并移除主机名,以免产生不必要的MITM.
13 |
14 | 配置 (QuanX)
15 | [MITM]
16 | hostname = gdongapi.wo-ish.com
17 |
18 | [rewrite_local]
19 | ^https:\/\/gdongapi\.wo-ish\.com\/user\/getUInfo url script-request-header https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/gdong.js
20 | ^https:\/\/gdongapi\.wo-ish\.com\/MsgBoard\/ShupUpV5 url script-request-body https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/gdong.js
21 |
22 | [task_local]
23 | 10 7 * * * https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/gdong.js, tag=G动, img-url=https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/gdong.png, enabled=true
24 | ====================================================================================================
25 | */
26 | const $ = new Env('G动');
27 |
28 | let gdCookie = $.getdata('gdCookie');
29 | let gd_accessToken = $.getdata('gd_accessToken');
30 |
31 | let checkInMsg = '', message = '';
32 | let isCheck = false, isComment = false;
33 |
34 | if (isGetCookie = typeof $request !== `undefined`) {
35 | getCookie();
36 | $.done();
37 | } else {
38 | !(async () => {
39 | if (gdCookie && gd_accessToken) {
40 | console.log('===== 开始【G动任务】 =====');
41 | await getSignState();
42 | if(!isCheck){
43 | await checkIn();
44 | } else{
45 | $.log(`每日签到已完成,跳过签到`);
46 | checkInMsg = `每日签到已完成,跳过签到`;
47 | }
48 | if(!isComment){
49 | await comment();
50 | } else{
51 | $.log(`社区评论已完成,跳过评论`);
52 | message = `社区评论已完成,跳过评论`;
53 | }
54 | await showMsg();
55 | } else {
56 | $.msg($.name, '【提示】请先获取G动Cookie和access_token', '');
57 | }
58 | })()
59 | .catch((e) => $.logErr(e))
60 | .finally(() => $.done())
61 | }
62 |
63 | // G动每日签到
64 | function checkIn() {
65 | return new Promise((resolve, reject) => {
66 | let opt = {
67 | url: 'https://gdongapi.wo-ish.com/Sign/SignV52',
68 | headers: {
69 | 'Content-Type': 'application/x-www-form-urlencoded',
70 | 'Cookie': gdCookie
71 | },
72 | body: $.queryStr({
73 | 'access_token' : gd_accessToken
74 | })
75 | }
76 | $.post(opt, async (error, resp, data) => {
77 | try {
78 | var obj = JSON.parse(data);
79 | if (obj.errcode === 0) {
80 | $.log(`签到成功`);
81 | checkInMsg = `签到成功`;
82 | } else {
83 | $.log(`签到失败:未知错误请查看日志或手动签到!!!\n${obj}`);
84 | checkInMsg = `签到失败:未知错误请查看日志或手动签到!!!\n${obj}`;
85 | }
86 | } catch (e) {
87 | $.logErr(e);
88 | } finally {
89 | resolve();
90 | }
91 | }
92 | )
93 | })
94 | }
95 |
96 | // G动社区评论,本请求为评论我的一篇文章
97 | function comment() {
98 | return new Promise((resolve, reject) => {
99 | let opt = {
100 | url: 'https://gdongapi.wo-ish.com/MsgBoard/CommentTopicV41',
101 | headers: {
102 | 'Content-Type': 'application/x-www-form-urlencoded',
103 | 'Cookie': gdCookie
104 | },
105 | body: $.queryStr({
106 | 'ReplayContext': '%E5%8A%A0%E6%B2%B9%E5%8A%A0%E6%B2%B9%E5%8A%A0%E6%B2%B9',
107 | 'TopicId': '2876047',
108 | 'access_token': gd_accessToken
109 | })
110 | }
111 | $.post(opt, async (error, resp, data) => {
112 | try {
113 | var obj = JSON.parse(data);
114 | if (obj.errcode === 0) {
115 | $.log(`评论成功`);
116 | message = `评论成功`;
117 | } else {
118 | $.log(`评论失败:未知错误请查看日志或手动评论!!!\n${obj}`);
119 | message = `评论失败:未知错误请查看日志或手动评论!!!\n${obj}`;
120 | }
121 | } catch (e) {
122 | $.logErr(e);
123 | } finally {
124 | resolve();
125 | }
126 | }
127 | )
128 | })
129 | }
130 |
131 | function getSignState() {
132 | return new Promise((resolve, reject) => {
133 | let opt = {
134 | url: 'https://gdongapi.wo-ish.com/Sign/SignStateV51',
135 | headers: {
136 | 'Content-Type': 'application/x-www-form-urlencoded',
137 | 'Cookie': gdCookie
138 | },
139 | body: $.queryStr({
140 | 'access_token' : gd_accessToken
141 | })
142 | }
143 | $.post(opt, async (error, resp, data) => {
144 | try {
145 | var obj = JSON.parse(data);
146 | if (obj.errcode === 0) {
147 | var taskList = obj.data.otherGetMethon;
148 | if(taskList[0].isFinish == 1){
149 | isCheck = true;
150 | }
151 | if(taskList[1].isFinish == 1){
152 | isComment = true;
153 | }
154 | } else {
155 | $.log(`查询失败:未知错误请查看日志!!!\n${obj}`);
156 | checkInMsg = `查询失败:未知错误请查看日志!!!\n${obj}`;
157 | }
158 | } catch (e) {
159 | $.logErr(e);
160 | } finally {
161 | resolve();
162 | }
163 | }
164 | )
165 | })
166 | }
167 |
168 | function getCookie() {
169 | if($request&&$request.method!=`OPTIONS`&&$request.url.match(/\/user\/getUInfo/)) {
170 | const cookie = $request.headers['Cookie'] || $request.headers['cookie'];
171 | if (cookie) {
172 | if (typeof gdCookie === 'undefined' || (gdCookie && gdCookie.length === 0)){
173 | $.setdata(cookie, 'gdCookie');
174 | $.log(`Cookie: ${cookie}`);
175 | $.msg($.name, '🎉 Cookie写入成功', '');
176 | } else if(cookie != gdCookie){
177 | $.setdata(cookie, 'gdCookie');
178 | $.log(`Cookie: ${cookie}`);
179 | $.msg($.name, '🎉 Cookie更新成功', '');
180 | } else {
181 | $.msg($.name, '⚠️ Cookie未变动 跳过更新', '');
182 | }
183 | } else {
184 | $.msg($.name, '⚠️ Cookie未找到', '');
185 | }
186 | }
187 | if($request&&$request.method!=`OPTIONS`&&$request.url.match(/\/MsgBoard\/ShupUpV5/)) {
188 | const gdBody = new URLSearchParams($request.body);
189 | let acc_token = '';
190 | if(gdBody.has('access_token')){
191 | acc_token = gdBody.get('access_token');
192 | if (typeof gd_accessToken === 'undefined' || (gd_accessToken && gd_accessToken.length === 0)){
193 | $.setdata(acc_token, 'gd_accessToken');
194 | $.log(`gd_accessToken: ${acc_token}`);
195 | $.msg($.name, '🎉 access_token写入成功', '');
196 | } else if(acc_token != gd_accessToken){
197 | $.setdata(acc_token, 'gd_accessToken');
198 | $.log(`gd_accessToken: ${acc_token}`);
199 | $.msg($.name, '🎉 access_token更新成功', '');
200 | } else {
201 | $.msg($.name, '⚠️ access_token未变动 跳过更新', '');
202 | }
203 | } else {
204 | $.msg($.name, '⚠️ access_token未找到', '');
205 | }
206 | }
207 | }
208 |
209 | async function showMsg() {
210 | $.msg($.name, checkInMsg, message);
211 | }
212 |
213 | // prettier-ignore
214 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,a)=>{s.call(this,t,(t,s,r)=>{t?a(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const a=this.getdata(t);if(a)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,a)=>e(a))})}runScript(t,e){return new Promise(s=>{let a=this.getdata("@chavy_boxjs_userCfgs.httpapi");a=a?a.replace(/\n/g,"").trim():a;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[i,o]=a.split("@"),n={url:`http://${o}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":i,Accept:"*/*"},timeout:r};this.post(n,(t,e,a)=>s(a))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e);if(!s&&!a)return{};{const a=s?t:e;try{return JSON.parse(this.fs.readFileSync(a))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):a?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const a=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of a)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,a)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[a+1])>>0==+e[a+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,a]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,a,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,a,r]=/^@(.*?)\.(.*?)$/.exec(e),i=this.getval(a),o=a?"null"===i?null:i||"{}":"{}";try{const e=JSON.parse(o);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),a)}catch(e){const i={};this.lodash_set(i,r,t),s=this.setval(JSON.stringify(i),a)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),t.params&&(t.url+="?"+this.queryStr(t.params)),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:a,statusCode:r,headers:i,rawBody:o}=t,n=s.decode(o,this.encoding);e(null,{status:a,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:a,response:r}=t;e(a,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let a=require("iconv-lite");this.initGotEnv(t);const{url:r,...i}=t;this.got[s](r,i).then(t=>{const{statusCode:s,statusCode:r,headers:i,rawBody:o}=t,n=a.decode(o,this.encoding);e(null,{status:s,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:s,response:r}=t;e(s,r,r&&a.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let a={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in a)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[e]:("00"+a[e]).substr((""+a[e]).length)));return t}queryStr(t){let e="";for(const s in t){let a=t[s];null!=a&&""!==a&&("object"==typeof a&&(a=JSON.stringify(a)),e+=`${s}=${a}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",a="",r){const i=t=>{switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{let e=t.url||t.openUrl||t["open-url"];return{url:e}}case"Loon":{let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}case"Quantumult X":{let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,a=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":a}}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,a,i(r));break;case"Quantumult X":$notify(e,s,a,i(r));break;case"Node.js":}if(!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),a&&t.push(a),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,t);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,t.stack)}}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)}
--------------------------------------------------------------------------------
/Script/iQiYi.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # -- coding: utf-8 --
3 | # -------------------------------
4 | # @Author : github@limoruirui https://github.com/limoruirui
5 | # @Modifier : github@WowYiJiu https://github.com/WowYiJiu
6 | # @Update : 2024/6/12
7 | # @env : iqyck
8 | # -------------------------------
9 | """
10 | cookie为爱奇艺整个cookie
11 | export iqyck = "cookie"
12 | """
13 | from datetime import datetime
14 | from hashlib import md5 as md5Encode
15 | from json import dumps
16 | from time import sleep, time
17 | from os import environ, system, path
18 | from random import randint, choice
19 | from re import findall
20 | from string import digits, ascii_lowercase, ascii_uppercase
21 | from sys import exit, stdout
22 | from uuid import uuid4
23 |
24 | def load_send():
25 | cur_path = path.abspath(path.dirname(__file__))
26 | if path.exists(cur_path + "/notify.py"):
27 | try:
28 | from notify import send
29 | return send
30 | except ImportError:
31 | return False
32 | else:
33 | return False
34 |
35 | try:
36 | from requests import Session, get, post
37 | from fake_useragent import UserAgent
38 | except:
39 | print(
40 | "你还没有安装requests库和fake_useragent库 正在尝试自动安装 请在安装结束后重新执行此脚本\n若还是提示本条消息 请自行运行pip3 install requests和pip3 install fake-useragent或者在青龙的依赖管理里安装python的requests和fake-useragent")
41 | system("pip3 install fake-useragent")
42 | system("pip3 install requests")
43 | print("安装完成 脚本退出 请重新执行")
44 | exit(0)
45 | iqyck = environ.get("iqyck") if environ.get("iqyck") else ""
46 | P00001 = P00003 = dfp = qyid = ""
47 | if iqyck == "":
48 | print("未找到iqy_ck,请填写iqy_ck变量")
49 | exit(0)
50 |
51 | check_items = ["P00001", "P00003", "QC005", "__dfp"]
52 |
53 | for item in check_items:
54 | try:
55 | found = findall(rf"{item}=(.*?)(;|$)", iqyck)
56 |
57 | if found:
58 | value = found[0][0]
59 |
60 | if item == "P00001":
61 | P00001 = value
62 | elif item == "P00003":
63 | P00003 = value
64 | elif item == "QC005":
65 | qyid = value
66 | elif item == "__dfp":
67 | dfp = value
68 | dfp = dfp.split("@")[0]
69 | else:
70 | print(f"{item}未在iqyck中找到")
71 | except IndexError:
72 | print(f"{item}存在但无法被正确解析")
73 |
74 | class IQiYi:
75 | name = "爱奇艺"
76 | def __init__(self):
77 | self.P00001 = P00001
78 | self.userId = P00003
79 | self.dfp = dfp
80 | self.qyid = qyid
81 | self.platform = str(uuid4())[:16],
82 | self.session = Session()
83 | self.user_agent = UserAgent().chrome
84 | self.headers = {
85 | "User-Agent": self.user_agent,
86 | "Cookie": f"P00001={self.P00001}",
87 | 'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
88 | 'sec-fetch-site': "none",
89 | 'sec-fetch-dest': "document",
90 | 'accept-language': "zh-CN,zh-Hans;q=0.9",
91 | 'sec-fetch-mode': "navigate"
92 | }
93 | self.msg = ""
94 | self.user_info = ""
95 | self.task_info = ""
96 | self.msg = ""
97 | self.taskList = []
98 | self.lotteryList = []
99 | self.shakeLotteryList = []
100 | self.gift_list = []
101 | self.sleep_await = environ.get("sleep_await") if environ.get("sleep_await") else 1
102 |
103 | """工具"""
104 | def req(self, url, req_method="GET", body=None):
105 | data = {}
106 | method = req_method.upper()
107 | if method not in ["GET", "POST", "OTHER"]:
108 | self.print_now(f"错误:不支持的请求方法:{method}")
109 | return
110 |
111 | try:
112 | if method == "GET":
113 | response = self.session.get(url, headers=self.headers, params=body)
114 | elif method == "POST":
115 | response = self.session.post(url, headers=self.headers, data=dumps(body))
116 | elif method == "OTHER":
117 | response = self.session.get(url, headers=self.headers, params=dumps(body))
118 |
119 | if method in ["GET", "POST"]:
120 | data = response.json()
121 |
122 | except requests.exceptions.RequestException as e:
123 | self.print_now(f"请求发送失败,可能为网络异常,异常详细信息:{str(e)}")
124 |
125 | return data
126 |
127 | def timestamp(self, short=False):
128 | if (short):
129 | return int(time())
130 | return int(time() * 1000)
131 |
132 | def md5(self, str):
133 | m = md5Encode(str.encode(encoding='utf-8'))
134 | return m.hexdigest()
135 |
136 | def uuid(self, num, upper=False):
137 | str = ''
138 | if upper:
139 | for i in range(num):
140 | str += choice(digits + ascii_lowercase + ascii_uppercase)
141 | else:
142 | for i in range(num):
143 | str += choice(digits + ascii_lowercase)
144 | return str
145 |
146 | def print_now(self, content):
147 | print(content)
148 | stdout.flush()
149 |
150 | def sign(self):
151 | # lequ-qfe.iqiyi.com
152 | time_stamp = self.timestamp()
153 | data = f'agenttype=20|agentversion=15.5.5|appKey=lequ_rn|appver=15.5.5|authCookie={self.P00001}|qyid={self.qyid}|srcplatform=20|task_code=natural_month_sign|timestamp={time_stamp}|userId={self.userId}|cRcFakm9KSPSjFEufg3W'
154 | url = f'https://community.iqiyi.com/openApi/task/execute?task_code=natural_month_sign×tamp={time_stamp}&appKey=lequ_rn&userId={self.userId}&authCookie={self.P00001}&agenttype=20&agentversion=15.5.5&srcplatform=20&appver=15.5.5&qyid={self.qyid}&sign={self.md5(data)}'
155 | headers = {
156 | 'Content-Type': 'application/json'
157 | }
158 | body = {
159 | "natural_month_sign": {
160 | "verticalCode": "iQIYI",
161 | "agentVersion": "15.4.6",
162 | "authCookie": self.P00001,
163 | "taskCode": "iQIYI_mofhr",
164 | "dfp": self.dfp,
165 | "qyid": self.qyid,
166 | "agentType": 20,
167 | "signFrom": 1
168 | }
169 | }
170 | data = post(url, headers=headers, data=dumps(body)).json()
171 | signDays = None
172 | if 'code' in data and data['code'] == 'A0003':
173 | self.print_now("iqyck已失效,请重新获取")
174 | exit(0)
175 | elif 'code' in data and data['code'] == 'A00000':
176 | data_data = data.get('data', {})
177 | msg = data_data.get('msg')
178 |
179 | if data_data.get('data'):
180 | signDays = data_data.get('data', {}).get('signDays')
181 | if msg and '已经到达上限' in msg:
182 | self.print_now(f"签到失败,今天已签到")
183 | self.task_info += f"签到失败,今天已签到\n"
184 | elif signDays is not None:
185 | self.print_now(f"签到成功, 本月累计签到{signDays}天")
186 | self.task_info += f"签到成功, 本月累计签到{signDays}天\n"
187 |
188 | if data_data['code'] != 'A0000' and data_data['code'] != 'A0014' and not (data_data.get('success')):
189 | self.print_now(f"签到失败:{msg}")
190 | self.task_info += f"签到失败:{msg}\n"
191 | else:
192 | self.print_now(f"签到失败:{data}")
193 | self.task_info += f"签到失败:{data}\n"
194 |
195 | def get_watch_time(self):
196 | url = "https://tc.vip.iqiyi.com/growthAgency/watch-film-duration"
197 | data = self.req(url)
198 | watch_time = data['data']['viewtime']['time']
199 | return watch_time
200 |
201 | def watchVideo(self):
202 | totalTime = self.get_watch_time()
203 | if totalTime >= 7200:
204 | self.print_now(f"您的账号今日观影时长大于2小时,不执行刷观影时长")
205 | self.task_info += f"今日观影任务已完成\n"
206 | return
207 | self.print_now("正在刷观影时长,为减少风控,本过程运行大概1个小时")
208 | for i in range(1, 121):
209 | Time = randint(70, 90)
210 | url = f"https://msg.qy.net/b?u=f600a23f03c26507f5482e6828cfc6c5&pu={self.userId}&p1=1_10_101&v=5.2.66&ce={self.uuid(32)}&de=1616773143.1639632721.1639653680.29&c1=2&ve={self.uuid(32)}&ht=0&pt={randint(1000000000, 9999999999) / 1000000}&isdm=0&duby=0&ra=5&clt=&ps2=DIRECT&ps3=&ps4=&br=mozilla%2F5.0%20(windows%20nt%2010.0%3B%20win64%3B%20x64)%20applewebkit%2F537.36%20(khtml%2C%20like%20gecko)%20chrome%2F96.0.4664.110%20safari%2F537.36&mod=cn_s&purl=https%3A%2F%2Fwww.iqiyi.com%2Fv_1eldg8u3r08.html%3Fvfrm%3Dpcw_home%26vfrmblk%3D712211_cainizaizhui%26vfrmrst%3D712211_cainizaizhui_image1%26r_area%3Drec_you_like%26r_source%3D62%2540128%26bkt%3DMBA_PW_T3_53%26e%3Db3ec4e6c74812510c7719f7ecc8fbb0f%26stype%3D2&tmplt=2&ptid=01010031010000000000&os=window&nu=0&vfm=&coop=&ispre=0&videotp=0&drm=&plyrv=&rfr=https%3A%2F%2Fwww.iqiyi.com%2F&fatherid={randint(1000000000000000, 9999999999999999)}&stauto=1&algot=abr_v12-rl&vvfrom=&vfrmtp=1&pagev=playpage_adv_xb&engt=2&ldt=1&krv=1.1.85&wtmk=0&duration={randint(1000000, 9999999)}&bkt=&e=&stype=&r_area=&r_source=&s4={randint(100000, 999999)}_dianshiju_tbrb_image2&abtest=1707_B%2C1550_B&s3={randint(100000, 999999)}_dianshiju_tbrb&vbr={randint(100000, 999999)}&mft=0&ra1=2&wint=3&s2=pcw_home&bw=10&ntwk=18&dl={randint(10, 999)}.27999999999997&rn=0.{randint(1000000000000000, 9999999999999999)}&dfp={dfp}&stime={self.timestamp()}&r={randint(1000000000000000, 9999999999999999)}&hu=1&t=2&tm={Time}&_={self.timestamp()}"
211 | self.req(url, 'other')
212 | totalTime += Time
213 | sleep(randint(30, 50))
214 | if i % 30 == 0:
215 | self.print_now(f"现在已经刷到了{totalTime}秒, 数据同步有延迟, 仅供参考")
216 | if totalTime >= 7200:
217 | sleep(60)
218 | self.print_now(f"今日观影任务已完成")
219 | self.task_info += f"今日观影任务已完成\n"
220 | break
221 |
222 | def dailyTask(self):
223 | # 查询任务
224 | """
225 | status: 0 已完成,未领奖 1 已完成,已领奖 2 未完成
226 | """
227 | url = f'https://tc.vip.iqiyi.com/taskCenter/task/queryUserTask?P00001={self.P00001}'
228 | data = self.req(url)
229 | if data['code'] == 'A00000':
230 | for item in data["data"].get("tasks", {}).get("daily", []):
231 | if item["taskCode"] != "WatchVideo60mins" and item["status"] != 1:
232 | self.taskList.append(
233 | {
234 | "taskTitle": item["taskTitle"],
235 | "taskCode": item["taskCode"],
236 | "status": item["status"]
237 | }
238 | )
239 | if self.taskList:
240 | for item in self.taskList:
241 | if item["status"] == 2:
242 | # 领任务
243 | url = f'https://tc.vip.iqiyi.com/taskCenter/task/joinTask?P00001={self.P00001}&taskCode={item["taskCode"]}&platform={self.platform}&lang=zh_CN&app_lm=cn'
244 | if self.req(url)['code'] == 'A00000':
245 | sleep(10)
246 | # 完成任务
247 | url = f'https://tc.vip.iqiyi.com/taskCenter/task/notify?taskCode={item["taskCode"]}&P00001={self.P00001}&platform={self.platform}&lang=cn&bizSource=component_browse_timing_tasks&_={self.timestamp()}'
248 | if self.req(url)['code'] == 'A00000':
249 | sleep(2)
250 | if item["status"] == 2 or item["status"] == 0:
251 | # 领取奖励
252 | url = f"https://tc.vip.iqiyi.com/taskCenter/task/getTaskRewards?P00001={self.P00001}&taskCode={item['taskCode']}&lang=zh_CN&platform={self.platform}"
253 | data = self.req(url)
254 | if data['code'] == 'A00000':
255 | price = data['dataNew'][0]["value"]
256 | self.print_now(f"{item['taskTitle']}任务已完成, 获得{int(price[1:])}点成长值")
257 | self.task_info += f"{item['taskTitle']}任务已完成, 获得{int(price[1:])}点成长值\n"
258 | sleep(5)
259 | else:
260 | self.print_now("今日日常浏览任务已全部完成")
261 | self.task_info += "今日日常浏览任务已全部完成\n"
262 |
263 | def lottery(self):
264 | url = "https://iface2.iqiyi.com/aggregate/3.0/lottery_activity"
265 | lottery_params = {
266 | "app_k": 0,
267 | "app_v": 0,
268 | "platform_id": 10,
269 | "dev_os": 0,
270 | "dev_ua": 0,
271 | "net_sts": 0,
272 | "qyid": self.qyid,
273 | "psp_uid": self.userId,
274 | "psp_cki": self.P00001,
275 | "psp_status": 3,
276 | "secure_v": 1,
277 | "secure_p": 0,
278 | "req_sn": self.timestamp()
279 | }
280 | params = lottery_params
281 | data = self.req(url, "get", params)
282 | if data.get("code") == 0:
283 | daysurpluschance = int(data.get("daysurpluschance"))
284 | if daysurpluschance == 0:
285 | if self.lotteryList:
286 | self.print_now(f"抽奖奖品:{'、'.join(self.lotteryList)}")
287 | self.task_info += f"抽奖奖品:{'、'.join(self.lotteryList)}\n"
288 | else:
289 | self.print_now(f"抽奖次数已用完, 明日再来吧")
290 | self.task_info += f"抽奖次数已用完, 明日再来吧\n"
291 | else:
292 | award_info = data.get("awardName")
293 | self.lotteryList.append(award_info)
294 | sleep(2)
295 | self.lottery()
296 | else:
297 | self.print_now(f"抽奖接口请求失败:{data}\n")
298 |
299 | def shake_lottery(self):
300 | url = f'https://act.vip.iqiyi.com/shake-api/lottery?P00001={self.P00001}&dfp={self.dfp}&qyid={self.qyid}&deviceID={self.qyid}&version=15.4.6&agentType=12&platform=bb35a104d95490f6&ptid=02030031010000000000&fv=afc0b50ed49e732d&source=afc0b50ed49e732d&_={self.timestamp()}&vipType=1&lotteryType=0&actCode=0k9GkUcjqqj4tne8&freeLotteryNum=3&extendParams={{"appIds":"iqiyi_pt_vip_iphone_video_autorenew_12m_348yuan_v2","supportSk2Identity":true,"testMode":"0","iosSystemVersion":"17.4.1","bundleId":"com.qiyi.iphone"}}'
301 | data = self.req(url)
302 | if data.get("code") == 'A00000':
303 | award_info = data.get("data", {}).get("title")
304 | self.shakeLotteryList.append(award_info)
305 | sleep(2)
306 | self.shake_lottery()
307 | elif data.get("msg") == "抽奖次数用完":
308 | if self.shakeLotteryList:
309 | self.print_now(f"每天摇一摇奖品:{'、'.join(self.shakeLotteryList)}")
310 | self.task_info += f"每天摇一摇奖品:{'、'.join(self.shakeLotteryList)}\n"
311 | else:
312 | self.print_now(f"每天摇一摇次数已用完, 明日再来吧")
313 | self.task_info += f"每天摇一摇次数已用完, 明日再来吧\n"
314 | else:
315 | self.print_now(f'每天摇一摇:{data.get("msg")}\n')
316 |
317 | def giveTimes(self):
318 | times_code_list = ["browseWeb", "browseWeb", "bookingMovie"]
319 | for times_code in times_code_list:
320 | url = f"https://pcell.iqiyi.com/lotto/giveTimes?dfp&qyid={self.qyid}&version&deviceId={self.qyid}&_cctimer={self.timestamp()}&actCode=bcf9d354bc9f677c×Code={times_code}&P00001={self.P00001}"
321 | data = self.req(url)
322 |
323 | def queryTimes(self):
324 | url = f"https://pcell.iqiyi.com/lotto/queryTimes?dfp&qyid={self.qyid}&version&deviceId={self.qyid}&_cctimer={self.timestamp()}&actCode=bcf9d354bc9f677c&P00001={self.P00001}"
325 | data = self.req(url)
326 | if data.get("code") == 'A00000':
327 | times = data["data"]["times"]
328 | return times
329 |
330 | def lotto_lottery(self):
331 | self.giveTimes()
332 | times = self.queryTimes()
333 | if times == 0:
334 | self.print_now(f"白金抽奖次数已用完, 明日再来吧")
335 | self.task_info += f"白金抽奖次数已用完, 明日再来吧"
336 | for _ in range(times):
337 | url = f"https://pcell.iqiyi.com/lotto/lottery?dfp&qyid={self.qyid}&version&deviceId={self.qyid}&_cctimer={self.timestamp()}&actCode=bcf9d354bc9f677c&P00001={self.P00001}"
338 | data = self.req(url)
339 | gift_name = data["data"]["giftName"]
340 | if gift_name and "未中奖" not in gift_name:
341 | self.gift_list.append(gift_name)
342 | if self.gift_list:
343 | self.print_now(f"白金抽奖奖品:{'、'.join(self.gift_list)}")
344 | self.task_info += f"白金抽奖奖品:{'、'.join(self.gift_list)}"
345 | elif times != 0:
346 | self.print_now(f"很遗憾,白金抽奖未中奖")
347 | self.task_info += f"很遗憾,白金抽奖未中奖"
348 |
349 | def get_userinfo(self):
350 | url = f"https://tc.vip.iqiyi.com/growthAgency/v2/growth-aggregation?messageId=b7d48dbba64c4fd0f9f257dc89de8e25&platform=97ae2982356f69d8&P00001={self.P00001}&responseNodes=duration,growth,upgrade,viewTime,growthAnnualCard&_={self.timestamp()}"
351 | data = self.req(url)
352 | growth_info = data['data']['growth']
353 | if data.get("code") == 'A00000':
354 | self.user_info += f"用户昵称:{ data['data']['user']['nickname']}\nVIP等级:{growth_info['level']}\nVIP到期时间:{growth_info['deadline']}\n今日成长:{growth_info['todayGrowthValue']}\n当前成长:{growth_info['growthvalue']}\n升级还需:{growth_info['distance']}\n"
355 | else:
356 | self.user_info = f"查询失败,未获取到用户信息\n"
357 |
358 | def main(self):
359 | self.sign()
360 | self.watchVideo()
361 | self.dailyTask()
362 | self.lottery()
363 | self.shake_lottery()
364 | self.lotto_lottery()
365 | self.print_now(f"任务已经执行完成,因爱奇艺观影时间同步较慢,这里等待1分钟再查询今日成长值信息\n若不需要等待直接查询,请设置环境变量名 sleep_await = 0")
366 | if int(self.sleep_await) == 1:
367 | sleep(60)
368 | self.get_userinfo()
369 | self.msg = self.user_info + self.task_info
370 | send = load_send()
371 | if callable(send):
372 | send("爱奇艺", self.msg)
373 | else:
374 | print('\n加载通知服务失败')
375 |
376 | if __name__ == '__main__':
377 | iqiyi = IQiYi()
378 | iqiyi.main()
--------------------------------------------------------------------------------
/Script/notify.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # _*_ coding:utf-8 _*_
3 | # -------------------------------
4 | # @Modifier : github@WowYiJiu https://github.com/WowYiJiu
5 | # @desp : 脚本CK失效使用Bark推送,正常则使用telegram_bot推送
6 | # @Update : 2024-6-9
7 | # -------------------------------
8 | import base64
9 | import hashlib
10 | import hmac
11 | import json
12 | import os
13 | import re
14 | import threading
15 | import time
16 | import urllib.parse
17 | import smtplib
18 | from email.mime.text import MIMEText
19 | from email.header import Header
20 | from email.utils import formataddr
21 |
22 | import requests
23 |
24 | # 原先的 print 函数和主线程的锁
25 | _print = print
26 | mutex = threading.Lock()
27 |
28 | # 定义新的 print 函数
29 | def print(text, *args, **kw):
30 | """
31 | 使输出有序进行,不出现多线程同一时间输出导致错乱的问题。
32 | """
33 | with mutex:
34 | _print(text, *args, **kw)
35 |
36 | # 通知服务
37 | # fmt: off
38 | push_config = {
39 | 'HITOKOTO': True, # 启用一言(随机句子)
40 |
41 | 'BARK_PUSH': '', # bark IP 或设备码,例:https://api.day.app/DxHcxxxxxRxxxxxxcm/
42 | 'BARK_ARCHIVE': '', # bark 推送是否存档
43 | 'BARK_GROUP': '', # bark 推送分组
44 | 'BARK_SOUND': '', # bark 推送声音
45 | 'BARK_ICON': '', # bark 推送图标
46 | 'BARK_LEVEL': '', # bark 推送时效性
47 | 'BARK_URL': '', # bark 推送跳转URL
48 |
49 | 'CONSOLE': False, # 控制台输出
50 |
51 | 'DD_BOT_SECRET': '', # 钉钉机器人的 DD_BOT_SECRET
52 | 'DD_BOT_TOKEN': '', # 钉钉机器人的 DD_BOT_TOKEN
53 |
54 | 'FSKEY': '', # 飞书机器人的 FSKEY
55 |
56 | 'GOBOT_URL': '', # go-cqhttp
57 | # 推送到个人QQ:http://127.0.0.1/send_private_msg
58 | # 群:http://127.0.0.1/send_group_msg
59 | 'GOBOT_QQ': '', # go-cqhttp 的推送群或用户
60 | # GOBOT_URL 设置 /send_private_msg 时填入 user_id=个人QQ
61 | # /send_group_msg 时填入 group_id=QQ群
62 | 'GOBOT_TOKEN': '', # go-cqhttp 的 access_token
63 |
64 | 'GOTIFY_URL': '', # gotify地址,如https://push.example.de:8080
65 | 'GOTIFY_TOKEN': '', # gotify的消息应用token
66 | 'GOTIFY_PRIORITY': 0, # 推送消息优先级,默认为0
67 |
68 | 'IGOT_PUSH_KEY': '', # iGot 聚合推送的 IGOT_PUSH_KEY
69 |
70 | 'PUSH_KEY': '', # server 酱的 PUSH_KEY,兼容旧版与 Turbo 版
71 |
72 | 'DEER_KEY': '', # PushDeer 的 PUSHDEER_KEY
73 | 'DEER_URL': '', # PushDeer 的 PUSHDEER_URL
74 |
75 | 'CHAT_URL': '', # synology chat url
76 | 'CHAT_TOKEN': '', # synology chat token
77 |
78 | 'PUSH_PLUS_TOKEN': '', # push+ 微信推送的用户令牌
79 | 'PUSH_PLUS_USER': '', # push+ 微信推送的群组编码
80 |
81 | 'WE_PLUS_BOT_TOKEN': '', # 微加机器人的用户令牌
82 | 'WE_PLUS_BOT_RECEIVER': '', # 微加机器人的消息接收者
83 | 'WE_PLUS_BOT_VERSION': 'pro', # 微加机器人的调用版本
84 |
85 | 'QMSG_KEY': '', # qmsg 酱的 QMSG_KEY
86 | 'QMSG_TYPE': '', # qmsg 酱的 QMSG_TYPE
87 |
88 | 'QYWX_ORIGIN': '', # 企业微信代理地址
89 |
90 | 'QYWX_AM': '', # 企业微信应用
91 |
92 | 'QYWX_KEY': '', # 企业微信机器人
93 |
94 | 'TG_BOT_TOKEN': '', # tg 机器人的 TG_BOT_TOKEN,例:1407203283:AAG9rt-6RDaaX0HBLZQq0laNOh898iFYaRQ
95 | 'TG_USER_ID': '', # tg 机器人的 TG_USER_ID,例:1434078534
96 | 'TG_API_HOST': '', # tg 代理 api
97 | 'TG_PROXY_AUTH': '', # tg 代理认证参数
98 | 'TG_PROXY_HOST': '', # tg 机器人的 TG_PROXY_HOST
99 | 'TG_PROXY_PORT': '', # tg 机器人的 TG_PROXY_PORT
100 |
101 | 'AIBOTK_KEY': '', # 智能微秘书 个人中心的apikey 文档地址:http://wechat.aibotk.com/docs/about
102 | 'AIBOTK_TYPE': '', # 智能微秘书 发送目标 room 或 contact
103 | 'AIBOTK_NAME': '', # 智能微秘书 发送群名 或者好友昵称和type要对应好
104 |
105 | 'SMTP_SERVER': '', # SMTP 发送邮件服务器,形如 smtp.exmail.qq.com:465
106 | 'SMTP_SSL': 'false', # SMTP 发送邮件服务器是否使用 SSL,填写 true 或 false
107 | 'SMTP_EMAIL': '', # SMTP 收发件邮箱,通知将会由自己发给自己
108 | 'SMTP_PASSWORD': '', # SMTP 登录密码,也可能为特殊口令,视具体邮件服务商说明而定
109 | 'SMTP_NAME': '', # SMTP 收发件人姓名,可随意填写
110 |
111 | 'PUSHME_KEY': '', # PushMe 的 PUSHME_KEY
112 | 'PUSHME_URL': '', # PushMe 的 PUSHME_URL
113 |
114 | 'CHRONOCAT_QQ': '', # qq号
115 | 'CHRONOCAT_TOKEN': '', # CHRONOCAT 的token
116 | 'CHRONOCAT_URL': '', # CHRONOCAT的url地址
117 |
118 | 'WEBHOOK_URL': '', # 自定义通知 请求地址
119 | 'WEBHOOK_BODY': '', # 自定义通知 请求体
120 | 'WEBHOOK_HEADERS': '', # 自定义通知 请求头
121 | 'WEBHOOK_METHOD': '', # 自定义通知 请求方法
122 | 'WEBHOOK_CONTENT_TYPE': '' # 自定义通知 content-type
123 | }
124 | # fmt: on
125 |
126 | # 首先读取 面板变量 或者 github action 运行变量
127 | for k in push_config:
128 | if os.getenv(k):
129 | v = os.getenv(k)
130 | push_config[k] = v
131 |
132 |
133 | def bark(title: str, content: str) -> None:
134 | """
135 | 使用 bark 推送消息。
136 | """
137 | if not push_config.get("BARK_PUSH"):
138 | print("bark 服务的 BARK_PUSH 未设置!!\n取消推送")
139 | return
140 | print("bark 服务启动")
141 |
142 | if push_config.get("BARK_PUSH").startswith("http"):
143 | url = f'{push_config.get("BARK_PUSH")}'
144 | else:
145 | url = f'https://api.day.app/{push_config.get("BARK_PUSH")}'
146 |
147 | bark_params = {
148 | "BARK_ARCHIVE": "isArchive",
149 | "BARK_GROUP": "group",
150 | "BARK_SOUND": "sound",
151 | "BARK_ICON": "icon",
152 | "BARK_LEVEL": "level",
153 | "BARK_URL": "url",
154 | }
155 | data = {
156 | "title": title,
157 | "body": content,
158 | }
159 | for pair in filter(
160 | lambda pairs: pairs[0].startswith("BARK_")
161 | and pairs[0] != "BARK_PUSH"
162 | and pairs[1]
163 | and bark_params.get(pairs[0]),
164 | push_config.items(),
165 | ):
166 | data[bark_params.get(pair[0])] = pair[1]
167 | headers = {"Content-Type": "application/json;charset=utf-8"}
168 | response = requests.post(
169 | url=url, data=json.dumps(data), headers=headers, timeout=15
170 | ).json()
171 |
172 | if response["code"] == 200:
173 | print("bark 推送成功!")
174 | else:
175 | print("bark 推送失败!")
176 |
177 |
178 | def console(title: str, content: str) -> None:
179 | """
180 | 使用 控制台 推送消息。
181 | """
182 | print(f"{title}\n\n{content}")
183 |
184 |
185 | def dingding_bot(title: str, content: str) -> None:
186 | """
187 | 使用 钉钉机器人 推送消息。
188 | """
189 | if not push_config.get("DD_BOT_SECRET") or not push_config.get("DD_BOT_TOKEN"):
190 | print("钉钉机器人 服务的 DD_BOT_SECRET 或者 DD_BOT_TOKEN 未设置!!\n取消推送")
191 | return
192 | print("钉钉机器人 服务启动")
193 |
194 | timestamp = str(round(time.time() * 1000))
195 | secret_enc = push_config.get("DD_BOT_SECRET").encode("utf-8")
196 | string_to_sign = "{}\n{}".format(timestamp, push_config.get("DD_BOT_SECRET"))
197 | string_to_sign_enc = string_to_sign.encode("utf-8")
198 | hmac_code = hmac.new(
199 | secret_enc, string_to_sign_enc, digestmod=hashlib.sha256
200 | ).digest()
201 | sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
202 | url = f'https://oapi.dingtalk.com/robot/send?access_token={push_config.get("DD_BOT_TOKEN")}×tamp={timestamp}&sign={sign}'
203 | headers = {"Content-Type": "application/json;charset=utf-8"}
204 | data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
205 | response = requests.post(
206 | url=url, data=json.dumps(data), headers=headers, timeout=15
207 | ).json()
208 |
209 | if not response["errcode"]:
210 | print("钉钉机器人 推送成功!")
211 | else:
212 | print("钉钉机器人 推送失败!")
213 |
214 |
215 | def feishu_bot(title: str, content: str) -> None:
216 | """
217 | 使用 飞书机器人 推送消息。
218 | """
219 | if not push_config.get("FSKEY"):
220 | print("飞书 服务的 FSKEY 未设置!!\n取消推送")
221 | return
222 | print("飞书 服务启动")
223 |
224 | url = f'https://open.feishu.cn/open-apis/bot/v2/hook/{push_config.get("FSKEY")}'
225 | data = {"msg_type": "text", "content": {"text": f"{title}\n\n{content}"}}
226 | response = requests.post(url, data=json.dumps(data)).json()
227 |
228 | if response.get("StatusCode") == 0 or response.get("code") == 0:
229 | print("飞书 推送成功!")
230 | else:
231 | print("飞书 推送失败!错误信息如下:\n", response)
232 |
233 |
234 | def go_cqhttp(title: str, content: str) -> None:
235 | """
236 | 使用 go_cqhttp 推送消息。
237 | """
238 | if not push_config.get("GOBOT_URL") or not push_config.get("GOBOT_QQ"):
239 | print("go-cqhttp 服务的 GOBOT_URL 或 GOBOT_QQ 未设置!!\n取消推送")
240 | return
241 | print("go-cqhttp 服务启动")
242 |
243 | url = f'{push_config.get("GOBOT_URL")}?access_token={push_config.get("GOBOT_TOKEN")}&{push_config.get("GOBOT_QQ")}&message=标题:{title}\n内容:{content}'
244 | response = requests.get(url).json()
245 |
246 | if response["status"] == "ok":
247 | print("go-cqhttp 推送成功!")
248 | else:
249 | print("go-cqhttp 推送失败!")
250 |
251 |
252 | def gotify(title: str, content: str) -> None:
253 | """
254 | 使用 gotify 推送消息。
255 | """
256 | if not push_config.get("GOTIFY_URL") or not push_config.get("GOTIFY_TOKEN"):
257 | print("gotify 服务的 GOTIFY_URL 或 GOTIFY_TOKEN 未设置!!\n取消推送")
258 | return
259 | print("gotify 服务启动")
260 |
261 | url = f'{push_config.get("GOTIFY_URL")}/message?token={push_config.get("GOTIFY_TOKEN")}'
262 | data = {
263 | "title": title,
264 | "message": content,
265 | "priority": push_config.get("GOTIFY_PRIORITY"),
266 | }
267 | response = requests.post(url, data=data).json()
268 |
269 | if response.get("id"):
270 | print("gotify 推送成功!")
271 | else:
272 | print("gotify 推送失败!")
273 |
274 |
275 | def iGot(title: str, content: str) -> None:
276 | """
277 | 使用 iGot 推送消息。
278 | """
279 | if not push_config.get("IGOT_PUSH_KEY"):
280 | print("iGot 服务的 IGOT_PUSH_KEY 未设置!!\n取消推送")
281 | return
282 | print("iGot 服务启动")
283 |
284 | url = f'https://push.hellyw.com/{push_config.get("IGOT_PUSH_KEY")}'
285 | data = {"title": title, "content": content}
286 | headers = {"Content-Type": "application/x-www-form-urlencoded"}
287 | response = requests.post(url, data=data, headers=headers).json()
288 |
289 | if response["ret"] == 0:
290 | print("iGot 推送成功!")
291 | else:
292 | print(f'iGot 推送失败!{response["errMsg"]}')
293 |
294 |
295 | def serverJ(title: str, content: str) -> None:
296 | """
297 | 通过 serverJ 推送消息。
298 | """
299 | if not push_config.get("PUSH_KEY"):
300 | print("serverJ 服务的 PUSH_KEY 未设置!!\n取消推送")
301 | return
302 | print("serverJ 服务启动")
303 |
304 | data = {"text": title, "desp": content.replace("\n", "\n\n")}
305 | if push_config.get("PUSH_KEY").find("SCT") != -1:
306 | url = f'https://sctapi.ftqq.com/{push_config.get("PUSH_KEY")}.send'
307 | else:
308 | url = f'https://sc.ftqq.com/{push_config.get("PUSH_KEY")}.send'
309 | response = requests.post(url, data=data).json()
310 |
311 | if response.get("errno") == 0 or response.get("code") == 0:
312 | print("serverJ 推送成功!")
313 | else:
314 | print(f'serverJ 推送失败!错误码:{response["message"]}')
315 |
316 |
317 | def pushdeer(title: str, content: str) -> None:
318 | """
319 | 通过PushDeer 推送消息
320 | """
321 | if not push_config.get("DEER_KEY"):
322 | print("PushDeer 服务的 DEER_KEY 未设置!!\n取消推送")
323 | return
324 | print("PushDeer 服务启动")
325 | data = {
326 | "text": title,
327 | "desp": content,
328 | "type": "markdown",
329 | "pushkey": push_config.get("DEER_KEY"),
330 | }
331 | url = "https://api2.pushdeer.com/message/push"
332 | if push_config.get("DEER_URL"):
333 | url = push_config.get("DEER_URL")
334 |
335 | response = requests.post(url, data=data).json()
336 |
337 | if len(response.get("content").get("result")) > 0:
338 | print("PushDeer 推送成功!")
339 | else:
340 | print("PushDeer 推送失败!错误信息:", response)
341 |
342 |
343 | def chat(title: str, content: str) -> None:
344 | """
345 | 通过Chat 推送消息
346 | """
347 | if not push_config.get("CHAT_URL") or not push_config.get("CHAT_TOKEN"):
348 | print("chat 服务的 CHAT_URL或CHAT_TOKEN 未设置!!\n取消推送")
349 | return
350 | print("chat 服务启动")
351 | data = "payload=" + json.dumps({"text": title + "\n" + content})
352 | url = push_config.get("CHAT_URL") + push_config.get("CHAT_TOKEN")
353 | response = requests.post(url, data=data)
354 |
355 | if response.status_code == 200:
356 | print("Chat 推送成功!")
357 | else:
358 | print("Chat 推送失败!错误信息:", response)
359 |
360 |
361 | def pushplus_bot(title: str, content: str) -> None:
362 | """
363 | 通过 push+ 推送消息。
364 | """
365 | if not push_config.get("PUSH_PLUS_TOKEN"):
366 | print("PUSHPLUS 服务的 PUSH_PLUS_TOKEN 未设置!!\n取消推送")
367 | return
368 | print("PUSHPLUS 服务启动")
369 |
370 | url = "http://www.pushplus.plus/send"
371 | data = {
372 | "token": push_config.get("PUSH_PLUS_TOKEN"),
373 | "title": title,
374 | "content": content,
375 | "topic": push_config.get("PUSH_PLUS_USER"),
376 | }
377 | body = json.dumps(data).encode(encoding="utf-8")
378 | headers = {"Content-Type": "application/json"}
379 | response = requests.post(url=url, data=body, headers=headers).json()
380 |
381 | if response["code"] == 200:
382 | print("PUSHPLUS 推送成功!")
383 |
384 | else:
385 | url_old = "http://pushplus.hxtrip.com/send"
386 | headers["Accept"] = "application/json"
387 | response = requests.post(url=url_old, data=body, headers=headers).json()
388 |
389 | if response["code"] == 200:
390 | print("PUSHPLUS(hxtrip) 推送成功!")
391 |
392 | else:
393 | print("PUSHPLUS 推送失败!")
394 |
395 |
396 | def weplus_bot(title: str, content: str) -> None:
397 | """
398 | 通过 微加机器人 推送消息。
399 | """
400 | if not push_config.get("WE_PLUS_BOT_TOKEN"):
401 | print("微加机器人 服务的 WE_PLUS_BOT_TOKEN 未设置!!\n取消推送")
402 | return
403 | print("微加机器人 服务启动")
404 |
405 | template = "txt"
406 | if len(content) > 800:
407 | template = "html"
408 |
409 | url = "https://www.weplusbot.com/send"
410 | data = {
411 | "token": push_config.get("WE_PLUS_BOT_TOKEN"),
412 | "title": title,
413 | "content": content,
414 | "template": template,
415 | "receiver": push_config.get("WE_PLUS_BOT_RECEIVER"),
416 | "version": push_config.get("WE_PLUS_BOT_VERSION"),
417 | }
418 | body = json.dumps(data).encode(encoding="utf-8")
419 | headers = {"Content-Type": "application/json"}
420 | response = requests.post(url=url, data=body, headers=headers).json()
421 |
422 | if response["code"] == 200:
423 | print("微加机器人 推送成功!")
424 | else:
425 | print("微加机器人 推送失败!")
426 |
427 |
428 | def qmsg_bot(title: str, content: str) -> None:
429 | """
430 | 使用 qmsg 推送消息。
431 | """
432 | if not push_config.get("QMSG_KEY") or not push_config.get("QMSG_TYPE"):
433 | print("qmsg 的 QMSG_KEY 或者 QMSG_TYPE 未设置!!\n取消推送")
434 | return
435 | print("qmsg 服务启动")
436 |
437 | url = f'https://qmsg.zendee.cn/{push_config.get("QMSG_TYPE")}/{push_config.get("QMSG_KEY")}'
438 | payload = {"msg": f'{title}\n\n{content.replace("----", "-")}'.encode("utf-8")}
439 | response = requests.post(url=url, params=payload).json()
440 |
441 | if response["code"] == 0:
442 | print("qmsg 推送成功!")
443 | else:
444 | print(f'qmsg 推送失败!{response["reason"]}')
445 |
446 |
447 | def wecom_app(title: str, content: str) -> None:
448 | """
449 | 通过 企业微信 APP 推送消息。
450 | """
451 | if not push_config.get("QYWX_AM"):
452 | print("QYWX_AM 未设置!!\n取消推送")
453 | return
454 | QYWX_AM_AY = re.split(",", push_config.get("QYWX_AM"))
455 | if 4 < len(QYWX_AM_AY) > 5:
456 | print("QYWX_AM 设置错误!!\n取消推送")
457 | return
458 | print("企业微信 APP 服务启动")
459 |
460 | corpid = QYWX_AM_AY[0]
461 | corpsecret = QYWX_AM_AY[1]
462 | touser = QYWX_AM_AY[2]
463 | agentid = QYWX_AM_AY[3]
464 | try:
465 | media_id = QYWX_AM_AY[4]
466 | except IndexError:
467 | media_id = ""
468 | wx = WeCom(corpid, corpsecret, agentid)
469 | # 如果没有配置 media_id 默认就以 text 方式发送
470 | if not media_id:
471 | message = title + "\n\n" + content
472 | response = wx.send_text(message, touser)
473 | else:
474 | response = wx.send_mpnews(title, content, media_id, touser)
475 |
476 | if response == "ok":
477 | print("企业微信推送成功!")
478 | else:
479 | print("企业微信推送失败!错误信息如下:\n", response)
480 |
481 |
482 | class WeCom:
483 | def __init__(self, corpid, corpsecret, agentid):
484 | self.CORPID = corpid
485 | self.CORPSECRET = corpsecret
486 | self.AGENTID = agentid
487 | self.ORIGIN = "https://qyapi.weixin.qq.com"
488 | if push_config.get("QYWX_ORIGIN"):
489 | self.ORIGIN = push_config.get("QYWX_ORIGIN")
490 |
491 | def get_access_token(self):
492 | url = f"{self.ORIGIN}/cgi-bin/gettoken"
493 | values = {
494 | "corpid": self.CORPID,
495 | "corpsecret": self.CORPSECRET,
496 | }
497 | req = requests.post(url, params=values)
498 | data = json.loads(req.text)
499 | return data["access_token"]
500 |
501 | def send_text(self, message, touser="@all"):
502 | send_url = (
503 | f"{self.ORIGIN}/cgi-bin/message/send?access_token={self.get_access_token()}"
504 | )
505 | send_values = {
506 | "touser": touser,
507 | "msgtype": "text",
508 | "agentid": self.AGENTID,
509 | "text": {"content": message},
510 | "safe": "0",
511 | }
512 | send_msges = bytes(json.dumps(send_values), "utf-8")
513 | respone = requests.post(send_url, send_msges)
514 | respone = respone.json()
515 | return respone["errmsg"]
516 |
517 | def send_mpnews(self, title, message, media_id, touser="@all"):
518 | send_url = (
519 | f"{self.ORIGIN}/cgi-bin/message/send?access_token={self.get_access_token()}"
520 | )
521 | send_values = {
522 | "touser": touser,
523 | "msgtype": "mpnews",
524 | "agentid": self.AGENTID,
525 | "mpnews": {
526 | "articles": [
527 | {
528 | "title": title,
529 | "thumb_media_id": media_id,
530 | "author": "Author",
531 | "content_source_url": "",
532 | "content": message.replace("\n", "
"),
533 | "digest": message,
534 | }
535 | ]
536 | },
537 | }
538 | send_msges = bytes(json.dumps(send_values), "utf-8")
539 | respone = requests.post(send_url, send_msges)
540 | respone = respone.json()
541 | return respone["errmsg"]
542 |
543 |
544 | def wecom_bot(title: str, content: str) -> None:
545 | """
546 | 通过 企业微信机器人 推送消息。
547 | """
548 | if not push_config.get("QYWX_KEY"):
549 | print("企业微信机器人 服务的 QYWX_KEY 未设置!!\n取消推送")
550 | return
551 | print("企业微信机器人服务启动")
552 |
553 | origin = "https://qyapi.weixin.qq.com"
554 | if push_config.get("QYWX_ORIGIN"):
555 | origin = push_config.get("QYWX_ORIGIN")
556 |
557 | url = f"{origin}/cgi-bin/webhook/send?key={push_config.get('QYWX_KEY')}"
558 | headers = {"Content-Type": "application/json;charset=utf-8"}
559 | data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
560 | response = requests.post(
561 | url=url, data=json.dumps(data), headers=headers, timeout=15
562 | ).json()
563 |
564 | if response["errcode"] == 0:
565 | print("企业微信机器人推送成功!")
566 | else:
567 | print("企业微信机器人推送失败!")
568 |
569 |
570 | def telegram_bot(title: str, content: str) -> None:
571 | """
572 | 使用 telegram 机器人 推送消息。
573 | """
574 | if not push_config.get("TG_BOT_TOKEN") or not push_config.get("TG_USER_ID"):
575 | print("tg 服务的 bot_token 或者 user_id 未设置!!\n取消推送")
576 | return
577 | print("tg 服务启动")
578 |
579 | if push_config.get("TG_API_HOST"):
580 | url = f"{push_config.get('TG_API_HOST')}/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
581 | else:
582 | url = (
583 | f"https://api.telegram.org/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
584 | )
585 | headers = {"Content-Type": "application/x-www-form-urlencoded"}
586 | payload = {
587 | "chat_id": str(push_config.get("TG_USER_ID")),
588 | "text": f"{title}\n\n{content}",
589 | "disable_web_page_preview": "true",
590 | }
591 | proxies = None
592 | if push_config.get("TG_PROXY_HOST") and push_config.get("TG_PROXY_PORT"):
593 | if push_config.get("TG_PROXY_AUTH") is not None and "@" not in push_config.get(
594 | "TG_PROXY_HOST"
595 | ):
596 | push_config["TG_PROXY_HOST"] = (
597 | push_config.get("TG_PROXY_AUTH")
598 | + "@"
599 | + push_config.get("TG_PROXY_HOST")
600 | )
601 | proxyStr = "http://{}:{}".format(
602 | push_config.get("TG_PROXY_HOST"), push_config.get("TG_PROXY_PORT")
603 | )
604 | proxies = {"http": proxyStr, "https": proxyStr}
605 | response = requests.post(
606 | url=url, headers=headers, params=payload, proxies=proxies
607 | ).json()
608 |
609 | if response["ok"]:
610 | print("tg 推送成功!")
611 | else:
612 | print("tg 推送失败!")
613 |
614 |
615 | def aibotk(title: str, content: str) -> None:
616 | """
617 | 使用 智能微秘书 推送消息。
618 | """
619 | if (
620 | not push_config.get("AIBOTK_KEY")
621 | or not push_config.get("AIBOTK_TYPE")
622 | or not push_config.get("AIBOTK_NAME")
623 | ):
624 | print(
625 | "智能微秘书 的 AIBOTK_KEY 或者 AIBOTK_TYPE 或者 AIBOTK_NAME 未设置!!\n取消推送"
626 | )
627 | return
628 | print("智能微秘书 服务启动")
629 |
630 | if push_config.get("AIBOTK_TYPE") == "room":
631 | url = "https://api-bot.aibotk.com/openapi/v1/chat/room"
632 | data = {
633 | "apiKey": push_config.get("AIBOTK_KEY"),
634 | "roomName": push_config.get("AIBOTK_NAME"),
635 | "message": {"type": 1, "content": f"【青龙快讯】\n\n{title}\n{content}"},
636 | }
637 | else:
638 | url = "https://api-bot.aibotk.com/openapi/v1/chat/contact"
639 | data = {
640 | "apiKey": push_config.get("AIBOTK_KEY"),
641 | "name": push_config.get("AIBOTK_NAME"),
642 | "message": {"type": 1, "content": f"【青龙快讯】\n\n{title}\n{content}"},
643 | }
644 | body = json.dumps(data).encode(encoding="utf-8")
645 | headers = {"Content-Type": "application/json"}
646 | response = requests.post(url=url, data=body, headers=headers).json()
647 | print(response)
648 | if response["code"] == 0:
649 | print("智能微秘书 推送成功!")
650 | else:
651 | print(f'智能微秘书 推送失败!{response["error"]}')
652 |
653 |
654 | def smtp(title: str, content: str) -> None:
655 | """
656 | 使用 SMTP 邮件 推送消息。
657 | """
658 | if (
659 | not push_config.get("SMTP_SERVER")
660 | or not push_config.get("SMTP_SSL")
661 | or not push_config.get("SMTP_EMAIL")
662 | or not push_config.get("SMTP_PASSWORD")
663 | or not push_config.get("SMTP_NAME")
664 | ):
665 | print(
666 | "SMTP 邮件 的 SMTP_SERVER 或者 SMTP_SSL 或者 SMTP_EMAIL 或者 SMTP_PASSWORD 或者 SMTP_NAME 未设置!!\n取消推送"
667 | )
668 | return
669 | print("SMTP 邮件 服务启动")
670 |
671 | message = MIMEText(content, "plain", "utf-8")
672 | message["From"] = formataddr(
673 | (
674 | Header(push_config.get("SMTP_NAME"), "utf-8").encode(),
675 | push_config.get("SMTP_EMAIL"),
676 | )
677 | )
678 | message["To"] = formataddr(
679 | (
680 | Header(push_config.get("SMTP_NAME"), "utf-8").encode(),
681 | push_config.get("SMTP_EMAIL"),
682 | )
683 | )
684 | message["Subject"] = Header(title, "utf-8")
685 |
686 | try:
687 | smtp_server = (
688 | smtplib.SMTP_SSL(push_config.get("SMTP_SERVER"))
689 | if push_config.get("SMTP_SSL") == "true"
690 | else smtplib.SMTP(push_config.get("SMTP_SERVER"))
691 | )
692 | smtp_server.login(
693 | push_config.get("SMTP_EMAIL"), push_config.get("SMTP_PASSWORD")
694 | )
695 | smtp_server.sendmail(
696 | push_config.get("SMTP_EMAIL"),
697 | push_config.get("SMTP_EMAIL"),
698 | message.as_bytes(),
699 | )
700 | smtp_server.close()
701 | print("SMTP 邮件 推送成功!")
702 | except Exception as e:
703 | print(f"SMTP 邮件 推送失败!{e}")
704 |
705 |
706 | def pushme(title: str, content: str) -> None:
707 | """
708 | 使用 PushMe 推送消息。
709 | """
710 | if not push_config.get("PUSHME_KEY"):
711 | print("PushMe 服务的 PUSHME_KEY 未设置!!\n取消推送")
712 | return
713 | print("PushMe 服务启动")
714 |
715 | url = (
716 | push_config.get("PUSHME_URL")
717 | if push_config.get("PUSHME_URL")
718 | else "https://push.i-i.me/"
719 | )
720 | data = {
721 | "push_key": push_config.get("PUSHME_KEY"),
722 | "title": title,
723 | "content": content,
724 | "date": push_config.get("date") if push_config.get("date") else "",
725 | "type": push_config.get("type") if push_config.get("type") else "",
726 | }
727 | response = requests.post(url, data=data)
728 |
729 | if response.status_code == 200 and response.text == "success":
730 | print("PushMe 推送成功!")
731 | else:
732 | print(f"PushMe 推送失败!{response.status_code} {response.text}")
733 |
734 |
735 | def chronocat(title: str, content: str) -> None:
736 | """
737 | 使用 CHRONOCAT 推送消息。
738 | """
739 | if (
740 | not push_config.get("CHRONOCAT_URL")
741 | or not push_config.get("CHRONOCAT_QQ")
742 | or not push_config.get("CHRONOCAT_TOKEN")
743 | ):
744 | print("CHRONOCAT 服务的 CHRONOCAT_URL 或 CHRONOCAT_QQ 未设置!!\n取消推送")
745 | return
746 |
747 | print("CHRONOCAT 服务启动")
748 |
749 | user_ids = re.findall(r"user_id=(\d+)", push_config.get("CHRONOCAT_QQ"))
750 | group_ids = re.findall(r"group_id=(\d+)", push_config.get("CHRONOCAT_QQ"))
751 |
752 | url = f'{push_config.get("CHRONOCAT_URL")}/api/message/send'
753 | headers = {
754 | "Content-Type": "application/json",
755 | "Authorization": f'Bearer {push_config.get("CHRONOCAT_TOKEN")}',
756 | }
757 |
758 | for chat_type, ids in [(1, user_ids), (2, group_ids)]:
759 | if not ids:
760 | continue
761 | for chat_id in ids:
762 | data = {
763 | "peer": {"chatType": chat_type, "peerUin": chat_id},
764 | "elements": [
765 | {
766 | "elementType": 1,
767 | "textElement": {"content": f"{title}\n\n{content}"},
768 | }
769 | ],
770 | }
771 | response = requests.post(url, headers=headers, data=json.dumps(data))
772 | if response.status_code == 200:
773 | if chat_type == 1:
774 | print(f"QQ个人消息:{ids}推送成功!")
775 | else:
776 | print(f"QQ群消息:{ids}推送成功!")
777 | else:
778 | if chat_type == 1:
779 | print(f"QQ个人消息:{ids}推送失败!")
780 | else:
781 | print(f"QQ群消息:{ids}推送失败!")
782 |
783 |
784 | def parse_headers(headers):
785 | if not headers:
786 | return {}
787 |
788 | parsed = {}
789 | lines = headers.split("\n")
790 |
791 | for line in lines:
792 | i = line.find(":")
793 | if i == -1:
794 | continue
795 |
796 | key = line[:i].strip().lower()
797 | val = line[i + 1 :].strip()
798 | parsed[key] = parsed.get(key, "") + ", " + val if key in parsed else val
799 |
800 | return parsed
801 |
802 |
803 | def parse_string(input_string, value_format_fn=None):
804 | matches = {}
805 | pattern = r"(\w+):\s*((?:(?!\n\w+:).)*)"
806 | regex = re.compile(pattern)
807 | for match in regex.finditer(input_string):
808 | key, value = match.group(1).strip(), match.group(2).strip()
809 | try:
810 | value = value_format_fn(value) if value_format_fn else value
811 | json_value = json.loads(value)
812 | matches[key] = json_value
813 | except:
814 | matches[key] = value
815 | return matches
816 |
817 |
818 | def parse_body(body, content_type, value_format_fn=None):
819 | if not body or content_type == "text/plain":
820 | return value_format_fn(body) if value_format_fn and body else body
821 |
822 | parsed = parse_string(body, value_format_fn)
823 |
824 | if content_type == "application/x-www-form-urlencoded":
825 | data = urllib.parse.urlencode(parsed, doseq=True)
826 | return data
827 |
828 | if content_type == "application/json":
829 | data = json.dumps(parsed)
830 | return data
831 |
832 | return parsed
833 |
834 |
835 | def custom_notify(title: str, content: str) -> None:
836 | """
837 | 通过 自定义通知 推送消息。
838 | """
839 | if not push_config.get("WEBHOOK_URL") or not push_config.get("WEBHOOK_METHOD"):
840 | print("自定义通知的 WEBHOOK_URL 或 WEBHOOK_METHOD 未设置!!\n取消推送")
841 | return
842 |
843 | print("自定义通知服务启动")
844 |
845 | WEBHOOK_URL = push_config.get("WEBHOOK_URL")
846 | WEBHOOK_METHOD = push_config.get("WEBHOOK_METHOD")
847 | WEBHOOK_CONTENT_TYPE = push_config.get("WEBHOOK_CONTENT_TYPE")
848 | WEBHOOK_BODY = push_config.get("WEBHOOK_BODY")
849 | WEBHOOK_HEADERS = push_config.get("WEBHOOK_HEADERS")
850 |
851 | if "$title" not in WEBHOOK_URL and "$title" not in WEBHOOK_BODY:
852 | print("请求头或者请求体中必须包含 $title 和 $content")
853 | return
854 |
855 | headers = parse_headers(WEBHOOK_HEADERS)
856 | body = parse_body(
857 | WEBHOOK_BODY,
858 | WEBHOOK_CONTENT_TYPE,
859 | lambda v: v.replace("$title", title).replace("$content", content),
860 | )
861 | formatted_url = WEBHOOK_URL.replace(
862 | "$title", urllib.parse.quote_plus(title)
863 | ).replace("$content", urllib.parse.quote_plus(content))
864 | response = requests.request(
865 | method=WEBHOOK_METHOD, url=formatted_url, headers=headers, timeout=15, data=body
866 | )
867 |
868 | if response.status_code == 200:
869 | print("自定义通知推送成功!")
870 | else:
871 | print(f"自定义通知推送失败!{response.status_code} {response.text}")
872 |
873 |
874 | def one() -> str:
875 | """
876 | 获取一条一言。
877 | :return:
878 | """
879 | url = "https://v1.hitokoto.cn/"
880 | res = requests.get(url).json()
881 | return res["hitokoto"] + " ----" + res["from"]
882 |
883 |
884 | def add_notify_function():
885 | notify_function = []
886 | if push_config.get("BARK_PUSH"):
887 | notify_function.append(bark)
888 | if push_config.get("CONSOLE"):
889 | notify_function.append(console)
890 | if push_config.get("DD_BOT_TOKEN") and push_config.get("DD_BOT_SECRET"):
891 | notify_function.append(dingding_bot)
892 | if push_config.get("FSKEY"):
893 | notify_function.append(feishu_bot)
894 | if push_config.get("GOBOT_URL") and push_config.get("GOBOT_QQ"):
895 | notify_function.append(go_cqhttp)
896 | if push_config.get("GOTIFY_URL") and push_config.get("GOTIFY_TOKEN"):
897 | notify_function.append(gotify)
898 | if push_config.get("IGOT_PUSH_KEY"):
899 | notify_function.append(iGot)
900 | if push_config.get("PUSH_KEY"):
901 | notify_function.append(serverJ)
902 | if push_config.get("DEER_KEY"):
903 | notify_function.append(pushdeer)
904 | if push_config.get("CHAT_URL") and push_config.get("CHAT_TOKEN"):
905 | notify_function.append(chat)
906 | if push_config.get("PUSH_PLUS_TOKEN"):
907 | notify_function.append(pushplus_bot)
908 | if push_config.get("WE_PLUS_BOT_TOKEN"):
909 | notify_function.append(weplus_bot)
910 | if push_config.get("QMSG_KEY") and push_config.get("QMSG_TYPE"):
911 | notify_function.append(qmsg_bot)
912 | if push_config.get("QYWX_AM"):
913 | notify_function.append(wecom_app)
914 | if push_config.get("QYWX_KEY"):
915 | notify_function.append(wecom_bot)
916 | if push_config.get("TG_BOT_TOKEN") and push_config.get("TG_USER_ID"):
917 | notify_function.append(telegram_bot)
918 | if (
919 | push_config.get("AIBOTK_KEY")
920 | and push_config.get("AIBOTK_TYPE")
921 | and push_config.get("AIBOTK_NAME")
922 | ):
923 | notify_function.append(aibotk)
924 | if (
925 | push_config.get("SMTP_SERVER")
926 | and push_config.get("SMTP_SSL")
927 | and push_config.get("SMTP_EMAIL")
928 | and push_config.get("SMTP_PASSWORD")
929 | and push_config.get("SMTP_NAME")
930 | ):
931 | notify_function.append(smtp)
932 | if push_config.get("PUSHME_KEY"):
933 | notify_function.append(pushme)
934 | if (
935 | push_config.get("CHRONOCAT_URL")
936 | and push_config.get("CHRONOCAT_QQ")
937 | and push_config.get("CHRONOCAT_TOKEN")
938 | ):
939 | notify_function.append(chronocat)
940 | if push_config.get("WEBHOOK_URL") and push_config.get("WEBHOOK_METHOD"):
941 | notify_function.append(custom_notify)
942 |
943 | if not notify_function:
944 | print(f"无推送渠道,请检查通知变量是否正确")
945 | return notify_function
946 |
947 |
948 | def send(title: str, content: str, ignore_default_config: bool = False, **kwargs):
949 | if kwargs:
950 | global push_config
951 | if ignore_default_config:
952 | push_config = kwargs # 清空从环境变量获取的配置
953 | else:
954 | push_config.update(kwargs)
955 |
956 | if not content:
957 | print(f"{title} 推送内容为空!")
958 | return
959 |
960 | # 根据标题跳过一些消息推送,环境变量:SKIP_PUSH_TITLE 用回车分隔
961 | skipTitle = os.getenv("SKIP_PUSH_TITLE").split("&")
962 | if skipTitle:
963 | if title in skipTitle and "失效" not in content:
964 | print(f"{title} 在SKIP_PUSH_TITLE环境变量内,跳过推送!")
965 | return
966 |
967 | hitokoto = push_config.get("HITOKOTO")
968 | content += "\n\n" + one() if hitokoto else ""
969 |
970 | notify_function = add_notify_function()
971 |
972 | if "失效" in content:
973 | bark(title, content)
974 | return
975 |
976 | telegram_bot(title, content)
977 |
978 | def main():
979 | send("title", "content")
980 |
981 |
982 | if __name__ == "__main__":
983 | main()
--------------------------------------------------------------------------------
/Script/ql_api.js:
--------------------------------------------------------------------------------
1 | $.ql = {
2 | type: "api",
3 | headers: {
4 | "Content-Type": `application/json;charset=UTF-8`,
5 | Authorization: "",
6 | },
7 | disabled(ids) {
8 | if (!this.headers.Authorization) return;
9 | const opt = {
10 | url: `${$.ql_url}/${this.type}/envs/disable`,
11 | headers: this.headers,
12 | body: JSON.stringify(ids),
13 | };
14 | return $.http.put(opt).then((response) => JSON.parse(response.body));
15 | },
16 | enabled(ids) {
17 | if (!this.headers.Authorization) return;
18 | const opt = {
19 | url: `${$.ql_url}/${this.type}/envs/enable`,
20 | headers: this.headers,
21 | body: JSON.stringify(ids),
22 | };
23 | return $.http.put(opt).then((response) => JSON.parse(response.body));
24 | },
25 | delete(ids) {
26 | if (!this.headers.Authorization) return;
27 | const opt = {
28 | url: `${$.ql_url}/${this.type}/envs`,
29 | headers: this.headers,
30 | body: JSON.stringify(ids),
31 | };
32 | return $.http.delete(opt).then((response) => JSON.parse(response.body));
33 | },
34 | add(records) {
35 | if (!this.headers.Authorization) return;
36 | const opt = {
37 | url: `${$.ql_url}/${this.type}/envs`,
38 | headers: this.headers,
39 | body: JSON.stringify(records),
40 | };
41 | return $.http.post(opt).then((response) => JSON.parse(response.body));
42 | },
43 | edit(records) {
44 | if (!this.headers.Authorization) return;
45 | const opt = {
46 | url: `${$.ql_url}/${this.type}/envs`,
47 | headers: this.headers,
48 | body: JSON.stringify(records),
49 | };
50 | return $.http.put(opt).then((response) => JSON.parse(response.body));
51 | },
52 | select(searchValue) {
53 | if (!this.headers.Authorization) return;
54 | const opt = {
55 | url: `${$.ql_url}/${this.type}/envs?searchValue=${searchValue}`,
56 | headers: this.headers,
57 | };
58 | return $.http.get(opt).then((response) => JSON.parse(response.body));
59 | },
60 | initial: () => {
61 | $.ql_url = $.ql_config.ip;
62 | if ($.ql_url && !$.ql_url.match(/^(http|https)/))
63 | $.ql_url = `http://${$.ql_url}`;
64 |
65 | $.application = {
66 | client_id: $.ql_config.client_id,
67 | client_secret: $.ql_config.client_secret,
68 | };
69 |
70 | $.ql_account = {
71 | username: $.ql_config.username,
72 | password: $.ql_config.password,
73 | };
74 | },
75 | };
76 |
77 | try {
78 | $.ql_config = JSON.parse($.read("#ql"));
79 | } catch (e) {
80 | $.ql_config = {};
81 | }
82 |
83 | $.ql.initial();
84 |
85 | function noReady() {
86 | $.ql = false;
87 | $.log("请配置好相关信息");
88 | }
89 |
90 | if ($.ql_config.is_pwd === "true") {
91 | if ($.ql_account.username && $.ql_account.password) {
92 | $.ql.login = async () => {
93 | const options = {
94 | url: `${$.ql_url}/api/user/login`,
95 | body: JSON.stringify($.ql_account),
96 | headers: {
97 | "Content-Type": `application/json;charset=UTF-8`,
98 | },
99 | };
100 |
101 | let response = await $.http.post(options);
102 | response = JSON.parse(response.body);
103 | if (response.code === 200) {
104 | $.ql.type = "api";
105 | $.ql.headers.Authorization = `Bearer ${response.data.token}`;
106 | $.log(`登陆青龙面板成功:${response.data.lastaddr}`);
107 | $.log(`ip:${response.data.lastip}`);
108 | } else {
109 | $.log(response);
110 | $.log(`登陆青龙面板失败:${response.message}`);
111 | }
112 | };
113 | } else {
114 | noReady();
115 | }
116 | } else {
117 | if ($.application.client_id && $.application.client_secret) {
118 | $.ql.login = async () => {
119 | const options = {
120 | url: `${$.ql_url}/open/auth/token?client_id=${$.application.client_id}&client_secret=${$.application.client_secret}`,
121 | headers: {
122 | "Content-Type": `application/json;charset=UTF-8`,
123 | },
124 | };
125 | let response = await $.http.get(options);
126 | response = JSON.parse(response.body);
127 | if (response.code === 200) {
128 | $.ql.type = "open";
129 | $.ql.headers.Authorization = `Bearer ${response.data.token}`;
130 | $.log(`登陆青龙面板成功`);
131 | } else {
132 | $.log(response);
133 | $.log(`登陆青龙面板失败:${response.message}`);
134 | }
135 | };
136 | } else {
137 | noReady();
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/Script/tenvideo.js:
--------------------------------------------------------------------------------
1 | /**
2 | *@file 腾讯视频
3 | *@desp 本脚本仅适用于腾讯视频及体育会员每日签到,仅测试Quantumult X、青龙(只支持单账号)
4 | *@env txspCookie、txspRefreshCookie、txspRefreshBody、dayOfGetMonthTicket、isSkipTxspCheckIn、isLottery
5 | *@author WowYiJiu
6 | *@updated 2024-6-14
7 | *@version v1.0.3
8 | *@link https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/tenvideo.js
9 |
10 | 🌟 环境变量说明
11 | txspCookie:腾讯视频app的Cookie
12 | txspRefreshCookie、txspRefreshBody:腾讯视频网页NewRefresh接口中的数据,用来刷新Cookie中的vqq_vusession
13 | dayOfGetMonthTicket:每月几号领取每月球票,默认为每月1号
14 | isSkipTxspCheckIn:值域[true, false] 默认为false表示正常进行腾讯视频会员签到,用于特殊情况下(账号需要获取短信验证码或者需要过滑块验证码)时开启
15 | isLottery: 值域[true, false] 默认为false表示不抽奖,抽抽乐于2024年2月29日10点下线,建议不开启,反正也抽不到
16 | ❗ 本脚本只能给腾讯视频正常账号签到,如有验证请设置isSkipTxspCheckIn为true,直到手动签到无验证为止
17 | ❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖❖
18 |
19 | 详细功能:
20 | 🔵 腾讯视频会员签到领V力值
21 | 🔵 腾讯体育会员签到领热爱值
22 | 🔵 腾讯体育领取每日球票
23 | 🔵 腾讯体育领取每月球票
24 |
25 | 📌 获取Cookie:(重写需要获取3个值:txspCookie、txspRefreshCookie、txspRefreshBody)
26 | - 进入腾讯视频app,点击右下角我的,点击头像下的视频VIP进入会员中心看到系统消息提示获取txspCookie成功即可
27 | - 浏览器进入腾讯视频网页版,登录后切换成桌面版,刷新网页看到系统消息提示获取txspRefreshCookie、txspRefreshBody成功即可
28 | - 获取Cookie后, 请将Cookie脚本禁用并移除主机名,以免产生不必要的MITM
29 |
30 | 💬 BoxJs订阅:https://raw.githubusercontent.com/WowYiJiu/Personal/main/WowYiJiu.box.json
31 |
32 | ⚙ 配置 (Quantumult X)
33 | [MITM]
34 | hostname = vip.video.qq.com, pbaccess.video.qq.com
35 |
36 | [rewrite_local]
37 | https://vip.video.qq.com/rpc/trpc.new_task_system.task_system.TaskSystem/ReadTaskList? url script-request-header https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/tenvideo.js
38 | https://pbaccess.video.qq.com/trpc.videosearch.hot_rank.HotRankServantHttp/HotRankHttp url script-request-header https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/tenvideo.js
39 | https://pbaccess.video.qq.com/trpc.video_account_login.web_login_trpc.WebLoginTrpc/NewRefresh url script-request-body https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/tenvideo.js
40 |
41 | [rewrite_remote]
42 | https://raw.githubusercontent.com/WowYiJiu/Personal/main/rewrite/get_tenvideo_cookie.conf, tag=腾讯视频, update-interval=172800, opt-parser=false, enabled=false
43 |
44 | [task_local]
45 | 5 7 * * * https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/tenvideo.js, tag=腾讯视频, img-url=https://github.com/WowYiJiu/Personal/blob/main/icon/Color/tenvideo.png?raw=true, enabled=true
46 | */
47 | const $ = new Env("腾讯视频");
48 |
49 | let txspCookie = ($.isNode() ? process.env.txspCookie : $.getdata('txspCookie')) || "";
50 | let txspRefreshCookie = ($.isNode() ? process.env.txspRefreshCookie : $.getdata('txspRefreshCookie')) || "";
51 | let txspRefreshBody = ($.isNode() ? process.env.txspRefreshBody : $.getdata('txspRefreshBody')) || "";
52 | let dayOfGetMonthTicket = ($.isNode() ? process.env.dayOfGetMonthTicket : $.getdata('dayOfGetMonthTicket')) || 1;
53 | let isSkipTxspCheckIn = $.isNode() ? process.env.isSkipTxspCheckIn : (($.getdata('isSkipTxspCheckIn') !== undefined && $.getdata('isSkipTxspCheckIn') !== '') ? JSON.parse($.getdata('isSkipTxspCheckIn')) : false);
54 | let isLottery = $.isNode() ? process.env.isLottery : (($.getdata('isLottery') !== undefined && $.getdata('isLottery') !== '') ? JSON.parse($.getdata('isLottery')) : false);
55 |
56 | const Notify = 1; //0为关闭通知,1为打开通知,默认为1
57 | const notify = $.isNode() ? require("./sendNotify") : "";
58 |
59 | let currentVersion = "v1.0.3", latestVersion = "";
60 | let nickname = "";
61 | let isTxspVip = false, isTxspSvip = false, isTxSportsVip = false, isTxSportsSvip = false;
62 | let endTime = "", svipEndTime = "", txSportsEndTime = "", txSportsSvipEndTime = "";
63 | let level = "", txSportsLevel = "";
64 | let score = "", txSportsScore = "";
65 | let month_received_score = "", month_limit = "";
66 | let isTxspCheckIn = "", isTxSportsCheckIn = "";
67 |
68 | let originalInfo = $.info;
69 | let originalWarn = $.warn;
70 | let originalError = $.error;
71 | let message = "";
72 | $.desc = "", $.taskInfo = "";
73 | $.info=function(message){originalInfo.call($,message);$.desc+=message+"\n"};$.warn=function(message){originalWarn.call($,message);$.desc+=message+"\n"};$.error=function(message){originalError.call($,message);$.desc+=message+"\n"};
74 |
75 | if ((isGetCookie = typeof $request !== `undefined`)) {
76 | getCookie();
77 | $.done();
78 | } else if (!$.isNode() && !txspCookie){
79 | $.msg($.name, "您未获取腾讯视频Cookie", "点击此条跳转到腾讯视频获取Cookie", { 'open-url': 'tenvideo://', 'media-url': 'https://raw.githubusercontent.com/WowYiJiu/Personal/main/icon/videoqq.png' });
80 | $.done();
81 | } else {
82 | !(async () => {
83 | $.log(` _ _ _ `);
84 | $.log(` __ _______ ___ _(_)(_|_)_ _ `);
85 | $.log(` \\ \\ /\\ / / _ \\ \\ /\\ / / | | | || | | | | | `);
86 | $.log(` \\ \V \V / (_) \\ \V \V /| |_| | || | | |_| | `);
87 | $.log(` \\_/\\_/ \\___/ \\_/\\_/ \\__, |_|/ |_|\\__,_| `);
88 | $.log(` |___/ |__/ `);
89 | await getNotice();
90 | await getVersion();
91 | $.log(`\n当前版本:${currentVersion} 最新版本:${latestVersion}\n`);
92 | $.version = `\n当前版本:${currentVersion} 最新版本:${latestVersion}\n`;
93 | if(!txspCookie){
94 | $.warn(`未填写txspCookie环境变量`);
95 | return;
96 | }
97 | $.info("---- 开始 刷新vusession ----");
98 | await refresh_vusession();
99 | $.info(`--------- 结束 ---------\n`);
100 | $.info(`用户昵称:${nickname}`);
101 | await getVipInfo();
102 | if (isTxspVip){
103 | $.info(`---- 腾讯视频VIP信息 ----`);
104 | if (isTxspSvip){
105 | $.info(`当前是腾讯视频SVIP`);
106 | } else {
107 | $.info(`当前是腾讯视频VIP`);
108 | }
109 | $.info(`当前等级:${level}`);
110 | $.info(`当前成长:${score}`);
111 | if (isTxspSvip){
112 | $.info(`SVIP到期时间:${svipEndTime}`);
113 | }
114 | $.info(`VIP到期时间:${endTime}`);
115 | $.info(`--------- 结束 ---------\n`);
116 | }
117 | if (isTxSportsVip){
118 | $.info(`--- 腾讯体育VIP信息 ---`);
119 | if (isTxSportsSvip){
120 | $.info(`当前是腾讯体育超级VIP`);
121 | } else {
122 | $.info(`当前是腾讯体育VIP`);
123 | }
124 | $.info(`当前等级:${txSportsLevel}`);
125 | $.info(`当前成长:${txSportsScore}`);
126 | if (isTxSportsSvip){
127 | $.info(`SVIP到期时间:${txSportsSvipEndTime}`);
128 | }
129 | $.info(`VIP到期时间:${txSportsEndTime}`);
130 | $.info(`--------- 结束 ---------\n`);
131 | }
132 | if (isTxspVip){
133 | $.info(`---- 开始 腾讯视频签到 ----`);
134 | if (isSkipTxspCheckIn){
135 | $.info(`当前设置为不进行腾讯视频签到,跳过`);
136 | } else {
137 | await readTxspTaskList();
138 | await waitRandom(1000, 2000);
139 | if (month_received_score === month_limit){
140 | $.info(`本月活跃任务已满${month_limit}V力值,下个月再来哦`);
141 | } else if (isTxspCheckIn){
142 | $.info(`今天已签到, 明日再来吧`);
143 | } else {
144 | await txspCheckIn();
145 | await waitRandom(1000, 2000);
146 | }
147 | }
148 | $.info(`--------- 结束 ---------\n`);
149 | }
150 | if (isTxSportsVip){
151 | $.info(`---- 开始 腾讯体育签到 ----`);
152 | await readTxSportsTaskList();
153 | await waitRandom(1000, 2000);
154 | if (isTxSportsCheckIn){
155 | $.info(`今天已签到, 明日再来吧`);
156 | } else {
157 | await txSportsCheckIn();
158 | await waitRandom(1000, 2000);
159 | }
160 | $.info(`--------- 结束 ---------\n`);
161 | $.info(`---- 开始 领取每日球票 ----`);
162 | await getDayTicket();
163 | await waitRandom(1000, 2000);
164 | $.info(`--------- 结束 ---------\n`);
165 | $.info(`---- 开始 领取每月球票 ----`);
166 | var today = new Date();
167 | var date = today.getDate();
168 | if (date !== dayOfGetMonthTicket){
169 | $.info(`目标日期:${dayOfGetMonthTicket}号`);
170 | $.info(`今天是${date}号`);
171 | $.info(`跳过`);
172 | } else {
173 | $.info(`目标日期:${dayOfGetMonthTicket}号`);
174 | $.info(`今天是${date}号`);
175 | await getMonthTicket();
176 | }
177 | $.info(`--------- 结束 ---------\n`);
178 | if (isLottery) {
179 | $.info(`---- 开始 抽抽乐 ----`);
180 | await lottery();
181 | await waitRandom(1000, 2000);
182 | $.info(`--------- 结束 ---------`);
183 | }
184 | }
185 | await SendMsg();
186 | })()
187 | .catch((e) => $.error(e))
188 | .finally(() => $.done());
189 | }
190 |
191 | async function refresh_vusession() {
192 | return new Promise((resolve) => {
193 | let opt = {
194 | url: `https://pbaccess.video.qq.com/trpc.video_account_login.web_login_trpc.WebLoginTrpc/NewRefresh`,
195 | headers: {
196 | cookie: txspRefreshCookie,
197 | origin: 'https://v.qq.com',
198 | referer: 'https://v.qq.com/',
199 | 'Content-Type': 'application/json'
200 | },
201 | body: txspRefreshBody
202 | };
203 | $.post(opt, async (error, resp, data) => {
204 | if (safeGet(data)) {
205 | var obj = JSON.parse(data);
206 | if (obj.data.errcode === 0) {
207 | let vqq_vusession = obj.data.vusession;
208 | nickname = decodeURIComponent(obj.data.nick);
209 | if (txspCookie.match(/main_login=([^;]*)/)[1] === "qq"){
210 | txspCookie = txspCookie.replace(/(vqq_vusession=)[^;]*/, `$1${vqq_vusession}`);
211 | } else if(txspCookie.match(/main_login=([^;]*)/)[1] === "wx"){
212 | txspCookie = txspCookie.replace(/(vusession=)[^;]*/, `$1${vusession}`);
213 | }
214 | $.info("刷新vusession成功")
215 | } else {
216 | $.warn("刷新vusession失败");
217 | }
218 | resolve();
219 | }
220 | }
221 | )
222 | })
223 | }
224 |
225 | async function getVipInfo() {
226 | return new Promise((resolve, reject) => {
227 | let opt = {
228 | url: `https://vip.video.qq.com/rpc/trpc.query_vipinfo.vipinfo.QueryVipInfo/GetVipUserInfoH5`,
229 | headers: {
230 | cookie: txspCookie,
231 | 'Content-Type': 'application/json'
232 | },
233 | body: JSON.stringify({"geticon":1,"viptype":"svip|sports|nfl","platform":5})
234 | };
235 | $.post(opt, async (error, resp, data) => {
236 | try {
237 | if (safeGet(data)) {
238 | var obj = JSON.parse(data);
239 | if (!obj.servicetype) {
240 | throw new Error(`Cookie已失效`);
241 | } else {
242 | if (obj.vip === 1){
243 | isTxspVip = true;
244 | endTime = obj.endTime;
245 | level = obj.level;
246 | score = obj.score;
247 | }
248 | if (obj.svip_info.vip === 1){
249 | isTxspSvip = true;
250 | svipEndTime = obj.svip_info.endTime;
251 | }
252 | if (obj.sports.vip.vip === 1){
253 | isTxSportsVip = true;
254 | txSportsEndTime = obj.sports.vip.endTime;
255 | txSportsLevel = obj.sports.vip.level;
256 | txSportsScore = obj.sports.vip.score;
257 | }
258 | if (obj.sports.svip.vip === 1){
259 | isTxSportsSvip = true;
260 | txSportsSvipEndTime = obj.sports.svip.endTime;
261 | }
262 | }
263 | resolve();
264 | }
265 | } catch (e) {
266 | $.error(e);
267 | reject(`该账号本次跳过执行\n`);
268 | }
269 | }
270 | )
271 | })
272 | }
273 |
274 | /**
275 | * 获取腾讯视频任务列表
276 | * @async
277 | * @function readTxspTaskList
278 | * @returns
279 | */
280 | async function readTxspTaskList() {
281 | return new Promise((resolve) => {
282 | let opt = {
283 | url: `https://vip.video.qq.com/rpc/trpc.new_task_system.task_system.TaskSystem/ReadTaskList?rpc_data={"business_id":"1","platform":5}`,
284 | headers: {
285 | Referer: "https://film.video.qq.com/x/grade/?ptag=user.apho&ovscroll=0&hidetitlebar=1&aid=V0$$1:0$2:7$3:8.11.01.25068$4:0$8:4&isDarkMode=1&uiType=REGULAR",
286 | Cookie: txspCookie,
287 | },
288 | };
289 | $.get(opt, async (error, resp, data) => {
290 | try {
291 | if (safeGet(data)) {
292 | var obj = JSON.parse(data);
293 | var code = obj.ret;
294 | let task_maintitle = "";
295 | if (code === 0) {
296 | month_received_score = obj.limit_info.month_received_score;
297 | month_limit = obj.limit_info.month_limit;
298 | let taskList = obj.task_list;
299 | let txspCheckInTask = taskList && taskList.find(task => task.task_maintitle === "VIP会员每日签到");
300 | isTxspCheckIn = txspCheckInTask.task_status;
301 | } else {
302 | $.warn(`获取腾讯视频任务列表失败,异常详细信息如下\n${data}`);
303 | }
304 | resolve();
305 | }
306 | } catch (e) {
307 | $.error(e);
308 | }
309 | });
310 | });
311 | }
312 |
313 | /**
314 | * 腾讯视频签到领取V力值
315 | * @async
316 | * @function txspCheckIn
317 | * @returns
318 | */
319 | async function txspCheckIn() {
320 | return new Promise((resolve, reject) => {
321 | let opt = {
322 | url: `https://vip.video.qq.com/rpc/trpc.new_task_system.task_system.TaskSystem/CheckIn?rpc_data={}`,
323 | headers: {
324 | Referer: "https://film.video.qq.com/x/grade/?ptag=user.apho&ovscroll=0&hidetitlebar=1&aid=V0$$1:0$2:7$3:8.11.01.25068$4:0$8:4&isDarkMode=1&uiType=REGULAR",
325 | Cookie: txspCookie,
326 | },
327 | };
328 | $.get(opt, async (error, resp, data) => {
329 | var obj = JSON.parse(data);
330 | var code = obj.ret;
331 | if (code === 0 && obj.check_in_score != undefined) {
332 | $.info(`签到成功:获得${obj.check_in_score}V力值`);
333 | $.taskInfo = `签到成功:获得${obj.check_in_score}V力值\n`;
334 | } else if (code === -2002) {
335 | $.info(`今天已签到, 明日再来吧`);
336 | $.taskInfo = `今天已签到, 明日再来吧\n`;
337 | } else {
338 | $.warn(`签到失败,异常详细信息如下\n${data}`);
339 | $.taskInfo = `签到失败, 异常详细信息请查看日志\n`;
340 | }
341 | resolve();
342 | });
343 | });
344 | }
345 |
346 | /**
347 | * 获取腾讯体育任务列表
348 | * @async
349 | * @function readTxSportsTaskList
350 | * @returns
351 | */
352 | async function readTxSportsTaskList() {
353 | return new Promise((resolve) => {
354 | let opt = {
355 | url: `https://vip.video.qq.com/rpc/trpc.new_task_system.task_system.TaskSystem/ReadTaskList?rpc_data={"business_id":3,"channel_id":4,"platform":5}`,
356 | headers: {
357 | Referer: "https://film.video.qq.com/x/sports-grade/?ovscroll=0&hidetitlebar=1&immersive=1",
358 | Cookie: txspCookie,
359 | },
360 | };
361 | $.get(opt, async (error, resp, data) => {
362 | try {
363 | if (safeGet(data)) {
364 | var obj = JSON.parse(data);
365 | var code = obj.ret;
366 | let task_maintitle = "";
367 | if (code === 0) {
368 | let taskList = obj.task_list;
369 | let txSportsCheckInTasks = taskList && taskList.find(task => task.task_maintitle === "每日签到");
370 | isTxSportsCheckIn = txSportsCheckInTasks.task_status;
371 | } else {
372 | $.warn(`获取腾讯视频任务列表失败,异常详细信息如下\n${data}`);
373 | }
374 | resolve();
375 | }
376 | } catch (e) {
377 | $.error(e);
378 | }
379 | });
380 | });
381 | }
382 |
383 | /**
384 | * 腾讯体育签到领取热爱值
385 | * @async
386 | * @function txSportsCheckIn
387 | * @returns
388 | */
389 | async function txSportsCheckIn() {
390 | return new Promise((resolve, reject) => {
391 | let opt = {
392 | url: `https://vip.video.qq.com/rpc/trpc.new_task_system.task_system.TaskSystem/CheckIn?rpc_data={"task_id":8006}`,
393 | headers: {
394 | Referer:
395 | "https://film.video.qq.com/x/sports-grade/?ovscroll=0&hidetitlebar=1&immersive=1",
396 | Cookie: txspCookie,
397 | },
398 | };
399 | $.get(opt, async (error, resp, data) => {
400 | var obj = JSON.parse(data);
401 | var code = obj.ret;
402 | if (code === 0 && obj.check_in_score != undefined) {
403 | $.info(`签到成功:获得${obj.check_in_score}热爱值`);
404 | $.taskInfo += `签到成功:获得${obj.check_in_score}热爱值\n`;
405 | } else if (code === -2002) {
406 | $.info(`今天已签到, 明日再来吧`);
407 | $.taskInfo += `今天已签到, 明日再来吧\n`;
408 | } else {
409 | $.warn(`签到失败,异常详细信息如下\n${data}`);
410 | $.taskInfo += `签到失败, 异常详细信息请查看日志\n`;
411 | }
412 | resolve();
413 | });
414 | });
415 | }
416 |
417 | /**
418 | * 领取每日球票
419 | * @async
420 | * @function getDayTicket
421 | * @returns
422 | */
423 | async function getDayTicket() {
424 | return new Promise((resolve, reject) => {
425 | let opt = {
426 | url: "https://activity.video.qq.com/fcgi-bin/asyn_activity?otype=xjson&act_id=118561&module_id=158089&type=90&option=5",
427 | headers: {
428 | Origin: "https://film.video.qq.com",
429 | Referer: "https://film.video.qq.com/x/sports-vip-channel/?from=tab",
430 | Cookie: txspCookie,
431 | },
432 | };
433 | $.get(opt, async (error, resp, data) => {
434 | try {
435 | var obj = JSON.parse(data);
436 | var code = obj.ret;
437 | if (code === 0) {
438 | $.info(`领取每日球票成功`);
439 | $.taskInfo += `领取每日球票成功\n`;
440 | } else if (code === -2021) {
441 | $.info(`每日球票已领取, 明日再来吧`);
442 | $.taskInfo += `每日球票已领取, 明日再来吧\n`;
443 | } else {
444 | $.warn(`领取每日球票失败,异常详细信息如下\n${data}`);
445 | $.taskInfo += `领取每日球票失败,异常详细信息请查看日志\n`;
446 | }
447 | } catch (e) {
448 | $.error(e);
449 | } finally {
450 | resolve();
451 | }
452 | });
453 | });
454 | }
455 |
456 | /**
457 | * 领取每月球票
458 | * @async
459 | * @function getMonthTicket
460 | * @returns
461 | */
462 | async function getMonthTicket() {
463 | return new Promise((resolve, reject) => {
464 | let opt = {
465 | url: "https://activity.video.qq.com/fcgi-bin/asyn_activity?otype=xjson&act_id=118561&module_id=165163&type=100160&option=100",
466 | headers: {
467 | Origin: "https://film.video.qq.com",
468 | Referer: "https://film.video.qq.com/x/sports-vip-channel/?from=tab",
469 | Cookie: txspCookie,
470 | },
471 | };
472 | $.get(opt, async (error, resp, data) => {
473 | try {
474 | var obj = JSON.parse(data);
475 | var code = obj.ret;
476 | if (code === 0) {
477 | $.info(`领取每月球票成功`);
478 | $.taskInfo += `领取每月球票成功\n`;
479 | } else if (code === -903) {
480 | $.info(`每月球票已领取,下个月再来哦`);
481 | $.taskInfo += `每月球票已领取,下个月再来哦\n`;
482 | } else {
483 | $.warn(`领取每月球票失败,异常详细信息如下\n${data}`);
484 | $.taskInfo += `领取每月球票失败,异常详细信息请查看日志\n`;
485 | }
486 | } catch (e) {
487 | $.error(e);
488 | } finally {
489 | resolve();
490 | }
491 | });
492 | });
493 | }
494 |
495 | /**
496 | * 抽抽乐 2024年2月29日10点下线
497 | * @async
498 | * @function lottery()
499 | * @returns
500 | */
501 | async function lottery() {
502 | return new Promise((resolve, reject) => {
503 | let opt = {
504 | url: "https://activity.video.qq.com/fcgi-bin/asyn_activity?otype=xjson&act_id=118561&module_id=158090&type=100143&option=100",
505 | headers: {
506 | Origin: "https://film.video.qq.com",
507 | Referer: "https://film.video.qq.com/x/sports-vip-channel/?from=tab",
508 | Cookie: txspCookie,
509 | },
510 | };
511 | $.get(opt, async (error, resp, data) => {
512 | try {
513 | var obj = JSON.parse(data);
514 | var code = obj.ret;
515 | if (code === 0) {
516 | $.info(`抽奖成功: ${obj.lotter_ext}`);
517 | } else if (code === -904) {
518 | $.info(`今天已抽奖, 明日再来吧`);
519 | } else {
520 | $.warn(`抽奖失败,异常详细信息如下\n${data}`);
521 | }
522 | } catch (e) {
523 | $.error(e);
524 | } finally {
525 | resolve();
526 | }
527 | });
528 | });
529 | }
530 |
531 | function getCookie() {
532 | if($request && $request.method !=`OPTIONS` && $request.url.match(/\/rpc\/trpc\.new_task_system\.task_system\.TaskSystem\/ReadTaskList/)){
533 | let txsp = $request.headers["Cookie"] || $request.headers["cookie"];
534 | if (txsp) {
535 | if (typeof txspCookie === "undefined" || (txspCookie && txspCookie.length === 0)) {
536 | $.setdata(txsp, "txspCookie");
537 | $.log(`Cookie: ${txsp}`);
538 | $.msg($.name, "🎉 Cookie写入成功", "不用请自行关闭重写!");
539 | } else if (txsp !== txspCookie) {
540 | $.setdata(txsp, "txspCookie");
541 | $.log(`Cookie: ${txsp}`);
542 | $.msg($.name, "🎉 Cookie更新成功", "不用请自行关闭重写!");
543 | } else {
544 | $.msg($.name, "⚠️ Cookie未变动 跳过更新", "不用请自行关闭重写!");
545 | }
546 | } else {
547 | $.msg($.name, "⚠️ Cookie未找到", "不用请自行关闭重写!");
548 | }
549 | }
550 | if($request && $request.method !=`OPTIONS` && $request.url.match(/\/trpc\.videosearch\.hot_rank\.HotRankServantHttp\/HotRankHttp/)){
551 | let refreshCookie = $request.headers["Cookie"] || $request.headers["cookie"];
552 | if (refreshCookie) {
553 | if (typeof txspRefreshCookie === "undefined" || (txspRefreshCookie && txspRefreshCookie.length === 0)) {
554 | $.setdata(refreshCookie, "txspRefreshCookie");
555 | $.log(`Cookie: ${refreshCookie}`);
556 | $.msg($.name, "🎉 refreshCookie写入成功", "不用请自行关闭重写!");
557 | } else if (refreshCookie !== txspRefreshCookie) {
558 | $.setdata(refreshCookie, "txspRefreshCookie");
559 | $.log(`Cookie: ${refreshCookie}`);
560 | $.msg($.name, "🎉 refreshCookie更新成功", "不用请自行关闭重写!");
561 | } else {
562 | $.msg($.name, "⚠️ refreshCookie未变动 跳过更新", "不用请自行关闭重写!");
563 | }
564 | } else {
565 | $.msg($.name, "⚠️ refreshCookie未找到", "不用请自行关闭重写!");
566 | }
567 | }
568 | if($request && $request.method !=`OPTIONS` && $request.url.match(/\/trpc\.video_account_login\.web_login_trpc\.WebLoginTrpc\/NewRefresh/)){
569 | let refreshBody = $request.body;
570 | if (refreshBody){
571 | if (typeof txspRefreshBody === "undefined" || (txspRefreshBody && txspRefreshBody.length === 0)) {
572 | $.setdata(refreshBody, "txspRefreshBody");
573 | $.log(`refreshBody: ${refreshBody}`);
574 | $.msg($.name, "🎉 refreshBody写入成功", "不用请自行关闭重写!");
575 | } else if (refreshBody !== txspRefreshBody) {
576 | $.setdata(refreshBody, "txspRefreshBody");
577 | $.log(`refreshBody: ${refreshBody}`);
578 | $.msg($.name, "🎉 refreshBody更新成功", "不用请自行关闭重写!");
579 | } else {
580 | $.msg($.name, "⚠️ refreshBody未变动 跳过更新", "不用请自行关闭重写!");
581 | }
582 | }
583 | }
584 | }
585 |
586 | async function getNotice() {
587 | return new Promise((resolve) => {
588 | let opt = {
589 | url: "https://github.wowyijiu.today/https://raw.githubusercontent.com/WowYiJiu/Personal/main/WowYiJiu.json",
590 | timeout: 10000,
591 | };
592 | $.get(opt, async (error, resp, data) => {
593 | try {
594 | if (error) {
595 | $.error("👾 获取免责声明失败");
596 | resolve();
597 | } else {
598 | if (data) {
599 | var obj = JSON.parse(data);
600 | $.log(obj.notice);
601 | resolve();
602 | }
603 | }
604 | } catch (e) {
605 | $.error(e);
606 | resolve();
607 | }
608 | });
609 | });
610 | }
611 |
612 | async function getVersion() {
613 | const timeoutMs = 10000;
614 | const opt = {
615 | url: "https://github.wowyijiu.today/https://raw.githubusercontent.com/WowYiJiu/Personal/main/Script/tenvideo.js",
616 | timeout: timeoutMs
617 | };
618 | const data = await new Promise((resolve) => {
619 | $.get(opt, (error, resp, data) => {
620 | if (error) {
621 | resolve("undefined");
622 | } else {
623 | resolve(data);
624 | }
625 | });
626 | });
627 |
628 | const versionInfo = data.match(/@version\s+(v\d+\.\d+\.\d+)/);
629 | if (versionInfo) {
630 | latestVersion = versionInfo[1];
631 | } else {
632 | latestVersion = "undefined";
633 | }
634 | return latestVersion;
635 | }
636 |
637 | async function SendMsg() {
638 | if (Notify > 0) {
639 | if ($.isNode()) {
640 | await notify.sendNotify($.name, `${$.version}\n\n${$.desc}`);
641 | } else {
642 | $.msg($.name, "", `${$.version}\n${$.taskInfo}`);
643 | }
644 | } else {
645 | $.msg($.name, "", `${$.version}\n${$.taskInfo}`);
646 | }
647 | }
648 |
649 | async function waitRandom(min, max) {
650 | var time = getRandomInt(min, max);
651 | await $.wait(time);
652 | }
653 |
654 | // 随机生成整数
655 | function getRandomInt(min, max) {
656 | min = Math.ceil(min);
657 | max = Math.floor(max);
658 | return Math.floor(Math.random() * (max - min + 1)) + min;
659 | }
660 |
661 | // 提取Cookie的指定字段
662 | function extractValues(str, keys) {
663 | let results = keys.map((key) =>
664 | str.split("; ").find((s) => s.startsWith(key + "="))
665 | );
666 | return results.join(";");
667 | }
668 |
669 | // 判断时间戳是不是今天
670 | function isToday(timestamp) {
671 | let date = new Date(timestamp);
672 | let today = new Date();
673 | return (
674 | date.getDate() === today.getDate() &&
675 | date.getMonth() === today.getMonth() &&
676 | date.getFullYear() === today.getFullYear()
677 | );
678 | }
679 |
680 | function safeGet(data) {
681 | try {
682 | if (typeof JSON.parse(data) == "object") {
683 | return true;
684 | }
685 | } catch (e) {
686 | $.error(e);
687 | $.error(`腾讯视频访问数据为空,请检查Cookie是否有效`);
688 | return false;
689 | }
690 | }
691 |
692 | // prettier-ignore
693 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise(((e,i)=>{s.call(this,t,((t,s,o)=>{t?i(t):e(s)}))}))}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.logLevels={debug:0,info:1,warn:2,error:3},this.logLevelPrefixs={debug:" DEBUG",info:" INFO",warn:" WARN",error:" ERROR"},this.logLevel="info",this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null,...s){try{return JSON.stringify(t,...s)}catch{return e}}getjson(t,e){let s=e;if(this.getdata(t))try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise((e=>{this.get({url:t},((t,s,i)=>e(i)))}))}runScript(t,e){return new Promise((s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let o=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");o=o?1*o:20,o=e&&e.timeout?e.timeout:o;const[r,a]=i.split("@"),n={url:`http://${a}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:o},headers:{"X-Key":r,Accept:"*/*"},timeout:o};this.post(n,((t,e,i)=>s(i)))})).catch((t=>this.logErr(t)))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),o=JSON.stringify(this.data);s?this.fs.writeFileSync(t,o):i?this.fs.writeFileSync(e,o):this.fs.writeFileSync(t,o)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let o=t;for(const t of i)if(o=Object(o)[t],void 0===o)return s;return o}lodash_set(t,e,s){return Object(t)!==t||(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce(((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{}),t)[e[e.length-1]]=s),t}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),o=s?this.getval(s):"";if(o)try{const t=JSON.parse(o);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,o]=/^@(.*?)\.(.*?)$/.exec(e),r=this.getval(i),a=i?"null"===r?null:r||"{}":"{}";try{const e=JSON.parse(a);this.lodash_set(e,o,t),s=this.setval(JSON.stringify(e),i)}catch(e){const r={};this.lodash_set(r,o,t),s=this.setval(JSON.stringify(r),i)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.cookie&&void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar)))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),t.params&&(t.url+="?"+this.queryStr(t.params)),void 0===t.followRedirect||t.followRedirect||((this.isSurge()||this.isLoon())&&(t["auto-redirect"]=!1),this.isQuanX()&&(t.opts?t.opts.redirection=!1:t.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,((t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)}));break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then((t=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=t;e(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)}),(t=>e(t&&t.error||"UndefinedError")));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",((t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}})).then((t=>{const{statusCode:i,statusCode:o,headers:r,rawBody:a}=t,n=s.decode(a,this.encoding);e(null,{status:i,statusCode:o,headers:r,rawBody:a,body:n},n)}),(t=>{const{message:i,response:o}=t;e(i,o,o&&s.decode(o.rawBody,this.encoding))}));break}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),void 0===t.followRedirect||t.followRedirect||((this.isSurge()||this.isLoon())&&(t["auto-redirect"]=!1),this.isQuanX()&&(t.opts?t.opts.redirection=!1:t.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,((t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)}));break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then((t=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=t;e(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)}),(t=>e(t&&t.error||"UndefinedError")));break;case"Node.js":let i=require("iconv-lite");this.initGotEnv(t);const{url:o,...r}=t;this.got[s](o,r).then((t=>{const{statusCode:s,statusCode:o,headers:r,rawBody:a}=t,n=i.decode(a,this.encoding);e(null,{status:s,statusCode:o,headers:r,rawBody:a,body:n},n)}),(t=>{const{message:s,response:o}=t;e(s,o,o&&i.decode(o.rawBody,this.encoding))}));break}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}queryStr(t){let e="";for(const s in t){let i=t[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),e+=`${s}=${i}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",i="",o={}){const r=t=>{const{$open:e,$copy:s,$media:i,$mediaMime:o}=t;switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{const r={};let a=t.openUrl||t.url||t["open-url"]||e;a&&Object.assign(r,{action:"open-url",url:a});let n=t["update-pasteboard"]||t.updatePasteboard||s;if(n&&Object.assign(r,{action:"clipboard",text:n}),i){let t,e,s;if(i.startsWith("http"))t=i;else if(i.startsWith("data:")){const[t]=i.split(";"),[,o]=i.split(",");e=o,s=t.replace("data:","")}else{e=i,s=(t=>{const e={JVBERi0:"application/pdf",R0lGODdh:"image/gif",R0lGODlh:"image/gif",iVBORw0KGgo:"image/png","/9j/":"image/jpg"};for(var s in e)if(0===t.indexOf(s))return e[s];return null})(i)}Object.assign(r,{"media-url":t,"media-base64":e,"media-base64-mime":o??s})}return Object.assign(r,{"auto-dismiss":t["auto-dismiss"],sound:t.sound}),r}case"Loon":{const s={};let o=t.openUrl||t.url||t["open-url"]||e;o&&Object.assign(s,{openUrl:o});let r=t.mediaUrl||t["media-url"];return i?.startsWith("http")&&(r=i),r&&Object.assign(s,{mediaUrl:r}),console.log(JSON.stringify(s)),s}case"Quantumult X":{const o={};let r=t["open-url"]||t.url||t.openUrl||e;r&&Object.assign(o,{"open-url":r});let a=t["media-url"]||t.mediaUrl;i?.startsWith("http")&&(a=i),a&&Object.assign(o,{"media-url":a});let n=t["update-pasteboard"]||t.updatePasteboard||s;return n&&Object.assign(o,{"update-pasteboard":n}),console.log(JSON.stringify(o)),o}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,i,r(o));break;case"Quantumult X":$notify(e,s,i,r(o));break;case"Node.js":break}if(!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}debug(...t){this.logLevels[this.logLevel]<=this.logLevels.debug&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`[${this.time('HH:mm:ss')}${this.logLevelPrefixs.debug}] ${t.map((t=>t??String(t))).join(this.logSeparator)}`))}info(...t){this.logLevels[this.logLevel]<=this.logLevels.info&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`[${this.time('HH:mm:ss')}${this.logLevelPrefixs.info}] ${t.map((t=>t??String(t))).join(this.logSeparator)}`))}warn(...t){this.logLevels[this.logLevel]<=this.logLevels.warn&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`[${this.time('HH:mm:ss')}${this.logLevelPrefixs.warn}] ${t.map((t=>t??String(t))).join(this.logSeparator)}`))}error(...t){this.logLevels[this.logLevel]<=this.logLevels.error&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`[${this.time('HH:mm:ss')}${this.logLevelPrefixs.error}] ${t.map((t=>t??String(t))).join(this.logSeparator)}`))}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.map((t=>t??String(t))).join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,e,t);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,e,void 0!==t.message?t.message:t,t.stack);break}}wait(t){return new Promise((e=>setTimeout(e,t)))}done(t={}){const e=((new Date).getTime()-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${e} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)}
--------------------------------------------------------------------------------
/Script/移动云盘.py:
--------------------------------------------------------------------------------
1 | # @file 中国移动云盘
2 | # @desp 签到 基础任务 果园 云朵大作战
3 | # @version v5.0.2
4 | # @author github@villagebully8 https://github.com/villagebully8
5 | # 使用说明:
6 | # - [抓包 Cookie:任意Authorization]
7 | # - [注意事项: 简易方法,开抓包进App,搜refresh,找到authTokenRefresh.do ,请求头中的Authorization]
8 | # 环境变量设置:
9 | # - 名称:[ydypCK] 格式:[Authorization值#手机号]
10 | # - 多账号处理方式:[换行或者@分割]
11 | # 定时设置: [0 0 8,16,20 * * *]
12 | # 更新日志:
13 | # - [1.30]: [同一环境变量获取]
14 | # - [5.13]: [删除笔记任务,删除捕获错误,删除笔记变量]
15 | # 注: 本脚本仅用于个人学习和交流,请勿用于非法用途。作者不承担由于滥用此脚本所引起的任何责任,请在下载后24小时内删除。
16 | # https://raw.githubusercontent.com/villagebully8/yybs/main/%E4%BA%91%E7%9B%98%E4%BA%91%E6%9C%B55.0.2.py
17 | import os
18 | import random
19 | import re
20 | import time
21 | import requests
22 | from os import path
23 |
24 | ua = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) MCloudApp/11.0.1 iPhone AppLanguage/zh-CN"
25 |
26 | err_accounts = "" # 异常账号
27 | err_message = "" # 错误信息
28 | user_amount = "" # 用户云朵·数量
29 | GLOBAL_DEBUG = False
30 |
31 |
32 | # 发送通知
33 | def load_send():
34 | cur_path = path.abspath(path.dirname(__file__))
35 | notify_file = cur_path + "/notify.py"
36 |
37 | if path.exists(notify_file):
38 | try:
39 | from notify import send # 导入模块的send为notify_send
40 |
41 | print("加载通知服务成功!")
42 | return send # 返回导入的函数
43 | except ImportError:
44 | print("加载通知服务失败~")
45 | else:
46 | print("加载通知服务失败~")
47 | return False # 返回False表示未成功加载通知服务
48 |
49 |
50 | class YP:
51 | def __init__(self, cookie, index):
52 | self.GLOBAL_DEBUG = False
53 | self.index = index
54 | self.click_num = 25 # 定义抽奖次数和摇一摇戳一戳次数
55 | self.draw = 1 # 抽奖次数,首次免费
56 | self.session = requests.Session()
57 |
58 | self.timestamp = str(int(round(time.time() * 1000)))
59 | self.cookies = {"sensors_stay_time": self.timestamp}
60 | self.Authorization = cookie.split("#")[0]
61 | self.account = cookie.split("#")[1]
62 | self.encrypt_account = self.account[:3] + "*" * 4 + self.account[7:]
63 | self.fruit_url = "https://happy.mail.10086.cn/jsp/cn/garden/"
64 |
65 | self.jwtHeaders = {
66 | "User-Agent": ua,
67 | "Accept": "*/*",
68 | "Host": "caiyun.feixin.10086.cn:7071",
69 | }
70 | self.treeHeaders = {
71 | "Host": "happy.mail.10086.cn",
72 | "Accept": "application/json, text/plain, */*",
73 | "User-Agent": ua,
74 | "Referer": "https://happy.mail.10086.cn/jsp/cn/garden/wap/index.html?sourceid=1003",
75 | "Cookie": "",
76 | }
77 |
78 | def run(self):
79 | if self.jwt():
80 | self.signin_status()
81 | self.click()
82 | # 任务
83 | self.get_tasklist(url="sign_in_3", app_type="cloud_app")
84 | print(f"\n☁️ 云朵大作战")
85 | self.cloud_game()
86 | print(f"\n🌳 果园任务")
87 | self.fruitLogin()
88 | print(f"\n📰 公众号任务")
89 | self.wxsign()
90 | self.shake()
91 | self.surplus_num()
92 | print(f"\n🔥 热门任务")
93 | self.backup_cloud()
94 | self.open_send()
95 | print(f"\n📧 139邮箱任务")
96 | self.get_tasklist(url="newsign_139mail", app_type="email_app")
97 | self.receive()
98 | else:
99 | global err_accounts
100 | # 失效账号
101 | err_accounts += f"{self.encrypt_account}\n"
102 |
103 | def send_request(self, url, headers=None, cookies=None, data=None, method='GET', debug=None, retries=5):
104 |
105 | debug = debug if debug is not None else self.GLOBAL_DEBUG
106 |
107 | self.session.headers.update(headers or {})
108 | if cookies:
109 | self.session.cookies.update(cookies)
110 | request_args = {"json": data} if isinstance(data, dict) else {"data": data}
111 |
112 | for attempt in range(retries):
113 | try:
114 | response = self.session.request(method, url, **request_args)
115 | response.raise_for_status()
116 | if debug:
117 | print(f"\n【账号{self.index}】:{url}响应数据:\n{response.text}\n")
118 | return response
119 | except (requests.RequestException, ConnectionError, TimeoutError) as e:
120 | print(f"【账号{self.index}】: {e}")
121 | if attempt >= retries - 1:
122 | print(f"达到最大重试次数。")
123 | return None
124 | time.sleep(0.1 * (2**attempt))
125 |
126 | # 随机延迟默认1-1.5s
127 | def sleep(self, min_delay=1, max_delay=1.5):
128 | delay = random.uniform(min_delay, max_delay)
129 | time.sleep(delay)
130 |
131 | # 日志
132 | def log_info(self, err_msg=None, amount=None):
133 | global err_message, user_amount
134 | if err_msg is not None:
135 | err_message += f"用户[{self.encrypt_account}]:{err_msg}\n" # 错误信息
136 | elif amount is not None:
137 | user_amount += f"用户[{self.encrypt_account}]:{amount}\n" # 云朵数量
138 |
139 | # 刷新令牌
140 | def sso(self):
141 | sso_url = "https://orches.yun.139.com/orchestration/auth-rebuild/token/v1.0/querySpecToken"
142 | sso_headers = {
143 | "Authorization": self.Authorization,
144 | "User-Agent": ua,
145 | "Content-Type": "application/json",
146 | "Accept": "*/*",
147 | "Host": "orches.yun.139.com",
148 | }
149 | sso_payload = {"account": self.account, "toSourceId": "001005"}
150 | sso_data = self.send_request(
151 | sso_url, headers=sso_headers, data=sso_payload, method="POST"
152 | ).json()
153 |
154 | if sso_data["success"]:
155 | refresh_token = sso_data["data"]["token"]
156 | return refresh_token
157 | else:
158 | print(sso_data["message"])
159 | return None
160 |
161 | # jwt
162 | def jwt(self):
163 | # 获取jwttoken
164 | token = self.sso()
165 | if token is not None:
166 |
167 | jwt_url = f"https://caiyun.feixin.10086.cn:7071/portal/auth/tyrzLogin.action?ssoToken={token}"
168 | jwt_data = self.send_request(
169 | jwt_url, headers=self.jwtHeaders, method="POST"
170 | ).json()
171 | if jwt_data["code"] != 0:
172 | print(jwt_data["msg"])
173 | return False
174 | self.jwtHeaders["jwtToken"] = jwt_data["result"]["token"]
175 | self.cookies["jwtToken"] = jwt_data["result"]["token"]
176 | return True
177 | else:
178 | print("-ck可能失效了")
179 | return False
180 |
181 | # 签到查询
182 | def signin_status(self):
183 | self.sleep()
184 | check_url = "https://caiyun.feixin.10086.cn/market/signin/page/info?client=app"
185 | try:
186 | check_data = self.send_request(
187 | check_url, headers=self.jwtHeaders, cookies=self.cookies
188 | ).json()
189 | if check_data["msg"] == "success":
190 | today_sign_in = check_data["result"].get("todaySignIn", False)
191 |
192 | if today_sign_in:
193 | print("✅已签到")
194 | else:
195 | print("❌ 未签到")
196 | signin_url = "https://caiyun.feixin.10086.cn/market/manager/commonMarketconfig/getByMarketRuleName?marketName=sign_in_3"
197 | signin_data = self.send_request(
198 | signin_url, headers=self.jwtHeaders, cookies=self.cookies
199 | ).json()
200 |
201 | if signin_data["msg"] == "success":
202 | print("✅签到成功")
203 | else:
204 | print(signin_data["msg"])
205 | self.log_info(signin_data["msg"])
206 | else:
207 | print(check_data["msg"])
208 | self.log_info(check_data["msg"])
209 |
210 | except Exception as e:
211 | print(f"签到查询失败 {e}")
212 |
213 | # 戳一下
214 | def click(self):
215 | url = "https://caiyun.feixin.10086.cn/market/signin/task/click?key=task&id=319"
216 | successful_click = 0 # 获得次数
217 |
218 | try:
219 | for _ in range(self.click_num):
220 | return_data = self.send_request(
221 | url, headers=self.jwtHeaders, cookies=self.cookies
222 | ).json()
223 | time.sleep(0.2)
224 |
225 | if "result" in return_data:
226 | print(f'✅{return_data["result"]}')
227 | successful_click += 1
228 |
229 | if successful_click == 0:
230 | print(f"❌未获得 x {self.click_num}")
231 | except Exception as e:
232 | print(f"戳一下错误信息:{e}")
233 |
234 | # 任务列表
235 | def get_tasklist(self, url, app_type):
236 | url = f"https://caiyun.feixin.10086.cn/market/signin/task/taskList?marketname={url}"
237 | return_data = self.send_request(
238 | url, headers=self.jwtHeaders, cookies=self.cookies
239 | ).json()
240 | self.sleep()
241 | # 任务列表
242 | task_list = return_data.get("result", {})
243 |
244 | try:
245 | for task_type, tasks in task_list.items():
246 | if task_type in ["new", "hidden", "hiddenabc"]:
247 | continue
248 | if app_type == "cloud_app":
249 | if task_type == "month":
250 | print("\n📆 云盘每月任务")
251 | for month in tasks:
252 | task_id = month.get("id")
253 | if task_id in [110, 435, 417]:
254 | continue
255 | task_name = month.get("name", "")
256 | task_status = month.get("state", "")
257 |
258 | if task_status == "FINISH":
259 | print(f"-已完成: {task_name}")
260 | continue
261 | print(f"-去完成: {task_name}")
262 | self.do_task(
263 | task_id, task_type="month", app_type="cloud_app"
264 | )
265 | time.sleep(2)
266 | elif task_type == "day":
267 | print("\n📆 云盘每日任务")
268 | for day in tasks:
269 | task_id = day.get("id")
270 | if task_id == 404:
271 | continue
272 | task_name = day.get("name")
273 | task_status = day.get("state", "")
274 |
275 | if task_status == "FINISH":
276 | print(f"-已完成: {task_name}")
277 | continue
278 | print(f"-去完成: {task_name}")
279 | self.do_task(task_id, task_type="day", app_type="cloud_app")
280 | elif app_type == "email_app":
281 | if task_type == "month":
282 | print("\n📆 139邮箱每月任务")
283 | for month in tasks:
284 | task_id = month.get("id")
285 | task_name = month.get("name", "")
286 | task_status = month.get("state", "")
287 | if task_id in [1004, 1005, 1015, 1020]:
288 | continue
289 |
290 | if task_status == "FINISH":
291 | print(f"-已完成: {task_name}")
292 | continue
293 | print(f"-去完成: {task_name}")
294 | self.do_task(
295 | task_id, task_type="month", app_type="email_app"
296 | )
297 | time.sleep(2)
298 | except Exception as e:
299 | print(f"错误信息:{e}")
300 |
301 | # 做任务
302 | def do_task(self, task_id, task_type, app_type):
303 | self.sleep()
304 | task_url = f"https://caiyun.feixin.10086.cn/market/signin/task/click?key=task&id={task_id}"
305 | self.send_request(task_url, headers=self.jwtHeaders, cookies=self.cookies)
306 |
307 | if app_type == "cloud_app" and task_type == "day" and task_id == 106:
308 | print("-开始上传文件,默认0kb")
309 | self.updata_file()
310 | elif task_id == 409:
311 | self.sleep()
312 | task_url = f"https://caiyun.feixin.10086.cn/market/signin/task/click?key=task2&id={task_id}"
313 | self.send_request(task_url, headers=self.jwtHeaders, cookies=self.cookies)
314 |
315 | # 上传文件
316 | def updata_file(self):
317 | url = "http://ose.caiyun.feixin.10086.cn/richlifeApp/devapp/IUploadAndDownload"
318 | headers = {
319 | "x-huawei-uploadSrc": "1",
320 | "x-ClientOprType": "11",
321 | "Connection": "keep-alive",
322 | "x-NetType": "6",
323 | "x-DeviceInfo": "6|127.0.0.1|1|10.0.1|Xiaomi|M2012K10C|CB63218727431865A48E691BFFDB49A1|02-00-00-00-00-00|android 11|1080X2272|zh||||032|",
324 | "x-huawei-channelSrc": "10000023",
325 | "x-MM-Source": "032",
326 | "x-SvcType": "1",
327 | "APP_NUMBER": self.account,
328 | "Authorization": self.Authorization,
329 | "X-Tingyun-Id": "p35OnrDoP8k;c=2;r=1955442920;u=43ee994e8c3a6057970124db00b2442c::8B3D3F05462B6E4C",
330 | "Host": "ose.caiyun.feixin.10086.cn",
331 | "User-Agent": "okhttp/3.11.0",
332 | "Content-Type": "application/xml; charset=UTF-8",
333 | "Accept": "*/*",
334 | }
335 | payload = """
336 |