From 98b87b156fcd58905b7586e7c110754447ba83c3 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 10 Mar 2022 18:10:16 +0800
Subject: [PATCH 001/105] add bahamut anime improvement scripts.
---
Bahamut/BahamutAnimeAds.js | 62 +++++++++++++++++++++++++++
Surge/Module/BahamutAnimeAds.sgmodule | 9 ++++
2 files changed, 71 insertions(+)
create mode 100644 Bahamut/BahamutAnimeAds.js
create mode 100644 Surge/Module/BahamutAnimeAds.sgmodule
diff --git a/Bahamut/BahamutAnimeAds.js b/Bahamut/BahamutAnimeAds.js
new file mode 100644
index 0000000000..8b871e2fa2
--- /dev/null
+++ b/Bahamut/BahamutAnimeAds.js
@@ -0,0 +1,62 @@
+/************************
+
+动画疯,屏蔽播放广告脚本 (黑屏25秒自动播放)
+由于动画疯强制验证观看广告时间,无法实现真正意义上的跳过广告。
+
+Surge(4.11+)模块:
+https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/BahamutAnimeAds.sgmodule
+
+QX(1.0.27+)用户请自行搭配KOP-XIAO资源解析器重写引用Surge模块。
+
+************************/
+
+let [req, rsp] = [$request, JSON.parse($response.body || '{}')];
+
+runs().catch((err) => {
+ console.log(`[BahamutAnime] ERROR: ${err.message||err}`)
+}).finally(() => $done({
+ body: JSON.stringify(rsp)
+}));
+
+async function runs() {
+ if (req.url.includes('token.php') && rsp.ad) {
+ rsp.ad.minor = [];
+ rsp.ad.major = [];
+ }
+ if (req.url.includes('m3u8.php') && rsp.message) {
+ await adURL('');
+ await new Promise(r => setTimeout(r, 25000));
+ await adURL('end');
+ rsp = await playURL();
+ }
+}
+
+function adURL(str) {
+ return new Promise((res) => {
+ get({
+ url: `https://api.gamer.com.tw/mobile_app/anime/v1/stat_ad.php?ad=${str}&schedule=0&sn=${req.url.split(/sn=(\d+)/)[1]}`,
+ headers: req.headers
+ }, (err, resp, data) => res())
+ })
+}
+
+function playURL() {
+ return new Promise((res) => {
+ get({
+ url: req.url,
+ headers: req.headers
+ }, (err, resp, data) => res(JSON.parse(data || '{}')))
+ })
+}
+
+function get(options, callback) {
+ if (typeof $task != "undefined") {
+ $task.fetch(options).then(response => {
+ response["status"] = response.statusCode
+ callback(null, response, response.body)
+ }, reason => callback(reason.error, null, null))
+ }
+ if (typeof $httpClient != "undefined") {
+ $httpClient.get(options, callback)
+ }
+}
\ No newline at end of file
diff --git a/Surge/Module/BahamutAnimeAds.sgmodule b/Surge/Module/BahamutAnimeAds.sgmodule
new file mode 100644
index 0000000000..bb2ff23df8
--- /dev/null
+++ b/Surge/Module/BahamutAnimeAds.sgmodule
@@ -0,0 +1,9 @@
+#!name=动画疯
+#!desc=屏蔽播放广告 (黑屏25秒自动播放)
+#!system=ios
+
+[Script]
+动画疯(屏蔽广告) = type=http-response,pattern=^https:\/\/api\.gamer\.com\.tw\/mobile_app\/anime\/v\d/(token|m3u8).php\?,requires-body=1,max-size=0,timeout=40,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js
+
+[MITM]
+hostname = %APPEND% api.gamer.com.tw
\ No newline at end of file
From 8a4364d132bba5061f71a3fb3b6607d0c1ad5f16 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 25 Apr 2022 19:07:06 +0800
Subject: [PATCH 002/105] update rule set.
---
Surge/WeChat.list | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Surge/WeChat.list b/Surge/WeChat.list
index 43a1ffc326..19633825bf 100644
--- a/Surge/WeChat.list
+++ b/Surge/WeChat.list
@@ -257,6 +257,7 @@ IP-CIDR6,2408:8752:0:10::/60,no-resolve
IP-CIDR6,2408:8752:0:2:30::/112,no-resolve
IP-CIDR6,2408:8752:0:30::/64,no-resolve
IP-CIDR6,2408:8752:0:F::/64,no-resolve
+IP-CIDR6,2408:8756:F50::/48,no-resolve
IP-CIDR6,2408:8756:2CF2:19::/112,no-resolve
IP-CIDR6,2408:8756:2CFF:10::/60,no-resolve
IP-CIDR6,2408:8756:3AF0:10::/112,no-resolve
@@ -293,13 +294,16 @@ IP-CIDR6,2409:8C5C:110:63::/72,no-resolve
# China Telecom IPv6 (WeChat)
IP-CIDR6,240E:928:1400:10::/112,no-resolve
+IP-CIDR6,240E:965:802:620::/60,no-resolve
IP-CIDR6,240E:93C:8:10::/60,no-resolve
IP-CIDR6,240E:95C:2003:20::/60,no-resolve
IP-CIDR6,240E:95C:3003:14::/60,no-resolve
IP-CIDR6,240E:96C:6400:700::/60,no-resolve
IP-CIDR6,240E:97C:18:601::/64,no-resolve
+IP-CIDR6,240E:97C:18:910::/60,no-resolve
IP-CIDR6,240E:97C:2F::/60,no-resolve
IP-CIDR6,240E:97D:4:1E00::/60,no-resolve
+IP-CIDR6,240E:97D:2010:100::/60,no-resolve
IP-CIDR6,240E:97F:3000:1102::/64,no-resolve
IP-CIDR6,240E:CF:8800::/56,no-resolve
IP-CIDR6,240E:E1:A800::/46,no-resolve
From a2630b4c8cd4352f8f27428d5972cb6395752634 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 25 Apr 2022 19:31:06 +0800
Subject: [PATCH 003/105] update readme.
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index a6746ec153..bd95ae495a 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@
| Application | Script name | Available | Maintenance |
| :-----------------------------------------------------: | :----------------------------------------------------------: | :----------: | :---------: |
-| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ✅(2021.7.4) | ✅ |
+| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ✅(2021.7.4) | ⚠️ |
| [百度贴吧](https://apps.apple.com/app/id477927812) | [TieBa.js](https://github.com/NobyDa/Script/blob/master/BDTieBa-DailyBonus/TieBa.js) | ✅(2021.7.4) | ❌ |
| [吾爱破解](https://www.52pojie.cn/) | [52pojie.js](https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js) | ❌(2021.11) | ❌ |
| [爱奇艺](https://apps.apple.com/cn/app/id393765873) | [iQIYI.js](https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js) | ✅(2022.1.26) | ❌ |
@@ -188,7 +188,7 @@ In the following disclaimer :
1. Do not use any scripts of the "Script project" for commercial or illegal purposes, **otherwise you will be responsible for the consequences.**
-### Nfringement
+### Infringement
1. If any company or individual believes that a scripts from "Script project" may be infringe on rights, you should promptly notify and provide proof of **identity** and **ownership**, and we will delete the scripts after receiving the relevant documents.
From cf352a5fdf03104650217e42d960286e79217d7a Mon Sep 17 00:00:00 2001
From: Durian-Life <66036934+Durian-Life@users.noreply.github.com>
Date: Sun, 1 May 2022 19:43:39 +0800
Subject: [PATCH 004/105] Update Js.conf
---
QuantumultX/Js.conf | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/QuantumultX/Js.conf b/QuantumultX/Js.conf
index 8a7767145c..53f1463423 100644
--- a/QuantumultX/Js.conf
+++ b/QuantumultX/Js.conf
@@ -1,4 +1,4 @@
-hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, www.zhihu.com, api.zhihu.com, link.zhihu.com, vip1.kuwo.cn, p.du.163.com, vsco.co, user*.zymk.cn, vni.kwaiying.com, *.my10api.com, www.luqijianggushi.com, account.wps.cn, origin-prod-phoenix.jibjab.com, api.bjxkhc.com, xy-viva.kakalili.com, ap*.intsig.net, m*.bybutter.com, api.vuevideo.net, api.picsart.c*, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.meiease.c*, trade-acs.m.taobao.com, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api.polaxiong.com
+hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, www.zhihu.com, api.zhihu.com, link.zhihu.com, vip1.kuwo.cn, p.du.163.com, vsco.co, user*.zymk.cn, vni.kwaiying.com, *.my10api.com, www.luqijianggushi.com, account.wps.cn, origin-prod-phoenix.jibjab.com, api.bjxkhc.com, xy-viva.kakalili.com, ap*.intsig.net, m*.bybutter.com, api.vuevideo.net, api.picsart.c*, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.meiease.c*, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api.polaxiong.com
# 去微信公众号广告 (By Choler)
^https?:\/\/mp\.weixin\.qq\.com\/mp\/getappmsgad url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js
@@ -81,11 +81,7 @@ https://app.bilibili.com/x/v2/(splash|search/square) url reject-200
https://api.bilibili.com/x/v2/dm/ad url reject-200
# 京东比价 (yichahucha)
-^https?://api\.m\.jd\.com/client\.action\?functionId=(wareBusiness|serverConfig|basicConfig) url script-response-body https://service.2ti.st/QuanX/Script/jd_tb_price/main.js
-
-# 淘宝比价 (yichahucha)
-^http://.+/amdc/mobileDispatch url script-request-body https://service.2ti.st/QuanX/Script/jd_tb_price/main.js
-^https?://trade-acs\.m\.taobao\.com/gw/mtop\.taobao\.detail\.getdetail url script-response-body https://service.2ti.st/QuanX/Script/jd_tb_price/main.js
+^https?://api\.m\.jd\.com/(client\.action|api)\?functionId=(wareBusiness|serverConfig|basicConfig|lite_wareBusiness|pingou_item) url script-response-body https://raw.githubusercontent.com/yichahucha/Surge/master/jd_price_lite.js
# Netflix评分 (yichahucha)
^https?://ios[-\w]*\.prod\.ftl\.netflix\.com/iosui/user/.+path=%5B%22videos%22%2C%\d+%22%2C%22summary%22%5D url script-request-header https://raw.githubusercontent.com/yichahucha/surge/master/nf_rating.js
From 8100443e32ae80e76209aae2df05f214852e7f38 Mon Sep 17 00:00:00 2001
From: Tartarus <39802246+Tartarus2014@users.noreply.github.com>
Date: Sat, 14 May 2022 16:58:13 +0800
Subject: [PATCH 005/105] Update and rename Loon_TF_Download.conf to
Loon_TF_Download.plugin
---
Loon/{Loon_TF_Download.conf => Loon_TF_Download.plugin} | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
rename Loon/{Loon_TF_Download.conf => Loon_TF_Download.plugin} (80%)
diff --git a/Loon/Loon_TF_Download.conf b/Loon/Loon_TF_Download.plugin
similarity index 80%
rename from Loon/Loon_TF_Download.conf
rename to Loon/Loon_TF_Download.plugin
index a89e06614a..2bd0b1e021 100644
--- a/Loon/Loon_TF_Download.conf
+++ b/Loon/Loon_TF_Download.plugin
@@ -1,6 +1,10 @@
# 该脚本订阅仅适用于Loon, 用于更新TestFlight App时, 提示"APP不可用"问题. 解除区域限制.
+[General]
+skip-proxy = iosapps.itunes.apple.com
+
+[Script]
http-request ^https?:\/\/testflight\.apple\.com\/v\d\/accounts\/.+?\/install$ requires-body=1,max-size=0,script-path=https://gist.githubusercontent.com/NobyDa/9be418b93afc5e9c8a8f4d28ae403cf2/raw/TF_Download.js, tag=TF区域限制解除
[MITM]
-hostname = testflight.apple.com
\ No newline at end of file
+hostname = testflight.apple.com
From 09b259e000002f845b5561c6b163e477e08abc5d Mon Sep 17 00:00:00 2001
From: Tartarus <39802246+Tartarus2014@users.noreply.github.com>
Date: Sat, 14 May 2022 17:05:55 +0800
Subject: [PATCH 006/105] Update and rename Loon_TF_Download.plugin to
Loon_TF_Download.conf
---
Loon/{Loon_TF_Download.plugin => Loon_TF_Download.conf} | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
rename Loon/{Loon_TF_Download.plugin => Loon_TF_Download.conf} (69%)
diff --git a/Loon/Loon_TF_Download.plugin b/Loon/Loon_TF_Download.conf
similarity index 69%
rename from Loon/Loon_TF_Download.plugin
rename to Loon/Loon_TF_Download.conf
index 2bd0b1e021..f7672510c3 100644
--- a/Loon/Loon_TF_Download.plugin
+++ b/Loon/Loon_TF_Download.conf
@@ -1,4 +1,5 @@
-# 该脚本订阅仅适用于Loon, 用于更新TestFlight App时, 提示"APP不可用"问题. 解除区域限制.
+#!name= Loon_TF_Download
+#!desc= 该脚本订阅仅适用于Loon, 用于更新TestFlight App时, 提示"APP不可用"问题. 解除区域限制.
[General]
skip-proxy = iosapps.itunes.apple.com
From a4f1266b449bb854b231e79552654e46012cc6cb Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 16 May 2022 18:22:14 +0800
Subject: [PATCH 007/105] Update Js.conf
---
QuantumultX/Js.conf | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/QuantumultX/Js.conf b/QuantumultX/Js.conf
index 53f1463423..7d2de30e3e 100644
--- a/QuantumultX/Js.conf
+++ b/QuantumultX/Js.conf
@@ -1,4 +1,4 @@
-hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, www.zhihu.com, api.zhihu.com, link.zhihu.com, vip1.kuwo.cn, p.du.163.com, vsco.co, user*.zymk.cn, vni.kwaiying.com, *.my10api.com, www.luqijianggushi.com, account.wps.cn, origin-prod-phoenix.jibjab.com, api.bjxkhc.com, xy-viva.kakalili.com, ap*.intsig.net, m*.bybutter.com, api.vuevideo.net, api.picsart.c*, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.meiease.c*, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api.polaxiong.com
+hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.zhihu.com, vip1.kuwo.cn, p.du.163.com, vsco.co, apigate.zymk.cn, vni.kwaiying.com, *.my10api.com, www.luqijianggushi.com, account.wps.cn, origin-prod-phoenix.jibjab.com, api.bjxkhc.com, xy-viva.kakalili.com, ap*.intsig.net, m*.bybutter.com, api.vuevideo.net, api.picsart.c*, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.meiease.c*, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api.polaxiong.com
# 去微信公众号广告 (By Choler)
^https?:\/\/mp\.weixin\.qq\.com\/mp\/getappmsgad url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js
@@ -18,7 +18,7 @@
^https?:\/\/p\.du\.163\.com\/gain\/readtime\/info\.json url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js
# 知音漫客VIP
-^https:\/\/(userpurchased|user-api)\.zymk\.cn\/v\d\/(userpurchased\/paychapters|getuserinfo)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
+^https:\/\/apigate\.zymk\.cn\/(zymk-getuserinfo-api\/v1\/getuserinfo|zymk-userpurchased-api\/v1\/userpurchased\/paychapters)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
# VSCO滤镜VIP
^https:\/\/(api\.revenuecat\.com\/v\d\/subscribers|vsco\.co\/api\/subscriptions\/\d\.\d\/user-subscriptions)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
@@ -80,8 +80,8 @@ https://api.zhihu.com/(ad|drama|fringe|commercial|market/popover|search/(top|pre
https://app.bilibili.com/x/v2/(splash|search/square) url reject-200
https://api.bilibili.com/x/v2/dm/ad url reject-200
-# 京东比价 (yichahucha)
-^https?://api\.m\.jd\.com/(client\.action|api)\?functionId=(wareBusiness|serverConfig|basicConfig|lite_wareBusiness|pingou_item) url script-response-body https://raw.githubusercontent.com/yichahucha/Surge/master/jd_price_lite.js
+# 京东比价
+^https?://api\.m\.jd\.com/client\.action\?functionId=(wareBusiness|serverConfig|basicConfig) url script-response-body https://service.2ti.st/QuanX/Script/jd_tb_price/main.js
# Netflix评分 (yichahucha)
^https?://ios[-\w]*\.prod\.ftl\.netflix\.com/iosui/user/.+path=%5B%22videos%22%2C%\d+%22%2C%22summary%22%5D url script-request-header https://raw.githubusercontent.com/yichahucha/surge/master/nf_rating.js
From 8404c2c07edb0d1c0675ee4c055488ddf93b6d32 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 16 May 2022 18:23:20 +0800
Subject: [PATCH 008/105] Update Zymh.js
---
QuantumultX/File/Zymh.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/QuantumultX/File/Zymh.js b/QuantumultX/File/Zymh.js
index 60ea25badc..d813926e16 100644
--- a/QuantumultX/File/Zymh.js
+++ b/QuantumultX/File/Zymh.js
@@ -5,19 +5,19 @@
QuantumultX:
[rewrite_local]
-^https:\/\/(userpurchased|user-api)\.zymk\.cn\/v\d\/(userpurchased\/paychapters|getuserinfo)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
+^https:\/\/apigate\.zymk\.cn\/(zymk-getuserinfo-api\/v1\/getuserinfo|zymk-userpurchased-api\/v1\/userpurchased\/paychapters)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
[mitm]
-hostname = user*.zymk.cn
+hostname = apigate.zymk.cn
***************************
Surge4 or Loon:
[Script]
-http-response ^https:\/\/(userpurchased|user-api)\.zymk\.cn\/v\d\/(userpurchased\/paychapters|getuserinfo)\/ requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
+http-response ^https:\/\/apigate\.zymk\.cn\/(zymk-getuserinfo-api\/v1\/getuserinfo|zymk-userpurchased-api\/v1\/userpurchased\/paychapters)\/ requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
[MITM]
-hostname = user*.zymk.cn
+hostname = apigate.zymk.cn
**************************/
var obj = JSON.parse($response.body);
@@ -25,4 +25,4 @@ obj.status = 0;
obj.data.isvip = 1;
obj.data.coins = 6666;
obj.data.Cgold = 6666;
-$done({body: JSON.stringify(obj)});
\ No newline at end of file
+$done({body: JSON.stringify(obj)});
From 6924ce91efa0e8dee956ca1b7fdb5fa9d74dbfd3 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 16 May 2022 18:41:38 +0800
Subject: [PATCH 009/105] Fix Douban rating query may fail in some episodes.
---
Surge/JS/Bili_Auto_Regions.js | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/Surge/JS/Bili_Auto_Regions.js b/Surge/JS/Bili_Auto_Regions.js
index 2d6eb639a1..f5fb1e89be 100644
--- a/Surge/JS/Bili_Auto_Regions.js
+++ b/Surge/JS/Bili_Auto_Regions.js
@@ -5,7 +5,7 @@
如需禁用豆瓣评分或策略通知, 可前往BoxJs设置.
BoxJs订阅地址: https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
-Update: 2022.01.26
+Update: 2022.05.16
Author: @NobyDa
Use: Surge, QuanX, Loon
@@ -40,7 +40,7 @@ Bili Region = type=http-response,pattern=^https:\/\/ap(p|i)\.bili(bili|api)\.(co
Bili Search = type=http-request,pattern=^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/x\/v\d\/search(\/type)?\?.+?%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)&,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js
[MITM]
-hostname = ap?.bilibili.com, ap?.biliapi.net
+hostname = ap?.bili*i.com, ap?.bili*i.net
****************************
Quantumult X 远程脚本配置 :
@@ -52,10 +52,10 @@ Quantumult X 远程脚本配置 :
^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/x\/v\d\/search(\/type)?\?.+?%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)& url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js
[mitm]
-hostname = ap?.bilibili.com, ap?.biliapi.net
+hostname = ap?.bili*i.com, ap?.bili*i.net
[filter_local]
-#可选, 由于qx纯tun特性, 不添加规则可能会导致脚本失效.
+#可选, 由于qx纯tun特性, 不添加规则可能会导致脚本失效. https://github.com/NobyDa/Script/issues/382
ip-cidr, 203.107.1.1/24, reject
****************************
@@ -68,7 +68,7 @@ http-response ^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/(pgc\/view\/v\d\/ap
http-request ^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/x\/v\d\/search(\/type)?\?.+?%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)& script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js, requires-body=true, tag=bili自动地区(搜索)
[Mitm]
-hostname = ap?.bilibili.com, ap?.biliapi.net
+hostname = ap?.bili*i.com, ap?.bili*i.net
***************************/
@@ -229,7 +229,7 @@ function GetRawInfo(t) {
} else {
if (/\u767b\u5f55<\/a>\u540e\u91cd\u8bd5\u3002/.test(data)) $.is403 = true;
let s = data.replace(/\n| |\d{2}/g, '')
- .match(/\[\u7535\u5f71\].+?subject-cast\">.+?<\/span>/g) || [];
+ .match(/\[(\u7535\u5f71|\u7535\u89c6\u5267)\].+?subject-cast\">.+?<\/span>/g) || [];
for (let i = 0; i < s.length; i++) {
res.push({
name: s[i].split(/\}\)">(.+?)<\/a>/)[1],
@@ -359,4 +359,4 @@ function nobyda() {
ssid,
get
}
-}
\ No newline at end of file
+}
From 5e11ea23a6a3caef82c69fc50864a9181e09ac4b Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 2 Jun 2022 22:08:24 +0800
Subject: [PATCH 010/105] Update support sub-store 1.5
---
Sub-store-parser/DataQuery.js | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/Sub-store-parser/DataQuery.js b/Sub-store-parser/DataQuery.js
index a35b1dacfe..1f61003f5e 100644
--- a/Sub-store-parser/DataQuery.js
+++ b/Sub-store-parser/DataQuery.js
@@ -5,6 +5,7 @@ Sub-Store外置流量查询脚本
该脚本基于Sub-Store, 可解决APP使用Sub-Store链接后, 没有流量通知的问题. 使用前需确认您的机场订阅是否支持流量信息. (注:节点名流量信息暂不支持)
Sub-Store订阅管理器: https://github.com/Peng-YM/Sub-Store
+最后更新: 2022.6.2
测试兼容: QuantumultX, Surge, Loon.
使用方法: 打开Sub-Store => 订阅 => 编辑 => 节点操作+ => 脚本操作 => 填入脚本链接或粘贴脚本 => 保存
@@ -16,24 +17,24 @@ Sub-Store订阅管理器: https://github.com/Peng-YM/Sub-Store
function operator(proxies) {
try {
- if ($request.headers["User-Agent"].match(/Quantumult|Surge|Loon|Decar/) && !$.raw_Name) {
- const rawInfo = $.read('subs');
- const readName = $.read('collections');
- const subtag = $request.url.match(/download\/(collection\/)?([\w-_]*)/)[2];
+ if ($request.headers["User-Agent"].match(/Quantumult|Surge|Loon|Decar/) && !obj.raw_Name) {
+ const rawInfo = obj.default.cache.subs;
+ const readName = obj.default.cache.collections;
+ const subtag = decodeURIComponent($request.url.split(/download\/(collection\/|)(.*)/)[2]);
if ($request.url.match(/\/collection\//)) { //collection subscription.
const isOpen = readName[subtag].process.map(o => o.type).indexOf("Script Operator") != -1;
for (var i = 0; i < readName[subtag].subscriptions.length; i++) {
- $.raw_Name = readName[subtag].subscriptions[i];
+ obj.raw_Name = readName[subtag].subscriptions[i];
if (!isOpen) break; //prevent queries in certain cases.
- AllSubs(rawInfo[$.raw_Name].url, $.raw_Name);
+ AllSubs(rawInfo[obj.raw_Name].url, obj.raw_Name);
}
} else { //single subscription.
- $.raw_Name = rawInfo[subtag].name;
- AllSubs(rawInfo[subtag].url, $.raw_Name);
+ obj.raw_Name = rawInfo[subtag].name;
+ AllSubs(rawInfo[subtag].url, obj.raw_Name);
}
}
} catch (err) {
- $.error(`\n🔹 订阅昵称:「 ${$.raw_Name||'未知'} 」\n🔺 查询失败:「 ${err.message||err} 」`);
+ obj.default.notify(`🔹 订阅昵称:「 ${obj.raw_Name||'未知'} 」`, ``, `🔺 查询失败:「 ${err.message||err} 」`)
} finally {
return proxies;
}
@@ -41,7 +42,7 @@ function operator(proxies) {
async function AllSubs(subsUrl, subsName) {
try { //reference to https://github.com/KOP-XIAO/QuantumultX/blob/master/Scripts/resource-parser.js
- var resp = await $.http.get(subsUrl);
+ var resp = await obj.default.http.get(subsUrl);
var sinfo = JSON.stringify(resp.headers || '').replace(/ /g, "").toLowerCase();
if (sinfo.indexOf("total=") == -1 || sinfo.indexOf("download=") == -1) throw new Error('该订阅不包含流量信息');
var total = (parseFloat(sinfo.split("total=")[1].split(",")[0]) / (1024 ** 3)).toFixed(0);
@@ -56,8 +57,8 @@ async function AllSubs(subsUrl, subsName) {
} else {
var epr = "";
}
- $.notify(`🔹 订阅昵称:「 ${subsName} 」`, epr, `🔸 已用流量:「 ${usd} GB 」\n🔸 剩余流量:「 ${left} GB 」`);
+ obj.default.notify(`🔹 订阅昵称:「 ${subsName} 」`, epr, `🔸 已用流量:「 ${usd} GB 」\n🔸 剩余流量:「 ${left} GB 」`);
} catch (er) {
- $.error(`\n🔹 订阅昵称:「 ${subsName} 」\n🔺 查询失败:「 ${er.message||er} 」`);
+ obj.default.notify(`🔹 订阅昵称:「 ${subsName} 」`, ``, `🔺 查询失败:「 ${er.message||er} 」`)
}
}
\ No newline at end of file
From c6bfe945e71e11ccddd131f53abe515cadcf16b7 Mon Sep 17 00:00:00 2001
From: paxprot <30484122+paxprot@users.noreply.github.com>
Date: Sun, 5 Jun 2022 09:25:41 +0800
Subject: [PATCH 011/105] Update WeChat.list
---
Surge/WeChat.list | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Surge/WeChat.list b/Surge/WeChat.list
index 19633825bf..97cbf92810 100644
--- a/Surge/WeChat.list
+++ b/Surge/WeChat.list
@@ -209,6 +209,7 @@ DOMAIN-KEYWORD,61.241.31.
DOMAIN-KEYWORD,61.241.44.
DOMAIN-KEYWORD,61.241.47.
DOMAIN-KEYWORD,61.241.49.
+DOMAIN-KEYWORD,43.156.86.
# WeChat Pay SDK
DOMAIN-KEYWORD,101.226.129.
@@ -354,4 +355,4 @@ DOMAIN-SUFFIX,up-hl.3g.qq.com
DOMAIN-SUFFIX,yun-hl.3g.qq.com
USER-AGENT,WeChat*
-USER-AGENT,MicroMessenger*
\ No newline at end of file
+USER-AGENT,MicroMessenger*
From 1e4ee6c2588fb2714f8b2c89c37de53ef3cd305b Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Tue, 7 Jun 2022 00:41:56 +0800
Subject: [PATCH 012/105] Update vsco.js
---
QuantumultX/File/vsco.js | 96 +++++++++++++++-------------------------
1 file changed, 35 insertions(+), 61 deletions(-)
diff --git a/QuantumultX/File/vsco.js b/QuantumultX/File/vsco.js
index d02b7872f9..081911876a 100644
--- a/QuantumultX/File/vsco.js
+++ b/QuantumultX/File/vsco.js
@@ -1,64 +1,38 @@
-/*
-VSCO 解锁高级特权
-
-***************************
-QuantumultX:
-
-[rewrite_local]
-^https:\/\/(api\.revenuecat\.com\/v\d\/subscribers|vsco\.co\/api\/subscriptions\/\d\.\d\/user-subscriptions)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
-
-[mitm]
-hostname = vsco.co, api.revenuecat.com
-
-***************************
-Surge4 or Loon:
-
-[Script]
-http-response ^https:\/\/(api\.revenuecat\.com\/v\d\/subscribers|vsco\.co\/api\/subscriptions\/\d\.\d\/user-subscriptions)\/ requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
-
-[MITM]
-hostname = vsco.co, api.revenuecat.com
-
-**************************/
-
-let obj = JSON.parse($response.body || '{}');
-
-if (obj.user_subscription) {
- obj.user_subscription["expires_on_sec"] = 1655536094;
- obj.user_subscription["expired"] = false;
- obj.user_subscription["payment_type"] = 2;
- obj.user_subscription["is_trial_period"] = true;
- obj.user_subscription["starts_on_sec"] = 1560831070;
- obj.user_subscription["is_active"] = true;
- obj.user_subscription["auto_renew"] = true;
- obj.user_subscription["last_verified_sec"] = 1560831070;
- obj.user_subscription["subscription_code"] = "VSCOANNUAL";
- obj.user_subscription["user_id"] = 54624336;
- obj.user_subscription["source"] = 1;
+/*
+ * Membership unlock for vsco & filebox
+ * Please note that you may need to reinstall app to make it work.
+ *
+ * Type: http-response (requires body)
+ * Regex: ^https?:\/\/api\.revenuecat\.com\/v\d\/subscribers\/
+ * Mitm: api.revenuecat.com
+ */
+
+const resp = {};
+const obj = JSON.parse($response.body || null);
+
+const product = {
+ "membership": "com.circles.fin.premium.yearly", //vsco
+ "filebox_pro": "com.premium.yearly" //filebox
}
-
-if (obj.subscriber) {
- obj.subscriber.subscriptions = {
- "com.circles.fin.premium.yearly": {
- "billing_issues_detected_at": null,
- "expires_date": "2030-02-18T07:52:54Z",
- "is_sandbox": false,
- "original_purchase_date": "2020-02-11T07:52:55Z",
- "period_type": "normal",
- "purchase_date": "2020-02-11T07:52:54Z",
- "store": "app_store",
- "unsubscribe_detected_at": null
- }
- };
- obj.subscriber.entitlements = {
- "membership": {
- "expires_date": "2030-02-18T07:52:54Z",
- "product_identifier": "com.circles.fin.premium.yearly",
- "purchase_date": "2020-02-11T07:52:54Z"
- }
- };
+const data = {
+ "expires_date": "2030-02-18T07:52:54Z",
+ "original_purchase_date": "2020-02-11T07:52:55Z",
+ "purchase_date": "2020-02-11T07:52:54Z"
+};
+
+if (obj && obj.subscriber) {
+ if (!obj.subscriber.subscriptions) {
+ obj.subscriber.subscriptions = {};
+ }
+ if (!obj.subscriber.entitlements) {
+ obj.subscriber.entitlements = {};
+ }
+ for (const i in product) {
+ obj.subscriber.subscriptions[product[i]] = data;
+ obj.subscriber.entitlements[i] = data;
+ obj.subscriber.entitlements[i].product_identifier = product[i];
+ }
+ resp.body = JSON.stringify(obj);
}
-$done({
- body: JSON.stringify(obj)
-});
\ No newline at end of file
+$done(resp);
From 16fee8ccf0eca3012d177272acd4f2f2b2d1ecec Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Tue, 7 Jun 2022 00:43:40 +0800
Subject: [PATCH 013/105] Update Js.conf
---
QuantumultX/Js.conf | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/QuantumultX/Js.conf b/QuantumultX/Js.conf
index 7d2de30e3e..eabe569ef5 100644
--- a/QuantumultX/Js.conf
+++ b/QuantumultX/Js.conf
@@ -1,4 +1,4 @@
-hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.zhihu.com, vip1.kuwo.cn, p.du.163.com, vsco.co, apigate.zymk.cn, vni.kwaiying.com, *.my10api.com, www.luqijianggushi.com, account.wps.cn, origin-prod-phoenix.jibjab.com, api.bjxkhc.com, xy-viva.kakalili.com, ap*.intsig.net, m*.bybutter.com, api.vuevideo.net, api.picsart.c*, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.meiease.c*, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api.polaxiong.com
+hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.zhihu.com, vip1.kuwo.cn, p.du.163.com, apigate.zymk.cn, vni.kwaiying.com, *.my10api.com, www.luqijianggushi.com, account.wps.cn, origin-prod-phoenix.jibjab.com, api.bjxkhc.com, xy-viva.kakalili.com, ap*.intsig.net, m*.bybutter.com, api.vuevideo.net, api.picsart.c*, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.meiease.c*, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api.polaxiong.com
# 去微信公众号广告 (By Choler)
^https?:\/\/mp\.weixin\.qq\.com\/mp\/getappmsgad url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js
@@ -21,7 +21,7 @@ hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.
^https:\/\/apigate\.zymk\.cn\/(zymk-getuserinfo-api\/v1\/getuserinfo|zymk-userpurchased-api\/v1\/userpurchased\/paychapters)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
# VSCO滤镜VIP
-^https:\/\/(api\.revenuecat\.com\/v\d\/subscribers|vsco\.co\/api\/subscriptions\/\d\.\d\/user-subscriptions)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
+^https?:\/\/api\.revenuecat\.com\/v\d\/subscribers\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
# 大片(Bigshot) 视频编辑器 VIP
^https:\/\/vni\.kwaiying\.com\/api\/v1\/user\/profile url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/dapian.js
From f80a7e5d266fde9da09983d1c58b77ca577683b1 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 12 Jun 2022 13:59:35 +0800
Subject: [PATCH 014/105] Update support sub-store 1.6
---
Sub-store-parser/DataQuery.js | 81 +++++++++++++++++++----------------
1 file changed, 43 insertions(+), 38 deletions(-)
diff --git a/Sub-store-parser/DataQuery.js b/Sub-store-parser/DataQuery.js
index 1f61003f5e..36af014b22 100644
--- a/Sub-store-parser/DataQuery.js
+++ b/Sub-store-parser/DataQuery.js
@@ -5,7 +5,7 @@ Sub-Store外置流量查询脚本
该脚本基于Sub-Store, 可解决APP使用Sub-Store链接后, 没有流量通知的问题. 使用前需确认您的机场订阅是否支持流量信息. (注:节点名流量信息暂不支持)
Sub-Store订阅管理器: https://github.com/Peng-YM/Sub-Store
-最后更新: 2022.6.2
+最后更新: 2022.6.12
测试兼容: QuantumultX, Surge, Loon.
使用方法: 打开Sub-Store => 订阅 => 编辑 => 节点操作+ => 脚本操作 => 填入脚本链接或粘贴脚本 => 保存
@@ -15,50 +15,55 @@ Sub-Store订阅管理器: https://github.com/Peng-YM/Sub-Store
******************************/
-function operator(proxies) {
- try {
- if ($request.headers["User-Agent"].match(/Quantumult|Surge|Loon|Decar/) && !obj.raw_Name) {
- const rawInfo = obj.default.cache.subs;
- const readName = obj.default.cache.collections;
- const subtag = decodeURIComponent($request.url.split(/download\/(collection\/|)(.*)/)[2]);
- if ($request.url.match(/\/collection\//)) { //collection subscription.
- const isOpen = readName[subtag].process.map(o => o.type).indexOf("Script Operator") != -1;
- for (var i = 0; i < readName[subtag].subscriptions.length; i++) {
- obj.raw_Name = readName[subtag].subscriptions[i];
- if (!isOpen) break; //prevent queries in certain cases.
- AllSubs(rawInfo[obj.raw_Name].url, obj.raw_Name);
+async function operator(proxies, client) {
+ if (['JSON', 'URI'].includes(client)) return proxies;
+ const $ = API('sub-store');
+ const single = $.read('subs');
+ const collection = $.read('collections');
+ const subtag = decodeURIComponent($request.url.split(/download\/(collection\/|)(.*)/)[2]);
+ const group = [];
+ if ($request.url.includes('/collection/')) { //collection subscription.
+ const deployed = collection[subtag].process.filter((c) => c.type == 'Script Operator' && c.args.content.includes('/DataQuery.js')).length;
+ for (let i = 0; i < collection[subtag].subscriptions.length; i++) {
+ if (deployed) group.push({
+ name: collection[subtag].subscriptions[i], url: single[collection[subtag].subscriptions[i]].url
+ });
}
- } else { //single subscription.
- obj.raw_Name = rawInfo[subtag].name;
- AllSubs(rawInfo[subtag].url, obj.raw_Name);
- }
+ } else { //single subscription.
+ group.push({ name: single[subtag].name, url: single[subtag].url })
}
- } catch (err) {
- obj.default.notify(`🔹 订阅昵称:「 ${obj.raw_Name||'未知'} 」`, ``, `🔺 查询失败:「 ${err.message||err} 」`)
- } finally {
+ await Promise.all(
+ group.map((c) => $.http.get(c.url)
+ .then((r) => {
+ const t = parseInfo(r);
+ $.notify(
+ `🔹 订阅昵称:「 ${c.name} 」`,
+ t.expire ? `🔹 过期时间:「 ${t.expire} 」` : ``,
+ `🔸 已用流量:「 ${t.used} GB 」\n🔸 剩余流量:「 ${t.free} GB 」`
+ );
+ })
+ .catch((e) => $.notify(`🔹 订阅昵称:「 ${c.name} 」`, ``, `🔺 查询失败:「 ${e.message || e} 」`))
+ )
+ )
return proxies;
- }
}
-async function AllSubs(subsUrl, subsName) {
- try { //reference to https://github.com/KOP-XIAO/QuantumultX/blob/master/Scripts/resource-parser.js
- var resp = await obj.default.http.get(subsUrl);
+function parseInfo(resp) { //reference to https://github.com/KOP-XIAO/QuantumultX/blob/master/Scripts/resource-parser.js
var sinfo = JSON.stringify(resp.headers || '').replace(/ /g, "").toLowerCase();
- if (sinfo.indexOf("total=") == -1 || sinfo.indexOf("download=") == -1) throw new Error('该订阅不包含流量信息');
- var total = (parseFloat(sinfo.split("total=")[1].split(",")[0]) / (1024 ** 3)).toFixed(0);
+ if (sinfo.indexOf("total=") == -1 && sinfo.indexOf("download=") == -1)
+ throw new Error('该订阅不包含流量信息');
+ // var total = (parseFloat(sinfo.split("total=")[1].split(",")[0]) / (1024 ** 3)).toFixed(0);
var usd = ((parseFloat(sinfo.indexOf("upload") != -1 ? sinfo.split("upload=")[1].split(",")[0] : "0") + parseFloat(sinfo.split("download=")[1].split(",")[0])) / (1024 ** 3)).toFixed(2);
var left = ((parseFloat(sinfo.split("total=")[1].split(",")[0]) / (1024 ** 3)) - ((parseFloat(sinfo.indexOf("upload") != -1 ? sinfo.split("upload=")[1].split(",")[0] : "0") + parseFloat(sinfo.split("download=")[1].split(",")[0])) / (1024 ** 3))).toFixed(2);
if (sinfo.indexOf("expire=") != -1) {
- var epr = new Date(parseFloat(sinfo.split("expire=")[1].split(",")[0]) * 1000);
- var year = epr.getFullYear();
- var mth = epr.getMonth() + 1 < 10 ? '0' + (epr.getMonth() + 1) : (epr.getMonth() + 1);
- var day = epr.getDate() < 10 ? "0" + (epr.getDate()) : epr.getDate();
- var epr = `🔹 过期时间:「 ${year}-${mth}-${day} 」`;
- } else {
- var epr = "";
+ var epr = new Date(parseFloat(sinfo.split("expire=")[1].split(",")[0]) * 1000);
+ var year = epr.getFullYear();
+ var mth = epr.getMonth() + 1 < 10 ? '0' + (epr.getMonth() + 1) : (epr.getMonth() + 1);
+ var day = epr.getDate() < 10 ? "0" + (epr.getDate()) : epr.getDate();
+ return { expire: `${year}-${mth}-${day}`, used: usd, free: left }
}
- obj.default.notify(`🔹 订阅昵称:「 ${subsName} 」`, epr, `🔸 已用流量:「 ${usd} GB 」\n🔸 剩余流量:「 ${left} GB 」`);
- } catch (er) {
- obj.default.notify(`🔹 订阅昵称:「 ${subsName} 」`, ``, `🔺 查询失败:「 ${er.message||er} 」`)
- }
-}
\ No newline at end of file
+ return { used: usd, free: left }
+}
+
+// https://github.com/Peng-YM/QuanX/tree/master/Tools/OpenAPI
+function ENV() { const e = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" != typeof $utils, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !e, isJSBox: e, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP(e = { baseURL: "" }) { const { isQX: t, isLoon: s, isSurge: o, isScriptable: n, isNode: i, isBrowser: r } = ENV(), u = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; const a = {}; return ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(h => a[h.toLowerCase()] = (a => (function (a, h) { h = "string" == typeof h ? { url: h } : h; const d = e.baseURL; d && !u.test(h.url || "") && (h.url = d ? d + h.url : h.url), h.body && h.headers && !h.headers["Content-Type"] && (h.headers["Content-Type"] = "application/x-www-form-urlencoded"); const l = (h = { ...e, ...h }).timeout, c = { onRequest: () => { }, onResponse: e => e, onTimeout: () => { }, ...h.events }; let f, p; if (c.onRequest(a, h), t) f = $task.fetch({ method: a, ...h }); else if (s || o || i) f = new Promise((e, t) => { (i ? require("request") : $httpClient)[a.toLowerCase()](h, (s, o, n) => { s ? t(s) : e({ statusCode: o.status || o.statusCode, headers: o.headers, body: n }) }) }); else if (n) { const e = new Request(h.url); e.method = a, e.headers = h.headers, e.body = h.body, f = new Promise((t, s) => { e.loadString().then(s => { t({ statusCode: e.response.statusCode, headers: e.response.headers, body: s }) }).catch(e => s(e)) }) } else r && (f = new Promise((e, t) => { fetch(h.url, { method: a, headers: h.headers, body: h.body }).then(e => e.json()).then(t => e({ statusCode: t.status, headers: t.headers, body: t.data })).catch(t) })); const y = l ? new Promise((e, t) => { p = setTimeout(() => (c.onTimeout(), t(`${a} URL: ${h.url} exceeds the timeout ${l} ms`)), l) }) : null; return (y ? Promise.race([y, f]).then(e => (clearTimeout(p), e)) : f).then(e => c.onResponse(e)) })(h, a))), a } function API(e = "untitled", t = !1) { const { isQX: s, isLoon: o, isSurge: n, isNode: i, isJSBox: r, isScriptable: u } = ENV(); return new class { constructor(e, t) { this.name = e, this.debug = t, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (i) { return { fs: require("fs") } } return null })(), this.initCache(); Promise.prototype.delay = function (e) { return this.then(function (t) { return ((e, t) => new Promise(function (s) { setTimeout(s.bind(null, t), e) }))(e, t) }) } } initCache() { if (s && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (o || n) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), i) { let e = "root.json"; this.node.fs.existsSync(e) || this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.root = {}, e = `${this.name}.json`, this.node.fs.existsSync(e) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.cache = {}) } } persistCache() { const e = JSON.stringify(this.cache, null, 2); s && $prefs.setValueForKey(e, this.name), (o || n) && $persistentStore.write(e, this.name), i && (this.node.fs.writeFileSync(`${this.name}.json`, e, { flag: "w" }, e => console.log(e)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, e => console.log(e))) } write(e, t) { if (this.log(`SET ${t}`), -1 !== t.indexOf("#")) { if (t = t.substr(1), n || o) return $persistentStore.write(e, t); if (s) return $prefs.setValueForKey(e, t); i && (this.root[t] = e) } else this.cache[t] = e; this.persistCache() } read(e) { return this.log(`READ ${e}`), -1 === e.indexOf("#") ? this.cache[e] : (e = e.substr(1), n || o ? $persistentStore.read(e) : s ? $prefs.valueForKey(e) : i ? this.root[e] : void 0) } delete(e) { if (this.log(`DELETE ${e}`), -1 !== e.indexOf("#")) { if (e = e.substr(1), n || o) return $persistentStore.write(null, e); if (s) return $prefs.removeValueForKey(e); i && delete this.root[e] } else delete this.cache[e]; this.persistCache() } notify(e, t = "", a = "", h = {}) { const d = h["open-url"], l = h["media-url"]; if (s && $notify(e, t, a, h), n && $notification.post(e, t, a + `${l ? "\n多媒体:" + l : ""}`, { url: d }), o) { let s = {}; d && (s.openUrl = d), l && (s.mediaUrl = l), "{}" === JSON.stringify(s) ? $notification.post(e, t, a) : $notification.post(e, t, a, s) } if (i || u) { const s = a + (d ? `\n点击跳转: ${d}` : "") + (l ? `\n多媒体: ${l}` : ""); if (r) { require("push").schedule({ title: e, body: (t ? t + "\n" : "") + s }) } else console.log(`${e}\n${t}\n${s}\n\n`) } } log(e) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(e)}`) } info(e) { console.log(`[${this.name}] INFO: ${this.stringify(e)}`) } error(e) { console.log(`[${this.name}] ERROR: ${this.stringify(e)}`) } wait(e) { return new Promise(t => setTimeout(t, e)) } done(e = {}) { s || o || n ? $done(e) : i && !r && "undefined" != typeof $context && ($context.headers = e.headers, $context.statusCode = e.statusCode, $context.body = e.body) } stringify(e) { if ("string" == typeof e || e instanceof String) return e; try { return JSON.stringify(e, null, 2) } catch (e) { return "[object Object]" } } }(e, t) }
\ No newline at end of file
From 735063ee4f47252737aee7dd31227aaa366f6505 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 13 Jun 2022 21:01:40 +0800
Subject: [PATCH 015/105] Fix broad match issues #396
---
QuantumultX/File/vsco.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/QuantumultX/File/vsco.js b/QuantumultX/File/vsco.js
index 081911876a..fbe0c2a926 100644
--- a/QuantumultX/File/vsco.js
+++ b/QuantumultX/File/vsco.js
@@ -9,6 +9,7 @@
const resp = {};
const obj = JSON.parse($response.body || null);
+const app = /VSCO|Fileb(ox|all)/.test($request.headers['User-Agent']);
const product = {
"membership": "com.circles.fin.premium.yearly", //vsco
@@ -20,7 +21,7 @@ const data = {
"purchase_date": "2020-02-11T07:52:54Z"
};
-if (obj && obj.subscriber) {
+if (app && obj && obj.subscriber) {
if (!obj.subscriber.subscriptions) {
obj.subscriber.subscriptions = {};
}
From 762148ef83eeb6bb93cd973de33760b455c17a41 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Wed, 15 Jun 2022 21:16:31 +0800
Subject: [PATCH 016/105] Fix HTTP/2 issues.
---
Bilibili-DailyBonus/Manga.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Bilibili-DailyBonus/Manga.js b/Bilibili-DailyBonus/Manga.js
index 44afbfc9a8..9012cee0ad 100644
--- a/Bilibili-DailyBonus/Manga.js
+++ b/Bilibili-DailyBonus/Manga.js
@@ -81,7 +81,7 @@ function GetCookie() {
var CookieKey = "CookieBM";
var regex = /SESSDATA=.+?;/;
if ($request.headers) {
- var header = $request.headers['Cookie'] ? $request.headers['Cookie'] : "";
+ var header = Object.keys($request.headers).reduce((t, i) => (t[i.toLowerCase()] = $request.headers[i], t), {})['cookie'] || '';
if (header.indexOf("SESSDATA=") != -1) {
var CookieValue = regex.exec(header)[0];
if ($.getdata(CookieKey)) {
From 55e057346306268aeb91dec2d082c5eea63e64e9 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 16 Jun 2022 17:12:20 +0800
Subject: [PATCH 017/105] Minor improvement.
---
Sub-store-parser/DataQuery.js | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/Sub-store-parser/DataQuery.js b/Sub-store-parser/DataQuery.js
index 36af014b22..22e96bc1fc 100644
--- a/Sub-store-parser/DataQuery.js
+++ b/Sub-store-parser/DataQuery.js
@@ -17,7 +17,7 @@ Sub-Store订阅管理器: https://github.com/Peng-YM/Sub-Store
async function operator(proxies, client) {
if (['JSON', 'URI'].includes(client)) return proxies;
- const $ = API('sub-store');
+ const $ = $substore; //OpenAPI in Sub-Store
const single = $.read('subs');
const collection = $.read('collections');
const subtag = decodeURIComponent($request.url.split(/download\/(collection\/|)(.*)/)[2]);
@@ -63,7 +63,4 @@ function parseInfo(resp) { //reference to https://github.com/KOP-XIAO/Quantumult
return { expire: `${year}-${mth}-${day}`, used: usd, free: left }
}
return { used: usd, free: left }
-}
-
-// https://github.com/Peng-YM/QuanX/tree/master/Tools/OpenAPI
-function ENV() { const e = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" != typeof $utils, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !e, isJSBox: e, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP(e = { baseURL: "" }) { const { isQX: t, isLoon: s, isSurge: o, isScriptable: n, isNode: i, isBrowser: r } = ENV(), u = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; const a = {}; return ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(h => a[h.toLowerCase()] = (a => (function (a, h) { h = "string" == typeof h ? { url: h } : h; const d = e.baseURL; d && !u.test(h.url || "") && (h.url = d ? d + h.url : h.url), h.body && h.headers && !h.headers["Content-Type"] && (h.headers["Content-Type"] = "application/x-www-form-urlencoded"); const l = (h = { ...e, ...h }).timeout, c = { onRequest: () => { }, onResponse: e => e, onTimeout: () => { }, ...h.events }; let f, p; if (c.onRequest(a, h), t) f = $task.fetch({ method: a, ...h }); else if (s || o || i) f = new Promise((e, t) => { (i ? require("request") : $httpClient)[a.toLowerCase()](h, (s, o, n) => { s ? t(s) : e({ statusCode: o.status || o.statusCode, headers: o.headers, body: n }) }) }); else if (n) { const e = new Request(h.url); e.method = a, e.headers = h.headers, e.body = h.body, f = new Promise((t, s) => { e.loadString().then(s => { t({ statusCode: e.response.statusCode, headers: e.response.headers, body: s }) }).catch(e => s(e)) }) } else r && (f = new Promise((e, t) => { fetch(h.url, { method: a, headers: h.headers, body: h.body }).then(e => e.json()).then(t => e({ statusCode: t.status, headers: t.headers, body: t.data })).catch(t) })); const y = l ? new Promise((e, t) => { p = setTimeout(() => (c.onTimeout(), t(`${a} URL: ${h.url} exceeds the timeout ${l} ms`)), l) }) : null; return (y ? Promise.race([y, f]).then(e => (clearTimeout(p), e)) : f).then(e => c.onResponse(e)) })(h, a))), a } function API(e = "untitled", t = !1) { const { isQX: s, isLoon: o, isSurge: n, isNode: i, isJSBox: r, isScriptable: u } = ENV(); return new class { constructor(e, t) { this.name = e, this.debug = t, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (i) { return { fs: require("fs") } } return null })(), this.initCache(); Promise.prototype.delay = function (e) { return this.then(function (t) { return ((e, t) => new Promise(function (s) { setTimeout(s.bind(null, t), e) }))(e, t) }) } } initCache() { if (s && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (o || n) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), i) { let e = "root.json"; this.node.fs.existsSync(e) || this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.root = {}, e = `${this.name}.json`, this.node.fs.existsSync(e) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.cache = {}) } } persistCache() { const e = JSON.stringify(this.cache, null, 2); s && $prefs.setValueForKey(e, this.name), (o || n) && $persistentStore.write(e, this.name), i && (this.node.fs.writeFileSync(`${this.name}.json`, e, { flag: "w" }, e => console.log(e)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, e => console.log(e))) } write(e, t) { if (this.log(`SET ${t}`), -1 !== t.indexOf("#")) { if (t = t.substr(1), n || o) return $persistentStore.write(e, t); if (s) return $prefs.setValueForKey(e, t); i && (this.root[t] = e) } else this.cache[t] = e; this.persistCache() } read(e) { return this.log(`READ ${e}`), -1 === e.indexOf("#") ? this.cache[e] : (e = e.substr(1), n || o ? $persistentStore.read(e) : s ? $prefs.valueForKey(e) : i ? this.root[e] : void 0) } delete(e) { if (this.log(`DELETE ${e}`), -1 !== e.indexOf("#")) { if (e = e.substr(1), n || o) return $persistentStore.write(null, e); if (s) return $prefs.removeValueForKey(e); i && delete this.root[e] } else delete this.cache[e]; this.persistCache() } notify(e, t = "", a = "", h = {}) { const d = h["open-url"], l = h["media-url"]; if (s && $notify(e, t, a, h), n && $notification.post(e, t, a + `${l ? "\n多媒体:" + l : ""}`, { url: d }), o) { let s = {}; d && (s.openUrl = d), l && (s.mediaUrl = l), "{}" === JSON.stringify(s) ? $notification.post(e, t, a) : $notification.post(e, t, a, s) } if (i || u) { const s = a + (d ? `\n点击跳转: ${d}` : "") + (l ? `\n多媒体: ${l}` : ""); if (r) { require("push").schedule({ title: e, body: (t ? t + "\n" : "") + s }) } else console.log(`${e}\n${t}\n${s}\n\n`) } } log(e) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(e)}`) } info(e) { console.log(`[${this.name}] INFO: ${this.stringify(e)}`) } error(e) { console.log(`[${this.name}] ERROR: ${this.stringify(e)}`) } wait(e) { return new Promise(t => setTimeout(t, e)) } done(e = {}) { s || o || n ? $done(e) : i && !r && "undefined" != typeof $context && ($context.headers = e.headers, $context.statusCode = e.statusCode, $context.body = e.body) } stringify(e) { if ("string" == typeof e || e instanceof String) return e; try { return JSON.stringify(e, null, 2) } catch (e) { return "[object Object]" } } }(e, t) }
\ No newline at end of file
+}
\ No newline at end of file
From 20238e7ea47e4d5f7df805c79d314f55fb594c17 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 16 Jun 2022 21:20:22 +0800
Subject: [PATCH 018/105] Loon plugin suffix name replace
---
Loon/Loon_GetCookie.conf | 18 ------------------
Loon/Loon_GetCookie.plugin | 19 +++++++++++++++++++
Loon/Loon_GetTask.conf | 17 -----------------
Loon/Loon_TF_Download.conf | 4 ++--
Loon/Loon_TF_Download.plugin | 14 ++++++++++++++
5 files changed, 35 insertions(+), 37 deletions(-)
delete mode 100644 Loon/Loon_GetCookie.conf
create mode 100644 Loon/Loon_GetCookie.plugin
delete mode 100644 Loon/Loon_GetTask.conf
create mode 100644 Loon/Loon_TF_Download.plugin
diff --git a/Loon/Loon_GetCookie.conf b/Loon/Loon_GetCookie.conf
deleted file mode 100644
index d8cbb77abe..0000000000
--- a/Loon/Loon_GetCookie.conf
+++ /dev/null
@@ -1,18 +0,0 @@
-# 该订阅仅适用于Loon, 用于解决任务脚本的Cookie获取, 具体获取方法请看相关脚本内注释.
-# 您可在使用后手动将其禁用, 以避免无意义的MITM.
-# URL : https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_GetCookie.conf
-
-http-request ^https:\/\/(api\.m|me-api|ms\.jr)\.jd\.com\/(client\.action\?functionId=signBean|user_new\/info\/GetJDUserInfoUnion\?|gw\/generic\/hy\/h5\/m\/appSign\?) script-path=https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js, requires-body=1, tag=获取京东Cookie
-
-http-request ^https:\/\/passport\.iqiyi\.com\/apis\/user\/info\.action script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js, tag=爱奇艺Cookie
-
-http-request ^https:\/\/www\.52pojie\.cn\/home\.php\? script-path=https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js, tag=吾爱破解Cookie
-
-http-request ^https:\/\/passport\.biligame\.com\/api\/login\/sso.+?version%22%3A%22(3|4|5) script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js, tag=哔哩漫画Cookie
-
-http-request ^https?:\/\/(c\.tieba\.baidu\.com|180\.97\.\d+\.\d+)\/c\/s\/login script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js, tag=百度贴吧Cookie
-
-http-request ^https?:\/\/api\.kkmh\.com\/v\d\/passport\/user script-path=https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js, tag=快看漫画Cookie
-
-[MITM]
-hostname = passport.iqiyi.com, www.52pojie.cn, api.m.jd.com, ms.jr.jd.com, me-api.jd.com, passport.biligame.com, c.tieba.baidu.com, api.kkmh.com
\ No newline at end of file
diff --git a/Loon/Loon_GetCookie.plugin b/Loon/Loon_GetCookie.plugin
new file mode 100644
index 0000000000..6088a5aaae
--- /dev/null
+++ b/Loon/Loon_GetCookie.plugin
@@ -0,0 +1,19 @@
+#!name= NobyDa签到脚本Cookie获取
+#!desc= 包括京东、哔哩漫画、贴吧、快看、爱奇艺,具体方法请看脚本注释;建议使用后手动将该插件禁用, 以避免无意义的MITM。
+#!author= NobyDa
+#!homepage= https://github.com/NobyDa/Script/tree/master
+#!icon= https://raw.githubusercontent.com/github/explore/80688e429a7d4ef2fca1e82350fe8e3517d3494d/topics/javascript/javascript.png
+
+[Script]
+http-request ^https:\/\/(api\.m|me-api|ms\.jr)\.jd\.com\/(client\.action\?functionId=signBean|user_new\/info\/GetJDUserInfoUnion\?|gw\/generic\/hy\/h5\/m\/appSign\?) script-path=https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js, requires-body=1, tag=京东签到Cookie
+
+http-request ^https:\/\/passport\.iqiyi\.com\/apis\/user\/info\.action script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js, tag=爱奇艺Cookie
+
+http-request ^https:\/\/app\.bilibili\.com\/x\/v2\/account\/myinfo script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js, tag=哔哩漫画Cookie
+
+http-request ^https?:\/\/(c\.tieba\.baidu\.com|180\.97\.\d+\.\d+)\/c\/s\/login script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js, tag=百度贴吧Cookie
+
+http-request ^https?:\/\/api\.kkmh\.com\/v\d\/passport\/user script-path=https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js, tag=快看漫画Cookie
+
+[MITM]
+hostname = passport.iqiyi.com, api.m.jd.com, ms.jr.jd.com, me-api.jd.com, app.bilibili.com, c.tieba.baidu.com, api.kkmh.com
\ No newline at end of file
diff --git a/Loon/Loon_GetTask.conf b/Loon/Loon_GetTask.conf
deleted file mode 100644
index 33b9548895..0000000000
--- a/Loon/Loon_GetTask.conf
+++ /dev/null
@@ -1,17 +0,0 @@
-# 该签到脚本订阅仅适用于Loon, 您需要获取Cookie后方可使用.
-# URL : https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_GetTask.conf
-
-# 京东签到, 执行时间: 0:05
-cron "5 0 * * *" ,timeout=30, script-path=https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js,tag=京东签到
-
-# 爱奇艺, 执行时间: 08:00
-cron "0 8 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js,tag=爱奇艺
-
-# 哔哩哔哩漫画, 执行时间: 08:02
-cron "2 8 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js,tag=哔哩哔哩漫画
-
-# 百度贴吧, 执行时间: 08:03-08:05 (3次)
-cron "3,4,5 8 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js,tag=百度贴吧(客户端)
-
-# 快看漫画, 执行时间: 08:06
-cron "6 8 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js, tag=快看漫画
\ No newline at end of file
diff --git a/Loon/Loon_TF_Download.conf b/Loon/Loon_TF_Download.conf
index f7672510c3..d01ea5174d 100644
--- a/Loon/Loon_TF_Download.conf
+++ b/Loon/Loon_TF_Download.conf
@@ -1,5 +1,5 @@
-#!name= Loon_TF_Download
-#!desc= 该脚本订阅仅适用于Loon, 用于更新TestFlight App时, 提示"APP不可用"问题. 解除区域限制.
+#!name= TestFlight区域限制解除
+#!desc= ‼️‼️‼️‼️‼️ 该URL已弃用,将在一段时间后删除;请把URL后缀 .conf 更换为 .plugin
[General]
skip-proxy = iosapps.itunes.apple.com
diff --git a/Loon/Loon_TF_Download.plugin b/Loon/Loon_TF_Download.plugin
new file mode 100644
index 0000000000..628dde3490
--- /dev/null
+++ b/Loon/Loon_TF_Download.plugin
@@ -0,0 +1,14 @@
+#!name= TestFlight区域限制解除
+#!desc= 该Loon插件用以解决更新TestFlight App时, 提示"APP不可用"问题.
+#!author= NobyDa
+#!homepage= https://github.com/NobyDa/Script/tree/master
+#!icon= https://cdn.jsdelivr.net/gh/NobyDa/mini@master/Color/testflight.png
+
+[General]
+skip-proxy = iosapps.itunes.apple.com
+
+[Script]
+http-request ^https?:\/\/testflight\.apple\.com\/v\d\/accounts\/.+?\/install$ requires-body=1,max-size=0,script-path=https://gist.githubusercontent.com/NobyDa/9be418b93afc5e9c8a8f4d28ae403cf2/raw/TF_Download.js, tag=TF区域限制解除
+
+[MITM]
+hostname = testflight.apple.com
From 705fd0e38967a440b26c472df281f50c8e545383 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 16 Jun 2022 21:33:09 +0800
Subject: [PATCH 019/105] Add Bahamut ad script to Loon plugin
---
Loon/Loon_Bahamut_ADS.plugin | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100644 Loon/Loon_Bahamut_ADS.plugin
diff --git a/Loon/Loon_Bahamut_ADS.plugin b/Loon/Loon_Bahamut_ADS.plugin
new file mode 100644
index 0000000000..ca1888d4eb
--- /dev/null
+++ b/Loon/Loon_Bahamut_ADS.plugin
@@ -0,0 +1,11 @@
+#!name= 巴哈姆特动画疯
+#!desc= 该Loon插件用以屏蔽动画疯播放广告 (由于强制验证观看广告时间,故以黑屏25秒的方式屏蔽)
+#!author= NobyDa
+#!homepage= https://github.com/NobyDa/Script/tree/master
+#!icon= https://raw.githubusercontent.com/NobyDa/mini/master/Color/bahamutGame.png
+
+[Script]
+http-response ^https:\/\/api\.gamer\.com\.tw\/mobile_app\/anime\/v\d/(token|m3u8).php\? requires-body=1,timeout=40,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js, tag=屏蔽动画疯广告
+
+[MITM]
+hostname = api.gamer.com.tw
\ No newline at end of file
From 992172320cfe81cd73898b9c3d2f7ff2f59bd0db Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 16 Jun 2022 21:44:38 +0800
Subject: [PATCH 020/105] Update readme
---
README.md | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index bd95ae495a..4f8ba398d5 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
## TOC
+- [TOC](#toc)
- [Script desc](#script-desc)
- [Daily bonus scripts](#daily-bonus-scripts)
- [Functionality-enhancing scripts](#functionality-enhancing-scripts)
@@ -12,7 +13,7 @@
- [Decrypt](#decrypt)
- [Privacy](#privacy)
- [Commercial](#commercial)
- - [Nfringement](#nfringement)
+ - [Infringement](#infringement)
- [Liability](#liability)
- [Change](#change)
- [Special thanks to](#special-thanks-to)
@@ -154,10 +155,9 @@ The above random generated device ID can be found at the bottom of Quantumult X
| File name | Desc | Type | Maintenance |
| :----------------------------------------------------------: | :-----------------------------: | :------------------: | :---------: |
-| [Loon_GetCookie.conf](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_GetCookie.conf) | Please see the desc in file. | Subscription scripts | ✅ |
-| [Loon_GetTask.conf](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_GetTask.conf) | Timed script task subscription. | Subscription scripts | ✅ |
-| [Loon_TF_Download.conf](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Download.conf) | Please see the desc in file. | Subscription scripts | ✅ |
-
+| [Loon_GetCookie.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_GetCookie.plugin) | Please see the desc in file. | Plugin | ✅ |
+| [Loon_TF_Download.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Download.plugin) | Please see the desc in file. | Plugin | ✅ |
+| [Loon_Bahamut_ADS.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_Bahamut_ADS.plugin) | Remove Bahamut anime Ads | Plugin | ✅ |
---
From b1bf8ad650bbc02441ae4aa130fa559441e3bd92 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 18 Jun 2022 18:39:54 +0800
Subject: [PATCH 021/105] Bug fixes.
---
KuaiKan-DailyBonus/KKMH.js | 11 ++++++-----
iQIYI-DailyBonus/iQIYI.js | 4 ++--
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/KuaiKan-DailyBonus/KKMH.js b/KuaiKan-DailyBonus/KKMH.js
index 8b60c637a7..c7a94517c6 100644
--- a/KuaiKan-DailyBonus/KKMH.js
+++ b/KuaiKan-DailyBonus/KKMH.js
@@ -1,7 +1,7 @@
/*
快看漫画签到脚本
-更新时间: 2021.9.22
+更新时间: 2022.06.18
脚本兼容: QuantumultX, Surge4, Loon, Node.js
电报频道: @NobyDa
问题反馈: @NobyDa_bot
@@ -174,13 +174,14 @@ function GiftPack(type) {
function GetCookie() {
const RA = $.getdata("@KKMH.COOKIE")
const TM = $.getdata("@KKMH.TIME")
- if (JSON.stringify($request.headers).match(/session=/)) {
- if (RA != $request.headers['Cookie']) {
- if ($.setdata($request.headers['Cookie'], "@KKMH.COOKIE")) {
+ const CK = $request.headers['Cookie'] || $request.headers['cookie'];
+ if (JSON.stringify($request.headers).match(/session=/) && CK) {
+ if (RA != CK) {
+ if ($.setdata(CK, "@KKMH.COOKIE")) {
$.setdata(JSON.stringify(Date.now()), "@KKMH.TIME")
if (!TM || TM && (Date.now() - TM) / 1000 >= 21600) {
$.msg(`${RA?`更新`:`首次写入`}${$.name}Cookie成功 🎉`, "", "", imgUrl)
- } else if (RA.match(/uid=\d+/)[0] == $request.headers['Cookie'].match(/uid=\d+/)[0]) {
+ } else if (RA.match(/uid=\d+/)[0] == CK.match(/uid=\d+/)[0]) {
$.log(`\n更新${$.name}Cookie成功! 🎉\n检测到频繁通知, 已转为输出日志`)
} else {
$.msg(`更新${$.name}Cookie成功 🎉`, "", "", imgUrl)
diff --git a/iQIYI-DailyBonus/iQIYI.js b/iQIYI-DailyBonus/iQIYI.js
index bbec201bcc..e92d78bcc9 100644
--- a/iQIYI-DailyBonus/iQIYI.js
+++ b/iQIYI-DailyBonus/iQIYI.js
@@ -1,7 +1,7 @@
/*
爱奇艺会员签到脚本
-更新时间: 2022.2.7
+更新时间: 2022.06.18
脚本兼容: QuantumultX, Surge4, Loon, JsBox, Node.js
电报频道: @NobyDa
问题反馈: @NobyDa_bot
@@ -416,7 +416,7 @@ function GetCookie() {
$nobyda.notify(`写入爱奇艺Cookie失败`, "", "请更新脚本配置(URL正则/MITM)");
return
}
- var CKA = $request.headers['Cookie'];
+ var CKA = $request.headers['Cookie'] || $request.headers['cookie'];;
var iQIYI = CKA && CKA.includes("P00001=") && CKA.includes("P00003=") && CKA;
var RA = $nobyda.read("CookieQY")
if (CKA && iQIYI) {
From 4d5df9b99c277db1477bb5c6a4fcbd71d9dcb3aa Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 18 Jun 2022 18:57:56 +0800
Subject: [PATCH 022/105] Fixed 52pojie.cn daily bonus script
---
52pojie-DailyBonus/52pojie.js | 104 +++++++++++++-----------------
Loon/Loon_GetCookie.plugin | 6 +-
NobyDa_BoxJs.json | 2 +-
QuantumultX/Js_Remote_Cookie.conf | 2 +-
4 files changed, 51 insertions(+), 63 deletions(-)
diff --git a/52pojie-DailyBonus/52pojie.js b/52pojie-DailyBonus/52pojie.js
index 52572b8bdc..c7e169b703 100644
--- a/52pojie-DailyBonus/52pojie.js
+++ b/52pojie-DailyBonus/52pojie.js
@@ -1,7 +1,7 @@
/*
吾爱破解签到脚本
-更新时间: 2021.09.22
+更新时间: 2022.6.18
脚本兼容: QuantumultX, Surge, Loon, Node.js
电报频道: @NobyDa
问题反馈: @NobyDa_bot
@@ -16,7 +16,7 @@ QX, Surge, Loon说明:
************************
Node.js说明:
************************
-需自行安装"got"与"tough-cookie"模块. 例: npm install got tough-cookie -g
+需自行安装"got"与"iconv-lite"模块. 例: npm install got iconv-lite -g
抓取Cookie说明:
浏览器打开 https://www.52pojie.cn/home.php 登录账号后, 开启抓包软件并刷新页面.
@@ -69,79 +69,65 @@ http-request https:\/\/www\.52pojie\.cn\/home\.php\? script-path=https://raw.git
hostname= www.52pojie.cn
*/
-var $ = new Env('吾爱破解');
-var date = new Date()
-if (typeof $request != "undefined") {
+const $ = API('nobyda_52pojie');
+const date = new Date();
+const reqData = {
+ url: 'https://www.52pojie.cn/home.php?mod=task&do=apply&id=2',
+ headers: {
+ Cookie: CookieWA || $.read("COOKIE"),
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0",
+ }
+};
+if ($.env.isRequest) {
GetCookie()
+} else if (!reqData.headers.Cookie) {
+ $.notify('吾爱破解', ``, `未填写/未获取Cookie!`);
+} else if (!reqData.headers.Cookie.includes('_auth=')) {
+ $.notify('吾爱破解', ``, `Cookie关键授权字段缺失, 需重新获取!`);
} else {
- checkin()
-}
-
-function checkin() {
- $.get({
- url: 'https://www.52pojie.cn/home.php?mod=task&do=apply&id=2&mobile=no',
- headers: {
- Cookie: CookieWA || $.getdata("CookieWA"),
- }
- }, async function(error, response, data) {
- if (error && !data) {
- $.msgBody = `签到请求失败 ‼️‼️\n${error}`
- } else {
- if (data.match(/(ÒÑÍê³É|\u606d\u559c\u60a8|��̳�š��ᰮ�ƽ�)/)) {
+ $.http.put(reqData)
+ .then((resp) => {
+ if (resp.body.match(/(ÒÑÍê³É|\u606d\u559c\u60a8|��̳�š��ᰮ�ƽ�)/)) {
$.msgBody = date.getMonth() + 1 + "月" + date.getDate() + "日, 签到成功 🎉"
- } else if (data.match(/(ÄúÒÑ|\u4e0b\u671f\u518d\u6765|>��Ǹ������)/)) {
+ } else if (resp.body.match(/(ÄúÒÑ|\u4e0b\u671f\u518d\u6765|>��Ǹ������)/)) {
$.msgBody = date.getMonth() + 1 + "月" + date.getDate() + "日, 已签过 ⚠️"
- } else if (data.match(/(ÏȵǼ|\u9700\u8981\u5148\u767b\u5f55|�Ҫ�ȵ�¼���ܼ�)/)) {
+ } else if (resp.body.match(/(ÏȵǼ|\u9700\u8981\u5148\u767b\u5f55|�Ҫ�ȵ�¼���ܼ�)/)) {
$.msgBody = "签到失败, Cookie失效 ‼️‼️"
- } else if (response.statusCode == 403) {
+ } else if (resp.statusCode == 403) {
$.msgBody = "服务器暂停签到 ⚠️"
} else {
$.msgBody = "脚本待更新 ‼️‼️"
}
- }
- if (barkKey) {
- await BarkNotify($, barkKey, $.name, $.msgBody);
- }
- $.msg($.name, ``, $.msgBody);
- $.done();
- })
+ })
+ .catch((err) => ($.msgBody = `签到失败 ‼️‼️\n${err || err.message}`))
+ .finally(async () => {
+ if (barkKey) {
+ await BarkNotify($, barkKey, '吾爱破解', $.msgBody);
+ }
+ $.notify('吾爱破解', ``, $.msgBody);
+ $.done();
+ })
}
function GetCookie() {
- try {
- if ($request.headers && $request.url.match(/www\.52pojie\.cn/)) {
- var CookieName = "吾爱破解";
- var CookieKey = "CookieWA";
- var CookieValue = $request.headers['Cookie'];
- if ($.getdata(CookieKey)) {
- if ($.getdata(CookieKey) != CookieValue) {
- var cookie = $.setdata(CookieValue, CookieKey);
- if (!cookie) {
- $.msg("", "", "更新" + CookieName + "Cookie失败 ‼️");
- } else {
- $.msg("", "", "更新" + CookieName + "Cookie成功 🎉");
- }
- }
- } else {
- var cookie = $.setdata(CookieValue, CookieKey);
- if (!cookie) {
- $.msg("", "", "首次写入" + CookieName + "Cookie失败 ‼️");
- } else {
- $.msg("", "", "首次写入" + CookieName + "Cookie成功 🎉");
- }
- }
+ const TM = $.read("TIME");
+ const CK = $request.headers['Cookie'] || $request.headers['cookie'];
+ if (CK && CK.includes('_auth=')) {
+ $.write(CK, "COOKIE");
+ if (!TM || TM && (Date.now() - TM) / 1000 >= 21600) {
+ $.notify("吾爱破解", "", `写入Cookie成功 🎉`);
+ $.write(JSON.stringify(Date.now()), "TIME");
} else {
- $.msg("写入Cookie失败", "", "请检查匹配URL或配置内脚本类型 ‼️");
+ $.info(`吾爱破解\n写入Cookie成功 🎉`)
}
- } catch (eor) {
- $.msg("写入Cookie失败", "", "未知错误 ‼️")
- $.log(JSON.stringify(eor) + "\n" + eor + "\n" + JSON.stringify($request.headers))
+ } else {
+ $.info(`吾爱破解\n写入Cookie失败, 关键值缺失`)
}
- $.done();
+ $.done()
}
//Bark APP notify
-async function BarkNotify(c,k,t,b){for(let i=0;i<3;i++){console.log(`🔷Bark notify >> Start push (${i+1})`);const s=await new Promise((n)=>{c.post({url:'https://api.day.app/push',headers:{'Content-Type':'application/json'},body:JSON.stringify({title:t,body:b,device_key:k,ext_params:{group:t}})},(e,r,d)=>r&&r.status==200?n(1):n(d||e))});if(s===1){console.log('✅Push success!');break}else{console.log(`❌Push failed! >> ${s.message||s}`)}}};
+async function BarkNotify(c, k, t, b) { for (let i = 0; i < 3; i++) { console.log(`🔷Bark notify >> Start push (${i + 1})`); const s = await new Promise((n) => { c.post({ url: 'https://api.day.app/push', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: t, body: b, device_key: k, ext_params: { group: t } }) }, (e, r, d) => r && r.status == 200 ? n(1) : n(d || e)) }); if (s === 1) { console.log('✅Push success!'); break } else { console.log(`❌Push failed! >> ${s.message || s}`) } } };
-//Compatible code from https://github.com/chavyleung/scripts/blob/master/Env.min.js
-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,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("","")}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("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(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{const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();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){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));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}}}};this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r)));let h=["",""];h.push(e),s&&h.push(s),i&&h.push(i),console.log(h.join("\n")),this.logs=this.logs.concat(h)}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("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)}
\ No newline at end of file
+//https://github.com/Peng-YM/QuanX/tree/master/Tools/OpenAPI
+function ENV() { const e = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !e, isJSBox: e, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP(e = { baseURL: "" }) { function t(t, a) { a = "string" == typeof a ? { url: a } : a; const h = e.baseURL; h && !d.test(a.url || "") && (a.url = h ? h + a.url : a.url), a.body && a.headers && !a.headers["Content-Type"] && (a.headers["Content-Type"] = "application/x-www-form-urlencoded"), a = { ...e, ...a }; const c = a.timeout, l = { onRequest: () => { }, onResponse: e => e, onTimeout: () => { }, ...a.events }; let f, y; if (l.onRequest(t, a), s) f = $task.fetch({ method: t, ...a }); else if (o || n) f = new Promise((e, s) => { $httpClient[t.toLowerCase()](a, (t, o, n) => { t ? s(t) : e({ statusCode: o.status || o.statusCode, headers: o.headers, body: n }) }) }); else if (r) { const e = require("got"), s = require("iconv-lite"); f = new Promise((o, n) => { e[t.toLowerCase()](a).then(e => o({ statusCode: e.statusCode, headers: e.headers, body: s.decode(e.rawBody, "utf-8") })).catch(n) }) } else if (i) { const e = new Request(a.url); e.method = t, e.headers = a.headers, e.body = a.body, f = new Promise((t, s) => { e.loadString().then(s => { t({ statusCode: e.response.statusCode, headers: e.response.headers, body: s }) }).catch(e => s(e)) }) } else u && (f = new Promise((e, s) => { fetch(a.url, { method: t, headers: a.headers, body: a.body }).then(e => e.json()).then(t => e({ statusCode: t.status, headers: t.headers, body: t.data })).catch(s) })); const p = c ? new Promise((e, s) => { y = setTimeout(() => (l.onTimeout(), s(`${t} URL: ${a.url} exceeds the timeout ${c} ms`)), c) }) : null; return (p ? Promise.race([p, f]).then(e => (clearTimeout(y), e)) : f).then(e => l.onResponse(e)) } const { isQX: s, isLoon: o, isSurge: n, isScriptable: i, isNode: r, isBrowser: u } = ENV(), a = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"], d = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/, h = {}; return a.forEach(e => h[e.toLowerCase()] = (s => t(e, s))), h } function API(e = "untitled", t = !1) { const { isQX: s, isLoon: o, isSurge: n, isNode: i, isJSBox: r, isScriptable: u } = ENV(); return new class { constructor(e, t) { this.name = e, this.debug = t, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (i) { const e = require("fs"); return { fs: e } } return null })(), this.initCache(); const s = (e, t) => new Promise(function (s) { setTimeout(s.bind(null, t), e) }); Promise.prototype.delay = function (e) { return this.then(function (t) { return s(e, t) }) } } initCache() { if (s && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (o || n) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), i) { let e = "root.json"; this.node.fs.existsSync(e) || this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.root = {}, e = `${this.name}.json`, this.node.fs.existsSync(e) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.cache = {}) } } persistCache() { const e = JSON.stringify(this.cache, null, 2); s && $prefs.setValueForKey(e, this.name), (o || n) && $persistentStore.write(e, this.name), i && (this.node.fs.writeFileSync(`${this.name}.json`, e, { flag: "w" }, e => console.log(e)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, e => console.log(e))) } write(e, t) { if (this.log(`SET ${t}`), -1 !== t.indexOf("#")) { if (t = t.substr(1), n || o) return $persistentStore.write(e, t); if (s) return $prefs.setValueForKey(e, t); i && (this.root[t] = e) } else this.cache[t] = e; this.persistCache() } read(e) { return this.log(`READ ${e}`), -1 === e.indexOf("#") ? this.cache[e] : (e = e.substr(1), n || o ? $persistentStore.read(e) : s ? $prefs.valueForKey(e) : i ? this.root[e] : void 0) } delete(e) { if (this.log(`DELETE ${e}`), -1 !== e.indexOf("#")) { if (e = e.substr(1), n || o) return $persistentStore.write(null, e); if (s) return $prefs.removeValueForKey(e); i && delete this.root[e] } else delete this.cache[e]; this.persistCache() } notify(e, t = "", a = "", d = {}) { const h = d["open-url"], c = d["media-url"]; if (s && $notify(e, t, a, d), n && $notification.post(e, t, a + `${c ? "\n多媒体:" + c : ""}`, { url: h }), o) { let s = {}; h && (s.openUrl = h), c && (s.mediaUrl = c), "{}" === JSON.stringify(s) ? $notification.post(e, t, a) : $notification.post(e, t, a, s) } if (i || u) { const s = a + (h ? `\n点击跳转: ${h}` : "") + (c ? `\n多媒体: ${c}` : ""); if (r) { const o = require("push"); o.schedule({ title: e, body: (t ? t + "\n" : "") + s }) } else console.log(`${e}\n${t}\n${s}\n\n`) } } log(e) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(e)}`) } info(e) { console.log(`[${this.name}] INFO: ${this.stringify(e)}`) } error(e) { console.log(`[${this.name}] ERROR: ${this.stringify(e)}`) } wait(e) { return new Promise(t => setTimeout(t, e)) } done(e = {}) { s || o || n ? $done(e) : i && !r && "undefined" != typeof $context && ($context.headers = e.headers, $context.statusCode = e.statusCode, $context.body = e.body) } stringify(e) { if ("string" == typeof e || e instanceof String) return e; try { return JSON.stringify(e, null, 2) } catch (e) { return "[object Object]" } } }(e, t) }
\ No newline at end of file
diff --git a/Loon/Loon_GetCookie.plugin b/Loon/Loon_GetCookie.plugin
index 6088a5aaae..c57764ed24 100644
--- a/Loon/Loon_GetCookie.plugin
+++ b/Loon/Loon_GetCookie.plugin
@@ -1,5 +1,5 @@
#!name= NobyDa签到脚本Cookie获取
-#!desc= 包括京东、哔哩漫画、贴吧、快看、爱奇艺,具体方法请看脚本注释;建议使用后手动将该插件禁用, 以避免无意义的MITM。
+#!desc= 包括京东、哔哩漫画、贴吧、快看、吾爱、爱奇艺,获取方法请看脚本注释;建议使用后手动将该插件禁用, 以避免无意义的MITM。
#!author= NobyDa
#!homepage= https://github.com/NobyDa/Script/tree/master
#!icon= https://raw.githubusercontent.com/github/explore/80688e429a7d4ef2fca1e82350fe8e3517d3494d/topics/javascript/javascript.png
@@ -15,5 +15,7 @@ http-request ^https?:\/\/(c\.tieba\.baidu\.com|180\.97\.\d+\.\d+)\/c\/s\/login s
http-request ^https?:\/\/api\.kkmh\.com\/v\d\/passport\/user script-path=https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js, tag=快看漫画Cookie
+http-request https:\/\/www\.52pojie\.cn\/home\.php\? script-path=https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js, tag=吾爱破解Cookie
+
[MITM]
-hostname = passport.iqiyi.com, api.m.jd.com, ms.jr.jd.com, me-api.jd.com, app.bilibili.com, c.tieba.baidu.com, api.kkmh.com
\ No newline at end of file
+hostname = passport.iqiyi.com, api.m.jd.com, ms.jr.jd.com, me-api.jd.com, app.bilibili.com, c.tieba.baidu.com, api.kkmh.com, www.52pojie.cn
\ No newline at end of file
diff --git a/NobyDa_BoxJs.json b/NobyDa_BoxJs.json
index 8eccecae21..02c8e1d43d 100644
--- a/NobyDa_BoxJs.json
+++ b/NobyDa_BoxJs.json
@@ -294,7 +294,7 @@
}, {
"id": "52poje",
"name": "吾爱破解",
- "keys": ["CookieWA"],
+ "keys": ["nobyda_52pojie"],
"descs_html": [
"
获取Cookie以及脚本配置请查看脚本注释 "
],
diff --git a/QuantumultX/Js_Remote_Cookie.conf b/QuantumultX/Js_Remote_Cookie.conf
index 4031559cc4..7b4865ef8a 100644
--- a/QuantumultX/Js_Remote_Cookie.conf
+++ b/QuantumultX/Js_Remote_Cookie.conf
@@ -6,7 +6,7 @@ hostname = passport.iqiyi.com, www.52pojie.cn, c.tieba.baidu.com, api.m.jd.com,
^https:\/\/passport\.iqiyi\.com\/apis\/user\/info\.action url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
# 吾爱破解 cookie
-https:\/\/www\.52pojie\.cn\/home\.php\?mod=space url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js
+https:\/\/www\.52pojie\.cn\/home\.php\? url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js
# 百度贴吧 cookie
https?:\/\/(c\.tieba\.baidu\.com|180\.97\.\d+\.\d+)\/c\/s\/login url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js
From 0ab27f2630ce9ba9fee092765f056f878cfc2cea Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 18 Jun 2022 18:59:28 +0800
Subject: [PATCH 023/105] Copywriting adjustments
---
README.md | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/README.md b/README.md
index 4f8ba398d5..a0a96b3af8 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@
-> **Please note that the scripts or rewrite rules described below need to open MITM and trust the certificate.**
+> **Please note that the scripts or rewrite rules described below may require MITM to be enabled, and the generated root certificate needs to be manually installed and trusted in the system.**
## Script desc
@@ -29,13 +29,13 @@
| Application | Script name | Available | Maintenance |
| :-----------------------------------------------------: | :----------------------------------------------------------: | :----------: | :---------: |
-| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ✅(2021.7.4) | ⚠️ |
-| [百度贴吧](https://apps.apple.com/app/id477927812) | [TieBa.js](https://github.com/NobyDa/Script/blob/master/BDTieBa-DailyBonus/TieBa.js) | ✅(2021.7.4) | ❌ |
-| [吾爱破解](https://www.52pojie.cn/) | [52pojie.js](https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js) | ❌(2021.11) | ❌ |
-| [爱奇艺](https://apps.apple.com/cn/app/id393765873) | [iQIYI.js](https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js) | ✅(2022.1.26) | ❌ |
-| [快看漫画](https://apps.apple.com/app/id906936224) | [KKMH.js](https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js) | ✅(2022.1.26) | ✅ |
-| [哔哩哔哩漫画](https://apps.apple.com/app/id1426252715) | [Manga.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js) | ✅(2022.1.26) | ✅ |
-| [巴哈姆特](https://www.gamer.com.tw/) | [BahamutDailyBonus.js](https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js) | ✅(2022.1.26) | ✅ |
+| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ⚠️(2022.6.18) | ⚠️ |
+| [百度贴吧](https://apps.apple.com/app/id477927812) | [TieBa.js](https://github.com/NobyDa/Script/blob/master/BDTieBa-DailyBonus/TieBa.js) | ✅(2021.6.18) | ❌ |
+| [吾爱破解](https://www.52pojie.cn/) | [52pojie.js](https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js) | ✅(2022.6.18) | ❌ |
+| [爱奇艺](https://apps.apple.com/cn/app/id393765873) | [iQIYI.js](https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js) | ✅(2022.6.18) | ❌ |
+| [快看漫画](https://apps.apple.com/app/id906936224) | [KKMH.js](https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js) | ✅(2022.6.18) | ✅ |
+| [哔哩哔哩漫画](https://apps.apple.com/app/id1426252715) | [Manga.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js) | ✅(2022.6.18) | ✅ |
+| [巴哈姆特](https://www.gamer.com.tw/) | [BahamutDailyBonus.js](https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js) | ✅(2022.6.18) | ✅ |
------
@@ -165,32 +165,32 @@ The above random generated device ID can be found at the bottom of Quantumult X
## Disclaimer
```
-In the following disclaimer :
+In the following disclaimer:
-"Script project" specifically refers to the open source scripts and rules in https://github.com/NobyDa/Script/tree/master
+The "Script project" refers specifically to the open source scripts and rules in https://github.com/NobyDa/Script/tree/master
-"NobyDa" specifically refers to the author and owner in https://github.com/NobyDa/Script/tree/master
+The "NobyDa" refers specifically to the author and owner in https://github.com/NobyDa/Script/tree/master
```
### Decrypt
-1. Any unlocking and decryption analysis scripts involved in the "Script project" are for resource sharing and study purposes only.
+1. Any unlocking and decryption analysis scripts involved in "Script project" are for resource sharing and study purposes only.
-2. Legality, accuracy, completeness, and validity cannot be guaranteed. **Please judge for yourself based on the actual situation.**
+2. Legality, accuracy, completeness and validity cannot be guaranteed. **Please make your own judgment based on the actual situation.**
-3. You must completely delete the scripts involving decryption from your computer or phone within **24 hours** of downloading.
+3. You must completely delete the scripts involved decryption from your computer or phone within **24 hours** of downloading.
### Privacy
-1. Any user who indirectly uses any of the scripts in the "Script project", including but not limited to violating relevant laws and regulations or establishing VPS to spread, **NobyDa is not responsible for any privacy leakage or other consequences caused by this.**
+1. Any user who indirectly uses any of the scripts in "Script project", including but not limited to violating relevant laws and regulations or establishing VPS to spread, **NobyDa is not responsible for any privacy breach or other consequences arising therefrom.**
### Commercial
-1. Do not use any scripts of the "Script project" for commercial or illegal purposes, **otherwise you will be responsible for the consequences.**
+1. Do not use any scripts of "Script project" for commercial or illegal purposes, **otherwise you will be responsible for the consequences.**
### Infringement
-1. If any company or individual believes that a scripts from "Script project" may be infringe on rights, you should promptly notify and provide proof of **identity** and **ownership**, and we will delete the scripts after receiving the relevant documents.
+1. If any company or individual believes that the scripts in "Script project" may be infringe on rights, you should promptly notify and provide proof of **identity** and proof of **ownership**, and we will delete the relevant scripts upon receipt of the relevant documents.
### Liability
@@ -198,9 +198,9 @@ In the following disclaimer :
### Change
-1. Anyone viewing or using the scripts of the "Script project" in any way, directly or indirectly, should read this statement carefully. And NobyDa reserves the right to change or supplement this disclaimer at any time.
+1. Anyone viewing or using in any way, directly or indirectly, the scripts in "Script project" should read this disclaimer carefully, and NobyDa reserves the right to change or supplement this disclaimer at any time.
-2. **Once you use or copy any related scripts of the "Script project", you will be deemed to have accepted this disclaimer.**
+2. **Once you view, use or copy any of the related scripts in "Script project", you will be deemed to have accepted this disclaimer.**
## Special thanks to
From 5ec0a35e01420f089b8820fff20af874d95b887e Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 18 Jun 2022 21:15:41 +0800
Subject: [PATCH 024/105] Fixed iqiyi cookie issues
---
Loon/Loon_GetCookie.plugin | 2 +-
QuantumultX/Js_Remote_Cookie.conf | 2 +-
Surge/Module/GetCookie.sgmodule | 2 +-
iQIYI-DailyBonus/iQIYI.js | 8 ++++----
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/Loon/Loon_GetCookie.plugin b/Loon/Loon_GetCookie.plugin
index c57764ed24..07e2b29849 100644
--- a/Loon/Loon_GetCookie.plugin
+++ b/Loon/Loon_GetCookie.plugin
@@ -7,7 +7,7 @@
[Script]
http-request ^https:\/\/(api\.m|me-api|ms\.jr)\.jd\.com\/(client\.action\?functionId=signBean|user_new\/info\/GetJDUserInfoUnion\?|gw\/generic\/hy\/h5\/m\/appSign\?) script-path=https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js, requires-body=1, tag=京东签到Cookie
-http-request ^https:\/\/passport\.iqiyi\.com\/apis\/user\/info\.action script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js, tag=爱奇艺Cookie
+http-request ^https:\/\/passport\.iqiyi\.com\/apis\/user\/ script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js, tag=爱奇艺Cookie
http-request ^https:\/\/app\.bilibili\.com\/x\/v2\/account\/myinfo script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js, tag=哔哩漫画Cookie
diff --git a/QuantumultX/Js_Remote_Cookie.conf b/QuantumultX/Js_Remote_Cookie.conf
index 7b4865ef8a..327b0ea006 100644
--- a/QuantumultX/Js_Remote_Cookie.conf
+++ b/QuantumultX/Js_Remote_Cookie.conf
@@ -3,7 +3,7 @@
hostname = passport.iqiyi.com, www.52pojie.cn, c.tieba.baidu.com, api.m.jd.com, ms.jr.jd.com, me-api.jd.com, passport.biligame.com, api.kkmh.com
# 爱奇艺 cookie
-^https:\/\/passport\.iqiyi\.com\/apis\/user\/info\.action url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
+^https:\/\/passport\.iqiyi\.com\/apis\/user\/ url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
# 吾爱破解 cookie
https:\/\/www\.52pojie\.cn\/home\.php\? url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js
diff --git a/Surge/Module/GetCookie.sgmodule b/Surge/Module/GetCookie.sgmodule
index a6df79a7a1..26494b2e66 100644
--- a/Surge/Module/GetCookie.sgmodule
+++ b/Surge/Module/GetCookie.sgmodule
@@ -6,7 +6,7 @@
吾爱Cookie = type=http-request,pattern=https:\/\/www\.52pojie\.cn\/home\.php\?,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js
-爱奇艺Cookie = type=http-request,pattern=^https:\/\/passport\.iqiyi\.com\/apis\/user\/info\.action,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
+爱奇艺Cookie = type=http-request,pattern=^https:\/\/passport\.iqiyi\.com\/apis\/user\/,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
哔哩漫画Cookie = type=http-request,pattern=^https:\/\/passport\.biligame\.com\/api\/login\/sso.+?version%22%3A%22(3|4|5),script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js
diff --git a/iQIYI-DailyBonus/iQIYI.js b/iQIYI-DailyBonus/iQIYI.js
index e92d78bcc9..9e4efa0c8a 100644
--- a/iQIYI-DailyBonus/iQIYI.js
+++ b/iQIYI-DailyBonus/iQIYI.js
@@ -40,7 +40,7 @@ QuantumultX 远程脚本配置:
[rewrite_local]
# 获取Cookie
-^https:\/\/passport\.iqiyi\.com\/apis\/user\/info\.action url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
+^https:\/\/passport\.iqiyi\.com\/apis\/user\/ url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
[mitm]
hostname= passport.iqiyi.com
@@ -51,7 +51,7 @@ Surge 4.2.0+ 脚本配置:
[Script]
爱奇艺签到 = type=cron,cronexp=0 9 * * *,timeout=120,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
-爱奇艺获取Cookie = type=http-request,pattern=^https:\/\/passport\.iqiyi\.com\/apis\/user\/info\.action,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
+爱奇艺获取Cookie = type=http-request,pattern=^https:\/\/passport\.iqiyi\.com\/apis\/user\/,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
[MITM]
hostname= passport.iqiyi.com
@@ -65,7 +65,7 @@ Loon 2.1.0+ 脚本配置:
cron "0 9 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
# 获取Cookie
-http-request ^https:\/\/passport\.iqiyi\.com\/apis\/user\/info\.action script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
+http-request ^https:\/\/passport\.iqiyi\.com\/apis\/user\/ script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
[Mitm]
hostname= passport.iqiyi.com
@@ -412,7 +412,7 @@ function getTaskRewards(task) {
}
function GetCookie() {
- if (!$request.url.includes("/apis/user/info.action")) {
+ if (!$request.url.includes("iqiyi.com")) {
$nobyda.notify(`写入爱奇艺Cookie失败`, "", "请更新脚本配置(URL正则/MITM)");
return
}
From 595f2d63b5c1faf5856a30b3b95630b4022359e6 Mon Sep 17 00:00:00 2001
From: Extra2001
Date: Sun, 19 Jun 2022 10:53:27 +0800
Subject: [PATCH 025/105] Update CamScanner Expire Time (#401)
---
Surge/JS/CamScanner.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Surge/JS/CamScanner.js b/Surge/JS/CamScanner.js
index 84f4adeb70..a88c128b62 100644
--- a/Surge/JS/CamScanner.js
+++ b/Surge/JS/CamScanner.js
@@ -30,5 +30,5 @@ hostname = ap*.intsig.net
**************************/
let obj = JSON.parse($response.body);
-obj = {"data":{"psnl_vip_property":{"expiry":"1643731200"}}};
+obj = {"data":{"psnl_vip_property":{"expiry":"1687017600"}}};
$done({body: JSON.stringify(obj)});
\ No newline at end of file
From 035f8e3f3e90be31c592e7703fae8ad5e2254fec Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Wed, 22 Jun 2022 18:30:55 +0800
Subject: [PATCH 026/105] Add TestFlight account script.
---
Loon/Loon_TF_Account.plugin | 14 ++
NobyDa_BoxJs.json | 19 +-
Surge/Module/TestFlightAccount.sgmodule | 11 +
TestFlight/TestFlightAccount.js | 289 ++++++++++++++++++++++++
4 files changed, 332 insertions(+), 1 deletion(-)
create mode 100644 Loon/Loon_TF_Account.plugin
create mode 100644 Surge/Module/TestFlightAccount.sgmodule
create mode 100644 TestFlight/TestFlightAccount.js
diff --git a/Loon/Loon_TF_Account.plugin b/Loon/Loon_TF_Account.plugin
new file mode 100644
index 0000000000..7482b3101f
--- /dev/null
+++ b/Loon/Loon_TF_Account.plugin
@@ -0,0 +1,14 @@
+#!name=TestFlight账户管理
+#!desc=自动存储/合并多个TestFlight账户列表, 并可分享/导出TestFlight APP.
+#!author= NobyDa
+#!homepage= https://github.com/NobyDa/Script/tree/master
+#!icon= https://cdn.jsdelivr.net/gh/NobyDa/mini@master/Color/testflight.png
+
+[General]
+skip-proxy = iosapps.itunes.apple.com
+
+[Script]
+http-request ^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/ requires-body=1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js,tag=TestFlight账户管理
+
+[MITM]
+hostname = testflight.apple.com
\ No newline at end of file
diff --git a/NobyDa_BoxJs.json b/NobyDa_BoxJs.json
index 02c8e1d43d..bf7430ac54 100644
--- a/NobyDa_BoxJs.json
+++ b/NobyDa_BoxJs.json
@@ -325,7 +325,7 @@
"name": "巴哈姆特",
"keys": ["@ND_BAHA.ID", "@ND_BAHA.PW", "@ND_BAHA.TOTP", "@ND_BAHA.GUILD", "@ND_BAHA.ANSWER", "@ND_BAHA.ADS"],
"descs_html": [
- "获取Cookie以及脚本配置请查看脚本注释 "
+ ""
],
"settings": [{
"id": "@ND_BAHA.ADS",
@@ -436,6 +436,23 @@
"author": "@NobyDa",
"repo": "https://github.com/NobyDa/Script/blob/master/Surge/JS/Bili_Auto_Regions.js",
"icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/bilibili.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/bilibili.png"]
+ }, {
+ "id": "TestFlightAccount",
+ "name": "TestFlight账户管理",
+ "keys": ["TESTFLIGHT-ACCOUNT"],
+ "descs_html": [
+ "脚本说明以及配置请查看脚本注释 "
+ ],
+ "settings": [{
+ "id": "@TESTFLIGHT-ACCOUNT.Debug",
+ "name": "开发者模式",
+ "val": false,
+ "type": "boolean",
+ "desc": "用于调试脚本, 一般用户请勿开启."
+ }],
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/blob/master/TestFlight/TestFlightAccount.js",
+ "icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/testflight.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/testflight.png"]
}],
"task": [{
"config": "0 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js, tag=京东签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/jd.png",
diff --git a/Surge/Module/TestFlightAccount.sgmodule b/Surge/Module/TestFlightAccount.sgmodule
new file mode 100644
index 0000000000..8822e7c46f
--- /dev/null
+++ b/Surge/Module/TestFlightAccount.sgmodule
@@ -0,0 +1,11 @@
+#!name=TestFlight账户管理
+#!desc=自动存储/合并多个TestFlight账户列表, 并可导出/分享TestFlight APP.
+
+[General]
+skip-proxy = %APPEND% iosapps.itunes.apple.com
+
+[Script]
+TestFlight账户管理 = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/,requires-body=1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js
+
+[MITM]
+hostname = %APPEND% testflight.apple.com
\ No newline at end of file
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
new file mode 100644
index 0000000000..403a4f9a01
--- /dev/null
+++ b/TestFlight/TestFlightAccount.js
@@ -0,0 +1,289 @@
+/********************************
+TestFlight账户管理脚本
+
+脚本作者: @NobyDa
+脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
+主要功能:
+1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
+
+2. 账户内单个测试版APP允许多方共享:
+ - 导出:点击测试版APP -> 底部开发者许可协议 -> 复制密钥并分享给对方
+ - 导入:TestFlight 右上角"兑换" -> 粘贴密钥 -> 弹出保存成功通知后刷新APP列表
+ - 多方共享为实验性功能,双方都需要使用该脚本; 该功能主要解决某些APP的TF名额稀缺的问题
+
+请注意,该脚本已经与"TF区域限制解除脚本"合并,如需使用该脚本请务必禁用它,否则可能出现APP安装异常
+
+*********************************
+Surge4 添加脚本:
+*********************************
+
+Surge模块地址:
+https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightAccount.sgmodule
+
+
+*********************************
+QuantumultX 添加脚本:
+*********************************
+
+QuantumultX重写引用地址:
+https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js
+
+注:以上引用地址需要打开并使用KOP-XIAO资源解析器,如没有解析器请使用脚本配置:
+
+[rewrite_local]
+^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/ url script-analyze-echo-response https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js
+
+[mitm]
+hostname = testflight.apple.com
+
+*********************************
+Loon 添加脚本:
+*********************************
+
+Loon插件地址:
+https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Account.plugin
+
+*********************************/
+
+const $ = API("TESTFLIGHT-ACCOUNT");
+$.env.isNode ? $request = $.read('Request') : null;
+const [arr, obj, req, rsp] = [[], new Map(), $request, {}];
+const [k1, k2, k3] = ['x-session-id', 'x-request-id', 'x-session-digest'];
+const [list, appList] = [$.read('AccountList') || {}, $.read('AppList') || {}];
+$.debug = $.read('Debug') === 'true';
+
+runs()
+ .catch(e => $.error(e.error || e.message || e))
+ .finally(() => {
+ const ret = {
+ ...{
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ },
+ ...rsp
+ };
+ ret.headers = formatHeaders(ret.headers); //compatible with HTTP/2
+ ret.status = $.env.isQX ? `HTTP/1.1 ${ret.status}` : ret.status;
+ delete ret.headers['content-length'];
+ delete ret.headers['transfer-encoding']; //prevent issues in qx
+ $.log(`Return to client: ${$.stringify(ret)}`);
+ $.done($.env.isQX ? ret : {
+ response: ret
+ })
+ });
+
+async function runs() {
+ // Object.keys(list).map(a => delete list[a].only)
+ req.headers = formatHeaders(req.headers); //compatible with HTTP/2
+ const appID = req.url.split(/\/apps\/(\d+)/)[1];
+ const build = req.url.split(/\/builds\/(\d+)/)[1];
+ const other = /\/(accept|withdraw|devices|session|notifications|status)/.test(req.url);
+ if (/accounts\/[a-z0-9-]{36}\/apps$/.test(req.url)) {
+ const acc = SaveAccount(req.url.split(/\/([a-z0-9-]{36})\//)[1]);
+ const all = await Promise.all(Object.keys(acc).map(QueryAppList));
+ const out = arr.filter(r => !r.previouslyTested && !obj.has(r.appAdamId) && obj.set(r.appAdamId, 1));
+ $.log(`Final app: ${$.stringify(out.map(i => i.name))}`);
+ if (out.length) {
+ rsp.body = $.stringify({
+ data: out,
+ error: null
+ });
+ $.write(out.reduce((l, v) => (l[v.appAdamId] = v.aid, l), {}), 'AppList');
+ }
+ } else if (/\/install$/.test(req.url) && req.body) {
+ req.body = JSON.parse(req.body);
+ req.body.storefrontId = '143380-1,29'; //prevent regional restrictions
+ req.body = $.stringify(req.body);
+ } else if (/\d+\/eula$/.test(req.url)) {
+ rsp.body = $.stringify(ShareAccount(appID, build));
+ } else if (/\/[A-Z]{200,}\/redeem$/.test(req.url)) {
+ rsp.body = ExternalAccount(req.url.split(/\/([A-Z]+)\/redeem$/)[1]);
+ }
+ if (!rsp.body) {
+ await QueryFallback(!other && appList[appID]);
+ }
+}
+
+function SaveAccount(id, part, o) {
+ if (!list[id]) {
+ list[id] = {};
+ const text = `Account ID "${id}" saved. (total ${Object.keys(list).length}) 🎉`;
+ $.notify('TestFlight Account', '', text);
+ $.info(text);
+ };
+ list[id][k1] = (part || req.headers)[k1];
+ list[id][k2] = (part || req.headers)[k2];
+ list[id][k3] = (part || req.headers)[k3];
+ if (o) {
+ if (list[id].only) {
+ list[id].only.push(o);
+ $.notify('TestFlight Account', '', `App ID "${o}" saved 🎉`);
+ } else {
+ list[id].only = [o];
+ }
+ }
+ return $.write(list, 'AccountList'), list;
+}
+
+function formatHeaders(h) {
+ return Object.keys(h).reduce((t, i) => (t[i.toLowerCase()] = h[i], t), {})
+}
+
+function ChangeHeaders(id) {
+ const re = JSON.parse(JSON.stringify(req)); //easy deep copy
+ if (id) {
+ $.log(`Request header replaced, using "${id}"`);
+ re.headers[k1] = list[id][k1];
+ re.headers[k2] = list[id][k2];
+ re.headers[k3] = list[id][k3];
+ re.url = re.url.replace(/\/[a-z0-9-]{36}\//, `/${id}/`);
+ }
+ if (typeof $Shadowrocket !== 'undefined') {
+ re.proxy = false; //prevent shadowrocket infinite loop
+ }
+ delete re.headers['if-none-match']; //prevent 304
+ delete re.headers['content-length'];
+ $.log(`Send request: ${$.stringify(re)}`);
+ return re;
+}
+
+function QueryFallback(o) {
+ return $.http[req.method.toLowerCase()](ChangeHeaders(o))
+ .then(r => {
+ $.log(`Received response: status=${r.statusCode}, body=${Boolean(r.body)}`);
+ [rsp.status, rsp.headers, rsp.body] = [r.statusCode, r.headers, r.body];
+ if (/\/apps\/\d+\/builds\/\d+$/.test(req.url) && r.body) { //beta app page
+ r.body = JSON.parse(r.body);
+ r.body.data.builds.map(e => e.eula = `https://testflight.apple.com/v1/apps/${e.appAdamId}/builds/${e.id}/eula`);
+ rsp.body = $.stringify(r.body);
+ }
+ })
+ .catch(e => $.error(`Response failed: ${e.error || e.message || e}`))
+}
+
+function QueryAppList(o) {
+ return $.http[req.method.toLowerCase()](ChangeHeaders(o))
+ .then(r => {
+ const m = req.url.includes(o);
+ $.log(`Received response: status=${r.statusCode}, body=${Boolean(r.body)}, account=${o}, main=${m}`);
+ if (m) {
+ [rsp.status, rsp.headers, rsp.body] = [r.statusCode, r.headers, r.body];
+ }
+ if (r.statusCode == 401) {
+ throw new Error('Key expires');
+ }
+ const res = JSON.parse(r.body || '{}');
+ $.log(`Account "${o}" app list: ${$.stringify((res.data || []).map(i => i.name))}`);
+ return (res.data || []).filter(i => (i.aid = o, !list[o].only || list[o].only.includes(String(i.appAdamId))))
+ .map(p => arr[m ? 'unshift' : 'push'](p))
+ }).catch(e => { //surge cannot get 401 in apple domain
+ if (/Key expires|NSURLErrorDomain.+?-1012/.test(e.error || e.message || e)) {
+ if (list[o].InvalidKey >= 2) { //prevent misjudgment
+ delete list[o];
+ } else {
+ list[o].InvalidKey = (list[o].InvalidKey || 0) + 1;
+ }
+ $.write(list, 'AccountList');
+ e = `key expired ⚠️`;
+ $.notify('TestFlight Account', '', `Account ID "${o}" ${e}`);
+ };
+ $.error(`Account "${o}" response failed: ${e.error || e.message || e}`);
+ })
+}
+
+function ExternalAccount(key) {
+ try {
+ const k = JSON.parse(letterDecode(key));
+ $.log(`Raw data: ${key}\nDecode data: ${$.stringify(k)}`);
+ if (!k.appID || !k.accID || !k.key[k1] || !k.key[k2] || !k.key[k3]) {
+ throw new Error('Missing data');
+ } else if (appList[k.appID]) {
+ $.notify('TestFlight Account', '', `Failed, app already exists ⚠️`);
+ } else {
+ const save = SaveAccount(k.accID, k.key, k.appID);
+ }
+ } catch (e) {
+ const text = `External account parse failed`;
+ $.notify('TestFlight Account', '', `${text} ⚠️`);
+ $.error(`${text}: ${e.message || e}`);
+ }
+ return '{}'
+}
+
+function ShareAccount(appID, bid) {
+ const raw = $.stringify({
+ appID: appID,
+ accID: appList[appID],
+ key: list[appList[appID]]
+ });
+ const key = letterEncode(raw);
+ const disclaimer = `
+请注意,使用"共享"功能时,请务必仔细阅读以下声明 ‼️
+请注意,使用"共享"功能时,请务必仔细阅读以下声明 ‼️
+请注意,使用"共享"功能时,请务必仔细阅读以下声明 ‼️
+
+======================================
+
+权限:
+您即将共享的密钥理论上具有以下权限,包括但不限于:
+
+ - 查看/下载您 TestFlight 账号内的任何测试版 APP
+ - 使用您的密钥接受测试 TestFlight 中的任何测试版 APP
+ - 停止测试您 TestFlight 账号内的任何测试版 APP
+ - 查看您接受 TestFlight 测试版 APP 邀请时所使用的邮箱
+ - 查看/加入/移除您 TestFlight 账号中的设备列表
+ - 更改您 TestFlight 测试版 APP 中的推送/电子邮件更新通知
+
+免责:
+任何用户使用"共享"功能时都应该仔细阅读权限声明,一旦您开始使用该功能,即视为您已知晓并理解密钥所具有的权限,密钥泄漏可能会导致不可预知的损失或损害,脚本作者(NobyDa)不对由此产生的任何后果负责。
+
+======================================
+
+该脚本在"默认"情况下,对方仅可查看/下载您共享的单个APP,但仍建议仅与您信任的人共享:
+
+`;
+ $.log(`Raw data: ${raw}\nEncode data: ${key}`);
+ return {
+ data: {
+ buildId: bid,
+ eula: disclaimer + key
+ },
+ messages: null
+ }
+}
+
+// private encode method, based on variant in RFC4648
+function letterEncode(e) {
+ e = e.split("").map(e => e.charCodeAt());
+ const t = new Uint8Array(4 * Math.ceil(8 * e.length / 4));
+ let n = 0;
+ for (const o of e) {
+ let e = 128;
+ for (let r = 0; r < 8; r++) t[n++] = o & e ? 1 : 0, e >>= 1
+ }
+ let o = "",
+ r = 0;
+ return t.forEach((e, t) => {
+ r = r << 1 | e, (t + 1) % 4 == 0 && (o += "XKNWSPRMCTGZVDHF"[r], r = 0)
+ }), o
+}
+
+function letterDecode(e) {
+ const t = new Uint8Array(4 * e.length);
+ let n = 0;
+ for (const o of e) {
+ const e = "XKNWSPRMCTGZVDHF".indexOf(o);
+ let r = 8;
+ for (let o = 0; o < 4; o++) t[n++] = e & r ? 1 : 0, r >>= 1
+ }
+ const o = new Uint8Array(Math.floor(t.length / 8));
+ return t.forEach((e, t) => {
+ const n = Math.floor(t / 8);
+ n < o.length && (o[n] = o[n] << 1 | e)
+ }), String.fromCharCode(...o)
+}
+
+// https://github.com/Peng-YM/QuanX/tree/master/Tools/OpenAPI
+function ENV() { const e = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !e, isJSBox: e, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP(e = { baseURL: "" }) { const { isQX: t, isLoon: s, isSurge: o, isScriptable: n, isNode: i, isBrowser: r } = ENV(), u = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; const a = {}; return ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(h => a[h.toLowerCase()] = (a => (function (a, h) { h = "string" == typeof h ? { url: h } : h; const d = e.baseURL; d && !u.test(h.url || "") && (h.url = d ? d + h.url : h.url), h.body && h.headers; const l = (h = { ...e, ...h }).timeout, c = { onRequest: () => { }, onResponse: e => e, onTimeout: () => { }, ...h.events }; let f, p; if (c.onRequest(a, h), t) f = $task.fetch({ method: a, ...h }); else if (s || o || i) f = new Promise((e, t) => { (i ? require("request") : $httpClient)[a.toLowerCase()](h, (s, o, n) => { s ? t(s) : e({ statusCode: o.status || o.statusCode, headers: o.headers, body: n }) }) }); else if (n) { const e = new Request(h.url); e.method = a, e.headers = h.headers, e.body = h.body, f = new Promise((t, s) => { e.loadString().then(s => { t({ statusCode: e.response.statusCode, headers: e.response.headers, body: s }) }).catch(e => s(e)) }) } else r && (f = new Promise((e, t) => { fetch(h.url, { method: a, headers: h.headers, body: h.body }).then(e => e.json()).then(t => e({ statusCode: t.status, headers: t.headers, body: t.data })).catch(t) })); const y = l ? new Promise((e, t) => { p = setTimeout(() => (c.onTimeout(), t(`${a} URL: ${h.url} exceeds the timeout ${l} ms`)), l) }) : null; return (y ? Promise.race([y, f]).then(e => (clearTimeout(p), e)) : f).then(e => c.onResponse(e)) })(h, a))), a } function API(e = "untitled", t = !1) { const { isQX: s, isLoon: o, isSurge: n, isNode: i, isJSBox: r, isScriptable: u } = ENV(); return new class { constructor(e, t) { this.name = e, this.debug = t, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (i) { return { fs: require("fs") } } return null })(), this.initCache(); Promise.prototype.delay = function (e) { return this.then(function (t) { return ((e, t) => new Promise(function (s) { setTimeout(s.bind(null, t), e) }))(e, t) }) } } initCache() { if (s && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (o || n) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), i) { let e = "root.json"; this.node.fs.existsSync(e) || this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.root = {}, e = `${this.name}.json`, this.node.fs.existsSync(e) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.cache = {}) } } persistCache() { const e = JSON.stringify(this.cache, null, 2); s && $prefs.setValueForKey(e, this.name), (o || n) && $persistentStore.write(e, this.name), i && (this.node.fs.writeFileSync(`${this.name}.json`, e, { flag: "w" }, e => console.log(e)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, e => console.log(e))) } write(e, t) { if (this.log(`SET ${t}`), -1 !== t.indexOf("#")) { if (t = t.substr(1), n || o) return $persistentStore.write(e, t); if (s) return $prefs.setValueForKey(e, t); i && (this.root[t] = e) } else this.cache[t] = e; this.persistCache() } read(e) { return this.log(`READ ${e}`), -1 === e.indexOf("#") ? this.cache[e] : (e = e.substr(1), n || o ? $persistentStore.read(e) : s ? $prefs.valueForKey(e) : i ? this.root[e] : void 0) } delete(e) { if (this.log(`DELETE ${e}`), -1 !== e.indexOf("#")) { if (e = e.substr(1), n || o) return $persistentStore.write(null, e); if (s) return $prefs.removeValueForKey(e); i && delete this.root[e] } else delete this.cache[e]; this.persistCache() } notify(e, t = "", a = "", h = {}) { const d = h["open-url"], l = h["media-url"]; if (s && $notify(e, t, a, h), n && $notification.post(e, t, a + `${l ? "\n多媒体:" + l : ""}`, { url: d }), o) { let s = {}; d && (s.openUrl = d), l && (s.mediaUrl = l), "{}" === JSON.stringify(s) ? $notification.post(e, t, a) : $notification.post(e, t, a, s) } if (i || u) { const s = a + (d ? `\n点击跳转: ${d}` : "") + (l ? `\n多媒体: ${l}` : ""); if (r) { require("push").schedule({ title: e, body: (t ? t + "\n" : "") + s }) } else console.log(`${e}\n${t}\n${s}\n\n`) } } log(e) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(e)}`) } info(e) { console.log(`[${this.name}] INFO: ${this.stringify(e)}`) } error(e) { console.log(`[${this.name}] ERROR: ${this.stringify(e)}`) } wait(e) { return new Promise(t => setTimeout(t, e)) } done(e = {}) { s || o || n ? $done(e) : i && !r && "undefined" != typeof $context && ($context.headers = e.headers, $context.statusCode = e.statusCode, $context.body = e.body) } stringify(e) { if ("string" == typeof e || e instanceof String) return e; try { return JSON.stringify(e, null, 2) } catch (e) { return "[object Object]" } } }(e, t) }
\ No newline at end of file
From 28bcd73c787830e24e5761295e919cb7062fa45f Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Wed, 29 Jun 2022 18:03:48 +0800
Subject: [PATCH 027/105] Update store ID
---
TestFlight/TestFlightAccount.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 403a4f9a01..6c47d4018e 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -94,7 +94,7 @@ async function runs() {
}
} else if (/\/install$/.test(req.url) && req.body) {
req.body = JSON.parse(req.body);
- req.body.storefrontId = '143380-1,29'; //prevent regional restrictions
+ req.body.storefrontId = '143441-19,29'; //prevent regional restrictions
req.body = $.stringify(req.body);
} else if (/\d+\/eula$/.test(req.url)) {
rsp.body = $.stringify(ShareAccount(appID, build));
From f489cbbb2ff516543d54b865b53c0afdb293d6a9 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 3 Jul 2022 07:41:54 +0800
Subject: [PATCH 028/105] Update support 1Blocker in-app purchases.
---
QuantumultX/File/vsco.js | 67 ++++++++++++++++++++++++----------------
QuantumultX/Js.conf | 3 +-
README.md | 4 ++-
3 files changed, 46 insertions(+), 28 deletions(-)
diff --git a/QuantumultX/File/vsco.js b/QuantumultX/File/vsco.js
index fbe0c2a926..63c425fd7f 100644
--- a/QuantumultX/File/vsco.js
+++ b/QuantumultX/File/vsco.js
@@ -1,37 +1,52 @@
-/*
- * Membership unlock for vsco & filebox
- * Please note that you may need to reinstall app to make it work.
- *
- * Type: http-response (requires body)
- * Regex: ^https?:\/\/api\.revenuecat\.com\/v\d\/subscribers\/
- * Mitm: api.revenuecat.com
- */
+/********************************
+Membership unlock for VSCO & Fileball & 1Blocker
+Please note that you may need to reinstall app for script to work.
-const resp = {};
-const obj = JSON.parse($response.body || null);
-const app = /VSCO|Fileb(ox|all)/.test($request.headers['User-Agent']);
+QuantumultX rewrite link:
+https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
-const product = {
- "membership": "com.circles.fin.premium.yearly", //vsco
- "filebox_pro": "com.premium.yearly" //filebox
-}
+Please note that the above rewrite link requires open KOP-XIAO's resource parser
+
+*********************************
+Surge4, Loon and Shadowrocket configuration:
+
+[Script]
+http-request ^https?:\/\/api\.revenuecat\.com\/v\d\/subscribers\/ script-path=https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
+http-response ^https?:\/\/api\.revenuecat\.com\/v\d\/subscribers\/ requires-body=1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
+
+[MITM]
+hostname = api.revenuecat.com
+********************************/
+
+const resp = {};
+const obj = JSON.parse(typeof $response != "undefined" && $response.body || null);
+const ua = $request.headers['User-Agent'] || $request.headers['user-agent'];
+const list = {
+ 'VSCO': { name: 'membership', id: 'com.circles.fin.premium.yearly' },
+ 'Filebox': { name: 'filebox_pro', id: 'com.premium.yearly' },
+ 'Fileball': { name: 'filebox_pro', id: 'com.premium.yearly' },
+ '1Blocker': { name: 'premium', id: 'blocker.ios.subscription.yearly' }
+};
const data = {
"expires_date": "2030-02-18T07:52:54Z",
"original_purchase_date": "2020-02-11T07:52:55Z",
"purchase_date": "2020-02-11T07:52:54Z"
};
-if (app && obj && obj.subscriber) {
- if (!obj.subscriber.subscriptions) {
- obj.subscriber.subscriptions = {};
- }
- if (!obj.subscriber.entitlements) {
- obj.subscriber.entitlements = {};
- }
- for (const i in product) {
- obj.subscriber.subscriptions[product[i]] = data;
- obj.subscriber.entitlements[i] = data;
- obj.subscriber.entitlements[i].product_identifier = product[i];
+if (typeof $response == "undefined") {
+ delete $request.headers["x-revenuecat-etag"]; // prevent 304 issues
+ delete $request.headers["X-RevenueCat-ETag"];
+ resp.headers = $request.headers;
+} else if (obj && obj.subscriber) {
+ obj.subscriber.subscriptions = obj.subscriber.subscriptions || {};
+ obj.subscriber.entitlement = obj.subscriber.entitlement || {};
+ for (const i in list) {
+ if (new RegExp(`^${i}`, `i`).test(ua)) {
+ obj.subscriber.subscriptions[list[i].id] = data;
+ obj.subscriber.entitlements[list[i].name] = JSON.parse(JSON.stringify(data));
+ obj.subscriber.entitlements[list[i].name].product_identifier = list[i].id;
+ break;
+ }
}
resp.body = JSON.stringify(obj);
}
diff --git a/QuantumultX/Js.conf b/QuantumultX/Js.conf
index eabe569ef5..2b08b04004 100644
--- a/QuantumultX/Js.conf
+++ b/QuantumultX/Js.conf
@@ -20,7 +20,8 @@ hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.
# 知音漫客VIP
^https:\/\/apigate\.zymk\.cn\/(zymk-getuserinfo-api\/v1\/getuserinfo|zymk-userpurchased-api\/v1\/userpurchased\/paychapters)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
-# VSCO滤镜VIP
+# VSCO & Fileball(Filebox) & 1Blocker
+^https?:\/\/api\.revenuecat\.com\/v\d\/subscribers\/ url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
^https?:\/\/api\.revenuecat\.com\/v\d\/subscribers\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
# 大片(Bigshot) 视频编辑器 VIP
diff --git a/README.md b/README.md
index a0a96b3af8..7e8854e1c6 100644
--- a/README.md
+++ b/README.md
@@ -57,7 +57,9 @@
| Application | Script name | Main Functions | Available | Maintenance |
| :----------------------------------------------------------: | :----------------------------------------------------------: | :---------------------: | :---------: | :---------: |
| [Bigshot](https://apps.apple.com/app/id1274910157) | [dapian.js](https://github.com/NobyDa/Script/blob/master/QuantumultX/File/dapian.js) | Unlock membership | ✅(2021.7.3) | ❌ |
-| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2021.7.3) | ✅ |
+| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022.7.3) | ✅ |
+| [Fileball](https://apps.apple.com/app/id1558391784) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022.7.3) | ❌ |
+| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022.7.3) | ❌ |
| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅(2021.7.3) | ❌ |
| [NiChi](https://apps.apple.com/app/id1442041390) | [NiChi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/NiChi.js) | Unlock material pack | ✅(2021.7.3) | ❌ |
| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ✅(2021.7.3) | ✅ |
From ac525811d1aa45cee3293be4314ecd43d3b41a25 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 3 Jul 2022 10:49:07 +0800
Subject: [PATCH 029/105] Update vivavideo script regex
---
QuantumultX/Js.conf | 4 ++--
Surge/JS/vivavideo.js | 8 ++++----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/QuantumultX/Js.conf b/QuantumultX/Js.conf
index 2b08b04004..f66bc49048 100644
--- a/QuantumultX/Js.conf
+++ b/QuantumultX/Js.conf
@@ -1,4 +1,4 @@
-hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.zhihu.com, vip1.kuwo.cn, p.du.163.com, apigate.zymk.cn, vni.kwaiying.com, *.my10api.com, www.luqijianggushi.com, account.wps.cn, origin-prod-phoenix.jibjab.com, api.bjxkhc.com, xy-viva.kakalili.com, ap*.intsig.net, m*.bybutter.com, api.vuevideo.net, api.picsart.c*, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.meiease.c*, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api.polaxiong.com
+hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.zhihu.com, vip1.kuwo.cn, p.du.163.com, apigate.zymk.cn, vni.kwaiying.com, *.my10api.com, www.luqijianggushi.com, account.wps.cn, origin-prod-phoenix.jibjab.com, api.bjxkhc.com, xy-viva.kakalili.com, ap*.intsig.net, m*.bybutter.com, api.vuevideo.net, api.picsart.c*, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.meiease.c*, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api.polaxiong.com, api-chn.rthdo.com
# 去微信公众号广告 (By Choler)
^https?:\/\/mp\.weixin\.qq\.com\/mp\/getappmsgad url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js
@@ -43,7 +43,7 @@ hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.
^https:\/\/origin-prod-phoenix\.jibjab\.com\/v1\/user url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js
# 小影 解锁Vip
-^https:\/\/xy-viva\.kakalili\.com\/api\/rest\/u\/vipVerifyReceipt url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js
+^https:\/\/(xy-viva\.kakalili|api-chn.rthdo)\.com\/api\/rest\/u\/vipVerifyReceipt url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js
# 扫描全能王 pro
^https:\/\/(api|api-cs)\.intsig\.net\/purchase\/cs\/query_property\? url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js
diff --git a/Surge/JS/vivavideo.js b/Surge/JS/vivavideo.js
index a52165c996..470f13cbb5 100644
--- a/Surge/JS/vivavideo.js
+++ b/Surge/JS/vivavideo.js
@@ -5,19 +5,19 @@
QuantumultX:
[rewrite_local]
-^https:\/\/xy-viva\.kakalili\.com\/api\/rest\/u\/vipVerifyReceipt url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js
+^https:\/\/(xy-viva\.kakalili|api-chn.rthdo)\.com\/api\/rest\/u\/vipVerifyReceipt url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js
[mitm]
-hostname = xy-viva.kakalili.com
+hostname = xy-viva.kakalili.com, api-chn.rthdo.com
***************************
Surge4 or Loon:
[Script]
-http-response ^https:\/\/xy-viva\.kakalili\.com\/api\/rest\/u\/vipVerifyReceipt requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js
+http-response ^https:\/\/(xy-viva\.kakalili|api-chn.rthdo)\.com\/api\/rest\/u\/vipVerifyReceipt requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js
[MITM]
-hostname = xy-viva.kakalili.com
+hostname = xy-viva.kakalili.com, api-chn.rthdo.com
**************************/
From 6f0b859efe152be0f83eb5635c4f5e5b2263355b Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 3 Jul 2022 10:50:21 +0800
Subject: [PATCH 030/105] Adjust readme
---
README.md | 190 +++++++++++++++++++++++++++---------------------------
1 file changed, 95 insertions(+), 95 deletions(-)
diff --git a/README.md b/README.md
index 7e8854e1c6..193ef110de 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,15 @@
## TOC
+
- [TOC](#toc)
-- [Script desc](#script-desc)
- - [Daily bonus scripts](#daily-bonus-scripts)
- - [Functionality-enhancing scripts](#functionality-enhancing-scripts)
- - [Other scripts](#other-scripts)
-- [Surge file desc](#surge-file-desc)
- - [Surge ruleset](#surge-ruleset)
- - [Surge module](#surge-module)
-- [QuantumultX file desc](#quantumultx--file-desc)
-- [Loon file desc](#loon-file-desc)
+- [Script Overview](#script-overview)
+ - [Daily-Bonus Script](#daily-bonus-script)
+ - [Functionality-enhancing Script](#functionality-enhancing-script)
+ - [Other Script](#other-script)
+- [Surge File Overview](#surge-file-overview)
+ - [Surge Ruleset](#surge-ruleset)
+ - [Surge Module](#surge-module)
+- [QuantumultX File Overview](#quantumultx-file-overview)
+- [Loon File Overview](#loon-file-overview)
- [Disclaimer](#disclaimer)
- [Decrypt](#decrypt)
- [Privacy](#privacy)
@@ -16,123 +17,122 @@
- [Infringement](#infringement)
- [Liability](#liability)
- [Change](#change)
-- [Special thanks to](#special-thanks-to)
+- [Acknowledgment](#acknowledgment)
- [License](#license)
-
-
> **Please note that the scripts or rewrite rules described below may require MITM to be enabled, and the generated root certificate needs to be manually installed and trusted in the system.**
-## Script desc
+## Script Overview
-### Daily bonus scripts
+### Daily-Bonus Script
-| Application | Script name | Available | Maintenance |
-| :-----------------------------------------------------: | :----------------------------------------------------------: | :----------: | :---------: |
-| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ⚠️(2022.6.18) | ⚠️ |
-| [百度贴吧](https://apps.apple.com/app/id477927812) | [TieBa.js](https://github.com/NobyDa/Script/blob/master/BDTieBa-DailyBonus/TieBa.js) | ✅(2021.6.18) | ❌ |
-| [吾爱破解](https://www.52pojie.cn/) | [52pojie.js](https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js) | ✅(2022.6.18) | ❌ |
-| [爱奇艺](https://apps.apple.com/cn/app/id393765873) | [iQIYI.js](https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js) | ✅(2022.6.18) | ❌ |
-| [快看漫画](https://apps.apple.com/app/id906936224) | [KKMH.js](https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js) | ✅(2022.6.18) | ✅ |
-| [哔哩哔哩漫画](https://apps.apple.com/app/id1426252715) | [Manga.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js) | ✅(2022.6.18) | ✅ |
-| [巴哈姆特](https://www.gamer.com.tw/) | [BahamutDailyBonus.js](https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js) | ✅(2022.6.18) | ✅ |
+| Application | Script name | Available | Maintenance |
+|:-------------------------------------------------:|:-------------------------------------------------------------------------------------------------:|:--------------:|:-----------:|
+| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ⚠️(2022/07/03) | ⚠️ |
+| [百度贴吧](https://apps.apple.com/app/id477927812) | [TieBa.js](https://github.com/NobyDa/Script/blob/master/BDTieBa-DailyBonus/TieBa.js) | ✅(2022/07/03) | ❌ |
+| [吾爱破解](https://www.52pojie.cn/) | [52pojie.js](https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js) | ✅(2022/07/03) | ❌ |
+| [爱奇艺](https://apps.apple.com/cn/app/id393765873) | [iQIYI.js](https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js) | ✅(2022/07/03) | ✅ |
+| [快看漫画](https://apps.apple.com/app/id906936224) | [KKMH.js](https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js) | ✅(2022/07/03) | ✅ |
+| [哔哩哔哩漫画](https://apps.apple.com/app/id1426252715) | [Manga.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js) | ✅(2022/07/03) | ✅ |
+| [巴哈姆特](https://www.gamer.com.tw/) | [BahamutDailyBonus.js](https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js) | ✅(2022/07/03) | ✅ |
------
-### Functionality-enhancing scripts
+### Functionality-enhancing Script
-| Script name | Main Functions | Maintenance |
-| :----------------------------------------------------------: | :----------------------------------------------------------: | :---------: |
-| [PolicySwitch.js](https://github.com/NobyDa/Script/blob/master/Shortcuts/PolicySwitch.js) | Switch [QX](https://apps.apple.com/app/id1443988620),[Surge](https://apps.apple.com/app/id1442620678),[Loon](https://apps.apple.com/app/id1373567447) policy groups using ios [shortcut](https://apps.apple.com/app/id1462947752). | ✅ |
-| [DataQuery.js](https://github.com/NobyDa/Script/blob/master/Sub-store-parser/DataQuery.js) | Server(VPN) traffic query based on [Sub-Store](https://github.com/Peng-YM/Sub-Store). | ✅ |
-| [Bili_Auto_Regions.js](https://github.com/NobyDa/Script/blob/master/Surge/JS/Bili_Auto_Regions.js) | [Bilibili anime](https://apps.apple.com/cn/app/id736536022) auto switch region & show [douban](https://www.douban.com/) rating. | ✅ |
-| [ExchangePoints.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/ExchangePoints.js) | [Bilibili manga](https://apps.apple.com/app/id1426252715) points mall auto snap up. | ✅ |
+| Script name | Description |
+|:-------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
+| [PolicySwitch.js](https://github.com/NobyDa/Script/blob/master/Shortcuts/PolicySwitch.js) | Switch [QX](https://apps.apple.com/app/id1443988620),[Surge](https://apps.apple.com/app/id1442620678),[Loon](https://apps.apple.com/app/id1373567447) policy groups using ios [shortcut](https://apps.apple.com/app/id1462947752). |
+| [DataQuery.js](https://github.com/NobyDa/Script/blob/master/Sub-store-parser/DataQuery.js) | Server(VPN) traffic query based on [Sub-Store](https://github.com/Peng-YM/Sub-Store). |
+| [Bili_Auto_Regions.js](https://github.com/NobyDa/Script/blob/master/Surge/JS/Bili_Auto_Regions.js) | [Bilibili anime](https://apps.apple.com/cn/app/id736536022) auto switch region & show [douban](https://www.douban.com/) rating. |
+| [ExchangePoints.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/ExchangePoints.js) | [Bilibili Comics](https://apps.apple.com/app/id1426252715) points mall auto snap up. |
+| [TestFlightAccount.js](https://github.com/NobyDa/Script/blob/master/TestFlight/TestFlightAccount.js) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts |
---
-
-
-### Other scripts
-
-| Application | Script name | Main Functions | Available | Maintenance |
-| :----------------------------------------------------------: | :----------------------------------------------------------: | :---------------------: | :---------: | :---------: |
-| [Bigshot](https://apps.apple.com/app/id1274910157) | [dapian.js](https://github.com/NobyDa/Script/blob/master/QuantumultX/File/dapian.js) | Unlock membership | ✅(2021.7.3) | ❌ |
-| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022.7.3) | ✅ |
-| [Fileball](https://apps.apple.com/app/id1558391784) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022.7.3) | ❌ |
-| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022.7.3) | ❌ |
-| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅(2021.7.3) | ❌ |
-| [NiChi](https://apps.apple.com/app/id1442041390) | [NiChi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/NiChi.js) | Unlock material pack | ✅(2021.7.3) | ❌ |
-| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ✅(2021.7.3) | ✅ |
-| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅(2021.7.6) | ❌ |
-| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ✅(2021.7.6) | ❌ |
-| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ✅(2021.7.3) | ❌ |
-| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ❌ | ❌ |
-| [酷我音乐](https://apps.apple.com/cn/app/id588673713) | [Kuwo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Kuwo.js) | Unlock vip listen | ✅(2021.7.3) | ❌ |
-| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ✅(2021.7.3) | ✅ |
-| [91短视频](http://download.91porn.love/) | [91.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/91.js) | Unlock membership | ✅(2021.7.3) | ❌ |
-| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ✅(2021.7.3) | ❌ |
-| [爱美剧](https://www.mjapp.cc) | [aimeiju.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/aimeiju.js) | Unlock membership | ✅(2021.7.3) | ❌ |
-| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅(2021.7.3) | ❌ |
-| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅(2021.7.3) | ❌ |
-| [WPS Office](https://apps.apple.com/app/id1491101673) | [Wps.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js) | Unlock membership | ✅(2021.7.3) | ❌ |
-| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅(2021.7.6) | ❌ |
-| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove ads | ✅(2021.7.3) | ❌ |
-| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove ads | ✅(2021.7.3) | ❌ |
+### Other Script
+
+| Application | Script name | Description | Available |
+|:---------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------:|:-----------------------:|:----------------:|
+| [Bigshot](https://apps.apple.com/app/id1274910157) | [dapian.js](https://github.com/NobyDa/Script/blob/master/QuantumultX/File/dapian.js) | Unlock membership | ⚠️No recent test |
+| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
+| [Fileball](https://apps.apple.com/app/id1558391784) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
+| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
+| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅(2022/07/03) |
+| [NiChi](https://apps.apple.com/app/id1442041390) | [NiChi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/NiChi.js) | Unlock material pack | ⚠️No recent test |
+| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ✅(2022/07/03) |
+| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅(2022/07/03) |
+| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ✅(2022/07/03) |
+| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ✅(2022/07/03) |
+| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ✅(2022/07/03) |
+| [酷我音乐](https://apps.apple.com/cn/app/id588673713) | [Kuwo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Kuwo.js) | Unlock vip listen | ⚠️No recent test |
+| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ✅(2022/07/03) |
+| [91短视频](http://download.91porn.love/) | [91.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/91.js) | Unlock membership | ⚠️No recent test |
+| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ✅(2022/07/03) |
+| [爱美剧](https://www.mjapp.cc) | [aimeiju.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/aimeiju.js) | Unlock membership | ⚠️No recent test |
+| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅(2022/07/03) |
+| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅(2022/07/03) |
+| [WPS Office](https://apps.apple.com/app/id1491101673) | [Wps.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js) | Unlock membership | ⚠️No recent test |
+| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ⚠️No recent test |
+| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅(2022/07/03) |
+| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ✅(2022/07/03) |
+| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅(2022/07/03) |
---
+## Surge File Overview
+### Surge Ruleset
-## Surge file desc
+| File name | Number | Description |
+|:-------------------------------------------------------------------------------------------:|:------:|:---------------------------------:|
+| [WeChat.list](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/WeChat.list) | 180+ | WeChat ruleset (China) |
+| [Apple.list](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Apple.list) | 60+ | Apple ruleset (Most countries) |
+| [Download.list](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Download.list) | 15+ | Some BT, Thunder, download rules. |
-### Surge ruleset
+### Surge Module
-| File name | Number | Integrate | Desc | Maintenance |
-| :----------------------------------------------------------: | :----: | :----------------------------------------------------------: | :-------------------------------: | :---------: |
-| [AdRule.list](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/AdRule.list) | 8000+ | [lhie1](https://github.com/lhie1/Rules), [ConnersHua](https://github.com/ConnersHua/Profiles) | Private ad ruleset | ❌ |
-| [AdRuleTest.list](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/AdRuleTest.list) | 1300+ | [Scomper](https://github.com/scomper/Surge) | Private ad ruleset (test only). | ❌ |
-| [WeChat.list](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/WeChat.list) | 180+ | N/A | WeChat ruleset (china) | ✅ |
-| [Apple.list](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Apple.list) | 60+ | N/A | Apple ruleset (global) | ✅ |
-| [Download.list](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Download.list) | 15+ | N/A | Some BT, Thunder, download rules. | ❌ |
-
-### Surge module
-
-| Module name | Desc | Maintenance |
-| :----------------------------------------------------------: | :----------------------------------------------------------: | :---------: |
-| [RewriteRules.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/RewriteRules.sgmodule) | Private ad rewrite rules, integrate [lhie1](https://github.com/lhie1/Rules)、[ConnersHua](https://github.com/ConnersHua/Profiles)、[onewayticket255](https://github.com/onewayticket255/Surge-Script) and [Choler](https://github.com/Choler/Surge/tree/master/Ruleset). | ❌ |
-| [HuiJuDongManAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/HuiJuDongManAds.sgmodule) | Please see the desc in module. | ✅ |
-| [IPA_install.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/IPA_install.sgmodule) | Use Surge to assist in install IPA (signed version) | ❌ |
-| [TestFlightDownload.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightDownload.sgmodule) | Please see the desc in module. | ✅ |
-| [GetCookie.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/GetCookie.sgmodule) | Please see the desc in module. | ✅ |
+| Module name | Description |
+|:------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:|
+| [HuiJuDongManAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/HuiJuDongManAds.sgmodule) | Remove [APP](https://apps.apple.com/app/id1451949669) Ads |
+| [IPA_install.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/IPA_install.sgmodule) | Use Surge to assist in install IPA (signed version) |
+| [TestFlightDownload.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightDownload.sgmodule) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions |
+| [TestFlightAccount.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightAccount.sgmodule) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts |
+| [GetCookie.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/GetCookie.sgmodule) | Daily bonus script related |
+| [BahamutAnimeAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/BahamutAnimeAds.sgmodule) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads |
---
-## QuantumultX file desc
+## QuantumultX File Overview
-| Name | Integrate | Number | Desc | Type | Maintenance |
-| :----------------------------------------------------------: | :----------------------------------------------------------: | :----: | :---------------------------: | :-----: | :---------: |
-| [AdRule.list](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/AdRule.list) | [lhie1](https://github.com/lhie1/Rules) | 7000+ | Private ad rules. | Rule | ❌ |
-| [AdRuleTest.list](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/AdRuleTest.list) | [Scomper](https://github.com/scomper/Surge) | 1300+ | Private ad rules (test only). | Rule | ❌ |
-| [Rewrite_lhie1.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Rewrite_lhie1.conf) | [lhie1](https://github.com/lhie1/Rules)、[onewayticket255](https://github.com/onewayticket255/Surge-Script)、[Choler](https://github.com/Choler/Surge/tree/master/Ruleset) | 400+ | Private rewrite rules. | Rewrite | ❌ |
-| [Js.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js.conf) | N/A | N/A | Remote script subscription. | Rewrite | ✅ |
-| [Js_Remote_Cookie.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf) | N/A | N/A | Please see the desc in file. | Rewrite | ✅ |
-| [TestFlightDownload.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/TestFlightDownload.conf) | N/A | N/A | Please see the desc in file. | Rewrite | ✅ |
+| File name | Description | Type |
+|:---------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:|:-------:|
+| [Js.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js.conf) | Remote script subscription. | Rewrite |
+| [Js_Remote_Cookie.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf) | Daily bonus script related | Rewrite |
+| [TestFlightDownload.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/TestFlightDownload.conf) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions | Rewrite |
Rules of type "Rule" include only ad hosts. Please select the REJECT policy.
-
Difference between QuantumultX versions (Click to view)
* AppStore version QX1.0.0 (120) This version is the initial version, JS function is unlimited.
+
* AppStore version QX1.0.1 (130) This version adds support V2Ray(protocols), but restricts the keywords of the script VIP type.
* AppStore version QX1.0.2 (136) This version adds support HTTP(protocols) and relaxes certain script keyword restrictions, but restricts script remote subscriptions
+
* AppStore version QX1.0.3 (155) This version removes the keyword restriction and restores the script remote subscription, however, the remote script needs to comment the device ID before execution.
+
* AppStore version QX1.0.4 (164) This version completely restricts remote script subscriptions, meaning that all scripts can only use local paths.
+
* AppStore version QX1.0.5 (192) This version adds a timed script task function.
+
* AppStore version QX1.0.6 (212) This version supports modifying HTTP request body, and replaying HTTP request.
+
* AppStore version QX1.0.7 (240) This version supports TLS 1.3 (TLS-based proxy protocol), and Trojan(protocols).
+
* ...
+
* AppStore version QX1.0.10 (313) In this version, script remote subscription has been restored.
QX1.0.3 add device ID, a simple example:
@@ -153,14 +153,14 @@ The above random generated device ID can be found at the bottom of Quantumult X
---
-## Loon file desc
-
-| File name | Desc | Type | Maintenance |
-| :----------------------------------------------------------: | :-----------------------------: | :------------------: | :---------: |
-| [Loon_GetCookie.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_GetCookie.plugin) | Please see the desc in file. | Plugin | ✅ |
-| [Loon_TF_Download.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Download.plugin) | Please see the desc in file. | Plugin | ✅ |
-| [Loon_Bahamut_ADS.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_Bahamut_ADS.plugin) | Remove Bahamut anime Ads | Plugin | ✅ |
+## Loon File Overview
+| File name | Description | Type |
+|:--------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:|:------:|
+| [Loon_GetCookie.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_GetCookie.plugin) | Daily bonus script related | Plugin |
+| [Loon_TF_Download.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Download.plugin) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions | Plugin |
+| [Loon_TF_Account.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Account.plugin) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts | Plugin |
+| [Loon_Bahamut_ADS.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_Bahamut_ADS.plugin) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads | Plugin |
---
@@ -204,7 +204,7 @@ The "NobyDa" refers specifically to the author and owner in https://github.com/N
2. **Once you view, use or copy any of the related scripts in "Script project", you will be deemed to have accepted this disclaimer.**
-## Special thanks to
+## Acknowledgment
* [@sazs34](https://github.com/sazs34)
* [@lhie1](https://github.com/lhie1)
From 7050d233d0bbcdde23ed46c4e09be5c92b2ba64c Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 3 Jul 2022 22:36:03 +0800
Subject: [PATCH 031/105] Update wps.js regex
---
QuantumultX/Js.conf | 23 ++---------------------
Surge/JS/Wps.js | 8 ++++----
2 files changed, 6 insertions(+), 25 deletions(-)
diff --git a/QuantumultX/Js.conf b/QuantumultX/Js.conf
index f66bc49048..a792377fc9 100644
--- a/QuantumultX/Js.conf
+++ b/QuantumultX/Js.conf
@@ -1,4 +1,4 @@
-hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.zhihu.com, vip1.kuwo.cn, p.du.163.com, apigate.zymk.cn, vni.kwaiying.com, *.my10api.com, www.luqijianggushi.com, account.wps.cn, origin-prod-phoenix.jibjab.com, api.bjxkhc.com, xy-viva.kakalili.com, ap*.intsig.net, m*.bybutter.com, api.vuevideo.net, api.picsart.c*, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.meiease.c*, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api.polaxiong.com, api-chn.rthdo.com
+hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.zhihu.com, vip1.kuwo.cn, p.du.163.com, apigate.zymk.cn, www.luqijianggushi.com, *account.wps.com, *account.wps.cn, origin-prod-phoenix.jibjab.com, xy-viva.kakalili.com, ap*.intsig.net, api.picsart.c*, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.meiease.c*, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api.polaxiong.com, api-chn.rthdo.com
# 去微信公众号广告 (By Choler)
^https?:\/\/mp\.weixin\.qq\.com\/mp\/getappmsgad url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js
@@ -6,13 +6,6 @@ hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.
# 酷我音乐SVIP (By yxiaocai)
^https?:\/\/vip1\.kuwo\.cn\/(vip\/v2\/user\/vip|vip\/spi/mservice) url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Kuwo.js
-# 爱美剧Vip (by huihui)(官网:app.meiju2018.com)
-^https?:\/\/api.bjxkhc.com\/index\.php\/app\/ios\/(vod\/show|(user|vod|topic|type)\/index) url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/aimeiju.js
-# 广告
-^https?://api.bjxkhc.com/index.php/app/ios/ads/index url reject-dict
-^https?://api.bjxkhc.com/index.php/app/ios/ver/index_ios$ url reject
-^https?://api.bjxkhc.com/index.php/app/ios/pay/ok$ url reject-dict
-
# 网易蜗牛读书VIP (By yxiaocai and JO2EY)
^https?://p\.du\.163\.com/readtime/info.json url reject
^https?:\/\/p\.du\.163\.com\/gain\/readtime\/info\.json url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js
@@ -24,12 +17,6 @@ hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.
^https?:\/\/api\.revenuecat\.com\/v\d\/subscribers\/ url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
^https?:\/\/api\.revenuecat\.com\/v\d\/subscribers\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
-# 大片(Bigshot) 视频编辑器 VIP
-^https:\/\/vni\.kwaiying\.com\/api\/v1\/user\/profile url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/dapian.js
-
-# 91短视频
-^https?:\/\/.+?\.(my10api|(.*91.*))\.(com|tips|app|xyz)(:\d{2,5}|)\/api.php$ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/91.js
-
# 香蕉视频VIP
^https?:\/\/.+?\.(pipi|fuli|xiang(jiao|xiang))apps\.com\/(ucp\/index|getGlobalData|(\/|)vod\/reqplay\/) url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js
@@ -37,7 +24,7 @@ hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.
^https:\/\/www\.luqijianggushi\.com\/api\/v2\/user\/get url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js
# WPS (By eHpo)
-^https://account.wps.cn/api/users/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js
+^https?:\/\/[a-z-]*account\.wps\.c(n|om)(:\d+|)\/api\/users url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js
# JibJab解锁pro
^https:\/\/origin-prod-phoenix\.jibjab\.com\/v1\/user url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js
@@ -48,12 +35,6 @@ hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.
# 扫描全能王 pro
^https:\/\/(api|api-cs)\.intsig\.net\/purchase\/cs\/query_property\? url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js
-# VUE pro
-^https:\/\/api\.vuevideo\.net\/api\/v1\/(users\/.+\/profile|subtitle\/prepare) url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/VUE.js
-
-# NiChi 解锁素材
-^https?:\/\/m(p|ini-hk)\.bybutter\.com\/mood\/(official-templates|privileges) url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/NiChi.js
-
# PicsArt美易 pro
^https:\/\/api\.(picsart|meiease)\.c(n|om)\/users\/show\/me\.json url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js
diff --git a/Surge/JS/Wps.js b/Surge/JS/Wps.js
index d580e157bd..0f6e5812a5 100644
--- a/Surge/JS/Wps.js
+++ b/Surge/JS/Wps.js
@@ -5,19 +5,19 @@ WPS Office 解锁部分功能
QuantumultX:
[rewrite_local]
-^https?:\/\/account\.wps\.cn\/api\/users url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js
+^https?:\/\/[a-z-]*account\.wps\.c(n|om)(:\d+|)\/api\/users url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js
[mitm]
-hostname = account.wps.cn
+hostname = *account.wps.cn, *account.wps.com
***************************
Surge4 or Loon:
[Script]
-http-response ^https?:\/\/account\.wps\.cn\/api\/users requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js
+http-response ^https?:\/\/[a-z-]*account\.wps\.c(n|om)(:\d+|)\/api\/users requires-body=1,max-size=-1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js
[MITM]
-hostname = account.wps.cn
+hostname = *account.wps.cn, *account.wps.com
**************************/
From 0ea7504242f11e563eb873f1575e0a79d69bbfc0 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 3 Jul 2022 22:38:47 +0800
Subject: [PATCH 032/105] Update README.md
---
README.md | 46 +++++++++++++++++++++-------------------------
1 file changed, 21 insertions(+), 25 deletions(-)
diff --git a/README.md b/README.md
index 193ef110de..801050c207 100644
--- a/README.md
+++ b/README.md
@@ -52,31 +52,27 @@
### Other Script
-| Application | Script name | Description | Available |
-|:---------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------:|:-----------------------:|:----------------:|
-| [Bigshot](https://apps.apple.com/app/id1274910157) | [dapian.js](https://github.com/NobyDa/Script/blob/master/QuantumultX/File/dapian.js) | Unlock membership | ⚠️No recent test |
-| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
-| [Fileball](https://apps.apple.com/app/id1558391784) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
-| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
-| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅(2022/07/03) |
-| [NiChi](https://apps.apple.com/app/id1442041390) | [NiChi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/NiChi.js) | Unlock material pack | ⚠️No recent test |
-| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ✅(2022/07/03) |
-| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅(2022/07/03) |
-| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ✅(2022/07/03) |
-| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ✅(2022/07/03) |
-| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ✅(2022/07/03) |
-| [酷我音乐](https://apps.apple.com/cn/app/id588673713) | [Kuwo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Kuwo.js) | Unlock vip listen | ⚠️No recent test |
-| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ✅(2022/07/03) |
-| [91短视频](http://download.91porn.love/) | [91.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/91.js) | Unlock membership | ⚠️No recent test |
-| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ✅(2022/07/03) |
-| [爱美剧](https://www.mjapp.cc) | [aimeiju.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/aimeiju.js) | Unlock membership | ⚠️No recent test |
-| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅(2022/07/03) |
-| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅(2022/07/03) |
-| [WPS Office](https://apps.apple.com/app/id1491101673) | [Wps.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js) | Unlock membership | ⚠️No recent test |
-| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ⚠️No recent test |
-| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅(2022/07/03) |
-| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ✅(2022/07/03) |
-| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅(2022/07/03) |
+| Application | Script name | Description | Available |
+|:---------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------:|:---------------------------------------------:|:-------------:|
+| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
+| [Fileball](https://apps.apple.com/app/id1558391784) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
+| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
+| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅(2022/07/03) |
+| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ✅(2022/07/03) |
+| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅(2022/07/03) |
+| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ✅(2022/07/03) |
+| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ✅(2022/07/03) |
+| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ✅(2022/07/03) |
+| [酷我音乐](https://apps.apple.com/cn/app/id588673713) | [Kuwo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Kuwo.js) | Unlock vip listen | ✅(2022/07/03) |
+| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ✅(2022/07/03) |
+| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ✅(2022/07/03) |
+| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅(2022/07/03) |
+| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅(2022/07/03) |
+| [WPS Office](https://apps.apple.com/app/id1491101673) | [Wps.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js) | Unlock membership | ✅(2022/07/03) |
+| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅(2022/07/03) |
+| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅(2022/07/03) |
+| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ✅(2022/07/03) |
+| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅(2022/07/03) |
---
From a1fc135dce63ee765b88544ee9386c904465e614 Mon Sep 17 00:00:00 2001
From: AisukaYuki
Date: Tue, 5 Jul 2022 08:05:29 +0800
Subject: [PATCH 033/105] Added SwitchRegion parameters (#406)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Additional title parameters: data→series→series_title
---
Surge/JS/Bili_Auto_Regions.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Surge/JS/Bili_Auto_Regions.js b/Surge/JS/Bili_Auto_Regions.js
index f5fb1e89be..74006fc552 100644
--- a/Surge/JS/Bili_Auto_Regions.js
+++ b/Surge/JS/Bili_Auto_Regions.js
@@ -135,7 +135,7 @@ function EnvInfo() {
if (typeof($response) !== 'undefined') {
const raw = JSON.parse($response.body);
const data = raw.data || raw.result || {};
- SwitchRegion(data.title || (raw.code === -404 ? -404 : null))
+ SwitchRegion(data.series?.series_title || data.title || (raw.code === -404 ? -404 : null))
.then(s => s ? $done({
status: $.isQuanX ? "HTTP/1.1 408 Request Timeout" : 408,
headers: {
From 9e9103e2dccddf4e420a3e5e5d6ba42c7a43a16b Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Tue, 5 Jul 2022 08:11:45 +0800
Subject: [PATCH 034/105] Fix Surge HTTP/2 and other minor issues
---
Surge/JS/Bili_Auto_Regions.js | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/Surge/JS/Bili_Auto_Regions.js b/Surge/JS/Bili_Auto_Regions.js
index 74006fc552..dd48762eba 100644
--- a/Surge/JS/Bili_Auto_Regions.js
+++ b/Surge/JS/Bili_Auto_Regions.js
@@ -5,7 +5,7 @@
如需禁用豆瓣评分或策略通知, 可前往BoxJs设置.
BoxJs订阅地址: https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
-Update: 2022.05.16
+Update: 2022.07.05
Author: @NobyDa
Use: Surge, QuanX, Loon
@@ -34,7 +34,7 @@ QX用户注: 使用切换地区功能请确保您的QX=>其他设置=>温和策
Surge 4.7+ 远程脚本配置 :
****************************
[Script]
-Bili Region = type=http-response,pattern=^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/(pgc\/view\/v\d\/app\/season|x\/v\d\/search\/defaultwords)\?access_key,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js
+Bili Region = type=http-response,pattern=^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/(pgc\/view\/v\d\/app\/season|x\/offline\/version)\?,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js
#可选, 适用于搜索指定地区的番剧
Bili Search = type=http-request,pattern=^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/x\/v\d\/search(\/type)?\?.+?%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)&,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js
@@ -46,7 +46,7 @@ hostname = ap?.bili*i.com, ap?.bili*i.net
Quantumult X 远程脚本配置 :
****************************
[rewrite_local]
-^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/(pgc\/view\/v\d\/app\/season|x\/v\d\/search\/defaultwords)\?access_key url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js
+^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/(pgc\/view\/v\d\/app\/season|x\/offline\/version)\? url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js
#可选, 适用于搜索指定地区的番剧
^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/x\/v\d\/search(\/type)?\?.+?%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)& url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js
@@ -62,7 +62,7 @@ ip-cidr, 203.107.1.1/24, reject
Loon 远程脚本配置 :
****************************
[Script]
-http-response ^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/(pgc\/view\/v\d\/app\/season|x\/v\d\/search\/defaultwords)\?access_key script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js, requires-body=true, tag=bili自动地区
+http-response ^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/(pgc\/view\/v\d\/app\/season|x\/offline\/version)\? script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js, requires-body=true, tag=bili自动地区
#可选, 适用于搜索指定地区的番剧
http-request ^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/x\/v\d\/search(\/type)?\?.+?%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)& script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js, requires-body=true, tag=bili自动地区(搜索)
@@ -132,23 +132,25 @@ function SwitchStatus(status, original, newPolicy) {
}
function EnvInfo() {
+ const url = $request.url;
if (typeof($response) !== 'undefined') {
- const raw = JSON.parse($response.body);
+ const raw = JSON.parse($response.body || "{}");
const data = raw.data || raw.result || {};
- SwitchRegion(data.series?.series_title || data.title || (raw.code === -404 ? -404 : null))
+ const t1 = (data.series && data.series.series_title) || data.title;
+ const t2 = raw.code === -404 ? -404 : null;
+ SwitchRegion(t1 || t2)
.then(s => s ? $done({
- status: $.isQuanX ? "HTTP/1.1 408 Request Timeout" : 408,
+ status: $.isQuanX ? "HTTP/1.1 307" : 307,
headers: {
- Connection: "close"
+ Location: url
},
body: "{}"
}) : QueryRating(raw, data));
} else {
- const raw = $request.url;
const res = {
- url: raw.replace(/%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)&/g, '&')
+ url: url.replace(/%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)&/g, '&')
};
- SwitchRegion(raw).then(() => $done(res));
+ SwitchRegion(url).then(() => $done(res));
}
}
@@ -157,7 +159,7 @@ async function QueryRating(body, play) {
const ratingEnabled = $.read('BiliDoubanRating') === 'false';
if (!ratingEnabled && play.title && body.data && body.data.badge_info) {
const [t1, t2] = await Promise.all([
- GetRawInfo(play.title),
+ GetRawInfo(play.title.replace(/\uff08\u50c5[\u4e00-\u9fa5]+\u5340\uff09/, '')),
GetRawInfo(play.origin_name)
]);
const exYear = body.data.publish.release_date_show.split(/^(\d{4})/)[1];
From 15c42fbc411d5b865c6619430ee4099372db8672 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Tue, 5 Jul 2022 12:05:42 +0800
Subject: [PATCH 035/105] Fix QuantumultX resource parser issue
---
Surge/JS/Bili_Auto_Regions.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Surge/JS/Bili_Auto_Regions.js b/Surge/JS/Bili_Auto_Regions.js
index dd48762eba..afa43cdc4c 100644
--- a/Surge/JS/Bili_Auto_Regions.js
+++ b/Surge/JS/Bili_Auto_Regions.js
@@ -65,7 +65,7 @@ Loon 远程脚本配置 :
http-response ^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/(pgc\/view\/v\d\/app\/season|x\/offline\/version)\? script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js, requires-body=true, tag=bili自动地区
#可选, 适用于搜索指定地区的番剧
-http-request ^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/x\/v\d\/search(\/type)?\?.+?%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)& script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js, requires-body=true, tag=bili自动地区(搜索)
+http-request ^https:\/\/ap(p|i)\.bili(bili|api)\.(com|net)\/x\/v\d\/search(\/type)?\?.+?%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)& script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Bili_Auto_Regions.js, tag=bili自动地区(搜索)
[Mitm]
hostname = ap?.bili*i.com, ap?.bili*i.net
@@ -140,7 +140,7 @@ function EnvInfo() {
const t2 = raw.code === -404 ? -404 : null;
SwitchRegion(t1 || t2)
.then(s => s ? $done({
- status: $.isQuanX ? "HTTP/1.1 307" : 307,
+ status: $.isQuanX ? "HTTP/1.1 307" :307,
headers: {
Location: url
},
From 0d7b085d51d6e5ce2cdfebc12587e2af21d8611a Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 9 Jul 2022 18:48:09 +0800
Subject: [PATCH 036/105] Update desc.
---
QuantumultX/File/vsco.js | 4 +---
QuantumultX/Js.conf | 2 +-
README.md | 41 ++++++++++++++++++++--------------------
3 files changed, 22 insertions(+), 25 deletions(-)
diff --git a/QuantumultX/File/vsco.js b/QuantumultX/File/vsco.js
index 63c425fd7f..2d8f247e56 100644
--- a/QuantumultX/File/vsco.js
+++ b/QuantumultX/File/vsco.js
@@ -1,5 +1,5 @@
/********************************
-Membership unlock for VSCO & Fileball & 1Blocker
+Membership unlock for VSCO & 1Blocker
Please note that you may need to reinstall app for script to work.
QuantumultX rewrite link:
@@ -23,8 +23,6 @@ const obj = JSON.parse(typeof $response != "undefined" && $response.body || null
const ua = $request.headers['User-Agent'] || $request.headers['user-agent'];
const list = {
'VSCO': { name: 'membership', id: 'com.circles.fin.premium.yearly' },
- 'Filebox': { name: 'filebox_pro', id: 'com.premium.yearly' },
- 'Fileball': { name: 'filebox_pro', id: 'com.premium.yearly' },
'1Blocker': { name: 'premium', id: 'blocker.ios.subscription.yearly' }
};
const data = {
diff --git a/QuantumultX/Js.conf b/QuantumultX/Js.conf
index a792377fc9..9ee1991606 100644
--- a/QuantumultX/Js.conf
+++ b/QuantumultX/Js.conf
@@ -13,7 +13,7 @@ hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.
# 知音漫客VIP
^https:\/\/apigate\.zymk\.cn\/(zymk-getuserinfo-api\/v1\/getuserinfo|zymk-userpurchased-api\/v1\/userpurchased\/paychapters)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
-# VSCO & Fileball(Filebox) & 1Blocker
+# VSCO & 1Blocker
^https?:\/\/api\.revenuecat\.com\/v\d\/subscribers\/ url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
^https?:\/\/api\.revenuecat\.com\/v\d\/subscribers\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js
diff --git a/README.md b/README.md
index 801050c207..5019cc29bd 100644
--- a/README.md
+++ b/README.md
@@ -52,27 +52,26 @@
### Other Script
-| Application | Script name | Description | Available |
-|:---------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------:|:---------------------------------------------:|:-------------:|
-| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
-| [Fileball](https://apps.apple.com/app/id1558391784) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
-| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
-| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅(2022/07/03) |
-| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ✅(2022/07/03) |
-| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅(2022/07/03) |
-| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ✅(2022/07/03) |
-| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ✅(2022/07/03) |
-| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ✅(2022/07/03) |
-| [酷我音乐](https://apps.apple.com/cn/app/id588673713) | [Kuwo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Kuwo.js) | Unlock vip listen | ✅(2022/07/03) |
-| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ✅(2022/07/03) |
-| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ✅(2022/07/03) |
-| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅(2022/07/03) |
-| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅(2022/07/03) |
-| [WPS Office](https://apps.apple.com/app/id1491101673) | [Wps.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js) | Unlock membership | ✅(2022/07/03) |
-| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅(2022/07/03) |
-| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅(2022/07/03) |
-| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ✅(2022/07/03) |
-| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅(2022/07/03) |
+| Application | Script name | Description | Available |
+|:---------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------:|:-----------------------:|:-------------:|
+| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
+| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
+| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅(2022/07/03) |
+| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ✅(2022/07/03) |
+| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅(2022/07/03) |
+| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ✅(2022/07/03) |
+| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ✅(2022/07/03) |
+| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ✅(2022/07/03) |
+| [酷我音乐](https://apps.apple.com/cn/app/id588673713) | [Kuwo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Kuwo.js) | Unlock vip listen | ✅(2022/07/03) |
+| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ✅(2022/07/03) |
+| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ✅(2022/07/03) |
+| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅(2022/07/03) |
+| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅(2022/07/03) |
+| [WPS Office](https://apps.apple.com/app/id1491101673) | [Wps.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js) | Unlock membership | ✅(2022/07/03) |
+| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅(2022/07/03) |
+| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅(2022/07/03) |
+| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ✅(2022/07/03) |
+| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅(2022/07/03) |
---
From 18dd5361c8101d981fdcec31432714f00946eddd Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 11 Jul 2022 15:04:40 +0800
Subject: [PATCH 037/105] Update Surge modules.
---
Surge/Module/HuiJuDongManAds.sgmodule | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/Surge/Module/HuiJuDongManAds.sgmodule b/Surge/Module/HuiJuDongManAds.sgmodule
index db544f506d..d339ec365c 100644
--- a/Surge/Module/HuiJuDongManAds.sgmodule
+++ b/Surge/Module/HuiJuDongManAds.sgmodule
@@ -1,18 +1,16 @@
#!name=荟聚动漫
#!desc=去除大多数弹屏以及底栏广告, 由于有广告缓存, 因此可能需要卸载App重装. @NobyDa
-# Update at 2021.01.30
+# Update at 2022/07/11
[Rule]
-#检测
-DOMAIN,www.umeng.com,DIRECT
-DOMAIN,www.adview.cn,DIRECT
-DOMAIN,adview.cn,DIRECT
#底栏
DOMAIN,googleads.g.doubleclick.net,REJECT-TINYGIF
DOMAIN,www.19831110.com,REJECT-TINYGIF
#HTTP
AND,((USER-AGENT,%E8%8D%9F%E8%81%9A%E5%8A%A8%E6%BC%AB*), (URL-REGEX,\/ad)),REJECT-TINYGIF
+#开屏
+DOMAIN-SUFFIX,admobile.top,REJECT-TINYGIF
[URL Rewrite]
#弹屏, 搜索, 以及底栏白屏广告
@@ -24,4 +22,4 @@ AND,((USER-AGENT,%E8%8D%9F%E8%81%9A%E5%8A%A8%E6%BC%AB*), (URL-REGEX,\/ad)),REJEC
^https?:\/\/.+?\.snssdk\.com\/ad\/ - reject
[MITM]
-hostname = %APPEND% sf?-ttcdn-tos.pstatp.com, www.51devapp.com, *.snssdk.com, www.19831110.com, api-access.pangolin-sdk-toutiao.com, os8.pw
\ No newline at end of file
+hostname = %APPEND% sf?-ttcdn-tos.pstatp.com, www.51devapp.com, *.snssdk.com, www.19831110.com, api-access.pangolin-sdk-toutiao.com, os8.pw, www.umeng.com, www.adview.cn, adview.cn
\ No newline at end of file
From 594d33435946952e0fb573c83be57997c2af5884 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 29 Jul 2022 21:03:53 +0800
Subject: [PATCH 038/105] Fix some issues with Bili_Auto_Regions.js
---
QuantumultX/Bilibili.list | 13 +++++++++++++
Surge/Bilibili.list | 13 +++++++++++++
Surge/JS/Bili_Auto_Regions.js | 35 ++++++++++++++++++-----------------
3 files changed, 44 insertions(+), 17 deletions(-)
create mode 100644 QuantumultX/Bilibili.list
create mode 100644 Surge/Bilibili.list
diff --git a/QuantumultX/Bilibili.list b/QuantumultX/Bilibili.list
new file mode 100644
index 0000000000..fee8848e83
--- /dev/null
+++ b/QuantumultX/Bilibili.list
@@ -0,0 +1,13 @@
+# 该规则集用于配合bilibili自动地区脚本使用。
+host,api.biliapi.com,Bilibili
+host,api.biliapi.net,Bilibili
+host,api.bilibili.com,Bilibili
+host,app.biliapi.com,Bilibili
+host,app.biliapi.net,Bilibili
+host,app.bilibili.com,Bilibili
+host,grpc.biliapi.net,Bilibili
+host,m.bilibili.com,Bilibili
+host,upos-hz-mirrorakam.akamaized.net,Bilibili
+host,www.bilibili.com,Bilibili
+host-keyword,cn-hk-eq-bcache-,Bilibili
+ip-cidr,121.11.192.0/24,Bilibili
\ No newline at end of file
diff --git a/Surge/Bilibili.list b/Surge/Bilibili.list
new file mode 100644
index 0000000000..662803c9f0
--- /dev/null
+++ b/Surge/Bilibili.list
@@ -0,0 +1,13 @@
+# 该规则集用于配合bilibili自动地区脚本使用。
+DOMAIN,api.biliapi.com
+DOMAIN,api.biliapi.net
+DOMAIN,api.bilibili.com
+DOMAIN,app.biliapi.com
+DOMAIN,app.biliapi.net
+DOMAIN,app.bilibili.com
+DOMAIN,grpc.biliapi.net
+DOMAIN,m.bilibili.com
+DOMAIN,upos-hz-mirrorakam.akamaized.net
+DOMAIN,www.bilibili.com
+DOMAIN-KEYWORD,cn-hk-eq-bcache-
+IP-CIDR,121.11.192.0/24,no-resolve
\ No newline at end of file
diff --git a/Surge/JS/Bili_Auto_Regions.js b/Surge/JS/Bili_Auto_Regions.js
index afa43cdc4c..e7674241ad 100644
--- a/Surge/JS/Bili_Auto_Regions.js
+++ b/Surge/JS/Bili_Auto_Regions.js
@@ -5,7 +5,7 @@
如需禁用豆瓣评分或策略通知, 可前往BoxJs设置.
BoxJs订阅地址: https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
-Update: 2022.07.05
+Update: 2022.07.29
Author: @NobyDa
Use: Surge, QuanX, Loon
@@ -18,10 +18,10 @@ Use: Surge, QuanX, Loon
您需要配置相关规则集:
Surge、Loon:
-https://raw.githubusercontent.com/DivineEngine/Profiles/master/Surge/Ruleset/StreamingMedia/StreamingSE.list
+https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Bilibili.list
QuanX:
-https://raw.githubusercontent.com/DivineEngine/Profiles/master/Quantumult/Filter/StreamingMedia/StreamingSE.list
+https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Bilibili.list
绑定相关select或static策略组,并且需要具有相关的区域代理服务器纳入您的子策略中,子策略可以是服务器也可以是其他区域策略组.
最后,您可以通过BoxJs设置策略名和子策略名,或者手动填入脚本.
@@ -108,7 +108,7 @@ async function SwitchRegion(play) {
if (!notify) {
$.notify((/^(http|-404)/.test(play) || !play) ? `` : play, ``, msg);
} else {
- console.log(`${(/^(http|-404)/.test(play)||!play)?``:play}\n${msg}`);
+ console.log(`${(/^(http|-404)/.test(play) || !play) ? `` : play}\n${msg}`);
}
if (change) {
return true;
@@ -133,14 +133,15 @@ function SwitchStatus(status, original, newPolicy) {
function EnvInfo() {
const url = $request.url;
- if (typeof($response) !== 'undefined') {
+ if (typeof ($response) !== 'undefined') {
const raw = JSON.parse($response.body || "{}");
const data = raw.data || raw.result || {};
- const t1 = (data.series && data.series.series_title) || data.title;
+ const t1 = [data.title, data.series && data.series.series_title, data.season_title]
+ .filter(c => /\u50c5[\u4e00-\u9fa5]+\u5340/.test(c))[0] || data.title;
const t2 = raw.code === -404 ? -404 : null;
SwitchRegion(t1 || t2)
.then(s => s ? $done({
- status: $.isQuanX ? "HTTP/1.1 307" :307,
+ status: $.isQuanX ? "HTTP/1.1 307" : 307,
headers: {
Location: url
},
@@ -172,12 +173,12 @@ async function QueryRating(body, play) {
.replace(/"\u53d7\u9650"/g, `""`).replace(/("area_limit":)1/g, '$10');
body.data.modules = JSON.parse(limit);
body.data.detail = body.data.new_ep.desc.replace(/连载中,/, '');
- body.data.badge_info.text = `⭐️ 豆瓣:${!$.is403?`${rating||'无评'}分 (${folk||'无评价'})`:`查询频繁!`}`;
- body.data.evaluate = `${body.data.evaluate||''}\n\n豆瓣评分搜索结果: ${JSON.stringify(other,0,1)}`;
+ body.data.badge_info.text = `⭐️ 豆瓣:${!$.is403 ? `${rating || '无评'}分 (${folk || '无评价'})` : `查询频繁!`}`;
+ body.data.evaluate = `${body.data.evaluate || ''}\n\n豆瓣评分搜索结果: ${JSON.stringify(other, 0, 1)}`;
body.data.new_ep.desc = name;
body.data.styles.unshift({
name: "⭐️ 点击此处打开豆瓣剧集详情页",
- url: `https://m.douban.com/${id?`movie/subject/${id}/`:`search/?query=${encodeURI(play.title)}`}`
+ url: `https://m.douban.com/${id ? `movie/subject/${id}/` : `search/?query=${encodeURI(play.title)}`}`
});
}
} catch (err) {
@@ -257,7 +258,7 @@ function nobyda() {
const isQuanX = typeof $task != "undefined";
const isSurge = typeof $network != "undefined" && typeof $script != "undefined";
const ssid = (() => {
- if (isQuanX && typeof($environment) !== 'undefined') {
+ if (isQuanX && typeof ($environment) !== 'undefined') {
return $environment.ssid;
}
if (isSurge && $network.wifi) {
@@ -287,7 +288,7 @@ function nobyda() {
}
const getPolicy = (groupName) => {
if (isSurge) {
- if (typeof($httpAPI) === 'undefined') return 3;
+ if (typeof ($httpAPI) === 'undefined') return 3;
return new Promise((resolve) => {
$httpAPI("GET", "v1/policy_groups/select", {
group_name: encodeURIComponent(groupName)
@@ -295,12 +296,12 @@ function nobyda() {
})
}
if (isLoon) {
- if (typeof($config.getPolicy) === 'undefined') return 3;
+ if (typeof ($config.getPolicy) === 'undefined') return 3;
const getName = $config.getPolicy(groupName);
return getName || 2;
}
if (isQuanX) {
- if (typeof($configuration) === 'undefined') return 3;
+ if (typeof ($configuration) === 'undefined') return 3;
return new Promise((resolve) => {
$configuration.sendMessage({
action: "get_policy_state"
@@ -313,7 +314,7 @@ function nobyda() {
}
}
const setPolicy = (group, policy) => {
- if (isSurge && typeof($httpAPI) !== 'undefined') {
+ if (isSurge && typeof ($httpAPI) !== 'undefined') {
return new Promise((resolve) => {
$httpAPI("POST", "v1/policy_groups/select", {
group_name: group,
@@ -321,11 +322,11 @@ function nobyda() {
}, (b) => resolve(!b.error || 0))
})
}
- if (isLoon && typeof($config.getPolicy) !== 'undefined') {
+ if (isLoon && typeof ($config.getPolicy) !== 'undefined') {
const set = $config.setSelectPolicy(group, policy);
return set || 0;
}
- if (isQuanX && typeof($configuration) !== 'undefined') {
+ if (isQuanX && typeof ($configuration) !== 'undefined') {
return new Promise((resolve) => {
$configuration.sendMessage({
action: "set_policy_state",
From e954e65166d9b01c6e1ddd3b55fbd7014c4558b2 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 1 Aug 2022 18:18:28 +0800
Subject: [PATCH 039/105] Fix #413
---
Surge/JS/Bili_Auto_Regions.js | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/Surge/JS/Bili_Auto_Regions.js b/Surge/JS/Bili_Auto_Regions.js
index e7674241ad..2b776adf91 100644
--- a/Surge/JS/Bili_Auto_Regions.js
+++ b/Surge/JS/Bili_Auto_Regions.js
@@ -5,7 +5,7 @@
如需禁用豆瓣评分或策略通知, 可前往BoxJs设置.
BoxJs订阅地址: https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
-Update: 2022.07.29
+Update: 2022.08.01
Author: @NobyDa
Use: Surge, QuanX, Loon
@@ -85,10 +85,10 @@ async function SwitchRegion(play) {
const current = await $.getPolicy(Group);
const area = (() => {
let select;
- if (/\u50c5[\u4e00-\u9fa5]+\u6e2f|%20%E6%B8%AF&/.test(play)) {
- const test = /\u50c5[\u4e00-\u9fa5]+\u53f0/.test(play);
+ if (/\u6e2f[\u4e00-\u9fa5]+\u5340|%20%E6%B8%AF&/.test(play)) {
+ const test = /\u53f0[\u4e00-\u9fa5]+\u5340/.test(play);
if (current != HK && (current == TW && test ? 0 : 1)) select = HK;
- } else if (/\u50c5[\u4e00-\u9fa5]+\u53f0|%20%E5%8F%B0&/.test(play)) {
+ } else if (/\u53f0[\u4e00-\u9fa5]+\u5340|%20%E5%8F%B0&/.test(play)) {
if (current != TW) select = TW;
} else if (play === -404) {
if (current != DF) select = DF;
@@ -137,7 +137,7 @@ function EnvInfo() {
const raw = JSON.parse($response.body || "{}");
const data = raw.data || raw.result || {};
const t1 = [data.title, data.series && data.series.series_title, data.season_title]
- .filter(c => /\u50c5[\u4e00-\u9fa5]+\u5340/.test(c))[0] || data.title;
+ .filter(c => /\u5340\uff09/.test(c))[0] || data.title;
const t2 = raw.code === -404 ? -404 : null;
SwitchRegion(t1 || t2)
.then(s => s ? $done({
@@ -160,7 +160,7 @@ async function QueryRating(body, play) {
const ratingEnabled = $.read('BiliDoubanRating') === 'false';
if (!ratingEnabled && play.title && body.data && body.data.badge_info) {
const [t1, t2] = await Promise.all([
- GetRawInfo(play.title.replace(/\uff08\u50c5[\u4e00-\u9fa5]+\u5340\uff09/, '')),
+ GetRawInfo(play.title.replace(/\uff08[\u4e00-\u9fa5]+\u5340\uff09/, '')),
GetRawInfo(play.origin_name)
]);
const exYear = body.data.publish.release_date_show.split(/^(\d{4})/)[1];
From fdd12605eb424dbb05e34677d3ebd34504710d2a Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 1 Aug 2022 18:22:49 +0800
Subject: [PATCH 040/105] Fix #409
---
QuantumultX/AdRule.list | 3 +--
Surge/AdRule.list | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/QuantumultX/AdRule.list b/QuantumultX/AdRule.list
index 982da34a0c..1a643e40e8 100644
--- a/QuantumultX/AdRule.list
+++ b/QuantumultX/AdRule.list
@@ -1,4 +1,4 @@
-# Update > 2022.1.26
+# Update > 2022/08/01
DOMAIN-SUFFIX,api-access.pangolin-sdk-toutiao-b.com,REJECT
DOMAIN-SUFFIX,apoll.m.taobao.com,REJECT
DOMAIN-SUFFIX,comet.yahoo.com,REJECT
@@ -2052,7 +2052,6 @@ DOMAIN-SUFFIX,cdn.mdotm.com,REJECT
DOMAIN-SUFFIX,cdn.media.innity.net,REJECT
DOMAIN-SUFFIX,cdn.millennialmedia.com,REJECT
DOMAIN-SUFFIX,cdn.mingmingtehui.com,REJECT
-DOMAIN-SUFFIX,cdn.moji.com,REJECT
DOMAIN-SUFFIX,cdn.moji002.com,REJECT
DOMAIN-SUFFIX,cdn.moogos.com,REJECT
DOMAIN-SUFFIX,cdn.ndapp.com,REJECT
diff --git a/Surge/AdRule.list b/Surge/AdRule.list
index f8649115d4..f90b5412b6 100644
--- a/Surge/AdRule.list
+++ b/Surge/AdRule.list
@@ -1,4 +1,4 @@
-# Update > 2022.1.26
+# Update > 2022/08/01
DOMAIN-SUFFIX,api-access.pangolin-sdk-toutiao-b.com
DOMAIN-SUFFIX,mcupdate.gstarcad.com
DOMAIN-SUFFIX,adx.open-adx.com
@@ -2063,7 +2063,6 @@ DOMAIN-SUFFIX,cdn.mdotm.com
DOMAIN-SUFFIX,cdn.media.innity.net
DOMAIN-SUFFIX,cdn.millennialmedia.com
DOMAIN-SUFFIX,cdn.mingmingtehui.com
-DOMAIN-SUFFIX,cdn.moji.com
DOMAIN-SUFFIX,cdn.moji002.com
DOMAIN-SUFFIX,cdn.moogos.com
DOMAIN-SUFFIX,cdn.ndapp.com
From bf80e28b0f6c59d6da61af2ff0c1d97dc1cf2dc0 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 2 Sep 2022 16:17:34 +0800
Subject: [PATCH 041/105] Fix #418
---
QuantumultX/AdRuleTest.list | 1 -
Surge/AdRule.list | 1 -
2 files changed, 2 deletions(-)
diff --git a/QuantumultX/AdRuleTest.list b/QuantumultX/AdRuleTest.list
index 9b228a8163..48b0903ea1 100644
--- a/QuantumultX/AdRuleTest.list
+++ b/QuantumultX/AdRuleTest.list
@@ -1190,7 +1190,6 @@ DOMAIN-SUFFIX,video.c-ctrip.com,REJECT
DOMAIN-SUFFIX,agn.aty.sohu.com,REJECT
DOMAIN-SUFFIX,map-mobile-opnimg.cdn.bcebos.com,REJECT
DOMAIN-SUFFIX,app.adjust.com,REJECT
-DOMAIN-SUFFIX,mob.com,REJECT
DOMAIN-SUFFIX,adthor.com,REJECT
DOMAIN-SUFFIX,pubnative.net,REJECT
DOMAIN-SUFFIX,flurry.com,REJECT
diff --git a/Surge/AdRule.list b/Surge/AdRule.list
index f90b5412b6..f6f1ad41fd 100644
--- a/Surge/AdRule.list
+++ b/Surge/AdRule.list
@@ -8355,7 +8355,6 @@ DOMAIN-SUFFIX,zunmi.cn
DOMAIN-SUFFIX,zzd6.com
DOMAIN-SUFFIX,mackeeper.com
DOMAIN-SUFFIX,app-measurement.com
-DOMAIN-SUFFIX,mob.com
DOMAIN-SUFFIX,api.joybj.com
DOMAIN-SUFFIX,api.whizzone.com
DOMAIN-SUFFIX,mmstat.com
From d90e51d6aba210a39a06beff004a2f70a9c7aba4 Mon Sep 17 00:00:00 2001
From: yyl217 <66333072+yyl217@users.noreply.github.com>
Date: Sat, 24 Sep 2022 16:08:51 +0800
Subject: [PATCH 042/105] Update WeChat.list (#424)
---
Surge/WeChat.list | 1 +
1 file changed, 1 insertion(+)
diff --git a/Surge/WeChat.list b/Surge/WeChat.list
index 97cbf92810..7ab3a69558 100644
--- a/Surge/WeChat.list
+++ b/Surge/WeChat.list
@@ -210,6 +210,7 @@ DOMAIN-KEYWORD,61.241.44.
DOMAIN-KEYWORD,61.241.47.
DOMAIN-KEYWORD,61.241.49.
DOMAIN-KEYWORD,43.156.86.
+DOMAIN-KEYWORD,43.156.222.
# WeChat Pay SDK
DOMAIN-KEYWORD,101.226.129.
From f87ce0b68b95d1ba24b43c366facbe43672d42f0 Mon Sep 17 00:00:00 2001
From: BlueSkyClouds <1471223507@qq.com>
Date: Wed, 9 Nov 2022 00:16:31 +0800
Subject: [PATCH 043/105] delete WebCheckin (#428)
---
iQIYI-DailyBonus/iQIYI.js | 56 +--------------------------------------
1 file changed, 1 insertion(+), 55 deletions(-)
diff --git a/iQIYI-DailyBonus/iQIYI.js b/iQIYI-DailyBonus/iQIYI.js
index 9e4efa0c8a..81e3af7704 100644
--- a/iQIYI-DailyBonus/iQIYI.js
+++ b/iQIYI-DailyBonus/iQIYI.js
@@ -1,7 +1,7 @@
/*
爱奇艺会员签到脚本
-更新时间: 2022.06.18
+更新时间: 2022.11.08
脚本兼容: QuantumultX, Surge4, Loon, JsBox, Node.js
电报频道: @NobyDa
问题反馈: @NobyDa_bot
@@ -102,7 +102,6 @@ var $nobyda = nobyda();
dfp = cookie.match(/__dfp=(.*?)@/)[1];
await login();
await Checkin();
- await WebCheckin();
for (let i = 0; i < 3; i++){
const run = await Lottery(i);
if (run) {
@@ -236,59 +235,6 @@ function Checkin() {
})
}
-function WebCheckin() {
- return new Promise(resolve => {
- const web_sign_date = {
- agenttype: "1",
- agentversion: "0",
- appKey: "basic_pca",
- appver: "0",
- authCookie: P00001,
- channelCode: "sign_pcw",
- dfp: dfp,
- scoreType: "1",
- srcplatform: "1",
- typeCode: "point",
- userId: P00003,
- // user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36",
- verticalCode: "iQIYI"
- };
-
- const sign = k("DO58SzN6ip9nbJ4QkM8H", web_sign_date, {
- split: "|",
- sort: !0,
- splitSecretKey: !0
- });
- var URL = {
- url: 'https://community.iqiyi.com/openApi/score/add?' + w(web_sign_date) + "&sign=" + sign
- }
- $nobyda.get(URL, function(error, response, data) {
- let WebCheckinMsg = '';
- const Details = LogDetails ? `msg:\n${data||error}` : ''
- try {
- if (error) throw new Error(`接口请求出错 ‼️`);
- const obj = JSON.parse(data)
- if (obj.code === "A00000") {
- if (obj.data[0].code === "A0000") {
- var quantity = obj.data[0].score;
- var continued = obj.data[0].continuousValue;
- WebCheckinMsg = "网页签到: 积分+" + quantity + ", 累计签到" + continued + "天 🎉"
- } else {
- WebCheckinMsg = "网页签到: " + obj.data[0].message + " ⚠️"
- }
- } else {
- WebCheckinMsg = `网页签到: ${obj.message||'未知错误'} ⚠️`
- }
- } catch (e) {
- WebCheckinMsg = `网页签到: ${e.message || e}`;
- }
- pushMsg.push(WebCheckinMsg);
- console.log(`爱奇艺-${WebCheckinMsg} ${Details}`);
- resolve()
- })
- })
-}
-
function Lottery(s) {
return new Promise(resolve => {
const URL = {
From 398648138597913c6d6637e5b0a34cb176d59505 Mon Sep 17 00:00:00 2001
From: Pegasus02 <102945996+Pegasus02@users.noreply.github.com>
Date: Fri, 11 Nov 2022 23:32:09 +0800
Subject: [PATCH 044/105] =?UTF-8?q?$loon=E7=9A=84=E8=BE=93=E5=87=BA?=
=?UTF-8?q?=E4=B8=8D=E5=86=8D=E6=94=AF=E6=8C=81=E4=B8=8A=E8=BF=B0=E4=BB=A3?=
=?UTF-8?q?=E7=A0=81=EF=BC=8C=E5=9B=A0=E6=AD=A4=E8=BF=99=E9=87=8C=E5=8F=AA?=
=?UTF-8?q?=E8=83=BD=E5=88=A0=E9=99=A4=20(#430)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Shortcuts/PolicySwitch.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Shortcuts/PolicySwitch.js b/Shortcuts/PolicySwitch.js
index 05c41fa5d8..432e867398 100644
--- a/Shortcuts/PolicySwitch.js
+++ b/Shortcuts/PolicySwitch.js
@@ -36,7 +36,7 @@ const body = JSON.parse($request.body || '{}');
})()
function nobyda() {
- const isLoon = typeof($loon) !== "undefined" && $loon > 289;
+ const isLoon = typeof($loon) !== "undefined";
const isQuanX = typeof($configuration) !== 'undefined';
const isSurge = typeof($httpAPI) !== 'undefined';
const m = `不支持您的APP版本, 请等待APP更新 ⚠️`;
From 2c9001c784d8f1a5266ac949d9fb4f4b539c838f Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 16 Jan 2023 00:34:37 +0800
Subject: [PATCH 045/105] Refresh date.
---
QuantumultX/File/wnyd.js | 2 +-
Surge/JS/BaiduCloud.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/QuantumultX/File/wnyd.js b/QuantumultX/File/wnyd.js
index c40f1c7bc4..c0f0673276 100644
--- a/QuantumultX/File/wnyd.js
+++ b/QuantumultX/File/wnyd.js
@@ -24,6 +24,6 @@ hostname = p.du.163.com
var body = $response.body;
var obj = JSON.parse(body);
-obj.tradeEndTime = 1679685290000;
+obj.tradeEndTime = 1879685290000;
body = JSON.stringify(obj);
$done({body});
diff --git a/Surge/JS/BaiduCloud.js b/Surge/JS/BaiduCloud.js
index 90004925ee..68cdcaa774 100644
--- a/Surge/JS/BaiduCloud.js
+++ b/Surge/JS/BaiduCloud.js
@@ -41,7 +41,7 @@ if ($response.body) {
"buy_time": 0,
"product_id": "1",
"auto_upgrade_to_svip": 0,
- "end_time": 1672502399,
+ "end_time": 1872502399,
"cluster": "vip",
"detail_cluster": "svip",
"status": 0
From 9afc5407a99b68c8a506808515c83e61014346b7 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 16 Jan 2023 00:43:43 +0800
Subject: [PATCH 046/105] Add bypass Google CAPTCHA script.
---
Surge/JS/Google_CAPTCHA.js | 63 ++++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
create mode 100644 Surge/JS/Google_CAPTCHA.js
diff --git a/Surge/JS/Google_CAPTCHA.js b/Surge/JS/Google_CAPTCHA.js
new file mode 100644
index 0000000000..0b33470c25
--- /dev/null
+++ b/Surge/JS/Google_CAPTCHA.js
@@ -0,0 +1,63 @@
+/*
+Google搜索内容时并发使用多个策略(组),以避免可能出现的人机验证
+
+注:该脚本仅兼容Surge(4.9.3+),使用时需要在脚本配置内的argument参数中填写筛选策略(组)的正则表达式,留空则表示同时使用所有策略(组)
+
+Surge脚本配置:
+
+[Script]
+Google CAPTCHA = type=http-response,pattern=^https:\/\/www\.google\.com(\.[a-z]+|)\/search\?q=,requires-body=1,debug=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js,max-size=0,timeout=10,ability=http-client-policy,argument=^(🇸🇬|🇭🇰)\s.*\d+$
+
+[MITM]
+hostname = www.google.com*
+
+*/
+
+let ret = {};
+
+(async () => {
+ if ($response.status !== 200) {
+ const allPolicy = await new Promise((r) => {
+ $httpAPI("GET", "v1/policies", null, (v) => r(
+ [...v.proxies, ...v['policy-groups']]
+ ))
+ });
+ const selected = allPolicy.filter((n) => {
+ return n && new RegExp(typeof $argument == 'string' ? $argument : "").test(n)
+ });
+ console.log(`[INFO]: Use policy ${JSON.stringify(selected, null, 2)}`);
+ const http = [
+ new Promise((r, e) => setTimeout(() => e('Timeout'), 5000)),
+ ...selected.map(
+ (v) => new Promise((r, e) => {
+ $httpClient[$request.method.toLowerCase()]({
+ url: $request.url,
+ headers: $request.headers,
+ policy: v
+ }, (error, response, body) => {
+ if (response && response.status == 200) {
+ r({
+ policy: v,
+ body: {
+ headers: response.headers,
+ status: response.status,
+ body: body
+ }
+ })
+ } else if (response && response.status == 429) {
+ console.log(`[ERROR]: Policy "${v}" need to CAPTCHA`);
+ } else if (error) {
+ console.log(`[ERROR]: Policy "${v}" ${error}`);
+ }
+ })
+ })
+ )
+ ];
+ await Promise.race(http).then((data) => {
+ ret = data.body;
+ console.log(`[INFO]: Use data from "${data.policy}"`);
+ });
+ }
+})()
+ .catch((err) => console.log(`[ERROR]: ${(err && err.message) || err}`))
+ .finally(() => $done(ret));
\ No newline at end of file
From fdb3a405b2ba9fc4a26b657e1963ba44c8451691 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 10 Feb 2023 17:12:12 +0800
Subject: [PATCH 047/105] Improve region match accuracy.
---
Surge/JS/Bili_Auto_Regions.js | 79 ++++++++++++++++++-----------------
1 file changed, 41 insertions(+), 38 deletions(-)
diff --git a/Surge/JS/Bili_Auto_Regions.js b/Surge/JS/Bili_Auto_Regions.js
index 2b776adf91..d20497ec6c 100644
--- a/Surge/JS/Bili_Auto_Regions.js
+++ b/Surge/JS/Bili_Auto_Regions.js
@@ -1,11 +1,11 @@
/**************************
-哔哩哔哩, 港澳台番剧自动切换地区 & 显示豆瓣评分
+哔哩哔哩(白图标外区版), 港澳台番剧自动切换地区 & 显示豆瓣评分
如需禁用豆瓣评分或策略通知, 可前往BoxJs设置.
BoxJs订阅地址: https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
-Update: 2022.08.01
+Update: 2023.02.10
Author: @NobyDa
Use: Surge, QuanX, Loon
@@ -75,7 +75,7 @@ hostname = ap?.bili*i.com, ap?.bili*i.net
let $ = nobyda();
let run = EnvInfo();
-async function SwitchRegion(play) {
+async function SwitchRegion(title, url, body) {
const Group = $.read('BiliArea_Policy') || '📺 DomesticMedia'; //Your blibli policy group name.
const CN = $.read('BiliArea_CN') || 'DIRECT'; //Your China sub-policy name.
const TW = $.read('BiliArea_TW') || '🇹🇼 sub-policy'; //Your Taiwan sub-policy name.
@@ -84,31 +84,44 @@ async function SwitchRegion(play) {
const off = $.read('BiliArea_disabled') || ''; //WiFi blacklist(disable region change), separated by commas.
const current = await $.getPolicy(Group);
const area = (() => {
- let select;
- if (/\u6e2f[\u4e00-\u9fa5]+\u5340|%20%E6%B8%AF&/.test(play)) {
- const test = /\u53f0[\u4e00-\u9fa5]+\u5340/.test(play);
- if (current != HK && (current == TW && test ? 0 : 1)) select = HK;
- } else if (/\u53f0[\u4e00-\u9fa5]+\u5340|%20%E5%8F%B0&/.test(play)) {
- if (current != TW) select = TW;
- } else if (play === -404) {
- if (current != DF) select = DF;
+ let select = {};
+ let chtMatch = title && title.split('').some(v => zhHans().includes(v));
+ if (/\u6e2f[\u4e00-\u9fa5]+\u5340|%20%E6%B8%AF&/.test(title || url)) {
+ const test = /\u53f0[\u4e00-\u9fa5]+\u5340/.test(title);
+ if (current != HK && (current == TW && test ? 0 : 1))
+ select = { policy: HK, mode: '香港' };
+ } else if (/\u53f0[\u4e00-\u9fa5]+\u5340|%20%E5%8F%B0&/.test(title || url)) {
+ if (current != TW) select = { policy: TW, mode: '台湾' };
+ } else if (body.code === -404 || chtMatch) {
+ if (current != DF) select = { policy: DF, mode: '后备' };
} else if (current != CN) {
- select = CN;
+ select = { policy: CN, mode: '直连' };
}
if ($.isQuanX && current === 'direct' && select === 'DIRECT') {
- select = null; //avoid loops in some cases
+ select = {}; //prevent loopback in some cases
}
return select;
})()
- if (area && !off.includes($.ssid || undefined)) {
- const change = await $.setPolicy(Group, area);
- const notify = $.read('BiliAreaNotify') === 'true';
- const msg = SwitchStatus(change, current, area);
- if (!notify) {
- $.notify((/^(http|-404)/.test(play) || !play) ? `` : play, ``, msg);
+ if (area.policy && !off.includes($.ssid || undefined)) {
+ const change = await $.setPolicy(Group, area.policy);
+ const msg = (() => {
+ if (change && typeof current !== 'number') {
+ return `${current} ➤ ${area.policy}`;
+ } else if (current === 2) {
+ return `策略组名未填写或填写有误 ⚠️`
+ } else if (current === 3) {
+ return `不支持您的VPN应用版本 ⚠️`
+ } else if (change === 0) {
+ return `子策略名未填写或填写有误 ⚠️`
+ } else {
+ return `未知错误 ⚠️`
+ }
+ })()
+ if ($.read('BiliAreaNotify') === 'true') {
+ console.log(`${title || ''}\n模式: 策略组使用"${area.mode}"子策略\n走向: ${msg}`);
} else {
- console.log(`${(/^(http|-404)/.test(play) || !play) ? `` : play}\n${msg}`);
+ $.notify(title || '', ``, `模式: 策略组使用"${area.mode}"子策略\n走向: ${msg}`);
}
if (change) {
return true;
@@ -117,29 +130,14 @@ async function SwitchRegion(play) {
return false;
}
-function SwitchStatus(status, original, newPolicy) {
- if (status && typeof original !== 'number') {
- return `${original} => ${newPolicy} => 🟢`;
- } else if (original === 2) {
- return `切换失败, 策略组名未填写或填写有误 ⚠️`
- } else if (original === 3) {
- return `切换失败, 不支持您的VPN应用版本 ⚠️`
- } else if (status === 0) {
- return `切换失败, 子策略名未填写或填写有误 ⚠️`
- } else {
- return `策略切换失败, 未知错误 ⚠️`
- }
-}
-
function EnvInfo() {
const url = $request.url;
if (typeof ($response) !== 'undefined') {
const raw = JSON.parse($response.body || "{}");
const data = raw.data || raw.result || {};
- const t1 = [data.title, data.series && data.series.series_title, data.season_title]
+ const title = [data.title, data.series && data.series.series_title, data.season_title]
.filter(c => /\u5340\uff09/.test(c))[0] || data.title;
- const t2 = raw.code === -404 ? -404 : null;
- SwitchRegion(t1 || t2)
+ SwitchRegion(title, null, raw)
.then(s => s ? $done({
status: $.isQuanX ? "HTTP/1.1 307" : 307,
headers: {
@@ -151,7 +149,7 @@ function EnvInfo() {
const res = {
url: url.replace(/%20(%E6%B8%AF|%E5%8F%B0|%E4%B8%AD)&/g, '&')
};
- SwitchRegion(url).then(() => $done(res));
+ SwitchRegion(null, url, {}).then(() => $done(res));
}
}
@@ -363,3 +361,8 @@ function nobyda() {
get
}
}
+
+// https://zh.wikipedia.org/wiki/Wikipedia:Unihan%E7%B9%81%E7%AE%80%E4%BD%93%E5%AF%B9%E7%85%A7%E8%A1%A8/%E7%B9%81%E7%AE%80%E4%B8%80%E4%B8%80%E5%AF%B9%E5%BA%94%E8%A1%A8
+function zhHans() {
+ return `䊷䋙䝼䰾䲁丟並乾亂亞佇馀併來侖侶俁係俔俠倀倆倈倉個們倫偉側偵偽傑傖傘備傭傯傳傴債傷傾僂僅僉僑僕僞僥僨價儀儂億儈儉儐儔儕儘償優儲儷儺儻儼兌兒兗內兩冊冪凈凍凜凱別刪剄則剋剎剗剛剝剮剴創劃劇劉劊劌劍劑勁動務勛勝勞勢勩勱勵勸勻匭匯匱區協卻厙厠厭厲厴參叄叢吒吳吶呂咼員唄唚問啓啞啟啢喎喚喪喬單喲嗆嗇嗊嗎嗚嗩嗶嘆嘍嘔嘖嘗嘜嘩嘮嘯嘰嘵嘸嘽噓噝噠噥噦噯噲噴噸噹嚀嚇嚌嚕嚙嚦嚨嚲嚳嚴嚶囀囁囂囅囈囑囪圇國圍園圓圖團垵埡埰執堅堊堖堝堯報場塊塋塏塒塗塢塤塵塹墊墜墮墳墻墾壇壈壋壓壘壙壚壞壟壠壢壩壯壺壼壽夠夢夾奐奧奩奪奬奮奼妝姍姦娛婁婦婭媧媯媼媽嫗嫵嫻嫿嬀嬈嬋嬌嬙嬡嬤嬪嬰嬸孌孫學孿宮寢實寧審寫寬寵寶將專尋對導尷屆屍屓屜屢層屨屬岡峴島峽崍崗崢崬嵐嶁嶄嶇嶔嶗嶠嶢嶧嶮嶴嶸嶺嶼巋巒巔巰帥師帳帶幀幃幗幘幟幣幫幬幹幺幾庫廁廂廄廈廚廝廟廠廡廢廣廩廬廳弒弳張強彈彌彎彙彞彥後徑從徠復徵徹恆恥悅悞悵悶惡惱惲惻愛愜愨愴愷愾慄態慍慘慚慟慣慤慪慫慮慳慶憂憊憐憑憒憚憤憫憮憲憶懇應懌懍懟懣懨懲懶懷懸懺懼懾戀戇戔戧戩戰戱戲戶拋拾挩挾捨捫掃掄掗掙掛採揀揚換揮損搖搗搵搶摑摜摟摯摳摶摻撈撏撐撓撝撟撣撥撫撲撳撻撾撿擁擄擇擊擋擓擔據擠擬擯擰擱擲擴擷擺擻擼擾攄攆攏攔攖攙攛攜攝攢攣攤攪攬敗敘敵數斂斃斕斬斷時晉晝暈暉暘暢暫曄曆曇曉曏曖曠曨曬書會朧東杴极柵桿梔梘條梟梲棄棖棗棟棧棲棶椏楊楓楨業極榪榮榲榿構槍槤槧槨槳樁樂樅樓標樞樣樸樹樺橈橋機橢橫檁檉檔檜檟檢檣檮檯檳檸檻櫃櫓櫚櫛櫝櫞櫟櫥櫧櫨櫪櫫櫬櫱櫳櫸櫻欄權欏欒欖欞欽歐歟歡歲歷歸歿殘殞殤殨殫殮殯殲殺殻殼毀毆毿氂氈氌氣氫氬氳決沒沖況洶浹涇涼淚淥淪淵淶淺渙減渦測渾湊湞湯溈準溝溫滄滅滌滎滬滯滲滷滸滻滾滿漁漚漢漣漬漲漵漸漿潁潑潔潙潛潤潯潰潷潿澀澆澇澗澠澤澦澩澮澱濁濃濕濘濟濤濫濰濱濺濼濾瀅瀆瀉瀏瀕瀘瀝瀟瀠瀦瀧瀨瀲瀾灃灄灑灕灘灝灠灣灤灧災為烏烴無煉煒煙煢煥煩煬熅熒熗熱熲熾燁燈燉燒燙燜營燦燭燴燼燾爍爐爛爭爲爺爾牆牘牽犖犢犧狀狹狽猙猶猻獁獄獅獎獨獪獫獮獰獲獵獷獸獺獻獼玀現琺琿瑋瑒瑣瑤瑩瑪瑲璉璣璦璫環璽瓊瓏瓔瓚甌產産畝畢異畵當疇疊痙痾瘂瘋瘍瘓瘞瘡瘧瘮瘲瘺瘻療癆癇癉癘癟癢癤癥癧癩癬癭癮癰癱癲發皚皰皸皺盜盞盡監盤盧眥眾睏睜睞瞘瞜瞞瞶瞼矓矚矯硜硤硨硯碩碭碸確碼磑磚磣磧磯磽礆礎礙礦礪礫礬礱祿禍禎禕禡禦禪禮禰禱禿秈稅稈稟種稱穀穌積穎穠穡穢穩穫穭窩窪窮窯窵窶窺竄竅竇竈竊竪競筆筍筧筴箋箏節範築篋篔篤篩篳簀簍簞簡簣簫簹簽簾籃籌籙籜籟籠籩籪籬籮粵糝糞糧糲糴糶糹糾紀紂約紅紆紇紈紉紋納紐紓純紕紖紗紘紙級紛紜紝紡紬細紱紲紳紵紹紺紼紿絀終組絅絆絎結絕絛絝絞絡絢給絨絰統絲絳絶絹綁綃綆綈綉綌綏經綜綞綠綢綣綫綬維綯綰綱網綳綴綸綹綺綻綽綾綿緄緇緊緋緑緒緓緔緗緘緙線緝緞締緡緣緦編緩緬緯緱緲練緶緹緻縈縉縊縋縐縑縕縗縛縝縞縟縣縧縫縭縮縱縲縳縵縶縷縹總績繃繅繆繒織繕繚繞繡繢繩繪繫繭繮繯繰繳繸繹繼繽繾纈纊續纍纏纓纖纘纜缽罈罌罰罵罷羅羆羈羋羥義習翹耬耮聖聞聯聰聲聳聵聶職聹聽聾肅脅脈脛脫脹腎腖腡腦腫腳腸膃膚膠膩膽膾膿臉臍臏臘臚臟臠臢臨臺與興舉舊艙艤艦艫艱艷芻苎苧茲荊莊莖莢莧華萇萊萬萵葉葒著葤葦葯葷蒓蒔蒞蒼蓀蓋蓮蓯蓴蓽蔔蔞蔣蔥蔦蔭蕁蕆蕎蕒蕓蕕蕘蕢蕩蕪蕭蕷薀薈薊薌薔薘薟薦薩薴薺藍藎藝藥藪藴藶藹藺蘄蘆蘇蘊蘋蘚蘞蘢蘭蘺蘿虆處虛虜號虧虯蛺蛻蜆蜡蝕蝟蝦蝸螄螞螢螻螿蟄蟈蟎蟣蟬蟯蟲蟶蟻蠅蠆蠐蠑蠟蠣蠨蠱蠶蠻衆術衕衚衛衝衹袞裊裏補裝裡製複褌褘褲褳褸褻襇襏襖襝襠襤襪襯襲見覎規覓視覘覡覥覦親覬覯覲覷覺覽覿觀觴觶觸訁訂訃計訊訌討訐訒訓訕訖託記訛訝訟訢訣訥訩訪設許訴訶診註詁詆詎詐詒詔評詖詗詘詛詞詠詡詢詣試詩詫詬詭詮詰話該詳詵詼詿誄誅誆誇誌認誑誒誕誘誚語誠誡誣誤誥誦誨說説誰課誶誹誼誾調諂諄談諉請諍諏諑諒論諗諛諜諝諞諢諤諦諧諫諭諮諱諳諶諷諸諺諼諾謀謁謂謄謅謊謎謐謔謖謗謙謚講謝謠謡謨謫謬謭謳謹謾證譎譏譖識譙譚譜譫譯議譴護譸譽譾讀變讎讒讓讕讖讜讞豈豎豐豬豶貓貝貞貟負財貢貧貨販貪貫責貯貰貲貳貴貶買貸貺費貼貽貿賀賁賂賃賄賅資賈賊賑賒賓賕賙賚賜賞賠賡賢賣賤賦賧質賫賬賭賴賵賺賻購賽賾贄贅贇贈贊贋贍贏贐贓贔贖贗贛贜赬趕趙趨趲跡踐踴蹌蹕蹣蹤蹺躂躉躊躋躍躑躒躓躕躚躡躥躦躪軀車軋軌軍軑軒軔軛軟軤軫軲軸軹軺軻軼軾較輅輇輈載輊輒輓輔輕輛輜輝輞輟輥輦輩輪輬輯輳輸輻輾輿轀轂轄轅轆轉轍轎轔轟轡轢轤辦辭辮辯農逕這連進運過達違遙遜遞遠適遲遷選遺遼邁還邇邊邏邐郟郵鄆鄉鄒鄔鄖鄧鄭鄰鄲鄴鄶鄺酇酈醖醜醞醫醬醱釀釁釃釅釋釐釒釓釔釕釗釘釙針釣釤釧釩釵釷釹釺鈀鈁鈃鈄鈈鈉鈍鈎鈐鈑鈒鈔鈕鈞鈣鈥鈦鈧鈮鈰鈳鈴鈷鈸鈹鈺鈽鈾鈿鉀鉅鉈鉉鉋鉍鉑鉕鉗鉚鉛鉞鉢鉤鉦鉬鉭鉶鉸鉺鉻鉿銀銃銅銍銑銓銖銘銚銛銜銠銣銥銦銨銩銪銫銬銱銳銷銹銻銼鋁鋃鋅鋇鋌鋏鋒鋙鋝鋟鋣鋤鋥鋦鋨鋩鋪鋭鋮鋯鋰鋱鋶鋸鋼錁錄錆錇錈錏錐錒錕錘錙錚錛錟錠錡錢錦錨錩錫錮錯録錳錶錸鍀鍁鍃鍆鍇鍈鍋鍍鍔鍘鍚鍛鍠鍤鍥鍩鍬鍰鍵鍶鍺鎂鎄鎇鎊鎔鎖鎘鎛鎡鎢鎣鎦鎧鎩鎪鎬鎮鎰鎲鎳鎵鎸鎿鏃鏇鏈鏌鏍鏐鏑鏗鏘鏜鏝鏞鏟鏡鏢鏤鏨鏰鏵鏷鏹鏽鐃鐋鐐鐒鐓鐔鐘鐙鐝鐠鐦鐧鐨鐫鐮鐲鐳鐵鐶鐸鐺鐿鑄鑊鑌鑒鑔鑕鑞鑠鑣鑥鑭鑰鑱鑲鑷鑹鑼鑽鑾鑿钁長門閂閃閆閈閉開閌閎閏閑間閔閘閡閣閥閨閩閫閬閭閱閲閶閹閻閼閽閾閿闃闆闈闊闋闌闍闐闒闓闔闕闖關闞闠闡闤闥阪陘陝陣陰陳陸陽隉隊階隕際隨險隱隴隸隻雋雖雙雛雜雞離難雲電霢霧霽靂靄靈靚靜靦靨鞀鞏鞝鞽韁韃韉韋韌韍韓韙韜韞韻響頁頂頃項順頇須頊頌頎頏預頑頒頓頗領頜頡頤頦頭頮頰頲頴頷頸頹頻頽顆題額顎顏顒顓顔願顙顛類顢顥顧顫顬顯顰顱顳顴風颭颮颯颱颳颶颸颺颻颼飀飄飆飈飛飠飢飣飥飩飪飫飭飯飲飴飼飽飾飿餃餄餅餉養餌餎餏餑餒餓餕餖餚餛餜餞餡館餱餳餶餷餺餼餾餿饁饃饅饈饉饊饋饌饑饒饗饜饞饢馬馭馮馱馳馴馹駁駐駑駒駔駕駘駙駛駝駟駡駢駭駰駱駸駿騁騂騅騌騍騎騏騖騙騤騫騭騮騰騶騷騸騾驀驁驂驃驄驅驊驌驍驏驕驗驚驛驟驢驤驥驦驪驫骯髏髒體髕髖髮鬆鬍鬚鬢鬥鬧鬩鬮鬱魎魘魚魛魢魨魯魴魷魺鮁鮃鮊鮋鮍鮎鮐鮑鮒鮓鮚鮜鮝鮞鮦鮪鮫鮭鮮鮳鮶鮺鯀鯁鯇鯉鯊鯒鯔鯕鯖鯗鯛鯝鯡鯢鯤鯧鯨鯪鯫鯴鯷鯽鯿鰁鰂鰃鰈鰉鰍鰏鰐鰒鰓鰜鰟鰠鰣鰥鰨鰩鰭鰮鰱鰲鰳鰵鰷鰹鰺鰻鰼鰾鱂鱅鱈鱉鱒鱔鱖鱗鱘鱝鱟鱠鱣鱤鱧鱨鱭鱯鱷鱸鱺鳥鳧鳩鳬鳲鳳鳴鳶鳾鴆鴇鴉鴒鴕鴛鴝鴞鴟鴣鴦鴨鴯鴰鴴鴷鴻鴿鵁鵂鵃鵐鵑鵒鵓鵜鵝鵠鵡鵪鵬鵮鵯鵲鵷鵾鶄鶇鶉鶊鶓鶖鶘鶚鶡鶥鶩鶪鶬鶯鶲鶴鶹鶺鶻鶼鶿鷀鷁鷂鷄鷈鷊鷓鷖鷗鷙鷚鷥鷦鷫鷯鷲鷳鷸鷹鷺鷽鷿鸇鸌鸏鸕鸘鸚鸛鸝鸞鹵鹹鹺鹽麗麥麩麵麽黃黌點黨黲黶黷黽黿鼉鼴齊齋齎齏齒齔齕齗齙齜齟齠齡齦齪齬齲齶齷龍龎龐龔龕龜`
+}
\ No newline at end of file
From f5a005774df34734374af008e25f5d01395efde4 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 11 Feb 2023 23:50:49 +0800
Subject: [PATCH 048/105] Fixed #438
---
Surge/JS/Bili_Auto_Regions.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Surge/JS/Bili_Auto_Regions.js b/Surge/JS/Bili_Auto_Regions.js
index d20497ec6c..8f16333e47 100644
--- a/Surge/JS/Bili_Auto_Regions.js
+++ b/Surge/JS/Bili_Auto_Regions.js
@@ -5,7 +5,7 @@
如需禁用豆瓣评分或策略通知, 可前往BoxJs设置.
BoxJs订阅地址: https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
-Update: 2023.02.10
+Update: 2023.02.11
Author: @NobyDa
Use: Surge, QuanX, Loon
@@ -97,7 +97,7 @@ async function SwitchRegion(title, url, body) {
} else if (current != CN) {
select = { policy: CN, mode: '直连' };
}
- if ($.isQuanX && current === 'direct' && select === 'DIRECT') {
+ if ($.isQuanX && current === 'direct' && select.policy === 'DIRECT') {
select = {}; //prevent loopback in some cases
}
return select;
From 2aefff58482fb70437a2078ce5b3c44f0cf068b8 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 16 Feb 2023 00:40:22 +0800
Subject: [PATCH 049/105] Fix iqiyi script push content.
---
iQIYI-DailyBonus/iQIYI.js | 23 ++++++++++-------------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/iQIYI-DailyBonus/iQIYI.js b/iQIYI-DailyBonus/iQIYI.js
index 81e3af7704..41293f67df 100644
--- a/iQIYI-DailyBonus/iQIYI.js
+++ b/iQIYI-DailyBonus/iQIYI.js
@@ -1,7 +1,7 @@
/*
爱奇艺会员签到脚本
-更新时间: 2022.11.08
+更新时间: 2023/02/16
脚本兼容: QuantumultX, Surge4, Loon, JsBox, Node.js
电报频道: @NobyDa
问题反馈: @NobyDa_bot
@@ -246,25 +246,22 @@ function Lottery(s) {
try {
if (error) throw new Error("接口请求出错 ‼️");
const obj = JSON.parse(data);
- $nobyda.last = data.match(/(机会|已经)用完/) ? true : false
- if (obj.awardName && obj.code == 0) {
- LotteryMsg = `应用抽奖: ${!$nobyda.last ? `${obj.awardName.replace(/《.+》/, "未中奖")} 🎉` : `您的抽奖次数已经用完 ⚠️`}`
- } else if (data.match(/\"errorReason\"/)) {
- const msg = data.match(/msg=.+?\)/) ? data.match(/msg=(.+?)\)/)[1].replace(/用户(未登录|不存在)/, "Cookie无效") : ""
- LotteryMsg = `应用抽奖: ${msg || `未知错误`} ⚠️`
+ if (obj.title) {
+ LotteryMsg = `应用抽奖: ${obj.title!='影片推荐'&&obj.awardName||'未中奖'} 🎉`;
+ LotteryMsg = `应用抽奖: ${obj.kv.code=='Q00702'&&`您的抽奖次数已经用完 ⚠️`||LotteryMsg}`;
+ $nobyda.stop = obj.kv.code == 'Q00702';
+ } else if (obj.kv.code == 'Q00304'){
+ LotteryMsg = `应用抽奖: Cookie无效 ⚠️`;
+ $nobyda.stop = 1;
} else {
- LotteryMsg = `应用抽奖: ${data}`
+ LotteryMsg = `应用抽奖: 未知错误 ⚠️`
}
} catch (e) {
LotteryMsg = `应用抽奖: ${e.message || e}`;
}
console.log(`爱奇艺-${LotteryMsg} (${s+1}) ${Details}`)
pushMsg.push(LotteryMsg)
- if (!$nobyda.last) {
- resolve(1)
- } else {
- resolve()
- }
+ resolve(!$nobyda.stop)
})
})
}
From 503bf08e9d26e945515d46c700c535687b5f55ad Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 26 Feb 2023 23:31:35 +0800
Subject: [PATCH 050/105] Minor improvements to iqiyi script.
---
iQIYI-DailyBonus/iQIYI.js | 240 +++++++++++++++++++-------------------
1 file changed, 119 insertions(+), 121 deletions(-)
diff --git a/iQIYI-DailyBonus/iQIYI.js b/iQIYI-DailyBonus/iQIYI.js
index 41293f67df..5182c3ba4b 100644
--- a/iQIYI-DailyBonus/iQIYI.js
+++ b/iQIYI-DailyBonus/iQIYI.js
@@ -1,7 +1,7 @@
/*
爱奇艺会员签到脚本
-更新时间: 2023/02/16
+更新时间: 2023/02/26
脚本兼容: QuantumultX, Surge4, Loon, JsBox, Node.js
电报频道: @NobyDa
问题反馈: @NobyDa_bot
@@ -80,55 +80,53 @@ var P00001 = '';
var P00003 = '';
-var dfp = '';
-
var $nobyda = nobyda();
(async () => {
cookie = cookie || $nobyda.read("CookieQY")
LogDetails = $nobyda.read("iQIYI_LogDetails") === "true" ? true : LogDetails
- if (typeof process !== 'undefined' && typeof process.env !== 'undefined') {
- cookie = cookie || process.env.IQIYI_COOKIE;
- LogDetails = LogDetails || process.env.IQIYI_DEBUG;
- barkKey = barkKey || process.env.BARK_PUSH;
- barkServer = barkServer || process.env.BARK_SERVER;
- }
+ if (typeof process !== 'undefined' && typeof process.env !== 'undefined') {
+ cookie = cookie || process.env.IQIYI_COOKIE;
+ LogDetails = LogDetails || process.env.IQIYI_DEBUG;
+ barkKey = barkKey || process.env.BARK_PUSH;
+ barkServer = barkServer || process.env.BARK_SERVER;
+ }
if ($nobyda.isRequest) {
GetCookie()
} else if (cookie) {
if (cookie.includes("P00001") && cookie.includes("P00003") && cookie.includes("__dfp")) {
- P00001 = cookie.match(/P00001=(.*?);/)[1];
- P00003 = cookie.match(/P00003=(.*?);/)[1];
- dfp = cookie.match(/__dfp=(.*?)@/)[1];
- await login();
- await Checkin();
- for (let i = 0; i < 3; i++){
- const run = await Lottery(i);
- if (run) {
- await new Promise(r => setTimeout(r, 1000));
- } else {
- break
- }
+ P00001 = cookie.match(/P00001=(.*?);/)[1];
+ P00003 = cookie.match(/P00003=(.*?);/)[1];
+ dfp = cookie.match(/__dfp=(.*?)@/)[1];
+ await login();
+ await Checkin();
+ for (let i = 0; i < 3; i++) {
+ const run = await Lottery(i);
+ if (run) {
+ await new Promise(r => setTimeout(r, 1000));
+ } else {
+ break
}
- const tasks = await getTaskList();
- for (let i = 0; i < tasks.length; i++){
- if (![1, 4].includes(tasks[i].status)) { //0:待领取 1:已完成 2:未开始 4:进行中
- await joinTask(tasks[i]);
- await notifyTask(tasks[i]);
- await new Promise(r => setTimeout(r, 1000));
- await getTaskRewards(tasks[i]);
- console.log(`--------------------`)
- }
+ }
+ const tasks = await getTaskList();
+ for (let i = 0; i < tasks.length; i++) {
+ if (![1, 4].includes(tasks[i].status)) { //0:待领取 1:已完成 2:未开始 4:进行中
+ await joinTask(tasks[i]);
+ await notifyTask(tasks[i]);
+ await new Promise(r => setTimeout(r, 1000));
+ await getTaskRewards(tasks[i]);
+ console.log(`--------------------`)
}
- const expires = $nobyda.expire ? $nobyda.expire.replace(/\u5230\u671f/, "") : "获取失败 ⚠️"
- if (!$nobyda.isNode) $nobyda.notify("爱奇艺", "到期时间: " + expires, pushMsg.join('\n'));
- if (barkKey) await BarkNotify($nobyda, barkKey, '爱奇艺', `到期时间: ${expires}\n${pushMsg.join('\n')}`, barkServer);
- await $nobyda.time();
- } else {
- console.log(`Cookie缺少关键值,需重新获取`)
}
+ const expires = $nobyda.expire ? $nobyda.expire.replace(/\u5230\u671f/, "") : "获取失败 ⚠️"
+ if (!$nobyda.isNode) $nobyda.notify("爱奇艺", "到期时间: " + expires, pushMsg.join('\n'));
+ if (barkKey) await BarkNotify($nobyda, barkKey, '爱奇艺', `到期时间: ${expires}\n${pushMsg.join('\n')}`, barkServer);
+ await $nobyda.time();
+ } else {
+ console.log(`Cookie缺少关键值,需重新获取`)
+ }
} else {
- $nobyda.notify("爱奇艺会员", "", "签到终止, 未获取Cookie");
+ $nobyda.notify("爱奇艺会员", "", "签到终止, 未获取Cookie");
}
})().finally(() => {
$nobyda.done();
@@ -143,7 +141,7 @@ function login() {
t: '479112291'
}
}
- $nobyda.get(URL, function(error, response, data) {
+ $nobyda.get(URL, function (error, response, data) {
const Details = LogDetails ? data ? `response:\n${data}` : '' : ''
if (!error && data.match(/\"text\":\"\d.+?\u5230\u671f\"/)) {
$nobyda.expire = data.match(/\"text\":\"(\d.+?\u5230\u671f)\"/)[1]
@@ -179,13 +177,13 @@ function Checkin() {
userId: P00003,
};
const post_date = {
- "natural_month_sign": {
- "agentType": "1",
- "agentversion": "1",
- "authCookie": P00001,
- "qyid": md5(stringRandom(16)),
- "taskCode": "iQIYI_mofhr",
- "verticalCode": "iQIYI"
+ "natural_month_sign": {
+ "agentType": "1",
+ "agentversion": "1",
+ "authCookie": P00001,
+ "qyid": md5(stringRandom(16)),
+ "taskCode": "iQIYI_mofhr",
+ "verticalCode": "iQIYI"
}
};
const sign = k("UKobMjDMsDoScuWOfp6F", sign_date, {
@@ -196,29 +194,29 @@ function Checkin() {
var URL = {
url: 'https://community.iqiyi.com/openApi/task/execute?' + w(sign_date) + "&sign=" + sign,
headers: {
- 'Content-Type':'application/json'
+ 'Content-Type': 'application/json'
},
body: JSON.stringify(post_date)
}
- $nobyda.post(URL, function(error, response, data) {
+ $nobyda.post(URL, function (error, response, data) {
let CheckinMsg, rewards = [];
- const Details = LogDetails ? `msg:\n${data||error}` : '';
+ const Details = LogDetails ? `msg:\n${data || error}` : '';
try {
- if (error) throw new Error(`接口请求出错 ‼️`);
+ if (error) throw new Error(`接口请求出错 ‼️`);
const obj = JSON.parse(data)
if (obj.code === "A00000") {
if (obj.data.code === "A0000") {
- for(let i = 0; i < obj.data.data.rewards.length; i++) {
- if (obj.data.data.rewards[i].rewardType == 1) {
- rewards.push(`成长值+${obj.data.data.rewards[i].rewardCount}`)
- } else if (obj.data.data.rewards[i].rewardType == 2) {
- rewards.push(`VIP天+${obj.data.data.rewards[i].rewardCount}`)
- } else if (obj.data.data.rewards[i].rewardType == 3) {
- rewards.push(`积分+${obj.data.data.rewards[i].rewardCount}`)
- }
- }
+ for (let i = 0; i < obj.data.data.rewards.length; i++) {
+ if (obj.data.data.rewards[i].rewardType == 1) {
+ rewards.push(`成长值+${obj.data.data.rewards[i].rewardCount}`)
+ } else if (obj.data.data.rewards[i].rewardType == 2) {
+ rewards.push(`VIP天+${obj.data.data.rewards[i].rewardCount}`)
+ } else if (obj.data.data.rewards[i].rewardType == 3) {
+ rewards.push(`积分+${obj.data.data.rewards[i].rewardCount}`)
+ }
+ }
var continued = obj.data.data.signDays;
- CheckinMsg = `应用签到: ${rewards.join(", ")}${rewards.length<3?`, 累计签到${continued}天`:``} 🎉`;
+ CheckinMsg = `应用签到: ${rewards.length ? `${rewards.join(", ")}${rewards.length < 3 ? `, 累计签到${continued}天` : ``}` : '无奖励'} 🎉`;
} else {
CheckinMsg = `应用签到: ${obj.data.msg} ⚠️`;
}
@@ -226,7 +224,7 @@ function Checkin() {
CheckinMsg = `应用签到: Cookie无效 ⚠️`;
}
} catch (e) {
- CheckinMsg = `应用签到: ${e.message||e}`;
+ CheckinMsg = `应用签到: ${e.message || e}`;
}
pushMsg.push(CheckinMsg);
console.log(`爱奇艺-${CheckinMsg} ${Details}`);
@@ -237,45 +235,45 @@ function Checkin() {
function Lottery(s) {
return new Promise(resolve => {
- const URL = {
- url: 'https://iface2.iqiyi.com/aggregate/3.0/lottery_activity?app_k=0&app_v=0&platform_id=0&dev_os=0&dev_ua=0&net_sts=0&qyid=0&psp_uid=0&psp_cki=' + P00001 + '&psp_status=0&secure_p=0&secure_v=0&req_sn=0'
- }
- $nobyda.get(URL, async function(error, response, data) {
- const Details = LogDetails ? `msg:\n${data||error}` : ''
- let LotteryMsg;
- try {
- if (error) throw new Error("接口请求出错 ‼️");
- const obj = JSON.parse(data);
- if (obj.title) {
- LotteryMsg = `应用抽奖: ${obj.title!='影片推荐'&&obj.awardName||'未中奖'} 🎉`;
- LotteryMsg = `应用抽奖: ${obj.kv.code=='Q00702'&&`您的抽奖次数已经用完 ⚠️`||LotteryMsg}`;
- $nobyda.stop = obj.kv.code == 'Q00702';
- } else if (obj.kv.code == 'Q00304'){
- LotteryMsg = `应用抽奖: Cookie无效 ⚠️`;
- $nobyda.stop = 1;
- } else {
- LotteryMsg = `应用抽奖: 未知错误 ⚠️`
- }
- } catch (e) {
- LotteryMsg = `应用抽奖: ${e.message || e}`;
+ const URL = {
+ url: 'https://iface2.iqiyi.com/aggregate/3.0/lottery_activity?app_k=0&app_v=0&platform_id=0&dev_os=0&dev_ua=0&net_sts=0&qyid=0&psp_uid=0&psp_cki=' + P00001 + '&psp_status=0&secure_p=0&secure_v=0&req_sn=0'
+ }
+ $nobyda.get(URL, async function (error, response, data) {
+ const Details = LogDetails ? `msg:\n${data || error}` : ''
+ let LotteryMsg;
+ try {
+ if (error) throw new Error("接口请求出错 ‼️");
+ const obj = JSON.parse(data);
+ if (obj.title) {
+ LotteryMsg = `应用抽奖: ${obj.title != '影片推荐' && obj.awardName || '未中奖'} 🎉`;
+ LotteryMsg = obj.kv.code == 'Q00702' && `应用抽奖: 您的抽奖次数已经用完 ⚠️` || LotteryMsg;
+ $nobyda.stop = obj.kv.code == 'Q00702';
+ } else if (obj.kv.code == 'Q00304') {
+ LotteryMsg = `应用抽奖: Cookie无效 ⚠️`;
+ $nobyda.stop = 1;
+ } else {
+ LotteryMsg = `应用抽奖: 未知错误 ⚠️`
}
- console.log(`爱奇艺-${LotteryMsg} (${s+1}) ${Details}`)
- pushMsg.push(LotteryMsg)
- resolve(!$nobyda.stop)
- })
+ } catch (e) {
+ LotteryMsg = `应用抽奖: ${e.message || e}`;
+ }
+ console.log(`爱奇艺-${LotteryMsg} (${s + 1}) ${Details}`)
+ pushMsg.push(LotteryMsg)
+ resolve(!$nobyda.stop)
+ })
})
}
function getTaskList(task) {
return new Promise(resolve => {
- $nobyda.get(`https://tc.vip.iqiyi.com/taskCenter/task/queryUserTask?P00001=${P00001}`, function(error, response, data) {
- let taskListMsg, taskList = [];
- const Details = LogDetails ? `msg:\n${data||error}` : '';
+ $nobyda.get(`https://tc.vip.iqiyi.com/taskCenter/task/queryUserTask?P00001=${P00001}`, function (error, response, data) {
+ let taskListMsg, taskList = [];
+ const Details = LogDetails ? `msg:\n${data || error}` : '';
try {
if (error) throw new Error(`请求失败`);
const obj = JSON.parse(data);
if (obj.code == 'A00000' && obj.data && obj.data.tasks) {
- Object.keys(obj.data.tasks).map((group) => {
+ Object.keys(obj.data.tasks).map((group) => {
(obj.data.tasks[group] || []).map((item) => {
taskList.push({
name: item.taskTitle,
@@ -289,7 +287,7 @@ function getTaskList(task) {
taskListMsg = `获取失败!`;
}
} catch (e) {
- taskListMsg = `${e.message||e} ‼️`;
+ taskListMsg = `${e.message || e} ‼️`;
}
console.log(`爱奇艺-任务列表: ${taskListMsg} ${Details}`)
resolve(taskList)
@@ -300,16 +298,16 @@ function getTaskList(task) {
function joinTask(task) {
return new Promise(resolve => {
$nobyda.get('https://tc.vip.iqiyi.com/taskCenter/task/joinTask?taskCode=' + task.taskCode + '&lang=zh_CN&platform=0000000000000000&P00001=' + P00001, function (error, response, data) {
- let joinTaskMsg, Details = LogDetails ? `msg:\n${data||error}` : '';
- try {
- if (error) throw new Error(`请求失败`);
- const obj = JSON.parse(data);
- joinTaskMsg = obj.code || '领取失败';
- } catch (e) {
- joinTaskMsg = `错误 ${e.message||e}`;
- }
- console.log(`爱奇艺-领取任务: ${task.name} => ${joinTaskMsg} ${Details}`)
- resolve()
+ let joinTaskMsg, Details = LogDetails ? `msg:\n${data || error}` : '';
+ try {
+ if (error) throw new Error(`请求失败`);
+ const obj = JSON.parse(data);
+ joinTaskMsg = obj.code || '领取失败';
+ } catch (e) {
+ joinTaskMsg = `错误 ${e.message || e}`;
+ }
+ console.log(`爱奇艺-领取任务: ${task.name} => ${joinTaskMsg} ${Details}`)
+ resolve()
})
})
}
@@ -317,16 +315,16 @@ function joinTask(task) {
function notifyTask(task) {
return new Promise(resolve => {
$nobyda.get('https://tc.vip.iqiyi.com/taskCenter/task/notify?taskCode=' + task.taskCode + '&lang=zh_CN&platform=0000000000000000&P00001=' + P00001, function (error, response, data) {
- let notifyTaskMsg, Details = LogDetails ? `msg:\n${data||error}` : '';
- try {
- if (error) throw new Error(`请求失败`);
- const obj = JSON.parse(data);
- notifyTaskMsg = obj.code || '失败';
- } catch (e) {
- notifyTaskMsg = e.message || e;
- }
- console.log(`爱奇艺-开始任务: ${task.name} => ${notifyTaskMsg} ${Details}`)
- resolve()
+ let notifyTaskMsg, Details = LogDetails ? `msg:\n${data || error}` : '';
+ try {
+ if (error) throw new Error(`请求失败`);
+ const obj = JSON.parse(data);
+ notifyTaskMsg = obj.code || '失败';
+ } catch (e) {
+ notifyTaskMsg = e.message || e;
+ }
+ console.log(`爱奇艺-开始任务: ${task.name} => ${notifyTaskMsg} ${Details}`)
+ resolve()
})
})
}
@@ -335,17 +333,17 @@ function getTaskRewards(task) {
return new Promise(resolve => {
$nobyda.get('https://tc.vip.iqiyi.com/taskCenter/task/getTaskRewards?taskCode=' + task.taskCode + '&lang=zh_CN&platform=0000000000000000&P00001=' + P00001, function (error, response, data) {
let RewardsMsg;
- const Details = LogDetails ? `msg:\n${data||error}` : ''
+ const Details = LogDetails ? `msg:\n${data || error}` : ''
try {
- if (error) throw new Error(`接口请求出错 ‼️`);
+ if (error) throw new Error(`接口请求出错 ‼️`);
const obj = JSON.parse(data)
if (obj.msg === "成功" && obj.code === "A00000" && obj.dataNew[0] !== undefined) {
RewardsMsg = `任务奖励: ${task.name} => ${obj.dataNew[0].name + obj.dataNew[0].value} 🎉`
} else {
- RewardsMsg = `任务奖励: ${task.name} => ${obj.msg!==`成功`&&obj.msg||`未完成`} ⚠️`
+ RewardsMsg = `任务奖励: ${task.name} => ${obj.msg !== `成功` && obj.msg || `未完成`} ⚠️`
}
} catch (e) {
- RewardsMsg = `任务奖励: ${e.message||e}`;
+ RewardsMsg = `任务奖励: ${e.message || e}`;
}
pushMsg.push(RewardsMsg)
console.log(`爱奇艺-${RewardsMsg} ${Details}`)
@@ -366,11 +364,11 @@ function GetCookie() {
if (RA != iQIYI) {
var OldTime = $nobyda.read("CookieQYTime")
if (!$nobyda.write(iQIYI, "CookieQY")) {
- $nobyda.notify(`${RA?`更新`:`首次写入`}爱奇艺签到Cookie失败‼️`, "", "")
+ $nobyda.notify(`${RA ? `更新` : `首次写入`}爱奇艺签到Cookie失败‼️`, "", "")
} else {
if (!OldTime || OldTime && (Date.now() - OldTime) / 1000 >= 21600) {
$nobyda.write(JSON.stringify(Date.now()), "CookieQYTime")
- $nobyda.notify(`${RA?`更新`:`首次写入`}爱奇艺签到Cookie成功 🎉`, "", "")
+ $nobyda.notify(`${RA ? `更新` : `首次写入`}爱奇艺签到Cookie成功 🎉`, "", "")
} else {
console.log(`\n更新爱奇艺Cookie成功! 🎉\n检测到频繁通知, 已转为输出日志`)
}
@@ -383,7 +381,7 @@ function GetCookie() {
}
}
-async function BarkNotify(c,k,t,b,p){for(let i=0;i<3;i++){console.log(`🔷Bark notify >> Start push (${i+1})`);const s=await new Promise((n)=>{c.post({url:p||'https://api.day.app/push',headers:{'Content-Type':'application/json'},body:JSON.stringify({title:t,body:b,device_key:k,ext_params:{group:t}})},(e,r,d)=>r&&r.status==200?n(1):n(d||e))});if(s===1){console.log('✅Push success!');break}else{console.log(`❌Push failed! >> ${s.message||s}`)}}}
+async function BarkNotify(c, k, t, b, p) { for (let i = 0; i < 3; i++) { console.log(`🔷Bark notify >> Start push (${i + 1})`); const s = await new Promise((n) => { c.post({ url: p || 'https://api.day.app/push', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: t, body: b, device_key: k, ext_params: { group: t } }) }, (e, r, d) => r && r.status == 200 ? n(1) : n(d || e)) }); if (s === 1) { console.log('✅Push success!'); break } else { console.log(`❌Push failed! >> ${s.message || s}`) } } }
function nobyda() {
const times = 0
@@ -454,7 +452,7 @@ function nobyda() {
url: options
}
options["header"] = options["headers"]
- options["handler"] = function(resp) {
+ options["handler"] = function (resp) {
let error = resp.error;
if (error) error = JSON.stringify(resp.error)
let body = resp.data;
@@ -490,7 +488,7 @@ function nobyda() {
url: options
}
options["header"] = options["headers"]
- options["handler"] = function(resp) {
+ options["handler"] = function (resp) {
let error = resp.error;
if (error) error = JSON.stringify(resp.error)
let body = resp.data;
@@ -542,9 +540,9 @@ function k(e, t) {
}
// Modified from https://github.com/blueimp/JavaScript-MD5
-function md5(string){function RotateLeft(lValue,iShiftBits){return(lValue<>>(32-iShiftBits))}function AddUnsigned(lX,lY){var lX4,lY4,lX8,lY8,lResult;lX8=(lX&0x80000000);lY8=(lY&0x80000000);lX4=(lX&0x40000000);lY4=(lY&0x40000000);lResult=(lX&0x3FFFFFFF)+(lY&0x3FFFFFFF);if(lX4&lY4){return(lResult^0x80000000^lX8^lY8)}if(lX4|lY4){if(lResult&0x40000000){return(lResult^0xC0000000^lX8^lY8)}else{return(lResult^0x40000000^lX8^lY8)}}else{return(lResult^lX8^lY8)}}function F(x,y,z){return(x&y)|((~x)&z)}function G(x,y,z){return(x&z)|(y&(~z))}function H(x,y,z){return(x^y^z)}function I(x,y,z){return(y^(x|(~z)))}function FF(a,b,c,d,x,s,ac){a=AddUnsigned(a,AddUnsigned(AddUnsigned(F(b,c,d),x),ac));return AddUnsigned(RotateLeft(a,s),b)};function GG(a,b,c,d,x,s,ac){a=AddUnsigned(a,AddUnsigned(AddUnsigned(G(b,c,d),x),ac));return AddUnsigned(RotateLeft(a,s),b)};function HH(a,b,c,d,x,s,ac){a=AddUnsigned(a,AddUnsigned(AddUnsigned(H(b,c,d),x),ac));return AddUnsigned(RotateLeft(a,s),b)};function II(a,b,c,d,x,s,ac){a=AddUnsigned(a,AddUnsigned(AddUnsigned(I(b,c,d),x),ac));return AddUnsigned(RotateLeft(a,s),b)};function ConvertToWordArray(string){var lWordCount;var lMessageLength=string.length;var lNumberOfWords_temp1=lMessageLength+8;var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1%64))/64;var lNumberOfWords=(lNumberOfWords_temp2+1)*16;var lWordArray=Array(lNumberOfWords-1);var lBytePosition=0;var lByteCount=0;while(lByteCount>>29;return lWordArray};function WordToHex(lValue){var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;for(lCount=0;lCount<=3;lCount++){lByte=(lValue>>>(lCount*8))&255;WordToHexValue_temp="0"+lByte.toString(16);WordToHexValue=WordToHexValue+WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2)}return WordToHexValue};function Utf8Encode(string){string=string.replace(/\r\n/g,"\n");var utftext="";for(var n=0;n127)&&(c<2048)){utftext+=String.fromCharCode((c>>6)|192);utftext+=String.fromCharCode((c&63)|128)}else{utftext+=String.fromCharCode((c>>12)|224);utftext+=String.fromCharCode(((c>>6)&63)|128);utftext+=String.fromCharCode((c&63)|128)}}return utftext};var x=Array();var k,AA,BB,CC,DD,a,b,c,d;var S11=7,S12=12,S13=17,S14=22;var S21=5,S22=9,S23=14,S24=20;var S31=4,S32=11,S33=16,S34=23;var S41=6,S42=10,S43=15,S44=21;string=Utf8Encode(string);x=ConvertToWordArray(string);a=0x67452301;b=0xEFCDAB89;c=0x98BADCFE;d=0x10325476;for(k=0;k>> (32 - iShiftBits)) } function AddUnsigned(lX, lY) { var lX4, lY4, lX8, lY8, lResult; lX8 = (lX & 0x80000000); lY8 = (lY & 0x80000000); lX4 = (lX & 0x40000000); lY4 = (lY & 0x40000000); lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF); if (lX4 & lY4) { return (lResult ^ 0x80000000 ^ lX8 ^ lY8) } if (lX4 | lY4) { if (lResult & 0x40000000) { return (lResult ^ 0xC0000000 ^ lX8 ^ lY8) } else { return (lResult ^ 0x40000000 ^ lX8 ^ lY8) } } else { return (lResult ^ lX8 ^ lY8) } } function F(x, y, z) { return (x & y) | ((~x) & z) } function G(x, y, z) { return (x & z) | (y & (~z)) } function H(x, y, z) { return (x ^ y ^ z) } function I(x, y, z) { return (y ^ (x | (~z))) } function FF(a, b, c, d, x, s, ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b) }; function GG(a, b, c, d, x, s, ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b) }; function HH(a, b, c, d, x, s, ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b) }; function II(a, b, c, d, x, s, ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b) }; function ConvertToWordArray(string) { var lWordCount; var lMessageLength = string.length; var lNumberOfWords_temp1 = lMessageLength + 8; var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64; var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16; var lWordArray = Array(lNumberOfWords - 1); var lBytePosition = 0; var lByteCount = 0; while (lByteCount < lMessageLength) { lWordCount = (lByteCount - (lByteCount % 4)) / 4; lBytePosition = (lByteCount % 4) * 8; lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition)); lByteCount++ } lWordCount = (lByteCount - (lByteCount % 4)) / 4; lBytePosition = (lByteCount % 4) * 8; lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition); lWordArray[lNumberOfWords - 2] = lMessageLength << 3; lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29; return lWordArray }; function WordToHex(lValue) { var WordToHexValue = "", WordToHexValue_temp = "", lByte, lCount; for (lCount = 0; lCount <= 3; lCount++) { lByte = (lValue >>> (lCount * 8)) & 255; WordToHexValue_temp = "0" + lByte.toString(16); WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2) } return WordToHexValue }; function Utf8Encode(string) { string = string.replace(/\r\n/g, "\n"); var utftext = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c) } else if ((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128) } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128) } } return utftext }; var x = Array(); var k, AA, BB, CC, DD, a, b, c, d; var S11 = 7, S12 = 12, S13 = 17, S14 = 22; var S21 = 5, S22 = 9, S23 = 14, S24 = 20; var S31 = 4, S32 = 11, S33 = 16, S34 = 23; var S41 = 6, S42 = 10, S43 = 15, S44 = 21; string = Utf8Encode(string); x = ConvertToWordArray(string); a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; for (k = 0; k < x.length; k += 16) { AA = a; BB = b; CC = c; DD = d; a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478); d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756); c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB); b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE); a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF); d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A); c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613); b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501); a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8); d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF); c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1); b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE); a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122); d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193); c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E); b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821); a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562); d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340); c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51); b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA); a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D); d = GG(d, a, b, c, x[k + 10], S22, 0x2441453); c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681); b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8); a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6); d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6); c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87); b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED); a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905); d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8); c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9); b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A); a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942); d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681); c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122); b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C); a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44); d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9); c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60); b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70); a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6); d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA); c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085); b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05); a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039); d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5); c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8); b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665); a = II(a, b, c, d, x[k + 0], S41, 0xF4292244); d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97); c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7); b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039); a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3); d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92); c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D); b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1); a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F); d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0); c = II(c, d, a, b, x[k + 6], S43, 0xA3014314); b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1); a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82); d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235); c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB); b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391); a = AddUnsigned(a, AA); b = AddUnsigned(b, BB); c = AddUnsigned(c, CC); d = AddUnsigned(d, DD) } var temp = WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d); return temp.toLowerCase() }
-function w(){
+function w() {
var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}
, t = [];
return Object.keys(e).forEach((function (a) {
From 97504925bbeb7599a05474212301001dd3359dde Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 27 Feb 2023 08:38:38 +0800
Subject: [PATCH 051/105] Adapt to new version bahamut API.
---
Bahamut/BahamutAnimeAds.js | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/Bahamut/BahamutAnimeAds.js b/Bahamut/BahamutAnimeAds.js
index 8b871e2fa2..09a88fcc7e 100644
--- a/Bahamut/BahamutAnimeAds.js
+++ b/Bahamut/BahamutAnimeAds.js
@@ -19,11 +19,17 @@ runs().catch((err) => {
}));
async function runs() {
- if (req.url.includes('token.php') && rsp.ad) {
- rsp.ad.minor = [];
- rsp.ad.major = [];
+ if (req.url.includes('token.php')) {
+ if (rsp.ad) {
+ rsp.ad.minor = [];
+ rsp.ad.major = [];
+ }
+ if (rsp.data && rsp.data.ad) {
+ rsp.data.ad.minor = [];
+ rsp.data.ad.major = [];
+ }
}
- if (req.url.includes('m3u8.php') && rsp.message) {
+ if (req.url.includes('m3u8.php') && (rsp.message || rsp.error)) {
await adURL('');
await new Promise(r => setTimeout(r, 25000));
await adURL('end');
@@ -34,7 +40,7 @@ async function runs() {
function adURL(str) {
return new Promise((res) => {
get({
- url: `https://api.gamer.com.tw/mobile_app/anime/v1/stat_ad.php?ad=${str}&schedule=0&sn=${req.url.split(/sn=(\d+)/)[1]}`,
+ url: `https://api.gamer.com.tw/mobile_app/anime/v1/stat_ad.php?ad=${str}&schedule=0&sn=${req.url.split(/sn=(\d+)/i)[1]}`,
headers: req.headers
}, (err, resp, data) => res())
})
From 50389e5efae6ccbf8c4606545227d0d2b90cdaf9 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Tue, 28 Feb 2023 22:07:20 +0800
Subject: [PATCH 052/105] Add new-bing surge module.
---
Surge/Module/NewBing.sgmodule | 8 ++++++++
1 file changed, 8 insertions(+)
create mode 100644 Surge/Module/NewBing.sgmodule
diff --git a/Surge/Module/NewBing.sgmodule b/Surge/Module/NewBing.sgmodule
new file mode 100644
index 0000000000..f3ca76baf7
--- /dev/null
+++ b/Surge/Module/NewBing.sgmodule
@@ -0,0 +1,8 @@
+#!name=New Bing for other browsers
+#!desc=Unlock browser restrictions for new bing AI search.
+
+[Header Rewrite]
+^https:\/\/www\.bing\.com\/(search|new) header-replace-regex User-Agent \w+\/[\d\.]+$ "AppleWebKit/537.36 Chrome/110.0 Safari/537.36 Edg/110.0"
+
+[MITM]
+hostname = %APPEND% www.bing.com
\ No newline at end of file
From cc62f662324716a83e4063aa89668456fe8f2338 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Tue, 28 Feb 2023 23:28:21 +0800
Subject: [PATCH 053/105] Add new-bing qx snippet.
---
QuantumultX/Sinppet/NewBing.snippet | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 QuantumultX/Sinppet/NewBing.snippet
diff --git a/QuantumultX/Sinppet/NewBing.snippet b/QuantumultX/Sinppet/NewBing.snippet
new file mode 100644
index 0000000000..5493256b56
--- /dev/null
+++ b/QuantumultX/Sinppet/NewBing.snippet
@@ -0,0 +1,5 @@
+# Unlock browser restrictions for new bing AI search.
+
+^https:\/\/www\.bing\.com\/(search|new) url request-header (\r\nUser-Agent:.+?)\w+\/[\d\.]+(\r\n) request-header $1AppleWebKit/537.36 Chrome/110.0 Safari/537.36 Edg/110.0$2
+
+hostname = www.bing.com
\ No newline at end of file
From 0925f477bab5c76975203acf506a761e683976a6 Mon Sep 17 00:00:00 2001
From: BlueSkyClouds <1471223507@qq.com>
Date: Tue, 14 Mar 2023 18:23:59 +0800
Subject: [PATCH 054/105] delete dfp (#442)
---
iQIYI-DailyBonus/iQIYI.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/iQIYI-DailyBonus/iQIYI.js b/iQIYI-DailyBonus/iQIYI.js
index 5182c3ba4b..b04c494c5d 100644
--- a/iQIYI-DailyBonus/iQIYI.js
+++ b/iQIYI-DailyBonus/iQIYI.js
@@ -94,10 +94,9 @@ var $nobyda = nobyda();
if ($nobyda.isRequest) {
GetCookie()
} else if (cookie) {
- if (cookie.includes("P00001") && cookie.includes("P00003") && cookie.includes("__dfp")) {
+ if (cookie.includes("P00001") && cookie.includes("P00003")) {
P00001 = cookie.match(/P00001=(.*?);/)[1];
P00003 = cookie.match(/P00003=(.*?);/)[1];
- dfp = cookie.match(/__dfp=(.*?)@/)[1];
await login();
await Checkin();
for (let i = 0; i < 3; i++) {
From a6b8d54948e95651e3a28cdfe9a37de52e7116e4 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Tue, 14 Mar 2023 22:18:00 +0800
Subject: [PATCH 055/105] Remove invalid scripts in qx snippet
---
QuantumultX/Js.conf | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/QuantumultX/Js.conf b/QuantumultX/Js.conf
index 9ee1991606..db786ddeb0 100644
--- a/QuantumultX/Js.conf
+++ b/QuantumultX/Js.conf
@@ -1,4 +1,4 @@
-hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.zhihu.com, vip1.kuwo.cn, p.du.163.com, apigate.zymk.cn, www.luqijianggushi.com, *account.wps.com, *account.wps.cn, origin-prod-phoenix.jibjab.com, xy-viva.kakalili.com, ap*.intsig.net, api.picsart.c*, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.meiease.c*, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api.polaxiong.com, api-chn.rthdo.com
+hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.zhihu.com, vip1.kuwo.cn, p.du.163.com, apigate.zymk.cn, www.luqijianggushi.com, *account.wps.com, *account.wps.cn, origin-prod-phoenix.jibjab.com, xy-viva.kakalili.com, ap*.intsig.net, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api-chn.rthdo.com
# 去微信公众号广告 (By Choler)
^https?:\/\/mp\.weixin\.qq\.com\/mp\/getappmsgad url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js
@@ -35,18 +35,12 @@ hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.
# 扫描全能王 pro
^https:\/\/(api|api-cs)\.intsig\.net\/purchase\/cs\/query_property\? url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js
-# PicsArt美易 pro
-^https:\/\/api\.(picsart|meiease)\.c(n|om)\/users\/show\/me\.json url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js
-
# 百度网盘 解除在线视频倍率/清晰度
^https:\/\/pan\.baidu\.com\/rest\/\d\.\d\/membership\/user url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js
# MIX 解锁高级特权 (需恢复购买)
^https?:\/\/bmall\.camera360\.com\/api\/mix\/recovery url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js
-# 泼辣修图 解锁高级特权 (需恢复购买)
-^https:\/\/api\.polaxiong\.com\/v1\/payments\/appleiap\/receipts\/confirmation url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js
-
#################################
###########其他仓库引用###########
#################################
From eb2eabc073c94fe16e2833b2848755feb8733877 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Tue, 14 Mar 2023 22:27:26 +0800
Subject: [PATCH 056/105] Update overview
---
README.md | 127 ++++++++++++++++++++++++++----------------------------
1 file changed, 61 insertions(+), 66 deletions(-)
diff --git a/README.md b/README.md
index 5019cc29bd..d4183bef5a 100644
--- a/README.md
+++ b/README.md
@@ -26,52 +26,53 @@
### Daily-Bonus Script
-| Application | Script name | Available | Maintenance |
-|:-------------------------------------------------:|:-------------------------------------------------------------------------------------------------:|:--------------:|:-----------:|
-| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ⚠️(2022/07/03) | ⚠️ |
-| [百度贴吧](https://apps.apple.com/app/id477927812) | [TieBa.js](https://github.com/NobyDa/Script/blob/master/BDTieBa-DailyBonus/TieBa.js) | ✅(2022/07/03) | ❌ |
-| [吾爱破解](https://www.52pojie.cn/) | [52pojie.js](https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js) | ✅(2022/07/03) | ❌ |
-| [爱奇艺](https://apps.apple.com/cn/app/id393765873) | [iQIYI.js](https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js) | ✅(2022/07/03) | ✅ |
-| [快看漫画](https://apps.apple.com/app/id906936224) | [KKMH.js](https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js) | ✅(2022/07/03) | ✅ |
-| [哔哩哔哩漫画](https://apps.apple.com/app/id1426252715) | [Manga.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js) | ✅(2022/07/03) | ✅ |
-| [巴哈姆特](https://www.gamer.com.tw/) | [BahamutDailyBonus.js](https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js) | ✅(2022/07/03) | ✅ |
+| Application | Script name | Available | Maintenance |
+| :-----------------------------------------------------: | :----------------------------------------------------------: | :-----------: | :---------: |
+| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ❌ | ⚠️ |
+| [百度贴吧](https://apps.apple.com/app/id477927812) | [TieBa.js](https://github.com/NobyDa/Script/blob/master/BDTieBa-DailyBonus/TieBa.js) | ✅(2023/03/14) | ❌ |
+| [吾爱破解](https://www.52pojie.cn/) | [52pojie.js](https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js) | ❌ | ❌ |
+| [爱奇艺](https://apps.apple.com/cn/app/id393765873) | [iQIYI.js](https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js) | ✅(2023/03/14) | ✅ |
+| [快看漫画](https://apps.apple.com/app/id906936224) | [KKMH.js](https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js) | ✅(2023/03/14) | ✅ |
+| [哔哩哔哩漫画](https://apps.apple.com/app/id1426252715) | [Manga.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js) | ✅(2023/03/14) | ✅ |
+| [巴哈姆特](https://www.gamer.com.tw/) | [BahamutDailyBonus.js](https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js) | ✅(2023/03/14) | ✅ |
------
### Functionality-enhancing Script
-| Script name | Description |
-|:-------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
-| [PolicySwitch.js](https://github.com/NobyDa/Script/blob/master/Shortcuts/PolicySwitch.js) | Switch [QX](https://apps.apple.com/app/id1443988620),[Surge](https://apps.apple.com/app/id1442620678),[Loon](https://apps.apple.com/app/id1373567447) policy groups using ios [shortcut](https://apps.apple.com/app/id1462947752). |
-| [DataQuery.js](https://github.com/NobyDa/Script/blob/master/Sub-store-parser/DataQuery.js) | Server(VPN) traffic query based on [Sub-Store](https://github.com/Peng-YM/Sub-Store). |
-| [Bili_Auto_Regions.js](https://github.com/NobyDa/Script/blob/master/Surge/JS/Bili_Auto_Regions.js) | [Bilibili anime](https://apps.apple.com/cn/app/id736536022) auto switch region & show [douban](https://www.douban.com/) rating. |
-| [ExchangePoints.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/ExchangePoints.js) | [Bilibili Comics](https://apps.apple.com/app/id1426252715) points mall auto snap up. |
-| [TestFlightAccount.js](https://github.com/NobyDa/Script/blob/master/TestFlight/TestFlightAccount.js) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts |
+| Script name | Description |
+| :----------------------------------------------------------: | :----------------------------------------------------------: |
+| [PolicySwitch.js](https://github.com/NobyDa/Script/blob/master/Shortcuts/PolicySwitch.js) | Switch [QX](https://apps.apple.com/app/id1443988620),[Surge](https://apps.apple.com/app/id1442620678),[Loon](https://apps.apple.com/app/id1373567447) policy groups using ios [shortcut](https://apps.apple.com/app/id1462947752). |
+| [DataQuery.js](https://github.com/NobyDa/Script/blob/master/Sub-store-parser/DataQuery.js) | Server(VPN) traffic query based on [Sub-Store](https://github.com/Peng-YM/Sub-Store). |
+| [Bili_Auto_Regions.js](https://github.com/NobyDa/Script/blob/master/Surge/JS/Bili_Auto_Regions.js) | [Bilibili anime](https://apps.apple.com/cn/app/id736536022) auto switch region & show [douban](https://www.douban.com/) rating. |
+| [ExchangePoints.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/ExchangePoints.js) | [Bilibili Comics](https://apps.apple.com/app/id1426252715) points mall auto snap up. |
+| [TestFlightAccount.js](https://github.com/NobyDa/Script/blob/master/TestFlight/TestFlightAccount.js) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts |
+| [Google_CAPTCHA.js](https://github.com/NobyDa/Script/blob/master/Surge/JS/Google_CAPTCHA.js) | Google CAPTCHA solution(Surge only) |
---
### Other Script
-| Application | Script name | Description | Available |
-|:---------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------:|:-----------------------:|:-------------:|
-| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
-| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅(2022/07/03) |
-| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅(2022/07/03) |
-| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ✅(2022/07/03) |
-| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅(2022/07/03) |
-| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ✅(2022/07/03) |
-| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ✅(2022/07/03) |
-| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ✅(2022/07/03) |
-| [酷我音乐](https://apps.apple.com/cn/app/id588673713) | [Kuwo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Kuwo.js) | Unlock vip listen | ✅(2022/07/03) |
-| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ✅(2022/07/03) |
-| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ✅(2022/07/03) |
-| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅(2022/07/03) |
-| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅(2022/07/03) |
-| [WPS Office](https://apps.apple.com/app/id1491101673) | [Wps.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js) | Unlock membership | ✅(2022/07/03) |
-| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅(2022/07/03) |
-| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅(2022/07/03) |
-| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ✅(2022/07/03) |
-| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅(2022/07/03) |
+| Application | Script name | Description | Available |
+| :----------------------------------------------------------: | :----------------------------------------------------------: | :---------------------: | :---------------------: |
+| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
+| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
+| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅ (2023/03/14) |
+| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ❌ |
+| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅ (2023/03/14) |
+| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ❌ |
+| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ⚠️ (Not tested recently) |
+| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ⚠️ (Not tested recently) |
+| [酷我音乐](https://apps.apple.com/cn/app/id588673713) | [Kuwo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Kuwo.js) | Unlock vip listen | ⚠️ (Not tested recently) |
+| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ⚠️ (Not tested recently) |
+| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ⚠️ (Not tested recently) |
+| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅ (2023/03/14) |
+| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅ (2023/03/14) |
+| [WPS Office](https://apps.apple.com/app/id1491101673) | [Wps.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js) | Unlock membership | ⚠️ (Not tested recently) |
+| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅ (2023/03/14) |
+| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅ (2023/03/14) |
+| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ❌ |
+| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅ (2023/03/14) |
---
@@ -87,24 +88,26 @@
### Surge Module
-| Module name | Description |
-|:------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:|
-| [HuiJuDongManAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/HuiJuDongManAds.sgmodule) | Remove [APP](https://apps.apple.com/app/id1451949669) Ads |
-| [IPA_install.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/IPA_install.sgmodule) | Use Surge to assist in install IPA (signed version) |
+| Module name | Description |
+| :----------------------------------------------------------: | :----------------------------------------------------------: |
+| [HuiJuDongManAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/HuiJuDongManAds.sgmodule) | Remove [APP](https://apps.apple.com/app/id1451949669) Ads |
+| [IPA_install.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/IPA_install.sgmodule) | Use Surge to assist in install IPA (signed version) |
| [TestFlightDownload.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightDownload.sgmodule) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions |
-| [TestFlightAccount.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightAccount.sgmodule) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts |
-| [GetCookie.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/GetCookie.sgmodule) | Daily bonus script related |
-| [BahamutAnimeAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/BahamutAnimeAds.sgmodule) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads |
+| [TestFlightAccount.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightAccount.sgmodule) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts |
+| [GetCookie.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/GetCookie.sgmodule) | Daily bonus script related |
+| [BahamutAnimeAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/BahamutAnimeAds.sgmodule) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads |
+| [NewBing.sgmodule](https://github.com/NobyDa/Script/blob/master/Surge/Module/NewBing.sgmodule) | Unlock browser restrictions for new bing AI search. |
---
## QuantumultX File Overview
-| File name | Description | Type |
-|:---------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:|:-------:|
-| [Js.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js.conf) | Remote script subscription. | Rewrite |
-| [Js_Remote_Cookie.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf) | Daily bonus script related | Rewrite |
-| [TestFlightDownload.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/TestFlightDownload.conf) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions | Rewrite |
+| File name | Description | Type |
+| :----------------------------------------------------------: | :----------------------------------------------------------: | :---------------: |
+| [Js.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js.conf) | Remote script subscription. | Rewrite Resources |
+| [Js_Remote_Cookie.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf) | Daily bonus script related | Rewrite Resources |
+| [TestFlightDownload.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/TestFlightDownload.conf) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions | Rewrite Resources |
+| [NewBing.snippet](https://github.com/NobyDa/Script/blob/master/QuantumultX/Sinppet/NewBing.snippet) | Unlock browser restrictions for new bing AI search. | Rewrite Resources |
Rules of type "Rule" include only ad hosts. Please select the REJECT policy.
@@ -132,7 +135,7 @@ Rules of type "Rule" include only ad hosts. Please select the REJECT policy.
QX1.0.3 add device ID, a simple example:
-```ini
+```javascript
/**
* @supported 23AD6B11CD4B
*/
@@ -161,43 +164,35 @@ The above random generated device ID can be found at the bottom of Quantumult X
## Disclaimer
-```
-In the following disclaimer:
-
-The "Script project" refers specifically to the open source scripts and rules in https://github.com/NobyDa/Script/tree/master
-
-The "NobyDa" refers specifically to the author and owner in https://github.com/NobyDa/Script/tree/master
-```
+Please note that in the following disclaimer, the term "Script-project" specifically refers to the open source scripts and rules available at "https://github.com/NobyDa/Script", while the term "NobyDa" specifically refers to the author and owner of these scripts and rules.
### Decrypt
-1. Any unlocking and decryption analysis scripts involved in "Script project" are for resource sharing and study purposes only.
-
-2. Legality, accuracy, completeness and validity cannot be guaranteed. **Please make your own judgment based on the actual situation.**
+- Any scripts involved in unlocking and decrypting in the Script-project are intended for resource sharing and study purposes only. The legality, accuracy, completeness, and validity of these scripts cannot be guaranteed. **Therefore, please use your own judgment based on the actual situation.**
-3. You must completely delete the scripts involved decryption from your computer or phone within **24 hours** of downloading.
+- You are required to delete the decryption scripts from your computer or phone completely within **24 hours** of downloading them.
### Privacy
-1. Any user who indirectly uses any of the scripts in "Script project", including but not limited to violating relevant laws and regulations or establishing VPS to spread, **NobyDa is not responsible for any privacy breach or other consequences arising therefrom.**
+- NobyDa is not responsible for any privacy breaches or other consequences arising from the direct or indirect use of any of the scripts in the Script-project, including but not limited to violating relevant laws and regulations or establishing VPS for spreading purposes.
### Commercial
-1. Do not use any scripts of "Script project" for commercial or illegal purposes, **otherwise you will be responsible for the consequences.**
+- Do not use any scripts from the Script-project for commercial or illegal purposes, **otherwise, you will be responsible for the consequences that may arise**.
### Infringement
-1. If any company or individual believes that the scripts in "Script project" may be infringe on rights, you should promptly notify and provide proof of **identity** and proof of **ownership**, and we will delete the relevant scripts upon receipt of the relevant documents.
+- If any company or individual believes that any script in the Script-project may infringe on their rights, they should promptly notify us and provide proof of **ownership** and **identity**. We will delete the relevant scripts upon receipt of the necessary documents.
### Liability
-1. NobyDa is not responsible for any scripts problems, **including but not limited to any loss or damage caused by any scripting errors.**
+- NobyDa is not responsible for any scripts problems, **including but not limited to any loss or damage caused by any scripting errors.**
### Change
-1. Anyone viewing or using in any way, directly or indirectly, the scripts in "Script project" should read this disclaimer carefully, and NobyDa reserves the right to change or supplement this disclaimer at any time.
+- Anyone who views or uses the scripts in the Script-project, whether directly or indirectly, should carefully read this disclaimer. NobyDa reserves the right to change or supplement this disclaimer at any time.
-2. **Once you view, use or copy any of the related scripts in "Script project", you will be deemed to have accepted this disclaimer.**
+- **By viewing, using, or copying any of the related scripts in the Script-project, you will be deemed to have accepted this disclaimer.**
## Acknowledgment
From 60a1f67f999562d46ab524dee463ac82ebd92d13 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Tue, 4 Apr 2023 23:54:51 +0800
Subject: [PATCH 057/105] Minor improvements.
---
Bilibili-DailyBonus/Manga.js | 58 +++++++++++++++---------------------
1 file changed, 24 insertions(+), 34 deletions(-)
diff --git a/Bilibili-DailyBonus/Manga.js b/Bilibili-DailyBonus/Manga.js
index 9012cee0ad..a779b14e69 100644
--- a/Bilibili-DailyBonus/Manga.js
+++ b/Bilibili-DailyBonus/Manga.js
@@ -4,6 +4,7 @@
脚本兼容: QuantumultX, Surge, Loon
电报频道:@NobyDa
问题反馈:@NobyDa_bot
+更新日期:04/04/2023
如果转载,请注明出处
说明:
@@ -43,7 +44,10 @@ const cookie = $.getdata("CookieBM") || ''; // 哔哩哔哩漫画Cookie
const barkKey = ''; //Bark APP 通知推送Key
if (typeof $request !== 'undefined') {
- GetCookie()
+ GetCookie(cookie)
+} else if (!cookie) {
+ $.msg($.name, ``, `签到Cookie失效/未获取 ⚠️`);
+ $.done();
} else {
checkin()
}
@@ -53,18 +57,20 @@ function checkin() {
url: 'https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn',
headers: {
Cookie: cookie,
+ "User-Agent": "comic-universal/1552 CFNetwork/1406.0.4 Darwin/22.4.0 os/ios model/iPhone 12 mobi_app/iphone_comic build/1552 osVer/16.4 network/2 channel/AppStore"
},
body: "platform=ios"
};
- $.post(bilibili, async function(error, response, data) {
+ $.post(bilibili, async function (error, response, data) {
if (error && !data) {
$.msgBody = `请求失败!\n${error}`;
} else if (parseInt(response.status) == 200) {
$.msgBody = "签到成功!🎉";
} else if (/duplicate/.test(data)) {
- $.msgBody = "今日已签过 ⚠️";
+ $.msgBody = "签到失败,今日已签过 ⚠️";
} else if (/uid must/.test(data)) {
- $.msgBody = "Cookie失效 ‼️‼️";
+ $.msgBody = "签到失败,Cookie失效(已清除) ⚠️";
+ $.setdata("", "CookieBM");
} else {
$.msgBody = `签到失败 ‼️\n${data}`;
}
@@ -76,42 +82,26 @@ function checkin() {
})
}
-function GetCookie() {
- var CookieName = "B站漫画";
- var CookieKey = "CookieBM";
- var regex = /SESSDATA=.+?;/;
- if ($request.headers) {
- var header = Object.keys($request.headers).reduce((t, i) => (t[i.toLowerCase()] = $request.headers[i], t), {})['cookie'] || '';
- if (header.indexOf("SESSDATA=") != -1) {
- var CookieValue = regex.exec(header)[0];
- if ($.getdata(CookieKey)) {
- if ($.getdata(CookieKey) != CookieValue) {
- var cookie = $.setdata(CookieValue, CookieKey);
- if (!cookie) {
- $.msg("更新" + CookieName + "Cookie失败‼️", "", "");
- } else {
- $.msg("更新" + CookieName + "Cookie成功 🎉", "", "");
- }
- }
- } else {
- var cookie = $.setdata(CookieValue, CookieKey);
- if (!cookie) {
- $.msg("首次写入" + CookieName + "Cookie失败‼️", "", "");
- } else {
- $.msg("首次写入" + CookieName + "Cookie成功 🎉", "", "");
- }
- }
+function GetCookie(oldCookie) {
+ const req = JSON.stringify($request);
+ if (!req.includes(`_comic`)) {
+ $.log($.name, `非${$.name}客户端URL请求,跳过脚本 ⚠️`);
+ } else if (!req.includes(`SESSDATA=`)) {
+ $.msg($.name, ``, `获取Cookie失败,关键值缺失 ⚠️`);
+ } else {
+ const cookieValue = req.split(/(SESSDATA=.+?;)/)[1];
+ const setCookie = $.setdata(cookieValue, `CookieBM`);
+ if (oldCookie) {
+ $.log($.name, `更新Cookie${setCookie ? `成功 🎉` : `失败 ⚠️`}`);
} else {
- $.msg("写入" + CookieName + "Cookie失败‼️", "", "Cookie关键值缺失");
+ $.msg($.name, ``, `获取Cookie${setCookie ? `成功 🎉` : `失败 ⚠️`}`);
}
- } else {
- $.msg("写入" + CookieName + "Cookie失败‼️", "", "配置错误, 无法读取请求头,");
}
$.done()
}
//Bark APP notify
-async function BarkNotify(c,k,t,b){for(let i=0;i<3;i++){console.log(`🔷Bark notify >> Start push (${i+1})`);const s=await new Promise((n)=>{c.post({url:'https://api.day.app/push',headers:{'Content-Type':'application/json'},body:JSON.stringify({title:t,body:b,device_key:k,ext_params:{group:t}})},(e,r,d)=>r&&r.status==200?n(1):n(d||e))});if(s===1){console.log('✅Push success!');break}else{console.log(`❌Push failed! >> ${s.message||s}`)}}};
+async function BarkNotify(c, k, t, b) { for (let i = 0; i < 3; i++) { console.log(`🔷Bark notify >> Start push (${i + 1})`); const s = await new Promise((n) => { c.post({ url: 'https://api.day.app/push', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: t, body: b, device_key: k, ext_params: { group: t } }) }, (e, r, d) => r && r.status == 200 ? n(1) : n(d || e)) }); if (s === 1) { console.log('✅Push success!'); break } else { console.log(`❌Push failed! >> ${s.message || s}`) } } };
// https://github.com/chavyleung/scripts/blob/master/Env.min.js
-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,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("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}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("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(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();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){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));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}}}};this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r)));let h=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];h.push(e),s&&h.push(s),i&&h.push(i),console.log(h.join("\n")),this.logs=this.logs.concat(h)}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("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)}
\ No newline at end of file
+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, 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("", `\ud83d\udd14${this.name}, \u5f00\u59cb!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } 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("@"), a = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; this.post(a, (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(); 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) { let e = { "M+": (new Date).getMonth() + 1, "d+": (new Date).getDate(), "H+": (new Date).getHours(), "m+": (new Date).getMinutes(), "s+": (new Date).getSeconds(), "q+": Math.floor(((new Date).getMonth() + 3) / 3), S: (new Date).getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, ((new Date).getFullYear() + "").substr(4 - RegExp.$1.length))); for (let s in e) new RegExp("(" + s + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? e[s] : ("00" + e[s]).substr(("" + e[s]).length))); 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 } } } }; this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))); let h = ["", "==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="]; h.push(e), s && h.push(s), i && h.push(i), console.log(h.join("\n")), this.logs = this.logs.concat(h) } 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("", `\u2757\ufe0f${this.name}, \u9519\u8bef!`, t.stack) : this.log("", `\u2757\ufe0f${this.name}, \u9519\u8bef!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) }
\ No newline at end of file
From cc03f717dedc94cb13fa91ddf8c44018f46171d6 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 28 Apr 2023 11:26:34 +0800
Subject: [PATCH 058/105] Fix #444
---
QuantumultX/AdRule.list | 4 +---
Surge/AdRule.list | 4 +---
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/QuantumultX/AdRule.list b/QuantumultX/AdRule.list
index 1a643e40e8..be16c740db 100644
--- a/QuantumultX/AdRule.list
+++ b/QuantumultX/AdRule.list
@@ -1,4 +1,4 @@
-# Update > 2022/08/01
+# Update > 2023/04/28
DOMAIN-SUFFIX,api-access.pangolin-sdk-toutiao-b.com,REJECT
DOMAIN-SUFFIX,apoll.m.taobao.com,REJECT
DOMAIN-SUFFIX,comet.yahoo.com,REJECT
@@ -135,7 +135,6 @@ DOMAIN-SUFFIX,m-78.jp,REJECT
DOMAIN-SUFFIX,nichibenren.or.jp,REJECT
DOMAIN-SUFFIX,nicorette.co.kr,REJECT
DOMAIN-SUFFIX,adnet.sohu.com,REJECT
-DOMAIN-SUFFIX,data.vod.itc.cn,REJECT
DOMAIN-SUFFIX,epro.sogou.com,REJECT
DOMAIN-SUFFIX,go.sohu.com,REJECT
DOMAIN-SUFFIX,golden1.sogou.com,REJECT
@@ -2012,7 +2011,6 @@ DOMAIN-SUFFIX,cc.yac8.com,REJECT
DOMAIN-SUFFIX,cca.mob.com,REJECT
DOMAIN-SUFFIX,ccb.uncle-ad.com,REJECT
DOMAIN-SUFFIX,ccbaihehq.com,REJECT
-DOMAIN-SUFFIX,ccclub.cmbchina.com,REJECT
DOMAIN-SUFFIX,cccrir.com,REJECT
DOMAIN-SUFFIX,ccr.yxdown.com,REJECT
DOMAIN-SUFFIX,cctyly.com,REJECT
diff --git a/Surge/AdRule.list b/Surge/AdRule.list
index f6f1ad41fd..de09430cd2 100644
--- a/Surge/AdRule.list
+++ b/Surge/AdRule.list
@@ -1,4 +1,4 @@
-# Update > 2022/08/01
+# Update > 2023/04/28
DOMAIN-SUFFIX,api-access.pangolin-sdk-toutiao-b.com
DOMAIN-SUFFIX,mcupdate.gstarcad.com
DOMAIN-SUFFIX,adx.open-adx.com
@@ -147,7 +147,6 @@ DOMAIN-SUFFIX,m-78.jp
DOMAIN-SUFFIX,nichibenren.or.jp
DOMAIN-SUFFIX,nicorette.co.kr
DOMAIN-SUFFIX,adnet.sohu.com
-DOMAIN-SUFFIX,data.vod.itc.cn
DOMAIN-SUFFIX,epro.sogou.com
DOMAIN-SUFFIX,go.sohu.com
DOMAIN-SUFFIX,golden1.sogou.com
@@ -2023,7 +2022,6 @@ DOMAIN-SUFFIX,cc.yac8.com
DOMAIN-SUFFIX,cca.mob.com
DOMAIN-SUFFIX,ccb.uncle-ad.com
DOMAIN-SUFFIX,ccbaihehq.com
-DOMAIN-SUFFIX,ccclub.cmbchina.com
DOMAIN-SUFFIX,cccrir.com
DOMAIN-SUFFIX,ccr.yxdown.com
DOMAIN-SUFFIX,cctyly.com
From 446dfd25543b5d88fa5d6be2e016188e89637592 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 12 Jun 2023 22:58:55 +0800
Subject: [PATCH 059/105] Fix #451
---
Surge/WeChat.list | 1 -
1 file changed, 1 deletion(-)
diff --git a/Surge/WeChat.list b/Surge/WeChat.list
index 7ab3a69558..f6569c7e64 100644
--- a/Surge/WeChat.list
+++ b/Surge/WeChat.list
@@ -160,7 +160,6 @@ DOMAIN-KEYWORD,203.205.232.
DOMAIN-KEYWORD,203.205.235.
DOMAIN-KEYWORD,203.205.253.
DOMAIN-KEYWORD,203.205.254.
-DOMAIN-KEYWORD,203.209.245.
DOMAIN-KEYWORD,211.95.137.
DOMAIN-KEYWORD,211.95.138.
DOMAIN-KEYWORD,218.68.88.
From 21b949863eb9a8690c826f2648cd4acdec66f19d Mon Sep 17 00:00:00 2001
From: Logan Lancaster <45466320+jarieshan@users.noreply.github.com>
Date: Tue, 27 Jun 2023 15:44:49 +0800
Subject: [PATCH 060/105] Update MIX.js (#452)
---
Surge/JS/MIX.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Surge/JS/MIX.js b/Surge/JS/MIX.js
index 6d0f701b4a..5af376d043 100644
--- a/Surge/JS/MIX.js
+++ b/Surge/JS/MIX.js
@@ -5,19 +5,19 @@ MIX 解锁特权 (需恢复购买)
QuantumultX:
[rewrite_local]
-https?:\/\/bmall\.camera360\.com\/api\/mix\/recovery url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js
+https?:\/\/cdn-bm\.camera360\.com\/api\/mix\/recovery url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js
[mitm]
-hostname = bmall.camera360.com
+hostname = cdn-bm.camera360.com
***************************
Surge4 or Loon:
[Script]
-http-response https?:\/\/bmall\.camera360\.com\/api\/mix\/recovery requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js
+http-response https?:\/\/cdn-bm\.camera360\.com\/api\/mix\/recovery requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js
[MITM]
-hostname = bmall.camera360.com
+hostname = cdn-bm.camera360.com
**************************/
@@ -89,4 +89,4 @@ if ($response.body) {
});
} else {
$done({})
-}
\ No newline at end of file
+}
From f7a1e8c63a90821901d376691da7060309b8189d Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Wed, 28 Jun 2023 00:28:12 +0800
Subject: [PATCH 061/105] fix bug in rare cases.
---
Surge/JS/Google_CAPTCHA.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Surge/JS/Google_CAPTCHA.js b/Surge/JS/Google_CAPTCHA.js
index 0b33470c25..36d03725b6 100644
--- a/Surge/JS/Google_CAPTCHA.js
+++ b/Surge/JS/Google_CAPTCHA.js
@@ -1,12 +1,12 @@
/*
Google搜索内容时并发使用多个策略(组),以避免可能出现的人机验证
-注:该脚本仅兼容Surge(4.9.3+),使用时需要在脚本配置内的argument参数中填写筛选策略(组)的正则表达式,留空则表示同时使用所有策略(组)
+注:该脚本仅兼容Surge(4.9.3+),使用时需要在脚本配置内的argument参数中填写筛选策略/组的正则表达式,留空则表示同时使用所有策略/组
Surge脚本配置:
[Script]
-Google CAPTCHA = type=http-response,pattern=^https:\/\/www\.google\.com(\.[a-z]+|)\/search\?q=,requires-body=1,debug=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js,max-size=0,timeout=10,ability=http-client-policy,argument=^(🇸🇬|🇭🇰)\s.*\d+$
+Google CAPTCHA = type=http-response,pattern=^https:\/\/www\.google\.com(\.[a-z]+|)\/search\?(client=[a-z-]+&|)q=,requires-body=1,debug=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js,max-size=0,timeout=10,ability=http-client-policy,argument=^(🇸🇬|🇭🇰)\s.*\d+$
[MITM]
hostname = www.google.com*
@@ -26,6 +26,8 @@ let ret = {};
return n && new RegExp(typeof $argument == 'string' ? $argument : "").test(n)
});
console.log(`[INFO]: Use policy ${JSON.stringify(selected, null, 2)}`);
+ delete $request.headers.cookie;
+ delete $request.headers.Cookie;
const http = [
new Promise((r, e) => setTimeout(() => e('Timeout'), 5000)),
...selected.map(
From 5de8bd53111f1ea19025c1244929636f30f419e4 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Wed, 16 Aug 2023 18:37:27 +0800
Subject: [PATCH 062/105] Remove obsolete files.
---
Loon/Loon_TF_Download.conf | 11 ----
QuantumultX/File/aimeiju.js | 77 -----------------------
QuantumultX/File/dapian.js | 32 ----------
QuantumultX/Js.conf | 12 +---
QuantumultX/Sinppet/NewBing.snippet | 5 --
README.md | 96 ++++++++++++++---------------
Surge/JS/IPA_install.js | 81 ------------------------
Surge/Module/NewBing.sgmodule | 8 ---
8 files changed, 47 insertions(+), 275 deletions(-)
delete mode 100644 Loon/Loon_TF_Download.conf
delete mode 100644 QuantumultX/File/aimeiju.js
delete mode 100644 QuantumultX/File/dapian.js
delete mode 100644 QuantumultX/Sinppet/NewBing.snippet
delete mode 100644 Surge/JS/IPA_install.js
delete mode 100644 Surge/Module/NewBing.sgmodule
diff --git a/Loon/Loon_TF_Download.conf b/Loon/Loon_TF_Download.conf
deleted file mode 100644
index d01ea5174d..0000000000
--- a/Loon/Loon_TF_Download.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-#!name= TestFlight区域限制解除
-#!desc= ‼️‼️‼️‼️‼️ 该URL已弃用,将在一段时间后删除;请把URL后缀 .conf 更换为 .plugin
-
-[General]
-skip-proxy = iosapps.itunes.apple.com
-
-[Script]
-http-request ^https?:\/\/testflight\.apple\.com\/v\d\/accounts\/.+?\/install$ requires-body=1,max-size=0,script-path=https://gist.githubusercontent.com/NobyDa/9be418b93afc5e9c8a8f4d28ae403cf2/raw/TF_Download.js, tag=TF区域限制解除
-
-[MITM]
-hostname = testflight.apple.com
diff --git a/QuantumultX/File/aimeiju.js b/QuantumultX/File/aimeiju.js
deleted file mode 100644
index 7ae00ccfcf..0000000000
--- a/QuantumultX/File/aimeiju.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-爱美剧 解锁部分功能
-官网: https://www.mjapp.cc
-脚本原作者: 灰灰
-
-可自行添加启动广告/弹窗规则, REGEX:
-^https?://api.bjxkhc.com/index.php/app/ios/ads/index
-^https?://api.bjxkhc.com/index.php/app/ios/ver/index_ios$
-^https?://api.bjxkhc.com/index.php/app/ios/pay/ok$
-
-***************************
-QuantumultX:
-
-[rewrite_local]
-^https?:\/\/api.bjxkhc.com\/index\.php\/app\/ios\/(vod\/show|(user|vod|topic|type)\/index) url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/aimeiju.js
-
-[mitm]
-hostname = api.bjxkhc.com
-
-***************************
-Surge4 or Loon:
-
-[Script]
-http-response ^https?:\/\/api.bjxkhc.com\/index\.php\/app\/ios\/(vod\/show|(user|vod|topic|type)\/index) requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/aimeiju.js
-
-[MITM]
-hostname = api.bjxkhc.com
-
-**************************/
-
-var url = $request.url;
-var obj = JSON.parse($response.body || '{}');
-const user = "/index.php/app/ios/user/index"; //用户信息
-const show = "/index.php/app/ios/vod/show"; //视频播放页面
-const banner = "/index.php/app/ios/vod/index";//首页轮播广告
-const topic = "/index.php/app/ios/topic/index";//豆瓣热榜中间广告
-const type = "/index.php/app/ios/type/index"//综合专区,美剧专区中间广告
-
-if (obj.data && obj.data.user && url.indexOf(user) != -1) {
- obj.data.user.viptime = "2088-08-08 08:08:08";
- obj.data.user.cion = "88888";
- obj.data.user.vip = "1";
-}
-
-if (obj.data && url.indexOf(show) != -1) {
- obj.data.looktime = -1;
- obj.data.vip = "4";
- delete obj.data.advertising;//视频下方轮播,删掉也不能清除广告占位
- obj.data.CT_App_Show_Pic1 = "";//联系客服图片
- obj.data.CT_App_Show_Url1 = "";//联系客服链接
- obj.data.CT_App_Show_Vod1 = "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1519044039,3175177225&fm=26&gp=0.jpg";//片头广告,留空的话不会自动播放
- obj.data.CT_App_Show_Vod_Time1 = "0";//片头广告显示时间(0秒也短暂显示)
- obj.data.CT_App_Show_Vod_Url1 = "";//片头广告链接
- obj.data.CT_App_Show_Vod_Type1 = "2";//片头广告显示类型,0一直显示,1暂停播放显示,2显示后自动播放
- obj.data.CT_App_Show_Vod_must_Time1 = "0";//片头联系客服图片显示时间,前面改VIP这里自动变0
- obj.data.CT_Pic_url1_pause = "";//暂停联系客服图片
- obj.data.CT_Pic_url1_pause_skip = "";//暂停联系客服链接
-}
-
-if (obj.data && url.indexOf(banner) != -1) {
- for (var i = obj.data.length - 1; i >= 0; i--) {
- if (obj.data[i].ad == 1) {
- obj.data.splice(i, 1)
- }
- }
-}
-
-if (obj.data && (url.indexOf(topic) != -1 || url.indexOf(type) != -1)) {
- for (var i = obj.data.length - 1; i >= 0; i--) {
- if (obj.data[i].ad == 1) {
- obj.data[i].ad = 0;
- obj.data[i].pic = "";
- delete obj.data[i].url
- }
- }
-}
-$done({ body: JSON.stringify(obj) });
\ No newline at end of file
diff --git a/QuantumultX/File/dapian.js b/QuantumultX/File/dapian.js
deleted file mode 100644
index c066da7d41..0000000000
--- a/QuantumultX/File/dapian.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-Bigshot 解锁高级特权(需登录)
-
-***************************
-QuantumultX:
-
-[rewrite_local]
-^https:\/\/vni\.kwaiying\.com\/api\/v1\/user\/profile url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/dapian.js
-
-[mitm]
-hostname = vni.kwaiying.com
-
-***************************
-Surge4 or Loon:
-
-[Script]
-http-response ^https:\/\/vni\.kwaiying\.com\/api\/v1\/user\/profile requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/dapian.js
-
-[MITM]
-hostname = vni.kwaiying.com
-**************************/
-
-var obj = JSON.parse($response.body);
-
-if (obj.data && obj.data.userInfo) {
- obj.data.userInfo.isVip = 1;
- obj.data.userInfo.memberId = 666
- obj.data.userInfo.vipStartTime = 1591430766000;
- obj.data.userInfo.vipEndTime = 3043037166000;
-}
-
-$done({ body: JSON.stringify(obj) });
\ No newline at end of file
diff --git a/QuantumultX/Js.conf b/QuantumultX/Js.conf
index db786ddeb0..d998a771f9 100644
--- a/QuantumultX/Js.conf
+++ b/QuantumultX/Js.conf
@@ -1,11 +1,8 @@
-hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.zhihu.com, vip1.kuwo.cn, p.du.163.com, apigate.zymk.cn, www.luqijianggushi.com, *account.wps.com, *account.wps.cn, origin-prod-phoenix.jibjab.com, xy-viva.kakalili.com, ap*.intsig.net, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api-chn.rthdo.com
+hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.zhihu.com, p.du.163.com, apigate.zymk.cn, www.luqijianggushi.com, origin-prod-phoenix.jibjab.com, xy-viva.kakalili.com, ap*.intsig.net, ios.fuliapps.com, apple.fuliapps.com, *.pipiapps.com, ios.xiangjiaoapps.com, apple.xiangjiaoapps.com, *.xiangxiangapps.com, api.m.jd.com, ios*.prod.ftl.netflix.com, api.revenuecat.com, pan.baidu.com, bmall.camera360.com, api-chn.rthdo.com
# 去微信公众号广告 (By Choler)
^https?:\/\/mp\.weixin\.qq\.com\/mp\/getappmsgad url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js
-# 酷我音乐SVIP (By yxiaocai)
-^https?:\/\/vip1\.kuwo\.cn\/(vip\/v2\/user\/vip|vip\/spi/mservice) url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Kuwo.js
-
# 网易蜗牛读书VIP (By yxiaocai and JO2EY)
^https?://p\.du\.163\.com/readtime/info.json url reject
^https?:\/\/p\.du\.163\.com\/gain\/readtime\/info\.json url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js
@@ -23,9 +20,6 @@ hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.
# 陆琪讲故事
^https:\/\/www\.luqijianggushi\.com\/api\/v2\/user\/get url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js
-# WPS (By eHpo)
-^https?:\/\/[a-z-]*account\.wps\.c(n|om)(:\d+|)\/api\/users url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js
-
# JibJab解锁pro
^https:\/\/origin-prod-phoenix\.jibjab\.com\/v1\/user url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js
@@ -52,10 +46,6 @@ hostname = api.weibo.cn, mapi.weibo.com, *.uve.weibo.com, mp.weixin.qq.com, api.
# 知乎去广告 (onewayticket255)
https://api.zhihu.com/(ad|drama|fringe|commercial|market/popover|search/(top|preset|tab)|.*featured-comment-ad) url reject-200
-# 哔哩哔哩动画去广告 (onewayticket255)
-https://app.bilibili.com/x/v2/(splash|search/square) url reject-200
-https://api.bilibili.com/x/v2/dm/ad url reject-200
-
# 京东比价
^https?://api\.m\.jd\.com/client\.action\?functionId=(wareBusiness|serverConfig|basicConfig) url script-response-body https://service.2ti.st/QuanX/Script/jd_tb_price/main.js
diff --git a/QuantumultX/Sinppet/NewBing.snippet b/QuantumultX/Sinppet/NewBing.snippet
deleted file mode 100644
index 5493256b56..0000000000
--- a/QuantumultX/Sinppet/NewBing.snippet
+++ /dev/null
@@ -1,5 +0,0 @@
-# Unlock browser restrictions for new bing AI search.
-
-^https:\/\/www\.bing\.com\/(search|new) url request-header (\r\nUser-Agent:.+?)\w+\/[\d\.]+(\r\n) request-header $1AppleWebKit/537.36 Chrome/110.0 Safari/537.36 Edg/110.0$2
-
-hostname = www.bing.com
\ No newline at end of file
diff --git a/README.md b/README.md
index d4183bef5a..d08a45cf11 100644
--- a/README.md
+++ b/README.md
@@ -26,53 +26,51 @@
### Daily-Bonus Script
-| Application | Script name | Available | Maintenance |
-| :-----------------------------------------------------: | :----------------------------------------------------------: | :-----------: | :---------: |
-| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ❌ | ⚠️ |
-| [百度贴吧](https://apps.apple.com/app/id477927812) | [TieBa.js](https://github.com/NobyDa/Script/blob/master/BDTieBa-DailyBonus/TieBa.js) | ✅(2023/03/14) | ❌ |
-| [吾爱破解](https://www.52pojie.cn/) | [52pojie.js](https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js) | ❌ | ❌ |
-| [爱奇艺](https://apps.apple.com/cn/app/id393765873) | [iQIYI.js](https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js) | ✅(2023/03/14) | ✅ |
-| [快看漫画](https://apps.apple.com/app/id906936224) | [KKMH.js](https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js) | ✅(2023/03/14) | ✅ |
-| [哔哩哔哩漫画](https://apps.apple.com/app/id1426252715) | [Manga.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js) | ✅(2023/03/14) | ✅ |
-| [巴哈姆特](https://www.gamer.com.tw/) | [BahamutDailyBonus.js](https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js) | ✅(2023/03/14) | ✅ |
+| Application | Script name | Available | Maintenance |
+|:-------------------------------------------------:|:-------------------------------------------------------------------------------------------------:|:-------------:|:-----------:|
+| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ❌ | ⚠️ |
+| [百度贴吧](https://apps.apple.com/app/id477927812) | [TieBa.js](https://github.com/NobyDa/Script/blob/master/BDTieBa-DailyBonus/TieBa.js) | ✅(2023/03/14) | ❌ |
+| [吾爱破解](https://www.52pojie.cn/) | [52pojie.js](https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js) | ❌ | ❌ |
+| [爱奇艺](https://apps.apple.com/cn/app/id393765873) | [iQIYI.js](https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js) | ✅(2023/03/14) | ✅ |
+| [快看漫画](https://apps.apple.com/app/id906936224) | [KKMH.js](https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js) | ✅(2023/03/14) | ✅ |
+| [哔哩哔哩漫画](https://apps.apple.com/app/id1426252715) | [Manga.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js) | ✅(2023/03/14) | ✅ |
+| [巴哈姆特](https://www.gamer.com.tw/) | [BahamutDailyBonus.js](https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js) | ✅(2023/03/14) | ✅ |
------
### Functionality-enhancing Script
-| Script name | Description |
-| :----------------------------------------------------------: | :----------------------------------------------------------: |
-| [PolicySwitch.js](https://github.com/NobyDa/Script/blob/master/Shortcuts/PolicySwitch.js) | Switch [QX](https://apps.apple.com/app/id1443988620),[Surge](https://apps.apple.com/app/id1442620678),[Loon](https://apps.apple.com/app/id1373567447) policy groups using ios [shortcut](https://apps.apple.com/app/id1462947752). |
-| [DataQuery.js](https://github.com/NobyDa/Script/blob/master/Sub-store-parser/DataQuery.js) | Server(VPN) traffic query based on [Sub-Store](https://github.com/Peng-YM/Sub-Store). |
-| [Bili_Auto_Regions.js](https://github.com/NobyDa/Script/blob/master/Surge/JS/Bili_Auto_Regions.js) | [Bilibili anime](https://apps.apple.com/cn/app/id736536022) auto switch region & show [douban](https://www.douban.com/) rating. |
-| [ExchangePoints.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/ExchangePoints.js) | [Bilibili Comics](https://apps.apple.com/app/id1426252715) points mall auto snap up. |
-| [TestFlightAccount.js](https://github.com/NobyDa/Script/blob/master/TestFlight/TestFlightAccount.js) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts |
-| [Google_CAPTCHA.js](https://github.com/NobyDa/Script/blob/master/Surge/JS/Google_CAPTCHA.js) | Google CAPTCHA solution(Surge only) |
+| Script name | Description |
+|:-------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
+| [PolicySwitch.js](https://github.com/NobyDa/Script/blob/master/Shortcuts/PolicySwitch.js) | Switch [QX](https://apps.apple.com/app/id1443988620),[Surge](https://apps.apple.com/app/id1442620678),[Loon](https://apps.apple.com/app/id1373567447) policy groups using ios [shortcut](https://apps.apple.com/app/id1462947752). |
+| [DataQuery.js](https://github.com/NobyDa/Script/blob/master/Sub-store-parser/DataQuery.js) | Server(VPN) traffic query based on [Sub-Store](https://github.com/Peng-YM/Sub-Store). |
+| [Bili_Auto_Regions.js](https://github.com/NobyDa/Script/blob/master/Surge/JS/Bili_Auto_Regions.js) | [Bilibili anime](https://apps.apple.com/cn/app/id736536022) auto switch region & show [douban](https://www.douban.com/) rating. |
+| [ExchangePoints.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/ExchangePoints.js) | [Bilibili Comics](https://apps.apple.com/app/id1426252715) points mall auto snap up. |
+| [TestFlightAccount.js](https://github.com/NobyDa/Script/blob/master/TestFlight/TestFlightAccount.js) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts |
+| [Google_CAPTCHA.js](https://github.com/NobyDa/Script/blob/master/Surge/JS/Google_CAPTCHA.js) | Google CAPTCHA solution(Surge only) |
---
### Other Script
-| Application | Script name | Description | Available |
-| :----------------------------------------------------------: | :----------------------------------------------------------: | :---------------------: | :---------------------: |
-| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
-| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
-| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅ (2023/03/14) |
-| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ❌ |
-| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅ (2023/03/14) |
-| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ❌ |
-| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ⚠️ (Not tested recently) |
-| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ⚠️ (Not tested recently) |
-| [酷我音乐](https://apps.apple.com/cn/app/id588673713) | [Kuwo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Kuwo.js) | Unlock vip listen | ⚠️ (Not tested recently) |
-| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ⚠️ (Not tested recently) |
-| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ⚠️ (Not tested recently) |
-| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅ (2023/03/14) |
-| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅ (2023/03/14) |
-| [WPS Office](https://apps.apple.com/app/id1491101673) | [Wps.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Wps.js) | Unlock membership | ⚠️ (Not tested recently) |
-| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅ (2023/03/14) |
-| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅ (2023/03/14) |
-| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ❌ |
-| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅ (2023/03/14) |
+| Application | Script name | Description | Available |
+|:---------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------:|:-----------------------:|:----------------------------------------------------:|
+| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
+| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
+| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅ (2023/03/14) |
+| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ❌ |
+| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅ (2023/03/14) |
+| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ❌ |
+| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ⚠️ (Not tested recently) |
+| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ⚠️ (Not tested recently) |
+| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ⚠️ (Not tested recently) |
+| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ⚠️ (Not tested recently) |
+| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅ (2023/03/14) |
+| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅ (2023/03/14) |
+| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅ (2023/03/14) |
+| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅ (2023/03/14) |
+| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ❌ |
+| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅ (2023/03/14) |
---
@@ -88,26 +86,24 @@
### Surge Module
-| Module name | Description |
-| :----------------------------------------------------------: | :----------------------------------------------------------: |
-| [HuiJuDongManAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/HuiJuDongManAds.sgmodule) | Remove [APP](https://apps.apple.com/app/id1451949669) Ads |
-| [IPA_install.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/IPA_install.sgmodule) | Use Surge to assist in install IPA (signed version) |
+| Module name | Description |
+|:------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:|
+| [HuiJuDongManAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/HuiJuDongManAds.sgmodule) | Remove [APP](https://apps.apple.com/app/id1451949669) Ads |
+| [IPA_install.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/IPA_install.sgmodule) | Use Surge to assist in install IPA (signed version) |
| [TestFlightDownload.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightDownload.sgmodule) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions |
-| [TestFlightAccount.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightAccount.sgmodule) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts |
-| [GetCookie.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/GetCookie.sgmodule) | Daily bonus script related |
-| [BahamutAnimeAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/BahamutAnimeAds.sgmodule) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads |
-| [NewBing.sgmodule](https://github.com/NobyDa/Script/blob/master/Surge/Module/NewBing.sgmodule) | Unlock browser restrictions for new bing AI search. |
+| [TestFlightAccount.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightAccount.sgmodule) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts |
+| [GetCookie.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/GetCookie.sgmodule) | Daily bonus script related |
+| [BahamutAnimeAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/BahamutAnimeAds.sgmodule) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads |
---
## QuantumultX File Overview
-| File name | Description | Type |
-| :----------------------------------------------------------: | :----------------------------------------------------------: | :---------------: |
-| [Js.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js.conf) | Remote script subscription. | Rewrite Resources |
-| [Js_Remote_Cookie.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf) | Daily bonus script related | Rewrite Resources |
+| File name | Description | Type |
+|:---------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:|:-----------------:|
+| [Js.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js.conf) | Remote script subscription. | Rewrite Resources |
+| [Js_Remote_Cookie.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf) | Daily bonus script related | Rewrite Resources |
| [TestFlightDownload.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/TestFlightDownload.conf) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions | Rewrite Resources |
-| [NewBing.snippet](https://github.com/NobyDa/Script/blob/master/QuantumultX/Sinppet/NewBing.snippet) | Unlock browser restrictions for new bing AI search. | Rewrite Resources |
Rules of type "Rule" include only ad hosts. Please select the REJECT policy.
diff --git a/Surge/JS/IPA_install.js b/Surge/JS/IPA_install.js
deleted file mode 100644
index 0c8245daf8..0000000000
--- a/Surge/JS/IPA_install.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * iOS14 IPA辅助安装脚本.
- *
- * 该脚本仅兼容Surge4.0+, 可解决iOS14或IPadOS14无法在移动端安装IPA的问题.
- * 注: 该脚本需要使用"Shu+捷径"或"Jsbox"辅助安装. 具体安装演示请移步TG频道 @NobyDa 查看.
- *
- * 作者: @NobyDa
- *
- * Surge模块地址: https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/IPA_install.sgmodule
- *
- * Jsbox辅助安装脚本: https://gist.githubusercontent.com/NobyDa/2489e84ca833a9ae559c2cf534b9cdc8/raw/IPA_Jsbox.js
- *
- * 捷径地址: https://www.icloud.com/shortcuts/53a7dad769c6453ca2ee54fa2a021ea2
- *
- */
-
-const eva = $request;
-const ipaUrl = eva.url.match(/\/jsbox/) ? "http://localhost:8080/download?path=%2Fapp.ipa" : "http://localhost/";
-if (eva.url.match(/install/)) {
- $httpClient.head(ipaUrl, (err, resp, data) => {
- if (resp && resp.headers && JSON.stringify(resp.headers).match(/UTF-8''.+?\.ipa/) && resp.status == 200) {
- const plist = `
-
-
-
- items
-
-
- assets
-
-
- kind
- software-package
- url
- https://nobyda/download${eva.url.match(/jsbox/)?"/jsbox":""}
-
-
- metadata
-
- bundle-identifier
- *
- bundle-version
- 1.0
- kind
- software
- title
- ${decodeURIComponent(JSON.stringify(resp.headers).match(/UTF-8''(.+?)\.ipa/)[1])}
-
-
-
-
- `;
- $done({
- response: {
- status: 200,
- body: plist
- }
- });
- } else {
- $notification.post('APP安装失败', '', '无法读取IPA安装包');
- $done()
- }
- })
-} else if (eva.method == "GET") {
- $httpClient.head(ipaUrl, (err, resp, data) => {
- if (resp && resp.headers && resp.status == 200) {
- const name = `正在安装: ${JSON.stringify(resp.headers).match(/UTF-8''(.+?)\.ipa/)[1]} ...`
- const size = `应用大小: ${(resp.headers['Content-Length'] / 1000 / 1000).toFixed(2)} MB`
- $notification.post(decodeURIComponent(name), size, '');
- } else {
- $notification.post('APP安装失败', '', `无法下载IPA安装包`);
- }
- $done({
- url: ipaUrl
- });
- })
-} else {
- $done({
- url: ipaUrl
- });
-}
\ No newline at end of file
diff --git a/Surge/Module/NewBing.sgmodule b/Surge/Module/NewBing.sgmodule
deleted file mode 100644
index f3ca76baf7..0000000000
--- a/Surge/Module/NewBing.sgmodule
+++ /dev/null
@@ -1,8 +0,0 @@
-#!name=New Bing for other browsers
-#!desc=Unlock browser restrictions for new bing AI search.
-
-[Header Rewrite]
-^https:\/\/www\.bing\.com\/(search|new) header-replace-regex User-Agent \w+\/[\d\.]+$ "AppleWebKit/537.36 Chrome/110.0 Safari/537.36 Edg/110.0"
-
-[MITM]
-hostname = %APPEND% www.bing.com
\ No newline at end of file
From 592c63af4dec5cbca548d3370f78d60a4c3308c5 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Wed, 16 Aug 2023 19:47:08 +0800
Subject: [PATCH 063/105] Update ipa installer script.
---
IPA-Installer/IPA-Installer-JSBox.js | 144 +++++++++++++++++++++
IPA-Installer/IPA-Installer-Pythonista.py | 74 +++++++++++
IPA-Installer/IPA-Installer.js | 146 ++++++++++++++++++++++
Loon/Loon_IPA_Installer.plugin | 12 ++
QuantumultX/IPA-Installer.snippet | 6 +
Stash/IPA-Installer.stoverride | 16 +++
Surge/Module/IPA_install.sgmodule | 9 +-
7 files changed, 403 insertions(+), 4 deletions(-)
create mode 100644 IPA-Installer/IPA-Installer-JSBox.js
create mode 100644 IPA-Installer/IPA-Installer-Pythonista.py
create mode 100644 IPA-Installer/IPA-Installer.js
create mode 100644 Loon/Loon_IPA_Installer.plugin
create mode 100644 QuantumultX/IPA-Installer.snippet
create mode 100644 Stash/IPA-Installer.stoverride
diff --git a/IPA-Installer/IPA-Installer-JSBox.js b/IPA-Installer/IPA-Installer-JSBox.js
new file mode 100644
index 0000000000..1284aaac21
--- /dev/null
+++ b/IPA-Installer/IPA-Installer-JSBox.js
@@ -0,0 +1,144 @@
+/*
+ * IPA-installer JSBox script. This script is not available stand alone, checkout the demo from TG channel @NobyDa
+ *
+ * Modified from https://github.com/axelburks/JSBox/blob/master/IPA%20Installer.js by @NobyDa
+ */
+
+var port_number = 8070
+var plist_url = `itms-services://?action=download-manifest&url=https://nobyda.app/install%3Fclient%3Djsbox%26url%3Dhttp%253A%252F%252F127.0.0.1%253A${port_number}%252Fdownload%253Fpath%253D%25252Fapp.ipa`
+
+$app.strings = {
+ "en": {
+ "starterror": "Not support running in this way",
+ "ftypeerror": " is not ipa file",
+ "installtitle": "Installing...",
+ "installmsg": "\n\nYou can check on Homescreen.\nPlease tap \"Done\" button after finished",
+ "inerrtitle": "IPA file import error",
+ "inerrmsg": "Please rerun the script"
+ },
+ "zh-Hans": {
+ "starterror": "不支持此方式运行!",
+ "ftypeerror": " 非 ipa 文件!",
+ "installtitle": "正在安装…",
+ "installmsg": "\n\n可前往桌面查看安装进度\n完成后请点击\"Done\"按钮",
+ "inerrtitle": "IPA文件导入失败",
+ "inerrmsg": "请重新运行此脚本"
+ }
+}
+
+// 从应用内启动
+if ($app.env == $env.app) {
+ $drive.open({
+ handler: function(data) {
+ fileCheck(data)
+ }
+ })
+}
+// 从 Action Entension 启动
+else if ($app.env == $env.action) {
+ fileCheck($context.data)
+}
+
+else {
+ $ui.error($l10n("starterror"))
+ delayClose(2)
+}
+
+
+function startServer(port) {
+ $http.startServer({
+ port: port,
+ path: "",
+ handler: function(result) {
+ console.info(result.url)
+ }
+ })
+}
+
+function fileCheck(data) {
+ if (data && data.fileName) {
+ var fileName = data.fileName;
+ if (fileName.indexOf(".ipa") == -1) {
+ $ui.error(fileName + $l10n("ftypeerror"))
+ delayClose(2)
+ } else {
+ install(fileName, data);
+ }
+ }
+}
+
+function install(fileName, file) {
+ var result = $file.write({
+ data: file,
+ path: "app.ipa"
+ })
+ if (result) {
+ startServer(port_number)
+ $location.startUpdates({
+ handler: function(resp) {
+ console.info(resp.lat + " " + resp.lng + " " + resp.alt)
+ }
+ })
+ var preResult = $app.openURL(plist_url);
+ if (preResult) {
+ $ui.alert({
+ title: $l10n("installtitle"),
+ message: "\n" + fileName + $l10n("installmsg"),
+ actions: [{
+ title: "Cancel",
+ style: "Cancel",
+ handler: function() {
+ $http.stopServer()
+ $file.delete("app.ipa")
+ delayClose(0.2)
+ }
+ },
+ {
+ title: "Done",
+ handler: function() {
+ $http.stopServer()
+ $file.delete("app.ipa")
+ delayClose(0.2)
+ }
+ }]
+ })
+ } else {
+ $ui.alert({
+ title: "Open itms-services scheme failed",
+ message: "Please rerun the script or restart device",
+ actions: [
+ {
+ title: "OK",
+ handler: function() {
+ delayClose(0.2)
+ }
+ }]
+ })
+ }
+ } else {
+ $ui.alert({
+ title: $l10n("inerrtitle"),
+ message: $l10n("inerrmsg"),
+ actions: [{
+ title: "OK",
+ style: "Cancel",
+ handler: function() {
+ delayClose(0.2)
+ }
+ }]
+ })
+ }
+}
+
+function delayClose(time) {
+ $location.stopUpdates()
+ $thread.main({
+ delay: time,
+ handler: function() {
+ if ($app.env == $env.action || $app.env == $env.safari) {
+ $context.close()
+ }
+ $app.close()
+ }
+ })
+}
diff --git a/IPA-Installer/IPA-Installer-Pythonista.py b/IPA-Installer/IPA-Installer-Pythonista.py
new file mode 100644
index 0000000000..a929058fe7
--- /dev/null
+++ b/IPA-Installer/IPA-Installer-Pythonista.py
@@ -0,0 +1,74 @@
+# IPA-installer pythonista script. This script is not available stand alone, checkout the demo from TG channel @NobyDa
+#
+# Modified from https://github.com/axelburks/Pythonista/blob/master/IPA%20Installer.py by @NobyDa
+
+import os, appex, console, shutil, http.server, webbrowser, time
+from os import path
+from threading import Thread
+
+port_number = 8090
+plist_url = f'itms-services://?action=download-manifest&url=https://nobyda.app/install%3Fclient%3Dpythonista%26url%3Dhttp%253A%252F%252F127.0.0.1%253A{port_number}%252Fipa%252Fapp.ipa'
+save_dir = path.expanduser('./ipa')
+if not path.exists(save_dir):
+ os.makedirs(save_dir)
+
+httpd = None
+def startServer(port):
+ Handler = http.server.SimpleHTTPRequestHandler
+
+ global httpd
+ httpd = http.server.HTTPServer(("", port), Handler)
+
+ print("Start server at port", port)
+ httpd.serve_forever()
+
+def start(port):
+ thread = Thread(target=startServer, args=[port])
+ thread.start()
+
+ startTime = int(time.time())
+ while not httpd:
+ if int(time.time()) > startTime + 60:
+ print("Time out")
+ break
+ return httpd
+
+def stop():
+ if httpd:
+ httpd.shutdown()
+
+def main():
+ if appex.is_running_extension():
+ get_path = appex.get_file_path()
+ file_name = path.basename(get_path)
+ file_ext = path.splitext(file_name)[-1]
+ if file_ext == '.ipa':
+ dstpath = path.join(save_dir, 'app.ipa')
+ try:
+ shutil.copy(get_path, dstpath)
+
+ except Exception as eer:
+ print(eer)
+ console.hud_alert('导入失败!','error',1)
+ start(port_number)
+ if httpd:
+ webbrowser.open(plist_url)
+ try:
+ finish = console.alert(file_name, '\n正在安装...请返回桌面查看进度...\n\n安装完成后请返回点击已完成','已完成', hide_cancel_button=False)
+ if finish == 1:
+ stop()
+ shutil.rmtree('./ipa')
+ print("Server stopped")
+ except:
+ stop()
+ shutil.rmtree('./ipa')
+ print("Cancelled")
+ appex.finish()
+ else:
+ console.hud_alert('非 ipa 文件无法导入安装', 'error', 2)
+ appex.finish()
+ else:
+ console.hud_alert('请在分享扩展中打开本脚本','error',2)
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/IPA-Installer/IPA-Installer.js b/IPA-Installer/IPA-Installer.js
new file mode 100644
index 0000000000..38d47c7124
--- /dev/null
+++ b/IPA-Installer/IPA-Installer.js
@@ -0,0 +1,146 @@
+/*
+ * iOS IPA应用辅助安装脚本.
+ *
+ * 兼容: QuantumultX、Surge5,Loon、Shadowrocket、Stash
+ * 作者: @NobyDa
+ *
+ * 快捷指令 + Shu配合安装:
+ * 导入IPA文件至Shu -> Shu长按IPA文件 -> 导出文件 -> WiFi传输 -> 本机 -> 系统共享 -> 分享至IPA-Installer快捷指令
+ *
+ * 快捷指令 + JSBox/Pythonista配合安装:
+ * IPA文件长按分享至IPA-Installer快捷指令,完成后再分享至Jsbox/pythonista分享扩展.
+ *
+ *
+ * QuanX重写: https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/IPA-Installer.snippet
+ *
+ * Surge模块: https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/IPA_install.sgmodule
+ *
+ * loon插件: https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_IPA_Installer.plugin
+ *
+ * Stash覆写: https://raw.githubusercontent.com/NobyDa/Script/master/Stash/IPA-Installer.stoverride
+ *
+ * 快捷指令: https://www.icloud.com/shortcuts/a89979261837465aa3b4cae3527cf5f9
+ *
+ * JSBox脚本: https://xteko.com/redir?url=https%3A%2F%2Fraw.githubusercontent.com%2FNobyDa%2FScript%2Fmaster%2FIPA-Installer%2FIPA-Installer-JSBox.js&name=IPA%20Installer%20%28NobyDa%29
+ *
+ * Pythonista脚本: https://github.com/NobyDa/Script/blob/master/IPA-Installer/IPA-Installer-Pythonista.py
+ */
+
+const $ = new compatible_tool();
+
+(async function () {
+ const args = urlArgs($request.url);
+ const plist = `
+
+
+
+ items
+
+
+ assets
+
+
+ kind
+ software-package
+ url
+ https://nobyda.app/download?url=${encodeURIComponent(args.url)}
+
+
+ metadata
+
+ bundle-identifier
+ ${args.bundleId || $.read("nobyda_ipa_bundle_id") || "*"}
+ bundle-version
+ 1.0
+ kind
+ software
+ title
+ IPA
+
+
+
+
+ `;
+ if ($request.url.includes("/install?")) {
+ if (args.bundleId) {
+ $.write(args.bundleId, "nobyda_ipa_bundle_id");
+ };
+ $.resp = { response: { status: 200, body: args.client && plist || "{}" } };
+ } else {
+ if ($request.method == "GET") {
+ const size = await ipaSize(args.url);
+ $.notify(`IPA Installer`, ``, size && `Installing IPA, Size: ${size} MB` || `HTTP local server read failed!`);
+ }
+ $.resp = { response: { status: 307, headers: { Location: args.url }, body: "{}" } };
+ }
+})()
+ .catch((e) => $.notify(`IPA Installer`, ``, `ERROR: ${e.message || e}\nPATH: ${e.stack}`))
+ .finally(() => $.done($.resp))
+
+
+function ipaSize(url) {
+ return new Promise((r, e) => {
+ $.http({ method: "head", url: url, policy: "DIRECT", }, (e, h, d) => {
+ r(h && h.status == 200 && `${((h.headers["Content-Length"] || 0) / 1000 / 1000).toFixed(2)}`)
+ });
+ setTimeout(() => r(), 1000)
+ });
+}
+
+function urlArgs(str) {
+ return Object.fromEntries(
+ (str.startsWith("http") && str.split("?")[1] || str).split("&")
+ .map((item) => item.split("="))
+ .map(([k, v]) => [k, decodeURIComponent(v)])
+ );
+}
+
+function compatible_tool() {
+ const isSurge = typeof $httpClient != "undefined";
+ const isQuanX = typeof $task != "undefined";
+ const isStash = typeof $environment == "object" && $environment["stash-version"];
+ const adapterStatus = (response) => {
+ if (response && response.statusCode) {
+ response.status = response.statusCode;
+ }
+ return response
+ };
+ this.read = (key) => {
+ if (isQuanX) return $prefs.valueForKey(key);
+ if (isSurge) return $persistentStore.read(key);
+ };
+ this.write = (value, key) => {
+ if (isQuanX) return $prefs.setValueForKey(value, key);
+ if (isSurge) return $persistentStore.write(value, key);
+ };
+ this.notify = (title, subtitle, message) => {
+ if (isQuanX) $notify(title, subtitle, message);
+ if (isSurge) $notification.post(title, subtitle, message);
+ };
+ this.http = (options, callback) => {
+ if (options.policy) {
+ options.node = options.policy;
+ options.opts = { policy: options.policy };
+ if (isStash) options.headers = {
+ ...options.headers,
+ ...{ "X-Stash-Selected-Proxy": encodeURIComponent(options.policy) }
+ };
+ }
+ if (isQuanX) {
+ $task.fetch(options).then(response => {
+ callback(null, adapterStatus(response), response.body)
+ }, reason => callback(reason.error, null, null))
+ }
+ if (isSurge) {
+ $httpClient[options.method](options, (error, response, body) => {
+ callback(error, adapterStatus(response), body)
+ })
+ }
+ };
+ this.done = (value = {}) => {
+ if (value.response && isQuanX) {
+ value.response.status = `HTTP/1.1 ${value.response.status}`;
+ }
+ $done((value.response && isQuanX) ? value.response : value)
+ }
+};
\ No newline at end of file
diff --git a/Loon/Loon_IPA_Installer.plugin b/Loon/Loon_IPA_Installer.plugin
new file mode 100644
index 0000000000..47c5531465
--- /dev/null
+++ b/Loon/Loon_IPA_Installer.plugin
@@ -0,0 +1,12 @@
+#!name=IPA应用辅助安装器
+#!desc=该模块可在iOS端辅助安装商店版或已签名IPA(需使用快捷指令 + Shu/Jsbox/pythonista), 查看脚本注释以了解具体方法; 安装演示可查看TG频道 @NobyDa
+#!author=NobyDa
+#!homepage=https://github.com/NobyDa/Script/tree/master
+#!icon=https://cdn.jsdelivr.net/gh/NobyDa/mini@master/Color/Apple.png
+
+
+[Script]
+http-request ^https:\/\/nobyda.app/(install|download) requires-body=true, script-path=https://raw.githubusercontent.com/NobyDa/Script/master/IPA-Installer/IPA-Installer.js, timeout=10, tag=IPA-Installer
+
+[MITM]
+hostname = nobyda.app
\ No newline at end of file
diff --git a/QuantumultX/IPA-Installer.snippet b/QuantumultX/IPA-Installer.snippet
new file mode 100644
index 0000000000..d8a3b125a3
--- /dev/null
+++ b/QuantumultX/IPA-Installer.snippet
@@ -0,0 +1,6 @@
+# 该文件为 "IPA应用辅助安装脚本" QuantumultX远端重写资源.
+# 该资源可在iOS端辅助安装商店版或已签名IPA(需使用快捷指令 + Shu/Jsbox/pythonista), 查看脚本注释以了解具体方法; 安装演示可查看TG频道 @NobyDa
+
+^https:\/\/nobyda.app/(install|download) url script-analyze-echo-response https://raw.githubusercontent.com/NobyDa/Script/master/IPA-Installer/IPA-Installer.js
+
+hostname = nobyda.app
\ No newline at end of file
diff --git a/Stash/IPA-Installer.stoverride b/Stash/IPA-Installer.stoverride
new file mode 100644
index 0000000000..29dd32268c
--- /dev/null
+++ b/Stash/IPA-Installer.stoverride
@@ -0,0 +1,16 @@
+name: IPA应用辅助安装器
+desc: 该模块可在iOS端辅助安装商店版或已签名IPA(需使用快捷指令 + Shu/Jsbox/pythonista), 查看脚本注释以了解具体方法; 安装演示可查看TG频道 @NobyDa
+
+http:
+ mitm:
+ - nobyda.app
+ script:
+ - match: ^https:\/\/nobyda.app/(install|download)
+ name: IPA-Installer
+ type: request
+ require-body: true
+ timeout: 10
+script-providers:
+ IPA-Installer:
+ url: https://raw.githubusercontent.com/NobyDa/Script/master/IPA-Installer/IPA-Installer.js
+ interval: 86400
\ No newline at end of file
diff --git a/Surge/Module/IPA_install.sgmodule b/Surge/Module/IPA_install.sgmodule
index b801d3918c..a9a707e58f 100644
--- a/Surge/Module/IPA_install.sgmodule
+++ b/Surge/Module/IPA_install.sgmodule
@@ -1,8 +1,9 @@
-#!name=iOS14 IPA应用安装
-#!desc=该模块可解决iOS14或IPadOS14无法在移动端安装IPA的问题. 注: 需要使用Shu+捷径或Jsbox辅助安装.
+#!name=IPA应用辅助安装器
+#!desc=该模块可在iOS端辅助安装商店版或已签名IPA(需使用快捷指令 + Shu/Jsbox/pythonista), 查看脚本注释以了解具体方法; 安装演示可查看TG频道 @NobyDa
+
[Script]
-IPA应用安装 = type=http-request,pattern=^https:\/\/nobyda/(install|download)(\/jsbox)?$,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/IPA_install.js
+IPA Installer = type=http-request,pattern=^https:\/\/nobyda.app/(install|download),requires-body=1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/IPA-Installer/IPA-Installer.js
[MITM]
-hostname = %APPEND% nobyda
\ No newline at end of file
+hostname = %APPEND% nobyda.app
\ No newline at end of file
From efa8b8799583335423c630cb559f999f3472f7d0 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Wed, 16 Aug 2023 20:00:27 +0800
Subject: [PATCH 064/105] Update readme.
---
README.md | 56 ++++++++++++++++++++++++++++++++-----------------------
1 file changed, 33 insertions(+), 23 deletions(-)
diff --git a/README.md b/README.md
index d08a45cf11..75b3554183 100644
--- a/README.md
+++ b/README.md
@@ -53,24 +53,24 @@
### Other Script
-| Application | Script name | Description | Available |
-|:---------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------:|:-----------------------:|:----------------------------------------------------:|
-| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
-| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
-| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅ (2023/03/14) |
-| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ❌ |
-| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅ (2023/03/14) |
-| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ❌ |
-| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ⚠️ (Not tested recently) |
-| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ⚠️ (Not tested recently) |
+| Application | Script name | Description | Available |
+|:---------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------:|:-----------------------:|:------------------------:|
+| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
+| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
+| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅ (2023/03/14) |
+| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ❌ |
+| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅ (2023/03/14) |
+| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ❌ |
+| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ⚠️ (Not tested recently) |
+| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ⚠️ (Not tested recently) |
| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ⚠️ (Not tested recently) |
-| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ⚠️ (Not tested recently) |
-| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅ (2023/03/14) |
-| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅ (2023/03/14) |
-| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅ (2023/03/14) |
-| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅ (2023/03/14) |
-| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ❌ |
-| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅ (2023/03/14) |
+| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ⚠️ (Not tested recently) |
+| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅ (2023/03/14) |
+| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅ (2023/03/14) |
+| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅ (2023/03/14) |
+| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅ (2023/03/14) |
+| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ❌ |
+| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅ (2023/03/14) |
---
@@ -104,6 +104,7 @@
| [Js.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js.conf) | Remote script subscription. | Rewrite Resources |
| [Js_Remote_Cookie.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf) | Daily bonus script related | Rewrite Resources |
| [TestFlightDownload.conf](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/TestFlightDownload.conf) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions | Rewrite Resources |
+| [IPA-Installer.snippet](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/IPA-Installer.snippe) | Use QX to assist in install IPA (signed version) | Rewrite Resources |
Rules of type "Rule" include only ad hosts. Please select the REJECT policy.
@@ -149,12 +150,21 @@ The above random generated device ID can be found at the bottom of Quantumult X
## Loon File Overview
-| File name | Description | Type |
-|:--------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:|:------:|
-| [Loon_GetCookie.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_GetCookie.plugin) | Daily bonus script related | Plugin |
-| [Loon_TF_Download.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Download.plugin) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions | Plugin |
-| [Loon_TF_Account.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Account.plugin) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts | Plugin |
-| [Loon_Bahamut_ADS.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_Bahamut_ADS.plugin) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads | Plugin |
+| File name | Description | Type |
+|:-------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:|:------:|
+| [Loon_GetCookie.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_GetCookie.plugin) | Daily bonus script related | Plugin |
+| [Loon_TF_Download.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Download.plugin) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions | Plugin |
+| [Loon_TF_Account.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Account.plugin) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts | Plugin |
+| [Loon_Bahamut_ADS.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_Bahamut_ADS.plugin) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads | Plugin |
+| [Loon_IPA_Installer.plugin]((https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_IPA_Installer.plugin) | Use Loon to assist in install IPA (signed version) | Plugin |
+
+---
+
+## Stash File Overview
+
+| File name | Description | Type |
+|:-----------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------:|:--------:|
+| [IPA-Installer.stoverride](https://raw.githubusercontent.com/NobyDa/Script/master/Stash/IPA-Installer.stoverride) | Use Stash to assist in install IPA (signed version) | Override |
---
From 89e4dc6524c5aec83f7016704687f968583331da Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Wed, 16 Aug 2023 21:47:38 +0800
Subject: [PATCH 065/105] Update shortcut url to support ios15.
---
IPA-Installer/IPA-Installer.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/IPA-Installer/IPA-Installer.js b/IPA-Installer/IPA-Installer.js
index 38d47c7124..6e166ac538 100644
--- a/IPA-Installer/IPA-Installer.js
+++ b/IPA-Installer/IPA-Installer.js
@@ -19,7 +19,7 @@
*
* Stash覆写: https://raw.githubusercontent.com/NobyDa/Script/master/Stash/IPA-Installer.stoverride
*
- * 快捷指令: https://www.icloud.com/shortcuts/a89979261837465aa3b4cae3527cf5f9
+ * 快捷指令: https://www.icloud.com/shortcuts/d8b2b49ae05141f892e6122c9084c67a
*
* JSBox脚本: https://xteko.com/redir?url=https%3A%2F%2Fraw.githubusercontent.com%2FNobyDa%2FScript%2Fmaster%2FIPA-Installer%2FIPA-Installer-JSBox.js&name=IPA%20Installer%20%28NobyDa%29
*
From f6cabc33a35209d7c604532aab2f53752a4bc238 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 17 Aug 2023 22:51:45 +0800
Subject: [PATCH 066/105] Update various script data.
---
QuantumultX/File/Zymh.js | 8 ++--
QuantumultX/File/vsco.js | 3 +-
README.md | 99 ++++++++++++++++++----------------------
Surge/JS/CamScanner.js | 2 +-
Surge/JS/PicsArt.js | 46 +++++++++++++++++--
Surge/JS/Polarr.js | 51 +++++++++++++--------
Surge/JS/vivavideo.js | 8 ++--
7 files changed, 129 insertions(+), 88 deletions(-)
mode change 100644 => 100755 README.md
diff --git a/QuantumultX/File/Zymh.js b/QuantumultX/File/Zymh.js
index d813926e16..ea44395072 100644
--- a/QuantumultX/File/Zymh.js
+++ b/QuantumultX/File/Zymh.js
@@ -5,19 +5,19 @@
QuantumultX:
[rewrite_local]
-^https:\/\/apigate\.zymk\.cn\/(zymk-getuserinfo-api\/v1\/getuserinfo|zymk-userpurchased-api\/v1\/userpurchased\/paychapters)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
+^https:\/\/apigate\.kaimanhua\.com\/(zymk-getuserinfo-api\/v1\/getuserinfo|zymk-userpurchased-api\/v1\/userpurchased\/paychapters)\/ url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
[mitm]
-hostname = apigate.zymk.cn
+hostname = apigate.kaimanhua.com
***************************
Surge4 or Loon:
[Script]
-http-response ^https:\/\/apigate\.zymk\.cn\/(zymk-getuserinfo-api\/v1\/getuserinfo|zymk-userpurchased-api\/v1\/userpurchased\/paychapters)\/ requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
+http-response ^https:\/\/apigate\.kaimanhua\.com\/(zymk-getuserinfo-api\/v1\/getuserinfo|zymk-userpurchased-api\/v1\/userpurchased\/paychapters)\/ requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js
[MITM]
-hostname = apigate.zymk.cn
+hostname = apigate.kaimanhua.com
**************************/
var obj = JSON.parse($response.body);
diff --git a/QuantumultX/File/vsco.js b/QuantumultX/File/vsco.js
index 2d8f247e56..c308e1dd1e 100644
--- a/QuantumultX/File/vsco.js
+++ b/QuantumultX/File/vsco.js
@@ -1,5 +1,5 @@
/********************************
-Membership unlock for VSCO & 1Blocker
+Membership unlock for VSCO & 1Blocker & HTTPBot
Please note that you may need to reinstall app for script to work.
QuantumultX rewrite link:
@@ -22,6 +22,7 @@ const resp = {};
const obj = JSON.parse(typeof $response != "undefined" && $response.body || null);
const ua = $request.headers['User-Agent'] || $request.headers['user-agent'];
const list = {
+ 'HTTPBot': { name: 'rc_lifetime', id: 'com.behindtechlines.HTTPBot.prounlock' },
'VSCO': { name: 'membership', id: 'com.circles.fin.premium.yearly' },
'1Blocker': { name: 'premium', id: 'blocker.ios.subscription.yearly' }
};
diff --git a/README.md b/README.md
old mode 100644
new mode 100755
index 75b3554183..2d53d4d436
--- a/README.md
+++ b/README.md
@@ -1,15 +1,13 @@
## TOC
-
- [TOC](#toc)
- [Script Overview](#script-overview)
- [Daily-Bonus Script](#daily-bonus-script)
- [Functionality-enhancing Script](#functionality-enhancing-script)
- [Other Script](#other-script)
- [Surge File Overview](#surge-file-overview)
- - [Surge Ruleset](#surge-ruleset)
- - [Surge Module](#surge-module)
- [QuantumultX File Overview](#quantumultx-file-overview)
- [Loon File Overview](#loon-file-overview)
+- [Stash File Overview](#stash-file-overview)
- [Disclaimer](#disclaimer)
- [Decrypt](#decrypt)
- [Privacy](#privacy)
@@ -20,21 +18,22 @@
- [Acknowledgment](#acknowledgment)
- [License](#license)
+
> **Please note that the scripts or rewrite rules described below may require MITM to be enabled, and the generated root certificate needs to be manually installed and trusted in the system.**
## Script Overview
### Daily-Bonus Script
-| Application | Script name | Available | Maintenance |
-|:-------------------------------------------------:|:-------------------------------------------------------------------------------------------------:|:-------------:|:-----------:|
-| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ❌ | ⚠️ |
-| [百度贴吧](https://apps.apple.com/app/id477927812) | [TieBa.js](https://github.com/NobyDa/Script/blob/master/BDTieBa-DailyBonus/TieBa.js) | ✅(2023/03/14) | ❌ |
-| [吾爱破解](https://www.52pojie.cn/) | [52pojie.js](https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js) | ❌ | ❌ |
-| [爱奇艺](https://apps.apple.com/cn/app/id393765873) | [iQIYI.js](https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js) | ✅(2023/03/14) | ✅ |
-| [快看漫画](https://apps.apple.com/app/id906936224) | [KKMH.js](https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js) | ✅(2023/03/14) | ✅ |
-| [哔哩哔哩漫画](https://apps.apple.com/app/id1426252715) | [Manga.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js) | ✅(2023/03/14) | ✅ |
-| [巴哈姆特](https://www.gamer.com.tw/) | [BahamutDailyBonus.js](https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js) | ✅(2023/03/14) | ✅ |
+| Application | Script name | Available | Maintenance |
+| :-----------------------------------------------------: | :----------------------------------------------------------: | :------------: | :---------: |
+| [京东商城](https://apps.apple.com/app/id414245413) | [JD_DailyBonus.js](https://github.com/NobyDa/Script/blob/master/JD-DailyBonus/JD_DailyBonus.js) | ❌ | ⚠️ |
+| [百度贴吧](https://apps.apple.com/app/id477927812) | [TieBa.js](https://github.com/NobyDa/Script/blob/master/BDTieBa-DailyBonus/TieBa.js) | ✅ (2023/08/17) | ❌ |
+| [吾爱破解](https://www.52pojie.cn/) | [52pojie.js](https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js) | ❌ | ❌ |
+| [爱奇艺](https://apps.apple.com/cn/app/id393765873) | [iQIYI.js](https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js) | ✅ (2023/08/17) | ✅ |
+| [快看漫画](https://apps.apple.com/app/id906936224) | [KKMH.js](https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js) | ✅ (2023/08/17) | ✅ |
+| [哔哩哔哩漫画](https://apps.apple.com/app/id1426252715) | [Manga.js](https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js) | ✅ (2023/08/17) | ✅ |
+| [巴哈姆特](https://www.gamer.com.tw/) | [BahamutDailyBonus.js](https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js) | ✅ (2023/08/17) | ✅ |
------
@@ -53,47 +52,37 @@
### Other Script
-| Application | Script name | Description | Available |
-|:---------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------:|:-----------------------:|:------------------------:|
-| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
-| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/03/14) |
-| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅ (2023/03/14) |
-| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ❌ |
-| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅ (2023/03/14) |
-| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ❌ |
-| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ⚠️ (Not tested recently) |
-| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ⚠️ (Not tested recently) |
-| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ⚠️ (Not tested recently) |
-| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ⚠️ (Not tested recently) |
-| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅ (2023/03/14) |
-| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅ (2023/03/14) |
-| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅ (2023/03/14) |
-| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅ (2023/03/14) |
-| [皮皮虾](https://apps.apple.com/cn/app/id1393912676) | [Super.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Super.js) | Remove Ads | ❌ |
-| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅ (2023/03/14) |
+| Application | Script name | Description | Available |
+| :----------------------------------------------------------: | :----------------------------------------------------------: | :---------------------: | :------------: |
+| [HTTPBot](https://apps.apple.com/cn/app/id1232603544) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/08/17) |
+| [VSCO](https://apps.apple.com/app/id588013838) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/08/17) |
+| [1Blocker](https://apps.apple.com/app/id1365531024) | [vsco.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/vsco.js) | Unlock membership | ✅ (2023/08/17) |
+| [JibJab](https://apps.apple.com/app/id875561136) | [jibjab.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/jibjab.js) | Unlock membership | ✅ (2023/08/17) |
+| [美易Picsart](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | [PicsArt.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js) | Unlock membership | ✅ (2023/08/17) |
+| [MIX滤镜大师](https://apps.apple.com/app/id913947918) | [MIX.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/MIX.js) | Unlock in-app purchases | ✅ (2023/08/17) |
+| [Polarr 泼辣](https://apps.apple.com/app/id988173374) | [Polarr.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js) | Unlock in-app purchases | ✅ (2023/08/17) |
+| [小影VivaVideo](https://apps.apple.com/app/id738897668) | [vivavideo.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js) | Unlock membership | ✅ (2023/08/17) |
+| [CamScanner](https://apps.apple.com/app/id388627783) | [CamScanner.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/CamScanner.js) | Unlock some benefits | ✅ (2023/08/17) |
+| [知音漫客](https://apps.apple.com/app/id1012491820) | [Zymh.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Zymh.js) | Unlock vip chapters | ✅ (2023/08/17) |
+| [香蕉视频](https://www.aa2.app) | [xjsp.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/xjsp.js) | Unlock membership | ✅ (2023/08/17) |
+| [网易蜗牛读书](https://apps.apple.com/app/id1127249355) | [wnyd.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/wnyd.js) | Unlock membership | ✅ (2023/08/17) |
+| [陆琪讲故事](https://apps.apple.com/app/id1435575842) | [luqi.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/luqi.js) | Unlock radio | ✅ (2023/08/17) |
+| [百度网盘](https://apps.apple.com/app/id547166701) | [BaiduCloud.js](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/BaiduCloud.js) | Unlock video speed | ✅ (2023/08/17) |
+| [WeChat](https://apps.apple.com/app/id414478124) | [Wechat.js](https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/File/Wechat.js) | Remove Ads | ✅ (2023/08/17) |
+| [動畫瘋](https://apps.apple.com/tw/app/id1102650114) | [BahamutAnimeAds.js](https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutAnimeAds.js) | Remove Ads | ✅ (2023/08/17) |
---
## Surge File Overview
-### Surge Ruleset
-
-| File name | Number | Description |
-|:-------------------------------------------------------------------------------------------:|:------:|:---------------------------------:|
-| [WeChat.list](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/WeChat.list) | 180+ | WeChat ruleset (China) |
-| [Apple.list](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Apple.list) | 60+ | Apple ruleset (Most countries) |
-| [Download.list](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Download.list) | 15+ | Some BT, Thunder, download rules. |
-
-### Surge Module
-
-| Module name | Description |
-|:------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:|
-| [HuiJuDongManAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/HuiJuDongManAds.sgmodule) | Remove [APP](https://apps.apple.com/app/id1451949669) Ads |
-| [IPA_install.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/IPA_install.sgmodule) | Use Surge to assist in install IPA (signed version) |
-| [TestFlightDownload.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightDownload.sgmodule) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions |
-| [TestFlightAccount.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightAccount.sgmodule) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts |
-| [GetCookie.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/GetCookie.sgmodule) | Daily bonus script related |
-| [BahamutAnimeAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/BahamutAnimeAds.sgmodule) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads |
+| File name | Description | Type |
+| :----------------------------------------------------------: | :----------------------------------------------------------: | ------ |
+| [HuiJuDongManAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/HuiJuDongManAds.sgmodule) | Remove [APP](https://apps.apple.com/app/id1451949669) Ads | Module |
+| [IPA_install.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/IPA_install.sgmodule) | Use Surge to assist in install IPA (signed version) | Module |
+| [TestFlightDownload.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightDownload.sgmodule) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions | Module |
+| [TestFlightAccount.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightAccount.sgmodule) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts | Module |
+| [GetCookie.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/GetCookie.sgmodule) | Daily bonus script related | Module |
+| [BahamutAnimeAds.sgmodule](https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/BahamutAnimeAds.sgmodule) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads | Module |
---
@@ -150,13 +139,13 @@ The above random generated device ID can be found at the bottom of Quantumult X
## Loon File Overview
-| File name | Description | Type |
-|:-------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:|:------:|
-| [Loon_GetCookie.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_GetCookie.plugin) | Daily bonus script related | Plugin |
-| [Loon_TF_Download.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Download.plugin) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions | Plugin |
-| [Loon_TF_Account.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Account.plugin) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts | Plugin |
-| [Loon_Bahamut_ADS.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_Bahamut_ADS.plugin) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads | Plugin |
-| [Loon_IPA_Installer.plugin]((https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_IPA_Installer.plugin) | Use Loon to assist in install IPA (signed version) | Plugin |
+| File name | Description | Type |
+| :----------------------------------------------------------: | :----------------------------------------------------------: | :----: |
+| [Loon_GetCookie.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_GetCookie.plugin) | Daily bonus script related | Plugin |
+| [Loon_TF_Download.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Download.plugin) | Remove [TestFlight](https://apps.apple.com/app/id899247664) region restrictions | Plugin |
+| [Loon_TF_Account.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Account.plugin) | Merge and share [TestFlight](https://apps.apple.com/app/id899247664) accounts | Plugin |
+| [Loon_Bahamut_ADS.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_Bahamut_ADS.plugin) | Remove [Bahamut anime](https://apps.apple.com/tw/app/id1102650114) Ads | Plugin |
+| [Loon_IPA_Installer.plugin](https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_IPA_Installer.plugin) | Use Loon to assist in install IPA (signed version) | Plugin |
---
diff --git a/Surge/JS/CamScanner.js b/Surge/JS/CamScanner.js
index a88c128b62..ac5deddef1 100644
--- a/Surge/JS/CamScanner.js
+++ b/Surge/JS/CamScanner.js
@@ -30,5 +30,5 @@ hostname = ap*.intsig.net
**************************/
let obj = JSON.parse($response.body);
-obj = {"data":{"psnl_vip_property":{"expiry":"1687017600"}}};
+obj = {"data":{"psnl_vip_property":{"expiry":"2013017600"}}};
$done({body: JSON.stringify(obj)});
\ No newline at end of file
diff --git a/Surge/JS/PicsArt.js b/Surge/JS/PicsArt.js
index 41ec9da898..9591e496ea 100644
--- a/Surge/JS/PicsArt.js
+++ b/Surge/JS/PicsArt.js
@@ -1,11 +1,12 @@
/*
PicsArt 解锁高级功能
+数据来自 @chxm1023
***************************
QuantumultX:
[rewrite_local]
-^https:\/\/api\.(picsart|meiease)\.c(n|om)\/users\/show\/me\.json url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js
+^https:\/\/api\.(picsart|meiease)\.c(n|om)\/shop\/subscription\/(validate|apple\/purchases) url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js
[mitm]
hostname = api.picsart.c*, api.meiease.c*
@@ -14,13 +15,48 @@ hostname = api.picsart.c*, api.meiease.c*
Surge4 or Loon:
[Script]
-http-response https:\/\/api\.(picsart|meiease)\.c(n|om)\/users\/show\/me\.json requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js
+http-response ^https:\/\/api\.(picsart|meiease)\.c(n|om)\/shop\/subscription\/(validate|apple\/purchases) requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/PicsArt.js
[MITM]
hostname = api.picsart.c*, api.meiease.c*
**************************/
-let obj = JSON.parse($response.body);
-obj.subscription.granted = "true";
-$done({body: JSON.stringify(obj)});
\ No newline at end of file
+$done({
+ body: JSON.stringify({
+ "status": "success",
+ "response": [
+ {
+ "status": "SUBSCRIPTION_PURCHASED",
+ "order_id": "490001314520000",
+ "original_order_id": "490001314520000",
+ "is_trial": true,
+ "plan_meta": {
+ "storage_limit_in_mb": 20480,
+ "frequency": "yearly",
+ "scope_id": "full",
+ "id": "com.picsart.editor.subscription_yearly",
+ "product_id": "subscription_yearly",
+ "level": 2000,
+ "auto_renew_product_id": "com.picsart.editor.subscription_yearly",
+ "type": "renewable",
+ "tier_id": "gold_old",
+ "permissions": [
+ "premium_tools_standard",
+ "premium_tools_ai"
+ ],
+ "description": "china"
+ },
+ "limitation": {
+ "max_count": 5,
+ "limits_exceeded": false
+ },
+ "reason": "ok",
+ "subscription_id": "com.picsart.editor.subscription_yearly",
+ "is_eligible_for_introductory": false,
+ "purchase_date": 1687020148000,
+ "expire_date": 4092599349000
+ }
+ ]
+ })
+});
\ No newline at end of file
diff --git a/Surge/JS/Polarr.js b/Surge/JS/Polarr.js
index 7b6a1e9ecd..db6bdac0bd 100644
--- a/Surge/JS/Polarr.js
+++ b/Surge/JS/Polarr.js
@@ -1,11 +1,11 @@
/*
-Polarr泼辣修图 解锁特权 (需恢复购买)
+Polarr泼辣修图 解锁特权 (需登陆)
***************************
QuantumultX:
[rewrite_local]
-^https:\/\/api\.polaxiong\.com\/v1\/payments\/appleiap\/receipts\/confirmation url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js
+^https:\/\/api\.polaxiong\.com\/v1\/payments\/(appleiap\/receipts\/confirmation|profiles\/@me\/subscription) url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js
[mitm]
hostname = api.polaxiong.com
@@ -14,27 +14,42 @@ hostname = api.polaxiong.com
Surge4 or Loon:
[Script]
-http-response ^https:\/\/api\.polaxiong\.com\/v1\/payments\/appleiap\/receipts\/confirmation requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js
+http-response ^https:\/\/api\.polaxiong\.com\/v1\/payments\/(appleiap\/receipts\/confirmation|profiles\/@me\/subscription) requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Polarr.js
[MITM]
hostname = api.polaxiong.com
**************************/
-const sta = typeof $task !== "undefined" ? "HTTP/1.1 200 OK" : 200;
-const res = $response;
-const req = $request;
-
-if (res.body && req.method == "PUT") {
- $done({
- body: JSON.stringify({
- "app": "PPE",
- "isUnlimited": true,
- "membershipExpiryDate": "2028-06-06T08:00:00.000Z"
- }),
- status: sta,
- headers: res.headers
+const statusCode = typeof $task !== "undefined" ? "HTTP/1.1 200 OK" : 200;
+const response = { status: statusCode, headers: $response.headers };
+
+if ($response.body && $request.url.includes("v1/payments/profiles/@me/subscription")) {
+ response.body = JSON.stringify({
+ "isSubscribed": true,
+ "planId": "co.polarr.ppe.premium.studio.yearly",
+ "subscriptionProduct": "yearly",
+ "isTrial": false,
+ "app": "PPE",
+ "isUnlimited": true,
+ "expiryDate": "2053-08-17T19:38:37.000Z",
+ "planType": "yearly",
+ "planTier": "studio",
+ "startDate": "2023-08-17T19:38:37.000Z",
+ "subscriptionTier": "studio",
+ "paymentChannel": "AppleIapSubscription",
+ "membershipExpiryDate": "2053-08-17T19:38:37.000Z"
});
-} else {
- $done({});
}
+
+if ($response.body && $request.url.includes("v1/payments/appleiap/receipts/confirmation")) {
+ response.body = JSON.stringify({
+ "app": "PPE",
+ "planType": "yearly",
+ "planTier": "studio",
+ "isUnlimited": true,
+ "membershipExpiryDate": "2053-08-17T19:38:37.000Z"
+ });
+}
+
+$done(response)
\ No newline at end of file
diff --git a/Surge/JS/vivavideo.js b/Surge/JS/vivavideo.js
index 470f13cbb5..cf26b3adb4 100644
--- a/Surge/JS/vivavideo.js
+++ b/Surge/JS/vivavideo.js
@@ -5,19 +5,19 @@
QuantumultX:
[rewrite_local]
-^https:\/\/(xy-viva\.kakalili|api-chn.rthdo)\.com\/api\/rest\/u\/vipVerifyReceipt url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js
+^https:\/\/api-use\.intsvs\.com\/api\/rest\/u\/vipVerifyReceipt url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js
[mitm]
-hostname = xy-viva.kakalili.com, api-chn.rthdo.com
+hostname = api-use.intsvs.com
***************************
Surge4 or Loon:
[Script]
-http-response ^https:\/\/(xy-viva\.kakalili|api-chn.rthdo)\.com\/api\/rest\/u\/vipVerifyReceipt requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js
+http-response ^https:\/\/api-use\.intsvs\.com\/api\/rest\/u\/vipVerifyReceipt requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/vivavideo.js
[MITM]
-hostname = xy-viva.kakalili.com, api-chn.rthdo.com
+hostname = api-use.intsvs.com
**************************/
From a20ef858ed90344eacb67109561f7a728b9dc49d Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 25 Aug 2023 00:09:47 +0800
Subject: [PATCH 067/105] Add iOS14 shortcut.
---
IPA-Installer/IPA-Installer.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/IPA-Installer/IPA-Installer.js b/IPA-Installer/IPA-Installer.js
index 6e166ac538..0592bed685 100644
--- a/IPA-Installer/IPA-Installer.js
+++ b/IPA-Installer/IPA-Installer.js
@@ -8,7 +8,7 @@
* 导入IPA文件至Shu -> Shu长按IPA文件 -> 导出文件 -> WiFi传输 -> 本机 -> 系统共享 -> 分享至IPA-Installer快捷指令
*
* 快捷指令 + JSBox/Pythonista配合安装:
- * IPA文件长按分享至IPA-Installer快捷指令,完成后再分享至Jsbox/pythonista分享扩展.
+ * IPA文件长按分享至IPA-Installer快捷指令(iOS14跳过),完成后再分享至Jsbox/pythonista分享扩展.
*
*
* QuanX重写: https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/IPA-Installer.snippet
@@ -19,7 +19,9 @@
*
* Stash覆写: https://raw.githubusercontent.com/NobyDa/Script/master/Stash/IPA-Installer.stoverride
*
- * 快捷指令: https://www.icloud.com/shortcuts/d8b2b49ae05141f892e6122c9084c67a
+ * 快捷指令(iOS15+): https://www.icloud.com/shortcuts/4a121aa54cae4619a952baa29e044e30
+ *
+ * 快捷指令(iOS14): https://www.icloud.com/shortcuts/179dfcd7505e44f89207086d2b1a32ea
*
* JSBox脚本: https://xteko.com/redir?url=https%3A%2F%2Fraw.githubusercontent.com%2FNobyDa%2FScript%2Fmaster%2FIPA-Installer%2FIPA-Installer-JSBox.js&name=IPA%20Installer%20%28NobyDa%29
*
From ae4c12f23de8078e02c373c9969b19af28257fcb Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Tue, 29 Aug 2023 00:42:14 +0800
Subject: [PATCH 068/105] Re add surge new bing module.
---
Surge/Module/NewBing.sgmodule | 8 ++++++++
1 file changed, 8 insertions(+)
create mode 100644 Surge/Module/NewBing.sgmodule
diff --git a/Surge/Module/NewBing.sgmodule b/Surge/Module/NewBing.sgmodule
new file mode 100644
index 0000000000..b35ccdd1b4
--- /dev/null
+++ b/Surge/Module/NewBing.sgmodule
@@ -0,0 +1,8 @@
+#!name=New Bing for other browsers
+#!desc=Unlock browser restrictions for new bing AI search.
+
+[Header Rewrite]
+^https:\/\/www\.bing\.com\/(search|new) header-replace-regex User-Agent ^\w+\/[0-9\.\s]+\((\w+);.+ "Mozilla/5.0 ($1; Intel Mac OS X 10_12_6) AppleWebKit/537.36 Chrome/110.0 Safari/537.36 Edg/110.0"
+
+[MITM]
+hostname = %APPEND% www.bing.com
\ No newline at end of file
From cc13ac8aac7c931fa261627bd3200846f02ba479 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 23 Dec 2023 21:27:08 +0800
Subject: [PATCH 069/105] Fix rule list.
---
QuantumultX/AdRule.list | 3 +--
Surge/AdRule.list | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/QuantumultX/AdRule.list b/QuantumultX/AdRule.list
index be16c740db..f077f195cb 100644
--- a/QuantumultX/AdRule.list
+++ b/QuantumultX/AdRule.list
@@ -1,4 +1,4 @@
-# Update > 2023/04/28
+# Update > 2023/12/23
DOMAIN-SUFFIX,api-access.pangolin-sdk-toutiao-b.com,REJECT
DOMAIN-SUFFIX,apoll.m.taobao.com,REJECT
DOMAIN-SUFFIX,comet.yahoo.com,REJECT
@@ -166,7 +166,6 @@ DOMAIN-SUFFIX,ad.video.51togic.com,REJECT
DOMAIN-SUFFIX,biz5.kankan.com,REJECT
DOMAIN-SUFFIX,c.algovid.com,REJECT
DOMAIN-SUFFIX,cms.laifeng.com,REJECT
-DOMAIN-SUFFIX,da.mmarket.com,REJECT
DOMAIN-SUFFIX,dotcounter.douyutv.com,REJECT
DOMAIN-SUFFIX,g.uusee.com,REJECT
DOMAIN-SUFFIX,gcdn.2mdn.net,REJECT
diff --git a/Surge/AdRule.list b/Surge/AdRule.list
index de09430cd2..4f404985a6 100644
--- a/Surge/AdRule.list
+++ b/Surge/AdRule.list
@@ -1,4 +1,4 @@
-# Update > 2023/04/28
+# Update > 2023/12/23
DOMAIN-SUFFIX,api-access.pangolin-sdk-toutiao-b.com
DOMAIN-SUFFIX,mcupdate.gstarcad.com
DOMAIN-SUFFIX,adx.open-adx.com
@@ -178,7 +178,6 @@ DOMAIN-SUFFIX,ad.video.51togic.com
DOMAIN-SUFFIX,biz5.kankan.com
DOMAIN-SUFFIX,c.algovid.com
DOMAIN-SUFFIX,cms.laifeng.com
-DOMAIN-SUFFIX,da.mmarket.com
DOMAIN-SUFFIX,dotcounter.douyutv.com
DOMAIN-SUFFIX,g.uusee.com
DOMAIN-SUFFIX,gcdn.2mdn.net
From 4bb08662ccc4173027fdca80a3da47032beeaf01 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 22 Feb 2024 21:55:59 +0800
Subject: [PATCH 070/105] Minor improvements.
---
Loon/Loon_TF_Account.plugin | 2 +-
Surge/Module/TestFlightAccount.sgmodule | 2 +-
TestFlight/TestFlightAccount.js | 4 +++-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/Loon/Loon_TF_Account.plugin b/Loon/Loon_TF_Account.plugin
index 7482b3101f..7f1aca81f0 100644
--- a/Loon/Loon_TF_Account.plugin
+++ b/Loon/Loon_TF_Account.plugin
@@ -8,7 +8,7 @@
skip-proxy = iosapps.itunes.apple.com
[Script]
-http-request ^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/ requires-body=1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js,tag=TestFlight账户管理
+http-request ^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/ requires-body=1,timeout=120,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js,tag=TestFlight账户管理
[MITM]
hostname = testflight.apple.com
\ No newline at end of file
diff --git a/Surge/Module/TestFlightAccount.sgmodule b/Surge/Module/TestFlightAccount.sgmodule
index 8822e7c46f..40bb032648 100644
--- a/Surge/Module/TestFlightAccount.sgmodule
+++ b/Surge/Module/TestFlightAccount.sgmodule
@@ -5,7 +5,7 @@
skip-proxy = %APPEND% iosapps.itunes.apple.com
[Script]
-TestFlight账户管理 = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/,requires-body=1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js
+TestFlight账户管理 = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/,requires-body=1,timeout=120,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js
[MITM]
hostname = %APPEND% testflight.apple.com
\ No newline at end of file
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 6c47d4018e..1dc7085fba 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -60,7 +60,8 @@ runs()
status: 200,
headers: {
'Content-Type': 'application/json'
- }
+ },
+ body: '{}'
},
...rsp
};
@@ -133,6 +134,7 @@ function formatHeaders(h) {
function ChangeHeaders(id) {
const re = JSON.parse(JSON.stringify(req)); //easy deep copy
+ re.timeout = $.env.isLoon ? 30 * 1000 : 30;
if (id) {
$.log(`Request header replaced, using "${id}"`);
re.headers[k1] = list[id][k1];
From 952ba7689fc74c75c82c6cb514b5b2f530831821 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 23 Feb 2024 05:34:17 +0800
Subject: [PATCH 071/105] Minor improvements.
---
TestFlight/TestFlightAccount.js | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 1dc7085fba..2cd05a0fa1 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -3,6 +3,7 @@ TestFlight账户管理脚本
脚本作者: @NobyDa
脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
+更新时间: 2024/02/23
主要功能:
1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
@@ -134,7 +135,7 @@ function formatHeaders(h) {
function ChangeHeaders(id) {
const re = JSON.parse(JSON.stringify(req)); //easy deep copy
- re.timeout = $.env.isLoon ? 30 * 1000 : 30;
+ re.timeout = 30;
if (id) {
$.log(`Request header replaced, using "${id}"`);
re.headers[k1] = list[id][k1];
@@ -142,7 +143,7 @@ function ChangeHeaders(id) {
re.headers[k3] = list[id][k3];
re.url = re.url.replace(/\/[a-z0-9-]{36}\//, `/${id}/`);
}
- if (typeof $Shadowrocket !== 'undefined') {
+ if ($.env.isShadowrocket) {
re.proxy = false; //prevent shadowrocket infinite loop
}
delete re.headers['if-none-match']; //prevent 304
@@ -288,4 +289,4 @@ function letterDecode(e) {
}
// https://github.com/Peng-YM/QuanX/tree/master/Tools/OpenAPI
-function ENV() { const e = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !e, isJSBox: e, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP(e = { baseURL: "" }) { const { isQX: t, isLoon: s, isSurge: o, isScriptable: n, isNode: i, isBrowser: r } = ENV(), u = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; const a = {}; return ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(h => a[h.toLowerCase()] = (a => (function (a, h) { h = "string" == typeof h ? { url: h } : h; const d = e.baseURL; d && !u.test(h.url || "") && (h.url = d ? d + h.url : h.url), h.body && h.headers; const l = (h = { ...e, ...h }).timeout, c = { onRequest: () => { }, onResponse: e => e, onTimeout: () => { }, ...h.events }; let f, p; if (c.onRequest(a, h), t) f = $task.fetch({ method: a, ...h }); else if (s || o || i) f = new Promise((e, t) => { (i ? require("request") : $httpClient)[a.toLowerCase()](h, (s, o, n) => { s ? t(s) : e({ statusCode: o.status || o.statusCode, headers: o.headers, body: n }) }) }); else if (n) { const e = new Request(h.url); e.method = a, e.headers = h.headers, e.body = h.body, f = new Promise((t, s) => { e.loadString().then(s => { t({ statusCode: e.response.statusCode, headers: e.response.headers, body: s }) }).catch(e => s(e)) }) } else r && (f = new Promise((e, t) => { fetch(h.url, { method: a, headers: h.headers, body: h.body }).then(e => e.json()).then(t => e({ statusCode: t.status, headers: t.headers, body: t.data })).catch(t) })); const y = l ? new Promise((e, t) => { p = setTimeout(() => (c.onTimeout(), t(`${a} URL: ${h.url} exceeds the timeout ${l} ms`)), l) }) : null; return (y ? Promise.race([y, f]).then(e => (clearTimeout(p), e)) : f).then(e => c.onResponse(e)) })(h, a))), a } function API(e = "untitled", t = !1) { const { isQX: s, isLoon: o, isSurge: n, isNode: i, isJSBox: r, isScriptable: u } = ENV(); return new class { constructor(e, t) { this.name = e, this.debug = t, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (i) { return { fs: require("fs") } } return null })(), this.initCache(); Promise.prototype.delay = function (e) { return this.then(function (t) { return ((e, t) => new Promise(function (s) { setTimeout(s.bind(null, t), e) }))(e, t) }) } } initCache() { if (s && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (o || n) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), i) { let e = "root.json"; this.node.fs.existsSync(e) || this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.root = {}, e = `${this.name}.json`, this.node.fs.existsSync(e) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.cache = {}) } } persistCache() { const e = JSON.stringify(this.cache, null, 2); s && $prefs.setValueForKey(e, this.name), (o || n) && $persistentStore.write(e, this.name), i && (this.node.fs.writeFileSync(`${this.name}.json`, e, { flag: "w" }, e => console.log(e)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, e => console.log(e))) } write(e, t) { if (this.log(`SET ${t}`), -1 !== t.indexOf("#")) { if (t = t.substr(1), n || o) return $persistentStore.write(e, t); if (s) return $prefs.setValueForKey(e, t); i && (this.root[t] = e) } else this.cache[t] = e; this.persistCache() } read(e) { return this.log(`READ ${e}`), -1 === e.indexOf("#") ? this.cache[e] : (e = e.substr(1), n || o ? $persistentStore.read(e) : s ? $prefs.valueForKey(e) : i ? this.root[e] : void 0) } delete(e) { if (this.log(`DELETE ${e}`), -1 !== e.indexOf("#")) { if (e = e.substr(1), n || o) return $persistentStore.write(null, e); if (s) return $prefs.removeValueForKey(e); i && delete this.root[e] } else delete this.cache[e]; this.persistCache() } notify(e, t = "", a = "", h = {}) { const d = h["open-url"], l = h["media-url"]; if (s && $notify(e, t, a, h), n && $notification.post(e, t, a + `${l ? "\n多媒体:" + l : ""}`, { url: d }), o) { let s = {}; d && (s.openUrl = d), l && (s.mediaUrl = l), "{}" === JSON.stringify(s) ? $notification.post(e, t, a) : $notification.post(e, t, a, s) } if (i || u) { const s = a + (d ? `\n点击跳转: ${d}` : "") + (l ? `\n多媒体: ${l}` : ""); if (r) { require("push").schedule({ title: e, body: (t ? t + "\n" : "") + s }) } else console.log(`${e}\n${t}\n${s}\n\n`) } } log(e) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(e)}`) } info(e) { console.log(`[${this.name}] INFO: ${this.stringify(e)}`) } error(e) { console.log(`[${this.name}] ERROR: ${this.stringify(e)}`) } wait(e) { return new Promise(t => setTimeout(t, e)) } done(e = {}) { s || o || n ? $done(e) : i && !r && "undefined" != typeof $context && ($context.headers = e.headers, $context.statusCode = e.statusCode, $context.body = e.body) } stringify(e) { if ("string" == typeof e || e instanceof String) return e; try { return JSON.stringify(e, null, 2) } catch (e) { return "[object Object]" } } }(e, t) }
\ No newline at end of file
+function ENV() { const e = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isShadowrocket: "undefined" != typeof $Shadowrocket, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !e, isJSBox: e, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP() { const { isQX: t, isLoon: s, isSurge: o, isScriptable: n, isNode: i, isBrowser: r } = ENV(), u = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; const a = {}; return ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(h => a[h.toLowerCase()] = (a => (function (a, h) { h = "string" == typeof h ? { url: h } : h; h.timeout && s && (h.timeout = h.timeout * 1000); let f, p; if (t) f = $task.fetch({ method: a, ...h }); else if (s || o || i) f = new Promise((e, t) => { (i ? require("request") : $httpClient)[a.toLowerCase()](h, (s, o, n) => { s ? t(s) : e({ statusCode: o.status || o.statusCode, headers: o.headers, body: n }) }) }); else if (n) { const e = new Request(h.url); e.method = a, e.headers = h.headers, e.body = h.body, f = new Promise((t, s) => { e.loadString().then(s => { t({ statusCode: e.response.statusCode, headers: e.response.headers, body: s }) }).catch(e => s(e)) }) } else r && (f = new Promise((e, t) => { fetch(h.url, { method: a, headers: h.headers, body: h.body }).then(e => e.json()).then(t => e({ statusCode: t.status, headers: t.headers, body: t.data })).catch(t) })); return f })(h, a))), a } function API(e = "untitled", t = !1) { const { isQX: s, isLoon: o, isSurge: n, isNode: i, isJSBox: r, isScriptable: u } = ENV(); return new class { constructor(e, t) { this.name = e, this.debug = t, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (i) { return { fs: require("fs") } } return null })(), this.initCache(); Promise.prototype.delay = function (e) { return this.then(function (t) { return ((e, t) => new Promise(function (s) { setTimeout(s.bind(null, t), e) }))(e, t) }) } } initCache() { if (s && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (o || n) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), i) { let e = "root.json"; this.node.fs.existsSync(e) || this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.root = {}, e = `${this.name}.json`, this.node.fs.existsSync(e) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.cache = {}) } } persistCache() { const e = JSON.stringify(this.cache, null, 2); s && $prefs.setValueForKey(e, this.name), (o || n) && $persistentStore.write(e, this.name), i && (this.node.fs.writeFileSync(`${this.name}.json`, e, { flag: "w" }, e => console.log(e)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, e => console.log(e))) } write(e, t) { if (this.log(`SET ${t}`), -1 !== t.indexOf("#")) { if (t = t.substr(1), n || o) return $persistentStore.write(e, t); if (s) return $prefs.setValueForKey(e, t); i && (this.root[t] = e) } else this.cache[t] = e; this.persistCache() } read(e) { return this.log(`READ ${e}`), -1 === e.indexOf("#") ? this.cache[e] : (e = e.substr(1), n || o ? $persistentStore.read(e) : s ? $prefs.valueForKey(e) : i ? this.root[e] : void 0) } delete(e) { if (this.log(`DELETE ${e}`), -1 !== e.indexOf("#")) { if (e = e.substr(1), n || o) return $persistentStore.write(null, e); if (s) return $prefs.removeValueForKey(e); i && delete this.root[e] } else delete this.cache[e]; this.persistCache() } notify(e, t = "", a = "", h = {}) { const d = h["open-url"], l = h["media-url"]; if (s && $notify(e, t, a, h), n && $notification.post(e, t, a + `${l ? "\n多媒体:" + l : ""}`, { url: d }), o) { let s = {}; d && (s.openUrl = d), l && (s.mediaUrl = l), "{}" === JSON.stringify(s) ? $notification.post(e, t, a) : $notification.post(e, t, a, s) } if (i || u) { const s = a + (d ? `\n点击跳转: ${d}` : "") + (l ? `\n多媒体: ${l}` : ""); if (r) { require("push").schedule({ title: e, body: (t ? t + "\n" : "") + s }) } else console.log(`${e}\n${t}\n${s}\n\n`) } } log(e) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(e)}`) } info(e) { console.log(`[${this.name}] INFO: ${this.stringify(e)}`) } error(e) { console.log(`[${this.name}] ERROR: ${this.stringify(e)}`) } wait(e) { return new Promise(t => setTimeout(t, e)) } done(e = {}) { s || o || n ? $done(e) : i && !r && "undefined" != typeof $context && ($context.headers = e.headers, $context.statusCode = e.statusCode, $context.body = e.body) } stringify(e) { if ("string" == typeof e || e instanceof String) return e; try { return JSON.stringify(e, null, 2) } catch (e) { return "[object Object]" } } }(e, t) }
\ No newline at end of file
From bff207400dfdfea9a3eb869498156e58439a997a Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 24 Feb 2024 09:46:43 +0800
Subject: [PATCH 072/105] Add rule storage script.
---
Rule-Storage/Include-Domain.txt | 26 ++++++
Rule-Storage/Rule-Storage.js | 139 ++++++++++++++++++++++++++++++++
2 files changed, 165 insertions(+)
create mode 100644 Rule-Storage/Include-Domain.txt
create mode 100644 Rule-Storage/Rule-Storage.js
diff --git a/Rule-Storage/Include-Domain.txt b/Rule-Storage/Include-Domain.txt
new file mode 100644
index 0000000000..e458138659
--- /dev/null
+++ b/Rule-Storage/Include-Domain.txt
@@ -0,0 +1,26 @@
+DOMAIN-KEYWORD,.a
+DOMAIN-KEYWORD,.b
+DOMAIN-KEYWORD,.c
+DOMAIN-KEYWORD,.d
+DOMAIN-KEYWORD,.e
+DOMAIN-KEYWORD,.f
+DOMAIN-KEYWORD,.g
+DOMAIN-KEYWORD,.h
+DOMAIN-KEYWORD,.i
+DOMAIN-KEYWORD,.j
+DOMAIN-KEYWORD,.k
+DOMAIN-KEYWORD,.l
+DOMAIN-KEYWORD,.m
+DOMAIN-KEYWORD,.n
+DOMAIN-KEYWORD,.o
+DOMAIN-KEYWORD,.p
+DOMAIN-KEYWORD,.q
+DOMAIN-KEYWORD,.r
+DOMAIN-KEYWORD,.s
+DOMAIN-KEYWORD,.t
+DOMAIN-KEYWORD,.u
+DOMAIN-KEYWORD,.v
+DOMAIN-KEYWORD,.w
+DOMAIN-KEYWORD,.x
+DOMAIN-KEYWORD,.y
+DOMAIN-KEYWORD,.z
\ No newline at end of file
diff --git a/Rule-Storage/Rule-Storage.js b/Rule-Storage/Rule-Storage.js
new file mode 100644
index 0000000000..297ed92983
--- /dev/null
+++ b/Rule-Storage/Rule-Storage.js
@@ -0,0 +1,139 @@
+/*
+Surge规则自动生成脚本
+更新时间:2024/02/24
+
+需按照博客内教程配合使用:
+https://nobyda.github.io/2024/02/24/Surge_Rule_Storage
+
+*/
+
+const args = argsList(typeof $argument == "string" && $argument || 'region=debug');
+/*
+When matching whitelist rules, skip generating suffix domain. Three ways to write:
+Domain: example.com
+Domain suffix: .example.com
+Domain keyword: .example.
+*/
+args.whitelist = args.whitelist || `[".mwcname.com", ".akadns.", ".akamai.", ".cloud.", ".cdn.", ".yun."]`;
+args.key = args.key || 'Rule-Storage';
+
+(async () => {
+ const host = $request.hostname.toLowerCase();
+ if (['127.0.0.1', '0.0.0.0'].filter((v) => [...$request.dnsResult.v4Addresses].includes(v)).length) {
+ // DNS poisoning
+ args.matched = false;
+ args.region = 'global';
+ }
+ if (!/\d$|:/.test(host) && host.includes('.')) {
+ const data = JSON.parse($persistentStore.read(args.key) || '{}');
+ const saved_rules = $persistentStore.read(`${args.key}-${args.region}`);
+ if (!evalRules(host, saved_rules)) {
+ data[args.region] = saveDecision(host, data[args.region]);
+ if (data[args.region][host].quantity >= (args.quantity || 10)) {
+ data.eTLD = await eTLD(data.eTLD);
+ const suffix = shortenDomain(host, data.eTLD.public_suffix);
+ const domain = evalRules(host, JSON.parse(args.whitelist)) ? host : suffix;
+ const text = [...formatRules(saved_rules), ...formatRules(domain)].join('\n');
+ delete data[args.region][host];
+ $persistentStore.write(text, `${args.key}-${args.region}`)
+ }
+ }
+ return $persistentStore.write(JSON.stringify(data, null, 2), args.key)
+ }
+})().catch((e) => $notification.post(args.key, ``, e.message || e))
+ .finally(() => $done({ matched: Boolean(args.matched) }));
+
+function saveDecision(host_name, content = {}) {
+ for (const i in content) {
+ if (Date.now() - content[i].update_time > 86400000 * 30) {
+ delete content[i];
+ }
+ }
+ if (content[host_name]) {
+ if (Date.now() - content[host_name].update_time > ((args.interval || 30) * 1000)) {
+ content[host_name].update_time = Date.now();
+ content[host_name].quantity++;
+ }
+ } else {
+ content[host_name] = { update_time: Date.now(), quantity: 1 }
+ }
+ return content
+}
+
+function evalRules(host_name, rule_list) {
+ const host_suffix = host_name.split('.').reverse();
+ rule_list = typeof rule_list == 'object' ? rule_list : formatRules(rule_list, 1);
+ for (const i in rule_list) {
+ if (rule_list[i].startsWith('.') && !rule_list[i].endsWith('.')) {
+ const rule_host_suffix = rule_list[i].split('.').reverse().filter((v) => v);
+ if (rule_host_suffix.filter((v, i) => host_suffix[i] === v).length === rule_host_suffix.length) {
+ return true
+ }
+ } else if (rule_list[i].startsWith('.') && rule_list[i].endsWith('.')) {
+ if (host_name.includes(rule_list[i].slice(1, -1))) {
+ return true
+ }
+ } else if (rule_list[i] === host_name) {
+ return true
+ }
+ }
+ return false
+}
+
+function formatRules(list, type) {
+ return (list || '').replace(/\r|\ |(\/\/|#|;).*/g, '').split('\n').map((v) => {
+ if (v.startsWith('DOMAIN,')) { return type ? v.split(",")[1] : v }
+ if (v.startsWith('DOMAIN-SUFFIX,')) { return type ? `.${v.split(",")[1]}` : v }
+ if (v.startsWith('.')) { return type ? v : `DOMAIN-SUFFIX,${v.slice(1)}` }
+ if (v.includes('.')) { return type ? v : `DOMAIN,${v}` }
+ }).filter((v) => v);
+}
+
+async function eTLD(content = {}) {
+ if (!content.update_time || (Date.now() - content.update_time > 86400000 * 30)) {
+ await new Promise(resolve => {
+ $httpClient.get({
+ url: 'https://publicsuffix.org/list/public_suffix_list.dat'
+ }, (error, resp, body) => {
+ if (resp.status == 200 && !error && body) {
+ content.update_time = Date.now();
+ content.public_suffix = body.replace(/\r|.*(\/\/|#|;).*|\n(\!|\*\.)/g, '\n').split('\n').filter((t) => t);
+ resolve()
+ } else if (content.update_time) {
+ console.log(`Update eTLD list failed: ${error}`);
+ resolve()
+ } else {
+ throw new Error(`Download eTLD list failed: ${error}`)
+ }
+ })
+ })
+ }
+ return content
+}
+
+/*
+Shorten multi level domain: non-eTLD, full eTLD, second level domain will return original
+Basic logic: www.abc.com -> .abc.com
+*/
+function shortenDomain(host_name, eTLD_list) {
+ return host_name.split('.').reverse().reduce((t, v, i, c) => {
+ if (t === host_name || c.length == 2) { return host_name }
+ if (t.startsWith('.')) { return t }
+ const host_suffix = v + (t && `.${t}` || '');
+ for (const ix in eTLD_list) {
+ if (eTLD_list[ix] === host_suffix) {
+ return host_suffix
+ }
+ }
+ return !i && host_name || `.${host_suffix}`
+ }, '')
+}
+
+function argsList(data) {
+ return Array.from(
+ data.split("&")
+ .map((i) => i.split("="))
+ .map(([k, v]) => [k, decodeURIComponent(v)])
+ )
+ .reduce((a, [k, v]) => Object.assign(a, { [k]: v }), {})
+}
\ No newline at end of file
From 7771161f058529caf70524820ba666b29042af27 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 26 Feb 2024 18:10:47 +0800
Subject: [PATCH 073/105] Bug fixes.
---
TestFlight/TestFlightAccount.js | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 2cd05a0fa1..7385059c69 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -61,11 +61,11 @@ runs()
status: 200,
headers: {
'Content-Type': 'application/json'
- },
- body: '{}'
+ }
},
...rsp
};
+ ret.body = ret.body || '{}';
ret.headers = formatHeaders(ret.headers); //compatible with HTTP/2
ret.status = $.env.isQX ? `HTTP/1.1 ${ret.status}` : ret.status;
delete ret.headers['content-length'];
@@ -136,6 +136,7 @@ function formatHeaders(h) {
function ChangeHeaders(id) {
const re = JSON.parse(JSON.stringify(req)); //easy deep copy
re.timeout = 30;
+ re.insecure = true;
if (id) {
$.log(`Request header replaced, using "${id}"`);
re.headers[k1] = list[id][k1];
From a5e6b059e3a1f28bc80c5982b8769224faaa5cf4 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 18 Mar 2024 19:42:17 +0800
Subject: [PATCH 074/105] bug fixes.
---
Bilibili-DailyBonus/Manga.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Bilibili-DailyBonus/Manga.js b/Bilibili-DailyBonus/Manga.js
index a779b14e69..0384d28099 100644
--- a/Bilibili-DailyBonus/Manga.js
+++ b/Bilibili-DailyBonus/Manga.js
@@ -1,10 +1,10 @@
/*
哔哩哔哩漫画签到
-脚本兼容: QuantumultX, Surge, Loon
+脚本兼容:QuantumultX, Surge, Loon
电报频道:@NobyDa
问题反馈:@NobyDa_bot
-更新日期:04/04/2023
+更新日期:2024/03/18
如果转载,请注明出处
说明:
@@ -64,11 +64,11 @@ function checkin() {
$.post(bilibili, async function (error, response, data) {
if (error && !data) {
$.msgBody = `请求失败!\n${error}`;
- } else if (parseInt(response.status) == 200) {
+ } else if (data.includes(`"code":0`)) {
$.msgBody = "签到成功!🎉";
- } else if (/duplicate/.test(data)) {
+ } else if (data.includes(`"code":1`)) {
$.msgBody = "签到失败,今日已签过 ⚠️";
- } else if (/uid must/.test(data)) {
+ } else if (data.includes(`"invalid_argument"`)) {
$.msgBody = "签到失败,Cookie失效(已清除) ⚠️";
$.setdata("", "CookieBM");
} else {
From 6cac08acaab8659deb04bc2580aa1581200f301a Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 22 Mar 2024 20:32:40 +0800
Subject: [PATCH 075/105] Add testflight account app list cache
---
NobyDa_BoxJs.json | 13 +++++++
Surge/Module/TestFlightAccount.sgmodule | 4 ++-
TestFlight/TestFlightAccount.js | 46 ++++++++++++++++++-------
3 files changed, 50 insertions(+), 13 deletions(-)
diff --git a/NobyDa_BoxJs.json b/NobyDa_BoxJs.json
index bf7430ac54..5581b969a5 100644
--- a/NobyDa_BoxJs.json
+++ b/NobyDa_BoxJs.json
@@ -449,6 +449,19 @@
"val": false,
"type": "boolean",
"desc": "用于调试脚本, 一般用户请勿开启."
+ }, {
+ "id": "@TESTFLIGHT-ACCOUNT.EnableCache",
+ "name": "启用缓存",
+ "val": false,
+ "type": "boolean",
+ "desc": "用于缓存APP列表, 改善列表页面加载过慢,需与\"请求超时\"配合使用。开启缓存并刷新列表后,可适当调小超时"
+ }, {
+ "id": "@TESTFLIGHT-ACCOUNT.Timeout",
+ "name": "请求超时",
+ "val":"",
+ "type": "number",
+ "placeholder": "30",
+ "desc": "默认为30, 单位: 秒"
}],
"author": "@NobyDa",
"repo": "https://github.com/NobyDa/Script/blob/master/TestFlight/TestFlightAccount.js",
diff --git a/Surge/Module/TestFlightAccount.sgmodule b/Surge/Module/TestFlightAccount.sgmodule
index 40bb032648..60e4671cdd 100644
--- a/Surge/Module/TestFlightAccount.sgmodule
+++ b/Surge/Module/TestFlightAccount.sgmodule
@@ -1,11 +1,13 @@
#!name=TestFlight账户管理
#!desc=自动存储/合并多个TestFlight账户列表, 并可导出/分享TestFlight APP.
+#!arguments=请求超时:30,列表缓存:0
+#!arguments-desc=请求超时:单位秒\n列表缓存:1/0,分别为开启/关闭
[General]
skip-proxy = %APPEND% iosapps.itunes.apple.com
[Script]
-TestFlight账户管理 = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/,requires-body=1,timeout=120,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js
+TestFlight账户管理 = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/,requires-body=1,timeout=180,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js, argument="timeout={{{请求超时}}}&enableCache={{{列表缓存}}}"
[MITM]
hostname = %APPEND% testflight.apple.com
\ No newline at end of file
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 7385059c69..c6f20eeb53 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -3,7 +3,7 @@ TestFlight账户管理脚本
脚本作者: @NobyDa
脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
-更新时间: 2024/02/23
+更新时间: 2024/03/22
主要功能:
1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
@@ -47,11 +47,13 @@ https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Account.plug
*********************************/
const $ = API("TESTFLIGHT-ACCOUNT");
+const args = formatArgument(typeof $argument == "string" && $argument || '');
$.env.isNode ? $request = $.read('Request') : null;
const [arr, obj, req, rsp] = [[], new Map(), $request, {}];
const [k1, k2, k3] = ['x-session-id', 'x-request-id', 'x-session-digest'];
const [list, appList] = [$.read('AccountList') || {}, $.read('AppList') || {}];
$.debug = $.read('Debug') === 'true';
+$.EnableCache = Number(args.enableCache) || ($.read('EnableCache') === 'true')
runs()
.catch(e => $.error(e.error || e.message || e))
@@ -133,9 +135,13 @@ function formatHeaders(h) {
return Object.keys(h).reduce((t, i) => (t[i.toLowerCase()] = h[i], t), {})
}
+function formatArgument(s) {
+ return Object.fromEntries(s.split('&').map(item => item.split('=')))
+}
+
function ChangeHeaders(id) {
const re = JSON.parse(JSON.stringify(req)); //easy deep copy
- re.timeout = 30;
+ re.timeout = Number(args.timeout || $.read('Timeout')) || 30;
re.insecure = true;
if (id) {
$.log(`Request header replaced, using "${id}"`);
@@ -168,22 +174,26 @@ function QueryFallback(o) {
}
function QueryAppList(o) {
+ const resp = {};
return $.http[req.method.toLowerCase()](ChangeHeaders(o))
.then(r => {
- const m = req.url.includes(o);
- $.log(`Received response: status=${r.statusCode}, body=${Boolean(r.body)}, account=${o}, main=${m}`);
- if (m) {
+ resp.data = r.body;
+ resp.main = req.url.includes(o);
+ $.log(`Received response: status=${r.statusCode}, body=${Boolean(r.body)}, account=${o}, main=${resp.main}`);
+ if (resp.main) {
[rsp.status, rsp.headers, rsp.body] = [r.statusCode, r.headers, r.body];
}
if (r.statusCode == 401) {
throw new Error('Key expires');
}
- const res = JSON.parse(r.body || '{}');
- $.log(`Account "${o}" app list: ${$.stringify((res.data || []).map(i => i.name))}`);
- return (res.data || []).filter(i => (i.aid = o, !list[o].only || list[o].only.includes(String(i.appAdamId))))
- .map(p => arr[m ? 'unshift' : 'push'](p))
- }).catch(e => { //surge cannot get 401 in apple domain
- if (/Key expires|NSURLErrorDomain.+?-1012/.test(e.error || e.message || e)) {
+ if ($.EnableCache && r.body.startsWith('{')) {
+ const cacheList = JSON.parse($.read('#TESTFLIGHT-ACCOUNT-CACHE') || '{}');
+ cacheList[o] = r.body;
+ $.write(cacheList, '#TESTFLIGHT-ACCOUNT-CACHE');
+ $.log(`Account "${o}" write app list to cache`)
+ }
+ }).catch(e => {
+ if ((e.error || e.message || e).includes('Key expires')) {
if (list[o].InvalidKey >= 2) { //prevent misjudgment
delete list[o];
} else {
@@ -194,6 +204,18 @@ function QueryAppList(o) {
$.notify('TestFlight Account', '', `Account ID "${o}" ${e}`);
};
$.error(`Account "${o}" response failed: ${e.error || e.message || e}`);
+ if ($.EnableCache && !(e.error || e.message || e).includes('Key expires')) {
+ resp.data = JSON.parse($.read('#TESTFLIGHT-ACCOUNT-CACHE') || '{}')[o];
+ $.error(`Account "${o}" Try using cache app list. Status: ${Boolean(resp.data)}`);
+ }
+ }).finally(() => {
+ if (resp.data) {
+ const res = JSON.parse(resp.data);
+ $.log(`Account "${o}" app list: ${$.stringify((res.data || []).map(i => i.name))}`);
+ return (res.data || [])
+ .filter(i => (i.aid = o, !list[o].only || list[o].only.includes(String(i.appAdamId))))
+ .map(p => arr[resp.main ? 'unshift' : 'push'](p))
+ }
})
}
@@ -290,4 +312,4 @@ function letterDecode(e) {
}
// https://github.com/Peng-YM/QuanX/tree/master/Tools/OpenAPI
-function ENV() { const e = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isShadowrocket: "undefined" != typeof $Shadowrocket, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !e, isJSBox: e, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP() { const { isQX: t, isLoon: s, isSurge: o, isScriptable: n, isNode: i, isBrowser: r } = ENV(), u = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; const a = {}; return ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(h => a[h.toLowerCase()] = (a => (function (a, h) { h = "string" == typeof h ? { url: h } : h; h.timeout && s && (h.timeout = h.timeout * 1000); let f, p; if (t) f = $task.fetch({ method: a, ...h }); else if (s || o || i) f = new Promise((e, t) => { (i ? require("request") : $httpClient)[a.toLowerCase()](h, (s, o, n) => { s ? t(s) : e({ statusCode: o.status || o.statusCode, headers: o.headers, body: n }) }) }); else if (n) { const e = new Request(h.url); e.method = a, e.headers = h.headers, e.body = h.body, f = new Promise((t, s) => { e.loadString().then(s => { t({ statusCode: e.response.statusCode, headers: e.response.headers, body: s }) }).catch(e => s(e)) }) } else r && (f = new Promise((e, t) => { fetch(h.url, { method: a, headers: h.headers, body: h.body }).then(e => e.json()).then(t => e({ statusCode: t.status, headers: t.headers, body: t.data })).catch(t) })); return f })(h, a))), a } function API(e = "untitled", t = !1) { const { isQX: s, isLoon: o, isSurge: n, isNode: i, isJSBox: r, isScriptable: u } = ENV(); return new class { constructor(e, t) { this.name = e, this.debug = t, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (i) { return { fs: require("fs") } } return null })(), this.initCache(); Promise.prototype.delay = function (e) { return this.then(function (t) { return ((e, t) => new Promise(function (s) { setTimeout(s.bind(null, t), e) }))(e, t) }) } } initCache() { if (s && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (o || n) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), i) { let e = "root.json"; this.node.fs.existsSync(e) || this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.root = {}, e = `${this.name}.json`, this.node.fs.existsSync(e) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, e => console.log(e)), this.cache = {}) } } persistCache() { const e = JSON.stringify(this.cache, null, 2); s && $prefs.setValueForKey(e, this.name), (o || n) && $persistentStore.write(e, this.name), i && (this.node.fs.writeFileSync(`${this.name}.json`, e, { flag: "w" }, e => console.log(e)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, e => console.log(e))) } write(e, t) { if (this.log(`SET ${t}`), -1 !== t.indexOf("#")) { if (t = t.substr(1), n || o) return $persistentStore.write(e, t); if (s) return $prefs.setValueForKey(e, t); i && (this.root[t] = e) } else this.cache[t] = e; this.persistCache() } read(e) { return this.log(`READ ${e}`), -1 === e.indexOf("#") ? this.cache[e] : (e = e.substr(1), n || o ? $persistentStore.read(e) : s ? $prefs.valueForKey(e) : i ? this.root[e] : void 0) } delete(e) { if (this.log(`DELETE ${e}`), -1 !== e.indexOf("#")) { if (e = e.substr(1), n || o) return $persistentStore.write(null, e); if (s) return $prefs.removeValueForKey(e); i && delete this.root[e] } else delete this.cache[e]; this.persistCache() } notify(e, t = "", a = "", h = {}) { const d = h["open-url"], l = h["media-url"]; if (s && $notify(e, t, a, h), n && $notification.post(e, t, a + `${l ? "\n多媒体:" + l : ""}`, { url: d }), o) { let s = {}; d && (s.openUrl = d), l && (s.mediaUrl = l), "{}" === JSON.stringify(s) ? $notification.post(e, t, a) : $notification.post(e, t, a, s) } if (i || u) { const s = a + (d ? `\n点击跳转: ${d}` : "") + (l ? `\n多媒体: ${l}` : ""); if (r) { require("push").schedule({ title: e, body: (t ? t + "\n" : "") + s }) } else console.log(`${e}\n${t}\n${s}\n\n`) } } log(e) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(e)}`) } info(e) { console.log(`[${this.name}] INFO: ${this.stringify(e)}`) } error(e) { console.log(`[${this.name}] ERROR: ${this.stringify(e)}`) } wait(e) { return new Promise(t => setTimeout(t, e)) } done(e = {}) { s || o || n ? $done(e) : i && !r && "undefined" != typeof $context && ($context.headers = e.headers, $context.statusCode = e.statusCode, $context.body = e.body) } stringify(e) { if ("string" == typeof e || e instanceof String) return e; try { return JSON.stringify(e, null, 2) } catch (e) { return "[object Object]" } } }(e, t) }
\ No newline at end of file
+function ENV() { const e = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isShadowrocket: "undefined" != typeof $Shadowrocket, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !e, isJSBox: e, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule, } } function HTTP(e = { baseURL: "" }) { const { isQX: t, isLoon: s, isSurge: o, isScriptable: n, isNode: i, isBrowser: r, } = ENV(), u = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; const a = {}; return (["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach((h) => (a[h.toLowerCase()] = (a) => (function (a, h) { h = "string" == typeof h ? { url: h } : h; const d = e.baseURL; d && !u.test(h.url || "") && (h.url = d ? d + h.url : h.url), h.body && h.headers; h.timeout && s && (h.timeout = h.timeout * 1000); const l = (h = { ...e, ...h }).timeout, c = { onRequest: () => { }, onResponse: (e) => e, onTimeout: () => { }, ...h.events, }; let f, p; if ((c.onRequest(a, h), t)) f = $task.fetch({ method: a, ...h }); else if (s || o || i) f = new Promise((e, t) => { (i ? require("request") : $httpClient)[a.toLowerCase()](h, (s, o, n) => { s ? t(s) : e({ statusCode: o.status || o.statusCode, headers: o.headers, body: n, }) },) }); else if (n) { const e = new Request(h.url); (e.method = a), (e.headers = h.headers), (e.body = h.body), (f = new Promise((t, s) => { e.loadString().then((s) => { t({ statusCode: e.response.statusCode, headers: e.response.headers, body: s, }) }).catch((e) => s(e)) })) } else r && (f = new Promise((e, t) => { fetch(h.url, { method: a, headers: h.headers, body: h.body }).then((e) => e.json()).then((t) => e({ statusCode: t.status, headers: t.headers, body: t.data, }),).catch(t) })); const y = l ? new Promise((e, t) => { p = setTimeout(() => (c.onTimeout(), t(`timeout`)), !s ? l * 1000 : l,) }) : null; return (y ? Promise.race([y, f]).then((e) => (clearTimeout(p), e)) : f).then((e) => c.onResponse(e)) })(h, a)),), a) } function API(e = "untitled", t = !1) { const { isQX: s, isLoon: o, isSurge: n, isNode: i, isJSBox: r, isScriptable: u, } = ENV(); return new (class { constructor(e, t) { (this.name = e), (this.debug = t), (this.http = HTTP()), (this.env = ENV()), (this.node = (() => { if (i) { return { fs: require("fs") } } return null })()), this.initCache(); Promise.prototype.delay = function (e) { return this.then(function (t) { return ((e, t) => new Promise(function (s) { setTimeout(s.bind(null, t), e) }))(e, t) }) } } initCache() { if ((s && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (o || n) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), i)) { let e = "root.json"; this.node.fs.existsSync(e) || this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, (e) => console.log(e),), (this.root = {}), (e = `${this.name}.json`), this.node.fs.existsSync(e) ? (this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`),)) : (this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, (e) => console.log(e),), (this.cache = {})) } } persistCache() { const e = JSON.stringify(this.cache, null, 2); s && $prefs.setValueForKey(e, this.name), (o || n) && $persistentStore.write(e, this.name), i && (this.node.fs.writeFileSync(`${this.name}.json`, e, { flag: "w" }, (e) => console.log(e),), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, (e) => console.log(e),)) } write(e, t) { if ((this.log(`SET ${t}`), -1 !== t.indexOf("#"))) { if (((t = t.substr(1)), n || o)) return $persistentStore.write(e, t); if (s) return $prefs.setValueForKey(e, t); i && (this.root[t] = e) } else this.cache[t] = e; this.persistCache() } read(e) { return (this.log(`READ ${e}`), -1 === e.indexOf("#") ? this.cache[e] : ((e = e.substr(1)), n || o ? $persistentStore.read(e) : s ? $prefs.valueForKey(e) : i ? this.root[e] : void 0)) } delete(e) { if ((this.log(`DELETE ${e}`), -1 !== e.indexOf("#"))) { if (((e = e.substr(1)), n || o)) return $persistentStore.write(null, e); if (s) return $prefs.removeValueForKey(e); i && delete this.root[e] } else delete this.cache[e]; this.persistCache() } notify(e, t = "", a = "", h = {}) { const d = h["open-url"], l = h["media-url"]; if ((s && $notify(e, t, a, h), n && $notification.post(e, t, a + `${l ? "\n多媒体:" + l : ""}`, { url: d, }), o)) { let s = {}; d && (s.openUrl = d), l && (s.mediaUrl = l), "{}" === JSON.stringify(s) ? $notification.post(e, t, a) : $notification.post(e, t, a, s) } if (i || u) { const s = a + (d ? `\n点击跳转:${d}` : "") + (l ? `\n多媒体:${l}` : ""); if (r) { require("push").schedule({ title: e, body: (t ? t + "\n" : "") + s }) } else console.log(`${e}\n${t}\n${s}\n\n`) } } log(e) { this.debug && console.log(`[${this.name}]LOG:${this.stringify(e)}`) } info(e) { console.log(`[${this.name}]INFO:${this.stringify(e)}`) } error(e) { console.log(`[${this.name}]ERROR:${this.stringify(e)}`) } wait(e) { return new Promise((t) => setTimeout(t, e)) } done(e = {}) { s || o || n ? $done(e) : i && !r && "undefined" != typeof $context && (($context.headers = e.headers), ($context.statusCode = e.statusCode), ($context.body = e.body)) } stringify(e) { if ("string" == typeof e || e instanceof String) return e; try { return JSON.stringify(e, null, 2) } catch (e) { return "[object Object]" } } })(e, t) }
\ No newline at end of file
From 273dd80dc63622a7db1207a9f4517d9920f2fd97 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 22 Mar 2024 21:24:10 +0800
Subject: [PATCH 076/105] Bug fixes.
---
TestFlight/TestFlightAccount.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index c6f20eeb53..96e323c899 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -189,7 +189,7 @@ function QueryAppList(o) {
if ($.EnableCache && r.body.startsWith('{')) {
const cacheList = JSON.parse($.read('#TESTFLIGHT-ACCOUNT-CACHE') || '{}');
cacheList[o] = r.body;
- $.write(cacheList, '#TESTFLIGHT-ACCOUNT-CACHE');
+ $.write($.stringify(cacheList), '#TESTFLIGHT-ACCOUNT-CACHE');
$.log(`Account "${o}" write app list to cache`)
}
}).catch(e => {
From aa0784871d0b642925c0b63e2fa540d35d8d268b Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 23 Mar 2024 21:55:03 +0800
Subject: [PATCH 077/105] fix shadowrocket issues.
---
NobyDa_BoxJs.json | 4 ++++
TestFlight/TestFlightAccount.js | 6 +++---
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/NobyDa_BoxJs.json b/NobyDa_BoxJs.json
index 5581b969a5..e471c259cc 100644
--- a/NobyDa_BoxJs.json
+++ b/NobyDa_BoxJs.json
@@ -463,6 +463,10 @@
"placeholder": "30",
"desc": "默认为30, 单位: 秒"
}],
+ "scripts": [{
+ "name": "清除缓存",
+ "script": "https://gist.githubusercontent.com/NobyDa/d025c53d3922657f921b983ce129fc1d/raw/TestFlightAccountRemoveCache.js"
+ }],
"author": "@NobyDa",
"repo": "https://github.com/NobyDa/Script/blob/master/TestFlight/TestFlightAccount.js",
"icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/testflight.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/testflight.png"]
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 96e323c899..98379690dc 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -3,7 +3,7 @@ TestFlight账户管理脚本
脚本作者: @NobyDa
脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
-更新时间: 2024/03/22
+更新时间: 2024/03/23
主要功能:
1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
@@ -53,7 +53,7 @@ const [arr, obj, req, rsp] = [[], new Map(), $request, {}];
const [k1, k2, k3] = ['x-session-id', 'x-request-id', 'x-session-digest'];
const [list, appList] = [$.read('AccountList') || {}, $.read('AppList') || {}];
$.debug = $.read('Debug') === 'true';
-$.EnableCache = Number(args.enableCache) || ($.read('EnableCache') === 'true')
+$.EnableCache = Number(args.enableCache) || ($.read('EnableCache') === 'true');
runs()
.catch(e => $.error(e.error || e.message || e))
@@ -312,4 +312,4 @@ function letterDecode(e) {
}
// https://github.com/Peng-YM/QuanX/tree/master/Tools/OpenAPI
-function ENV() { const e = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isShadowrocket: "undefined" != typeof $Shadowrocket, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !e, isJSBox: e, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule, } } function HTTP(e = { baseURL: "" }) { const { isQX: t, isLoon: s, isSurge: o, isScriptable: n, isNode: i, isBrowser: r, } = ENV(), u = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; const a = {}; return (["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach((h) => (a[h.toLowerCase()] = (a) => (function (a, h) { h = "string" == typeof h ? { url: h } : h; const d = e.baseURL; d && !u.test(h.url || "") && (h.url = d ? d + h.url : h.url), h.body && h.headers; h.timeout && s && (h.timeout = h.timeout * 1000); const l = (h = { ...e, ...h }).timeout, c = { onRequest: () => { }, onResponse: (e) => e, onTimeout: () => { }, ...h.events, }; let f, p; if ((c.onRequest(a, h), t)) f = $task.fetch({ method: a, ...h }); else if (s || o || i) f = new Promise((e, t) => { (i ? require("request") : $httpClient)[a.toLowerCase()](h, (s, o, n) => { s ? t(s) : e({ statusCode: o.status || o.statusCode, headers: o.headers, body: n, }) },) }); else if (n) { const e = new Request(h.url); (e.method = a), (e.headers = h.headers), (e.body = h.body), (f = new Promise((t, s) => { e.loadString().then((s) => { t({ statusCode: e.response.statusCode, headers: e.response.headers, body: s, }) }).catch((e) => s(e)) })) } else r && (f = new Promise((e, t) => { fetch(h.url, { method: a, headers: h.headers, body: h.body }).then((e) => e.json()).then((t) => e({ statusCode: t.status, headers: t.headers, body: t.data, }),).catch(t) })); const y = l ? new Promise((e, t) => { p = setTimeout(() => (c.onTimeout(), t(`timeout`)), !s ? l * 1000 : l,) }) : null; return (y ? Promise.race([y, f]).then((e) => (clearTimeout(p), e)) : f).then((e) => c.onResponse(e)) })(h, a)),), a) } function API(e = "untitled", t = !1) { const { isQX: s, isLoon: o, isSurge: n, isNode: i, isJSBox: r, isScriptable: u, } = ENV(); return new (class { constructor(e, t) { (this.name = e), (this.debug = t), (this.http = HTTP()), (this.env = ENV()), (this.node = (() => { if (i) { return { fs: require("fs") } } return null })()), this.initCache(); Promise.prototype.delay = function (e) { return this.then(function (t) { return ((e, t) => new Promise(function (s) { setTimeout(s.bind(null, t), e) }))(e, t) }) } } initCache() { if ((s && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (o || n) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), i)) { let e = "root.json"; this.node.fs.existsSync(e) || this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, (e) => console.log(e),), (this.root = {}), (e = `${this.name}.json`), this.node.fs.existsSync(e) ? (this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`),)) : (this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, (e) => console.log(e),), (this.cache = {})) } } persistCache() { const e = JSON.stringify(this.cache, null, 2); s && $prefs.setValueForKey(e, this.name), (o || n) && $persistentStore.write(e, this.name), i && (this.node.fs.writeFileSync(`${this.name}.json`, e, { flag: "w" }, (e) => console.log(e),), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, (e) => console.log(e),)) } write(e, t) { if ((this.log(`SET ${t}`), -1 !== t.indexOf("#"))) { if (((t = t.substr(1)), n || o)) return $persistentStore.write(e, t); if (s) return $prefs.setValueForKey(e, t); i && (this.root[t] = e) } else this.cache[t] = e; this.persistCache() } read(e) { return (this.log(`READ ${e}`), -1 === e.indexOf("#") ? this.cache[e] : ((e = e.substr(1)), n || o ? $persistentStore.read(e) : s ? $prefs.valueForKey(e) : i ? this.root[e] : void 0)) } delete(e) { if ((this.log(`DELETE ${e}`), -1 !== e.indexOf("#"))) { if (((e = e.substr(1)), n || o)) return $persistentStore.write(null, e); if (s) return $prefs.removeValueForKey(e); i && delete this.root[e] } else delete this.cache[e]; this.persistCache() } notify(e, t = "", a = "", h = {}) { const d = h["open-url"], l = h["media-url"]; if ((s && $notify(e, t, a, h), n && $notification.post(e, t, a + `${l ? "\n多媒体:" + l : ""}`, { url: d, }), o)) { let s = {}; d && (s.openUrl = d), l && (s.mediaUrl = l), "{}" === JSON.stringify(s) ? $notification.post(e, t, a) : $notification.post(e, t, a, s) } if (i || u) { const s = a + (d ? `\n点击跳转:${d}` : "") + (l ? `\n多媒体:${l}` : ""); if (r) { require("push").schedule({ title: e, body: (t ? t + "\n" : "") + s }) } else console.log(`${e}\n${t}\n${s}\n\n`) } } log(e) { this.debug && console.log(`[${this.name}]LOG:${this.stringify(e)}`) } info(e) { console.log(`[${this.name}]INFO:${this.stringify(e)}`) } error(e) { console.log(`[${this.name}]ERROR:${this.stringify(e)}`) } wait(e) { return new Promise((t) => setTimeout(t, e)) } done(e = {}) { s || o || n ? $done(e) : i && !r && "undefined" != typeof $context && (($context.headers = e.headers), ($context.statusCode = e.statusCode), ($context.body = e.body)) } stringify(e) { if ("string" == typeof e || e instanceof String) return e; try { return JSON.stringify(e, null, 2) } catch (e) { return "[object Object]" } } })(e, t) }
\ No newline at end of file
+function ENV() { const e = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isShadowrocket: "undefined" != typeof $Shadowrocket, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !e, isJSBox: e, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule, } } function HTTP(e = { baseURL: "" }) { const { isQX: t, isLoon: s, isSurge: o, isScriptable: n, isNode: i, isBrowser: r, } = ENV(), u = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; const a = {}; return (["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach((h) => (a[h.toLowerCase()] = (a) => (function (a, h) { h = "string" == typeof h ? { url: h } : h; const d = e.baseURL; d && !u.test(h.url || "") && (h.url = d ? d + h.url : h.url), h.body && h.headers; h.timeout && s && (h.timeout = h.timeout * 1000); const l = (h = { ...e, ...h }).timeout, c = { onRequest: () => { }, onResponse: (e) => e, onTimeout: () => { }, ...h.events, }; let f, p; if ((c.onRequest(a, h), t)) f = $task.fetch({ method: a, ...h }); else if (s || o || i) f = new Promise((e, t) => { (i ? require("request") : $httpClient)[a.toLowerCase()](h, (s, o, n) => { s ? t(s) : e({ statusCode: o.status || o.statusCode, headers: o.headers, body: n, }) },) }); else if (n) { const e = new Request(h.url); (e.method = a), (e.headers = h.headers), (e.body = h.body), (f = new Promise((t, s) => { e.loadString().then((s) => { t({ statusCode: e.response.statusCode, headers: e.response.headers, body: s, }) }).catch((e) => s(e)) })) } else r && (f = new Promise((e, t) => { fetch(h.url, { method: a, headers: h.headers, body: h.body }).then((e) => e.json()).then((t) => e({ statusCode: t.status, headers: t.headers, body: t.data, }),).catch(t) })); const y = l ? new Promise((e, t) => { p = setTimeout(() => (c.onTimeout(), t(`timeout`)), !s ? l * 1000 : l,) }) : null; return (y ? Promise.race([y, f]).then((e) => ((typeof clearTimeout !== 'undefined') && clearTimeout(p), e)) : f).then((e) => c.onResponse(e)) })(h, a)),), a) } function API(e = "untitled", t = !1) { const { isQX: s, isLoon: o, isSurge: n, isNode: i, isJSBox: r, isScriptable: u, } = ENV(); return new (class { constructor(e, t) { (this.name = e), (this.debug = t), (this.http = HTTP()), (this.env = ENV()), (this.node = (() => { if (i) { return { fs: require("fs") } } return null })()), this.initCache(); Promise.prototype.delay = function (e) { return this.then(function (t) { return ((e, t) => new Promise(function (s) { setTimeout(s.bind(null, t), e) }))(e, t) }) } } initCache() { if ((s && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (o || n) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), i)) { let e = "root.json"; this.node.fs.existsSync(e) || this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, (e) => console.log(e),), (this.root = {}), (e = `${this.name}.json`), this.node.fs.existsSync(e) ? (this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`),)) : (this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, (e) => console.log(e),), (this.cache = {})) } } persistCache() { const e = JSON.stringify(this.cache, null, 2); s && $prefs.setValueForKey(e, this.name), (o || n) && $persistentStore.write(e, this.name), i && (this.node.fs.writeFileSync(`${this.name}.json`, e, { flag: "w" }, (e) => console.log(e),), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, (e) => console.log(e),)) } write(e, t) { if ((this.log(`SET ${t}`), -1 !== t.indexOf("#"))) { if (((t = t.substr(1)), n || o)) return $persistentStore.write(e, t); if (s) return $prefs.setValueForKey(e, t); i && (this.root[t] = e) } else this.cache[t] = e; this.persistCache() } read(e) { return (this.log(`READ ${e}`), -1 === e.indexOf("#") ? this.cache[e] : ((e = e.substr(1)), n || o ? $persistentStore.read(e) : s ? $prefs.valueForKey(e) : i ? this.root[e] : void 0)) } delete(e) { if ((this.log(`DELETE ${e}`), -1 !== e.indexOf("#"))) { if (((e = e.substr(1)), n || o)) return $persistentStore.write(null, e); if (s) return $prefs.removeValueForKey(e); i && delete this.root[e] } else delete this.cache[e]; this.persistCache() } notify(e, t = "", a = "", h = {}) { const d = h["open-url"], l = h["media-url"]; if ((s && $notify(e, t, a, h), n && $notification.post(e, t, a + `${l ? "\n多媒体:" + l : ""}`, { url: d, }), o)) { let s = {}; d && (s.openUrl = d), l && (s.mediaUrl = l), "{}" === JSON.stringify(s) ? $notification.post(e, t, a) : $notification.post(e, t, a, s) } if (i || u) { const s = a + (d ? `\n点击跳转:${d}` : "") + (l ? `\n多媒体:${l}` : ""); if (r) { require("push").schedule({ title: e, body: (t ? t + "\n" : "") + s }) } else console.log(`${e}\n${t}\n${s}\n\n`) } } log(e) { this.debug && console.log(`[${this.name}]LOG:${this.stringify(e)}`) } info(e) { console.log(`[${this.name}]INFO:${this.stringify(e)}`) } error(e) { console.log(`[${this.name}]ERROR:${this.stringify(e)}`) } wait(e) { return new Promise((t) => setTimeout(t, e)) } done(e = {}) { s || o || n ? $done(e) : i && !r && "undefined" != typeof $context && (($context.headers = e.headers), ($context.statusCode = e.statusCode), ($context.body = e.body)) } stringify(e) { if ("string" == typeof e || e instanceof String) return e; try { return JSON.stringify(e, null, 2) } catch (e) { return "[object Object]" } } })(e, t) }
\ No newline at end of file
From 8f5f61e1c1d22a8d7c1e52c5966e35f7b45d8b0a Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 25 Mar 2024 14:43:17 +0800
Subject: [PATCH 078/105] add support for mac force ios headers.
---
NobyDa_BoxJs.json | 6 +
Surge/Module/TestFlightAccount.sgmodule | 7 +-
TestFlight/TestFlightAccount.js | 204 +++++++++++-------------
3 files changed, 107 insertions(+), 110 deletions(-)
diff --git a/NobyDa_BoxJs.json b/NobyDa_BoxJs.json
index e471c259cc..43144f3728 100644
--- a/NobyDa_BoxJs.json
+++ b/NobyDa_BoxJs.json
@@ -462,6 +462,12 @@
"type": "number",
"placeholder": "30",
"desc": "默认为30, 单位: 秒"
+ }, {
+ "id": "@TESTFLIGHT-ACCOUNT.ForceIOSlist",
+ "name": "使用iOS应用列表",
+ "val": false,
+ "type": "boolean",
+ "desc": "强制使用iOS应用列表, 用于改善 macOS TestFlight 加载过慢, iOS用户无需开启"
}],
"scripts": [{
"name": "清除缓存",
diff --git a/Surge/Module/TestFlightAccount.sgmodule b/Surge/Module/TestFlightAccount.sgmodule
index 60e4671cdd..2fd2bf911a 100644
--- a/Surge/Module/TestFlightAccount.sgmodule
+++ b/Surge/Module/TestFlightAccount.sgmodule
@@ -1,13 +1,14 @@
#!name=TestFlight账户管理
#!desc=自动存储/合并多个TestFlight账户列表, 并可导出/分享TestFlight APP.
-#!arguments=请求超时:30,列表缓存:0
-#!arguments-desc=请求超时:单位秒\n列表缓存:1/0,分别为开启/关闭
+#!arguments=请求超时:30,列表缓存:0,使用iOS列表:0,调试模式:0
+#!arguments-desc=请求超时:单位:秒\n\n列表缓存:1/0,开启/关闭。用于缓存APP列表,改善列表页面加载过慢。一般与"请求超时"配合使用,开启缓存并刷新列表后,可适当调小超时。\n\n使用iOS列表:1/0,开启/关闭。强制使用iOS应用列表,用于改善 macOS TestFlight 加载过慢。iOS用户无需开启。\n\n调试模式:1/0,开启/关闭。用于调试脚本。
+#!category=🐻 NobyDa
[General]
skip-proxy = %APPEND% iosapps.itunes.apple.com
[Script]
-TestFlight账户管理 = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/,requires-body=1,timeout=180,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js, argument="timeout={{{请求超时}}}&enableCache={{{列表缓存}}}"
+TestFlight账户管理 = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/,requires-body=1,timeout=180,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js,debug={{{调试模式}}},argument="timeout={{{请求超时}}}&enableCache={{{列表缓存}}}&forceIOSlist={{{使用iOS列表}}}&debug={{{调试模式}}}"
[MITM]
hostname = %APPEND% testflight.apple.com
\ No newline at end of file
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 98379690dc..3619a551a0 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -3,12 +3,12 @@ TestFlight账户管理脚本
脚本作者: @NobyDa
脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
-更新时间: 2024/03/23
+更新时间: 2024/03/25
主要功能:
1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
2. 账户内单个测试版APP允许多方共享:
- - 导出:点击测试版APP -> 底部开发者许可协议 -> 复制密钥并分享给对方
+ - 导出:点击测试版APP -> App详情 -> 描述 -> 复制底部密钥并分享给对方
- 导入:TestFlight 右上角"兑换" -> 粘贴密钥 -> 弹出保存成功通知后刷新APP列表
- 多方共享为实验性功能,双方都需要使用该脚本; 该功能主要解决某些APP的TF名额稀缺的问题
@@ -21,7 +21,6 @@ Surge4 添加脚本:
Surge模块地址:
https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TestFlightAccount.sgmodule
-
*********************************
QuantumultX 添加脚本:
*********************************
@@ -49,65 +48,42 @@ https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_TF_Account.plug
const $ = API("TESTFLIGHT-ACCOUNT");
const args = formatArgument(typeof $argument == "string" && $argument || '');
$.env.isNode ? $request = $.read('Request') : null;
-const [arr, obj, req, rsp] = [[], new Map(), $request, {}];
+const [obj, req, rsp] = [new Map(), $request, {}];
const [k1, k2, k3] = ['x-session-id', 'x-request-id', 'x-session-digest'];
const [list, appList] = [$.read('AccountList') || {}, $.read('AppList') || {}];
-$.debug = $.read('Debug') === 'true';
+$.debug = Number(args.debug) || ($.read('Debug') === 'true');
$.EnableCache = Number(args.enableCache) || ($.read('EnableCache') === 'true');
+$.ForceIOSlist = Number(args.forceIOSlist) || ($.read('ForceIOSlist') === 'true');
runs()
+ .then((resp) => {
+ resp = ChangeBody(resp);
+ rsp.body = resp.body || '{}';
+ rsp.headers = formatHeaders(resp.headers || { 'Content-Type': 'application/json' });
+ rsp.status = $.env.isQX ? `HTTP/1.1 ${resp.status || 200}` : resp.status || 200;
+ delete rsp.headers['content-length'];
+ delete rsp.headers['transfer-encoding']; //prevent issues in qx
+ $.log(`Return to client: ${$.stringify(rsp)}`);
+ })
.catch(e => $.error(e.error || e.message || e))
- .finally(() => {
- const ret = {
- ...{
- status: 200,
- headers: {
- 'Content-Type': 'application/json'
- }
- },
- ...rsp
- };
- ret.body = ret.body || '{}';
- ret.headers = formatHeaders(ret.headers); //compatible with HTTP/2
- ret.status = $.env.isQX ? `HTTP/1.1 ${ret.status}` : ret.status;
- delete ret.headers['content-length'];
- delete ret.headers['transfer-encoding']; //prevent issues in qx
- $.log(`Return to client: ${$.stringify(ret)}`);
- $.done($.env.isQX ? ret : {
- response: ret
- })
- });
+ .finally(() => $.done($.env.isQX ? rsp : { response: rsp }));
async function runs() {
// Object.keys(list).map(a => delete list[a].only)
req.headers = formatHeaders(req.headers); //compatible with HTTP/2
const appID = req.url.split(/\/apps\/(\d+)/)[1];
- const build = req.url.split(/\/builds\/(\d+)/)[1];
const other = /\/(accept|withdraw|devices|session|notifications|status)/.test(req.url);
if (/accounts\/[a-z0-9-]{36}\/apps$/.test(req.url)) {
const acc = SaveAccount(req.url.split(/\/([a-z0-9-]{36})\//)[1]);
- const all = await Promise.all(Object.keys(acc).map(QueryAppList));
- const out = arr.filter(r => !r.previouslyTested && !obj.has(r.appAdamId) && obj.set(r.appAdamId, 1));
- $.log(`Final app: ${$.stringify(out.map(i => i.name))}`);
- if (out.length) {
- rsp.body = $.stringify({
- data: out,
- error: null
- });
- $.write(out.reduce((l, v) => (l[v.appAdamId] = v.aid, l), {}), 'AppList');
- }
+ return await Promise.all(Object.keys(acc).map(QueryRequest));
} else if (/\/install$/.test(req.url) && req.body) {
req.body = JSON.parse(req.body);
req.body.storefrontId = '143441-19,29'; //prevent regional restrictions
req.body = $.stringify(req.body);
- } else if (/\d+\/eula$/.test(req.url)) {
- rsp.body = $.stringify(ShareAccount(appID, build));
} else if (/\/[A-Z]{200,}\/redeem$/.test(req.url)) {
- rsp.body = ExternalAccount(req.url.split(/\/([A-Z]+)\/redeem$/)[1]);
- }
- if (!rsp.body) {
- await QueryFallback(!other && appList[appID]);
+ return { body: ExternalAccount(req.url.split(/\/([A-Z]+)\/redeem$/)[1]) };
}
+ return await QueryRequest(!other && appList[appID]);
}
function SaveAccount(id, part, o) {
@@ -141,8 +117,11 @@ function formatArgument(s) {
function ChangeHeaders(id) {
const re = JSON.parse(JSON.stringify(req)); //easy deep copy
- re.timeout = Number(args.timeout || $.read('Timeout')) || 30;
+ re.timeout = (Number(args.timeout || $.read('Timeout')) || 30) * 1000;
re.insecure = true;
+ if ($.ForceIOSlist && req.url.endsWith('/apps') && re.headers['user-agent'].includes('Mac')) {
+ re.headers['user-agent'] = 'Oasis/3.5.1 OasisBuild/425.2 iOS/17.4 model/iPhone16,2 hwp/t8130 build/21E219 (6; dt:311) AMS/1 TSE/0';
+ }
if (id) {
$.log(`Request header replaced, using "${id}"`);
re.headers[k1] = list[id][k1];
@@ -159,63 +138,78 @@ function ChangeHeaders(id) {
return re;
}
-function QueryFallback(o) {
- return $.http[req.method.toLowerCase()](ChangeHeaders(o))
- .then(r => {
- $.log(`Received response: status=${r.statusCode}, body=${Boolean(r.body)}`);
- [rsp.status, rsp.headers, rsp.body] = [r.statusCode, r.headers, r.body];
- if (/\/apps\/\d+\/builds\/\d+$/.test(req.url) && r.body) { //beta app page
- r.body = JSON.parse(r.body);
- r.body.data.builds.map(e => e.eula = `https://testflight.apple.com/v1/apps/${e.appAdamId}/builds/${e.id}/eula`);
- rsp.body = $.stringify(r.body);
+function ChangeBody(resp) {
+ if (req.url.endsWith('/apps')) {
+ const cache = $.EnableCache && JSON.parse($.read('#TESTFLIGHT-ACCOUNT-CACHE') || '{}');
+ resp = resp.map((v) => {
+ v.body = JSON.parse(v.body || '{}');
+ if (v.status == 401) {
+ if (list[v.account].InvalidKey >= 2) { //prevent misjudgment
+ delete list[v.account];
+ } else {
+ list[v.account].InvalidKey = (list[v.account].InvalidKey || 0) + 1;
+ }
+ $.write(list, 'AccountList');
+ $.error(`Account "${v.account}" key expired ⚠️`);
+ $.notify('TestFlight Account', '', `Account ID "${v.account}" key expired ⚠️`);
}
- })
- .catch(e => $.error(`Response failed: ${e.error || e.message || e}`))
+ if ($.EnableCache && v.body.data) {
+ $.log(`Account "${v.account}" write app list to cache`);
+ cache[v.account] = $.stringify(v.body);
+ $.write($.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
+ }
+ if ($.EnableCache && !v.body.data) {
+ v.body = JSON.parse(cache[v.account] || '{}');
+ $.log(`Account "${v.account}" Try using cache app list`);
+ }
+ $.log(`Account "${v.account}" app list: ${$.stringify((v.body.data || []).map(i => i.name))}`);
+ return v
+ }).reduce((t, d) => {
+ d.body.data = (d.body.data || []).map(i => {
+ if ($.ForceIOSlist) {
+ i.platforms = i.platforms.map(j => {
+ if (j.name == 'osx') {
+ $.log(`Account "${d.account}" app [${i.name}] force mac compatible`);
+ j.build.compatible = true;
+ j.build.platformCompatible = true;
+ j.build.osCompatible = true;
+ j.build.hardwareCompatible = true;
+ }
+ return j
+ })
+ }
+ i.aid = d.account;
+ const only = !list[d.account].only || list[d.account].only.includes(String(i.appAdamId));
+ return only && t.body.data[req.url.includes(d.account) ? 'unshift' : 'push'](i), i;
+ });
+ if (req.url.includes(d.account)) {
+ [t.status, t.headers] = [d.statusCode, d.headers];
+ }
+ return t
+ }, { body: { data: [], error: null } });
+ resp.body.data = resp.body.data.filter(r => !r.previouslyTested && !obj.has(r.appAdamId) && obj.set(r.appAdamId, 1));
+ $.write(resp.body.data.reduce((l, v) => (l[v.appAdamId] = v.aid, l), {}), 'AppList');
+ $.log(`Final app: ${$.stringify(resp.body.data.map(i => i.name))}`);
+ resp.body = JSON.stringify(resp.body);
+ }
+ if (/\/apps\/\d+\/builds\/\d+$/.test(req.url) && resp.body) { //beta app page
+ const share = ShareAccount(req.url.split(/\/apps\/(\d+)/)[1]);
+ resp.body = JSON.parse(resp.body);
+ resp.body.data.builds.map(e => e.description = `${e.description || '-'}${share}`);
+ resp.body = JSON.stringify(resp.body);
+ }
+ return resp;
}
-function QueryAppList(o) {
- const resp = {};
+function QueryRequest(o) {
return $.http[req.method.toLowerCase()](ChangeHeaders(o))
.then(r => {
- resp.data = r.body;
- resp.main = req.url.includes(o);
- $.log(`Received response: status=${r.statusCode}, body=${Boolean(r.body)}, account=${o}, main=${resp.main}`);
- if (resp.main) {
- [rsp.status, rsp.headers, rsp.body] = [r.statusCode, r.headers, r.body];
- }
- if (r.statusCode == 401) {
- throw new Error('Key expires');
- }
- if ($.EnableCache && r.body.startsWith('{')) {
- const cacheList = JSON.parse($.read('#TESTFLIGHT-ACCOUNT-CACHE') || '{}');
- cacheList[o] = r.body;
- $.write($.stringify(cacheList), '#TESTFLIGHT-ACCOUNT-CACHE');
- $.log(`Account "${o}" write app list to cache`)
- }
- }).catch(e => {
- if ((e.error || e.message || e).includes('Key expires')) {
- if (list[o].InvalidKey >= 2) { //prevent misjudgment
- delete list[o];
- } else {
- list[o].InvalidKey = (list[o].InvalidKey || 0) + 1;
- }
- $.write(list, 'AccountList');
- e = `key expired ⚠️`;
- $.notify('TestFlight Account', '', `Account ID "${o}" ${e}`);
- };
+ $.log(`Account "${o}" response: status=${r.statusCode}, body=${Boolean(r.body)}`);
+ return { status: r.statusCode, headers: r.headers, body: r.body, account: o }
+ })
+ .catch(e => {
$.error(`Account "${o}" response failed: ${e.error || e.message || e}`);
- if ($.EnableCache && !(e.error || e.message || e).includes('Key expires')) {
- resp.data = JSON.parse($.read('#TESTFLIGHT-ACCOUNT-CACHE') || '{}')[o];
- $.error(`Account "${o}" Try using cache app list. Status: ${Boolean(resp.data)}`);
- }
- }).finally(() => {
- if (resp.data) {
- const res = JSON.parse(resp.data);
- $.log(`Account "${o}" app list: ${$.stringify((res.data || []).map(i => i.name))}`);
- return (res.data || [])
- .filter(i => (i.aid = o, !list[o].only || list[o].only.includes(String(i.appAdamId))))
- .map(p => arr[resp.main ? 'unshift' : 'push'](p))
- }
+ return { error: e, account: o }
})
}
@@ -238,19 +232,21 @@ function ExternalAccount(key) {
return '{}'
}
-function ShareAccount(appID, bid) {
+function ShareAccount(appID) {
const raw = $.stringify({
appID: appID,
accID: appList[appID],
key: list[appList[appID]]
});
const key = letterEncode(raw);
- const disclaimer = `
+ const disclaimer = `\n\n\n
+================================
+TestFlight 账户管理脚本:
+
请注意,使用"共享"功能时,请务必仔细阅读以下声明 ‼️
请注意,使用"共享"功能时,请务必仔细阅读以下声明 ‼️
请注意,使用"共享"功能时,请务必仔细阅读以下声明 ‼️
-
-======================================
+================================
权限:
您即将共享的密钥理论上具有以下权限,包括但不限于:
@@ -265,19 +261,13 @@ function ShareAccount(appID, bid) {
免责:
任何用户使用"共享"功能时都应该仔细阅读权限声明,一旦您开始使用该功能,即视为您已知晓并理解密钥所具有的权限,密钥泄漏可能会导致不可预知的损失或损害,脚本作者(NobyDa)不对由此产生的任何后果负责。
-======================================
+================================
该脚本在"默认"情况下,对方仅可查看/下载您共享的单个APP,但仍建议仅与您信任的人共享:
`;
$.log(`Raw data: ${raw}\nEncode data: ${key}`);
- return {
- data: {
- buildId: bid,
- eula: disclaimer + key
- },
- messages: null
- }
+ return disclaimer + key;
}
// private encode method, based on variant in RFC4648
@@ -312,4 +302,4 @@ function letterDecode(e) {
}
// https://github.com/Peng-YM/QuanX/tree/master/Tools/OpenAPI
-function ENV() { const e = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isShadowrocket: "undefined" != typeof $Shadowrocket, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !e, isJSBox: e, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule, } } function HTTP(e = { baseURL: "" }) { const { isQX: t, isLoon: s, isSurge: o, isScriptable: n, isNode: i, isBrowser: r, } = ENV(), u = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; const a = {}; return (["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach((h) => (a[h.toLowerCase()] = (a) => (function (a, h) { h = "string" == typeof h ? { url: h } : h; const d = e.baseURL; d && !u.test(h.url || "") && (h.url = d ? d + h.url : h.url), h.body && h.headers; h.timeout && s && (h.timeout = h.timeout * 1000); const l = (h = { ...e, ...h }).timeout, c = { onRequest: () => { }, onResponse: (e) => e, onTimeout: () => { }, ...h.events, }; let f, p; if ((c.onRequest(a, h), t)) f = $task.fetch({ method: a, ...h }); else if (s || o || i) f = new Promise((e, t) => { (i ? require("request") : $httpClient)[a.toLowerCase()](h, (s, o, n) => { s ? t(s) : e({ statusCode: o.status || o.statusCode, headers: o.headers, body: n, }) },) }); else if (n) { const e = new Request(h.url); (e.method = a), (e.headers = h.headers), (e.body = h.body), (f = new Promise((t, s) => { e.loadString().then((s) => { t({ statusCode: e.response.statusCode, headers: e.response.headers, body: s, }) }).catch((e) => s(e)) })) } else r && (f = new Promise((e, t) => { fetch(h.url, { method: a, headers: h.headers, body: h.body }).then((e) => e.json()).then((t) => e({ statusCode: t.status, headers: t.headers, body: t.data, }),).catch(t) })); const y = l ? new Promise((e, t) => { p = setTimeout(() => (c.onTimeout(), t(`timeout`)), !s ? l * 1000 : l,) }) : null; return (y ? Promise.race([y, f]).then((e) => ((typeof clearTimeout !== 'undefined') && clearTimeout(p), e)) : f).then((e) => c.onResponse(e)) })(h, a)),), a) } function API(e = "untitled", t = !1) { const { isQX: s, isLoon: o, isSurge: n, isNode: i, isJSBox: r, isScriptable: u, } = ENV(); return new (class { constructor(e, t) { (this.name = e), (this.debug = t), (this.http = HTTP()), (this.env = ENV()), (this.node = (() => { if (i) { return { fs: require("fs") } } return null })()), this.initCache(); Promise.prototype.delay = function (e) { return this.then(function (t) { return ((e, t) => new Promise(function (s) { setTimeout(s.bind(null, t), e) }))(e, t) }) } } initCache() { if ((s && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (o || n) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), i)) { let e = "root.json"; this.node.fs.existsSync(e) || this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, (e) => console.log(e),), (this.root = {}), (e = `${this.name}.json`), this.node.fs.existsSync(e) ? (this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`),)) : (this.node.fs.writeFileSync(e, JSON.stringify({}), { flag: "wx" }, (e) => console.log(e),), (this.cache = {})) } } persistCache() { const e = JSON.stringify(this.cache, null, 2); s && $prefs.setValueForKey(e, this.name), (o || n) && $persistentStore.write(e, this.name), i && (this.node.fs.writeFileSync(`${this.name}.json`, e, { flag: "w" }, (e) => console.log(e),), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, (e) => console.log(e),)) } write(e, t) { if ((this.log(`SET ${t}`), -1 !== t.indexOf("#"))) { if (((t = t.substr(1)), n || o)) return $persistentStore.write(e, t); if (s) return $prefs.setValueForKey(e, t); i && (this.root[t] = e) } else this.cache[t] = e; this.persistCache() } read(e) { return (this.log(`READ ${e}`), -1 === e.indexOf("#") ? this.cache[e] : ((e = e.substr(1)), n || o ? $persistentStore.read(e) : s ? $prefs.valueForKey(e) : i ? this.root[e] : void 0)) } delete(e) { if ((this.log(`DELETE ${e}`), -1 !== e.indexOf("#"))) { if (((e = e.substr(1)), n || o)) return $persistentStore.write(null, e); if (s) return $prefs.removeValueForKey(e); i && delete this.root[e] } else delete this.cache[e]; this.persistCache() } notify(e, t = "", a = "", h = {}) { const d = h["open-url"], l = h["media-url"]; if ((s && $notify(e, t, a, h), n && $notification.post(e, t, a + `${l ? "\n多媒体:" + l : ""}`, { url: d, }), o)) { let s = {}; d && (s.openUrl = d), l && (s.mediaUrl = l), "{}" === JSON.stringify(s) ? $notification.post(e, t, a) : $notification.post(e, t, a, s) } if (i || u) { const s = a + (d ? `\n点击跳转:${d}` : "") + (l ? `\n多媒体:${l}` : ""); if (r) { require("push").schedule({ title: e, body: (t ? t + "\n" : "") + s }) } else console.log(`${e}\n${t}\n${s}\n\n`) } } log(e) { this.debug && console.log(`[${this.name}]LOG:${this.stringify(e)}`) } info(e) { console.log(`[${this.name}]INFO:${this.stringify(e)}`) } error(e) { console.log(`[${this.name}]ERROR:${this.stringify(e)}`) } wait(e) { return new Promise((t) => setTimeout(t, e)) } done(e = {}) { s || o || n ? $done(e) : i && !r && "undefined" != typeof $context && (($context.headers = e.headers), ($context.statusCode = e.statusCode), ($context.body = e.body)) } stringify(e) { if ("string" == typeof e || e instanceof String) return e; try { return JSON.stringify(e, null, 2) } catch (e) { return "[object Object]" } } })(e, t) }
\ No newline at end of file
+function ENV() { const a = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isShadowrocket: "undefined" != typeof $Shadowrocket, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !a, isJSBox: a, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP(a = { baseURL: "" }) { function b(b, j) { j = "string" == typeof j ? { url: j } : j; const k = a.baseURL; k && !i.test(j.url || "") && (j.url = k ? k + j.url : j.url), j = { ...a, ...j }; const l = j.timeout, m = { ...{ onRequest: () => { }, onResponse: a => a, onTimeout: () => { } }, ...j.events }; m.onRequest(b, j); let n; if (c) n = $task.fetch({ method: b, ...j }); else if (d || e || g) n = new Promise((a, c) => { var e = Math.ceil; const f = g ? require("request") : $httpClient; !j.timeout || g || d || (j.timeout = e(j.timeout / 1e3)), f[b.toLowerCase()](j, (b, d, e) => { b ? c(b) : a({ statusCode: d.status || d.statusCode, headers: d.headers, body: e }) }) }); else if (f) { const a = new Request(j.url); a.method = b, a.headers = j.headers, a.body = j.body, n = new Promise((b, c) => { a.loadString().then(c => { b({ statusCode: a.response.statusCode, headers: a.response.headers, body: c }) }).catch(a => c(a)) }) } else h && (n = new Promise((a, c) => { fetch(j.url, { method: b, headers: j.headers, body: j.body }).then(a => a.json()).then(b => a({ statusCode: b.status, headers: b.headers, body: b.data })).catch(c) })); let o; const p = l ? new Promise((a, b) => { o = setTimeout(() => (m.onTimeout(), b(`timeout`)), l) }) : null; return (p ? Promise.race([p, n]).then(a => ("undefined" != typeof clearTimeout && clearTimeout(o), a)) : n).then(a => m.onResponse(a)) } const { isQX: c, isLoon: d, isSurge: e, isScriptable: f, isNode: g, isBrowser: h } = ENV(), i = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/, j = {}; return ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(a => j[a.toLowerCase()] = c => b(a, c)), j } function API(a = "untitled", b = !1) { const { isQX: c, isLoon: d, isSurge: e, isNode: f, isJSBox: g, isScriptable: h } = ENV(); return new class { constructor(a, b) { this.name = a, this.debug = b, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (f) { const a = require("fs"); return { fs: a } } return null })(), this.initCache(); const c = (a, b) => new Promise(function (c) { setTimeout(c.bind(null, b), a) }); Promise.prototype.delay = function (a) { return this.then(function (b) { return c(a, b) }) } } initCache() { if (c && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (d || e) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), f) { let a = "root.json"; this.node.fs.existsSync(a) || this.node.fs.writeFileSync(a, JSON.stringify({}), { flag: "wx" }, a => console.log(a)), this.root = {}, a = `${this.name}.json`, this.node.fs.existsSync(a) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(a, JSON.stringify({}), { flag: "wx" }, a => console.log(a)), this.cache = {}) } } persistCache() { const a = JSON.stringify(this.cache, null, 2); c && $prefs.setValueForKey(a, this.name), (d || e) && $persistentStore.write(a, this.name), f && (this.node.fs.writeFileSync(`${this.name}.json`, a, { flag: "w" }, a => console.log(a)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, a => console.log(a))) } write(a, b) { if (this.log(`SET ${b}`), -1 !== b.indexOf("#")) { if (b = b.substr(1), e || d) return $persistentStore.write(a, b); if (c) return $prefs.setValueForKey(a, b); f && (this.root[b] = a) } else this.cache[b] = a; this.persistCache() } read(a) { if (this.log(`READ ${a}`), -1 !== a.indexOf("#")) { if (a = a.substr(1), e || d) return $persistentStore.read(a); if (c) return $prefs.valueForKey(a); if (f) return this.root[a] } else return this.cache[a] } delete(a) { if (this.log(`DELETE ${a}`), -1 !== a.indexOf("#")) { if (a = a.substr(1), e || d) return $persistentStore.write(null, a); if (c) return $prefs.removeValueForKey(a); f && delete this.root[a] } else delete this.cache[a]; this.persistCache() } notify(a, b = "", i = "", j = {}) { const k = j["open-url"], l = j["media-url"]; if (c && $notify(a, b, i, j), e && $notification.post(a, b, i + `${l ? "\n\u591A\u5A92\u4F53:" + l : ""}`, { url: k }), d) { let c = {}; k && (c.openUrl = k), l && (c.mediaUrl = l), "{}" === JSON.stringify(c) ? $notification.post(a, b, i) : $notification.post(a, b, i, c) } if (f || h) { const c = i + (k ? `\n点击跳转: ${k}` : "") + (l ? `\n多媒体: ${l}` : ""); if (g) { const d = require("push"); d.schedule({ title: a, body: (b ? b + "\n" : "") + c }) } else console.log(`${a}\n${b}\n${c}\n\n`) } } log(a) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(a)}`) } info(a) { console.log(`[${this.name}] INFO: ${this.stringify(a)}`) } error(a) { console.log(`[${this.name}] ERROR: ${this.stringify(a)}`) } wait(a) { return new Promise(b => setTimeout(b, a)) } done(a = {}) { c || d || e ? $done(a) : f && !g && "undefined" != typeof $context && ($context.headers = a.headers, $context.statusCode = a.statusCode, $context.body = a.body) } stringify(a) { if ("string" == typeof a || a instanceof String) return a; try { return JSON.stringify(a, null, 2) } catch (a) { return "[object Object]" } } }(a, b) }
\ No newline at end of file
From 346b68af17d15fe5f37f26cbbc579ad838c3fe51 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 25 Mar 2024 18:46:29 +0800
Subject: [PATCH 079/105] add debug script.
---
Debug/Real-time-debug.js | 64 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
create mode 100644 Debug/Real-time-debug.js
diff --git a/Debug/Real-time-debug.js b/Debug/Real-time-debug.js
new file mode 100644
index 0000000000..7abff11a82
--- /dev/null
+++ b/Debug/Real-time-debug.js
@@ -0,0 +1,64 @@
+/*
+ * LAN script real-time debug
+ *
+ * PC: Use "Live Server" plugin in VSCode to create a LAN backend
+ * APP: After backend address is modified in script, use this script as script path
+ */
+
+!async function() {
+ const _$ = new nobyda();
+ const _r = await new Promise(e => {
+ _$.get({
+ url: 'http://192.168.1.66:5500/debug.js' // LAN backend address
+ }, (t, c, o) => {
+ if (c && c.status == 200 && o) {
+ _$.write(o, 'Real-time-debug');
+ e(o);
+ }
+ });
+ setTimeout(e, 100);
+ });
+ if (_r) {
+ console.log("🌐 Run local network script...");
+ eval(_r);
+ } else {
+ console.log("⚠️ Run cache script...");
+ eval(_$.read('Real-time-debug'))
+ }
+
+ function nobyda() {
+ const isSurge = typeof $httpClient != "undefined";
+ const isQuanX = typeof $task != "undefined";
+ const adapterStatus = (response) => {
+ if (response) {
+ if (response.status) {
+ response["statusCode"] = response.status
+ } else if (response.statusCode) {
+ response["status"] = response.statusCode
+ }
+ }
+ return response
+ };
+ this.write = (value, key) => {
+ if (isQuanX) return $prefs.setValueForKey(value, key);
+ if (isSurge) return $persistentStore.write(value, key);
+ };
+ this.read = (key) => {
+ if (isQuanX) return $prefs.valueForKey(key);
+ if (isSurge) return $persistentStore.read(key);
+ };
+ this.get = (options, callback) => {
+ if (isQuanX) {
+ $task.fetch(options).then(response => {
+ callback(null, adapterStatus(response), response.body)
+ }, reason => callback(reason.error, null, null))
+ }
+ if (isSurge) {
+ $httpClient.get(options, (error, response, body) => {
+ callback(error, adapterStatus(response), body)
+ })
+ }
+ };
+ this.done = (value = {}) => $done(value)
+ }
+}();
\ No newline at end of file
From f5f752f6e792a3c25b035157171be784a155a2bd Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 4 Apr 2024 23:42:55 +0800
Subject: [PATCH 080/105] Improved cache structure to cache all requests.
---
TestFlight/TestFlightAccount.js | 70 +++++++++++++++++----------------
1 file changed, 36 insertions(+), 34 deletions(-)
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 3619a551a0..61ffc79124 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -3,7 +3,7 @@ TestFlight账户管理脚本
脚本作者: @NobyDa
脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
-更新时间: 2024/03/25
+更新时间: 2024/04/04
主要功能:
1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
@@ -54,6 +54,7 @@ const [list, appList] = [$.read('AccountList') || {}, $.read('AppList') || {}];
$.debug = Number(args.debug) || ($.read('Debug') === 'true');
$.EnableCache = Number(args.enableCache) || ($.read('EnableCache') === 'true');
$.ForceIOSlist = Number(args.forceIOSlist) || ($.read('ForceIOSlist') === 'true');
+const cache = $.EnableCache && JSON.parse($.read('#TESTFLIGHT-ACCOUNT-CACHE') || '{}');
runs()
.then((resp) => {
@@ -83,7 +84,7 @@ async function runs() {
} else if (/\/[A-Z]{200,}\/redeem$/.test(req.url)) {
return { body: ExternalAccount(req.url.split(/\/([A-Z]+)\/redeem$/)[1]) };
}
- return await QueryRequest(!other && appList[appID]);
+ return await QueryRequest(!other && appList[appID] || null);
}
function SaveAccount(id, part, o) {
@@ -140,31 +141,9 @@ function ChangeHeaders(id) {
function ChangeBody(resp) {
if (req.url.endsWith('/apps')) {
- const cache = $.EnableCache && JSON.parse($.read('#TESTFLIGHT-ACCOUNT-CACHE') || '{}');
- resp = resp.map((v) => {
- v.body = JSON.parse(v.body || '{}');
- if (v.status == 401) {
- if (list[v.account].InvalidKey >= 2) { //prevent misjudgment
- delete list[v.account];
- } else {
- list[v.account].InvalidKey = (list[v.account].InvalidKey || 0) + 1;
- }
- $.write(list, 'AccountList');
- $.error(`Account "${v.account}" key expired ⚠️`);
- $.notify('TestFlight Account', '', `Account ID "${v.account}" key expired ⚠️`);
- }
- if ($.EnableCache && v.body.data) {
- $.log(`Account "${v.account}" write app list to cache`);
- cache[v.account] = $.stringify(v.body);
- $.write($.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
- }
- if ($.EnableCache && !v.body.data) {
- v.body = JSON.parse(cache[v.account] || '{}');
- $.log(`Account "${v.account}" Try using cache app list`);
- }
- $.log(`Account "${v.account}" app list: ${$.stringify((v.body.data || []).map(i => i.name))}`);
- return v
- }).reduce((t, d) => {
+ resp = resp.reduce((t, d) => {
+ d.body = JSON.parse(d.status == 200 && d.body || '{}');
+ $.log(`Account "${d.account}" app list: ${$.stringify((d.body.data || []).map(i => i.name))}`);
d.body.data = (d.body.data || []).map(i => {
if ($.ForceIOSlist) {
i.platforms = i.platforms.map(j => {
@@ -183,7 +162,7 @@ function ChangeBody(resp) {
return only && t.body.data[req.url.includes(d.account) ? 'unshift' : 'push'](i), i;
});
if (req.url.includes(d.account)) {
- [t.status, t.headers] = [d.statusCode, d.headers];
+ [t.status, t.headers] = [d.status, d.headers];
}
return t
}, { body: { data: [], error: null } });
@@ -192,7 +171,7 @@ function ChangeBody(resp) {
$.log(`Final app: ${$.stringify(resp.body.data.map(i => i.name))}`);
resp.body = JSON.stringify(resp.body);
}
- if (/\/apps\/\d+\/builds\/\d+$/.test(req.url) && resp.body) { //beta app page
+ if (/\/apps\/\d+\/builds\/\d+$/.test(req.url) && resp.status == 200 && resp.body) { //beta app page
const share = ShareAccount(req.url.split(/\/apps\/(\d+)/)[1]);
resp.body = JSON.parse(resp.body);
resp.body.data.builds.map(e => e.description = `${e.description || '-'}${share}`);
@@ -202,14 +181,37 @@ function ChangeBody(resp) {
}
function QueryRequest(o) {
- return $.http[req.method.toLowerCase()](ChangeHeaders(o))
+ const option = ChangeHeaders(o);
+ return $.http[req.method.toLowerCase()](option)
.then(r => {
- $.log(`Account "${o}" response: status=${r.statusCode}, body=${Boolean(r.body)}`);
- return { status: r.statusCode, headers: r.headers, body: r.body, account: o }
+ $.log(`Account "${o}" response: status=${r.status}, body=${Boolean(r.body)}`);
+ if (r.status == 401) {
+ if (list[o].InvalidKey >= 2) { //prevent misjudgment
+ delete list[o];
+ } else {
+ list[o].InvalidKey = (list[o].InvalidKey || 0) + 1;
+ }
+ $.write(list, 'AccountList');
+ $.notify('TestFlight Account', '', `Account ID "${o}" key expired ⚠️`);
+ throw new Error('key expired ⚠️');
+ }
+ if ($.EnableCache && r.body && r.body.startsWith('{')) {
+ $.log(`Account "${o}" URL "${option.url}" Write data to cache`);
+ cache[option.url] = { response: r, lastUsed: Date.now() };
+ Object.keys(cache).forEach((i) => (Date.now() - (cache[i].lastUsed || 0) > 864e5 * 7) && delete cache[i]);
+ $.write($.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
+ }
+ return { ...r, account: o }
})
.catch(e => {
$.error(`Account "${o}" response failed: ${e.error || e.message || e}`);
- return { error: e, account: o }
+ if ($.EnableCache && cache[option.url] && !(e.error || e.message || e).includes('key expired')) {
+ cache[option.url].lastUsed = Date.now();
+ $.log(`Account "${o}" URL "${option.url}" Using cached data`);
+ $.write($.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
+ return { ...cache[option.url].response, account: o }
+ }
+ return { account: o }
})
}
@@ -302,4 +304,4 @@ function letterDecode(e) {
}
// https://github.com/Peng-YM/QuanX/tree/master/Tools/OpenAPI
-function ENV() { const a = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isShadowrocket: "undefined" != typeof $Shadowrocket, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !a, isJSBox: a, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP(a = { baseURL: "" }) { function b(b, j) { j = "string" == typeof j ? { url: j } : j; const k = a.baseURL; k && !i.test(j.url || "") && (j.url = k ? k + j.url : j.url), j = { ...a, ...j }; const l = j.timeout, m = { ...{ onRequest: () => { }, onResponse: a => a, onTimeout: () => { } }, ...j.events }; m.onRequest(b, j); let n; if (c) n = $task.fetch({ method: b, ...j }); else if (d || e || g) n = new Promise((a, c) => { var e = Math.ceil; const f = g ? require("request") : $httpClient; !j.timeout || g || d || (j.timeout = e(j.timeout / 1e3)), f[b.toLowerCase()](j, (b, d, e) => { b ? c(b) : a({ statusCode: d.status || d.statusCode, headers: d.headers, body: e }) }) }); else if (f) { const a = new Request(j.url); a.method = b, a.headers = j.headers, a.body = j.body, n = new Promise((b, c) => { a.loadString().then(c => { b({ statusCode: a.response.statusCode, headers: a.response.headers, body: c }) }).catch(a => c(a)) }) } else h && (n = new Promise((a, c) => { fetch(j.url, { method: b, headers: j.headers, body: j.body }).then(a => a.json()).then(b => a({ statusCode: b.status, headers: b.headers, body: b.data })).catch(c) })); let o; const p = l ? new Promise((a, b) => { o = setTimeout(() => (m.onTimeout(), b(`timeout`)), l) }) : null; return (p ? Promise.race([p, n]).then(a => ("undefined" != typeof clearTimeout && clearTimeout(o), a)) : n).then(a => m.onResponse(a)) } const { isQX: c, isLoon: d, isSurge: e, isScriptable: f, isNode: g, isBrowser: h } = ENV(), i = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/, j = {}; return ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(a => j[a.toLowerCase()] = c => b(a, c)), j } function API(a = "untitled", b = !1) { const { isQX: c, isLoon: d, isSurge: e, isNode: f, isJSBox: g, isScriptable: h } = ENV(); return new class { constructor(a, b) { this.name = a, this.debug = b, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (f) { const a = require("fs"); return { fs: a } } return null })(), this.initCache(); const c = (a, b) => new Promise(function (c) { setTimeout(c.bind(null, b), a) }); Promise.prototype.delay = function (a) { return this.then(function (b) { return c(a, b) }) } } initCache() { if (c && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (d || e) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), f) { let a = "root.json"; this.node.fs.existsSync(a) || this.node.fs.writeFileSync(a, JSON.stringify({}), { flag: "wx" }, a => console.log(a)), this.root = {}, a = `${this.name}.json`, this.node.fs.existsSync(a) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(a, JSON.stringify({}), { flag: "wx" }, a => console.log(a)), this.cache = {}) } } persistCache() { const a = JSON.stringify(this.cache, null, 2); c && $prefs.setValueForKey(a, this.name), (d || e) && $persistentStore.write(a, this.name), f && (this.node.fs.writeFileSync(`${this.name}.json`, a, { flag: "w" }, a => console.log(a)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, a => console.log(a))) } write(a, b) { if (this.log(`SET ${b}`), -1 !== b.indexOf("#")) { if (b = b.substr(1), e || d) return $persistentStore.write(a, b); if (c) return $prefs.setValueForKey(a, b); f && (this.root[b] = a) } else this.cache[b] = a; this.persistCache() } read(a) { if (this.log(`READ ${a}`), -1 !== a.indexOf("#")) { if (a = a.substr(1), e || d) return $persistentStore.read(a); if (c) return $prefs.valueForKey(a); if (f) return this.root[a] } else return this.cache[a] } delete(a) { if (this.log(`DELETE ${a}`), -1 !== a.indexOf("#")) { if (a = a.substr(1), e || d) return $persistentStore.write(null, a); if (c) return $prefs.removeValueForKey(a); f && delete this.root[a] } else delete this.cache[a]; this.persistCache() } notify(a, b = "", i = "", j = {}) { const k = j["open-url"], l = j["media-url"]; if (c && $notify(a, b, i, j), e && $notification.post(a, b, i + `${l ? "\n\u591A\u5A92\u4F53:" + l : ""}`, { url: k }), d) { let c = {}; k && (c.openUrl = k), l && (c.mediaUrl = l), "{}" === JSON.stringify(c) ? $notification.post(a, b, i) : $notification.post(a, b, i, c) } if (f || h) { const c = i + (k ? `\n点击跳转: ${k}` : "") + (l ? `\n多媒体: ${l}` : ""); if (g) { const d = require("push"); d.schedule({ title: a, body: (b ? b + "\n" : "") + c }) } else console.log(`${a}\n${b}\n${c}\n\n`) } } log(a) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(a)}`) } info(a) { console.log(`[${this.name}] INFO: ${this.stringify(a)}`) } error(a) { console.log(`[${this.name}] ERROR: ${this.stringify(a)}`) } wait(a) { return new Promise(b => setTimeout(b, a)) } done(a = {}) { c || d || e ? $done(a) : f && !g && "undefined" != typeof $context && ($context.headers = a.headers, $context.statusCode = a.statusCode, $context.body = a.body) } stringify(a) { if ("string" == typeof a || a instanceof String) return a; try { return JSON.stringify(a, null, 2) } catch (a) { return "[object Object]" } } }(a, b) }
\ No newline at end of file
+function ENV() { const a = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isShadowrocket: "undefined" != typeof $Shadowrocket, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !a, isJSBox: a, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP(a = { baseURL: "" }) { function b(b, j) { j = "string" == typeof j ? { url: j } : j; const k = a.baseURL; k && !i.test(j.url || "") && (j.url = k ? k + j.url : j.url), j = { ...a, ...j }; const l = j.timeout, m = { ...{ onRequest: () => { }, onResponse: a => a, onTimeout: () => { } }, ...j.events }; m.onRequest(b, j); let n; if (c) n = $task.fetch({ method: b, ...j }); else if (d || e || g) n = new Promise((a, c) => { var e = Math.ceil; const f = g ? require("request") : $httpClient; !j.timeout || g || d || (j.timeout = e(j.timeout / 1e3)), f[b.toLowerCase()](j, (b, d, e) => { b ? c(b) : a({ status: d.status || d.statusCode, headers: d.headers, body: e }) }) }); else if (f) { const a = new Request(j.url); a.method = b, a.headers = j.headers, a.body = j.body, n = new Promise((b, c) => { a.loadString().then(c => { b({ status: a.response.statusCode, headers: a.response.headers, body: c }) }).catch(a => c(a)) }) } else h && (n = new Promise((a, c) => { fetch(j.url, { method: b, headers: j.headers, body: j.body }).then(a => a.json()).then(b => a({ status: b.status, headers: b.headers, body: b.data })).catch(c) })); let o; const p = l ? new Promise((a, b) => { o = setTimeout(() => (m.onTimeout(), b(`timeout`)), l) }) : null; return (p ? Promise.race([p, n]).then(a => ("undefined" != typeof clearTimeout && clearTimeout(o), a)) : n).then(a => m.onResponse(a)) } const { isQX: c, isLoon: d, isSurge: e, isScriptable: f, isNode: g, isBrowser: h } = ENV(), i = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/, j = {}; return ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(a => j[a.toLowerCase()] = c => b(a, c)), j } function API(a = "untitled", b = !1) { const { isQX: c, isLoon: d, isSurge: e, isNode: f, isJSBox: g, isScriptable: h } = ENV(); return new class { constructor(a, b) { this.name = a, this.debug = b, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (f) { const a = require("fs"); return { fs: a } } return null })(), this.initCache(); const c = (a, b) => new Promise(function (c) { setTimeout(c.bind(null, b), a) }); Promise.prototype.delay = function (a) { return this.then(function (b) { return c(a, b) }) } } initCache() { if (c && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (d || e) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), f) { let a = "root.json"; this.node.fs.existsSync(a) || this.node.fs.writeFileSync(a, JSON.stringify({}), { flag: "wx" }, a => console.log(a)), this.root = {}, a = `${this.name}.json`, this.node.fs.existsSync(a) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(a, JSON.stringify({}), { flag: "wx" }, a => console.log(a)), this.cache = {}) } } persistCache() { const a = JSON.stringify(this.cache, null, 2); c && $prefs.setValueForKey(a, this.name), (d || e) && $persistentStore.write(a, this.name), f && (this.node.fs.writeFileSync(`${this.name}.json`, a, { flag: "w" }, a => console.log(a)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, a => console.log(a))) } write(a, b) { if (this.log(`SET ${b}`), -1 !== b.indexOf("#")) { if (b = b.substr(1), e || d) return $persistentStore.write(a, b); if (c) return $prefs.setValueForKey(a, b); f && (this.root[b] = a) } else this.cache[b] = a; this.persistCache() } read(a) { if (this.log(`READ ${a}`), -1 !== a.indexOf("#")) { if (a = a.substr(1), e || d) return $persistentStore.read(a); if (c) return $prefs.valueForKey(a); if (f) return this.root[a] } else return this.cache[a] } delete(a) { if (this.log(`DELETE ${a}`), -1 !== a.indexOf("#")) { if (a = a.substr(1), e || d) return $persistentStore.write(null, a); if (c) return $prefs.removeValueForKey(a); f && delete this.root[a] } else delete this.cache[a]; this.persistCache() } notify(a, b = "", i = "", j = {}) { const k = j["open-url"], l = j["media-url"]; if (c && $notify(a, b, i, j), e && $notification.post(a, b, i + `${l ? "\n\u591A\u5A92\u4F53:" + l : ""}`, { url: k }), d) { let c = {}; k && (c.openUrl = k), l && (c.mediaUrl = l), "{}" === JSON.stringify(c) ? $notification.post(a, b, i) : $notification.post(a, b, i, c) } if (f || h) { const c = i + (k ? `\n点击跳转: ${k}` : "") + (l ? `\n多媒体: ${l}` : ""); if (g) { const d = require("push"); d.schedule({ title: a, body: (b ? b + "\n" : "") + c }) } else console.log(`${a}\n${b}\n${c}\n\n`) } } log(a) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(a)}`) } info(a) { console.log(`[${this.name}] INFO: ${this.stringify(a)}`) } error(a) { console.log(`[${this.name}] ERROR: ${this.stringify(a)}`) } wait(a) { return new Promise(b => setTimeout(b, a)) } done(a = {}) { c || d || e ? $done(a) : f && !g && "undefined" != typeof $context && ($context.headers = a.headers, $context.statusCode = a.statusCode, $context.body = a.body) } stringify(a) { if ("string" == typeof a || a instanceof String) return a; try { return JSON.stringify(a, null, 2) } catch (a) { return "[object Object]" } } }(a, b) }
\ No newline at end of file
From b00608e9ac997c554fc093c7a3b5bf1bce8061d0 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 5 Apr 2024 22:38:45 +0800
Subject: [PATCH 081/105] bug fixes.
---
TestFlight/TestFlightAccount.js | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 61ffc79124..b766aaf90b 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -3,7 +3,7 @@ TestFlight账户管理脚本
脚本作者: @NobyDa
脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
-更新时间: 2024/04/04
+更新时间: 2024/04/05
主要功能:
1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
@@ -185,7 +185,7 @@ function QueryRequest(o) {
return $.http[req.method.toLowerCase()](option)
.then(r => {
$.log(`Account "${o}" response: status=${r.status}, body=${Boolean(r.body)}`);
- if (r.status == 401) {
+ if (r.status == 401 && o) {
if (list[o].InvalidKey >= 2) { //prevent misjudgment
delete list[o];
} else {
@@ -193,7 +193,7 @@ function QueryRequest(o) {
}
$.write(list, 'AccountList');
$.notify('TestFlight Account', '', `Account ID "${o}" key expired ⚠️`);
- throw new Error('key expired ⚠️');
+ throw 'key expired ⚠️';
}
if ($.EnableCache && r.body && r.body.startsWith('{')) {
$.log(`Account "${o}" URL "${option.url}" Write data to cache`);
@@ -204,13 +204,13 @@ function QueryRequest(o) {
return { ...r, account: o }
})
.catch(e => {
- $.error(`Account "${o}" response failed: ${e.error || e.message || e}`);
- if ($.EnableCache && cache[option.url] && !(e.error || e.message || e).includes('key expired')) {
+ if ($.EnableCache && cache[option.url] && !(e).includes('key expired')) {
cache[option.url].lastUsed = Date.now();
$.log(`Account "${o}" URL "${option.url}" Using cached data`);
$.write($.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
return { ...cache[option.url].response, account: o }
}
+ $.error(`Account "${o}" response failed: ${e}`);
return { account: o }
})
}
@@ -304,4 +304,4 @@ function letterDecode(e) {
}
// https://github.com/Peng-YM/QuanX/tree/master/Tools/OpenAPI
-function ENV() { const a = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isShadowrocket: "undefined" != typeof $Shadowrocket, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !a, isJSBox: a, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP(a = { baseURL: "" }) { function b(b, j) { j = "string" == typeof j ? { url: j } : j; const k = a.baseURL; k && !i.test(j.url || "") && (j.url = k ? k + j.url : j.url), j = { ...a, ...j }; const l = j.timeout, m = { ...{ onRequest: () => { }, onResponse: a => a, onTimeout: () => { } }, ...j.events }; m.onRequest(b, j); let n; if (c) n = $task.fetch({ method: b, ...j }); else if (d || e || g) n = new Promise((a, c) => { var e = Math.ceil; const f = g ? require("request") : $httpClient; !j.timeout || g || d || (j.timeout = e(j.timeout / 1e3)), f[b.toLowerCase()](j, (b, d, e) => { b ? c(b) : a({ status: d.status || d.statusCode, headers: d.headers, body: e }) }) }); else if (f) { const a = new Request(j.url); a.method = b, a.headers = j.headers, a.body = j.body, n = new Promise((b, c) => { a.loadString().then(c => { b({ status: a.response.statusCode, headers: a.response.headers, body: c }) }).catch(a => c(a)) }) } else h && (n = new Promise((a, c) => { fetch(j.url, { method: b, headers: j.headers, body: j.body }).then(a => a.json()).then(b => a({ status: b.status, headers: b.headers, body: b.data })).catch(c) })); let o; const p = l ? new Promise((a, b) => { o = setTimeout(() => (m.onTimeout(), b(`timeout`)), l) }) : null; return (p ? Promise.race([p, n]).then(a => ("undefined" != typeof clearTimeout && clearTimeout(o), a)) : n).then(a => m.onResponse(a)) } const { isQX: c, isLoon: d, isSurge: e, isScriptable: f, isNode: g, isBrowser: h } = ENV(), i = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/, j = {}; return ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(a => j[a.toLowerCase()] = c => b(a, c)), j } function API(a = "untitled", b = !1) { const { isQX: c, isLoon: d, isSurge: e, isNode: f, isJSBox: g, isScriptable: h } = ENV(); return new class { constructor(a, b) { this.name = a, this.debug = b, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (f) { const a = require("fs"); return { fs: a } } return null })(), this.initCache(); const c = (a, b) => new Promise(function (c) { setTimeout(c.bind(null, b), a) }); Promise.prototype.delay = function (a) { return this.then(function (b) { return c(a, b) }) } } initCache() { if (c && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (d || e) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), f) { let a = "root.json"; this.node.fs.existsSync(a) || this.node.fs.writeFileSync(a, JSON.stringify({}), { flag: "wx" }, a => console.log(a)), this.root = {}, a = `${this.name}.json`, this.node.fs.existsSync(a) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(a, JSON.stringify({}), { flag: "wx" }, a => console.log(a)), this.cache = {}) } } persistCache() { const a = JSON.stringify(this.cache, null, 2); c && $prefs.setValueForKey(a, this.name), (d || e) && $persistentStore.write(a, this.name), f && (this.node.fs.writeFileSync(`${this.name}.json`, a, { flag: "w" }, a => console.log(a)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, a => console.log(a))) } write(a, b) { if (this.log(`SET ${b}`), -1 !== b.indexOf("#")) { if (b = b.substr(1), e || d) return $persistentStore.write(a, b); if (c) return $prefs.setValueForKey(a, b); f && (this.root[b] = a) } else this.cache[b] = a; this.persistCache() } read(a) { if (this.log(`READ ${a}`), -1 !== a.indexOf("#")) { if (a = a.substr(1), e || d) return $persistentStore.read(a); if (c) return $prefs.valueForKey(a); if (f) return this.root[a] } else return this.cache[a] } delete(a) { if (this.log(`DELETE ${a}`), -1 !== a.indexOf("#")) { if (a = a.substr(1), e || d) return $persistentStore.write(null, a); if (c) return $prefs.removeValueForKey(a); f && delete this.root[a] } else delete this.cache[a]; this.persistCache() } notify(a, b = "", i = "", j = {}) { const k = j["open-url"], l = j["media-url"]; if (c && $notify(a, b, i, j), e && $notification.post(a, b, i + `${l ? "\n\u591A\u5A92\u4F53:" + l : ""}`, { url: k }), d) { let c = {}; k && (c.openUrl = k), l && (c.mediaUrl = l), "{}" === JSON.stringify(c) ? $notification.post(a, b, i) : $notification.post(a, b, i, c) } if (f || h) { const c = i + (k ? `\n点击跳转: ${k}` : "") + (l ? `\n多媒体: ${l}` : ""); if (g) { const d = require("push"); d.schedule({ title: a, body: (b ? b + "\n" : "") + c }) } else console.log(`${a}\n${b}\n${c}\n\n`) } } log(a) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(a)}`) } info(a) { console.log(`[${this.name}] INFO: ${this.stringify(a)}`) } error(a) { console.log(`[${this.name}] ERROR: ${this.stringify(a)}`) } wait(a) { return new Promise(b => setTimeout(b, a)) } done(a = {}) { c || d || e ? $done(a) : f && !g && "undefined" != typeof $context && ($context.headers = a.headers, $context.statusCode = a.statusCode, $context.body = a.body) } stringify(a) { if ("string" == typeof a || a instanceof String) return a; try { return JSON.stringify(a, null, 2) } catch (a) { return "[object Object]" } } }(a, b) }
\ No newline at end of file
+function ENV() { const a = "function" == typeof require && "undefined" != typeof $jsbox; return { isQX: "undefined" != typeof $task, isLoon: "undefined" != typeof $loon, isSurge: "undefined" != typeof $httpClient && "undefined" == typeof $loon, isShadowrocket: "undefined" != typeof $Shadowrocket, isBrowser: "undefined" != typeof document, isNode: "function" == typeof require && !a, isJSBox: a, isRequest: "undefined" != typeof $request, isScriptable: "undefined" != typeof importModule } } function HTTP(a = { baseURL: "" }) { function b(b, j) { j = "string" == typeof j ? { url: j } : j; const k = a.baseURL; k && !i.test(j.url || "") && (j.url = k ? k + j.url : j.url), j = { ...a, ...j }; const l = j.timeout, m = { ...{ onRequest: () => { }, onResponse: a => a, onTimeout: () => { } }, ...j.events }; m.onRequest(b, j); let n; if (c) n = new Promise((a, c) => { $task.fetch({ method: b, ...j }).then(b => a({ status: b.statusCode, headers: b.headers, body: b.body }), a => c(a.error)) }); else if (d || e || g) n = new Promise((a, c) => { var e = Math.ceil; const f = g ? require("request") : $httpClient; !j.timeout || g || d || (j.timeout = e(j.timeout / 1e3)), f[b.toLowerCase()](j, (b, d, e) => { b ? c(b) : a({ status: d.status || d.statusCode, headers: d.headers, body: e }) }) }); else if (f) { const a = new Request(j.url); a.method = b, a.headers = j.headers, a.body = j.body, n = new Promise((b, c) => { a.loadString().then(c => { b({ status: a.response.statusCode, headers: a.response.headers, body: c }) }).catch(a => c(a)) }) } else h && (n = new Promise((a, c) => { fetch(j.url, { method: b, headers: j.headers, body: j.body }).then(a => a.json()).then(b => a({ status: b.status, headers: b.headers, body: b.data })).catch(c) })); let o; const p = l ? new Promise((a, b) => { o = setTimeout(() => (m.onTimeout(), b(`timeout`)), l) }) : null; return (p ? Promise.race([p, n]).then(a => ("undefined" != typeof clearTimeout && clearTimeout(o), a)) : n).then(a => m.onResponse(a)) } const { isQX: c, isLoon: d, isSurge: e, isScriptable: f, isNode: g, isBrowser: h } = ENV(), i = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/, j = {}; return ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].forEach(a => j[a.toLowerCase()] = c => b(a, c)), j } function API(a = "untitled", b = !1) { const { isQX: c, isLoon: d, isSurge: e, isNode: f, isJSBox: g, isScriptable: h } = ENV(); return new class { constructor(a, b) { this.name = a, this.debug = b, this.http = HTTP(), this.env = ENV(), this.node = (() => { if (f) { const a = require("fs"); return { fs: a } } return null })(), this.initCache(); const c = (a, b) => new Promise(function (c) { setTimeout(c.bind(null, b), a) }); Promise.prototype.delay = function (a) { return this.then(function (b) { return c(a, b) }) } } initCache() { if (c && (this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}")), (d || e) && (this.cache = JSON.parse($persistentStore.read(this.name) || "{}")), f) { let a = "root.json"; this.node.fs.existsSync(a) || this.node.fs.writeFileSync(a, JSON.stringify({}), { flag: "wx" }, a => console.log(a)), this.root = {}, a = `${this.name}.json`, this.node.fs.existsSync(a) ? this.cache = JSON.parse(this.node.fs.readFileSync(`${this.name}.json`)) : (this.node.fs.writeFileSync(a, JSON.stringify({}), { flag: "wx" }, a => console.log(a)), this.cache = {}) } } persistCache() { const a = JSON.stringify(this.cache, null, 2); c && $prefs.setValueForKey(a, this.name), (d || e) && $persistentStore.write(a, this.name), f && (this.node.fs.writeFileSync(`${this.name}.json`, a, { flag: "w" }, a => console.log(a)), this.node.fs.writeFileSync("root.json", JSON.stringify(this.root, null, 2), { flag: "w" }, a => console.log(a))) } write(a, b) { if (this.log(`SET ${b}`), -1 !== b.indexOf("#")) { if (b = b.substr(1), e || d) return $persistentStore.write(a, b); if (c) return $prefs.setValueForKey(a, b); f && (this.root[b] = a) } else this.cache[b] = a; this.persistCache() } read(a) { if (this.log(`READ ${a}`), -1 !== a.indexOf("#")) { if (a = a.substr(1), e || d) return $persistentStore.read(a); if (c) return $prefs.valueForKey(a); if (f) return this.root[a] } else return this.cache[a] } delete(a) { if (this.log(`DELETE ${a}`), -1 !== a.indexOf("#")) { if (a = a.substr(1), e || d) return $persistentStore.write(null, a); if (c) return $prefs.removeValueForKey(a); f && delete this.root[a] } else delete this.cache[a]; this.persistCache() } notify(a, b = "", i = "", j = {}) { const k = j["open-url"], l = j["media-url"]; if (c && $notify(a, b, i, j), e && $notification.post(a, b, i + `${l ? "\n\u591A\u5A92\u4F53:" + l : ""}`, { url: k }), d) { let c = {}; k && (c.openUrl = k), l && (c.mediaUrl = l), "{}" === JSON.stringify(c) ? $notification.post(a, b, i) : $notification.post(a, b, i, c) } if (f || h) { const c = i + (k ? `\n点击跳转: ${k}` : "") + (l ? `\n多媒体: ${l}` : ""); if (g) { const d = require("push"); d.schedule({ title: a, body: (b ? b + "\n" : "") + c }) } else console.log(`${a}\n${b}\n${c}\n\n`) } } log(a) { this.debug && console.log(`[${this.name}] LOG: ${this.stringify(a)}`) } info(a) { console.log(`[${this.name}] INFO: ${this.stringify(a)}`) } error(a) { console.log(`[${this.name}] ERROR: ${this.stringify(a)}`) } wait(a) { return new Promise(b => setTimeout(b, a)) } done(a = {}) { c || d || e ? $done(a) : f && !g && "undefined" != typeof $context && ($context.headers = a.headers, $context.statusCode = a.statusCode, $context.body = a.body) } stringify(a) { if ("string" == typeof a || a instanceof String) return a; try { return JSON.stringify(a, null, 2) } catch (a) { return "[object Object]" } } }(a, b) }
\ No newline at end of file
From 458659b25708b6fcc86b935b9a3fa5204fbdc1b9 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 6 Apr 2024 01:18:21 +0800
Subject: [PATCH 082/105] Enable cache is set to default
---
NobyDa_BoxJs.json | 2 +-
Surge/Module/TestFlightAccount.sgmodule | 6 +++---
TestFlight/TestFlightAccount.js | 6 +++---
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/NobyDa_BoxJs.json b/NobyDa_BoxJs.json
index 43144f3728..0497b3579e 100644
--- a/NobyDa_BoxJs.json
+++ b/NobyDa_BoxJs.json
@@ -452,7 +452,7 @@
}, {
"id": "@TESTFLIGHT-ACCOUNT.EnableCache",
"name": "启用缓存",
- "val": false,
+ "val": true,
"type": "boolean",
"desc": "用于缓存APP列表, 改善列表页面加载过慢,需与\"请求超时\"配合使用。开启缓存并刷新列表后,可适当调小超时"
}, {
diff --git a/Surge/Module/TestFlightAccount.sgmodule b/Surge/Module/TestFlightAccount.sgmodule
index 2fd2bf911a..92e18a9e9b 100644
--- a/Surge/Module/TestFlightAccount.sgmodule
+++ b/Surge/Module/TestFlightAccount.sgmodule
@@ -1,14 +1,14 @@
#!name=TestFlight账户管理
#!desc=自动存储/合并多个TestFlight账户列表, 并可导出/分享TestFlight APP.
-#!arguments=请求超时:30,列表缓存:0,使用iOS列表:0,调试模式:0
-#!arguments-desc=请求超时:单位:秒\n\n列表缓存:1/0,开启/关闭。用于缓存APP列表,改善列表页面加载过慢。一般与"请求超时"配合使用,开启缓存并刷新列表后,可适当调小超时。\n\n使用iOS列表:1/0,开启/关闭。强制使用iOS应用列表,用于改善 macOS TestFlight 加载过慢。iOS用户无需开启。\n\n调试模式:1/0,开启/关闭。用于调试脚本。
+#!arguments=请求超时:30,启用缓存:1,使用iOS列表:0,调试模式:0
+#!arguments-desc=请求超时:单位:秒。默认30秒。\n\n启用缓存:1/0,开启/关闭,默认开启。用于缓存APP列表,改善列表页面加载过慢。一般与"请求超时"配合使用,开启缓存并刷新列表后,可适当调小超时。\n\n使用iOS列表:1/0,开启/关闭。强制使用iOS应用列表,用于改善 macOS TestFlight 加载过慢。iOS用户无需开启。\n\n调试模式:1/0,开启/关闭。用于调试脚本。
#!category=🐻 NobyDa
[General]
skip-proxy = %APPEND% iosapps.itunes.apple.com
[Script]
-TestFlight账户管理 = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/,requires-body=1,timeout=180,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js,debug={{{调试模式}}},argument="timeout={{{请求超时}}}&enableCache={{{列表缓存}}}&forceIOSlist={{{使用iOS列表}}}&debug={{{调试模式}}}"
+TestFlight账户管理 = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/,requires-body=1,timeout=180,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js,debug={{{调试模式}}},argument="timeout={{{请求超时}}}&enableCache={{{启用缓存}}}&forceIOSlist={{{使用iOS列表}}}&debug={{{调试模式}}}",engine=jsc
[MITM]
hostname = %APPEND% testflight.apple.com
\ No newline at end of file
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index b766aaf90b..16c3a0946e 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -3,7 +3,7 @@ TestFlight账户管理脚本
脚本作者: @NobyDa
脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
-更新时间: 2024/04/05
+更新时间: 2024/04/06
主要功能:
1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
@@ -52,7 +52,7 @@ const [obj, req, rsp] = [new Map(), $request, {}];
const [k1, k2, k3] = ['x-session-id', 'x-request-id', 'x-session-digest'];
const [list, appList] = [$.read('AccountList') || {}, $.read('AppList') || {}];
$.debug = Number(args.debug) || ($.read('Debug') === 'true');
-$.EnableCache = Number(args.enableCache) || ($.read('EnableCache') === 'true');
+$.EnableCache = !(Number(args.enableCache) === 0) || !($.read('EnableCache') === 'false');
$.ForceIOSlist = Number(args.forceIOSlist) || ($.read('ForceIOSlist') === 'true');
const cache = $.EnableCache && JSON.parse($.read('#TESTFLIGHT-ACCOUNT-CACHE') || '{}');
@@ -207,7 +207,7 @@ function QueryRequest(o) {
if ($.EnableCache && cache[option.url] && !(e).includes('key expired')) {
cache[option.url].lastUsed = Date.now();
$.log(`Account "${o}" URL "${option.url}" Using cached data`);
- $.write($.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
+ $.write(JSON.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
return { ...cache[option.url].response, account: o }
}
$.error(`Account "${o}" response failed: ${e}`);
From 6137b5add444292eb688930a8bf42e0d46bd3cf0 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 7 Apr 2024 21:11:59 +0800
Subject: [PATCH 083/105] Minor improvements.
---
Surge/Module/TestFlightAccount.sgmodule | 6 +++---
TestFlight/TestFlightAccount.js | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/Surge/Module/TestFlightAccount.sgmodule b/Surge/Module/TestFlightAccount.sgmodule
index 92e18a9e9b..8ad486b781 100644
--- a/Surge/Module/TestFlightAccount.sgmodule
+++ b/Surge/Module/TestFlightAccount.sgmodule
@@ -1,14 +1,14 @@
#!name=TestFlight账户管理
#!desc=自动存储/合并多个TestFlight账户列表, 并可导出/分享TestFlight APP.
-#!arguments=请求超时:30,启用缓存:1,使用iOS列表:0,调试模式:0
-#!arguments-desc=请求超时:单位:秒。默认30秒。\n\n启用缓存:1/0,开启/关闭,默认开启。用于缓存APP列表,改善列表页面加载过慢。一般与"请求超时"配合使用,开启缓存并刷新列表后,可适当调小超时。\n\n使用iOS列表:1/0,开启/关闭。强制使用iOS应用列表,用于改善 macOS TestFlight 加载过慢。iOS用户无需开启。\n\n调试模式:1/0,开启/关闭。用于调试脚本。
+#!arguments=请求超时:30,启用缓存:1,使用iOS列表:0,脚本引擎:jsc,调试模式:0
+#!arguments-desc=请求超时:单位:秒。默认30秒。\n\n启用缓存:1/0,开启/关闭,默认开启。用于缓存APP列表,改善列表页面加载过慢。一般与"请求超时"配合使用,开启缓存并刷新列表后,可适当调小超时。\n\n使用iOS列表:1/0,开启/关闭。强制使用iOS应用列表,用于改善 macOS TestFlight 加载过慢。iOS用户无需开启。\n\n脚本引擎:jsc/webview/auto,默认为jsc,如遇内存超限问题可调整为 auto 或 webview\n\n调试模式:1/0,开启/关闭。用于调试脚本。
#!category=🐻 NobyDa
[General]
skip-proxy = %APPEND% iosapps.itunes.apple.com
[Script]
-TestFlight账户管理 = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/,requires-body=1,timeout=180,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js,debug={{{调试模式}}},argument="timeout={{{请求超时}}}&enableCache={{{启用缓存}}}&forceIOSlist={{{使用iOS列表}}}&debug={{{调试模式}}}",engine=jsc
+TestFlight账户管理 = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v\d\/(app|account|invite)s\/,requires-body=1,timeout=180,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/TestFlight/TestFlightAccount.js,debug={{{调试模式}}},argument="timeout={{{请求超时}}}&enableCache={{{启用缓存}}}&forceIOSlist={{{使用iOS列表}}}&debug={{{调试模式}}}",engine={{{脚本引擎}}}
[MITM]
hostname = %APPEND% testflight.apple.com
\ No newline at end of file
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 16c3a0946e..a03235565b 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -3,7 +3,7 @@ TestFlight账户管理脚本
脚本作者: @NobyDa
脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
-更新时间: 2024/04/06
+更新时间: 2024/04/07
主要功能:
1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
@@ -80,7 +80,7 @@ async function runs() {
} else if (/\/install$/.test(req.url) && req.body) {
req.body = JSON.parse(req.body);
req.body.storefrontId = '143441-19,29'; //prevent regional restrictions
- req.body = $.stringify(req.body);
+ req.body = JSON.stringify(req.body);
} else if (/\/[A-Z]{200,}\/redeem$/.test(req.url)) {
return { body: ExternalAccount(req.url.split(/\/([A-Z]+)\/redeem$/)[1]) };
}
@@ -199,7 +199,7 @@ function QueryRequest(o) {
$.log(`Account "${o}" URL "${option.url}" Write data to cache`);
cache[option.url] = { response: r, lastUsed: Date.now() };
Object.keys(cache).forEach((i) => (Date.now() - (cache[i].lastUsed || 0) > 864e5 * 7) && delete cache[i]);
- $.write($.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
+ $.write(JSON.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
}
return { ...r, account: o }
})
From 16a20f1b85f54806b42a7eae1579f1518a7ffafd Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 13 Apr 2024 10:51:05 +0800
Subject: [PATCH 084/105] Reduce cache time.
---
TestFlight/TestFlightAccount.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index a03235565b..08daa4d004 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -3,7 +3,7 @@ TestFlight账户管理脚本
脚本作者: @NobyDa
脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
-更新时间: 2024/04/07
+更新时间: 2024/04/13
主要功能:
1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
@@ -198,7 +198,7 @@ function QueryRequest(o) {
if ($.EnableCache && r.body && r.body.startsWith('{')) {
$.log(`Account "${o}" URL "${option.url}" Write data to cache`);
cache[option.url] = { response: r, lastUsed: Date.now() };
- Object.keys(cache).forEach((i) => (Date.now() - (cache[i].lastUsed || 0) > 864e5 * 7) && delete cache[i]);
+ Object.keys(cache).forEach((i) => (Date.now() - (cache[i].lastUsed || 0) > 864e5 * 3) && delete cache[i]);
$.write(JSON.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
}
return { ...r, account: o }
From 56285e87ac6eeecd2aef5bf2302093146110a60d Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Mon, 15 Apr 2024 21:05:34 +0800
Subject: [PATCH 085/105] Optimize NE memory usage.
---
TestFlight/TestFlightAccount.js | 44 ++++++++++++++++++---------------
1 file changed, 24 insertions(+), 20 deletions(-)
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 08daa4d004..049d06b81b 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -3,7 +3,7 @@ TestFlight账户管理脚本
脚本作者: @NobyDa
脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
-更新时间: 2024/04/13
+更新时间: 2024/04/15
主要功能:
1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
@@ -50,11 +50,11 @@ const args = formatArgument(typeof $argument == "string" && $argument || '');
$.env.isNode ? $request = $.read('Request') : null;
const [obj, req, rsp] = [new Map(), $request, {}];
const [k1, k2, k3] = ['x-session-id', 'x-request-id', 'x-session-digest'];
-const [list, appList] = [$.read('AccountList') || {}, $.read('AppList') || {}];
+const [list, appList, cacheInfo] = [$.read('AccountList') || {}, $.read('AppList') || {}, $.read('CachedInfo') || {}];
$.debug = Number(args.debug) || ($.read('Debug') === 'true');
$.EnableCache = !(Number(args.enableCache) === 0) || !($.read('EnableCache') === 'false');
$.ForceIOSlist = Number(args.forceIOSlist) || ($.read('ForceIOSlist') === 'true');
-const cache = $.EnableCache && JSON.parse($.read('#TESTFLIGHT-ACCOUNT-CACHE') || '{}');
+$.RequestTimeout = Number(args.timeout || $.read('Timeout')) || 30;
runs()
.then((resp) => {
@@ -118,8 +118,10 @@ function formatArgument(s) {
function ChangeHeaders(id) {
const re = JSON.parse(JSON.stringify(req)); //easy deep copy
- re.timeout = (Number(args.timeout || $.read('Timeout')) || 30) * 1000;
- re.insecure = true;
+ re.url = re.url.replace(/:\/\/.+?\//, '://testflight.apple.com/'); //prevent cdn issues
+ re.timeout = $.RequestTimeout * 1000;
+ re.insecure = true; //skip ssl
+ re['X-Surge-Skip-Scripting'] = true; //prevent shadowrocket loopback issues
if ($.ForceIOSlist && req.url.endsWith('/apps') && re.headers['user-agent'].includes('Mac')) {
re.headers['user-agent'] = 'Oasis/3.5.1 OasisBuild/425.2 iOS/17.4 model/iPhone16,2 hwp/t8130 build/21E219 (6; dt:311) AMS/1 TSE/0';
}
@@ -130,9 +132,6 @@ function ChangeHeaders(id) {
re.headers[k3] = list[id][k3];
re.url = re.url.replace(/\/[a-z0-9-]{36}\//, `/${id}/`);
}
- if ($.env.isShadowrocket) {
- re.proxy = false; //prevent shadowrocket infinite loop
- }
delete re.headers['if-none-match']; //prevent 304
delete re.headers['content-length'];
$.log(`Send request: ${$.stringify(re)}`);
@@ -182,9 +181,10 @@ function ChangeBody(resp) {
function QueryRequest(o) {
const option = ChangeHeaders(o);
+ const needCache = $.EnableCache && (option.url.endsWith('/apps') || /\/apps\/\d+\/builds\/\d+$/.test(req.url));
return $.http[req.method.toLowerCase()](option)
.then(r => {
- $.log(`Account "${o}" response: status=${r.status}, body=${Boolean(r.body)}`);
+ $.log(`URL "${option.url}" response: status=${r.status}, body=${Boolean(r.body)}`);
if (r.status == 401 && o) {
if (list[o].InvalidKey >= 2) { //prevent misjudgment
delete list[o];
@@ -195,22 +195,26 @@ function QueryRequest(o) {
$.notify('TestFlight Account', '', `Account ID "${o}" key expired ⚠️`);
throw 'key expired ⚠️';
}
- if ($.EnableCache && r.body && r.body.startsWith('{')) {
- $.log(`Account "${o}" URL "${option.url}" Write data to cache`);
- cache[option.url] = { response: r, lastUsed: Date.now() };
- Object.keys(cache).forEach((i) => (Date.now() - (cache[i].lastUsed || 0) > 864e5 * 3) && delete cache[i]);
- $.write(JSON.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
+ if (needCache && r.status == 200 && r.body && r.body.startsWith('{')) {
+ const cacheKey = (cacheInfo[option.url] && cacheInfo[option.url].key) || `TESTFLIGHT-ACCOUNT-${letterEncode(option.url.split(/\/\/.+?\/(.+)/)[1])}`;
+ $.log(`Write to cache, URL "${option.url}", READ KEY "${cacheKey}"`);
+ cacheInfo[option.url] = { key: cacheKey, lastUsed: Date.now() };
+ Object.keys(cacheInfo).forEach((i) => (Date.now() - (cacheInfo[i].lastUsed || 0) > 864e5 * 7) && delete cacheInfo[i] && $.delete(`#${cacheKey}`));
+ $.write(cacheInfo, 'CachedInfo');
+ $.write(JSON.stringify(r), `#${cacheKey}`);
}
return { ...r, account: o }
})
.catch(e => {
- if ($.EnableCache && cache[option.url] && !(e).includes('key expired')) {
- cache[option.url].lastUsed = Date.now();
- $.log(`Account "${o}" URL "${option.url}" Using cached data`);
- $.write(JSON.stringify(cache), '#TESTFLIGHT-ACCOUNT-CACHE');
- return { ...cache[option.url].response, account: o }
+ if (needCache && cacheInfo[option.url] && !(e).includes('key expired')) {
+ $.log(`URL "${option.url}" Try using cached data`);
+ const cachedData = $.read(`#${cacheInfo[option.url].key}`);
+ cacheInfo[option.url].lastUsed = Date.now();
+ !cachedData ? delete cacheInfo[option.url] : null;
+ $.write(cacheInfo, 'CachedInfo');
+ return { ...JSON.parse(cachedData || '{}'), account: o }
}
- $.error(`Account "${o}" response failed: ${e}`);
+ $.error(`URL "${option.url}" response failed: ${e}`);
return { account: o }
})
}
From d10c2c7f218169d9f6aa30917fdffc11571bb560 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 26 Apr 2024 14:39:53 +0800
Subject: [PATCH 086/105] bug fixes.
---
TestFlight/TestFlightAccount.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/TestFlight/TestFlightAccount.js b/TestFlight/TestFlightAccount.js
index 049d06b81b..8b4f63cf46 100644
--- a/TestFlight/TestFlightAccount.js
+++ b/TestFlight/TestFlightAccount.js
@@ -3,7 +3,7 @@ TestFlight账户管理脚本
脚本作者: @NobyDa
脚本兼容: Surge4、QuantumultX、Loon(2.1.20 413+)
-更新时间: 2024/04/15
+更新时间: 2024/04/26
主要功能:
1. 自动存储多个TestFlight账户,并自动合并APP列表,避免切换账户。
@@ -199,7 +199,7 @@ function QueryRequest(o) {
const cacheKey = (cacheInfo[option.url] && cacheInfo[option.url].key) || `TESTFLIGHT-ACCOUNT-${letterEncode(option.url.split(/\/\/.+?\/(.+)/)[1])}`;
$.log(`Write to cache, URL "${option.url}", READ KEY "${cacheKey}"`);
cacheInfo[option.url] = { key: cacheKey, lastUsed: Date.now() };
- Object.keys(cacheInfo).forEach((i) => (Date.now() - (cacheInfo[i].lastUsed || 0) > 864e5 * 7) && delete cacheInfo[i] && $.delete(`#${cacheKey}`));
+ Object.keys(cacheInfo).forEach((i) => (Date.now() - (cacheInfo[i].lastUsed || 0) > 864e5 * 3) && $.delete(`#${cacheInfo[i].key}`) && delete cacheInfo[i]); //clear unused cache for 3 days
$.write(cacheInfo, 'CachedInfo');
$.write(JSON.stringify(r), `#${cacheKey}`);
}
From 75023e3eb98002f49dd36ff931057a443b10d65e Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sat, 4 May 2024 14:09:02 +0800
Subject: [PATCH 087/105] Add disney+ rating script.
---
Disney/DisneyRating.js | 253 +++++++++++++++++++++++++++++
QuantumultX/DisneyRating.snippet | 7 +
Surge/Module/DisneyRating.sgmodule | 11 ++
3 files changed, 271 insertions(+)
create mode 100644 Disney/DisneyRating.js
create mode 100644 QuantumultX/DisneyRating.snippet
create mode 100644 Surge/Module/DisneyRating.sgmodule
diff --git a/Disney/DisneyRating.js b/Disney/DisneyRating.js
new file mode 100644
index 0000000000..8ea74acf29
--- /dev/null
+++ b/Disney/DisneyRating.js
@@ -0,0 +1,253 @@
+/*********************************
+Disney+ 显示IMDb评分 / 烂番茄评分 / 豆瓣评分
+
+脚本作者: @NobyDa
+脚本兼容: Surge、QuantumultX、Loon
+系统兼容: iOS14+
+更新时间: 2024/05/04
+脚本参考: https://github.com/yichahucha/surge/blob/master/nf_rating.js
+
+Surge模块:
+https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/DisneyRating.sgmodule
+
+QuantumultX重写引用:
+https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/DisneyRating.snippet
+
+*********************************/
+
+const $tool = new Tool();
+const consoleLog = false;
+let obj = $response.body;
+let IMDbApikeys = IMDbApikeyList();
+let IMDbApikey = $tool.read("ImdbApikeyCacheKey");
+if (!IMDbApikey) {
+ updateIMDbApikey();
+}
+
+const requestRatings = async () => {
+ if (consoleLog) console.log("Disney Original Body:\n" + obj);
+ obj = JSON.parse(obj);
+ const sliced = obj?.data?.page?.actions?.[0]?.internalTitle?.split(' - ');
+ let title = sliced?.[0] || obj?.data?.page?.visuals?.title;
+ if (title) {
+ title = title.replace(/.+?:\s|\s?\(.+?\)\s?/g,'');
+ } else {
+ throw 'NO TITLE';
+ }
+ const year = obj?.data?.page?.visuals?.metastringParts?.releaseYearRange?.startYear;
+ const type = (sliced?.[1]?.startsWith('s') && 'series') || (sliced?.[1] == 'movie' && 'movie');
+ const IMDb = await requestIMDbRating(title, year, type);
+ const Douban = await requestDoubanRating(IMDb.id);
+ const IMDbrating = IMDb.msg.rating;
+ const tomatoes = IMDb.msg.tomatoes;
+ const country = IMDb.msg.country;
+ // const awards = IMDb.msg.awards;
+ const doubanRating = Douban.rating;
+ // const message = `${awards.length > 0 ? awards + "\n" : ""}${country}\n${IMDbrating}\n${doubanRating}${tomatoes.length > 0 ? "\n" + tomatoes + "\n" : "\n"}`;
+ return { country, tomatoes, IMDbrating, doubanRating };
+}
+
+requestRatings()
+ .then(data => {
+ if (obj?.data?.page?.visuals) {
+ obj.data.page.visuals.promoLabel = {
+ promoLabelType: "generic",
+ header: `${data.country}${data.tomatoes ? `\n${data.tomatoes}` : ``}`,
+ subheader: `${data.IMDbrating}${data.doubanRating ? `\n${data.doubanRating}` : ``}`
+ }
+ }
+ if (consoleLog) console.log("Disney Modified Body:\n" + JSON.stringify(obj));
+ })
+ .catch(error => console.log(`ERROR: ${error}`))
+ .finally(() => $done({ body: typeof obj == 'object' ? JSON.stringify(obj) : obj }));
+
+function requestDoubanRating(imdbId) {
+ return new Promise(function (resolve, reject) {
+ const url = `https://www.douban.com/search?cat=1002&q=${imdbId}`;
+ if (consoleLog) console.log("Disney Douban Rating URL:\n" + url);
+ $tool.get(url, function (error, response, data) {
+ if (!error) {
+ if (consoleLog) console.log("Disney Douban Rating Data:\n" + data);
+ if (response.status == 200) {
+ const rating = get_douban_rating_message(data);
+ resolve({ rating });
+ } else {
+ resolve({});
+ }
+ } else {
+ console.log("Disney Douban Rating Error: " + error);
+ resolve({});
+ }
+ });
+ });
+}
+
+function requestIMDbRating(title, year, type) {
+ return new Promise(function (resolve, reject) {
+ let url = "https://www.omdbapi.com/?t=" + encodeURIComponent(title) + "&apikey=" + IMDbApikey;
+ if (year) url += "&y=" + year;
+ if (type) url += "&type=" + type;
+ if (consoleLog) console.log("Disney IMDb Rating URL:\n" + url);
+ $tool.get(url, function (error, response, data) {
+ if (!error) {
+ if (consoleLog) console.log("Disney IMDb Rating Data:\n" + data);
+ if (response.status == 200) {
+ const obj = JSON.parse(data);
+ if (obj.Response == "True") {
+ const id = obj.imdbID;
+ const msg = get_IMDb_message(obj);
+ resolve({ id, msg });
+ } else {
+ reject(`Title [${title}] IMDb data not found`);
+ }
+ } else if (response.status == 401) {
+ if (IMDbApikeys.length > 1) {
+ updateIMDbApikey();
+ requestIMDbRating(title, year, type);
+ } else {
+ reject(`IMDb Key invalid`);
+ }
+ } else {
+ reject(`Unknown status: ${response.status}, Data: ${data}`);
+ }
+ } else {
+ reject(`IMDB data response failed: ${error}`);
+ }
+ });
+ });
+}
+
+function updateIMDbApikey() {
+ if (IMDbApikey) IMDbApikeys.splice(IMDbApikeys.indexOf(IMDbApikey), 1);
+ const index = Math.floor(Math.random() * IMDbApikeys.length);
+ IMDbApikey = IMDbApikeys[index];
+ $tool.write(IMDbApikey, "ImdbApikeyCacheKey");
+}
+
+function get_IMDb_message(data) {
+ let rating_message = "IMDb: ⭐️ N/A";
+ let tomatoes_message = "";
+ let country_message = "";
+ let ratings = data.Ratings;
+ let awards_message = "";
+ if (data.Awards && data.Awards != "N/A") {
+ awards_message = "🏆 " + data.Awards;
+ }
+ if (ratings.length > 0) {
+ const imdb_source = ratings[0]["Source"];
+ if (imdb_source == "Internet Movie Database") {
+ const imdb_votes = data.imdbVotes;
+ const imdb_rating = ratings[0]["Value"];
+ rating_message = "IMDb: ⭐️ " + imdb_rating + " " + imdb_votes;
+ if (data.Type == "movie") {
+ if (ratings.length > 1) {
+ const source = ratings[1]["Source"];
+ if (source == "Rotten Tomatoes") {
+ const tomatoes = ratings[1]["Value"];
+ tomatoes_message = "Tomatoes: 🍅 " + tomatoes;
+ }
+ }
+ }
+ }
+ }
+ country_message = get_country_message(data.Country);
+ return { rating: rating_message, tomatoes: tomatoes_message, country: country_message, awards: awards_message }
+}
+
+function get_douban_rating_message(data) {
+ const s = data.replace(/\n| |\d{2}/g, '')
+ .match(/\[(\u7535\u5f71|\u7535\u89c6\u5267)\].+?subject-cast\">.+?<\/span>/g);
+ const average = s ? s[0].split(/">(\d\.\d))[1] || '' : '';
+ const numRaters = s ? s[0].split(/(\d+)\u4eba\u8bc4\u4ef7/)[1] || '' : '';
+ const rating_message = `Douban: ⭐️ ${average ? average + "/10" : "N/A"} ${!numRaters ? "" : parseFloat(numRaters).toLocaleString()}`;
+ return average && rating_message;
+}
+
+function get_country_message(data) {
+ const country = data;
+ const countrys = country.split(", ");
+ let emoji_country = "";
+ countrys.forEach(item => {
+ emoji_country += countryEmoji(item) + " " + item + ", ";
+ });
+ return emoji_country.slice(0, -2);
+}
+
+// function errorTip() {
+// return { noData: "⭐️ N/A", error: "❌ N/A" }
+// }
+
+function IMDbApikeyList() {
+ const apikeys = [
+ "f75e0253", "d8bb2d6b",
+ "ae64ce8d", "7218d678",
+ "b2650e38", "8c4a29ab",
+ "9bd135c2", "953dbabe",
+ "1a66ef12", "3e7ea721",
+ "457fc4ff", "d2131426",
+ "9cc1a9b7", "e53c2c11",
+ "f6dfce0e", "b9db622f",
+ "e6bde2b9", "d324dbab",
+ "d7904fa3", "aeaf88b9",
+ "4e89234e",];
+ return apikeys;
+}
+
+function countryEmoji(name) { const emojiMap = { "Chequered": "🏁", "Triangular": "🚩", "Crossed": "🎌", "Black": "🏴", "White": "🏳", "Rainbow": "🏳️🌈", "Pirate": "🏴☠️", "Ascension Island": "🇦🇨", "Andorra": "🇦🇩", "United Arab Emirates": "🇦🇪", "Afghanistan": "🇦🇫", "Antigua & Barbuda": "🇦🇬", "Anguilla": "🇦🇮", "Albania": "🇦🇱", "Armenia": "🇦🇲", "Angola": "🇦🇴", "Antarctica": "🇦🇶", "Argentina": "🇦🇷", "American Samoa": "🇦🇸", "Austria": "🇦🇹", "Australia": "🇦🇺", "Aruba": "🇦🇼", "Åland Islands": "🇦🇽", "Azerbaijan": "🇦🇿", "Bosnia & Herzegovina": "🇧🇦", "Barbados": "🇧🇧", "Bangladesh": "🇧🇩", "Belgium": "🇧🇪", "Burkina Faso": "🇧🇫", "Bulgaria": "🇧🇬", "Bahrain": "🇧🇭", "Burundi": "🇧🇮", "Benin": "🇧🇯", "St. Barthélemy": "🇧🇱", "Bermuda": "🇧🇲", "Brunei": "🇧🇳", "Bolivia": "🇧🇴", "Caribbean Netherlands": "🇧🇶", "Brazil": "🇧🇷", "Bahamas": "🇧🇸", "Bhutan": "🇧🇹", "Bouvet Island": "🇧🇻", "Botswana": "🇧🇼", "Belarus": "🇧🇾", "Belize": "🇧🇿", "Canada": "🇨🇦", "Cocos (Keeling) Islands": "🇨🇨", "Congo - Kinshasa": "🇨🇩", "Congo": "🇨🇩", "Central African Republic": "🇨🇫", "Congo - Brazzaville": "🇨🇬", "Switzerland": "🇨🇭", "Côte d’Ivoire": "🇨🇮", "Cook Islands": "🇨🇰", "Chile": "🇨🇱", "Cameroon": "🇨🇲", "China": "🇨🇳", "Colombia": "🇨🇴", "Clipperton Island": "🇨🇵", "Costa Rica": "🇨🇷", "Cuba": "🇨🇺", "Cape Verde": "🇨🇻", "Curaçao": "🇨🇼", "Christmas Island": "🇨🇽", "Cyprus": "🇨🇾", "Czechia": "🇨🇿", "Czech Republic": "🇨🇿", "Germany": "🇩🇪", "Diego Garcia": "🇩🇬", "Djibouti": "🇩🇯", "Denmark": "🇩🇰", "Dominica": "🇩🇲", "Dominican Republic": "🇩🇴", "Algeria": "🇩🇿", "Ceuta & Melilla": "🇪🇦", "Ecuador": "🇪🇨", "Estonia": "🇪🇪", "Egypt": "🇪🇬", "Western Sahara": "🇪🇭", "Eritrea": "🇪🇷", "Spain": "🇪🇸", "Ethiopia": "🇪🇹", "European Union": "🇪🇺", "Finland": "🇫🇮", "Fiji": "🇫🇯", "Falkland Islands": "🇫🇰", "Micronesia": "🇫🇲", "Faroe Islands": "🇫🇴", "France": "🇫🇷", "Gabon": "🇬🇦", "United Kingdom": "🇬🇧", "UK": "🇬🇧", "Grenada": "🇬🇩", "Georgia": "🇬🇪", "French Guiana": "🇬🇫", "Guernsey": "🇬🇬", "Ghana": "🇬🇭", "Gibraltar": "🇬🇮", "Greenland": "🇬🇱", "Gambia": "🇬🇲", "Guinea": "🇬🇳", "Guadeloupe": "🇬🇵", "Equatorial Guinea": "🇬🇶", "Greece": "🇬🇷", "South Georgia & South Sandwich Is lands": "🇬🇸", "Guatemala": "🇬🇹", "Guam": "🇬🇺", "Guinea-Bissau": "🇬🇼", "Guyana": "🇬🇾", "Hong Kong SAR China": "🇭🇰", "Hong Kong": "🇭🇰", "Heard & McDonald Islands": "🇭🇲", "Honduras": "🇭🇳", "Croatia": "🇭🇷", "Haiti": "🇭🇹", "Hungary": "🇭🇺", "Canary Islands": "🇮🇨", "Indonesia": "🇮🇩", "Ireland": "🇮🇪", "Israel": "🇮🇱", "Isle of Man": "🇮🇲", "India": "🇮🇳", "British Indian Ocean Territory": "🇮🇴", "Iraq": "🇮🇶", "Iran": "🇮🇷", "Iceland": "🇮🇸", "Italy": "🇮🇹", "Jersey": "🇯🇪", "Jamaica": "🇯🇲", "Jordan": "🇯🇴", "Japan": "🇯🇵", "Kenya": "🇰🇪", "Kyrgyzstan": "🇰🇬", "Cambodia": "🇰🇭", "Kiribati": "🇰🇮", "Comoros": "🇰🇲", "St. Kitts & Nevis": "🇰🇳", "North Korea": "🇰🇵", "South Korea": "🇰🇷", "Kuwait": "🇰🇼", "Cayman Islands": "🇰🇾", "Kazakhstan": "🇰🇿", "Laos": "🇱🇦", "Lebanon": "🇱🇧", "St. Lucia": "🇱🇨", "Liechtenstein": "🇱🇮", "Sri Lanka": "🇱🇰", "Liberia": "🇱🇷", "Lesotho": "🇱🇸", "Lithuania": "🇱🇹", "Luxembourg": "🇱🇺", "Latvia": "🇱🇻", "Libya": "🇱🇾", "Morocco": "🇲🇦", "Monaco": "🇲🇨", "Moldova": "🇲🇩", "Montenegro": "🇲🇪", "St. Martin": "🇲🇫", "Madagascar": "🇲🇬", "Marshall Islands": "🇲🇭", "North Macedonia": "🇲🇰", "Mali": "🇲🇱", "Myanmar (Burma)": "🇲🇲", "Mongolia": "🇲🇳", "Macau Sar China": "🇲🇴", "Northern Mariana Islands": "🇲🇵", "Martinique": "🇲🇶", "Mauritania": "🇲🇷", "Montserrat": "🇲🇸", "Malta": "🇲🇹", "Mauritius": "🇲🇺", "Maldives": "🇲🇻", "Malawi": "🇲🇼", "Mexico": "🇲🇽", "Malaysia": "🇲🇾", "Mozambique": "🇲🇿", "Namibia": "🇳🇦", "New Caledonia": "🇳🇨", "Niger": "🇳🇪", "Norfolk Island": "🇳🇫", "Nigeria": "🇳🇬", "Nicaragua": "🇳🇮", "Netherlands": "🇳🇱", "Norway": "🇳🇴", "Nepal": "🇳🇵", "Nauru": "🇳🇷", "Niue": "🇳🇺", "New Zealand": "🇳🇿", "Oman": "🇴🇲", "Panama": "🇵🇦", "Peru": "🇵🇪", "French Polynesia": "🇵🇫", "Papua New Guinea": "🇵🇬", "Philippines": "🇵🇭", "Pakistan": "🇵🇰", "Poland": "🇵🇱", "St. Pierre & Miquelon": "🇵🇲", "Pitcairn Islands": "🇵🇳", "Puerto Rico": "🇵🇷", "Palestinian Territories": "🇵🇸", "Portugal": "🇵🇹", "Palau": "🇵🇼", "Paraguay": "🇵🇾", "Qatar": "🇶🇦", "Réunion": "🇷🇪", "Romania": "🇷🇴", "Serbia": "🇷🇸", "Russia": "🇷🇺", "Rwanda": "🇷🇼", "Saudi Arabia": "🇸🇦", "Solomon Islands": "🇸🇧", "Seychelles": "🇸🇨", "Sudan": "🇸🇩", "Sweden": "🇸🇪", "Singapore": "🇸🇬", "St. Helena": "🇸🇭", "Slovenia": "🇸🇮", "Svalbard & Jan Mayen": "🇸🇯", "Slovakia": "🇸🇰", "Sierra Leone": "🇸🇱", "San Marino": "🇸🇲", "Senegal": "🇸🇳", "Somalia": "🇸🇴", "Suriname": "🇸🇷", "South Sudan": "🇸🇸", "São Tomé & Príncipe": "🇸🇹", "El Salvador": "🇸🇻", "Sint Maarten": "🇸🇽", "Syria": "🇸🇾", "Swaziland": "🇸🇿", "Tristan Da Cunha": "🇹🇦", "Turks & Caicos Islands": "🇹🇨", "Chad": "🇹🇩", "French Southern Territories": "🇹🇫", "Togo": "🇹🇬", "Thailand": "🇹🇭", "Tajikistan": "🇹🇯", "Tokelau": "🇹🇰", "Timor-Leste": "🇹🇱", "Turkmenistan": "🇹🇲", "Tunisia": "🇹🇳", "Tonga": "🇹🇴", "Turkey": "🇹🇷", "Trinidad & Tobago": "🇹🇹", "Tuvalu": "🇹🇻", "Taiwan": "🇨🇳", "Tanzania": "🇹🇿", "Ukraine": "🇺🇦", "Uganda": "🇺🇬", "U.S. Outlying Islands": "🇺🇲", "United Nations": "🇺🇳", "United States": "🇺🇸", "USA": "🇺🇸", "Uruguay": "🇺🇾", "Uzbekistan": "🇺🇿", "Vatican City": "🇻🇦", "St. Vincent & Grenadines": "🇻🇨", "Venezuela": "🇻🇪", "British Virgin Islands": "🇻🇬", "U.S. Virgin Islands": "🇻🇮", "Vietnam": "🇻🇳", "Vanuatu": "🇻🇺", "Wallis & Futuna": "🇼🇫", "Samoa": "🇼🇸", "Kosovo": "🇽🇰", "Yemen": "🇾🇪", "Mayotte": "🇾🇹", "South Africa": "🇿🇦", "Zambia": "🇿🇲", "Zimbabwe": "🇿🇼", "England": "🏴", "Scotland": "🏴", "Wales": "🏴", }; return emojiMap[name] ? emojiMap[name] : emojiMap["Chequered"] }
+
+function Tool() {
+ _node = (() => {
+ if (typeof require == "function") {
+ const request = require('request')
+ return ({ request })
+ } else {
+ return (null)
+ }
+ })()
+ _isSurge = typeof $httpClient != "undefined"
+ _isQuanX = typeof $task != "undefined"
+ this.isSurge = _isSurge
+ this.isQuanX = _isQuanX
+ this.isResponse = typeof $response != "undefined"
+ this.notify = (title, subtitle, message) => {
+ if (_isQuanX) $notify(title, subtitle, message)
+ if (_isSurge) $notification.post(title, subtitle, message)
+ if (_node) console.log(JSON.stringify({ title, subtitle, message }));
+ }
+ this.write = (value, key) => {
+ if (_isQuanX) return $prefs.setValueForKey(value, key)
+ if (_isSurge) return $persistentStore.write(value, key)
+ }
+ this.read = (key) => {
+ if (_isQuanX) return $prefs.valueForKey(key)
+ if (_isSurge) return $persistentStore.read(key)
+ }
+ this.get = (options, callback) => {
+ if (_isQuanX) {
+ if (typeof options == "string") options = { url: options }
+ options["method"] = "GET"
+ $task.fetch(options).then(response => { callback(null, _status(response), response.body) }, reason => callback(reason.error, null, null))
+ }
+ if (_isSurge) $httpClient.get(options, (error, response, body) => { callback(error, _status(response), body) })
+ if (_node) _node.request(options, (error, response, body) => { callback(error, _status(response), body) })
+ }
+ this.post = (options, callback) => {
+ if (_isQuanX) {
+ if (typeof options == "string") options = { url: options }
+ options["method"] = "POST"
+ $task.fetch(options).then(response => { callback(null, _status(response), response.body) }, reason => callback(reason.error, null, null))
+ }
+ if (_isSurge) $httpClient.post(options, (error, response, body) => { callback(error, _status(response), body) })
+ if (_node) _node.request.post(options, (error, response, body) => { callback(error, _status(response), body) })
+ }
+ _status = (response) => {
+ if (response) {
+ if (response.status) {
+ response["statusCode"] = response.status
+ } else if (response.statusCode) {
+ response["status"] = response.statusCode
+ }
+ }
+ return response
+ }
+}
diff --git a/QuantumultX/DisneyRating.snippet b/QuantumultX/DisneyRating.snippet
new file mode 100644
index 0000000000..8cef49cb34
--- /dev/null
+++ b/QuantumultX/DisneyRating.snippet
@@ -0,0 +1,7 @@
+# Disney+剧集页显示IMDb / 烂番茄 / 豆瓣评分
+# https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/DisneyRating.snippet
+
+
+^https:\/\/disney\.api\.edge\.bamgrid\.com\/explore\/v\d\.\d\/page\/entity- url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Disney/DisneyRating.js
+
+hostname = disney.api.edge.bamgrid.com
\ No newline at end of file
diff --git a/Surge/Module/DisneyRating.sgmodule b/Surge/Module/DisneyRating.sgmodule
new file mode 100644
index 0000000000..f7ec39c985
--- /dev/null
+++ b/Surge/Module/DisneyRating.sgmodule
@@ -0,0 +1,11 @@
+#!name=Disney+评分
+#!desc=Disney+剧集页显示IMDb / 烂番茄 / 豆瓣评分
+#!arguments=脚本引擎:jsc,调试模式:0
+#!arguments-desc=脚本引擎:jsc/webview/auto,默认jsc。\n\n调试模式:1/0,开启/关闭。
+#!category=🐻 NobyDa
+
+[Script]
+DisneyRating = type=http-response,pattern=^https:\/\/disney\.api\.edge\.bamgrid\.com\/explore\/v\d\.\d\/page\/entity-,requires-body=1,max-size=0,binary-body-mode=0,debug={{{调试模式}}},script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Disney/DisneyRating.js,engine={{{脚本引擎}}}
+
+[MITM]
+hostname = %APPEND% disney.api.edge.bamgrid.com
\ No newline at end of file
From 1f2ceb1cfa36935c444fcf4a252572efe35e067a Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 5 May 2024 15:05:20 +0800
Subject: [PATCH 088/105] Update google CAPTCHA
---
Surge/JS/Google_CAPTCHA.js | 2 +-
Surge/Module/GoogleCAPTCHA.sgmodule | 11 +++++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
create mode 100644 Surge/Module/GoogleCAPTCHA.sgmodule
diff --git a/Surge/JS/Google_CAPTCHA.js b/Surge/JS/Google_CAPTCHA.js
index 36d03725b6..84e8554fe2 100644
--- a/Surge/JS/Google_CAPTCHA.js
+++ b/Surge/JS/Google_CAPTCHA.js
@@ -6,7 +6,7 @@ Google搜索内容时并发使用多个策略(组),以避免可能出现的人
Surge脚本配置:
[Script]
-Google CAPTCHA = type=http-response,pattern=^https:\/\/www\.google\.com(\.[a-z]+|)\/search\?(client=[a-z-]+&|)q=,requires-body=1,debug=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js,max-size=0,timeout=10,ability=http-client-policy,argument=^(🇸🇬|🇭🇰)\s.*\d+$
+Google CAPTCHA = type=http-response,pattern=^https:\/\/www\.google\.com(?:\.[a-z]+|)\/(?:search\?(?:|.+?&)q=|$),requires-body=1,debug=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js,max-size=0,timeout=10,ability=http-client-policy,argument=^(🇸🇬|🇭🇰)\s.*\d+$
[MITM]
hostname = www.google.com*
diff --git a/Surge/Module/GoogleCAPTCHA.sgmodule b/Surge/Module/GoogleCAPTCHA.sgmodule
new file mode 100644
index 0000000000..de44339b46
--- /dev/null
+++ b/Surge/Module/GoogleCAPTCHA.sgmodule
@@ -0,0 +1,11 @@
+#!name=Google人机验证
+#!desc=Google搜索内容时并发使用多个策略/策略组,以避免可能出现的人机验证。注意:需要在模块参数填写策略/策略组名的正则表达式。
+#!arguments=策略正则,脚本引擎:auto
+#!arguments-desc=策略正则:策略/策略组名的正则表达式,例如 ^(🇸🇬|🇭🇰)\s.*\d+$ 如需同时使用所有策略/策略组可使用 .+ 表示。\n\n脚本引擎:jsc/webview/auto,默认auto。
+#!category=🐻 NobyDa
+
+[Script]
+Google CAPTCHA = type=http-response,pattern=^https:\/\/www\.google\.com(?:\.[a-z]+|)\/(?:search\?(?:|.+?&)q=|$),requires-body=1,debug=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js,max-size=0,timeout=10,ability=http-client-policy,engine={{{脚本引擎}}},argument={{{策略正则}}}
+
+[MITM]
+hostname = www.google.com*
\ No newline at end of file
From b929f675231f6499f454ca231de4ecc77822f33d Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 5 May 2024 17:25:20 +0800
Subject: [PATCH 089/105] Fix module issues.
---
Surge/Module/GoogleCAPTCHA.sgmodule | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Surge/Module/GoogleCAPTCHA.sgmodule b/Surge/Module/GoogleCAPTCHA.sgmodule
index de44339b46..88baccec9d 100644
--- a/Surge/Module/GoogleCAPTCHA.sgmodule
+++ b/Surge/Module/GoogleCAPTCHA.sgmodule
@@ -1,11 +1,11 @@
#!name=Google人机验证
#!desc=Google搜索内容时并发使用多个策略/策略组,以避免可能出现的人机验证。注意:需要在模块参数填写策略/策略组名的正则表达式。
#!arguments=策略正则,脚本引擎:auto
-#!arguments-desc=策略正则:策略/策略组名的正则表达式,例如 ^(🇸🇬|🇭🇰)\s.*\d+$ 如需同时使用所有策略/策略组可使用 .+ 表示。\n\n脚本引擎:jsc/webview/auto,默认auto。
+#!arguments-desc=策略正则:策略/策略组名的正则表达式,例如:\n^(🇸🇬|🇭🇰)\s.*\d+$ 如需同时使用所有策略/策略组可使用 .+ 表示。\n\n脚本引擎:jsc/webview/auto,默认auto。
#!category=🐻 NobyDa
[Script]
Google CAPTCHA = type=http-response,pattern=^https:\/\/www\.google\.com(?:\.[a-z]+|)\/(?:search\?(?:|.+?&)q=|$),requires-body=1,debug=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js,max-size=0,timeout=10,ability=http-client-policy,engine={{{脚本引擎}}},argument={{{策略正则}}}
[MITM]
-hostname = www.google.com*
\ No newline at end of file
+hostname = %APPEND% www.google.com*
\ No newline at end of file
From be728727d1876f652ef3f0d97ddd20a763beb249 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Tue, 7 May 2024 19:47:22 +0800
Subject: [PATCH 090/105] Fix benchmark domain issues.
---
Rule-Storage/Rule-Storage.js | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/Rule-Storage/Rule-Storage.js b/Rule-Storage/Rule-Storage.js
index 297ed92983..19ccd4ef91 100644
--- a/Rule-Storage/Rule-Storage.js
+++ b/Rule-Storage/Rule-Storage.js
@@ -1,6 +1,6 @@
/*
Surge规则自动生成脚本
-更新时间:2024/02/24
+更新时间:2024/05/07
需按照博客内教程配合使用:
https://nobyda.github.io/2024/02/24/Surge_Rule_Storage
@@ -19,12 +19,13 @@ args.key = args.key || 'Rule-Storage';
(async () => {
const host = $request.hostname.toLowerCase();
- if (['127.0.0.1', '0.0.0.0'].filter((v) => [...$request.dnsResult.v4Addresses].includes(v)).length) {
+ const inHost = $request.listenPort == 6152 && !$request.sourcePort && !$request.processPath && /^[a-z0-9]{10}\.[a-z]+$/.test(host); //Prevent benchmark
+ if (['127.0.0.1', '0.0.0.0'].filter((v) => [...($request.dnsResult || {}).v4Addresses || []].includes(v)).length) {
// DNS poisoning
args.matched = false;
args.region = 'global';
}
- if (!/\d$|:/.test(host) && host.includes('.')) {
+ if (!/\d$|:/.test(host) && host.includes('.') && !inHost) {
const data = JSON.parse($persistentStore.read(args.key) || '{}');
const saved_rules = $persistentStore.read(`${args.key}-${args.region}`);
if (!evalRules(host, saved_rules)) {
@@ -38,14 +39,14 @@ args.key = args.key || 'Rule-Storage';
$persistentStore.write(text, `${args.key}-${args.region}`)
}
}
- return $persistentStore.write(JSON.stringify(data, null, 2), args.key)
+ return $persistentStore.write(JSON.stringify(data), args.key)
}
})().catch((e) => $notification.post(args.key, ``, e.message || e))
.finally(() => $done({ matched: Boolean(args.matched) }));
function saveDecision(host_name, content = {}) {
for (const i in content) {
- if (Date.now() - content[i].update_time > 86400000 * 30) {
+ if (Date.now() - content[i].update_time > 86400000 * (args.cacheDays || 30)) {
delete content[i];
}
}
From 782fa3630d5a59d8935a7ebff3fd1cfe09e72203 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 9 May 2024 19:25:14 +0800
Subject: [PATCH 091/105] Add ctrip script.
---
Ctrip-DailyBonus/Ctrip.js | 138 ++++++++++++++++++++++++++++++++++++++
1 file changed, 138 insertions(+)
create mode 100644 Ctrip-DailyBonus/Ctrip.js
diff --git a/Ctrip-DailyBonus/Ctrip.js b/Ctrip-DailyBonus/Ctrip.js
new file mode 100644
index 0000000000..c6381521af
--- /dev/null
+++ b/Ctrip-DailyBonus/Ctrip.js
@@ -0,0 +1,138 @@
+/********************************
+携程旅行签到脚本
+配置脚本后登陆”携程旅行“微信小程序即可获取账号授权。支持多账号,支持Node.js
+
+脚本作者:@NobyDa
+更新时间:2024/05/09
+平台兼容:Surge / QuantumultX / Loon / Stash / Node.js
+模块依赖(Node.js):iconv-lite / got@11.8.3 / tough-cookie
+环境变量(Node.js):CTRIP_AUTH / CTRIP_BARK_KEY
+
+*********************************
+Surge(iOS 5.9.0+/macOS 5.5.0+)模块:
+https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/CtripDailyBonus.sgmodule
+
+*********************************
+QuantumultX 任务仓库(Gallery)订阅:
+https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
+
+工具&分析->HTTP请求->右上角添加任务仓库->选择脚本添加定时任务和附加组件
+
+*********************************/
+
+const $ = new Env('CTRIP_DAILY_BONUS');
+const barkKey = $.isNode() && process.env['CTRIP_BARK_KEY'] || ''; // bark key
+const notifyMsg = [];
+const auth = ''; // '{"account":{"user1":{"auth":"xxx"},"user2":{"auth":"xxx"}}}'
+
+!(async () => {
+ $.logLevel = $.getdata(`@${$.name}.Debug`) == 'true' && 'debug' || 'info';
+ const user = JSON.parse(auth || $.getdata($.name) || ($.isNode() && process.env['CTRIP_AUTH']) || '{}');
+ const userNum = Object.keys(user.account || {}).length;
+ if (typeof $response !== 'undefined') {
+ const body = JSON.parse($response.body || '{}');
+ return GetAuth(body, user);
+ }
+ if (userNum) {
+ const invalidUser = [];
+ for (const i in user.account) {
+ const text = [
+ userNum > 1 && `[账号${notifyMsg.length + 1}(${i.slice(-4)})]`,
+ await Checkin(user.account[i].auth),
+ await Points(user.account[i].auth)
+ ].filter((v) => v).join(', ');
+ if (text.includes('登陆失效')) {
+ invalidUser.push(i)
+ }
+ $.info(text);
+ notifyMsg.push(text);
+ }
+ invalidUser.forEach((i) => delete user.account[i] && !$.isNode() && $.setjson(user, $.name));
+ } else {
+ notifyMsg.push(`未获取授权!`);
+ }
+})()
+ .catch((err) => notifyMsg.push(`错误: ${err}`) && $.error(err))
+ .finally(async () => {
+ if (notifyMsg.length) {
+ $.msg(`携程旅行`, ``, notifyMsg.join('\n'))
+ }
+ if (barkKey) {
+ await BarkNotify($, barkKey, `携程旅行`, notifyMsg.join('\n'));
+ }
+ $.done({});
+ });
+
+function Checkin(key) {
+ const opts = {
+ url: 'https://m.ctrip.com/restapi/soa2/22769/signToday',
+ headers: {
+ "Content-Type": "application/json",
+ "User-Agent": 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/21E219 MicroMessenger/8.0.49'
+ },
+ body: JSON.stringify({ head: { auth: key } })
+ };
+ $.debug(`Send checkin request:`, $.toStr(opts, 'error', null, 1));
+ return $.http.post(opts)
+ .then((resp) => {
+ $.debug(`Receive checkin request response:`, $.toStr(resp))
+ resp.body = JSON.parse(resp.body?.startsWith('{') && resp.body || '{}');
+ if (resp.body.code == 0) {
+ return '签到成功'
+ } else if (resp.body.code == 400001) {
+ return '已签过'
+ } else if (resp.body.code == 404001) {
+ return '登陆失效, 尝试移除账号...'
+ } else {
+ return `签到失败`
+ }
+ })
+ .catch((err) => {
+ $.error(`Send checkin request error:`, err);
+ return `签到错误`
+ })
+}
+
+function Points(key) {
+ const opts = {
+ url: 'https://m.ctrip.com/restapi/soa2/15634/json/getPointsOrderUserInfo',
+ headers: {
+ "Content-Type": "application/json",
+ "User-Agent": 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/21E219 MicroMessenger/8.0.49'
+ },
+ body: JSON.stringify({ needUserInfo: true, head: { auth: key } })
+ };
+ $.debug(`Send points request:`, $.toStr(opts, 'error', null, 1));
+ return $.http.post(opts)
+ .then((resp) => {
+ $.debug(`Receive points request response:`, $.toStr(resp))
+ resp.body = JSON.parse(resp.body?.startsWith('{') && resp.body || '{}');
+ if (resp.body.isLogin) {
+ return `总积分: ${resp.body.availableCredits || 0}`
+ }
+ })
+ .catch((err) => {
+ $.error(`Send points request error:`, err)
+ return `总积分: 查询错误`
+ })
+}
+
+function GetAuth(body, data) {
+ if (body.ticket && body.uid) {
+ if (!data.account || !data.account[body.uid]) {
+ notifyMsg.push(`账号: ${body.uid}\n写入授权成功!`);
+ } else {
+ $.info(`账号: ${body.uid}\n更新授权成功!`);
+ }
+ data.account = { ...data.account, ...{ [body.uid]: { auth: body.ticket } } };
+ } else {
+ $.error(`写入授权失败, 授权值缺失.`)
+ }
+ return $.setjson(data, $.name);
+}
+
+//Bark APP notify
+async function BarkNotify(c, k, t, b) { for (let i = 0; i < 3; i++) { c.log(`🔷Bark notify >> Start push (${i + 1})`); const s = await new Promise((n) => { c.post({ url: 'https://api.day.app/push', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: t, body: b, device_key: k, ext_params: { group: t } }) }, (e, r, d) => r && r.status == 200 ? n(1) : n(d || e)) }); if (s === 1) { c.log('✅Push success!'); break } else { c.log(`❌Push failed! >> ${s.message || s}`) } } };
+
+// https://github.com/chavyleung/scripts/blob/master/Env.min.js
+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.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.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.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.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) }
\ No newline at end of file
From 994373425ff16d3786adca7d50890b1079e706cb Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 9 May 2024 19:28:03 +0800
Subject: [PATCH 092/105] Resource improvements.
---
NobyDa_BoxJs.json | 1194 +++++++++++--------
QuantumultX/Js_Remote_Cookie.conf | 22 -
QuantumultX/Snippet/BiliComicCookie.snippet | 8 +
QuantumultX/Snippet/CtripAuth.snippet | 8 +
QuantumultX/Snippet/KuaiKanCookie.snippet | 8 +
QuantumultX/Snippet/TieBaCookie.snippet | 8 +
QuantumultX/Snippet/iQiYiCookie.snippet | 8 +
Surge/Module/CtripDailyBonus.sgmodule | 13 +
8 files changed, 747 insertions(+), 522 deletions(-)
delete mode 100644 QuantumultX/Js_Remote_Cookie.conf
create mode 100644 QuantumultX/Snippet/BiliComicCookie.snippet
create mode 100644 QuantumultX/Snippet/CtripAuth.snippet
create mode 100644 QuantumultX/Snippet/KuaiKanCookie.snippet
create mode 100644 QuantumultX/Snippet/TieBaCookie.snippet
create mode 100644 QuantumultX/Snippet/iQiYiCookie.snippet
create mode 100644 Surge/Module/CtripDailyBonus.sgmodule
diff --git a/NobyDa_BoxJs.json b/NobyDa_BoxJs.json
index 0497b3579e..086ebda039 100644
--- a/NobyDa_BoxJs.json
+++ b/NobyDa_BoxJs.json
@@ -1,504 +1,698 @@
{
- "id": "NobyDa.app.sub",
- "name": "NobyDa 脚本订阅",
- "description": "该订阅兼容BoxJs以及QX Gallery",
- "author": "@NobyDa",
- "icon": "https://avatars2.githubusercontent.com/u/53217160",
- "repo": "https://github.com/NobyDa/Script/tree/master",
- "apps": [{
- "id": "多合一签到",
- "name": "京东",
- "keys": ["CookiesJD"],
- "descs_html": [
- "获取Cookie以及脚本配置请查看脚本注释 ",
- "如需修改Cookie列表请严格按照JSON格式 修改 ",
- "建议通过脚本获取Cookie ",
- " ",
- "签到相关教程 ",
- "VIDEO
"
- ],
- "settings": [{
- "id": "JD_DailyBonusLog",
- "name": "详细响应日志",
- "val": false,
- "type": "boolean",
- "desc": "打印原始签到结果, 用于调试脚本, 一般用户建议关闭."
- }, {
- "id": "JD_Crash_disable",
- "name": "崩溃自动禁用",
- "val": true,
- "type": "boolean",
- "desc": "脚本运行崩溃时(如VPN断连), 下次运行时将自动禁用相关崩溃接口(仅部分接口启用), 注: 崩溃时可能会误禁用正常接口."
- }, {
- "id": "JD_Retry_disable",
- "name": "签到接口增强",
- "val": true,
- "type": "boolean",
- "desc": "用于部分接口提示\"不含活动数据\"问题, 开启后会进行二次查询, 注: 可能会导致崩溃(小概率)."
- }, {
- "id": "JD_Follow_disable",
- "name": "自动关注店铺",
- "val": true,
- "type": "boolean",
- "desc": "部分接口签到过程可能需要关注店铺, 如介意可选择关闭."
- }, {
- "id": "JD_DailyBonusDisables",
- "name": "签到接口禁用",
- "val": "",
- "type": "checkboxes",
- "desc": "",
- "items": [{
- "key": "JDBean",
- "label": "京东京豆"
- }, {
- "key": "JRSteel",
- "label": "金融钢镚"
- }, {
- "key": "JDTurn",
- "label": "京东转盘"
- }, {
- "key": "JDGStore",
- "label": "京东超市"
- }, {
- "key": "JDCard",
- "label": "京东卡包"
- }, {
- "key": "JD3C",
- "label": "京东数码"
- }, {
- "key": "JDSuitcase",
- "label": "京东箱包"
- }, {
- "key": "JDChild",
- "label": "京东童装"
- }, {
- "key": "JDBaby",
- "label": "京东母婴"
- }, {
- "key": "JDCash",
- "label": "京东红包"
- }, {
- "key": "JDFSale",
- "label": "京东闪购"
- }, {
- "key": "JDBook",
- "label": "京东图书"
- }, {
- "key": "JDStory",
- "label": "失眠补贴"
- }, {
- "key": "JDPhone",
- "label": "手机小时达"
- }, {
- "key": "JDSchool",
- "label": "京东校园"
- }, {
- "key": "JDUndies",
- "label": "京东内衣"
- }, {
- "key": "JDShoes",
- "label": "京东鞋靴"
- }, {
- "key": "JDShand",
- "label": "京东二手"
- }, {
- "key": "JDHealth",
- "label": "京东健康"
- }, {
- "key": "JDWomen",
- "label": "京东女装"
- }, {
- "key": "JDSecKill",
- "label": "京东秒杀"
- }, {
- "key": "JTDouble",
- "label": "金贴双签"
- }, {
- "key": "JDVege",
- "label": "京东菜场"
- }, {
- "key": "JDClean",
- "label": "京东清洁"
- }, {
- "key": "JDCare",
- "label": "京东个护"
- }, {
- "key": "JDaccompany",
- "label": "京东陪伴"
- }, {
- "key": "JDCube",
- "label": "京东魔方"
- }, {
- "key": "JDJiaDian",
- "label": "京东家电"
- }, {
- "key": "JDDouble",
- "label": "京豆双签"
- }, {
- "key": "subsidy",
- "label": "京东金贴"
- }, {
- "key": "JDGetCash",
- "label": "京东现金"
- }, {
- "key": "JDShake",
- "label": "京东摇一摇"
- }, {
- "key": "Qbear",
- "label": "总京豆查询"
- }, {
- "key": "TCash",
- "label": "总红包查询"
- }, {
- "key": "TSteel",
- "label": "总钢镚查询"
- }, {
- "key": "TotalSubsidy",
- "label": "总金贴查询"
- }, {
- "key": "TotalMoney",
- "label": "总现金查询"
- }]
- }, {
- "id": "JD_DailyBonusTimeOut",
- "name": "超时退出 (毫秒)",
- "val": "",
- "type": "number",
- "placeholder": "默认无超时 (点击以展开说明)",
- "desc": "按需填写, 用于由网络不稳定引起的脚本中断, 正常或越狱用户建议留空. 如QX日志出现大量\"JS Context timeout\"后脚本中断时, 建议填写6000"
- }, {
- "id": "JD_DailyBonusDelay",
- "name": "接口延迟 (毫秒)",
- "val": "",
- "type": "number",
- "placeholder": "默认并发无延迟 (点击以展开说明)",
- "desc": "延迟作用于每个签到接口, 该参数接受随机或指定延迟(例: '2000'则表示延迟2秒; '2000-5000'则表示延迟最小2秒,最大5秒内的随机延迟), 如填入延迟则切换顺序签到(耗时较长); VPN重启或越狱用户建议填写1(顺序执行), Surge用户请注意在SurgeUI界面调整脚本超时."
- }, {
- "id": "CookiesJD",
- "name": "Cookie列表",
- "val": "",
- "type": "textarea",
- "autoGrow": false,
- "rows": 9,
- "val": "[\n {\n \"cookie\": \"此处填写账号1 Cookie\"\n },\n {\n \"cookie\": \"此处填写账号2 Cookie\",\n \"jrBody\": \"此处填写账号2 钢镚Body\"\n }\n]",
- "placeholder": "[ {\"cookie\": \"pt_key=xxx;pt_pin=yyy;\", \"jrBody\": \"reqData=zzz\"} ]",
- "desc": "Cookie和钢镚签到Body列表, 如需修改请严格按照JSON格式填写; \"cookie\"为必须, 其他为可选."
- }],
- "scripts": [{
- "name": "京东签到",
- "script": "https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js"
- }, {
- "name": "初始化设置",
- "script": "https://gist.githubusercontent.com/NobyDa/91cbe57dd50b3588a975af8922507a72/raw/JD_initial.js"
- }],
- "author": "@NobyDa",
- "repo": "https://github.com/NobyDa/Script/tree/master/JD-DailyBonus",
- "icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/jd.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/jd.png"]
- }, {
- "id": "iQIYI",
- "name": "爱奇艺",
- "keys": ["CookieQY"],
- "descs_html": [
- "获取Cookie以及脚本配置请查看脚本注释 "
- ],
- "settings": [{
- "id": "iQIYI_LogDetails",
- "name": "响应日志",
- "val": false,
- "type": "boolean",
- "desc": ""
- }],
- "script": "https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js",
- "author": "@NobyDa",
- "repo": "https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js",
- "icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/iQIYI.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/iQIYI.png"]
- }, {
- "id": "BiliManga",
- "name": "哔哩漫画",
- "keys": ["CookieBM"],
- "descs_html": [
- "获取Cookie以及脚本配置请查看脚本注释 "
- ],
- "script": "https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js",
+ "id": "NobyDa.app.sub",
+ "name": "NobyDa 脚本订阅",
+ "description": "该订阅兼容BoxJs以及QX Gallery",
"author": "@NobyDa",
- "repo": "https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js",
- "icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/manga.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/manga.png"]
- }, {
- "id": "BiliMangaPoints",
- "name": "哔哩漫画抢券",
- "descs_html": [
- ""
+ "icon": "https://avatars2.githubusercontent.com/u/53217160",
+ "repo": "https://github.com/NobyDa/Script/tree/master",
+ "apps": [
+ {
+ "id": "多合一签到",
+ "name": "京东",
+ "keys": [
+ "CookiesJD"
+ ],
+ "descs_html": [
+ "获取Cookie以及脚本配置请查看脚本注释 ",
+ "如需修改Cookie列表请严格按照JSON格式 修改 ",
+ "建议通过脚本获取Cookie ",
+ " ",
+ "签到相关教程 ",
+ "VIDEO
"
+ ],
+ "settings": [
+ {
+ "id": "JD_DailyBonusLog",
+ "name": "详细响应日志",
+ "val": false,
+ "type": "boolean",
+ "desc": "打印原始签到结果, 用于调试脚本, 一般用户建议关闭."
+ },
+ {
+ "id": "JD_Crash_disable",
+ "name": "崩溃自动禁用",
+ "val": true,
+ "type": "boolean",
+ "desc": "脚本运行崩溃时(如VPN断连), 下次运行时将自动禁用相关崩溃接口(仅部分接口启用), 注: 崩溃时可能会误禁用正常接口."
+ },
+ {
+ "id": "JD_Retry_disable",
+ "name": "签到接口增强",
+ "val": true,
+ "type": "boolean",
+ "desc": "用于部分接口提示\"不含活动数据\"问题, 开启后会进行二次查询, 注: 可能会导致崩溃(小概率)."
+ },
+ {
+ "id": "JD_Follow_disable",
+ "name": "自动关注店铺",
+ "val": true,
+ "type": "boolean",
+ "desc": "部分接口签到过程可能需要关注店铺, 如介意可选择关闭."
+ },
+ {
+ "id": "JD_DailyBonusDisables",
+ "name": "签到接口禁用",
+ "val": "",
+ "type": "checkboxes",
+ "desc": "",
+ "items": [
+ {
+ "key": "JDBean",
+ "label": "京东京豆"
+ },
+ {
+ "key": "JRSteel",
+ "label": "金融钢镚"
+ },
+ {
+ "key": "JDTurn",
+ "label": "京东转盘"
+ },
+ {
+ "key": "JDGStore",
+ "label": "京东超市"
+ },
+ {
+ "key": "JDCard",
+ "label": "京东卡包"
+ },
+ {
+ "key": "JD3C",
+ "label": "京东数码"
+ },
+ {
+ "key": "JDSuitcase",
+ "label": "京东箱包"
+ },
+ {
+ "key": "JDChild",
+ "label": "京东童装"
+ },
+ {
+ "key": "JDBaby",
+ "label": "京东母婴"
+ },
+ {
+ "key": "JDCash",
+ "label": "京东红包"
+ },
+ {
+ "key": "JDFSale",
+ "label": "京东闪购"
+ },
+ {
+ "key": "JDBook",
+ "label": "京东图书"
+ },
+ {
+ "key": "JDStory",
+ "label": "失眠补贴"
+ },
+ {
+ "key": "JDPhone",
+ "label": "手机小时达"
+ },
+ {
+ "key": "JDSchool",
+ "label": "京东校园"
+ },
+ {
+ "key": "JDUndies",
+ "label": "京东内衣"
+ },
+ {
+ "key": "JDShoes",
+ "label": "京东鞋靴"
+ },
+ {
+ "key": "JDShand",
+ "label": "京东二手"
+ },
+ {
+ "key": "JDHealth",
+ "label": "京东健康"
+ },
+ {
+ "key": "JDWomen",
+ "label": "京东女装"
+ },
+ {
+ "key": "JDSecKill",
+ "label": "京东秒杀"
+ },
+ {
+ "key": "JTDouble",
+ "label": "金贴双签"
+ },
+ {
+ "key": "JDVege",
+ "label": "京东菜场"
+ },
+ {
+ "key": "JDClean",
+ "label": "京东清洁"
+ },
+ {
+ "key": "JDCare",
+ "label": "京东个护"
+ },
+ {
+ "key": "JDaccompany",
+ "label": "京东陪伴"
+ },
+ {
+ "key": "JDCube",
+ "label": "京东魔方"
+ },
+ {
+ "key": "JDJiaDian",
+ "label": "京东家电"
+ },
+ {
+ "key": "JDDouble",
+ "label": "京豆双签"
+ },
+ {
+ "key": "subsidy",
+ "label": "京东金贴"
+ },
+ {
+ "key": "JDGetCash",
+ "label": "京东现金"
+ },
+ {
+ "key": "JDShake",
+ "label": "京东摇一摇"
+ },
+ {
+ "key": "Qbear",
+ "label": "总京豆查询"
+ },
+ {
+ "key": "TCash",
+ "label": "总红包查询"
+ },
+ {
+ "key": "TSteel",
+ "label": "总钢镚查询"
+ },
+ {
+ "key": "TotalSubsidy",
+ "label": "总金贴查询"
+ },
+ {
+ "key": "TotalMoney",
+ "label": "总现金查询"
+ }
+ ]
+ },
+ {
+ "id": "JD_DailyBonusTimeOut",
+ "name": "超时退出 (毫秒)",
+ "val": "",
+ "type": "number",
+ "placeholder": "默认无超时 (点击以展开说明)",
+ "desc": "按需填写, 用于由网络不稳定引起的脚本中断, 正常或越狱用户建议留空. 如QX日志出现大量\"JS Context timeout\"后脚本中断时, 建议填写6000"
+ },
+ {
+ "id": "JD_DailyBonusDelay",
+ "name": "接口延迟 (毫秒)",
+ "val": "",
+ "type": "number",
+ "placeholder": "默认并发无延迟 (点击以展开说明)",
+ "desc": "延迟作用于每个签到接口, 该参数接受随机或指定延迟(例: '2000'则表示延迟2秒; '2000-5000'则表示延迟最小2秒,最大5秒内的随机延迟), 如填入延迟则切换顺序签到(耗时较长); VPN重启或越狱用户建议填写1(顺序执行), Surge用户请注意在SurgeUI界面调整脚本超时."
+ },
+ {
+ "id": "CookiesJD",
+ "name": "Cookie列表",
+ "type": "textarea",
+ "autoGrow": false,
+ "rows": 9,
+ "val": "[\n {\n \"cookie\": \"此处填写账号1 Cookie\"\n },\n {\n \"cookie\": \"此处填写账号2 Cookie\",\n \"jrBody\": \"此处填写账号2 钢镚Body\"\n }\n]",
+ "placeholder": "[ {\"cookie\": \"pt_key=xxx;pt_pin=yyy;\", \"jrBody\": \"reqData=zzz\"} ]",
+ "desc": "Cookie和钢镚签到Body列表, 如需修改请严格按照JSON格式填写; \"cookie\"为必须, 其他为可选."
+ }
+ ],
+ "scripts": [
+ {
+ "name": "京东签到",
+ "script": "https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js"
+ },
+ {
+ "name": "初始化设置",
+ "script": "https://gist.githubusercontent.com/NobyDa/91cbe57dd50b3588a975af8922507a72/raw/JD_initial.js"
+ }
+ ],
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/tree/master/JD-DailyBonus",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/jd.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/jd.png"
+ ]
+ },
+ {
+ "id": "iQIYI",
+ "name": "爱奇艺",
+ "keys": [
+ "CookieQY"
+ ],
+ "descs_html": [
+ "获取Cookie以及脚本配置请查看脚本注释 "
+ ],
+ "settings": [
+ {
+ "id": "iQIYI_LogDetails",
+ "name": "响应日志",
+ "val": false,
+ "type": "boolean",
+ "desc": ""
+ }
+ ],
+ "script": "https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js",
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/blob/master/iQIYI-DailyBonus/iQIYI.js",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/iQIYI.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/iQIYI.png"
+ ]
+ },
+ {
+ "id": "BiliManga",
+ "name": "哔哩漫画",
+ "keys": [
+ "CookieBM"
+ ],
+ "descs_html": [
+ "获取Cookie以及脚本配置请查看脚本注释 "
+ ],
+ "script": "https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js",
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/Manga.js",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/manga.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/manga.png"
+ ]
+ },
+ {
+ "id": "BiliMangaPoints",
+ "name": "哔哩漫画抢券",
+ "descs_html": [
+ ""
+ ],
+ "keys": [
+ "BM_ProductName",
+ "BM_ProductNum",
+ "BM_ExchangeNum"
+ ],
+ "settings": [
+ {
+ "id": "BM_ProductName",
+ "name": "商品名",
+ "val": "积分兑换",
+ "type": "text",
+ "placeholder": "(点击以展开说明)",
+ "desc": "要抢购的积分商城商品名"
+ },
+ {
+ "id": "BM_ProductNum",
+ "name": "兑换数量",
+ "val": "",
+ "type": "text",
+ "placeholder": "(点击以展开说明)",
+ "desc": "要兑换的数量, 默认为积分可兑换的最大值"
+ },
+ {
+ "id": "BM_ExchangeNum",
+ "name": "抢购次数",
+ "val": "",
+ "type": "text",
+ "placeholder": "(点击以展开说明)",
+ "desc": "默认暴力抢购100次"
+ }
+ ],
+ "script": "https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/ExchangePoints.js",
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/ExchangePoints.js",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/manga.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/manga.png"
+ ]
+ },
+ {
+ "id": "BaiduTB",
+ "name": "百度贴吧",
+ "keys": [
+ "CookieTB"
+ ],
+ "descs_html": [
+ "获取Cookie以及脚本配置请查看脚本注释 "
+ ],
+ "settings": [
+ {
+ "id": "BDTB_DailyBonus_Mode",
+ "name": "签到模式",
+ "val": "0",
+ "type": "radios",
+ "desc": "",
+ "items": [
+ {
+ "key": "0",
+ "label": "自动切换"
+ },
+ {
+ "key": "1",
+ "label": "顺序执行"
+ },
+ {
+ "key": "2",
+ "label": "并发执行"
+ }
+ ]
+ },
+ {
+ "id": "BDTB_DailyBonus_notify",
+ "name": "通知汇总",
+ "val": "",
+ "type": "number",
+ "placeholder": "默认20 (点击以展开说明)",
+ "desc": "想签到几个汇总到一个通知里, 这里就填几个(比如我有13个要签到的, 这里填了5, 就会分三次推送通知)"
+ }
+ ],
+ "script": "https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js",
+ "author": "@sazs34, @NobyDa",
+ "repo": "https://github.com/sazs34/TaskConfig/blob/master/task/sign_baidu_tieba_v2.js",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/tieba.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/tieba.png"
+ ]
+ },
+ {
+ "id": "52poje",
+ "name": "吾爱破解",
+ "keys": [
+ "nobyda_52pojie"
+ ],
+ "descs_html": [
+ "获取Cookie以及脚本配置请查看脚本注释 "
+ ],
+ "script": "https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js",
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/52pj.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/52pj.png"
+ ]
+ },
+ {
+ "id": "KuaiKan",
+ "name": "快看漫画",
+ "keys": [
+ "@KKMH.COOKIE",
+ "@KKMH.TIME",
+ "@KKMH.UID",
+ "@KKMH.DATE"
+ ],
+ "descs_html": [
+ "获取Cookie以及脚本配置请查看脚本注释 "
+ ],
+ "settings": [
+ {
+ "id": "@KKMH.LOG",
+ "name": "响应日志",
+ "val": false,
+ "type": "boolean",
+ "desc": "打印原始签到结果, 用于调试脚本, 一般用户建议关闭."
+ }
+ ],
+ "script": "https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js",
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/KuaiKan.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/KuaiKan.png"
+ ]
+ },
+ {
+ "id": "Bahamut",
+ "name": "巴哈姆特",
+ "keys": [
+ "@ND_BAHA.ID",
+ "@ND_BAHA.PW",
+ "@ND_BAHA.TOTP",
+ "@ND_BAHA.GUILD",
+ "@ND_BAHA.ANSWER",
+ "@ND_BAHA.ADS"
+ ],
+ "descs_html": [
+ ""
+ ],
+ "settings": [
+ {
+ "id": "@ND_BAHA.ADS",
+ "name": "签到广告",
+ "val": false,
+ "type": "boolean",
+ "desc": "开启后将签到双倍巴币奖励, 默认关闭. 请注意, 此功能耗时过长(30秒以上), 如果使用Surge请调整该脚本超时为300秒"
+ },
+ {
+ "id": "@ND_BAHA.GUILD",
+ "name": "签到公会",
+ "val": true,
+ "type": "boolean",
+ "desc": "开启后将自动签到公会"
+ },
+ {
+ "id": "@ND_BAHA.ANSWER",
+ "name": "动画疯答题",
+ "val": true,
+ "type": "boolean",
+ "desc": "开启后将自动答题"
+ },
+ {
+ "id": "@ND_BAHA.ID",
+ "name": "用户名",
+ "val": "",
+ "type": "text",
+ "placeholder": "(点击以展开说明)",
+ "desc": "输入用户名(账号)"
+ },
+ {
+ "id": "@ND_BAHA.PW",
+ "name": "用户密码",
+ "val": "",
+ "type": "text",
+ "placeholder": "",
+ "desc": "输入用户密码"
+ },
+ {
+ "id": "@ND_BAHA.TOTP",
+ "name": "两步验证令牌",
+ "val": "",
+ "type": "text",
+ "placeholder": "(点击以展开说明)",
+ "desc": "输入网站生成的16位令牌, 如未设置两步验证, 请留空"
+ }
+ ],
+ "script": "https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutDailyBonus.js",
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/bahamutGame.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/bahamutGame.png"
+ ]
+ },
+ {
+ "id": "BiliRegion",
+ "name": "哔哩番剧自动地区",
+ "descs_html": [
+ ""
+ ],
+ "keys": [
+ "BiliArea_Policy",
+ "BiliArea_CN",
+ "BiliArea_HK",
+ "BiliArea_TW",
+ "BiliArea_DF",
+ "BiliArea_disabled"
+ ],
+ "settings": [
+ {
+ "id": "BiliAreaNotify",
+ "name": "静默运行",
+ "val": false,
+ "type": "boolean",
+ "desc": "开启后将不再发出切换策略通知"
+ },
+ {
+ "id": "BiliDoubanRating",
+ "name": "豆瓣评分",
+ "val": true,
+ "type": "boolean",
+ "desc": "关闭后将不再查询豆瓣评分, 可显著提高相关页面载入速度"
+ },
+ {
+ "id": "BiliArea_Policy",
+ "name": "策略组名",
+ "val": "",
+ "type": "text",
+ "placeholder": "(点击以展开说明)",
+ "desc": "哔哩哔哩分流的策略组名"
+ },
+ {
+ "id": "BiliArea_CN",
+ "name": "中国大陆-子策略名",
+ "val": "DIRECT",
+ "type": "text",
+ "placeholder": "(点击以展开说明)",
+ "desc": "哔哩哔哩分流策略组里的中国大陆子策略名"
+ },
+ {
+ "id": "BiliArea_HK",
+ "name": "中国香港-子策略名",
+ "val": "",
+ "type": "text",
+ "placeholder": "(点击以展开说明)",
+ "desc": "哔哩哔哩分流策略组里的香港子策略名"
+ },
+ {
+ "id": "BiliArea_TW",
+ "name": "中国台湾-子策略名",
+ "val": "",
+ "type": "text",
+ "placeholder": "(点击以展开说明)",
+ "desc": "哔哩哔哩分流策略组里的台湾子策略名"
+ },
+ {
+ "id": "BiliArea_DF",
+ "name": "后备-子策略名",
+ "val": "",
+ "type": "text",
+ "placeholder": "(点击以展开说明)",
+ "desc": "部分番剧可能会被屏蔽, 使用该策略以避免页面加载失败. 建议填写台湾子策略"
+ },
+ {
+ "id": "BiliArea_disabled",
+ "name": "WiFi黑名单",
+ "val": "",
+ "type": "text",
+ "placeholder": "(点击以展开说明)",
+ "desc": "WiFi名称以逗号分隔, 名单内将跳过策略切换"
+ }
+ ],
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/blob/master/Surge/JS/Bili_Auto_Regions.js",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/bilibili.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/bilibili.png"
+ ]
+ },
+ {
+ "id": "TestFlightAccount",
+ "name": "TestFlight账户管理",
+ "keys": [
+ "TESTFLIGHT-ACCOUNT"
+ ],
+ "descs_html": [
+ "脚本说明以及配置请查看脚本注释 "
+ ],
+ "settings": [
+ {
+ "id": "@TESTFLIGHT-ACCOUNT.Debug",
+ "name": "开发者模式",
+ "val": false,
+ "type": "boolean",
+ "desc": "用于调试脚本, 一般用户请勿开启."
+ },
+ {
+ "id": "@TESTFLIGHT-ACCOUNT.EnableCache",
+ "name": "启用缓存",
+ "val": true,
+ "type": "boolean",
+ "desc": "用于缓存APP列表, 改善列表页面加载过慢,需与\"请求超时\"配合使用。开启缓存并刷新列表后,可适当调小超时"
+ },
+ {
+ "id": "@TESTFLIGHT-ACCOUNT.Timeout",
+ "name": "请求超时",
+ "val": "",
+ "type": "number",
+ "placeholder": "30",
+ "desc": "默认为30, 单位: 秒"
+ },
+ {
+ "id": "@TESTFLIGHT-ACCOUNT.ForceIOSlist",
+ "name": "使用iOS应用列表",
+ "val": false,
+ "type": "boolean",
+ "desc": "强制使用iOS应用列表, 用于改善 macOS TestFlight 加载过慢, iOS用户无需开启"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "清除缓存",
+ "script": "https://gist.githubusercontent.com/NobyDa/d025c53d3922657f921b983ce129fc1d/raw/TestFlightAccountRemoveCache.js"
+ }
+ ],
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/blob/master/TestFlight/TestFlightAccount.js",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/testflight.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/testflight.png"
+ ]
+ },
+ {
+ "id": "Ctrip",
+ "name": "携程旅行",
+ "keys": [
+ "CTRIP_DAILY_BONUS"
+ ],
+ "descs_html": [
+ "脚本说明以及配置请查看脚本注释 "
+ ],
+ "settings": [
+ {
+ "id": "@CTRIP_DAILY_BONUS.Debug",
+ "name": "开发者模式",
+ "val": false,
+ "type": "boolean",
+ "desc": "用于调试脚本, 一般用户请勿开启."
+ }
+ ],
+ "script": "https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js",
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/blob/master/Ctrip-DailyBonus/Ctrip.js",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/ctrip.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/ctrip.png"
+ ]
+ }
],
- "keys": ["BM_ProductName", "BM_ProductNum", "BM_ExchangeNum"],
- "settings": [{
- "id": "BM_ProductName",
- "name": "商品名",
- "val": "积分兑换",
- "type": "text",
- "placeholder": "(点击以展开说明)",
- "desc": "要抢购的积分商城商品名"
- }, {
- "id": "BM_ProductNum",
- "name": "兑换数量",
- "val": "",
- "type": "text",
- "placeholder": "(点击以展开说明)",
- "desc": "要兑换的数量, 默认为积分可兑换的最大值"
- }, {
- "id": "BM_ExchangeNum",
- "name": "抢购次数",
- "val": "",
- "type": "text",
- "placeholder": "(点击以展开说明)",
- "desc": "默认暴力抢购100次"
- }],
- "script": "https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/ExchangePoints.js",
- "author": "@NobyDa",
- "repo": "https://github.com/NobyDa/Script/blob/master/Bilibili-DailyBonus/ExchangePoints.js",
- "icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/manga.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/manga.png"]
- }, {
- "id": "BaiduTB",
- "name": "百度贴吧",
- "keys": ["CookieTB"],
- "descs_html": [
- "获取Cookie以及脚本配置请查看脚本注释 "
- ],
- "settings": [{
- "id": "BDTB_DailyBonus_Mode",
- "name": "签到模式",
- "val": "0",
- "type": "radios",
- "desc": "",
- "items": [{
- "key": "0",
- "label": "自动切换"
- }, {
- "key": "1",
- "label": "顺序执行"
- }, {
- "key": "2",
- "label": "并发执行"
- }]
- }, {
- "id": "BDTB_DailyBonus_notify",
- "name": "通知汇总",
- "val": "",
- "type": "number",
- "placeholder": "默认20 (点击以展开说明)",
- "desc": "想签到几个汇总到一个通知里, 这里就填几个(比如我有13个要签到的, 这里填了5, 就会分三次推送通知)"
- }],
- "script": "https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js",
- "author": "@sazs34, @NobyDa",
- "repo": "https://github.com/sazs34/TaskConfig/blob/master/task/sign_baidu_tieba_v2.js",
- "icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/tieba.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/tieba.png"]
- }, {
- "id": "52poje",
- "name": "吾爱破解",
- "keys": ["nobyda_52pojie"],
- "descs_html": [
- "获取Cookie以及脚本配置请查看脚本注释 "
- ],
- "script": "https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js",
- "author": "@NobyDa",
- "repo": "https://github.com/NobyDa/Script/blob/master/52pojie-DailyBonus/52pojie.js",
- "icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/52pj.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/52pj.png"]
- }, {
- "id": "KuaiKan",
- "name": "快看漫画",
- "keys": ["@KKMH.COOKIE", "@KKMH.TIME", "@KKMH.UID", "@KKMH.DATE"],
- "descs_html": [
- "获取Cookie以及脚本配置请查看脚本注释 "
- ],
- "settings": [{
- "id": "@KKMH.LOG",
- "name": "响应日志",
- "val": false,
- "type": "boolean",
- "desc": "打印原始签到结果, 用于调试脚本, 一般用户建议关闭."
- }],
- "script": "https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js",
- "author": "@NobyDa",
- "repo": "https://github.com/NobyDa/Script/blob/master/KuaiKan-DailyBonus/KKMH.js",
- "icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/KuaiKan.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/KuaiKan.png"]
- }, {
- "id": "Bahamut",
- "name": "巴哈姆特",
- "keys": ["@ND_BAHA.ID", "@ND_BAHA.PW", "@ND_BAHA.TOTP", "@ND_BAHA.GUILD", "@ND_BAHA.ANSWER", "@ND_BAHA.ADS"],
- "descs_html": [
- ""
- ],
- "settings": [{
- "id": "@ND_BAHA.ADS",
- "name": "签到广告",
- "val": false,
- "type": "boolean",
- "desc": "开启后将签到双倍巴币奖励, 默认关闭. 请注意, 此功能耗时过长(30秒以上), 如果使用Surge请调整该脚本超时为300秒"
- }, {
- "id": "@ND_BAHA.GUILD",
- "name": "签到公会",
- "val": true,
- "type": "boolean",
- "desc": "开启后将自动签到公会"
- }, {
- "id": "@ND_BAHA.ANSWER",
- "name": "动画疯答题",
- "val": true,
- "type": "boolean",
- "desc": "开启后将自动答题"
- }, {
- "id": "@ND_BAHA.ID",
- "name": "用户名",
- "val": "",
- "type": "text",
- "placeholder": "(点击以展开说明)",
- "desc": "输入用户名(账号)"
- }, {
- "id": "@ND_BAHA.PW",
- "name": "用户密码",
- "val": "",
- "type": "text",
- "placeholder": "",
- "desc": "输入用户密码"
- }, {
- "id": "@ND_BAHA.TOTP",
- "name": "两步验证令牌",
- "val": "",
- "type": "text",
- "placeholder": "(点击以展开说明)",
- "desc": "输入网站生成的16位令牌, 如未设置两步验证, 请留空"
- }],
- "script": "https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutDailyBonus.js",
- "author": "@NobyDa",
- "repo": "https://github.com/NobyDa/Script/blob/master/Bahamut/BahamutDailyBonus.js",
- "icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/bahamutGame.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/bahamutGame.png"]
- }, {
- "id": "BiliRegion",
- "name": "哔哩番剧自动地区",
- "descs_html": [
- ""
- ],
- "keys": ["BiliArea_Policy", "BiliArea_CN", "BiliArea_HK", "BiliArea_TW", "BiliArea_DF", "BiliArea_disabled"],
- "settings": [{
- "id": "BiliAreaNotify",
- "name": "静默运行",
- "val": false,
- "type": "boolean",
- "desc": "开启后将不再发出切换策略通知"
- }, {
- "id": "BiliDoubanRating",
- "name": "豆瓣评分",
- "val": true,
- "type": "boolean",
- "desc": "关闭后将不再查询豆瓣评分, 可显著提高相关页面载入速度"
- }, {
- "id": "BiliArea_Policy",
- "name": "策略组名",
- "val": "",
- "type": "text",
- "placeholder": "(点击以展开说明)",
- "desc": "哔哩哔哩分流的策略组名"
- }, {
- "id": "BiliArea_CN",
- "name": "中国大陆-子策略名",
- "val": "DIRECT",
- "type": "text",
- "placeholder": "(点击以展开说明)",
- "desc": "哔哩哔哩分流策略组里的中国大陆子策略名"
- }, {
- "id": "BiliArea_HK",
- "name": "中国香港-子策略名",
- "val": "",
- "type": "text",
- "placeholder": "(点击以展开说明)",
- "desc": "哔哩哔哩分流策略组里的香港子策略名"
- }, {
- "id": "BiliArea_TW",
- "name": "中国台湾-子策略名",
- "val": "",
- "type": "text",
- "placeholder": "(点击以展开说明)",
- "desc": "哔哩哔哩分流策略组里的台湾子策略名"
- }, {
- "id": "BiliArea_DF",
- "name": "后备-子策略名",
- "val": "",
- "type": "text",
- "placeholder": "(点击以展开说明)",
- "desc": "部分番剧可能会被屏蔽, 使用该策略以避免页面加载失败. 建议填写台湾子策略"
- }, {
- "id": "BiliArea_disabled",
- "name": "WiFi黑名单",
- "val": "",
- "type": "text",
- "placeholder": "(点击以展开说明)",
- "desc": "WiFi名称以逗号分隔, 名单内将跳过策略切换"
- }],
- "author": "@NobyDa",
- "repo": "https://github.com/NobyDa/Script/blob/master/Surge/JS/Bili_Auto_Regions.js",
- "icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/bilibili.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/bilibili.png"]
- }, {
- "id": "TestFlightAccount",
- "name": "TestFlight账户管理",
- "keys": ["TESTFLIGHT-ACCOUNT"],
- "descs_html": [
- "脚本说明以及配置请查看脚本注释 "
- ],
- "settings": [{
- "id": "@TESTFLIGHT-ACCOUNT.Debug",
- "name": "开发者模式",
- "val": false,
- "type": "boolean",
- "desc": "用于调试脚本, 一般用户请勿开启."
- }, {
- "id": "@TESTFLIGHT-ACCOUNT.EnableCache",
- "name": "启用缓存",
- "val": true,
- "type": "boolean",
- "desc": "用于缓存APP列表, 改善列表页面加载过慢,需与\"请求超时\"配合使用。开启缓存并刷新列表后,可适当调小超时"
- }, {
- "id": "@TESTFLIGHT-ACCOUNT.Timeout",
- "name": "请求超时",
- "val":"",
- "type": "number",
- "placeholder": "30",
- "desc": "默认为30, 单位: 秒"
- }, {
- "id": "@TESTFLIGHT-ACCOUNT.ForceIOSlist",
- "name": "使用iOS应用列表",
- "val": false,
- "type": "boolean",
- "desc": "强制使用iOS应用列表, 用于改善 macOS TestFlight 加载过慢, iOS用户无需开启"
- }],
- "scripts": [{
- "name": "清除缓存",
- "script": "https://gist.githubusercontent.com/NobyDa/d025c53d3922657f921b983ce129fc1d/raw/TestFlightAccountRemoveCache.js"
- }],
- "author": "@NobyDa",
- "repo": "https://github.com/NobyDa/Script/blob/master/TestFlight/TestFlightAccount.js",
- "icons": ["https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/testflight.png", "https://raw.githubusercontent.com/NobyDa/mini/master/Color/testflight.png"]
- }],
- "task": [{
- "config": "0 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js, tag=京东签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/jd.png",
- "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf, tag=NobyDa Cookie获取"
- }, {
- "config": "5 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js, tag=爱奇艺签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/iQIYI.png",
- "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf, tag=NobyDa Cookie获取"
- }, {
- "config": "10 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js, tag=哔哩漫画签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/manga.png",
- "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf, tag=NobyDa Cookie获取"
- }, {
- "config": "10,20,30 0 12 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/ExchangePoints.js, tag=哔哩漫画抢券, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/manga.png",
- "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf, tag=NobyDa Cookie获取"
- }, {
- "config": "15 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js, tag=百度贴吧签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/tieba.png",
- "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf, tag=NobyDa Cookie获取"
- }, {
- "config": "20 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js, tag=吾爱破解签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/52pj.png",
- "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf, tag=NobyDa Cookie获取"
- }, {
- "config": "25 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js, tag=快看漫画签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/KuaiKan.png",
- "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js_Remote_Cookie.conf, tag=NobyDa Cookie获取"
- }, {
- "config": "0 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutDailyBonus.js, tag=巴哈姆特签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/bahamutGame.png"
- }]
+ "task": [
+ {
+ "config": "30 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js, tag=携程旅行签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/ctrip.png",
+ "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/CtripAuth.snippet, tag=携程旅行(获取授权)"
+ },
+ {
+ "config": "5 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js, tag=爱奇艺签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/iQIYI.png",
+ "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/iQiYiCookie.snippet, tag=爱奇艺(获取Cookie)"
+ },
+ {
+ "config": "10 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js, tag=哔哩漫画签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/manga.png",
+ "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/BiliComicCookie.snippet, tag=哔哩漫画(获取Cookie)"
+ },
+ {
+ "config": "10,20,30 0 12 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/ExchangePoints.js, tag=哔哩漫画抢券, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/manga.png",
+ "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/BiliComicCookie.snippet, tag=哔哩漫画(获取Cookie)"
+ },
+ {
+ "config": "15 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js, tag=百度贴吧签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/tieba.png",
+ "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/TieBaCookie.snippet, tag=百度贴吧(获取Cookie)"
+ },
+ {
+ "config": "25 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js, tag=快看漫画签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/KuaiKan.png",
+ "addons": "https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/KuaiKanCookie.snippet, tag=快看漫画(获取Cookie)"
+ },
+ {
+ "config": "0 8 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutDailyBonus.js, tag=巴哈姆特签到, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/bahamutGame.png"
+ }
+ ]
}
\ No newline at end of file
diff --git a/QuantumultX/Js_Remote_Cookie.conf b/QuantumultX/Js_Remote_Cookie.conf
deleted file mode 100644
index 327b0ea006..0000000000
--- a/QuantumultX/Js_Remote_Cookie.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-# 此远程订阅用于解决QX任务脚本的cookie获取,仅适用于QX 1.0.10及更高版本,您可在使用后手动将其禁用,以避免无意义的MITM。
-
-hostname = passport.iqiyi.com, www.52pojie.cn, c.tieba.baidu.com, api.m.jd.com, ms.jr.jd.com, me-api.jd.com, passport.biligame.com, api.kkmh.com
-
-# 爱奇艺 cookie
-^https:\/\/passport\.iqiyi\.com\/apis\/user\/ url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
-
-# 吾爱破解 cookie
-https:\/\/www\.52pojie\.cn\/home\.php\? url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js
-
-# 百度贴吧 cookie
-https?:\/\/(c\.tieba\.baidu\.com|180\.97\.\d+\.\d+)\/c\/s\/login url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js
-
-# 京东 cookie
-^https:\/\/(api\.m|me-api)\.jd\.com\/(client\.action\?functionId=signBean|user_new\/info\/GetJDUserInfoUnion\?) url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js
-^https:\/\/ms\.jr\.jd\.com\/gw\/generic\/hy\/h5\/m\/appSign\? url script-request-body https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js
-
-# 哔哩哔哩漫画 Get cookie
-^https:\/\/passport\.biligame\.com\/api\/login\/sso.+?version%22%3A%22(3|4|5) url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js
-
-# 快看漫画 cookie
-^https:\/\/api\.kkmh\.com\/v\d\/passport\/user url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js
\ No newline at end of file
diff --git a/QuantumultX/Snippet/BiliComicCookie.snippet b/QuantumultX/Snippet/BiliComicCookie.snippet
new file mode 100644
index 0000000000..d3d5bdb494
--- /dev/null
+++ b/QuantumultX/Snippet/BiliComicCookie.snippet
@@ -0,0 +1,8 @@
+# 该 QuantumultX 远程重写配置片段用于获取"哔哩哔哩漫画签到"账号Cookie
+# 配置脚本后打开哔哩哔哩漫画(AppStore中国区),点击"我的"可完成获取
+# https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/BiliComicCookie.snippet
+
+
+^https:\/\/app\.bilibili\.com\/x\/v2\/account\/myinfo url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js
+
+hostname = app.bilibili.com
\ No newline at end of file
diff --git a/QuantumultX/Snippet/CtripAuth.snippet b/QuantumultX/Snippet/CtripAuth.snippet
new file mode 100644
index 0000000000..aaa0757e97
--- /dev/null
+++ b/QuantumultX/Snippet/CtripAuth.snippet
@@ -0,0 +1,8 @@
+# 该 QuantumultX 远程重写配置片段用于获取"携程签到"账号授权
+# 配置脚本后登陆"携程旅行"微信小程序可完成获取
+# https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/CtripAuth.snippet
+
+
+^https:\/\/m\.ctrip\.com\/restapi\/soa2\/\d+\/[a-zA-Z]+Login(?:$|\?) url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js
+
+hostname = m.ctrip.com
\ No newline at end of file
diff --git a/QuantumultX/Snippet/KuaiKanCookie.snippet b/QuantumultX/Snippet/KuaiKanCookie.snippet
new file mode 100644
index 0000000000..2cd8e0eaa4
--- /dev/null
+++ b/QuantumultX/Snippet/KuaiKanCookie.snippet
@@ -0,0 +1,8 @@
+# 该 QuantumultX 远程重写配置片段用于获取"快看漫画签到"账号Cookie
+# 配置脚本后打开快看漫画(AppStore中国区),点击"我的"可完成获取
+# https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/KuaiKanCookie.snippet
+
+
+^https:\/\/api\.kkmh\.com\/v\d\/passport\/user url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js
+
+hostname = api.kkmh.com
\ No newline at end of file
diff --git a/QuantumultX/Snippet/TieBaCookie.snippet b/QuantumultX/Snippet/TieBaCookie.snippet
new file mode 100644
index 0000000000..1a5e923ce0
--- /dev/null
+++ b/QuantumultX/Snippet/TieBaCookie.snippet
@@ -0,0 +1,8 @@
+# 该 QuantumultX 远程重写配置片段用于获取"百度贴吧签到"账号Cookie
+# 配置脚本后打开百度贴吧App(AppStore中国区, 非内部版),点击"我的"可完成获取
+# https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/TieBaCookie.snippet
+
+
+https?:\/\/(c\.tieba\.baidu\.com|180\.97\.\d+\.\d+)\/c\/s\/login url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js
+
+hostname = c.tieba.baidu.com
\ No newline at end of file
diff --git a/QuantumultX/Snippet/iQiYiCookie.snippet b/QuantumultX/Snippet/iQiYiCookie.snippet
new file mode 100644
index 0000000000..0c77dbc4b3
--- /dev/null
+++ b/QuantumultX/Snippet/iQiYiCookie.snippet
@@ -0,0 +1,8 @@
+# 该 QuantumultX 远程重写配置片段用于获取"爱奇艺签到"账号Cookie
+# 配置脚本后 Safari 浏览器打开 https://m.iqiyi.com/user.html 使用密码登录可完成获取
+# https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/iQiYiCookie.snippet
+
+
+^https:\/\/passport\.iqiyi\.com\/apis\/user\/ url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
+
+hostname = passport.iqiyi.com
\ No newline at end of file
diff --git a/Surge/Module/CtripDailyBonus.sgmodule b/Surge/Module/CtripDailyBonus.sgmodule
new file mode 100644
index 0000000000..6c266301c9
--- /dev/null
+++ b/Surge/Module/CtripDailyBonus.sgmodule
@@ -0,0 +1,13 @@
+#!name=携程签到
+#!desc=每日定时签到,支持多账号。登陆"携程旅行"微信小程序可获取账号授权,填写模块参数可禁用脚本。
+#!arguments=定时签到:30 8 * * *,禁用脚本:携程旅行(获取),禁用MITM:hostname
+#!arguments-desc=定时签到:Cron表达式,默认每日 8:30 执行。\n\n禁用脚本:禁用获取授权脚本,输入 # 表示禁用。\n\n禁用MITM:禁用MITM主机名,输入 # 表示禁用。
+#!category=🐻 NobyDa
+
+[Script]
+携程旅行(签到) = type=cron,cronexp="{{{定时签到}}}",wake-system=1,script-update-interval=0,timeout=60,wake-system=1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js
+
+{{{禁用脚本}}} = type=http-response,pattern=^https:\/\/m\.ctrip\.com\/restapi\/soa2\/\d+\/[a-zA-Z]+Login(?:$|\?),requires-body=1,max-size=0,debug=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js
+
+[MITM]
+{{{禁用MITM}}} = %APPEND% m.ctrip.com
\ No newline at end of file
From 3c455ca2ae7b254eaeba782c741a63366b75b277 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 9 May 2024 23:15:50 +0800
Subject: [PATCH 093/105] Improvement notes.
---
Ctrip-DailyBonus/Ctrip.js | 6 ++++--
QuantumultX/Snippet/CtripAuth.snippet | 2 +-
Surge/Module/CtripDailyBonus.sgmodule | 2 +-
3 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/Ctrip-DailyBonus/Ctrip.js b/Ctrip-DailyBonus/Ctrip.js
index c6381521af..6f381de42a 100644
--- a/Ctrip-DailyBonus/Ctrip.js
+++ b/Ctrip-DailyBonus/Ctrip.js
@@ -1,6 +1,8 @@
/********************************
携程旅行签到脚本
-配置脚本后登陆”携程旅行“微信小程序即可获取账号授权。支持多账号,支持Node.js
+
+支持多账号,支持Node.js,支持Bark推送。
+配置脚本后登陆"携程旅行"微信小程序或"携程网页版"(https://m.ctrip.com/)即可获取账号授权。多账号请勿"退出登陆"。
脚本作者:@NobyDa
更新时间:2024/05/09
@@ -16,7 +18,7 @@ https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/CtripDailyBo
QuantumultX 任务仓库(Gallery)订阅:
https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
-工具&分析->HTTP请求->右上角添加任务仓库->选择脚本添加定时任务和附加组件
+工具&分析->HTTP请求->右上角添加任务仓库->选择携程脚本添加定时任务和附加组件
*********************************/
diff --git a/QuantumultX/Snippet/CtripAuth.snippet b/QuantumultX/Snippet/CtripAuth.snippet
index aaa0757e97..78327113a7 100644
--- a/QuantumultX/Snippet/CtripAuth.snippet
+++ b/QuantumultX/Snippet/CtripAuth.snippet
@@ -1,5 +1,5 @@
# 该 QuantumultX 远程重写配置片段用于获取"携程签到"账号授权
-# 配置脚本后登陆"携程旅行"微信小程序可完成获取
+# 配置脚本后登陆"携程旅行"微信小程序或"携程网页版"(https://m.ctrip.com/)即可完成获取
# https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/CtripAuth.snippet
diff --git a/Surge/Module/CtripDailyBonus.sgmodule b/Surge/Module/CtripDailyBonus.sgmodule
index 6c266301c9..205e3a7b5b 100644
--- a/Surge/Module/CtripDailyBonus.sgmodule
+++ b/Surge/Module/CtripDailyBonus.sgmodule
@@ -1,5 +1,5 @@
#!name=携程签到
-#!desc=每日定时签到,支持多账号。登陆"携程旅行"微信小程序可获取账号授权,填写模块参数可禁用脚本。
+#!desc=每日定时签到,支持多账号。登陆"携程旅行"微信小程序或"携程网页版"(https://m.ctrip.com/)可获取账号授权,填写模块参数可禁用脚本。
#!arguments=定时签到:30 8 * * *,禁用脚本:携程旅行(获取),禁用MITM:hostname
#!arguments-desc=定时签到:Cron表达式,默认每日 8:30 执行。\n\n禁用脚本:禁用获取授权脚本,输入 # 表示禁用。\n\n禁用MITM:禁用MITM主机名,输入 # 表示禁用。
#!category=🐻 NobyDa
From 3b34931921b412ab33c81658254303a988437ae5 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 9 May 2024 23:24:02 +0800
Subject: [PATCH 094/105] Improvement notes.
---
Surge/Module/CtripDailyBonus.sgmodule | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Surge/Module/CtripDailyBonus.sgmodule b/Surge/Module/CtripDailyBonus.sgmodule
index 205e3a7b5b..2d20994e92 100644
--- a/Surge/Module/CtripDailyBonus.sgmodule
+++ b/Surge/Module/CtripDailyBonus.sgmodule
@@ -1,5 +1,5 @@
#!name=携程签到
-#!desc=每日定时签到,支持多账号。登陆"携程旅行"微信小程序或"携程网页版"(https://m.ctrip.com/)可获取账号授权,填写模块参数可禁用脚本。
+#!desc=每日定时签到,支持多账号。\n登陆"携程旅行"微信小程序或"携程网页版"(https://m.ctrip.com/)可获取账号授权,填写模块参数可禁用脚本。
#!arguments=定时签到:30 8 * * *,禁用脚本:携程旅行(获取),禁用MITM:hostname
#!arguments-desc=定时签到:Cron表达式,默认每日 8:30 执行。\n\n禁用脚本:禁用获取授权脚本,输入 # 表示禁用。\n\n禁用MITM:禁用MITM主机名,输入 # 表示禁用。
#!category=🐻 NobyDa
From d55c48ec92e0e2d632dc2e47ef798fdeb3c830be Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 9 May 2024 23:41:10 +0800
Subject: [PATCH 095/105] Minor improvements.
---
Ctrip-DailyBonus/Ctrip.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Ctrip-DailyBonus/Ctrip.js b/Ctrip-DailyBonus/Ctrip.js
index 6f381de42a..b20a3ccdcb 100644
--- a/Ctrip-DailyBonus/Ctrip.js
+++ b/Ctrip-DailyBonus/Ctrip.js
@@ -86,7 +86,7 @@ function Checkin(key) {
} else if (resp.body.code == 404001) {
return '登陆失效, 尝试移除账号...'
} else {
- return `签到失败`
+ return `签到失败(${resp.body.message})`
}
})
.catch((err) => {
From 6f418508f10dd9392897ba889a8c6651cba53717 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Wed, 15 May 2024 00:07:36 +0800
Subject: [PATCH 096/105] Fix iqiyi script issues.
---
iQIYI-DailyBonus/iQIYI.js | 39 +++++++++++++++++++++------------------
1 file changed, 21 insertions(+), 18 deletions(-)
diff --git a/iQIYI-DailyBonus/iQIYI.js b/iQIYI-DailyBonus/iQIYI.js
index b04c494c5d..8efdd2517a 100644
--- a/iQIYI-DailyBonus/iQIYI.js
+++ b/iQIYI-DailyBonus/iQIYI.js
@@ -1,7 +1,7 @@
/*
爱奇艺会员签到脚本
-更新时间: 2023/02/26
+更新时间: 2024/05/15
脚本兼容: QuantumultX, Surge4, Loon, JsBox, Node.js
电报频道: @NobyDa
问题反馈: @NobyDa_bot
@@ -76,9 +76,7 @@ var LogDetails = false; // 响应日志
var pushMsg = [];
-var P00001 = '';
-
-var P00003 = '';
+let P00001, P00003, DFP
var $nobyda = nobyda();
@@ -94,9 +92,10 @@ var $nobyda = nobyda();
if ($nobyda.isRequest) {
GetCookie()
} else if (cookie) {
- if (cookie.includes("P00001") && cookie.includes("P00003")) {
+ if (cookie.includes("P00001") && cookie.includes("P00003") && cookie.includes("__dfp=")) {
P00001 = cookie.match(/P00001=(.*?);/)[1];
P00003 = cookie.match(/P00003=(.*?);/)[1];
+ DFP = cookie.match(/__dfp=(\w+)/)[1];
await login();
await Checkin();
for (let i = 0; i < 3; i++) {
@@ -165,27 +164,31 @@ function Checkin() {
};
return new Promise(resolve => {
const sign_date = {
- agentType: "1",
- agentversion: "1.0",
- appKey: "basic_pcw",
- authCookie: P00001,
- qyid: md5(stringRandom(16)),
- task_code: "natural_month_sign",
+ task_code: 'natural_month_sign',
timestamp: timestamp,
- typeCode: "point",
+ appKey: 'lequ_rn',
userId: P00003,
+ authCookie: P00001,
+ agenttype: 20,
+ agentversion: '15.4.6',
+ srcplatform: 20,
+ appver: '15.4.6',
+ qyid: md5(stringRandom(16))
};
+
const post_date = {
"natural_month_sign": {
- "agentType": "1",
- "agentversion": "1",
+ "verticalCode": "iQIYI",
+ "agentVersion": "15.4.6",
"authCookie": P00001,
- "qyid": md5(stringRandom(16)),
"taskCode": "iQIYI_mofhr",
- "verticalCode": "iQIYI"
+ "dfp": DFP,
+ "qyid": md5(stringRandom(16)),
+ "agentType": 20,
+ "signFrom": 1
}
};
- const sign = k("UKobMjDMsDoScuWOfp6F", sign_date, {
+ const sign = k("cRcFakm9KSPSjFEufg3W", sign_date, {
split: "|",
sort: !0,
splitSecretKey: !0
@@ -357,7 +360,7 @@ function GetCookie() {
return
}
var CKA = $request.headers['Cookie'] || $request.headers['cookie'];;
- var iQIYI = CKA && CKA.includes("P00001=") && CKA.includes("P00003=") && CKA;
+ var iQIYI = CKA && CKA.includes("P00001=") && CKA.includes("P00003=") && CKA.includes("__dfp=") && CKA;
var RA = $nobyda.read("CookieQY")
if (CKA && iQIYI) {
if (RA != iQIYI) {
From fd6be0871fd607176f4c74ffee4138cde2f37fcb Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 16 May 2024 20:54:44 +0800
Subject: [PATCH 097/105] Google_CAPTCHA.js now compatible with qx.
---
NobyDa_BoxJs.json | 26 ++++
QuantumultX/Snippet/GoogleCAPTCHA.snippet | 12 ++
Surge/JS/Google_CAPTCHA.js | 173 +++++++++++++++-------
3 files changed, 155 insertions(+), 56 deletions(-)
create mode 100644 QuantumultX/Snippet/GoogleCAPTCHA.snippet
diff --git a/NobyDa_BoxJs.json b/NobyDa_BoxJs.json
index 086ebda039..26c427c286 100644
--- a/NobyDa_BoxJs.json
+++ b/NobyDa_BoxJs.json
@@ -664,6 +664,32 @@
"https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/ctrip.png",
"https://raw.githubusercontent.com/NobyDa/mini/master/Color/ctrip.png"
]
+ },
+ {
+ "id": "GoogleCAPTCHA",
+ "name": "Google搜索人机验证",
+ "keys": [
+ "GOOGLE_CAPTCHA"
+ ],
+ "descs_html": [
+ "脚本说明以及配置请查看脚本注释 "
+ ],
+ "settings": [
+ {
+ "id": "@GOOGLE_CAPTCHA.Regex",
+ "name": "代理策略/策略组正则表达式",
+ "val": "",
+ "type": "text",
+ "placeholder": "^(🇸🇬|🇭🇰)\\s.*\\d+$",
+ "desc": "筛选的代理策略/策略组, 限制20个, 留空则表示随机使用。"
+ }
+ ],
+ "author": "@NobyDa",
+ "repo": "https://github.com/NobyDa/Script/blob/master/Surge/JS/Google_CAPTCHA.js",
+ "icons": [
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Alpha/Google.png",
+ "https://raw.githubusercontent.com/NobyDa/mini/master/Color/Google.png"
+ ]
}
],
"task": [
diff --git a/QuantumultX/Snippet/GoogleCAPTCHA.snippet b/QuantumultX/Snippet/GoogleCAPTCHA.snippet
new file mode 100644
index 0000000000..0f7e985912
--- /dev/null
+++ b/QuantumultX/Snippet/GoogleCAPTCHA.snippet
@@ -0,0 +1,12 @@
+# QuantumultX 远程重写配置片段
+
+# Google搜索人机验证解决方案
+# Google搜索内容时并发使用多个代理策略、策略组尝试搜索内容,并返回最优结果。具体细节可查看脚本注释。
+
+# 脚本:https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js
+# 片段:https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/GoogleCAPTCHA.snippet
+
+
+^https:\/\/www\.google\.com(?:\.[a-z]+|)\/(?:search\?(?:|.+?&)q=|$) url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js
+
+hostname = www.google.com*
\ No newline at end of file
diff --git a/Surge/JS/Google_CAPTCHA.js b/Surge/JS/Google_CAPTCHA.js
index 84e8554fe2..630e57adaf 100644
--- a/Surge/JS/Google_CAPTCHA.js
+++ b/Surge/JS/Google_CAPTCHA.js
@@ -1,65 +1,126 @@
-/*
-Google搜索内容时并发使用多个策略(组),以避免可能出现的人机验证
+/********************************
+Google搜索人机验证解决方案
+搜索内容时遇到人机验证立即并发使用多个代理策略、策略组尝试搜索内容,并返回最优结果。
-注:该脚本仅兼容Surge(4.9.3+),使用时需要在脚本配置内的argument参数中填写筛选策略/组的正则表达式,留空则表示同时使用所有策略/组
+脚本作者:@NobyDa
+更新时间:2024/05/16
+平台兼容:Surge(iOS4.9.3+/macOS4.2.3+) / QuantumultX(1.0.26+)
-Surge脚本配置:
+可在BoxJs或Surge脚本配置参数(argument)填写筛选的代理策略、策略组的正则表达式。
+所有代理策略、策略组至多筛选、使用20个,不筛选则表示随机使用。
-[Script]
-Google CAPTCHA = type=http-response,pattern=^https:\/\/www\.google\.com(?:\.[a-z]+|)\/(?:search\?(?:|.+?&)q=|$),requires-body=1,debug=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js,max-size=0,timeout=10,ability=http-client-policy,argument=^(🇸🇬|🇭🇰)\s.*\d+$
+注意:Surge由于策略架构问题,正则表达式筛选的"代理策略"不包含"外部代理策略";
+QuantumultX无此限制,正则表达式可筛选所有"策略组"内的"代理策略"。
-[MITM]
-hostname = www.google.com*
+*********************************
+Surge(iOS 5.9.0+/macOS 5.5.0+) 模块:
+https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/GoogleCAPTCHA.sgmodule
-*/
+*********************************
+QuantumultX(1.0.26+) 重写资源引用:
+https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/GoogleCAPTCHA.snippet
-let ret = {};
+*********************************/
-(async () => {
- if ($response.status !== 200) {
- const allPolicy = await new Promise((r) => {
- $httpAPI("GET", "v1/policies", null, (v) => r(
- [...v.proxies, ...v['policy-groups']]
- ))
- });
- const selected = allPolicy.filter((n) => {
- return n && new RegExp(typeof $argument == 'string' ? $argument : "").test(n)
- });
- console.log(`[INFO]: Use policy ${JSON.stringify(selected, null, 2)}`);
- delete $request.headers.cookie;
- delete $request.headers.Cookie;
- const http = [
- new Promise((r, e) => setTimeout(() => e('Timeout'), 5000)),
- ...selected.map(
- (v) => new Promise((r, e) => {
- $httpClient[$request.method.toLowerCase()]({
- url: $request.url,
- headers: $request.headers,
- policy: v
- }, (error, response, body) => {
- if (response && response.status == 200) {
- r({
- policy: v,
- body: {
- headers: response.headers,
- status: response.status,
- body: body
- }
- })
- } else if (response && response.status == 429) {
- console.log(`[ERROR]: Policy "${v}" need to CAPTCHA`);
- } else if (error) {
- console.log(`[ERROR]: Policy "${v}" ${error}`);
- }
- })
- })
- )
- ];
- await Promise.race(http).then((data) => {
- ret = data.body;
- console.log(`[INFO]: Use data from "${data.policy}"`);
- });
- }
+const $ = new NobyDa_Tools();
+$.ret = {};
+
+!(async () => {
+ if (($response.status || $response.statusCode) == 200) return;
+ const req = JSON.parse(JSON.stringify($request));
+ const policy = await $.policy();
+ const regexText = (typeof $argument == 'string' && $argument) ||
+ JSON.parse($.data.read('GOOGLE_CAPTCHA') || '{}').Regex || ''; // empty = all
+ const selected = [...policy.group, ...policy.proxy]
+ .filter((n) => n && new RegExp(regexText).test(n))
+ .sort(() => Math.random() - 0.5).slice(0, 20); // prevent too many TCP, filtered to random select up to 20
+ console.log(`[INFO]: Use policy ${JSON.stringify(selected, null, 2)}`);
+ await Promise.any([
+ ...selected.map(
+ (i) => new Promise((r, e) => {
+ if (req.headers['User-Agent']) req.headers.Cookie = `${Math.random()}`; // prevent set-cookie
+ if (req.headers['user-agent']) req.headers.cookie = `${Math.random()}`; // h2
+ $.http[req.method.toLowerCase()]({
+ policy: i, node: i, opts: { policy: i }, // policy:surge, node:loon, opts:qx
+ ...req
+ }).then((v) => {
+ if (v.status == 200) {
+ r({ policy: i, body: { ...v, status: $.isQuanX ? 'HTTP/1.1 200' : 200 } })
+ } else if (v.status == 429) {
+ e(console.log(`[INFO]: Policy "${i}" need to CAPTCHA`))
+ } else {
+ e(console.log(`[INFO]: Policy "${i}" unknown resp status "${v.status}"`))
+ }
+ }).catch((err) => e(console.log(`[ERROR]: ${err}`)))
+ })
+ )
+ ]).then((data) => {
+ $.ret = data.body;
+ console.log(`[INFO]: Use data from "${data.policy}"`);
+ })
})()
.catch((err) => console.log(`[ERROR]: ${(err && err.message) || err}`))
- .finally(() => $done(ret));
\ No newline at end of file
+ .finally(() => $done($.ret));
+
+
+function NobyDa_Tools() {
+ this.isLoon = typeof $loon !== "undefined";
+ this.isQuanX = typeof $configuration !== 'undefined';
+ this.isSurge = typeof $environment !== 'undefined' && $environment['surge-version'];
+ this.isNode = typeof module !== 'undefined'&& !!module.exports;
+ this.http = Object.fromEntries(
+ ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].map(
+ (m) => [m.toLowerCase(), (opts) => {
+ if (this.isQuanX) return new Promise((resolve, reject) => {
+ $task.fetch({ method: m, ...opts })
+ .then((r) => resolve({
+ status: r.statusCode, headers: r.headers, body: r.body,
+ }), e => reject(e.error))
+ });
+ if (this.isSurge || this.isLoon || this.isNode) return new Promise((resolve, reject) => {
+ const request = this.isNode ? require("request") : $httpClient;
+ request[m.toLowerCase()](opts, (e, r, b) => {
+ if (e) reject(e);
+ else resolve({ status: r.status || r.statusCode, headers: r.headers, body: b })
+ })
+ });
+ }]
+ )
+ );
+ this.policy = () => {
+ if (this.isSurge) return new Promise((r) => {
+ $httpAPI("GET", "v1/policies", null, (v) => r({
+ proxy: v.proxies,
+ group: v['policy-groups']
+ }))
+ });
+ if (this.isQuanX) return new Promise((r) => {
+ $configuration.sendMessage({
+ action: "get_customized_policy"
+ }).then(b => r({
+ proxy: Object.keys(b.ret)
+ .reduce((t, i) => [...new Set([...t, ...b.ret[i].candidates || []])], [])
+ .filter((v) => !b.ret[v] && !['direct', 'proxy', 'reject'].includes(v)),
+ group: Object.keys(b.ret)
+ }), () => r({}));
+ });
+ // if (this.isLoon) {
+ // const config = JSON.parse($config.getConfig());
+ // const proxy = config['all_policy_groups']
+ // .reduce((t, i) => [...new Set([...t, ...JSON.parse($config.getSubPolicies(i) || '[]').map(n => n.name)])], [])
+ // .filter((v) => ![...config['all_policy_groups'], ...config['all_buildin_nodes']].includes(v));
+ // return { proxy, group: config['all_policy_groups'] }
+ // };
+ };
+ this.data = Object.fromEntries(['read', 'write'].map(
+ (i) => [i, (v1, v2) => {
+ if (i === 'write') {
+ if (this.isSurge || this.isLoon) return $persistentStore.write(v1, v2);
+ if (this.isQuanX) return $prefs.setValueForKey(v1, v2);
+ } else if (i === 'read') {
+ if (this.isSurge || this.isLoon) return $persistentStore.read(v1);
+ if (this.isQuanX) return $prefs.valueForKey(v1);
+ }
+ }]
+ ));
+}
\ No newline at end of file
From e28453c223da9784020a8c6ecbc4ffa31c0d71f7 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 19 May 2024 21:58:41 +0800
Subject: [PATCH 098/105] Google_CAPTCHA.js now supports loon
---
Loon/Loon_Google_CAPTCHA.plugin | 14 ++++++++++++
NobyDa_BoxJs.json | 14 ++++++++++++
Surge/JS/Google_CAPTCHA.js | 40 ++++++++++++++++++++++-----------
3 files changed, 55 insertions(+), 13 deletions(-)
create mode 100644 Loon/Loon_Google_CAPTCHA.plugin
diff --git a/Loon/Loon_Google_CAPTCHA.plugin b/Loon/Loon_Google_CAPTCHA.plugin
new file mode 100644
index 0000000000..7baec65ae4
--- /dev/null
+++ b/Loon/Loon_Google_CAPTCHA.plugin
@@ -0,0 +1,14 @@
+#!name = Google人机验证
+#!desc = Google搜索内容时并发使用多个策略/策略组,以避免可能出现的人机验证。注意:需要在插件参数填写策略/策略组名的正则表达式。
+#!author = NobyDa
+#!input = GOOGLE_CAPTCHA_REGEX
+#!homepage = https://github.com/NobyDa/Script/tree/master
+#!icon = https://cdn.jsdelivr.net/gh/NobyDa/mini@master/Color/Google.png
+#!date = 2024-05-19 12:00:00
+
+
+[Script]
+http-response ^https:\/\/www\.google\.com(?:\.[a-z]+|)\/(?:search\?(?:|.+?&)q=|$) requires-body=1,timeout=30,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js,tag=Google人机验证
+
+[MITM]
+hostname = www.google.com*
\ No newline at end of file
diff --git a/NobyDa_BoxJs.json b/NobyDa_BoxJs.json
index 26c427c286..f162ecf3c4 100644
--- a/NobyDa_BoxJs.json
+++ b/NobyDa_BoxJs.json
@@ -682,6 +682,20 @@
"type": "text",
"placeholder": "^(🇸🇬|🇭🇰)\\s.*\\d+$",
"desc": "筛选的代理策略/策略组, 限制20个, 留空则表示随机使用。"
+ },
+ {
+ "id": "@GOOGLE_CAPTCHA.RegexTest",
+ "name": "正则表达式测试",
+ "val": "",
+ "type": "text",
+ "placeholder": "(🇸🇬|🇭🇰)",
+ "desc": "填写并保存后可在右上角测试匹配的策略/策略组。"
+ }
+ ],
+ "scripts": [
+ {
+ "name": "测试匹配的策略/策略组",
+ "script": "https://gist.githubusercontent.com/NobyDa/830932e4526c9c84169020a56c3ef199/raw/GOOGLE_CAPTCHA_TEST_POLICY.js"
}
],
"author": "@NobyDa",
diff --git a/Surge/JS/Google_CAPTCHA.js b/Surge/JS/Google_CAPTCHA.js
index 630e57adaf..4b96ec11f1 100644
--- a/Surge/JS/Google_CAPTCHA.js
+++ b/Surge/JS/Google_CAPTCHA.js
@@ -3,14 +3,14 @@ Google搜索人机验证解决方案
搜索内容时遇到人机验证立即并发使用多个代理策略、策略组尝试搜索内容,并返回最优结果。
脚本作者:@NobyDa
-更新时间:2024/05/16
-平台兼容:Surge(iOS4.9.3+/macOS4.2.3+) / QuantumultX(1.0.26+)
+更新时间:2024/05/19
+平台兼容:Surge(iOS4.9.3+/macOS4.2.3+) / QuantumultX(1.0.26+) / Loon(3.1.9[694]+)
-可在BoxJs或Surge脚本配置参数(argument)填写筛选的代理策略、策略组的正则表达式。
-所有代理策略、策略组至多筛选、使用20个,不筛选则表示随机使用。
+可在 BoxJs(低优先级)、Surge模块参数、Loon插件参数中填写筛选的代理策略、策略组的正则表达式。
+所有代理策略、策略组至多筛选、使用20个,可在BoxJs中测试匹配的策略,不筛选则表示随机使用。
注意:Surge由于策略架构问题,正则表达式筛选的"代理策略"不包含"外部代理策略";
-QuantumultX无此限制,正则表达式可筛选所有"策略组"内的"代理策略"。
+QuantumultX、Loon则无此限制,正则表达式可筛选所有"策略组"内的"代理策略"。
*********************************
Surge(iOS 5.9.0+/macOS 5.5.0+) 模块:
@@ -20,6 +20,14 @@ https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/GoogleCAPTCH
QuantumultX(1.0.26+) 重写资源引用:
https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/GoogleCAPTCHA.snippet
+*********************************
+Loon(3.1.9[694]+) 插件:
+https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_Google_CAPTCHA.plugin
+
+*********************************
+BoxJs 订阅地址:
+https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
+
*********************************/
const $ = new NobyDa_Tools();
@@ -30,6 +38,7 @@ $.ret = {};
const req = JSON.parse(JSON.stringify($request));
const policy = await $.policy();
const regexText = (typeof $argument == 'string' && $argument) ||
+ $.data.read('GOOGLE_CAPTCHA_REGEX') || // loon plugin args.
JSON.parse($.data.read('GOOGLE_CAPTCHA') || '{}').Regex || ''; // empty = all
const selected = [...policy.group, ...policy.proxy]
.filter((n) => n && new RegExp(regexText).test(n))
@@ -67,7 +76,7 @@ function NobyDa_Tools() {
this.isLoon = typeof $loon !== "undefined";
this.isQuanX = typeof $configuration !== 'undefined';
this.isSurge = typeof $environment !== 'undefined' && $environment['surge-version'];
- this.isNode = typeof module !== 'undefined'&& !!module.exports;
+ this.isNode = typeof module !== 'undefined' && !!module.exports;
this.http = Object.fromEntries(
["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].map(
(m) => [m.toLowerCase(), (opts) => {
@@ -104,13 +113,18 @@ function NobyDa_Tools() {
group: Object.keys(b.ret)
}), () => r({}));
});
- // if (this.isLoon) {
- // const config = JSON.parse($config.getConfig());
- // const proxy = config['all_policy_groups']
- // .reduce((t, i) => [...new Set([...t, ...JSON.parse($config.getSubPolicies(i) || '[]').map(n => n.name)])], [])
- // .filter((v) => ![...config['all_policy_groups'], ...config['all_buildin_nodes']].includes(v));
- // return { proxy, group: config['all_policy_groups'] }
- // };
+ if (this.isLoon) return new Promise(async (r1) => {
+ const config = JSON.parse($config.getConfig());
+ const groupData = await Promise.all(config['all_policy_groups'].map((i) => new Promise((r2) => {
+ $config.getSubPolicies(i, (b) => { r2(JSON.parse(b || '[]')) })
+ })));
+ r1({
+ proxy: groupData.reduce((t, i) => [...new Set([...t, ...i.filter((v) => {
+ return v.type == 'node' && !config['all_buildin_nodes'].includes(v.name)
+ }).map((n) => n.name)])], []),
+ group: config['all_policy_groups']
+ })
+ });
};
this.data = Object.fromEntries(['read', 'write'].map(
(i) => [i, (v1, v2) => {
From ad57633758629897b823f515b2d8034ff3de3047 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 2 Jun 2024 21:07:13 +0800
Subject: [PATCH 099/105] Minor improvements.
---
BDTieBa-DailyBonus/TieBa.js | 92 ++++++++-------------------
Bilibili-DailyBonus/ExchangePoints.js | 36 +++++++----
2 files changed, 52 insertions(+), 76 deletions(-)
diff --git a/BDTieBa-DailyBonus/TieBa.js b/BDTieBa-DailyBonus/TieBa.js
index a5c9984c0c..104b018db5 100644
--- a/BDTieBa-DailyBonus/TieBa.js
+++ b/BDTieBa-DailyBonus/TieBa.js
@@ -1,57 +1,32 @@
-/*
+/*********************************
百度贴吧签到脚本
-脚本修改自: https://github.com/sazs34/TaskConfig
-兼容: QuantumultX, Surge4, Loon
+脚本原作者: @sazs34
+平台兼容: QuantumultX, Surge, Loon
+更新日期: 2024/06/01
获取Cookie说明:
-打开百度贴吧App后(AppStore中国区, 非内部版),点击"我的", 如通知成功获取cookie, 则可以使用此签到脚本.
-获取Cookie后, 请将Cookie脚本禁用并移除主机名,以免产生不必要的MITM.
-脚本将在每天上午9:00执行, 您可以修改执行时间。
+打开百度贴吧App后(AppStore中国区, 非内部版),点击"我的", 如通知成功获取cookie则可以使用该脚本.
-************************
-Surge 4.2.0+ 脚本配置:
-************************
+*********************************
+Surge(iOS 5.9.0+/macOS 5.5.0+)模块:
+https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/TieBaDailyBonus.sgmodule
-[Script]
-贴吧签到 = type=cron,cronexp=0 9 * * *,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js
+*********************************
+QuantumultX 任务仓库(Gallery)订阅:
+https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
-贴吧获取Cookie = type=http-request,pattern=https?:\/\/(c\.tieba\.baidu\.com|180\.97\.\d+\.\d+)\/c\/s\/login,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js
+工具&分析->HTTP请求->右上角添加任务仓库->选择百度贴吧签到脚本添加定时任务和附加组件
-[MITM]
-hostname= c.tieba.baidu.com
+*********************************
+Loon 脚本订阅(非插件):
+https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_Daily_bonus.plugin
-************************
-QuantumultX 本地脚本配置:
-************************
+添加后请按需启用脚本
-[task_local]
-# 贴吧签到
-0 9 * * * TieBa.js
+*********************************/
-[rewrite_local]
-# 获取Cookie
-https?:\/\/(c\.tieba\.baidu\.com|180\.97\.\d+\.\d+)\/c\/s\/login url script-request-header TieBa.js
-[mitm]
-hostname= c.tieba.baidu.com
-
-************************
-Loon 2.1.0+ 脚本配置:
-************************
-
-[Script]
-# 贴吧签到
-cron "0 9 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js
-
-# 获取Cookie
-http-request https?:\/\/(c\.tieba\.baidu\.com|180\.97\.\d+\.\d+)\/c\/s\/login script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js
-
-[Mitm]
-hostname= c.tieba.baidu.com
-
-
-*/
var $nobyda = nobyda();
var cookieVal = $nobyda.read("CookieTB");
var useParallel = 0; //0自动切换,1串行,2并行(当贴吧数量大于30个以后,并行可能会导致QX崩溃,所以您可以自动切换)
@@ -254,31 +229,18 @@ function checkIsAllProcessed() {
}
function GetCookie() {
- var headerCookie = $request.headers["Cookie"];
- if (headerCookie) {
- if ($nobyda.read("CookieTB") != undefined) {
- if ($nobyda.read("CookieTB") != headerCookie) {
- if (headerCookie.indexOf("BDUSS") != -1) {
- var cookie = $nobyda.write(headerCookie, "CookieTB");
- if (!cookie) {
- $nobyda.notify("更新贴吧Cookie失败‼️", "", "");
- } else {
- $nobyda.notify("更新贴吧Cookie成功 🎉", "", "");
- }
- }
- }
- } else {
- if (headerCookie.indexOf("BDUSS") != -1) {
- var cookie = $nobyda.write(headerCookie, "CookieTB");
- if (!cookie) {
- $nobyda.notify("首次写入贴吧Cookie失败‼️", "", "");
- } else {
- $nobyda.notify("首次写入贴吧Cookie成功 🎉", "", "");
- }
+ let headerCookie = $request.headers["Cookie"] || $request.headers["cookie"];
+ if (headerCookie && headerCookie.includes('BDUSS=')) {
+ if (!cookieVal) {
+ $nobyda.notify("写入百度贴吧Cookie成功 🎉", "", "");
+ } else {
+ console.log(`写入百度贴吧Cookie成功 🎉`);
}
- }
+ $nobyda.write(headerCookie, "CookieTB")
+ } else {
+ console.log(`写入Cookie失败, BDUSS值缺失. `);
}
- $nobyda.done()
+ return $nobyda.done();
}
function nobyda() {
diff --git a/Bilibili-DailyBonus/ExchangePoints.js b/Bilibili-DailyBonus/ExchangePoints.js
index 811e34634c..fecf645070 100644
--- a/Bilibili-DailyBonus/ExchangePoints.js
+++ b/Bilibili-DailyBonus/ExchangePoints.js
@@ -1,15 +1,17 @@
/*
哔哩哔哩漫画, 积分商城自动抢购脚本
-脚本兼容: Surge, QuantumultX, Loon
+脚本作者:@NobyDa
+更新时间:2024/06/01
+平台兼容:Surge, QuantumultX, Loon
*************************
【 抢购脚本注意事项 】:
*************************
该脚本需要使用签到脚本获取Cookie后方可使用.
-默认兑换积分商城中的"积分兑换", 兑换数量为用户积分可兑换的最大值 (可于BoxJs内修改)
-默认执行时间为中午12:00:10、12:00:20、12:00:30
+默认兑换积分商城中的"【超特惠】限量-0点秒杀", 兑换数量为用户积分可兑换的最大值 (可于BoxJs内修改)
+默认执行时间为:每周日、每周一的凌晨 0:00:00 - 0:01:59 之间每秒执行一次
BoxJs订阅地址: https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
@@ -18,28 +20,31 @@ BoxJs订阅地址: https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa
*************************
[Script]
-cron "10,20,30 0 12 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/ExchangePoints.js, wake-system=1, timeout=60
+cron "0-59 0 0 * * 0-1" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/ExchangePoints.js, wake-system=1, timeout=60
*************************
【 QX 1.0.10+ 脚本配置 】 :
*************************
[task_local]
-10,20,30 0 12 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/ExchangePoints.js, tag=哔哩哔哩漫画抢券, enabled=true
+0-59 0 0 * * 0-1 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/ExchangePoints.js, tag=哔哩哔哩漫画抢券, enabled=true
*/
// 新建一个实例对象, 把兼容函数定义到$中, 以便统一调用
let $ = new nobyda();
-// 读取兑换商品名, 默认兑换积分商城中的"积分兑换"; 该接口为BoxJs预留, 以便修改
-let productName = $.read('BM_ProductName') || '积分兑换';
+// 读取Surge脚本参数并转成对象
+let args = argsList(typeof $argument == "string" && $argument || '');
-// 读取兑换数量, 默认兑换最大值; 该接口为BoxJs预留, 以便修改
-let productNum = $.read('BM_ProductNum');
+// 读取兑换商品名, 默认兑换积分商城中的"【超特惠】限量-0点秒杀"
+let productName = args.ProductName || $.read('BM_ProductName') || '【超特惠】限量-0点秒杀';
-// 读取循环抢购次数, 默认100次; 该接口为BoxJs预留, 以便修改
-let exchangeNum = $.read('BM_ExchangeNum') || '100';
+// 读取兑换数量, 默认兑换最大值
+let productNum = parseInt(args.ProductNum) || $.read('BM_ProductNum');
+
+// 读取循环抢购次数, 默认100次
+let exchangeNum = args.ExchangeNum || $.read('BM_ExchangeNum') || '100';
// 读取哔哩哔哩漫画签到脚本所使用的Cookie
let cookie = $.read('CookieBM');
@@ -176,6 +181,15 @@ function startExchange(url, item, amount) {
})
}
+function argsList(data) {
+ return Array.from(
+ data.split("&")
+ .map((i) => i.split("="))
+ .map(([k, v]) => [k, decodeURIComponent(v)])
+ )
+ .reduce((a, [k, v]) => Object.assign(a, { [k]: v }), {})
+}
+
function nobyda() {
const isSurge = typeof $httpClient != "undefined";
const isQuanX = typeof $task != "undefined";
From c3289c86fad8e6449e2a20c90eeca5e38006fa14 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 2 Jun 2024 21:14:01 +0800
Subject: [PATCH 100/105] Subscription improvements.
---
Loon/Loon_Daily_bonus.plugin | 38 +++++++++++++++++++
Loon/Loon_GetCookie.plugin | 10 ++---
Surge/Module/BahamutDailyBonus.sgmodule | 8 ++++
Surge/Module/BiliComicsDailyBonus.sgmodule | 13 +++++++
.../Module/BiliComicsExchangePoints.sgmodule | 8 ++++
Surge/Module/CtripDailyBonus.sgmodule | 6 +--
Surge/Module/GetCookie.sgmodule | 17 ++++-----
Surge/Module/KuaiKanComicsDailyBonus.sgmodule | 13 +++++++
Surge/Module/TieBaDailyBonus.sgmodule | 13 +++++++
Surge/Module/iQIYIDailyBonus.sgmodule | 13 +++++++
10 files changed, 120 insertions(+), 19 deletions(-)
create mode 100644 Loon/Loon_Daily_bonus.plugin
create mode 100644 Surge/Module/BahamutDailyBonus.sgmodule
create mode 100644 Surge/Module/BiliComicsDailyBonus.sgmodule
create mode 100644 Surge/Module/BiliComicsExchangePoints.sgmodule
create mode 100644 Surge/Module/KuaiKanComicsDailyBonus.sgmodule
create mode 100644 Surge/Module/TieBaDailyBonus.sgmodule
create mode 100644 Surge/Module/iQIYIDailyBonus.sgmodule
diff --git a/Loon/Loon_Daily_bonus.plugin b/Loon/Loon_Daily_bonus.plugin
new file mode 100644
index 0000000000..fb8a2f2a76
--- /dev/null
+++ b/Loon/Loon_Daily_bonus.plugin
@@ -0,0 +1,38 @@
+#!name= 🐻 NobyDa签到脚本
+#!desc= 包括哔哩漫画、贴吧、快看、爱奇艺,携程旅行、巴哈姆特。部分脚本获取Cookie方法请看脚本注释。注意,该Loon链接目前仅适用于"订阅脚本",非"插件"。添加脚本订阅后请按需启用脚本。
+#!author= NobyDa
+#!homepage= https://github.com/NobyDa/Script/tree/master
+#!icon= https://raw.githubusercontent.com/github/explore/80688e429a7d4ef2fca1e82350fe8e3517d3494d/topics/javascript/javascript.png
+
+
+[Script]
+cron "30 8 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/ctrip.png, timeout=300, enabled=false, tag=携程旅行 [签到]
+
+http-response ^https:\/\/m\.ctrip\.com\/restapi\/soa2\/\d+\/[a-zA-Z]+Login(?:$|\?) script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/ctrip.png, requires-body=true, enabled=false, tag=携程旅行 [Cookie]
+
+
+cron "10 9 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/iQIYI.png, timeout=300, enabled=false, tag=爱奇艺 [会员签到]
+
+http-request ^https:\/\/passport\.iqiyi\.com\/apis\/user\/ script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/iQIYI.png, enabled=false, tag=爱奇艺 [Cookie]
+
+
+cron "0 9 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/manga.png, timeout=300, enabled=false, tag=哔哩漫画 [签到]
+
+http-request ^https:\/\/app\.bilibili\.com\/x\/v2\/account\/myinfo script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/manga.png, enabled=false, tag=哔哩漫画 [Cookie]
+
+
+cron "40 8 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/tieba.png, timeout=300, enabled=false, tag=百度贴吧 [签到]
+
+http-request ^https?:\/\/(c\.tieba|tiebac)\.baidu\.com\/c\/s\/login script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/tieba.png, enabled=false, tag=百度贴吧 [Cookie]
+
+
+cron "10 9 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/KuaiKan.png, timeout=300, enabled=false, tag=快看漫画 [签到]
+
+http-request ^https?:\/\/api\.kkmh\.com\/v\d\/passport\/user script-path=https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/KuaiKan.png, enabled=false, tag=快看漫画 [Cookie]
+
+
+cron "20 8 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutDailyBonus.js, img-url=https://raw.githubusercontent.com/NobyDa/mini/master/Color/bahamutGame.png, timeout=300, enabled=false, tag=巴哈姆特 [签到]
+
+
+[MITM]
+hostname = passport.iqiyi.com, app.bilibili.com, c.tieba.baidu.com, tiebac.baidu.com, api.kkmh.com, m.ctrip.com
\ No newline at end of file
diff --git a/Loon/Loon_GetCookie.plugin b/Loon/Loon_GetCookie.plugin
index 07e2b29849..078e52b0ee 100644
--- a/Loon/Loon_GetCookie.plugin
+++ b/Loon/Loon_GetCookie.plugin
@@ -1,21 +1,19 @@
#!name= NobyDa签到脚本Cookie获取
-#!desc= 包括京东、哔哩漫画、贴吧、快看、吾爱、爱奇艺,获取方法请看脚本注释;建议使用后手动将该插件禁用, 以避免无意义的MITM。
+#!desc= 包括哔哩漫画、贴吧、快看、爱奇艺,携程旅行。获取方法请看脚本注释;建议使用后手动将该插件禁用, 以避免无意义的MITM。
#!author= NobyDa
#!homepage= https://github.com/NobyDa/Script/tree/master
#!icon= https://raw.githubusercontent.com/github/explore/80688e429a7d4ef2fca1e82350fe8e3517d3494d/topics/javascript/javascript.png
[Script]
-http-request ^https:\/\/(api\.m|me-api|ms\.jr)\.jd\.com\/(client\.action\?functionId=signBean|user_new\/info\/GetJDUserInfoUnion\?|gw\/generic\/hy\/h5\/m\/appSign\?) script-path=https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js, requires-body=1, tag=京东签到Cookie
-
http-request ^https:\/\/passport\.iqiyi\.com\/apis\/user\/ script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js, tag=爱奇艺Cookie
http-request ^https:\/\/app\.bilibili\.com\/x\/v2\/account\/myinfo script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js, tag=哔哩漫画Cookie
-http-request ^https?:\/\/(c\.tieba\.baidu\.com|180\.97\.\d+\.\d+)\/c\/s\/login script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js, tag=百度贴吧Cookie
+http-request ^https?:\/\/(c\.tieba|tiebac)\.baidu\.com\/c\/s\/login script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js, tag=百度贴吧Cookie
http-request ^https?:\/\/api\.kkmh\.com\/v\d\/passport\/user script-path=https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js, tag=快看漫画Cookie
-http-request https:\/\/www\.52pojie\.cn\/home\.php\? script-path=https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js, tag=吾爱破解Cookie
+http-response ^https:\/\/m\.ctrip\.com\/restapi\/soa2\/\d+\/[a-zA-Z]+Login(?:$|\?) script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js, requires-body=true, tag=携程旅行Cookie
[MITM]
-hostname = passport.iqiyi.com, api.m.jd.com, ms.jr.jd.com, me-api.jd.com, app.bilibili.com, c.tieba.baidu.com, api.kkmh.com, www.52pojie.cn
\ No newline at end of file
+hostname = passport.iqiyi.com, app.bilibili.com, c.tieba.baidu.com, tiebac.baidu.com, api.kkmh.com, m.ctrip.com
\ No newline at end of file
diff --git a/Surge/Module/BahamutDailyBonus.sgmodule b/Surge/Module/BahamutDailyBonus.sgmodule
new file mode 100644
index 0000000000..4fecbd3759
--- /dev/null
+++ b/Surge/Module/BahamutDailyBonus.sgmodule
@@ -0,0 +1,8 @@
+#!name=🐻 巴哈姆特 [签到]
+#!desc=每日定时签到,包含主站签到、公会签到、动画疯答题等;模块参数可调整签到时间。\n使用前需要进入BoxJs填写账号密码,BoxJs订阅链接可查看脚本注释。
+#!arguments=定时签到:20 8 * * *
+#!arguments-desc=定时签到:Cron表达式,默认每天早上 08:20 执行。(如需动画疯答题,不建议在凌晨0:00-0:30执行)
+#!category=🐻 NobyDa
+
+[Script]
+巴哈姆特[签到] = type=cron,cronexp="{{{定时签到}}}",wake-system=1,script-update-interval=0,timeout=300,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bahamut/BahamutDailyBonus.js
\ No newline at end of file
diff --git a/Surge/Module/BiliComicsDailyBonus.sgmodule b/Surge/Module/BiliComicsDailyBonus.sgmodule
new file mode 100644
index 0000000000..ad94ba1a36
--- /dev/null
+++ b/Surge/Module/BiliComicsDailyBonus.sgmodule
@@ -0,0 +1,13 @@
+#!name=🐻 哔哩哔哩漫画 [签到]
+#!desc=每日定时签到,模块参数可调整签到时间。\n打开哔哩哔哩漫画APP点击"我的"即可获取cookie.
+#!arguments=定时签到:0 9 * * *,禁用脚本:哔哩漫画[Cookie],禁用MITM:hostname
+#!arguments-desc=定时签到:Cron表达式,默认每天早上 09:00 执行。\n\n禁用脚本:禁用获取Cookie脚本,输入 # 表示禁用。\n\n禁用MITM:禁用MITM主机名,输入 # 表示禁用。
+#!category=🐻 NobyDa
+
+[Script]
+哔哩漫画[签到] = type=cron,cronexp="{{{定时签到}}}",wake-system=1,script-update-interval=0,timeout=60,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js
+
+{{{禁用脚本}}} = type=http-request,pattern=^https:\/\/app\.bilibili\.com\/x\/v\d\/account\/myinfo,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js
+
+[MITM]
+{{{禁用MITM}}} = %APPEND% app.bilibili.com
\ No newline at end of file
diff --git a/Surge/Module/BiliComicsExchangePoints.sgmodule b/Surge/Module/BiliComicsExchangePoints.sgmodule
new file mode 100644
index 0000000000..6d8474bcab
--- /dev/null
+++ b/Surge/Module/BiliComicsExchangePoints.sgmodule
@@ -0,0 +1,8 @@
+#!name=🐻 哔哩哔哩漫画 [积分抢购]
+#!desc=定时抢购积分商城物品,模块参数可调整抢购设置,该模块需使用"哔哩哔哩漫画签到模块"获取Cookie。
+#!arguments=定时抢购:0-59 0 0 * * 0-1,商品名称:【超特惠】限量-0点秒杀,抢购数量:0,抢购次数:100
+#!arguments-desc=定时抢购:Cron表达式,默认每周日、每周一的凌晨 0:00:00 - 0:01:59 之间每秒执行一次。\n\n商品名称:默认抢购商品名"【超特惠】限量-0点秒杀"\n\n抢购数量:默认为用户积分可抢购的最大值(以0表示)\n\n抢购次数:抢购失败时重试次数,默认100次
+#!category=🐻 NobyDa
+
+[Script]
+哔哩漫画[积分抢购] = type=cron,cronexp="{{{定时抢购}}}",script-update-interval=0,timeout=60,wake-system=1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/ExchangePoints.js,argument="ProductName={{{商品名称}}}&ProductNum={{{抢购数量}}}&ExchangeNum={{{抢购次数}}}
\ No newline at end of file
diff --git a/Surge/Module/CtripDailyBonus.sgmodule b/Surge/Module/CtripDailyBonus.sgmodule
index 2d20994e92..0ae64b88fa 100644
--- a/Surge/Module/CtripDailyBonus.sgmodule
+++ b/Surge/Module/CtripDailyBonus.sgmodule
@@ -1,11 +1,11 @@
-#!name=携程签到
+#!name=🐻 携程旅行 [签到]
#!desc=每日定时签到,支持多账号。\n登陆"携程旅行"微信小程序或"携程网页版"(https://m.ctrip.com/)可获取账号授权,填写模块参数可禁用脚本。
-#!arguments=定时签到:30 8 * * *,禁用脚本:携程旅行(获取),禁用MITM:hostname
+#!arguments=定时签到:30 8 * * *,禁用脚本:携程旅行[授权],禁用MITM:hostname
#!arguments-desc=定时签到:Cron表达式,默认每日 8:30 执行。\n\n禁用脚本:禁用获取授权脚本,输入 # 表示禁用。\n\n禁用MITM:禁用MITM主机名,输入 # 表示禁用。
#!category=🐻 NobyDa
[Script]
-携程旅行(签到) = type=cron,cronexp="{{{定时签到}}}",wake-system=1,script-update-interval=0,timeout=60,wake-system=1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js
+携程旅行[签到] = type=cron,cronexp="{{{定时签到}}}",wake-system=1,script-update-interval=0,timeout=300,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js
{{{禁用脚本}}} = type=http-response,pattern=^https:\/\/m\.ctrip\.com\/restapi\/soa2\/\d+\/[a-zA-Z]+Login(?:$|\?),requires-body=1,max-size=0,debug=0,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js
diff --git a/Surge/Module/GetCookie.sgmodule b/Surge/Module/GetCookie.sgmodule
index 26494b2e66..b26d78ce0c 100644
--- a/Surge/Module/GetCookie.sgmodule
+++ b/Surge/Module/GetCookie.sgmodule
@@ -1,20 +1,17 @@
-#!name=Get cookie. By NobyDa
-#!desc=该模块适用于定时签到脚本的Cookie获取. 集成: 京东, 吾爱破解, 爱奇艺, 哔哩哔哩漫画, 百度贴吧, 快看漫画; 您可以在使用后手动将其禁用,以免产生不必要的MITM.
+#!name=🐻 签到脚本Cookie获取
+#!desc=该模块适用于NobyDa定时签到脚本的Cookie获取. 集成: 爱奇艺, 哔哩哔哩漫画, 百度贴吧, 快看漫画, 携程旅行。
#!system=ios
[Script]
-
-吾爱Cookie = type=http-request,pattern=https:\/\/www\.52pojie\.cn\/home\.php\?,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/52pojie-DailyBonus/52pojie.js
-
爱奇艺Cookie = type=http-request,pattern=^https:\/\/passport\.iqiyi\.com\/apis\/user\/,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
-哔哩漫画Cookie = type=http-request,pattern=^https:\/\/passport\.biligame\.com\/api\/login\/sso.+?version%22%3A%22(3|4|5),script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js
+哔哩漫画Cookie = type=http-request,pattern=^https:\/\/app\.bilibili\.com\/x\/v\d\/account\/myinfo,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js
-贴吧Cookie = type=http-request,pattern=https?:\/\/(c\.tieba\.baidu\.com|180\.97\.\d+\.\d+)\/c\/s\/login,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js
+百度贴吧Cookie = type=http-request,pattern=^https?:\/\/(c\.tieba|tiebac)\.baidu\.com\/c\/s\/login,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js
-京东签到Cookie = type=http-request,requires-body=1,pattern=^https:\/\/(api\.m|me-api|ms\.jr)\.jd\.com\/(client\.action\?functionId=signBean|user_new\/info\/GetJDUserInfoUnion\?|gw\/generic\/hy\/h5\/m\/appSign\?),script-path=https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js
+快看漫画Cookie = type=http-request,pattern=^https:\/\/api\.kkmh\.com\/v\d\/passport\/user,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js
-快看漫画Cookie = type=http-request,pattern=https:\/\/api\.kkmh\.com\/v\d\/passport\/user,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js
+携程旅行Cookie = type=http-response,pattern=^https:\/\/m\.ctrip\.com\/restapi\/soa2\/\d+\/[a-zA-Z]+Login(?:$|\?),requires-body=1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Ctrip-DailyBonus/Ctrip.js
[MITM]
-hostname = %APPEND% passport.iqiyi.com, www.52pojie.cn, api.m.jd.com, ms.jr.jd.com, me-api.jd.com, passport.biligame.com, c.tieba.baidu.com, api.kkmh.com
\ No newline at end of file
+hostname = %APPEND% passport.iqiyi.com, app.bilibili.com, c.tieba.baidu.com, tiebac.baidu.com, api.kkmh.com, m.ctrip.com
\ No newline at end of file
diff --git a/Surge/Module/KuaiKanComicsDailyBonus.sgmodule b/Surge/Module/KuaiKanComicsDailyBonus.sgmodule
new file mode 100644
index 0000000000..c69570ca5c
--- /dev/null
+++ b/Surge/Module/KuaiKanComicsDailyBonus.sgmodule
@@ -0,0 +1,13 @@
+#!name=🐻 快看漫画 [签到]
+#!desc=每日定时签到,模块参数可调整签到时间。\n打开快看漫画APP点击"我的"即可获取cookie.
+#!arguments=定时签到:10 9 * * *,禁用脚本:快看漫画[Cookie],禁用MITM:hostname
+#!arguments-desc=定时签到:Cron表达式,默认每天早上 09:10 执行。\n\n禁用脚本:禁用获取Cookie脚本,输入 # 表示禁用。\n\n禁用MITM:禁用MITM主机名,输入 # 表示禁用。
+#!category=🐻 NobyDa
+
+[Script]
+快看漫画[签到] = type=cron,cronexp="{{{定时签到}}}",wake-system=1,script-update-interval=0,timeout=60,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js
+
+{{{禁用脚本}}} = type=http-request,pattern=^https?:\/\/api\.kkmh\.com\/v\d\/passport\/user,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/KuaiKan-DailyBonus/KKMH.js
+
+[MITM]
+{{{禁用MITM}}} = %APPEND% api.kkmh.com
\ No newline at end of file
diff --git a/Surge/Module/TieBaDailyBonus.sgmodule b/Surge/Module/TieBaDailyBonus.sgmodule
new file mode 100644
index 0000000000..294084e1b3
--- /dev/null
+++ b/Surge/Module/TieBaDailyBonus.sgmodule
@@ -0,0 +1,13 @@
+#!name=🐻 百度贴吧 [签到]
+#!desc=每日定时签到,模块参数可调整签到时间。\n打开百度贴吧APP点击"我的"即可获取cookie.
+#!arguments=定时签到:40 8 * * *,禁用脚本:百度贴吧[Cookie],禁用MITM:hostname
+#!arguments-desc=定时签到:Cron表达式,默认每天早上 08:40 执行。\n\n禁用脚本:禁用获取Cookie脚本,输入 # 表示禁用。\n\n禁用MITM:禁用MITM主机名,输入 # 表示禁用。
+#!category=🐻 NobyDa
+
+[Script]
+百度贴吧[签到] = type=cron,cronexp="{{{定时签到}}}",wake-system=1,script-update-interval=0,timeout=600,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js
+
+{{{禁用脚本}}} = type=http-request,pattern=^https?:\/\/(c\.tieba|tiebac)\.baidu\.com\/c\/s\/login,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/BDTieBa-DailyBonus/TieBa.js
+
+[MITM]
+{{{禁用MITM}}} = %APPEND% c.tieba.baidu.com, tiebac.baidu.com
\ No newline at end of file
diff --git a/Surge/Module/iQIYIDailyBonus.sgmodule b/Surge/Module/iQIYIDailyBonus.sgmodule
new file mode 100644
index 0000000000..d705c77753
--- /dev/null
+++ b/Surge/Module/iQIYIDailyBonus.sgmodule
@@ -0,0 +1,13 @@
+#!name=🐻 爱奇艺 [会员签到]
+#!desc=每日定时签到,模块参数可调整签到时间。\n登陆爱奇艺网页版 https://m.ctrip.com/ 使用密码登录可获取签到Cookie.
+#!arguments=定时签到:10 9 * * *,禁用脚本:爱奇艺[Cookie],禁用MITM:hostname
+#!arguments-desc=定时签到:Cron表达式,默认每天早上 09:10 执行。\n\n禁用脚本:禁用获取Cookie脚本,输入 # 表示禁用。\n\n禁用MITM:禁用MITM主机名,输入 # 表示禁用。
+#!category=🐻 NobyDa
+
+[Script]
+爱奇艺[会员签到] = type=cron,cronexp="{{{定时签到}}}",wake-system=1,script-update-interval=0,timeout=60,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
+
+{{{禁用脚本}}} = type=http-request,pattern=^https:\/\/passport\.iqiyi\.com\/apis\/user\/,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js
+
+[MITM]
+{{{禁用MITM}}} = %APPEND% passport.iqiyi.com
\ No newline at end of file
From 1ac36bdfa9162c4a412da6c7898bf485e957b0fb Mon Sep 17 00:00:00 2001
From: ocd0711
Date: Wed, 19 Jun 2024 14:45:42 +0800
Subject: [PATCH 101/105] bug fixes. (#481)
---
Bilibili-DailyBonus/Manga.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Bilibili-DailyBonus/Manga.js b/Bilibili-DailyBonus/Manga.js
index 0384d28099..f99ecd7c42 100644
--- a/Bilibili-DailyBonus/Manga.js
+++ b/Bilibili-DailyBonus/Manga.js
@@ -39,9 +39,9 @@ hostname = app.bilibili.com
const $ = new Env(`哔哩哔哩漫画`);
-const cookie = $.getdata("CookieBM") || ''; // 哔哩哔哩漫画Cookie
+const cookie = $.getdata("CookieBM") || ($.isNode() && process.env['CookieBM']) || ''; // 哔哩哔哩漫画Cookie
-const barkKey = ''; //Bark APP 通知推送Key
+const barkKey = $.isNode() && process.env['BM_BARK_KEY'] || ''; // bark key
if (typeof $request !== 'undefined') {
GetCookie(cookie)
From 10d1426d9d60edb37e24451b28811b163efc8e43 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Sun, 11 Aug 2024 22:01:41 +0800
Subject: [PATCH 102/105] Optimize memory usage.
---
Rule-Storage/Rule-Storage.js | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/Rule-Storage/Rule-Storage.js b/Rule-Storage/Rule-Storage.js
index 19ccd4ef91..56f56a3293 100644
--- a/Rule-Storage/Rule-Storage.js
+++ b/Rule-Storage/Rule-Storage.js
@@ -1,6 +1,6 @@
/*
Surge规则自动生成脚本
-更新时间:2024/05/07
+更新时间:2024/08/11
需按照博客内教程配合使用:
https://nobyda.github.io/2024/02/24/Surge_Rule_Storage
@@ -31,8 +31,12 @@ args.key = args.key || 'Rule-Storage';
if (!evalRules(host, saved_rules)) {
data[args.region] = saveDecision(host, data[args.region]);
if (data[args.region][host].quantity >= (args.quantity || 10)) {
- data.eTLD = await eTLD(data.eTLD);
- const suffix = shortenDomain(host, data.eTLD.public_suffix);
+ const eTLDs = await eTLD(data.eTLD || JSON.parse($persistentStore.read(`${args.key}-eTLD`) || '{}'));
+ if (data.eTLD) { // legacy
+ $persistentStore.write(JSON.stringify(data.eTLD), `${args.key}-eTLD`);
+ delete data.eTLD;
+ }
+ const suffix = shortenDomain(host, eTLDs.public_suffix);
const domain = evalRules(host, JSON.parse(args.whitelist)) ? host : suffix;
const text = [...formatRules(saved_rules), ...formatRules(domain)].join('\n');
delete data[args.region][host];
@@ -45,9 +49,23 @@ args.key = args.key || 'Rule-Storage';
.finally(() => $done({ matched: Boolean(args.matched) }));
function saveDecision(host_name, content = {}) {
+ const count = [];
for (const i in content) {
if (Date.now() - content[i].update_time > 86400000 * (args.cacheDays || 30)) {
delete content[i];
+ continue
+ }
+ count.push(content[i].update_time);
+ }
+ if (count.length > (args.cacheNumber || 1000)) { // limit amount to prevent NE memory issues.
+ const spill = count.sort((x, y) => x - y).slice(0, count.length - (args.cacheNumber || 1000));
+ for (const is of spill) {
+ for (const ic in content) {
+ if (content[ic].update_time === is) {
+ delete content[ic];
+ break
+ }
+ }
}
}
if (content[host_name]) {
@@ -99,6 +117,7 @@ async function eTLD(content = {}) {
if (resp.status == 200 && !error && body) {
content.update_time = Date.now();
content.public_suffix = body.replace(/\r|.*(\/\/|#|;).*|\n(\!|\*\.)/g, '\n').split('\n').filter((t) => t);
+ $persistentStore.write(JSON.stringify(content), `${args.key}-eTLD`);
resolve()
} else if (content.update_time) {
console.log(`Update eTLD list failed: ${error}`);
From b11b9be4eecedbe3366faa409b732aeef644e2a5 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Thu, 16 Jan 2025 16:33:16 +0800
Subject: [PATCH 103/105] revision.
---
README.md | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
index 2d53d4d436..dee52ced84 100755
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@
- [License](#license)
-> **Please note that the scripts or rewrite rules described below may require MITM to be enabled, and the generated root certificate needs to be manually installed and trusted in the system.**
+> **The scripts or rewrite rules described below may require enabling MITM. Additionally, the generated root certificate must be installed and trusted manually in the system.**
## Script Overview
@@ -99,27 +99,27 @@ Rules of type "Rule" include only ad hosts. Please select the REJECT policy.
Difference between QuantumultX versions (Click to view)
-* AppStore version QX1.0.0 (120) This version is the initial version, JS function is unlimited.
+* AppStore version QX1.0.0 (120): This is the initial version, and JS functionality is unrestricted.
-* AppStore version QX1.0.1 (130) This version adds support V2Ray(protocols), but restricts the keywords of the script VIP type.
+* AppStore version QX1.0.1 (130): This version adds support for V2Ray protocols but restricts certain keywords for VIP-type scripts.
-* AppStore version QX1.0.2 (136) This version adds support HTTP(protocols) and relaxes certain script keyword restrictions, but restricts script remote subscriptions
+* AppStore version QX1.0.2 (136): This version adds support for HTTP protocols and relaxes certain script keyword restrictions but restricts remote script subscriptions.
-* AppStore version QX1.0.3 (155) This version removes the keyword restriction and restores the script remote subscription, however, the remote script needs to comment the device ID before execution.
+* AppStore version QX1.0.3 (155): This version removes keyword restrictions and restores the script remote subscription functionality. However, the device ID must be commented out in the remote script before execution.
-* AppStore version QX1.0.4 (164) This version completely restricts remote script subscriptions, meaning that all scripts can only use local paths.
+* AppStore version QX1.0.4 (164): This version completely restricts remote script subscriptions, requiring all scripts to use local paths.
-* AppStore version QX1.0.5 (192) This version adds a timed script task function.
+* AppStore version QX1.0.5 (192): This version introduces a scheduled script task feature.
-* AppStore version QX1.0.6 (212) This version supports modifying HTTP request body, and replaying HTTP request.
+* AppStore version QX1.0.6 (212): This version supports modifying HTTP request body and replaying HTTP requests.
-* AppStore version QX1.0.7 (240) This version supports TLS 1.3 (TLS-based proxy protocol), and Trojan(protocols).
+* AppStore version QX1.0.7 (240): This version supports TLS 1.3 (TLS-based proxy protocol) and Trojan protocols.
* ...
-* AppStore version QX1.0.10 (313) In this version, script remote subscription has been restored.
+* AppStore version QX1.0.10 (313): This version restores remote script subscriptions.
-QX1.0.3 add device ID, a simple example:
+In QX1.0.3, the device ID feature was added. Here’s a simple example:
```javascript
/**
@@ -131,7 +131,7 @@ obj["example"] = 0;
$done({body:JSON.stringify(obj)})
```
-The above random generated device ID can be found at the bottom of Quantumult X additional menu, and it may change after system restore.
+The randomly generated device ID above is located at the bottom of the Quantumult X additional menu and may change after a system restore.
@@ -163,17 +163,17 @@ Please note that in the following disclaimer, the term "Script-project" specifi
### Decrypt
-- Any scripts involved in unlocking and decrypting in the Script-project are intended for resource sharing and study purposes only. The legality, accuracy, completeness, and validity of these scripts cannot be guaranteed. **Therefore, please use your own judgment based on the actual situation.**
+- Any scripts within the Script-project that involve unlocking and decrypting are intended for resource sharing and study purposes only. The legality, accuracy, completeness, and validity of these scripts cannot be guaranteed. **Therefore, please use your own judgment based on the actual situation.**
- You are required to delete the decryption scripts from your computer or phone completely within **24 hours** of downloading them.
### Privacy
-- NobyDa is not responsible for any privacy breaches or other consequences arising from the direct or indirect use of any of the scripts in the Script-project, including but not limited to violating relevant laws and regulations or establishing VPS for spreading purposes.
+- NobyDa is not responsible for any privacy breaches or other consequences arising from the direct or indirect use of any of the scripts in the Script-project, including but not limited to violating relevant laws and regulations or establishing a VPS for distribution purposes.
### Commercial
-- Do not use any scripts from the Script-project for commercial or illegal purposes, **otherwise, you will be responsible for the consequences that may arise**.
+- Do not use any scripts from the Script-project for commercial or illegal purposes, **or you will bear full responsibility for the consequences that may arise**.
### Infringement
@@ -181,7 +181,7 @@ Please note that in the following disclaimer, the term "Script-project" specifi
### Liability
-- NobyDa is not responsible for any scripts problems, **including but not limited to any loss or damage caused by any scripting errors.**
+- NobyDa is not responsible for any problems with the Script-project, **including but not limited to any loss or damage caused by any scripting errors.**
### Change
From 42f36ab009949dd51246690832ad7f3f0a9b1f36 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 18 Jul 2025 00:38:58 +0800
Subject: [PATCH 104/105] Update disney+ rating regex.
---
QuantumultX/DisneyRating.snippet | 2 +-
Surge/Module/DisneyRating.sgmodule | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/QuantumultX/DisneyRating.snippet b/QuantumultX/DisneyRating.snippet
index 8cef49cb34..5ae613e3d9 100644
--- a/QuantumultX/DisneyRating.snippet
+++ b/QuantumultX/DisneyRating.snippet
@@ -2,6 +2,6 @@
# https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/DisneyRating.snippet
-^https:\/\/disney\.api\.edge\.bamgrid\.com\/explore\/v\d\.\d\/page\/entity- url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Disney/DisneyRating.js
+^https:\/\/disney\.api\.edge\.bamgrid\.com\/explore\/v\d\.\d+\/page\/entity- url script-response-body https://raw.githubusercontent.com/NobyDa/Script/master/Disney/DisneyRating.js
hostname = disney.api.edge.bamgrid.com
\ No newline at end of file
diff --git a/Surge/Module/DisneyRating.sgmodule b/Surge/Module/DisneyRating.sgmodule
index f7ec39c985..0f8a3c8897 100644
--- a/Surge/Module/DisneyRating.sgmodule
+++ b/Surge/Module/DisneyRating.sgmodule
@@ -5,7 +5,7 @@
#!category=🐻 NobyDa
[Script]
-DisneyRating = type=http-response,pattern=^https:\/\/disney\.api\.edge\.bamgrid\.com\/explore\/v\d\.\d\/page\/entity-,requires-body=1,max-size=0,binary-body-mode=0,debug={{{调试模式}}},script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Disney/DisneyRating.js,engine={{{脚本引擎}}}
+DisneyRating = type=http-response,pattern=^https:\/\/disney\.api\.edge\.bamgrid\.com\/explore\/v\d\.\d+\/page\/entity-,requires-body=1,max-size=0,binary-body-mode=0,debug={{{调试模式}}},script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Disney/DisneyRating.js,engine={{{脚本引擎}}}
[MITM]
hostname = %APPEND% disney.api.edge.bamgrid.com
\ No newline at end of file
From 7f8b309f8d943806b90c6ff25d8b8aa0c59b0c03 Mon Sep 17 00:00:00 2001
From: NobyDa <53217160+NobyDa@users.noreply.github.com>
Date: Fri, 19 Dec 2025 11:18:17 +0800
Subject: [PATCH 105/105] Refactoring bili checkin/points scripts.
---
Bilibili-DailyBonus/ExchangePoints.js | 482 +++++++++++++-------------
Bilibili-DailyBonus/Manga.js | 190 ++++++----
NobyDa_BoxJs.json | 8 +-
3 files changed, 367 insertions(+), 313 deletions(-)
diff --git a/Bilibili-DailyBonus/ExchangePoints.js b/Bilibili-DailyBonus/ExchangePoints.js
index fecf645070..f66e06761b 100644
--- a/Bilibili-DailyBonus/ExchangePoints.js
+++ b/Bilibili-DailyBonus/ExchangePoints.js
@@ -1,254 +1,272 @@
-/*
-哔哩哔哩漫画, 积分商城自动抢购脚本
+/********************************
+哔哩哔哩漫画积分商城自动抢购脚本
-脚本作者:@NobyDa
-更新时间:2024/06/01
-平台兼容:Surge, QuantumultX, Loon
+默认兑换积分商城中的"【超特惠】限量-0点秒杀"
+兑换数量为用户积分可兑换的最大值 (可于BoxJs内修改)
+默认执行时间为:每周日、每周一的凌晨 0:00:00 - 0:00:30 之间每秒执行一次
-*************************
-【 抢购脚本注意事项 】:
-*************************
+该脚本需要使用签到脚本获取Cookie后方可使用,支持多账号。
-该脚本需要使用签到脚本获取Cookie后方可使用.
-默认兑换积分商城中的"【超特惠】限量-0点秒杀", 兑换数量为用户积分可兑换的最大值 (可于BoxJs内修改)
-默认执行时间为:每周日、每周一的凌晨 0:00:00 - 0:01:59 之间每秒执行一次
+脚本作者:@NobyDa is powered by AI
+更新时间:2025/12/19
+平台兼容:Surge / QuantumultX / Loon / Stash
-BoxJs订阅地址: https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
+*********************************
+Surge(iOS 5.9.0+/macOS 5.5.0+)模块:
+*********************************
-*************************
-【 Surge & Loon 脚本配置 】:
-*************************
+https://raw.githubusercontent.com/NobyDa/Script/refs/heads/master/Surge/Module/BiliComicsExchangePoints.sgmodule
-[Script]
-cron "0-59 0 0 * * 0-1" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/ExchangePoints.js, wake-system=1, timeout=60
+*********************************
+QuantumultX 任务仓库(Gallery)订阅:
+*********************************
-*************************
-【 QX 1.0.10+ 脚本配置 】 :
-*************************
+https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
+工具&分析->HTTP请求->右上角添加任务仓库->选择相关脚本添加定时任务和附加组件
+或者添加QuantumultX配置:
[task_local]
0-59 0 0 * * 0-1 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/ExchangePoints.js, tag=哔哩哔哩漫画抢券, enabled=true
-*/
-
-// 新建一个实例对象, 把兼容函数定义到$中, 以便统一调用
-let $ = new nobyda();
-
-// 读取Surge脚本参数并转成对象
-let args = argsList(typeof $argument == "string" && $argument || '');
-
-// 读取兑换商品名, 默认兑换积分商城中的"【超特惠】限量-0点秒杀"
-let productName = args.ProductName || $.read('BM_ProductName') || '【超特惠】限量-0点秒杀';
-
-// 读取兑换数量, 默认兑换最大值
-let productNum = parseInt(args.ProductNum) || $.read('BM_ProductNum');
-
-// 读取循环抢购次数, 默认100次
-let exchangeNum = args.ExchangeNum || $.read('BM_ExchangeNum') || '100';
-
-// 读取哔哩哔哩漫画签到脚本所使用的Cookie
-let cookie = $.read('CookieBM');
-
-// 预留的空对象, 便于函数之间读取数据
-let user = {};
-
-(async function() { // 立即运行的匿名异步函数
- // 使用await关键字声明, 表示以同步方式执行异步函数, 可以简单理解为顺序执行
- await Promise.all([ //该方法用于将多个实例包装成一个新的实例, 可以简单理解为同时调用函数, 以进一步提高执行速度
- GetUserPoint(), //查询积分函数
- ListProduct() //查询商品函数
- ]);
- await ExchangeProduct(); //上面的查询都完成后, 则执行抢购
- $.done(); //抢购完成后调用Surge、QX内部特有的函数, 用于退出脚本执行
-})();
-
-function GetUserPoint() {
- const pointUrl = { //查询积分接口
- url: 'https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/GetUserPoint',
- headers: { //请求头
- 'Cookie': cookie //用户鉴权Cookie
- }
- }
- return new Promise((resolve) => { //主函数返回Promise实例对象, 以便后续调用时可以实现顺序执行异步函数
- $.post(pointUrl, (error, resp, data) => { //使用post请求查询, 再使用回调函数处理返回的结果
- try { //使用try方法捕获可能出现的代码异常
- if (error) {
- throw new Error(error); //如果请求失败, 例如无法联网, 则抛出一个异常
- } else {
- const body = JSON.parse(data); //解析响应体json并转化为对象
- if (body.code == 0 && body.data) { //如果响应体为预期格式
- user.point = parseInt(body.data.point); //把查询的积分赋值到全局变量user中
- console.log(`\n当前积分: ${body.data.point}`); //打印日志
- } else { //否则抛出一个异常
- throw new Error(body.msg || data);
- }
- }
- } catch (e) { //接住try代码块中抛出的异常, 并打印日志
- console.log(`\n查询积分: 失败\n出现错误: ${e.message}`);
- } finally { //finally语句在try和catch之后无论有无异常都会执行
- resolve(); //异步操作成功时调用, 将Promise对象的状态标记为"成功", 表示已完成查询积分
- }
- })
- })
+*********************************/
+
+const $ = new Env('BILI_COMICS_CHECKIN');
+const barkKey = $.isNode() && process.env['BM_BARK_KEY'] || '';
+const notifyMsg = [];
+
+!(async () => {
+ $.logLevel = $.getdata(`@${$.name}.Debug`) == 'true' && 'debug' || 'info';
+ const args = argsList(typeof $argument == "string" && $argument || '');
+ const user = JSON.parse($.getdata($.name) || ($.isNode() && process.env[$.name]) || '{}');
+ const userNum = Object.keys(user.account || {}).length;
+ const todayFlag = getTodayFlag();
+ // 读取配置参数
+ const productName = args.ProductName || user.ProductName || '【超特惠】限量-0点秒杀';
+ const productNum = args.ProductNum || parseInt(user.ProductNum) || 0;
+ const exchangeNum = args.ExchangeNum || parseInt(user.ExchangeNum) || 100;
+ if (userNum) {
+ for (const i in user.account) {
+ // 检查今日是否已抢购成功
+ if (user.account[i].lastSuccessDate === todayFlag) {
+ const text = `账号(${i})今日已抢购成功,跳过执行`;
+ $.info(text);
+ continue
+ }
+ // 检查今日是否已标记积分不足
+ if (user.account[i].lastInsufficientDate === todayFlag) {
+ const text = `账号(${i})今日积分不足,跳过执行`;
+ $.info(text);
+ continue
+ }
+ const accountPrefix = userNum > 1 ? `[账号(${i})]` : '';
+ try {
+ const result = await ExchangeForAccount(user.account[i], productName, productNum, exchangeNum);
+ const text = accountPrefix ? `${accountPrefix} ${result.message}` : result.message;
+ $.info(text);
+ // 只有抢购成功时才加入通知消息并标记成功
+ if (result.success) {
+ notifyMsg.push(text);
+ user.account[i].lastSuccessDate = todayFlag;
+ // 清除积分不足标记
+ delete user.account[i].lastInsufficientDate;
+ $.setjson(user, $.name);
+ $.info(`账号 ${i} 已标记今日抢购成功`);
+ }
+ // 如果是积分不足(非异常情况),标记今日积分不足
+ else if (result.insufficient) {
+ user.account[i].lastInsufficientDate = todayFlag;
+ $.setjson(user, $.name);
+ $.info(`账号 ${i} 已标记今日积分不足`);
+ }
+ } catch (err) {
+ const text = `${accountPrefix} 抢购错误: ${err.message}`;
+ $.error(text);
+ notifyMsg.push(text);
+ }
+ }
+ } else {
+ notifyMsg.push(`抢购Cookie失效/未获取 ⚠️`);
+ }
+})()
+ .catch((err) => notifyMsg.push(`错误: ${err}`) && $.error(err))
+ .finally(async () => {
+ if (notifyMsg.length) {
+ if (barkKey) {
+ await BarkNotify($, barkKey, `哔哩哔哩漫画抢券`, notifyMsg.join('\n'));
+ }
+ $.msg(`哔哩哔哩漫画抢券`, ``, notifyMsg.join('\n'));
+ }
+ $.done({});
+ });
+
+async function ExchangeForAccount(account, productName, productNum, exchangeNum) {
+ // 先只查询商品信息(不查询积分)
+ const productList = await ListProduct(account);
+
+ // 查找目标商品
+ const product = productList.find(t => t.title == productName);
+ if (!product) {
+ return { success: false, insufficient: false, message: `查询商品失败: 未找到"${productName}"` };
+ }
+
+ // 先检查商品库存,如果库存为0则直接返回,不查询积分
+ if (!product.remain_amount) {
+ $.info(`查询商品: ${productName}, 库存: 0`);
+ return { success: false, insufficient: false, message: `抢购终止: 商品库存为0` };
+ }
+
+ // 库存充足时才查询积分
+ const userPoint = await GetUserPoint(account);
+ $.info(`查询商品: ${productName}, 库存: ${product.remain_amount}, 当前积分: ${userPoint}`);
+
+ // 检查积分是否足够
+ if (userPoint < product.real_cost) {
+ return {
+ success: false,
+ insufficient: true,
+ message: `抢购终止: 积分不足 (需要${product.real_cost}, 当前${userPoint})`
+ };
+ }
+
+ // 计算兑换数量
+ const num = productNum > 0 ? Math.min(productNum, Math.floor(userPoint / product.real_cost)) : Math.floor(userPoint / product.real_cost);
+
+ if (num <= 0) {
+ return {
+ success: false,
+ insufficient: true,
+ message: `抢购终止: 积分不足以兑换`
+ };
+ }
+
+ // 开始抢购
+ for (let i = 0; i < exchangeNum; i++) {
+ const result = await StartExchange(account, product, num, i);
+ if (result.success) {
+ return {
+ success: true,
+ insufficient: false,
+ message: `抢购成功: 第${i + 1}次, 数量: ${num}, 消耗积分: ${num * product.real_cost}`
+ };
+ }
+ if (i === exchangeNum - 1) {
+ return {
+ success: false,
+ insufficient: false,
+ message: `抢购失败: 已尝试${exchangeNum}次 (${result.message})`
+ };
+ }
+ }
}
-function ListProduct() {
- const listUrl = { //查询商品接口
- url: 'https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/ListProduct',
- headers: {}
- }
- return new Promise((resolve) => { //主函数返回Promise实例对象, 以便后续调用时可以实现顺序执行异步函数
- $.post(listUrl, (error, resp, data) => { //使用post请求查询, 再使用回调函数处理返回的结果
- try { //使用try方法捕获可能出现的代码异常
- if (error) {
- throw new Error(error); //如果请求失败, 例如无法联网, 则抛出一个异常
- } else {
- const body = JSON.parse(data); //解析响应体json并转化为对象
- if (body.code == 0 && body.data.length >= 1) { //如果接口正常返回商品信息
- // 按全局变量所填写的商品名进行过滤, 并把商品信息赋值到全局变量user中
- user.list = body.data.filter(t => t.title == productName).pop();
- if (!user.list) {
- throw new Error('请检查商品名'); //如果填错商品名则抛出一个异常
- } else { //否则打印日志
- console.log(`\n查询商品: ${productName}\n商品库存: ${user.list.remain_amount}`)
- }
- } else { //否则抛出一个异常
- throw new Error('无商品列表');
- }
- }
- } catch (e) { //接住try代码块中抛出的异常并打印日志
- console.log(`\n查询商品: ${productName}\n出现错误: ${e.message}`);
- } finally { //finally语句在try和catch之后无论有无异常都会执行
- resolve(); //异步操作成功时调用, 将Promise对象的状态标记为"成功", 表示已完成查询商品
- }
- })
- })
+function GetUserPoint(account) {
+ const opts = {
+ url: 'https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/GetUserPoint',
+ headers: {
+ "User-Agent": "comic-universal/3412 CFNetwork/1410.0.3 Darwin/22.6.0 os/ios model/iPhone 12 mobi_app/iphone_comic build/3412 osVer/16.6 network/2 channel/AppStore",
+ "Cookie": account.cookie
+ },
+ throwHttpErrors: false
+ };
+
+ $.debug(`Send GetUserPoint request:`, $.toStr(opts, null, null, 1));
+
+ return $.http.post(opts)
+ .then((resp) => {
+ $.debug(`Receive GetUserPoint response:`, $.toStr(resp, null, null, 1));
+ const body = JSON.parse(resp.body?.startsWith('{') && resp.body || '{}');
+ if (body.code == 0 && body.data) {
+ return parseInt(body.data.point);
+ } else {
+ throw new Error(body.msg || '查询积分失败');
+ }
+ })
+ .catch((err) => {
+ $.error(`GetUserPoint error:`, err);
+ throw err;
+ });
}
-function ExchangeProduct() {
- return new Promise(async (resolve) => { //主函数返回Promise实例对象, 以便后续调用时可以实现顺序执行异步函数, 该实例函数带有async关键字, 表示里面有异步操作, 例如可使用await得到异步结果
- if (user.list && user.list.remain_amount && user.point >= 100) { //如果商品有库存并且用户积分大于100则进行抢购
- //兑换商品数量(用户积分 除与 商品单价得到兑换数量), 并转成整数; 默认兑换最大数量
- const num = parseInt(productNum || (user.point / user.list.real_cost));
- const exchangeUrl = {
- url: 'https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/Exchange', //兑换商品接口
- headers: { //请求头
- 'Content-Type': 'application/json', //声明请求体数据格式
- 'Cookie': cookie //用户鉴权Cookie
- },
- body: JSON.stringify({ //请求体转成字符串类型
- product_id: user.list.id, //兑换的商品id
- product_num: num, //兑换的商品数量
- point: num * user.list.real_cost //消耗的积分总数 (兑换数量乘单价得到积分总数)
- })
- };
- for (let i = 0; i < parseInt(exchangeNum); i++) { //根据全局变量定义的次数, 暴力循环抢购
- // 循环内调用另一个抢购函数, 并传入请求、第几次循环、兑换数量等参数,
- // 使用await关键字声明, 表示需要等待每一次的执行结果
- const run = await startExchange(exchangeUrl, i, num);
- if (run) {
- break; //如果函数返回布尔值true, 则跳出循环, 脚本结束
- }
- }
- } else { //商品无库存或用户积分小于100等情况, 则不执行抢购, 脚本结束
- console.log(`\n抢购终止: 不具备兑换条件`); //打印日志
- }
- resolve(); //将主函数的Promise对象状态标记为"成功", 表示已完成抢购任务
- })
+function ListProduct(account) {
+ const opts = {
+ url: 'https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/ListProduct',
+ headers: {
+ "User-Agent": "comic-universal/3412 CFNetwork/1410.0.3 Darwin/22.6.0 os/ios model/iPhone 12 mobi_app/iphone_comic build/3412 osVer/16.6 network/2 channel/AppStore"
+ },
+ throwHttpErrors: false
+ };
+
+ $.debug(`Send ListProduct request:`, $.toStr(opts, null, null, 1));
+
+ return $.http.post(opts)
+ .then((resp) => {
+ $.debug(`Receive ListProduct response:`, $.toStr(resp, null, null, 1));
+ const body = JSON.parse(resp.body?.startsWith('{') && resp.body || '{}');
+ if (body.code == 0 && body.data && body.data.length >= 1) {
+ return body.data;
+ } else {
+ throw new Error(body.msg || '查询商品列表失败');
+ }
+ })
+ .catch((err) => {
+ $.error(`ListProduct error:`, err);
+ throw err;
+ });
}
-function startExchange(url, item, amount) {
- return new Promise((resolve) => { //主函数返回Promise实例对象, 以便后续调用时可以实现顺序执行异步函数
- $.post(url, (error, resp, data) => { //使用post请求查询, 再使用回调函数处理返回的结果
- try { //使用try方法捕获可能出现的代码异常
- if (error) {
- throw new Error(error); //如果请求失败, 例如无法联网, 则抛出一个异常
- } else {
- const body = JSON.parse(data); //解析响应体json并转化为对象
- if (body.code == 0) { //如果抢购成功, 则输出日志和通知
- console.log(`\n抢购成功: 第${item+1}次\n抢购数量: ${amount}\n消耗积分: ${amount * user.list.real_cost}`);
- $.notify('哔哩哔哩漫画抢券', '', `"${productName}"抢购成功, 数量: ${amount}, 消耗积分: ${amount * user.list.real_cost}`);
- resolve(true); //将Promise对象的状态标记为"成功", 然后返回一个布尔值true用于跳出循环
- } else {
- throw new Error(body.msg || '未知'); //抢购失败则抛出异常
- }
- }
- } catch (e) { //接住try代码块中抛出的异常并打印日志
- console.log(`\n抢购失败: 第${item+1}次\n失败原因: ${e.message}`);
- resolve(); //将Promise对象的状态标记为"成功", 但不返回任何值, 表示继续循环抢购
- }
- })
- })
+function StartExchange(account, product, num, attempt) {
+ const opts = {
+ url: 'https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/Exchange',
+ headers: {
+ "User-Agent": "comic-universal/3412 CFNetwork/1410.0.3 Darwin/22.6.0 os/ios model/iPhone 12 mobi_app/iphone_comic build/3412 osVer/16.6 network/2 channel/AppStore",
+ "Content-Type": "application/json",
+ "Cookie": account.cookie
+ },
+ body: JSON.stringify({
+ product_id: product.id,
+ product_num: num,
+ point: num * product.real_cost
+ }),
+ throwHttpErrors: false
+ };
+
+ $.debug(`Send Exchange request (attempt ${attempt + 1}):`, $.toStr(opts, null, null, 1));
+
+ return $.http.post(opts)
+ .then((resp) => {
+ $.debug(`Receive Exchange response (attempt ${attempt + 1}):`, $.toStr(resp, null, null, 1));
+ const body = JSON.parse(resp.body?.startsWith('{') && resp.body || '{}');
+ if (body.code == 0) {
+ return { success: true, message: '兑换成功' };
+ } else {
+ return { success: false, message: body.msg || '未知错误' };
+ }
+ })
+ .catch((err) => {
+ $.error(`Exchange error (attempt ${attempt + 1}):`, err);
+ return { success: false, message: err.message || '请求失败' };
+ });
+}
+
+function getTodayFlag() {
+ const now = new Date();
+ const year = now.getFullYear();
+ const month = String(now.getMonth() + 1).padStart(2, '0');
+ const day = String(now.getDate()).padStart(2, '0');
+ return `${year}-${month}-${day}`;
}
function argsList(data) {
- return Array.from(
- data.split("&")
- .map((i) => i.split("="))
- .map(([k, v]) => [k, decodeURIComponent(v)])
- )
- .reduce((a, [k, v]) => Object.assign(a, { [k]: v }), {})
+ return Array.from(
+ data.split("&")
+ .map((i) => i.split("="))
+ .map(([k, v]) => [k, decodeURIComponent(v)])
+ )
+ .reduce((a, [k, v]) => Object.assign(a, { [k]: v }), {})
}
-function nobyda() {
- const isSurge = typeof $httpClient != "undefined";
- const isQuanX = typeof $task != "undefined";
- const isNode = typeof require == "function";
- const node = (() => {
- if (isNode) {
- const request = require('request');
- return {
- request
- }
- } else {
- return null;
- }
- })()
- const adapterStatus = (response) => {
- if (response) {
- if (response.status) {
- response["statusCode"] = response.status
- } else if (response.statusCode) {
- response["status"] = response.statusCode
- }
- }
- return response
- }
- this.read = (key) => {
- if (isQuanX) return $prefs.valueForKey(key)
- if (isSurge) return $persistentStore.read(key)
- }
- this.notify = (title, subtitle, message) => {
- if (isQuanX) $notify(title, subtitle, message)
- if (isSurge) $notification.post(title, subtitle, message)
- if (isNode) console.log(`${title}\n${subtitle}\n${message}`)
- }
- this.post = (options, callback) => {
- options.headers['User-Agent'] = 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/609.3.5.0.2 (KHTML, like Gecko) Mobile/17G80 BiliApp/822 mobi_app/ios_comic channel/AppStore BiliComic/822'
- if (isQuanX) {
- if (typeof options == "string") options = {
- url: options
- }
- options["method"] = "POST"
- $task.fetch(options).then(response => {
- callback(null, adapterStatus(response), response.body)
- }, reason => callback(reason.error, null, null))
- }
- if (isSurge) {
- options.headers['X-Surge-Skip-Scripting'] = false
- $httpClient.post(options, (error, response, body) => {
- callback(error, adapterStatus(response), body)
- })
- }
- if (isNode) {
- node.request.post(options, (error, response, body) => {
- callback(error, adapterStatus(response), body)
- })
- }
- }
- this.done = () => {
- if (isQuanX || isSurge) {
- $done()
- }
- }
-};
\ No newline at end of file
+//Bark APP notify
+async function BarkNotify(c, k, t, b) { for (let i = 0; i < 3; i++) { c.log(`🔷Bark notify >> Start push (${i + 1})`); const s = await new Promise((n) => { c.post({ url: 'https://api.day.app/push', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: t, body: b, device_key: k, ext_params: { group: t } }) }, (e, r, d) => r && r.status == 200 ? n(1) : n(d || e)) }); if (s === 1) { c.log('✅Push success!'); break } else { c.log(`❌Push failed! >> ${s.message || s}`) } } };
+
+// https://github.com/chavyleung/scripts/blob/master/Env.min.js
+function Env(e, t) { class s { constructor(e) { this.env = e } send(e, t = "GET") { e = "string" == typeof e ? { url: e } : e; let s = this.get; "POST" === t && (s = this.post); const i = new Promise(((t, i) => { s.call(this, e, ((e, s, o) => { e ? i(e) : t(s) })) })); return e.timeout ? ((e, t = 1e3) => Promise.race([e, new Promise(((e, s) => { setTimeout((() => { s(new Error("请求超时")) }), t) }))]))(i, e.timeout) : i } get(e) { return this.send.call(this.env, e) } post(e) { return this.send.call(this.env, e, "POST") } } return new class { constructor(e, t) { 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 = e, 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, t) } 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(e, t = null) { try { return JSON.parse(e) } catch { return t } } toStr(e, t = null, ...s) { try { return JSON.stringify(e, ...s) } catch { return t } } getjson(e, t) { let s = t; if (this.getdata(e)) try { s = JSON.parse(this.getdata(e)) } catch { } return s } setjson(e, t) { try { return this.setdata(JSON.stringify(e), t) } catch { return !1 } } getScript(e) { return new Promise((t => { this.get({ url: e }, ((e, s, i) => t(i))) })) } runScript(e, t) { 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 = t && t.timeout ? t.timeout : o; const [r, a] = i.split("@"), n = { url: `http://${a}/v1/scripting/evaluate`, body: { script_text: e, mock_type: "cron", timeout: o }, headers: { "X-Key": r, Accept: "*/*" }, policy: "DIRECT", timeout: o }; this.post(n, ((e, t, i) => s(i))) })).catch((e => this.logErr(e))) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const e = this.path.resolve(this.dataFile), t = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(e), i = !s && this.fs.existsSync(t); if (!s && !i) return {}; { const i = s ? e : t; try { return JSON.parse(this.fs.readFileSync(i)) } catch (e) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const e = this.path.resolve(this.dataFile), t = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(e), i = !s && this.fs.existsSync(t), o = JSON.stringify(this.data); s ? this.fs.writeFileSync(e, o) : i ? this.fs.writeFileSync(t, o) : this.fs.writeFileSync(e, o) } } lodash_get(e, t, s) { const i = t.replace(/\[(\d+)\]/g, ".$1").split("."); let o = e; for (const e of i) if (o = Object(o)[e], void 0 === o) return s; return o } lodash_set(e, t, s) { return Object(e) !== e || (Array.isArray(t) || (t = t.toString().match(/[^.[\]]+/g) || []), t.slice(0, -1).reduce(((e, s, i) => Object(e[s]) === e[s] ? e[s] : e[s] = Math.abs(t[i + 1]) >> 0 == +t[i + 1] ? [] : {}), e)[t[t.length - 1]] = s), e } getdata(e) { let t = this.getval(e); if (/^@/.test(e)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(e), o = s ? this.getval(s) : ""; if (o) try { const e = JSON.parse(o); t = e ? this.lodash_get(e, i, "") : t } catch (e) { t = "" } } return t } setdata(e, t) { let s = !1; if (/^@/.test(t)) { const [, i, o] = /^@(.*?)\.(.*?)$/.exec(t), r = this.getval(i), a = i ? "null" === r ? null : r || "{}" : "{}"; try { const t = JSON.parse(a); this.lodash_set(t, o, e), s = this.setval(JSON.stringify(t), i) } catch (t) { const r = {}; this.lodash_set(r, o, e), s = this.setval(JSON.stringify(r), i) } } else s = this.setval(e, t); return s } getval(e) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.read(e); case "Quantumult X": return $prefs.valueForKey(e); case "Node.js": return this.data = this.loaddata(), this.data[e]; default: return this.data && this.data[e] || null } } setval(e, t) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.write(e, t); case "Quantumult X": return $prefs.setValueForKey(e, t); case "Node.js": return this.data = this.loaddata(), this.data[t] = e, this.writedata(), !0; default: return this.data && this.data[t] || null } } initGotEnv(e) { 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, e && (e.headers = e.headers ? e.headers : {}, e && (e.headers = e.headers ? e.headers : {}, void 0 === e.headers.cookie && void 0 === e.headers.Cookie && void 0 === e.cookieJar && (e.cookieJar = this.ckjar))) } get(e, t = (() => { })) { switch (e.headers && (delete e.headers["Content-Type"], delete e.headers["Content-Length"], delete e.headers["content-type"], delete e.headers["content-length"]), e.params && (e.url += "?" + this.queryStr(e.params)), void 0 === e.followRedirect || e.followRedirect || ((this.isSurge() || this.isLoon()) && (e["auto-redirect"] = !1), this.isQuanX() && (e.opts ? e.opts.redirection = !1 : e.opts = { redirection: !1 })), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: this.isSurge() && this.isNeedRewrite && (e.headers = e.headers || {}, Object.assign(e.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(e, ((e, s, i) => { !e && s && (s.body = i, s.statusCode = s.status ? s.status : s.statusCode, s.status = s.statusCode), t(e, s, i) })); break; case "Quantumult X": this.isNeedRewrite && (e.opts = e.opts || {}, Object.assign(e.opts, { hints: !1 })), $task.fetch(e).then((e => { const { statusCode: s, statusCode: i, headers: o, body: r, bodyBytes: a } = e; t(null, { status: s, statusCode: i, headers: o, body: r, bodyBytes: a }, r, a) }), (e => t(e && e.error || "UndefinedError"))); break; case "Node.js": let s = require("iconv-lite"); this.initGotEnv(e), this.got(e).on("redirect", ((e, t) => { try { if (e.headers["set-cookie"]) { const s = e.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), t.cookieJar = this.ckjar } } catch (e) { this.logErr(e) } })).then((e => { const { statusCode: i, statusCode: o, headers: r, rawBody: a } = e, n = s.decode(a, this.encoding); t(null, { status: i, statusCode: o, headers: r, rawBody: a, body: n }, n) }), (e => { const { message: i, response: o } = e; t(i, o, o && s.decode(o.rawBody, this.encoding)) })); break } } post(e, t = (() => { })) { const s = e.method ? e.method.toLocaleLowerCase() : "post"; switch (e.body && e.headers && !e.headers["Content-Type"] && !e.headers["content-type"] && (e.headers["content-type"] = "application/x-www-form-urlencoded"), e.headers && (delete e.headers["Content-Length"], delete e.headers["content-length"]), void 0 === e.followRedirect || e.followRedirect || ((this.isSurge() || this.isLoon()) && (e["auto-redirect"] = !1), this.isQuanX() && (e.opts ? e.opts.redirection = !1 : e.opts = { redirection: !1 })), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: this.isSurge() && this.isNeedRewrite && (e.headers = e.headers || {}, Object.assign(e.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient[s](e, ((e, s, i) => { !e && s && (s.body = i, s.statusCode = s.status ? s.status : s.statusCode, s.status = s.statusCode), t(e, s, i) })); break; case "Quantumult X": e.method = s, this.isNeedRewrite && (e.opts = e.opts || {}, Object.assign(e.opts, { hints: !1 })), $task.fetch(e).then((e => { const { statusCode: s, statusCode: i, headers: o, body: r, bodyBytes: a } = e; t(null, { status: s, statusCode: i, headers: o, body: r, bodyBytes: a }, r, a) }), (e => t(e && e.error || "UndefinedError"))); break; case "Node.js": let i = require("iconv-lite"); this.initGotEnv(e); const { url: o, ...r } = e; this.got[s](o, r).then((e => { const { statusCode: s, statusCode: o, headers: r, rawBody: a } = e, n = i.decode(a, this.encoding); t(null, { status: s, statusCode: o, headers: r, rawBody: a, body: n }, n) }), (e => { const { message: s, response: o } = e; t(s, o, o && i.decode(o.rawBody, this.encoding)) })); break } } time(e, t = null) { const s = t ? new Date(t) : 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(e) && (e = e.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let t in i) new RegExp("(" + t + ")").test(e) && (e = e.replace(RegExp.$1, 1 == RegExp.$1.length ? i[t] : ("00" + i[t]).substr(("" + i[t]).length))); return e } queryStr(e) { let t = ""; for (const s in e) { let i = e[s]; null != i && "" !== i && ("object" == typeof i && (i = JSON.stringify(i)), t += `${s}=${i}&`) } return t = t.substring(0, t.length - 1), t } msg(t = e, s = "", i = "", o = {}) { const r = e => { const { $open: t, $copy: s, $media: i, $mediaMime: o } = e; switch (typeof e) { case void 0: return e; case "string": switch (this.getEnv()) { case "Surge": case "Stash": default: return { url: e }; case "Loon": case "Shadowrocket": return e; case "Quantumult X": return { "open-url": e }; case "Node.js": return }case "object": switch (this.getEnv()) { case "Surge": case "Stash": case "Shadowrocket": default: { const r = {}; let a = e.openUrl || e.url || e["open-url"] || t; a && Object.assign(r, { action: "open-url", url: a }); let n = e["update-pasteboard"] || e.updatePasteboard || s; n && Object.assign(r, { action: "clipboard", text: n }); let h = e.mediaUrl || e["media-url"] || i; if (h) { let e, t; if (h.startsWith("http")); else if (h.startsWith("data:")) { const [s] = h.split(";"), [, i] = h.split(","); e = i, t = s.replace("data:", "") } else { e = h, t = (e => { const t = { JVBERi0: "application/pdf", R0lGODdh: "image/gif", R0lGODlh: "image/gif", iVBORw0KGgo: "image/png", "/9j/": "image/jpg" }; for (var s in t) if (0 === e.indexOf(s)) return t[s]; return null })(h) } Object.assign(r, { "media-url": h, "media-base64": e, "media-base64-mime": o ?? t }) } return Object.assign(r, { "auto-dismiss": e["auto-dismiss"], sound: e.sound }), r } case "Loon": { const s = {}; let o = e.openUrl || e.url || e["open-url"] || t; o && Object.assign(s, { openUrl: o }); let r = e.mediaUrl || e["media-url"] || i; return r && Object.assign(s, { mediaUrl: r }), console.log(JSON.stringify(s)), s } case "Quantumult X": { const o = {}; let r = e["open-url"] || e.url || e.openUrl || t; r && Object.assign(o, { "open-url": r }); let a = e.mediaUrl || e["media-url"] || i; a && Object.assign(o, { "media-url": a }); let n = e["update-pasteboard"] || e.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(t, s, i, r(o)); break; case "Quantumult X": $notify(t, s, i, r(o)); break; case "Node.js": break }if (!this.isMuteLog) { let e = ["", "============================"]; e.push(t), s && e.push(s), i && e.push(i), console.log(e.join("\n")), this.logs = this.logs.concat(e) } } debug(...e) { this.logLevels[this.logLevel] <= this.logLevels.debug && (e.length > 0 && (this.logs = [...this.logs, ...e]), console.log(`${this.logLevelPrefixs.debug}${e.map((e => e ?? String(e))).join(this.logSeparator)}`)) } info(...e) { this.logLevels[this.logLevel] <= this.logLevels.info && (e.length > 0 && (this.logs = [...this.logs, ...e]), console.log(`${this.logLevelPrefixs.info}${e.map((e => e ?? String(e))).join(this.logSeparator)}`)) } warn(...e) { this.logLevels[this.logLevel] <= this.logLevels.warn && (e.length > 0 && (this.logs = [...this.logs, ...e]), console.log(`${this.logLevelPrefixs.warn}${e.map((e => e ?? String(e))).join(this.logSeparator)}`)) } error(...e) { this.logLevels[this.logLevel] <= this.logLevels.error && (e.length > 0 && (this.logs = [...this.logs, ...e]), console.log(`${this.logLevelPrefixs.error}${e.map((e => e ?? String(e))).join(this.logSeparator)}`)) } log(...e) { e.length > 0 && (this.logs = [...this.logs, ...e]), console.log(e.map((e => e ?? String(e))).join(this.logSeparator)) } logErr(e, t) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": case "Quantumult X": default: this.log("", `❗️${this.name}, 错误!`, t, e); break; case "Node.js": this.log("", `❗️${this.name}, 错误!`, t, void 0 !== e.message ? e.message : e, e.stack); break } } wait(e) { return new Promise((t => setTimeout(t, e))) } done(e = {}) { const t = ((new Date).getTime() - this.startTime) / 1e3; switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": case "Quantumult X": default: $done(e); break; case "Node.js": process.exit(1) } } }(e, t) }
diff --git a/Bilibili-DailyBonus/Manga.js b/Bilibili-DailyBonus/Manga.js
index f99ecd7c42..45a06ceb9d 100644
--- a/Bilibili-DailyBonus/Manga.js
+++ b/Bilibili-DailyBonus/Manga.js
@@ -1,107 +1,143 @@
-/*
-哔哩哔哩漫画签到
+/********************************
+哔哩哔哩漫画签到脚本
-脚本兼容:QuantumultX, Surge, Loon
-电报频道:@NobyDa
-问题反馈:@NobyDa_bot
-更新日期:2024/03/18
-如果转载,请注明出处
+支持多账号,支持Node.js,支持Bark推送。
+打开哔哩哔哩/漫画后 (AppStore中国区),单击"我的", 即可获取cookie
-说明:
-打开哔哩哔哩漫画后 (AppStore中国区),单击"我的", 如果通知获取cookie成功, 则可以使用此脚本.
+脚本作者:@NobyDa
+更新时间:2025/12/19
+平台兼容:Surge / QuantumultX / Loon / Stash / Node.js
+模块依赖(Node.js):iconv-lite / got / tough-cookie
+环境变量(Node.js):BILI_COMIC_DAILY_BONUS / BM_BARK_KEY
-脚本将在每天上午9点执行。 您可以修改执行时间。
+*********************************
+Surge(iOS 5.9.0+/macOS 5.5.0+)模块:
+*********************************
-~~~~~~~~~~~~~~~~
-Surge 4.2.0+ :
+https://raw.githubusercontent.com/NobyDa/Script/refs/heads/master/Surge/Module/BiliComicsDailyBonus.sgmodule
-[Script]
-Bili漫画签到 = type=cron,cronexp=0 9 * * *,wake-system=1,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js
+*********************************
+QuantumultX 任务仓库(Gallery)订阅:
+*********************************
-Bili漫画Cookie = type=http-request,pattern=^https:\/\/app\.bilibili\.com\/x\/v2\/account\/myinfo,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js
-
-[MITM]
-hostname = app.bilibili.com
-~~~~~~~~~~~~~~~~
-QX 1.0.10+ :
+https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json
+工具&分析->HTTP请求->右上角添加任务仓库->选择相关脚本添加定时任务和附加组件
+或者添加QuantumultX配置:
[task_local]
-0 9 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js, tag=Bili漫画签到
+0 9 * * * https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js, tag=哔哩哔哩漫画签到
[rewrite_local]
-#获取Bili漫画Cookie
^https:\/\/app\.bilibili\.com\/x\/v2\/account\/myinfo url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/Bilibili-DailyBonus/Manga.js
[mitm]
hostname = app.bilibili.com
-~~~~~~~~~~~~~~~~
-*/
-
-const $ = new Env(`哔哩哔哩漫画`);
-
-const cookie = $.getdata("CookieBM") || ($.isNode() && process.env['CookieBM']) || ''; // 哔哩哔哩漫画Cookie
+*********************************/
+const $ = new Env('BILI_COMICS_CHECKIN');
const barkKey = $.isNode() && process.env['BM_BARK_KEY'] || ''; // bark key
+const notifyMsg = [];
+const auth = ''; // '{"account":{"user1":{"cookie":"xxx","access_key":"xxx"},"user2":{"cookie":"xxx","access_key":"xxx"}}}'
+
+!(async () => {
+ $.logLevel = $.getdata(`@${$.name}.Debug`) == 'true' && 'debug' || 'info';
+ const user = JSON.parse(auth || $.getdata($.name) || ($.isNode() && process.env[$.name]) || '{}');
+ const userNum = Object.keys(user.account || {}).length;
+ if (typeof $request !== 'undefined') {
+ return GetAuth($request, user);
+ }
+ if (userNum) {
+ const invalidUser = [];
+ for (const i in user.account) {
+ const text = [
+ userNum > 1 && `[账号${notifyMsg.length + 1}(${i})]`,
+ await Checkin(user.account[i], i),
+ ].filter((v) => v).join(' ');
+ if (text.includes('登陆失效')) {
+ invalidUser.push(i)
+ }
+ $.info(text);
+ notifyMsg.push(text);
+ }
+ invalidUser.forEach((i) => delete user.account[i] && !$.isNode() && $.setjson(user, $.name));
+ } else {
+ notifyMsg.push(`签到Cookie失效/未获取 ⚠️`);
+ }
+})()
+ .catch((err) => notifyMsg.push(`错误: ${err}`) && $.error(err))
+ .finally(async () => {
+ const finalContent = notifyMsg.filter((v) => !v.includes('已签过'));
+ if (finalContent.length) {
+ if (barkKey) {
+ await BarkNotify($, barkKey, `哔哩哔哩漫画`, finalContent.join('\n'));
+ }
+ $.msg(`哔哩哔哩漫画`, ``, finalContent.join('\n'))
+ }
+ $.done({});
+ });
-if (typeof $request !== 'undefined') {
- GetCookie(cookie)
-} else if (!cookie) {
- $.msg($.name, ``, `签到Cookie失效/未获取 ⚠️`);
- $.done();
-} else {
- checkin()
-}
-
-function checkin() {
- const bilibili = {
- url: 'https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn',
+function Checkin(key) {
+ const opts = {
+ url: `https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn?platform=ios`,
headers: {
- Cookie: cookie,
- "User-Agent": "comic-universal/1552 CFNetwork/1406.0.4 Darwin/22.4.0 os/ios model/iPhone 12 mobi_app/iphone_comic build/1552 osVer/16.4 network/2 channel/AppStore"
+ "User-Agent": "comic-universal/3412 CFNetwork/1410.0.3 Darwin/22.6.0 os/ios model/iPhone 12 mobi_app/iphone_comic build/3412 osVer/16.6 network/2 channel/AppStore"
},
- body: "platform=ios"
+ throwHttpErrors: false // a fucking legacy in Env.js
};
- $.post(bilibili, async function (error, response, data) {
- if (error && !data) {
- $.msgBody = `请求失败!\n${error}`;
- } else if (data.includes(`"code":0`)) {
- $.msgBody = "签到成功!🎉";
- } else if (data.includes(`"code":1`)) {
- $.msgBody = "签到失败,今日已签过 ⚠️";
- } else if (data.includes(`"invalid_argument"`)) {
- $.msgBody = "签到失败,Cookie失效(已清除) ⚠️";
- $.setdata("", "CookieBM");
- } else {
- $.msgBody = `签到失败 ‼️\n${data}`;
- }
- if (barkKey) {
- await BarkNotify($, barkKey, $.name, $.msgBody);
- }
- $.msg($.name, ``, $.msgBody);
- $.done();
- })
+ if (key.cookie) { opts.headers.Cookie = key.cookie }
+ if (key.access_key) { opts.url = `${opts.url}&access_key=${key.access_key}` }
+ $.debug(`Send checkin request:`, $.toStr(opts, null, null, 1));
+ return $.http.post(opts)
+ .then((resp) => {
+ $.debug(`Receive checkin request response:`, $.toStr(resp, null, null, 1))
+ resp.body = JSON.parse((resp.body?.startsWith('{') && resp.body) || '{}');
+ if (resp.body.code == 0) {
+ return '签到成功!🎉'
+ } else if (resp.body.code == 1) {
+ return '今日已签过 ⚠️'
+ } else if (resp.body.msg == 'uid must > 0') {
+ return '签到失败, 登陆失效 ⚠️'
+ } else {
+ return `签到失败(${resp.body.msg})`
+ }
+ })
+ .catch((err) => {
+ $.error(`Send checkin request error:`, err);
+ return `签到错误 ⚠️`
+ })
}
-function GetCookie(oldCookie) {
- const req = JSON.stringify($request);
- if (!req.includes(`_comic`)) {
- $.log($.name, `非${$.name}客户端URL请求,跳过脚本 ⚠️`);
- } else if (!req.includes(`SESSDATA=`)) {
- $.msg($.name, ``, `获取Cookie失败,关键值缺失 ⚠️`);
- } else {
- const cookieValue = req.split(/(SESSDATA=.+?;)/)[1];
- const setCookie = $.setdata(cookieValue, `CookieBM`);
- if (oldCookie) {
- $.log($.name, `更新Cookie${setCookie ? `成功 🎉` : `失败 ⚠️`}`);
+function GetAuth(raw, data) {
+ raw.headers = formatHeaders(raw.headers);
+ const uid = raw.headers['x-bili-mid'];
+ // cookies may not always be present in app.
+ const cookie = raw.headers.cookie?.split(/(SESSDATA=[a-zA-Z0-9%_-]+)/)[1];
+ const access_key = raw.url.split(/access_key=([a-zA-Z0-9_-]+)/)[1];
+ if (uid && (cookie?.includes('SESSDATA=') || access_key)) {
+ if (!data.account || !data.account[uid]) {
+ notifyMsg.push(`账号: ${uid} 写入鉴权成功!🎉`);
} else {
- $.msg($.name, ``, `获取Cookie${setCookie ? `成功 🎉` : `失败 ⚠️`}`);
+ $.info(`账号: ${uid} 更新鉴权成功!🎉`);
}
+ data.account = {
+ ...data.account, [uid]: {
+ ...data.account?.[uid],
+ ...(cookie && { cookie }),
+ ...(access_key && { access_key })
+ }
+ }
+ } else {
+ $.error(`写入授权失败, 数据缺失.`)
}
- $.done()
+ return $.setjson(data, $.name);
+}
+
+function formatHeaders(h) {
+ return Object.keys(h).reduce((t, i) => (t[i.toLowerCase()] = h[i], t), {})
}
//Bark APP notify
-async function BarkNotify(c, k, t, b) { for (let i = 0; i < 3; i++) { console.log(`🔷Bark notify >> Start push (${i + 1})`); const s = await new Promise((n) => { c.post({ url: 'https://api.day.app/push', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: t, body: b, device_key: k, ext_params: { group: t } }) }, (e, r, d) => r && r.status == 200 ? n(1) : n(d || e)) }); if (s === 1) { console.log('✅Push success!'); break } else { console.log(`❌Push failed! >> ${s.message || s}`) } } };
+async function BarkNotify(c, k, t, b) { for (let i = 0; i < 3; i++) { c.log(`🔷Bark notify >> Start push (${i + 1})`); const s = await new Promise((n) => { c.post({ url: 'https://api.day.app/push', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: t, body: b, device_key: k, ext_params: { group: t } }) }, (e, r, d) => r && r.status == 200 ? n(1) : n(d || e)) }); if (s === 1) { c.log('✅Push success!'); break } else { c.log(`❌Push failed! >> ${s.message || s}`) } } };
// https://github.com/chavyleung/scripts/blob/master/Env.min.js
-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, 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("", `\ud83d\udd14${this.name}, \u5f00\u59cb!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } 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("@"), a = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; this.post(a, (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(); 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) { let e = { "M+": (new Date).getMonth() + 1, "d+": (new Date).getDate(), "H+": (new Date).getHours(), "m+": (new Date).getMinutes(), "s+": (new Date).getSeconds(), "q+": Math.floor(((new Date).getMonth() + 3) / 3), S: (new Date).getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, ((new Date).getFullYear() + "").substr(4 - RegExp.$1.length))); for (let s in e) new RegExp("(" + s + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? e[s] : ("00" + e[s]).substr(("" + e[s]).length))); 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 } } } }; this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))); let h = ["", "==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="]; h.push(e), s && h.push(s), i && h.push(i), console.log(h.join("\n")), this.logs = this.logs.concat(h) } 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("", `\u2757\ufe0f${this.name}, \u9519\u8bef!`, t.stack) : this.log("", `\u2757\ufe0f${this.name}, \u9519\u8bef!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) }
\ No newline at end of file
+function Env(e, t) { class s { constructor(e) { this.env = e } send(e, t = "GET") { e = "string" == typeof e ? { url: e } : e; let s = this.get; "POST" === t && (s = this.post); const i = new Promise(((t, i) => { s.call(this, e, ((e, s, o) => { e ? i(e) : t(s) })) })); return e.timeout ? ((e, t = 1e3) => Promise.race([e, new Promise(((e, s) => { setTimeout((() => { s(new Error("请求超时")) }), t) }))]))(i, e.timeout) : i } get(e) { return this.send.call(this.env, e) } post(e) { return this.send.call(this.env, e, "POST") } } return new class { constructor(e, t) { 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 = e, 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, t) } 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(e, t = null) { try { return JSON.parse(e) } catch { return t } } toStr(e, t = null, ...s) { try { return JSON.stringify(e, ...s) } catch { return t } } getjson(e, t) { let s = t; if (this.getdata(e)) try { s = JSON.parse(this.getdata(e)) } catch { } return s } setjson(e, t) { try { return this.setdata(JSON.stringify(e), t) } catch { return !1 } } getScript(e) { return new Promise((t => { this.get({ url: e }, ((e, s, i) => t(i))) })) } runScript(e, t) { 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 = t && t.timeout ? t.timeout : o; const [r, a] = i.split("@"), n = { url: `http://${a}/v1/scripting/evaluate`, body: { script_text: e, mock_type: "cron", timeout: o }, headers: { "X-Key": r, Accept: "*/*" }, policy: "DIRECT", timeout: o }; this.post(n, ((e, t, i) => s(i))) })).catch((e => this.logErr(e))) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const e = this.path.resolve(this.dataFile), t = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(e), i = !s && this.fs.existsSync(t); if (!s && !i) return {}; { const i = s ? e : t; try { return JSON.parse(this.fs.readFileSync(i)) } catch (e) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const e = this.path.resolve(this.dataFile), t = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(e), i = !s && this.fs.existsSync(t), o = JSON.stringify(this.data); s ? this.fs.writeFileSync(e, o) : i ? this.fs.writeFileSync(t, o) : this.fs.writeFileSync(e, o) } } lodash_get(e, t, s) { const i = t.replace(/\[(\d+)\]/g, ".$1").split("."); let o = e; for (const e of i) if (o = Object(o)[e], void 0 === o) return s; return o } lodash_set(e, t, s) { return Object(e) !== e || (Array.isArray(t) || (t = t.toString().match(/[^.[\]]+/g) || []), t.slice(0, -1).reduce(((e, s, i) => Object(e[s]) === e[s] ? e[s] : e[s] = Math.abs(t[i + 1]) >> 0 == +t[i + 1] ? [] : {}), e)[t[t.length - 1]] = s), e } getdata(e) { let t = this.getval(e); if (/^@/.test(e)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(e), o = s ? this.getval(s) : ""; if (o) try { const e = JSON.parse(o); t = e ? this.lodash_get(e, i, "") : t } catch (e) { t = "" } } return t } setdata(e, t) { let s = !1; if (/^@/.test(t)) { const [, i, o] = /^@(.*?)\.(.*?)$/.exec(t), r = this.getval(i), a = i ? "null" === r ? null : r || "{}" : "{}"; try { const t = JSON.parse(a); this.lodash_set(t, o, e), s = this.setval(JSON.stringify(t), i) } catch (t) { const r = {}; this.lodash_set(r, o, e), s = this.setval(JSON.stringify(r), i) } } else s = this.setval(e, t); return s } getval(e) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.read(e); case "Quantumult X": return $prefs.valueForKey(e); case "Node.js": return this.data = this.loaddata(), this.data[e]; default: return this.data && this.data[e] || null } } setval(e, t) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": return $persistentStore.write(e, t); case "Quantumult X": return $prefs.setValueForKey(e, t); case "Node.js": return this.data = this.loaddata(), this.data[t] = e, this.writedata(), !0; default: return this.data && this.data[t] || null } } initGotEnv(e) { 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, e && (e.headers = e.headers ? e.headers : {}, e && (e.headers = e.headers ? e.headers : {}, void 0 === e.headers.cookie && void 0 === e.headers.Cookie && void 0 === e.cookieJar && (e.cookieJar = this.ckjar))) } get(e, t = (() => { })) { switch (e.headers && (delete e.headers["Content-Type"], delete e.headers["Content-Length"], delete e.headers["content-type"], delete e.headers["content-length"]), e.params && (e.url += "?" + this.queryStr(e.params)), void 0 === e.followRedirect || e.followRedirect || ((this.isSurge() || this.isLoon()) && (e["auto-redirect"] = !1), this.isQuanX() && (e.opts ? e.opts.redirection = !1 : e.opts = { redirection: !1 })), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: this.isSurge() && this.isNeedRewrite && (e.headers = e.headers || {}, Object.assign(e.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(e, ((e, s, i) => { !e && s && (s.body = i, s.statusCode = s.status ? s.status : s.statusCode, s.status = s.statusCode), t(e, s, i) })); break; case "Quantumult X": this.isNeedRewrite && (e.opts = e.opts || {}, Object.assign(e.opts, { hints: !1 })), $task.fetch(e).then((e => { const { statusCode: s, statusCode: i, headers: o, body: r, bodyBytes: a } = e; t(null, { status: s, statusCode: i, headers: o, body: r, bodyBytes: a }, r, a) }), (e => t(e && e.error || "UndefinedError"))); break; case "Node.js": let s = require("iconv-lite"); this.initGotEnv(e), this.got(e).on("redirect", ((e, t) => { try { if (e.headers["set-cookie"]) { const s = e.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), t.cookieJar = this.ckjar } } catch (e) { this.logErr(e) } })).then((e => { const { statusCode: i, statusCode: o, headers: r, rawBody: a } = e, n = s.decode(a, this.encoding); t(null, { status: i, statusCode: o, headers: r, rawBody: a, body: n }, n) }), (e => { const { message: i, response: o } = e; t(i, o, o && s.decode(o.rawBody, this.encoding)) })); break } } post(e, t = (() => { })) { const s = e.method ? e.method.toLocaleLowerCase() : "post"; switch (e.body && e.headers && !e.headers["Content-Type"] && !e.headers["content-type"] && (e.headers["content-type"] = "application/x-www-form-urlencoded"), e.headers && (delete e.headers["Content-Length"], delete e.headers["content-length"]), void 0 === e.followRedirect || e.followRedirect || ((this.isSurge() || this.isLoon()) && (e["auto-redirect"] = !1), this.isQuanX() && (e.opts ? e.opts.redirection = !1 : e.opts = { redirection: !1 })), this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": default: this.isSurge() && this.isNeedRewrite && (e.headers = e.headers || {}, Object.assign(e.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient[s](e, ((e, s, i) => { !e && s && (s.body = i, s.statusCode = s.status ? s.status : s.statusCode, s.status = s.statusCode), t(e, s, i) })); break; case "Quantumult X": e.method = s, this.isNeedRewrite && (e.opts = e.opts || {}, Object.assign(e.opts, { hints: !1 })), $task.fetch(e).then((e => { const { statusCode: s, statusCode: i, headers: o, body: r, bodyBytes: a } = e; t(null, { status: s, statusCode: i, headers: o, body: r, bodyBytes: a }, r, a) }), (e => t(e && e.error || "UndefinedError"))); break; case "Node.js": let i = require("iconv-lite"); this.initGotEnv(e); const { url: o, ...r } = e; this.got[s](o, r).then((e => { const { statusCode: s, statusCode: o, headers: r, rawBody: a } = e, n = i.decode(a, this.encoding); t(null, { status: s, statusCode: o, headers: r, rawBody: a, body: n }, n) }), (e => { const { message: s, response: o } = e; t(s, o, o && i.decode(o.rawBody, this.encoding)) })); break } } time(e, t = null) { const s = t ? new Date(t) : 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(e) && (e = e.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let t in i) new RegExp("(" + t + ")").test(e) && (e = e.replace(RegExp.$1, 1 == RegExp.$1.length ? i[t] : ("00" + i[t]).substr(("" + i[t]).length))); return e } queryStr(e) { let t = ""; for (const s in e) { let i = e[s]; null != i && "" !== i && ("object" == typeof i && (i = JSON.stringify(i)), t += `${s}=${i}&`) } return t = t.substring(0, t.length - 1), t } msg(t = e, s = "", i = "", o = {}) { const r = e => { const { $open: t, $copy: s, $media: i, $mediaMime: o } = e; switch (typeof e) { case void 0: return e; case "string": switch (this.getEnv()) { case "Surge": case "Stash": default: return { url: e }; case "Loon": case "Shadowrocket": return e; case "Quantumult X": return { "open-url": e }; case "Node.js": return }case "object": switch (this.getEnv()) { case "Surge": case "Stash": case "Shadowrocket": default: { const r = {}; let a = e.openUrl || e.url || e["open-url"] || t; a && Object.assign(r, { action: "open-url", url: a }); let n = e["update-pasteboard"] || e.updatePasteboard || s; n && Object.assign(r, { action: "clipboard", text: n }); let h = e.mediaUrl || e["media-url"] || i; if (h) { let e, t; if (h.startsWith("http")); else if (h.startsWith("data:")) { const [s] = h.split(";"), [, i] = h.split(","); e = i, t = s.replace("data:", "") } else { e = h, t = (e => { const t = { JVBERi0: "application/pdf", R0lGODdh: "image/gif", R0lGODlh: "image/gif", iVBORw0KGgo: "image/png", "/9j/": "image/jpg" }; for (var s in t) if (0 === e.indexOf(s)) return t[s]; return null })(h) } Object.assign(r, { "media-url": h, "media-base64": e, "media-base64-mime": o ?? t }) } return Object.assign(r, { "auto-dismiss": e["auto-dismiss"], sound: e.sound }), r } case "Loon": { const s = {}; let o = e.openUrl || e.url || e["open-url"] || t; o && Object.assign(s, { openUrl: o }); let r = e.mediaUrl || e["media-url"] || i; return r && Object.assign(s, { mediaUrl: r }), console.log(JSON.stringify(s)), s } case "Quantumult X": { const o = {}; let r = e["open-url"] || e.url || e.openUrl || t; r && Object.assign(o, { "open-url": r }); let a = e.mediaUrl || e["media-url"] || i; a && Object.assign(o, { "media-url": a }); let n = e["update-pasteboard"] || e.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(t, s, i, r(o)); break; case "Quantumult X": $notify(t, s, i, r(o)); break; case "Node.js": break }if (!this.isMuteLog) { let e = ["", "============================"]; e.push(t), s && e.push(s), i && e.push(i), console.log(e.join("\n")), this.logs = this.logs.concat(e) } } debug(...e) { this.logLevels[this.logLevel] <= this.logLevels.debug && (e.length > 0 && (this.logs = [...this.logs, ...e]), console.log(`${this.logLevelPrefixs.debug}${e.map((e => e ?? String(e))).join(this.logSeparator)}`)) } info(...e) { this.logLevels[this.logLevel] <= this.logLevels.info && (e.length > 0 && (this.logs = [...this.logs, ...e]), console.log(`${this.logLevelPrefixs.info}${e.map((e => e ?? String(e))).join(this.logSeparator)}`)) } warn(...e) { this.logLevels[this.logLevel] <= this.logLevels.warn && (e.length > 0 && (this.logs = [...this.logs, ...e]), console.log(`${this.logLevelPrefixs.warn}${e.map((e => e ?? String(e))).join(this.logSeparator)}`)) } error(...e) { this.logLevels[this.logLevel] <= this.logLevels.error && (e.length > 0 && (this.logs = [...this.logs, ...e]), console.log(`${this.logLevelPrefixs.error}${e.map((e => e ?? String(e))).join(this.logSeparator)}`)) } log(...e) { e.length > 0 && (this.logs = [...this.logs, ...e]), console.log(e.map((e => e ?? String(e))).join(this.logSeparator)) } logErr(e, t) { switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": case "Quantumult X": default: this.log("", `❗️${this.name}, 错误!`, t, e); break; case "Node.js": this.log("", `❗️${this.name}, 错误!`, t, void 0 !== e.message ? e.message : e, e.stack); break } } wait(e) { return new Promise((t => setTimeout(t, e))) } done(e = {}) { const t = ((new Date).getTime() - this.startTime) / 1e3; switch (this.getEnv()) { case "Surge": case "Loon": case "Stash": case "Shadowrocket": case "Quantumult X": default: $done(e); break; case "Node.js": process.exit(1) } } }(e, t) }
\ No newline at end of file
diff --git a/NobyDa_BoxJs.json b/NobyDa_BoxJs.json
index f162ecf3c4..0a5d5e8aa9 100644
--- a/NobyDa_BoxJs.json
+++ b/NobyDa_BoxJs.json
@@ -280,7 +280,7 @@
"id": "BiliManga",
"name": "哔哩漫画",
"keys": [
- "CookieBM"
+ "BILI_COMICS_CHECKIN"
],
"descs_html": [
"获取Cookie以及脚本配置请查看脚本注释 "
@@ -306,7 +306,7 @@
],
"settings": [
{
- "id": "BM_ProductName",
+ "id": "@BILI_COMICS_CHECKIN.ProductName",
"name": "商品名",
"val": "积分兑换",
"type": "text",
@@ -314,7 +314,7 @@
"desc": "要抢购的积分商城商品名"
},
{
- "id": "BM_ProductNum",
+ "id": "@BILI_COMICS_CHECKIN.ProductNum",
"name": "兑换数量",
"val": "",
"type": "text",
@@ -322,7 +322,7 @@
"desc": "要兑换的数量, 默认为积分可兑换的最大值"
},
{
- "id": "BM_ExchangeNum",
+ "id": "@BILI_COMICS_CHECKIN.ExchangeNum",
"name": "抢购次数",
"val": "",
"type": "text",