diff --git a/README.md b/README.md
index 6deab8d..84105f6 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,9 @@
绝大多数代码都用到了@chavyleung 的 Env.js 和@Peng-YM 的 OpenAPI.js,感谢!
+如果能请杯奶茶,就很感谢啦!
+
+
## 脚本合集
### 【BoxJs】订阅
@@ -15,7 +18,7 @@ https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.bo
### 【Quantumult X】脚本订阅合集+自己写的去广告
https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/QuantumultX.rewrite.conf
-https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/QuantumultX.task.conf (需要将内容复制到[task_local])
+https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/QuantumultX.task.json
### 【Surge】脚本订阅合集
@@ -46,6 +49,13 @@ https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/Loon.scripts.c
3. 支持 BoxJs。
4. checkin_env.js 修改自@Neurogram-R,增加了多平台支持。
+### [公众号监控](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/wechatsubs/wechatsubs.js)
+
+#### 功能特点
+
+1. 设定关键词监控公众号推送。
+2. 可自定关键词推送间隔。
+
### [热门监控](https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/hotsearch/hot.js)
#### 功能特点
@@ -66,7 +76,7 @@ https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/Loon.scripts.c
14. 监控 36 氪关键词。
15. 监控 Kindle 图书关键词。
16. 监控 RSSHub 订阅,感谢@api-evangelist-[rss2json](https://github.com/api-evangelist/rss2json)。
-17. 监控人人影视最新上传,配合捷径[磁力离线](https://www.icloud.com/shortcuts/cfad8390798e459db458d6233d229209)可实现磁力下载,解锁追剧新姿势。
+17. ~~监控人人影视最新上传,配合捷径[磁力离线](https://www.icloud.com/shortcuts/cfad8390798e459db458d6233d229209)可实现磁力下载,解锁追剧新姿势。~~
18. 可自定关键词推送间隔。
### [App 价格监控](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/appstore/AppMonitor.js)
@@ -90,7 +100,7 @@ https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/Loon.scripts.c
#### 功能特点
-1. 可选择随机 or 最新内容
+1. 可选择随机 or 最新内容。
### [Funboat](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/funboat/funboat.js)
@@ -98,13 +108,46 @@ https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/Loon.scripts.c
1. 喜欢 funko 可以关注该微信小程序。
+### [九木杂物社](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/jiumu/jiumu.js)
+
+#### 功能特点
+
+1. 九木杂物社自动签到。
+
+### [酷乐潮玩](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/klcw)
+
+#### 功能特点
+
+1. 酷乐潮玩小程序、App 自动签到。
+
+### [信息查询](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/wechatsubs)
+
+#### 功能特点
+
+1. 支持事业单位招聘监控。
+2. 支持高校人才网监控。
+
+### [彩票查询](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/ssq/ssq.js)
+
+#### 功能特点
+
+1. 支持双色球、大乐透、福彩 3D、七乐彩。
+2. 支持仅查询当日开奖的彩票。
+
+### [华住会](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/hzh/hzh.js)
+
+#### 功能特点
+
+1. 自动签到。
+2. 领取奖励(开发中)。
+
## 规则类
### [去广告](https://github.com/evilbutcher/Quantumult_X/tree/master/remove_ad)
#### 功能特点
-[readme](https://github.com/evilbutcher/Quantumult_X/tree/master/remove_ad/README.md)
+[Readme](https://github.com/evilbutcher/Quantumult_X/tree/master/remove_ad/README.md)
### 免责声明
diff --git a/README_EN.md b/README_EN.md
index f838a46..1187c0b 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -43,6 +43,14 @@ https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/Loon.scripts.c
2. View traffic information.
3. Support BoxJs.
4. Checkin_env.js is modified from @Neurogram-R, adding multi-platform support.
+5. GitHub Action has been supported. First, Fork this repo, add CHECKIN_TITLE CHECKIN_URL CHECKIN_EMAIL CHECKIN_PASSWORD four data in the Secrets of the forked repo. Different accounts are separated by &. Both schedule and Star your repo, checkin can be run. Please refer to [pull](https://github.com/wei/pull/blob/master/README.md) on how to keep in sync.
+
+### [Wechatsubs](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/wechatsubs/wechatsubs.js)
+
+#### Features
+
+1. You can set keywords to monitor the push of Wechat Subscriptions.
+2. You can customize the keyword push interval.
### [Hotlist Monitor](https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/hotsearch/hot.js)
@@ -64,7 +72,7 @@ https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/Loon.scripts.c
14. Monitor 36Kr keywords.
15. Monitor Kindle book keywords.
16. Monitor RSSHub feeds, thanks to @api-evangelist-[rss2json](https://github.com/api-evangelist/rss2json).
-17. Monitor the latest uploads of RenRenTV, with shortcuts [magnetic offline](https://www.icloud.com/shortcuts/cfad8390798e459db458d6233d229209) can achieve magnetic download, unlocking a new way to catch up on dramas.
+17. ~~Monitor the latest uploads of RenRenTV, with shortcuts [magnetic offline](https://www.icloud.com/shortcuts/cfad8390798e459db458d6233d229209) can achieve magnetic download, unlocking a new way to catch up on dramas.~~
18. You can customize the keyword push interval.
### [App Price Monitor](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/appstore/AppMonitor.js)
@@ -96,6 +104,18 @@ https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/Loon.scripts.c
1. Who like funko can follow the WeChat app.
+### [Jiumu](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/jiumu/jiumu.js)
+
+#### Features
+
+1. Automatic check-in.
+
+### [KuLeChaoWan](https://github.com/evilbutcher/Quantumult_X/blob/master/check_in/klcw)
+
+#### Features
+
+1. Automatic check-in.
+
### Disclaimer
1. This script is only used for study and research, and does not guarantee its legitimacy, accuracy, and validity. Please make your own judgment based on the situation. I do not assume any guarantee responsibility for this.
diff --git a/check_in/appstore/AppMonitor.js b/check_in/appstore/AppMonitor.js
index 5eb23d7..22026d8 100644
--- a/check_in/appstore/AppMonitor.js
+++ b/check_in/appstore/AppMonitor.js
@@ -95,7 +95,7 @@ async function post_data(d) {
app_monitor = {};
} else {
app_monitor = JSON.parse(app_monitor);
- console.log(app_monitor);
+ console.log(JSON.stringify(app_monitor));
}
let infos = {};
await Promise.all(
@@ -151,9 +151,10 @@ async function post_data(d) {
$.write(infos, "app_monitor");
if (notifys.length > 0) {
notify(notifys);
+ $.done();
} else {
console.log("APP监控:版本及价格无变化");
- $.done;
+ $.done();
}
} catch (e) {
console.log(e);
@@ -161,9 +162,8 @@ async function post_data(d) {
}
function notify(notifys) {
notifys = notifys.join("\n");
- console.log(notifys);
+ console.log(JSON.stringify(notifys));
$.notify("APP监控", "", notifys);
- $.done;
}
function flag(x) {
var flags = new Map([
@@ -283,7 +283,11 @@ function flag(x) {
return flags.get(x.toUpperCase());
}
-//From Peng-YM's OpenAPI.js
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
function ENV() {
const isQX = typeof $task !== "undefined";
const isLoon = typeof $loon !== "undefined";
@@ -292,17 +296,41 @@ function ENV() {
const isNode = typeof require == "function" && !isJSBox;
const isRequest = typeof $request !== "undefined";
const isScriptable = typeof importModule !== "undefined";
- return { isQX, isLoon, isSurge, isNode, isJSBox, isRequest, isScriptable };
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
}
-function HTTP(baseURL, defaultOptions = {}) {
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
function send(method, options) {
- options = typeof options === "string" ? { url: options } : options;
- options.url = baseURL ? baseURL + options.url : options.url;
- options = { ...defaultOptions, ...options };
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
const timeout = options.timeout;
const events = {
...{
@@ -317,7 +345,10 @@ function HTTP(baseURL, defaultOptions = {}) {
let worker;
if (isQX) {
- worker = $task.fetch({ method, ...options });
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
} else if (isLoon || isSurge || isNode) {
worker = new Promise((resolve, reject) => {
const request = isNode ? require("request") : $httpClient;
@@ -413,8 +444,8 @@ function API(name = "untitled", debug = false) {
});
};
}
- // persistance
+ // persistence
// initialize cache
initCache() {
if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
@@ -428,7 +459,9 @@ function API(name = "untitled", debug = false) {
this.node.fs.writeFileSync(
fpath,
JSON.stringify({}),
- { flag: "wx" },
+ {
+ flag: "wx",
+ },
(err) => console.log(err)
);
}
@@ -440,7 +473,9 @@ function API(name = "untitled", debug = false) {
this.node.fs.writeFileSync(
fpath,
JSON.stringify({}),
- { flag: "wx" },
+ {
+ flag: "wx",
+ },
(err) => console.log(err)
);
this.cache = {};
@@ -454,20 +489,24 @@ function API(name = "untitled", debug = false) {
// store cache
persistCache() {
- const data = JSON.stringify(this.cache);
+ const data = JSON.stringify(this.cache, null, 2);
if (isQX) $prefs.setValueForKey(data, this.name);
if (isLoon || isSurge) $persistentStore.write(data, this.name);
if (isNode) {
this.node.fs.writeFileSync(
`${this.name}.json`,
data,
- { flag: "w" },
+ {
+ flag: "w",
+ },
(err) => console.log(err)
);
this.node.fs.writeFileSync(
"root.json",
- JSON.stringify(this.root),
- { flag: "w" },
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
(err) => console.log(err)
);
}
@@ -477,11 +516,11 @@ function API(name = "untitled", debug = false) {
this.log(`SET ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
- $persistentStore.write(data, key);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
}
if (isQX) {
- $prefs.setValueForKey(data, key);
+ return $prefs.setValueForKey(data, key);
}
if (isNode) {
this.root[key] = data;
@@ -496,7 +535,7 @@ function API(name = "untitled", debug = false) {
this.log(`READ ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
+ if (isSurge || isLoon) {
return $persistentStore.read(key);
}
if (isQX) {
@@ -514,11 +553,11 @@ function API(name = "untitled", debug = false) {
this.log(`DELETE ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
- $persistentStore.write(null, key);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
}
if (isQX) {
- $prefs.removeValueForKey(key);
+ return $prefs.removeValueForKey(key);
}
if (isNode) {
delete this.root[key];
@@ -549,7 +588,7 @@ function API(name = "untitled", debug = false) {
let opts = {};
if (openURL) opts["openUrl"] = openURL;
if (mediaURL) opts["mediaUrl"] = mediaURL;
- if (JSON.stringify(opts) == "{}") {
+ if (JSON.stringify(opts) === "{}") {
$notification.post(title, subtitle, content);
} else {
$notification.post(title, subtitle, content, opts);
@@ -574,15 +613,15 @@ function API(name = "untitled", debug = false) {
// other helper functions
log(msg) {
- if (this.debug) console.log(msg);
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
}
info(msg) {
- console.log(msg);
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
}
error(msg) {
- console.log("ERROR: " + msg);
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
}
wait(millisec) {
@@ -600,5 +639,16 @@ function API(name = "untitled", debug = false) {
}
}
}
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
})(name, debug);
}
diff --git a/check_in/funboat/funboat.js b/check_in/funboat/funboat.js
index fa35292..dcb7b3b 100644
--- a/check_in/funboat/funboat.js
+++ b/check_in/funboat/funboat.js
@@ -24,8 +24,8 @@
【Quantumult X】
————————————————
[rewrite_local]
-https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
-https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx9b5caf9d1669dc96 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx9b5caf9d1669dc96 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
[task_local]
5 8 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
@@ -34,15 +34,15 @@ https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats url script-request-heade
————————————————
[Script]
Funboat签到 = type=cron,cronexp=5 0 * * *,wake-system=1,timeout=20,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
-Funboat获取签到Cookie = type=http-request,pattern=https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
-Funboat获取积分Cookie = type=http-request,pattern=https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+Funboat获取签到Cookie = type=http-request,pattern=^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx9b5caf9d1669dc96,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+Funboat获取积分Cookie = type=http-request,pattern=^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx9b5caf9d1669dc96,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
【Loon】
————————————————
[Script]
cron "5 0 * * *" tag=Funboat签到, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
-http-request https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin tag=Funboat获取签到Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
-http-request https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats tag=Funboat获取积分Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+http-request ^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx9b5caf9d1669dc96 tag=Funboat获取签到Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+http-request ^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx9b5caf9d1669dc96 tag=Funboat获取积分Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
【All App MitM】
hostname = h5.youzan.com
@@ -84,13 +84,13 @@ function checkin() {
headers: { "Extra-Data": sicookie },
};
console.log("checkRequest");
- console.log(checkRequest);
+ console.log(JSON.stringify(checkRequest));
return new Promise((resolve) => {
$.get(checkRequest, (error, response, data) => {
if (response.statusCode == 200) {
var body = response.body;
var obj = JSON.parse(body);
- console.log(obj);
+ console.log(body);
if (obj.code == 0) {
var prize = obj.data.prizes[0].points;
var count = obj.data.times;
@@ -121,13 +121,13 @@ function getall() {
headers: { "Extra-Data": stcookie },
};
console.log("\nallRequest");
- console.log(allRequest);
+ console.log(JSON.stringify(allRequest));
return new Promise((resolve) => {
$.get(allRequest, (error, response, data) => {
if (response.statusCode == 200) {
var body = response.body;
var obj = JSON.parse(body);
- console.log(obj);
+ console.log(body);
if (obj.code == 0) {
var allpoints = obj.data.stats.points;
all = "总积分 " + allpoints + "分 🎉";
@@ -503,11 +503,15 @@ function Env(name, opts) {
this.got(opts)
.on("redirect", (resp, nextOpts) => {
try {
- const ck = resp.headers["set-cookie"]
- .map(this.cktough.Cookie.parse)
- .toString();
- this.ckjar.setCookieSync(ck, null);
- nextOpts.cookieJar = this.ckjar;
+ if (resp.headers["set-cookie"]) {
+ const ck = resp.headers["set-cookie"]
+ .map(this.cktough.Cookie.parse)
+ .toString();
+ if (ck) {
+ this.ckjar.setCookieSync(ck, null);
+ }
+ nextOpts.cookieJar = this.ckjar;
+ }
} catch (e) {
this.logErr(e);
}
@@ -578,23 +582,25 @@ function Env(name, opts) {
* :$.time('yyyyMMddHHmmssS')
* y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒
* 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符
- * @param {*} fmt 格式化参数
+ * @param {string} fmt 格式化参数
+ * @param {number} 可选: 根据指定时间戳返回格式化日期
*
*/
- time(fmt) {
+ time(fmt, ts = null) {
+ const date = ts ? new Date(ts) : new Date();
let o = {
- "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(),
+ "M+": date.getMonth() + 1,
+ "d+": date.getDate(),
+ "H+": date.getHours(),
+ "m+": date.getMinutes(),
+ "s+": date.getSeconds(),
+ "q+": Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds(),
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
- (new Date().getFullYear() + "").substr(4 - RegExp.$1.length)
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (let k in o)
if (new RegExp("(" + k + ")").test(fmt))
@@ -655,12 +661,14 @@ function Env(name, opts) {
$notify(title, subt, desc, toEnvOpts(opts));
}
}
- let logs = ["", "==============📣系统通知📣=============="];
- logs.push(title);
- subt ? logs.push(subt) : "";
- desc ? logs.push(desc) : "";
- console.log(logs.join("\n"));
- this.logs = this.logs.concat(logs);
+ if (!this.isMuteLog) {
+ let logs = ["", "==============📣系统通知📣=============="];
+ logs.push(title);
+ subt ? logs.push(subt) : "";
+ desc ? logs.push(desc) : "";
+ console.log(logs.join("\n"));
+ this.logs = this.logs.concat(logs);
+ }
}
log(...logs) {
diff --git a/check_in/glados/checkin_env.js b/check_in/glados/checkin_env.js
index 8c0d21d..e6f605d 100644
--- a/check_in/glados/checkin_env.js
+++ b/check_in/glados/checkin_env.js
@@ -38,7 +38,7 @@ Modified by evilbutcher
*/
const $ = new Env("机场签到");
-$.autoLogout = false;
+$.autoLogout = true;
if (
$.getdata("evil_checkintitle") != undefined &&
@@ -47,7 +47,7 @@ if (
var acc = $.getdata("evil_checkintitle");
accounts = acc.split(",");
} else {
- $.msg("机场签到", "", "请在 BoxJs 检查填写是否正确", "http://boxjs.com");
+ $.msg("机场签到", "", "请在 BoxJs 检查标题填写是否正确", "http://boxjs.com");
}
if (
@@ -57,7 +57,7 @@ if (
var ur = $.getdata("evil_checkinlogin");
urls = ur.split(",");
} else {
- $.msg("机场签到", "", "请在 BoxJs 检查填写是否正确", "http://boxjs.com");
+ $.msg("机场签到", "", "请在 BoxJs 检查链接填写是否正确", "http://boxjs.com");
}
if (
@@ -67,7 +67,7 @@ if (
var ema = $.getdata("evil_checkinemail");
emails = ema.split(",");
} else {
- $.msg("机场签到", "", "请在 BoxJs 检查填写是否正确", "http://boxjs.com");
+ $.msg("机场签到", "", "请在 BoxJs 检查邮箱填写是否正确", "http://boxjs.com");
}
if (
@@ -77,12 +77,22 @@ if (
var pwd = $.getdata("evil_checkinpwd");
passwords = pwd.split(",");
} else {
- $.msg("机场签到", "", "请在 BoxJs 检查填写是否正确", "http://boxjs.com");
+ $.msg("机场签到", "", "请在 BoxJs 检查密码填写是否正确", "http://boxjs.com");
}
$.autoLogout = JSON.parse($.getdata("evil_autoLogout") || $.autoLogout);
-function launch() {
+!(async () => {
+ await launch();
+})()
+ .catch((e) => {
+ $.log("", `❌失败! 原因: ${e}!`, "");
+ })
+ .finally(() => {
+ $.done();
+ });
+
+async function launch() {
for (var i in accounts) {
let title = accounts[i];
let url = urls[i];
@@ -94,43 +104,56 @@ function launch() {
var logouturl = {
url: url.replace(/(auth|user)\/login(.php)*/g, "") + logoutPath,
};
- console.log(logouturl);
- $.get(logouturl, function (error, response, data) {
- login(url, email, password, title);
- });
+ console.log(JSON.stringify(logouturl));
+ $.get(logouturl);
+ }
+ await checkin(url, email, password, title);
+ if ($.checkinok == true) {
+ await dataResults(url, $.checkindatamsg, title);
} else {
- checkin(url, email, password, title);
+ await login(url, email, password, title);
+ if ($.loginok == true) {
+ await checkin(url, email, password, title);
+ if ($.checkinok == true) {
+ await dataResults(url, $.checkindatamsg, title);
+ }
+ }
}
}
- $.done();
}
-launch();
-
function login(url, email, password, title) {
let loginPath =
url.indexOf("auth/login") != -1 ? "auth/login" : "user/_login.php";
let table = {
- url: url.replace(/(auth|user)\/login(.php)*/g, "") + loginPath,
- body: `email=${email}&passwd=${password}&rumber-me=week`,
+ url:
+ url.replace(/(auth|user)\/login(.php)*/g, "") +
+ loginPath +
+ `?email=${email}&passwd=${password}&rumber-me=week`,
};
- console.log(table);
- $.post(table, function (error, response, data) {
- if (error) {
- console.log(error);
- $.msg(title + "登录失败", JSON.stringify(error), "");
- } else {
- if (
- JSON.parse(data).msg.match(
- /邮箱或者密码错误|Mail or password is incorrect/
- )
- ) {
- console.log(response);
- $.msg(title + "邮箱或者密码错误", "", "");
+ console.log(loginPath + " 保护隐私隐去登录信息");
+ return new Promise((resolve) => {
+ $.post(table, function (error, response, data) {
+ if (error) {
+ console.log(JSON.stringify(error));
+ $.msg(title + "登录失败", JSON.stringify(error), "");
+ resolve();
} else {
- checkin(url, email, password, title);
+ if (
+ JSON.parse(data).msg.match(
+ /邮箱或者密码错误|Mail or password is incorrect/
+ )
+ ) {
+ console.log(response);
+ $.msg(title + "邮箱或者密码错误", "", "");
+ $.loginok = false;
+ } else {
+ $.loginok = true;
+ $.log("登陆成功");
+ }
+ resolve();
}
- }
+ });
});
}
@@ -140,18 +163,25 @@ function checkin(url, email, password, title) {
var checkinreqest = {
url: url.replace(/(auth|user)\/login(.php)*/g, "") + checkinPath,
};
- console.log(checkinreqest);
- $.post(checkinreqest, (error, response, data) => {
- if (error) {
- console.log(error);
- $.msg(title + "签到失败", JSON.stringify(error), "");
- } else {
- if (data.match(/\"msg\"\:/)) {
- dataResults(url, JSON.parse(data).msg, title);
+ console.log(JSON.stringify(checkinreqest));
+ return new Promise((resolve) => {
+ $.post(checkinreqest, function (error, response, data) {
+ if (error) {
+ console.log(JSON.stringify(error));
+ $.msg(title + "签到失败", JSON.stringify(error), "");
+ resolve();
} else {
- login(url, email, password, title);
+ if (data.match(/\"msg\"\:/)) {
+ $.checkinok = true;
+ $.checkindatamsg = JSON.parse(data).msg;
+ $.log("签到成功");
+ } else {
+ $.checkinok = false;
+ $.log("签到失败");
+ }
+ resolve();
}
- }
+ });
});
}
@@ -160,58 +190,63 @@ function dataResults(url, checkinMsg, title) {
var datarequest = {
url: url.replace(/(auth|user)\/login(.php)*/g, "") + userPath,
};
- console.log(datarequest);
- $.get(datarequest, (error, response, data) => {
- let resultData = "";
- let result = [];
- if (data.match(/theme\/malio/)) {
- let flowInfo = data.match(/trafficDountChat\s*\(([^\)]+)/);
- if (flowInfo) {
- let flowData = flowInfo[1].match(/\d[^\']+/g);
- let usedData = flowData[0];
- let todatUsed = flowData[1];
- let restData = flowData[2];
- result.push(`今日:${todatUsed}\n已用:${usedData}\n剩余:${restData}`);
- }
- let userInfo = data.match(/ChatraIntegration\s*=\s*({[^}]+)/);
- if (userInfo) {
- let user_name = userInfo[1].match(/name.+'(.+)'/)[1];
- let user_class = userInfo[1].match(/Class.+'(.+)'/)[1];
- let class_expire = userInfo[1].match(/Class_Expire.+'(.+)'/)[1];
- let money = userInfo[1].match(/Money.+'(.+)'/)[1];
- result.push(
- `用户名:${user_name}\n用户等级:lv${user_class}\n余额:${money}\n到期时间:${class_expire}`
+ console.log(JSON.stringify(datarequest));
+ return new Promise((resolve) => {
+ $.get(datarequest, function (error, response, data) {
+ let resultData = "";
+ let result = [];
+ if (data.match(/theme\/malio/)) {
+ let flowInfo = data.match(/trafficDountChat\s*\(([^\)]+)/);
+ if (flowInfo) {
+ let flowData = flowInfo[1].match(/\d[^\']+/g);
+ let usedData = flowData[0];
+ let todatUsed = flowData[1];
+ let restData = flowData[2];
+ result.push(
+ `今日:${todatUsed}\n已用:${usedData}\n剩余:${restData}`
+ );
+ }
+ let userInfo = data.match(/ChatraIntegration\s*=\s*({[^}]+)/);
+ if (userInfo) {
+ let user_name = userInfo[1].match(/name.+'(.+)'/)[1];
+ let user_class = userInfo[1].match(/Class.+'(.+)'/)[1];
+ let class_expire = userInfo[1].match(/Class_Expire.+'(.+)'/)[1];
+ let money = userInfo[1].match(/Money.+'(.+)'/)[1];
+ result.push(
+ `用户名:${user_name}\n用户等级:lv${user_class}\n余额:${money}\n到期时间:${class_expire}`
+ );
+ }
+ if (result.length != 0) {
+ resultData = result.join("\n\n");
+ }
+ } else {
+ let todayUsed = data.match(/>*\s*今日(已用|使用)*[^B]+/);
+ if (todayUsed) {
+ todayUsed = flowFormat(todayUsed[0]);
+ result.push(`今日:${todayUsed}`);
+ }
+ let usedData = data.match(
+ /(Used Transfer|>过去已用|>已用|>总已用|\"已用)[^B]+/
);
+ if (usedData) {
+ usedData = flowFormat(usedData[0]);
+ result.push(`已用:${usedData}`);
+ }
+ let restData = data.match(
+ /(Remaining Transfer|>剩余流量|>流量剩余|>可用|\"剩余)[^B]+/
+ );
+ if (restData) {
+ restData = flowFormat(restData[0]);
+ result.push(`剩余:${restData}`);
+ }
+ if (result.length != 0) {
+ resultData = result.join("\n");
+ }
}
- if (result.length != 0) {
- resultData = result.join("\n\n");
- }
- } else {
- let todayUsed = data.match(/>*\s*今日(已用|使用)*[^B]+/);
- if (todayUsed) {
- todayUsed = flowFormat(todayUsed[0]);
- result.push(`今日:${todayUsed}`);
- }
- let usedData = data.match(
- /(Used Transfer|>过去已用|>已用|>总已用|\"已用)[^B]+/
- );
- if (usedData) {
- usedData = flowFormat(usedData[0]);
- result.push(`已用:${usedData}`);
- }
- let restData = data.match(
- /(Remaining Transfer|>剩余流量|>流量剩余|>可用|\"剩余)[^B]+/
- );
- if (restData) {
- restData = flowFormat(restData[0]);
- result.push(`剩余:${restData}`);
- }
- if (result.length != 0) {
- resultData = result.join("\n");
- }
- }
- let flowMsg = resultData == "" ? "流量信息获取失败" : resultData;
- $.msg(title, checkinMsg, flowMsg);
+ let flowMsg = resultData == "" ? "流量信息获取失败" : resultData;
+ $.msg(title, checkinMsg, flowMsg);
+ resolve();
+ });
});
}
@@ -539,11 +574,15 @@ function Env(name, opts) {
this.got(opts)
.on("redirect", (resp, nextOpts) => {
try {
- const ck = resp.headers["set-cookie"]
- .map(this.cktough.Cookie.parse)
- .toString();
- this.ckjar.setCookieSync(ck, null);
- nextOpts.cookieJar = this.ckjar;
+ if (resp.headers["set-cookie"]) {
+ const ck = resp.headers["set-cookie"]
+ .map(this.cktough.Cookie.parse)
+ .toString();
+ if (ck) {
+ this.ckjar.setCookieSync(ck, null);
+ }
+ nextOpts.cookieJar = this.ckjar;
+ }
} catch (e) {
this.logErr(e);
}
@@ -614,23 +653,25 @@ function Env(name, opts) {
* :$.time('yyyyMMddHHmmssS')
* y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒
* 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符
- * @param {*} fmt 格式化参数
+ * @param {string} fmt 格式化参数
+ * @param {number} 可选: 根据指定时间戳返回格式化日期
*
*/
- time(fmt) {
+ time(fmt, ts = null) {
+ const date = ts ? new Date(ts) : new Date();
let o = {
- "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(),
+ "M+": date.getMonth() + 1,
+ "d+": date.getDate(),
+ "H+": date.getHours(),
+ "m+": date.getMinutes(),
+ "s+": date.getSeconds(),
+ "q+": Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds(),
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
- (new Date().getFullYear() + "").substr(4 - RegExp.$1.length)
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (let k in o)
if (new RegExp("(" + k + ")").test(fmt))
@@ -691,12 +732,14 @@ function Env(name, opts) {
$notify(title, subt, desc, toEnvOpts(opts));
}
}
- let logs = ["", "==============📣系统通知📣=============="];
- logs.push(title);
- subt ? logs.push(subt) : "";
- desc ? logs.push(desc) : "";
- console.log(logs.join("\n"));
- this.logs = this.logs.concat(logs);
+ if (!this.isMuteLog) {
+ let logs = ["", "==============📣系统通知📣=============="];
+ logs.push(title);
+ subt ? logs.push(subt) : "";
+ desc ? logs.push(desc) : "";
+ console.log(logs.join("\n"));
+ this.logs = this.logs.concat(logs);
+ }
}
log(...logs) {
diff --git a/check_in/glados/checkincookie_env.js b/check_in/glados/checkincookie_env.js
index 0b62ce0..476e143 100644
--- a/check_in/glados/checkincookie_env.js
+++ b/check_in/glados/checkincookie_env.js
@@ -535,11 +535,15 @@ function Env(name, opts) {
this.got(opts)
.on("redirect", (resp, nextOpts) => {
try {
- const ck = resp.headers["set-cookie"]
- .map(this.cktough.Cookie.parse)
- .toString();
- this.ckjar.setCookieSync(ck, null);
- nextOpts.cookieJar = this.ckjar;
+ if (resp.headers["set-cookie"]) {
+ const ck = resp.headers["set-cookie"]
+ .map(this.cktough.Cookie.parse)
+ .toString();
+ if (ck) {
+ this.ckjar.setCookieSync(ck, null);
+ }
+ nextOpts.cookieJar = this.ckjar;
+ }
} catch (e) {
this.logErr(e);
}
@@ -610,23 +614,25 @@ function Env(name, opts) {
* :$.time('yyyyMMddHHmmssS')
* y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒
* 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符
- * @param {*} fmt 格式化参数
+ * @param {string} fmt 格式化参数
+ * @param {number} 可选: 根据指定时间戳返回格式化日期
*
*/
- time(fmt) {
+ time(fmt, ts = null) {
+ const date = ts ? new Date(ts) : new Date();
let o = {
- "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(),
+ "M+": date.getMonth() + 1,
+ "d+": date.getDate(),
+ "H+": date.getHours(),
+ "m+": date.getMinutes(),
+ "s+": date.getSeconds(),
+ "q+": Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds(),
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
- (new Date().getFullYear() + "").substr(4 - RegExp.$1.length)
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (let k in o)
if (new RegExp("(" + k + ")").test(fmt))
@@ -687,12 +693,14 @@ function Env(name, opts) {
$notify(title, subt, desc, toEnvOpts(opts));
}
}
- let logs = ["", "==============📣系统通知📣=============="];
- logs.push(title);
- subt ? logs.push(subt) : "";
- desc ? logs.push(desc) : "";
- console.log(logs.join("\n"));
- this.logs = this.logs.concat(logs);
+ if (!this.isMuteLog) {
+ let logs = ["", "==============📣系统通知📣=============="];
+ logs.push(title);
+ subt ? logs.push(subt) : "";
+ desc ? logs.push(desc) : "";
+ console.log(logs.join("\n"));
+ this.logs = this.logs.concat(logs);
+ }
}
log(...logs) {
diff --git a/check_in/glados/glados.js b/check_in/glados/glados.js
index a6d929d..ace6913 100644
--- a/check_in/glados/glados.js
+++ b/check_in/glados/glados.js
@@ -27,20 +27,20 @@
[Script]
GLaDOS签到 = type=cron,cronexp=5 0 * * *,wake-system=1,timeout=20,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
-获取GLaDOS_Cookie = type=http-request, pattern=https:\/\/glados\.rocks\/api\/user\/status, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
+获取GLaDOS_Cookie = type=http-request, pattern=https:\/\/glados\.rocks\/api\/user\/checkin, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
【Loon】
-----------------
[Script]
cron "5 0 * * *" tag=GLaDOS签到, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
-http-request https:\/\/glados\.rocks\/api\/user\/status tag=获取GLaDOS_Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
+http-request https:\/\/glados\.rocks\/api\/user\/checkin tag=获取GLaDOS_Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
【Quantumult X】
-----------------
[rewrite_local]
-https:\/\/glados\.rocks\/api\/user\/status url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
+https:\/\/glados\.rocks\/api\/user\/checkin url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
[task_local]
1 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
@@ -52,15 +52,18 @@ hostname = glados.rocks
const $ = new Env("GLaDOS");
const signcookie = "evil_gladoscookie";
+const signauthorization = "evil_galdosauthorization"
var sicookie = $.getdata(signcookie);
+var siauthorization = $.getdata(siauthorization)
var account;
var expday;
var remain;
var remainday;
var change;
+var changeday;
var msge;
-var message = [];
+var message = "";
!(async () => {
if (typeof $request != "undefined") {
@@ -79,22 +82,50 @@ var message = [];
function signin() {
return new Promise((resolve) => {
+ const header = {
+ Accept: `application/json, text/plain, */*`,
+ Origin: `https://glados.rocks`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ Cookie: sicookie,
+ "Content-Type": `application/json;charset=utf-8`,
+ Host: `glados.rocks`,
+ Connection: `keep-alive`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1`,
+ 'Authorization': siauthorization,
+ "Accept-Language": `zh-cn`,
+ };
+ const body = `{ "token": "glados.network" }`;
const signinRequest = {
url: "https://glados.rocks/api/user/checkin",
- headers: { Cookie: sicookie },
+ headers: header,
+ body: body,
};
$.post(signinRequest, (error, response, data) => {
var body = response.body;
var obj = JSON.parse(body);
- if (obj.code == 0) {
- change = obj.list[0].change;
- changeday = parseInt(change);
- msge = obj.message;
- if (msge == "Please Checkin Tomorrow") {
- message.push("今日已签到");
+ if (obj.message != "oops, token error") {
+ if (obj.message != "Please Try Tomorrow") {
+ var date = new Date();
+ var y = date.getFullYear();
+ var m = date.getMonth() + 1;
+ if (m < 10) m = "0" + m;
+ var d = date.getDate();
+ if (d < 10) d = "0" + d;
+ var time = y + "-" + m + "-" + d;
+ var business = obj.list[0].business;
+ var sysdate = business.slice(-10);
+ if (JSON.stringify(time) == JSON.stringify(sysdate)) {
+ change = obj.list[0].change;
+ changeday = parseInt(change);
+ message += `今日签到获得${changeday}天`;
+ } else {
+ message += `今日签到获得0天`;
+ }
} else {
- message.push(`签到获得${changeday}天`);
+ message += "今日已签到";
}
+ } else {
+ message += obj.message;
}
resolve();
});
@@ -115,7 +146,7 @@ function status() {
expday = obj.data.days;
remain = obj.data.leftDays;
remainday = parseInt(remain);
- message.push(`已用${expday}天,剩余${remainday}天`);
+ message += `\n已用${expday}天,剩余${remainday}天`;
$.msg("GLaDOS", `账户:${account}`, message);
} else {
$.log(response);
@@ -130,11 +161,14 @@ function getCookie() {
if (
$request &&
$request.method != "OPTIONS" &&
- $request.url.match(/status/)
+ $request.url.match(/checkin/)
) {
const sicookie = $request.headers["Cookie"];
$.log(sicookie);
$.setdata(sicookie, signcookie);
+ const siauthorization = $request.headers["Authorization"];
+ $.log(siauthorization);
+ $.setdata(siauthorization, signauthorization);
$.msg("GLaDOS", "", "获取签到Cookie成功🎉");
}
}
@@ -222,7 +256,7 @@ function Env(name, opts) {
if (val) {
try {
json = JSON.parse(this.getdata(key));
- } catch {}
+ } catch { }
}
return json;
}
@@ -423,7 +457,7 @@ function Env(name, opts) {
}
}
- get(opts, callback = () => {}) {
+ get(opts, callback = () => { }) {
if (opts.headers) {
delete opts.headers["Content-Type"];
delete opts.headers["Content-Length"];
@@ -457,11 +491,15 @@ function Env(name, opts) {
this.got(opts)
.on("redirect", (resp, nextOpts) => {
try {
- const ck = resp.headers["set-cookie"]
- .map(this.cktough.Cookie.parse)
- .toString();
- this.ckjar.setCookieSync(ck, null);
- nextOpts.cookieJar = this.ckjar;
+ if (resp.headers["set-cookie"]) {
+ const ck = resp.headers["set-cookie"]
+ .map(this.cktough.Cookie.parse)
+ .toString();
+ if (ck) {
+ this.ckjar.setCookieSync(ck, null);
+ }
+ nextOpts.cookieJar = this.ckjar;
+ }
} catch (e) {
this.logErr(e);
}
@@ -480,7 +518,7 @@ function Env(name, opts) {
}
}
- post(opts, callback = () => {}) {
+ post(opts, callback = () => { }) {
// 如果指定了请求体, 但没指定`Content-Type`, 则自动生成
if (opts.body && opts.headers && !opts.headers["Content-Type"]) {
opts.headers["Content-Type"] = "application/x-www-form-urlencoded";
@@ -532,23 +570,25 @@ function Env(name, opts) {
* :$.time('yyyyMMddHHmmssS')
* y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒
* 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符
- * @param {*} fmt 格式化参数
+ * @param {string} fmt 格式化参数
+ * @param {number} 可选: 根据指定时间戳返回格式化日期
*
*/
- time(fmt) {
+ time(fmt, ts = null) {
+ const date = ts ? new Date(ts) : new Date();
let o = {
- "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(),
+ "M+": date.getMonth() + 1,
+ "d+": date.getDate(),
+ "H+": date.getHours(),
+ "m+": date.getMinutes(),
+ "s+": date.getSeconds(),
+ "q+": Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds(),
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
- (new Date().getFullYear() + "").substr(4 - RegExp.$1.length)
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (let k in o)
if (new RegExp("(" + k + ")").test(fmt))
@@ -609,12 +649,14 @@ function Env(name, opts) {
$notify(title, subt, desc, toEnvOpts(opts));
}
}
- let logs = ["", "==============📣系统通知📣=============="];
- logs.push(title);
- subt ? logs.push(subt) : "";
- desc ? logs.push(desc) : "";
- console.log(logs.join("\n"));
- this.logs = this.logs.concat(logs);
+ if (!this.isMuteLog) {
+ let logs = ["", "==============📣系统通知📣=============="];
+ logs.push(title);
+ subt ? logs.push(subt) : "";
+ desc ? logs.push(desc) : "";
+ console.log(logs.join("\n"));
+ this.logs = this.logs.concat(logs);
+ }
}
log(...logs) {
diff --git a/check_in/hotsearch/hot.js b/check_in/hotsearch/hot.js
index bfdd875..ffb0e75 100644
--- a/check_in/hotsearch/hot.js
+++ b/check_in/hotsearch/hot.js
@@ -90,8 +90,8 @@ $.amazon = true; //是否开启相应榜单监控
$.amznum = 6; //自定Kindle图书榜单数量
$.rss = true; //是否开启相应榜单监控
$.rssnum = 6; //自定rss订阅推送数量
-$.zmz = true; //是否开启相应榜单监控
-$.zmznum = 6; //自定人人影视推送数量
+/*$.zmz = true; //是否开启相应榜单监控
+$.zmznum = 6; //自定人人影视推送数量*/
$.splitpushwb = false; //是否分开推送微博榜单
$.pushnewwb = false; //是否忽略关键词推送微博最新内容
$.splitpushzh = false; //是否分开推送知乎榜单
@@ -110,8 +110,8 @@ $.splitpushamz = false; //是否分开推送Kindle图书榜单
$.pushnewamz = false; //是否忽略关键词推送Kindle图书最新内容
$.splitpushrss = false; //是否分开推送rss内容
$.pushnewrss = false; //是否忽略关键词推送rss最新内容
-$.splitpushzmz = false; //是否分开推送人人影视内容
-$.pushnewzmz = false; //是否忽略关键词推送人人影视最新内容
+/*$.splitpushzmz = false; //是否分开推送人人影视内容
+$.pushnewzmz = false; //是否忽略关键词推送人人影视最新内容*/
$.attachurl = false; //通知是否附带跳转链接
$.refreshtime = 6; //重复内容默认在6小时内不再通知,之后清空,可自行修改
$.rid = 0; //更改B站监控榜单
@@ -127,7 +127,7 @@ var itemsdy = [];
var itemsk36 = [];
var itemsamz = [];
var itemsrss = [];
-var itemszmz = [];
+//var itemszmz = [];
var urlswb = [];
var urlszh = [];
var urlsbd = [];
@@ -137,7 +137,7 @@ var urlsdy = [];
var urlsk36 = [];
var urlsamz = [];
var urlsrss = [];
-var urlszmz = [];
+//var urlszmz = [];
var coversbl = [];
var coversdb = [];
var coversamz = [];
@@ -151,7 +151,7 @@ var resultdy = [];
var resultk36 = [];
var resultamz = [];
var resultrss = [];
-var resultzmz = [];
+//var resultzmz = [];
var openurlwb = [];
var openurlzh = [];
var openurlbd = [];
@@ -161,7 +161,7 @@ var openurldy = [];
var openurlk36 = [];
var openurlamz = [];
var openurlrss = [];
-var openurlzmz = [];
+//var openurlzmz = [];
var mediaurlbl = [];
var mediaurldb = [];
var mediaurlamz = [];
@@ -217,11 +217,11 @@ var checkrssresult = false;
} else {
$.log("Kindle图书榜单未获取😫");
}
- if ($.zmz == true) {
+ /*if ($.zmz == true) {
await getzmzlist();
} else {
$.log("人人影视榜单未获取😫");
- }
+ }*/
if ($.rss == true) {
if (haversslink()) {
await Promise.all(
@@ -521,7 +521,7 @@ function gethotsearch() {
resolve();
} catch (e) {
$.log("获取微博热搜出现错误❌原因:\n");
- $.log(JSON.stringify(e));
+ $.log(JSON.stringify(e, Object.getOwnPropertyNames(e)));
resolve();
}
setTimeout(() => {
@@ -605,7 +605,7 @@ function gethotlist() {
resolve();
} catch (e) {
$.log("获取知乎热榜出现错误❌原因:\n");
- $.log(JSON.stringify(e));
+ $.log(JSON.stringify(e, Object.getOwnPropertyNames(e)));
resolve();
}
setTimeout(() => {
@@ -697,7 +697,7 @@ function getfylist() {
resolve();
} catch (e) {
$.log("获取百度风云榜出现错误❌原因:\n");
- $.log(JSON.stringify(e));
+ $.log(JSON.stringify(e, Object.getOwnPropertyNames(e)));
resolve();
}
setTimeout(() => {
@@ -785,7 +785,7 @@ function getbllist() {
resolve();
} catch (e) {
$.log("获取B站日榜出现错误❌原因:\n");
- $.log(JSON.stringify(e));
+ $.log(JSON.stringify(e, Object.getOwnPropertyNames(e)));
resolve();
}
setTimeout(() => {
@@ -885,7 +885,7 @@ function getdblist() {
resolve();
} catch (e) {
$.log("获取豆瓣榜单出现错误❌原因:\n");
- $.log(JSON.stringify(e));
+ $.log(JSON.stringify(e, Object.getOwnPropertyNames(e)));
resolve();
}
setTimeout(() => {
@@ -947,7 +947,7 @@ function getdylist() {
resolve();
} catch (e) {
$.log("获取抖音榜单出现错误❌原因:\n");
- $.log(JSON.stringify(e));
+ $.log(JSON.stringify(e, Object.getOwnPropertyNames(e)));
resolve();
}
setTimeout(() => {
@@ -1008,7 +1008,7 @@ function getk36list() {
resolve();
} catch (e) {
$.log("获取36氪榜单出现错误❌原因:\n");
- $.log(JSON.stringify(e));
+ $.log(JSON.stringify(e, Object.getOwnPropertyNames(e)));
resolve();
}
setTimeout(() => {
@@ -1077,7 +1077,7 @@ function getamazonlist() {
resolve();
} catch (e) {
$.log("获取Kindle图书榜单出现错误❌原因:\n");
- $.log(JSON.stringify(e));
+ $.log(JSON.stringify(e, Object.getOwnPropertyNames(e)));
resolve();
}
setTimeout(() => {
@@ -1174,7 +1174,7 @@ function getzmzlist() {
resolve();
} catch (e) {
$.log("获取人人影视榜单出现错误❌原因:\n");
- $.log(JSON.stringify(e));
+ $.log(JSON.stringify(e, Object.getOwnPropertyNames(e)));
resolve();
}
setTimeout(() => {
@@ -1307,7 +1307,7 @@ function getrsslist(
resolve();
} catch (e) {
$.log("获取RSS内容出现错误❌原因:\n");
- $.log(JSON.stringify(e));
+ $.log(JSON.stringify(e, Object.getOwnPropertyNames(e)));
resolve();
}
setTimeout(() => {
@@ -1658,7 +1658,7 @@ function last() {
resultdy.length == 0 &&
resultk36.length == 0 &&
resultamz.length == 0 &&
- resultzmz.length == 0 &&
+ //resultzmz.length == 0 &&
checkrssresult == false
) {
$.log(`\n😫您订阅的关键词"${keyword}"暂时没有更新`);
@@ -1676,8 +1676,8 @@ function final() {
$.douyin == false &&
$.k36 == false &&
$.amazon == false &&
- $.rss == false &&
- $.zmz == false
+ $.rss == false
+ //$.zmz == false
) {
$.msg(
"热门监控",
@@ -2141,11 +2141,15 @@ function Env(name, opts) {
this.got(opts)
.on("redirect", (resp, nextOpts) => {
try {
- const ck = resp.headers["set-cookie"]
- .map(this.cktough.Cookie.parse)
- .toString();
- this.ckjar.setCookieSync(ck, null);
- nextOpts.cookieJar = this.ckjar;
+ if (resp.headers["set-cookie"]) {
+ const ck = resp.headers["set-cookie"]
+ .map(this.cktough.Cookie.parse)
+ .toString();
+ if (ck) {
+ this.ckjar.setCookieSync(ck, null);
+ }
+ nextOpts.cookieJar = this.ckjar;
+ }
} catch (e) {
this.logErr(e);
}
@@ -2216,23 +2220,25 @@ function Env(name, opts) {
* :$.time('yyyyMMddHHmmssS')
* y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒
* 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符
- * @param {*} fmt 格式化参数
+ * @param {string} fmt 格式化参数
+ * @param {number} 可选: 根据指定时间戳返回格式化日期
*
*/
- time(fmt) {
+ time(fmt, ts = null) {
+ const date = ts ? new Date(ts) : new Date();
let o = {
- "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(),
+ "M+": date.getMonth() + 1,
+ "d+": date.getDate(),
+ "H+": date.getHours(),
+ "m+": date.getMinutes(),
+ "s+": date.getSeconds(),
+ "q+": Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds(),
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
- (new Date().getFullYear() + "").substr(4 - RegExp.$1.length)
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (let k in o)
if (new RegExp("(" + k + ")").test(fmt))
@@ -2293,12 +2299,14 @@ function Env(name, opts) {
$notify(title, subt, desc, toEnvOpts(opts));
}
}
- let logs = ["", "==============📣系统通知📣=============="];
- logs.push(title);
- subt ? logs.push(subt) : "";
- desc ? logs.push(desc) : "";
- console.log(logs.join("\n"));
- this.logs = this.logs.concat(logs);
+ if (!this.isMuteLog) {
+ let logs = ["", "==============📣系统通知📣=============="];
+ logs.push(title);
+ subt ? logs.push(subt) : "";
+ desc ? logs.push(desc) : "";
+ console.log(logs.join("\n"));
+ this.logs = this.logs.concat(logs);
+ }
}
log(...logs) {
diff --git a/check_in/hzh/hzh.js b/check_in/hzh/hzh.js
new file mode 100644
index 0000000..340546b
--- /dev/null
+++ b/check_in/hzh/hzh.js
@@ -0,0 +1,695 @@
+/*
+【华住会】@evilbutcher
+
+【仓库地址】https://github.com/evilbutcher/Quantumult_X/tree/master(欢迎star🌟)
+
+【BoxJs】https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.boxjs.json
+
+【致谢】
+感谢Peng-YM的OpenAPI.js!
+
+⚠️【免责声明】
+------------------------------------------
+1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
+2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
+3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
+4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
+5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
+6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
+7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
+
+
+【使用说明】
+手动签到获取Cookie即可使用。
+
+【Surge】
+-----------------
+[Script]
+华住会获取签到Cookie = type=http-request, pattern = https:\/\/hweb-mbf\.huazhu\.com\/api\/signIn, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js, requires-body=false
+华住会 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js
+
+【Loon】
+-----------------
+[Script]
+http-request https:\/\/hweb-mbf\.huazhu\.com\/api\/signIn tag=华住会获取签到Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js, requires-body=false
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js, tag=华住会
+
+【Quantumult X】
+-----------------
+[rewrite_local]
+https:\/\/hweb-mbf\.huazhu\.com\/api\/signIn url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js
+
+[task_local]
+5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js, tag=华住会
+
+【All App MitM】
+hostname = hweb-mbf.huazhu.com
+
+【Icon】
+透明:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/hzh_tran.png
+彩色:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/hzh.png
+*/
+
+const $ = new API("hzh", true);
+const ERR = MYERR();
+$.cookie = $.read("evil_hzhCookie");
+$.usertoken = $.read("evil_hzhUserToken");
+
+!(async () => {
+ if (typeof $request != "undefined") {
+ getCookie();
+ return;
+ }
+ if ($.cookie != undefined && $.usertoken != undefined) {
+ await checkin();
+ await checkinfo();
+ /*for (var i = 1; i < 4; i++) {
+ await checkprize(i);
+ }
+ if ($.prizeid.length != 0) {
+ for (var j = 0; j < $.prizeid.length; j++) {
+ await getprize($.prizeid[j]);
+ }
+ }*/
+ showmsg();
+ } else {
+ $.notify("华住会", "", "❌ 请先获取Cookie");
+ }
+})()
+ .catch((err) => {
+ if (err instanceof ERR.ParseError) {
+ $.notify("华住会", "❌ 解析数据出现错误", err.message);
+ } else if (err instanceof ERR.EventError) {
+ $.notify("华住会", "❌ 请尝试重新获取Cookie", err.message);
+ } else {
+ $.notify(
+ "华住会",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
+ }
+ })
+ .finally(() => $.done());
+
+function checkin() {
+ var date = new Date();
+ var strDate = date.getDate();
+ if (strDate >= 0 && strDate <= 9) {
+ strDate = "0" + strDate;
+ }
+ var body = `state=1&day=${strDate}`;
+ const url = `https://hweb-mbf.huazhu.com/api/signIn`;
+ const headers = {
+ Connection: `keep-alive`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ "Client-Platform": `APP-IOS`,
+ "Content-Type": `application/x-www-form-urlencoded`,
+ Origin: `https://campaign.huazhu.com`,
+ "User-Agent": `HUAZHU/ios/iPhone12,1/14.6/8.0.70/HUAZHU/ios/iPhone12,1/14.6/8.0.70/HUAZHU/ios/iPhone12,1/14.6/8.0.70/HUAZHU/ios/iPhone12,1/14.6/8.0.70/Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148`,
+ "User-Token": $.usertoken,
+ Cookie: $.cookie,
+ Host: `hweb-mbf.huazhu.com`,
+ Referer: `https://campaign.huazhu.com/points-shop/`,
+ "Accept-Language": `zh-cn`,
+ Accept: `application/json, text/plain, */*`,
+ };
+ const myRequest = {
+ url: url,
+ headers: headers,
+ body: body,
+ };
+ return $.http.post(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ if (JSON.parse(response.body).message == "fail") {
+ throw new ERR.EventError("服务器返回数据错误,请重新获取Cookie");
+ } else {
+ $.data = JSON.parse(response.body).content;
+ $.log($.data);
+ }
+ } else {
+ $.error(JSON.stringify(response));
+ throw new ERR.ParseError("签到错误,请检查日志,稍后再试");
+ }
+ });
+}
+
+function checkinfo() {
+ const url2 = `https://hweb-mbf.huazhu.com/api/singInIndex`;
+ const headers2 = {
+ Origin: `https://campaign.huazhu.com`,
+ Cookie: $.cookie,
+ "Client-Platform": `APP-IOS`,
+ Connection: `keep-alive`,
+ Accept: `application/json, text/plain, */*`,
+ "User-Token": $.usertoken,
+ Host: `hweb-mbf.huazhu.com`,
+ "User-Agent": `HUAZHU/ios/iPhone12,1/14.6/8.0.70/HUAZHU/ios/iPhone12,1/14.6/8.0.70/HUAZHU/ios/iPhone12,1/14.6/8.0.70/HUAZHU/ios/iPhone12,1/14.6/8.0.70/Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148`,
+ Referer: `https://campaign.huazhu.com/points-shop/`,
+ "Accept-Language": `zh-cn`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ };
+
+ const myRequest2 = {
+ url: url2,
+ headers: headers2,
+ };
+ return $.http.get(myRequest2).then((response) => {
+ if (response.statusCode == 200) {
+ if (JSON.parse(response.body).message == "fail") {
+ throw new ERR.EventError("服务器返回数据错误,请重新获取Cookie");
+ } else {
+ $.datainfo = JSON.parse(response.body).content;
+ $.log($.datainfo);
+ }
+ } else {
+ $.error(JSON.stringify(response));
+ throw new ERR.ParseError("查询签到错误,请检查日志,稍后再试");
+ }
+ });
+}
+
+function showmsg() {
+ count = $.datainfo.signInCount;
+ if ($.data.isSign != null && $.data.isSign == true) {
+ $.notify("华住会", "今日已签到🎉", `累计签到${count}天!`);
+ } else if ($.data.isSign != null && $.data.isSign == false) {
+ point = $.data.point;
+ $.notify("华住会", "签到成功🎉", `获得${point}积分,累计签到${count}天!`);
+ }
+}
+
+function MYERR() {
+ class ParseError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ParseError";
+ }
+ }
+ class EventError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "EventError";
+ }
+ }
+ return {
+ ParseError,
+ EventError,
+ };
+}
+
+function getCookie() {
+ if (
+ $request &&
+ $request.method != "OPTIONS" &&
+ $request.url.match(/api\/signIn/)
+ ) {
+ const cookie = $request.headers["Cookie"];
+ $.log(cookie);
+ $.write(cookie, "evil_hzhCookie");
+ const usertoken = $request.headers["User-Token"];
+ $.log(usertoken);
+ $.write(usertoken, "evil_hzhUserToken");
+ $.notify("华住会", "", "获取签到Cookie成功🎉");
+ }
+}
+
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
+function ENV() {
+ const isQX = typeof $task !== "undefined";
+ const isLoon = typeof $loon !== "undefined";
+ const isSurge = typeof $httpClient !== "undefined" && !isLoon;
+ const isJSBox = typeof require == "function" && typeof $jsbox != "undefined";
+ const isNode = typeof require == "function" && !isJSBox;
+ const isRequest = typeof $request !== "undefined";
+ const isScriptable = typeof importModule !== "undefined";
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
+}
+
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
+ const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
+ const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX =
+ /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+
+ function send(method, options) {
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ if (options.body && options.headers && !options.headers["Content-Type"]) {
+ options.headers["Content-Type"] = "application/x-www-form-urlencoded";
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
+ const timeout = options.timeout;
+ const events = {
+ ...{
+ onRequest: () => {},
+ onResponse: (resp) => resp,
+ onTimeout: () => {},
+ },
+ ...options.events,
+ };
+
+ events.onRequest(method, options);
+
+ let worker;
+ if (isQX) {
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
+ } else if (isLoon || isSurge || isNode) {
+ worker = new Promise((resolve, reject) => {
+ const request = isNode ? require("request") : $httpClient;
+ request[method.toLowerCase()](options, (err, response, body) => {
+ if (err) reject(err);
+ else
+ resolve({
+ statusCode: response.status || response.statusCode,
+ headers: response.headers,
+ body,
+ });
+ });
+ });
+ } else if (isScriptable) {
+ const request = new Request(options.url);
+ request.method = method;
+ request.headers = options.headers;
+ request.body = options.body;
+ worker = new Promise((resolve, reject) => {
+ request
+ .loadString()
+ .then((body) => {
+ resolve({
+ statusCode: request.response.statusCode,
+ headers: request.response.headers,
+ body,
+ });
+ })
+ .catch((err) => reject(err));
+ });
+ }
+
+ let timeoutid;
+ const timer = timeout
+ ? new Promise((_, reject) => {
+ timeoutid = setTimeout(() => {
+ events.onTimeout();
+ return reject(
+ `${method} URL: ${options.url} exceeds the timeout ${timeout} ms`
+ );
+ }, timeout);
+ })
+ : null;
+
+ return (
+ timer
+ ? Promise.race([timer, worker]).then((res) => {
+ clearTimeout(timeoutid);
+ return res;
+ })
+ : worker
+ ).then((resp) => events.onResponse(resp));
+ }
+
+ const http = {};
+ methods.forEach(
+ (method) =>
+ (http[method.toLowerCase()] = (options) => send(method, options))
+ );
+ return http;
+}
+
+function API(name = "untitled", debug = false) {
+ const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV();
+ return new (class {
+ constructor(name, debug) {
+ this.name = name;
+ this.debug = debug;
+
+ this.http = HTTP();
+ this.env = ENV();
+
+ this.node = (() => {
+ if (isNode) {
+ const fs = require("fs");
+
+ return {
+ fs,
+ };
+ } else {
+ return null;
+ }
+ })();
+ this.initCache();
+
+ const delay = (t, v) =>
+ new Promise(function (resolve) {
+ setTimeout(resolve.bind(null, v), t);
+ });
+
+ Promise.prototype.delay = function (t) {
+ return this.then(function (v) {
+ return delay(t, v);
+ });
+ };
+ }
+
+ // persistence
+ // initialize cache
+ initCache() {
+ if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
+ if (isLoon || isSurge)
+ this.cache = JSON.parse($persistentStore.read(this.name) || "{}");
+
+ if (isNode) {
+ // create a json for root cache
+ let fpath = "root.json";
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ }
+ this.root = {};
+
+ // create a json file with the given name if not exists
+ fpath = `${this.name}.json`;
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ this.cache = {};
+ } else {
+ this.cache = JSON.parse(
+ this.node.fs.readFileSync(`${this.name}.json`)
+ );
+ }
+ }
+ }
+
+ // store cache
+ persistCache() {
+ const data = JSON.stringify(this.cache, null, 2);
+ if (isQX) $prefs.setValueForKey(data, this.name);
+ if (isLoon || isSurge) $persistentStore.write(data, this.name);
+ if (isNode) {
+ this.node.fs.writeFileSync(
+ `${this.name}.json`,
+ data,
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ this.node.fs.writeFileSync(
+ "root.json",
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ }
+ }
+
+ write(data, key) {
+ this.log(`SET ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
+ }
+ if (isQX) {
+ return $prefs.setValueForKey(data, key);
+ }
+ if (isNode) {
+ this.root[key] = data;
+ }
+ } else {
+ this.cache[key] = data;
+ }
+ this.persistCache();
+ }
+
+ read(key) {
+ this.log(`READ ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.read(key);
+ }
+ if (isQX) {
+ return $prefs.valueForKey(key);
+ }
+ if (isNode) {
+ return this.root[key];
+ }
+ } else {
+ return this.cache[key];
+ }
+ }
+
+ delete(key) {
+ this.log(`DELETE ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
+ }
+ if (isQX) {
+ return $prefs.removeValueForKey(key);
+ }
+ if (isNode) {
+ delete this.root[key];
+ }
+ } else {
+ delete this.cache[key];
+ }
+ this.persistCache();
+ }
+
+ // notification
+ notify(title, subtitle = "", content = "", options = {}) {
+ const openURL = options["open-url"];
+ const mediaURL = options["media-url"];
+
+ if (isQX) $notify(title, subtitle, content, options);
+ if (isSurge) {
+ $notification.post(
+ title,
+ subtitle,
+ content + `${mediaURL ? "\n多媒体:" + mediaURL : ""}`,
+ {
+ url: openURL,
+ }
+ );
+ }
+ if (isLoon) {
+ let opts = {};
+ if (openURL) opts["openUrl"] = openURL;
+ if (mediaURL) opts["mediaUrl"] = mediaURL;
+ if (JSON.stringify(opts) === "{}") {
+ $notification.post(title, subtitle, content);
+ } else {
+ $notification.post(title, subtitle, content, opts);
+ }
+ }
+ if (isNode || isScriptable) {
+ const content_ =
+ content +
+ (openURL ? `\n点击跳转: ${openURL}` : "") +
+ (mediaURL ? `\n多媒体: ${mediaURL}` : "");
+ if (isJSBox) {
+ const push = require("push");
+ push.schedule({
+ title: title,
+ body: (subtitle ? subtitle + "\n" : "") + content_,
+ });
+ } else {
+ console.log(`${title}\n${subtitle}\n${content_}\n\n`);
+ }
+ }
+ }
+
+ // other helper functions
+ log(msg) {
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
+ }
+
+ info(msg) {
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
+ }
+
+ error(msg) {
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
+ }
+
+ wait(millisec) {
+ return new Promise((resolve) => setTimeout(resolve, millisec));
+ }
+
+ done(value = {}) {
+ if (isQX || isLoon || isSurge) {
+ $done(value);
+ } else if (isNode && !isJSBox) {
+ if (typeof $context !== "undefined") {
+ $context.headers = value.headers;
+ $context.statusCode = value.statusCode;
+ $context.body = value.body;
+ }
+ }
+ }
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
+ })(name, debug);
+}
+
+//以下代码已失效
+/*function checkprize(num) {
+ var sk = $.body.replace(/.*?sk\=/, "");
+ const url3 = `https://newactivity.huazhu.com/v1/pointStore/taskInfo?taskId=${num}&sk=${sk}`;
+ const headers3 = {
+ Origin: `https://campaign.huazhu.com`,
+ Accept: `application/json, text/plain, * /*`,
+ Connection: `keep-alive`,
+ "Content-Type": `application/x-www-form-urlencoded`,
+ fp: $.fp,
+ Host: `newactivity.huazhu.com`,
+ "User-Agent": `HUAZHU/ios/iPhone12,1/14.6/8.0.60/Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148`,
+ Referer: `https://campaign.huazhu.com/pointsShop/`,
+ "Accept-Language": `zh-cn`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ };
+ const myRequest3 = {
+ url: url3,
+ headers: headers3,
+ };
+ return $.http.get(myRequest3).then((response) => {
+ if (response.statusCode == 200) {
+ if (JSON.parse(response.body).code == 200) {
+ var list = JSON.parse(response.body).data.taskPrizes;
+ var info = JSON.parse(response.body).data.buttonInfo;
+ var name = "";
+ for (var i = 0; i < list.length; i++) {
+ name = name + list[i].prizeInfo + " ";
+ }
+ if (info != null && info == "已领取") {
+ $.log(info + ":" + name);
+ } else if (info != null && info == "去完成") {
+ $.log("请继续签到以获得:" + name);
+ } else if (info != null && info == "立即领取") {
+ var id = JSON.parse(response.body).data.taskRecordId;
+ $.prizeid.push(id);
+ $.log("准备尝试领取:" + name);
+ } else {
+ $.log(JSON.parse(response.body).data);
+ }
+ } else {
+ $.log("查询奖励失败,原因:" + JSON.parse(response.body).msg);
+ return;
+ }
+ } else {
+ $.error(JSON.stringify(response));
+ throw new ERR.ParseError("查询奖励错误,请检查日志,稍后再试");
+ }
+ });
+}
+
+async function getprize(id) {
+ var sk = $.body.replace(/.*?sk\=/, "");
+ const url4 = `https://newactivity.huazhu.com/v1/pointStore/sendPrize?taskRecordId=${id}&sk=${sk}`;
+ const headers4 = {
+ Origin: `https://campaign.huazhu.com`,
+ Accept: `application/json, text/plain, * /*`,
+ Connection: `keep-alive`,
+ "Content-Type": `application/x-www-form-urlencoded`,
+ fp: $.fp,
+ Host: `newactivity.huazhu.com`,
+ "User-Agent": `HUAZHU/ios/iPhone12,1/14.6/8.0.5/Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148`,
+ Referer: `https://campaign.huazhu.com/pointsShop/`,
+ "Accept-Language": `zh-cn`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ };
+ const headers5 = {
+ Origin: `https://campaign.huazhu.com`,
+ "Access-Control-Request-Headers": `fp`,
+ Connection: `keep-alive`,
+ Accept: `* /*`,
+ Referer: `https://campaign.huazhu.com/`,
+ Host: `newactivity.huazhu.com`,
+ "User-Agent": `HUAZHU/ios/iPhone12,1/14.6/8.0.60/HUAZHU/ios/iPhone12,1/14.6/8.0.60/Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148`,
+ "Accept-Language": `zh-cn`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ "Access-Control-Request-Method": `GET`,
+ };
+ const myRequest4 = {
+ url: url4,
+ headers: headers4,
+ };
+ const myRequest5 = {
+ url: url4,
+ headers: headers5,
+ };
+ await $.http.options(myRequest5).then((response) => {
+ $.log(response);
+ $.log("尝试领取完成");
+ });
+ return $.http.get(myRequest4).then((response) => {
+ var body = JSON.parse(response.body);
+ if (response.statusCode == 200) {
+ if (body.success == true) {
+ var prize = body.data;
+ for (var i = 0; i < prize.length; i++) {
+ $.getprize = $.getprize + prize[i].prizeInfo;
+ }
+ }
+ } else {
+ $.error(JSON.stringify(response));
+ throw new ERR.ParseError("领取奖励错误,请检查日志,稍后再试");
+ }
+ });
+} */
diff --git a/check_in/idaily/idaily.js b/check_in/idaily/idaily.js
index 24cf3fb..6fb3980 100644
--- a/check_in/idaily/idaily.js
+++ b/check_in/idaily/idaily.js
@@ -51,10 +51,14 @@ $.random = [true, "true"].includes($.read("random")) || false;
if (err instanceof ERR.ParseError) {
$.notify("iDaily", "❌ 解析数据出现错误", err.message);
} else {
- $.notify("iDaily", "❌ 出现错误", JSON.stringify(err));
+ $.notify(
+ "iDaily",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
}
})
- .finally($.done());
+ .finally(() => $.done());
function getcontent() {
const url = `https://idaily-cdn.idailycdn.com/api/list/v3/iphone/zh-hans?page=1&ver=iphone&app_ver=122&app_timestamp=${$.time}`;
@@ -70,7 +74,7 @@ function getcontent() {
headers: headers,
};
return $.http.get(myRequest).then((response) => {
- $.log(JSON.parse(response.body));
+ $.log(response.body);
if (response.statusCode == 200) {
var obj = JSON.parse(response.body);
$.data = obj;
@@ -88,7 +92,7 @@ function showmsg() {
} else {
i = 0;
}
- $.info($.data[i]);
+ $.info(JSON.stringify($.data[i]));
var content = $.data[i].content;
var location = $.data[i].location;
var cover = $.data[i]["cover_landscape_hd"];
@@ -117,7 +121,11 @@ function MYERR() {
};
}
-//From Peng-YM's OpenAPI.js
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
function ENV() {
const isQX = typeof $task !== "undefined";
const isLoon = typeof $loon !== "undefined";
@@ -126,17 +134,41 @@ function ENV() {
const isNode = typeof require == "function" && !isJSBox;
const isRequest = typeof $request !== "undefined";
const isScriptable = typeof importModule !== "undefined";
- return { isQX, isLoon, isSurge, isNode, isJSBox, isRequest, isScriptable };
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
}
-function HTTP(baseURL, defaultOptions = {}) {
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
function send(method, options) {
- options = typeof options === "string" ? { url: options } : options;
- options.url = baseURL ? baseURL + options.url : options.url;
- options = { ...defaultOptions, ...options };
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
const timeout = options.timeout;
const events = {
...{
@@ -151,7 +183,10 @@ function HTTP(baseURL, defaultOptions = {}) {
let worker;
if (isQX) {
- worker = $task.fetch({ method, ...options });
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
} else if (isLoon || isSurge || isNode) {
worker = new Promise((resolve, reject) => {
const request = isNode ? require("request") : $httpClient;
@@ -247,8 +282,8 @@ function API(name = "untitled", debug = false) {
});
};
}
- // persistance
+ // persistence
// initialize cache
initCache() {
if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
@@ -262,7 +297,9 @@ function API(name = "untitled", debug = false) {
this.node.fs.writeFileSync(
fpath,
JSON.stringify({}),
- { flag: "wx" },
+ {
+ flag: "wx",
+ },
(err) => console.log(err)
);
}
@@ -274,7 +311,9 @@ function API(name = "untitled", debug = false) {
this.node.fs.writeFileSync(
fpath,
JSON.stringify({}),
- { flag: "wx" },
+ {
+ flag: "wx",
+ },
(err) => console.log(err)
);
this.cache = {};
@@ -288,20 +327,24 @@ function API(name = "untitled", debug = false) {
// store cache
persistCache() {
- const data = JSON.stringify(this.cache);
+ const data = JSON.stringify(this.cache, null, 2);
if (isQX) $prefs.setValueForKey(data, this.name);
if (isLoon || isSurge) $persistentStore.write(data, this.name);
if (isNode) {
this.node.fs.writeFileSync(
`${this.name}.json`,
data,
- { flag: "w" },
+ {
+ flag: "w",
+ },
(err) => console.log(err)
);
this.node.fs.writeFileSync(
"root.json",
- JSON.stringify(this.root),
- { flag: "w" },
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
(err) => console.log(err)
);
}
@@ -311,11 +354,11 @@ function API(name = "untitled", debug = false) {
this.log(`SET ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
- $persistentStore.write(data, key);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
}
if (isQX) {
- $prefs.setValueForKey(data, key);
+ return $prefs.setValueForKey(data, key);
}
if (isNode) {
this.root[key] = data;
@@ -330,7 +373,7 @@ function API(name = "untitled", debug = false) {
this.log(`READ ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
+ if (isSurge || isLoon) {
return $persistentStore.read(key);
}
if (isQX) {
@@ -348,11 +391,11 @@ function API(name = "untitled", debug = false) {
this.log(`DELETE ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
- $persistentStore.write(null, key);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
}
if (isQX) {
- $prefs.removeValueForKey(key);
+ return $prefs.removeValueForKey(key);
}
if (isNode) {
delete this.root[key];
@@ -383,7 +426,7 @@ function API(name = "untitled", debug = false) {
let opts = {};
if (openURL) opts["openUrl"] = openURL;
if (mediaURL) opts["mediaUrl"] = mediaURL;
- if (JSON.stringify(opts) == "{}") {
+ if (JSON.stringify(opts) === "{}") {
$notification.post(title, subtitle, content);
} else {
$notification.post(title, subtitle, content, opts);
@@ -408,15 +451,15 @@ function API(name = "untitled", debug = false) {
// other helper functions
log(msg) {
- if (this.debug) console.log(msg);
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
}
info(msg) {
- console.log(msg);
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
}
error(msg) {
- console.log("ERROR: " + msg);
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
}
wait(millisec) {
@@ -434,5 +477,16 @@ function API(name = "untitled", debug = false) {
}
}
}
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
})(name, debug);
}
diff --git a/check_in/jiumu/jiumu.js b/check_in/jiumu/jiumu.js
new file mode 100644
index 0000000..7363beb
--- /dev/null
+++ b/check_in/jiumu/jiumu.js
@@ -0,0 +1,610 @@
+/*
+【九木杂物社】@evilbutcher
+
+【仓库地址】https://github.com/evilbutcher/Quantumult_X/tree/master(欢迎star🌟)
+
+【BoxJs】https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.boxjs.json
+
+【致谢】
+感谢Peng-YM的OpenAPI.js!
+
+⚠️【免责声明】
+------------------------------------------
+1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
+2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
+3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
+4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
+5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
+6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
+7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
+
+
+【使用说明】
+微信小程序-九木杂物社-社员中心-每日签到,手动签到获取Cookie即可使用。
+
+【Surge】
+-----------------
+[Script]
+九木杂物社获取Cookie = http-request, pattern = https:\/\/wxavip\-up\.ezrpro\.cn\/Vip\/SignIn\/SignIn, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js, requires-body=true
+九木杂物社 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js
+
+【Loon】
+-----------------
+[Script]
+http-request https:\/\/wxavip\-up\.ezrpro\.cn\/Vip\/SignIn\/SignIn tag=九木杂物社获取Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js, requires-body=true
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js, tag=九木杂物社
+
+【Quantumult X】
+-----------------
+[rewrite_local]
+https:\/\/wxavip\-up\.ezrpro\.cn\/Vip\/SignIn\/SignIn url script-request-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js
+
+[task_local]
+5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js, tag=九木杂物社
+
+【All App MitM】
+hostname = wxavip-up.ezrpro.cn
+
+【Icon】
+透明:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/jiumu_tran.png
+彩色:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/jiumu.png
+*/
+
+const $ = new API("Jiumu", true);
+const ERR = MYERR();
+$.time = (new Date().getTime() / 1000).toFixed(0);
+$.SignStr = $.read("evil_jiumuSignStr");
+$.Referer = $.read("evil_jiumuReferer");
+$.vip = $.read("evil_jiumuVip");
+$.encrypt = $.read("evil_jiumuEncrypt");
+$.body = $.read("evil_jiumuBody");
+
+!(async () => {
+ if (typeof $request != "undefined") {
+ getCookie();
+ return;
+ }
+ if (
+ $.SignStr != undefined &&
+ $.Referer != undefined &&
+ $.vip != undefined &&
+ $.encrypt != undefined &&
+ $.body != undefined
+ ) {
+ await checkin();
+ await checkcoupon();
+ showmsg();
+ } else {
+ $.notify("九木杂物社", "", "❌ 请先获取Cookie");
+ }
+})()
+ .catch((err) => {
+ if (err instanceof ERR.ParseError) {
+ $.notify("九木杂物社", "❌ 解析数据出现错误", err.message);
+ } else if (err instanceof ERR.EventError) {
+ $.notify("九木杂物社", "❌ 请尝试重新获取Cookie", err.message);
+ } else {
+ $.notify(
+ "九木杂物社",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
+ }
+ })
+ .finally(() => $.done());
+
+function checkin() {
+ const url = `https://wxavip-up.ezrpro.cn/Vip/SignIn/SignIn`;
+ const headers = {
+ Connection: `keep-alive`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ "ezr-v-ip": $.vip,
+ timestamp: $.time,
+ "Content-Type": `application/json`,
+ SignStr: $.SignStr,
+ "ezr-encrypt": $.encrypt,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/7.0.18(0x1700122f) NetType/4G Language/zh_CN`,
+ Referer: $.Referer,
+ Host: `wxavip-up.ezrpro.cn`,
+ "Accept-Language": `zh-cn`,
+ Accept: `*/*`,
+ };
+ const myRequest = {
+ url: url,
+ headers: headers,
+ body: $.body,
+ };
+
+ return $.http.post(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ $.data = JSON.parse(response.body);
+ console.log(JSON.stringify($.data));
+ } else {
+ $.error(JSON.stringify(response));
+ throw new ERR.ParseError("签到数据解析错误,请检查日志");
+ }
+ });
+}
+
+function checkcoupon() {
+ const url = `https://wxavip-up.ezrpro.cn/Vip/SignIn/GetSignInDtlInfo`;
+ const headers = {
+ Connection: `keep-alive`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ "ezr-v-ip": $.vip,
+ timestamp: $.time,
+ "Content-Type": `application/json`,
+ SignStr: $.SignStr,
+ "ezr-encrypt": $.encrypt,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/7.0.18(0x1700122f) NetType/4G Language/zh_CN`,
+ Referer: $.Referer,
+ Host: `wxavip-up.ezrpro.cn`,
+ "Accept-Language": `zh-cn`,
+ Accept: `*/*`,
+ };
+ const myRequest = {
+ url: url,
+ headers: headers,
+ };
+
+ return $.http.get(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ $.datacoupon = JSON.parse(response.body);
+ console.log(JSON.stringify($.datacoupon));
+ } else {
+ $.error(JSON.stringify(response));
+ throw new ERR.ParseError("查询优惠券数据解析错误,请检查日志");
+ }
+ });
+}
+
+function showmsg() {
+ if ($.data.Result.ErrMsg == "今日已签到") {
+ var bonus = [];
+ var coupon = $.datacoupon.Result.StepGiveInfo;
+ for (var i = 0; i < coupon.length; i++) {
+ if (coupon[i].IsFinished == true && coupon[i].IsGive == false) {
+ bonus.push(coupon[i].StepName);
+ }
+ }
+ if (bonus.length == 0) {
+ $.notify("九木杂物社", "", `今日已签到🎉`);
+ } else {
+ bonus = bonus.join(" ");
+ $.notify("九木杂物社", "今日已签到", `已获得 ${bonus}🎉\n请尽快领取~`);
+ }
+ } else if ($.data.Result.ErrMsg != null) {
+ throw new ERR.EventError(
+ `签到错误,请检查日志,原因:${$.data.Result.ErrMsg}`
+ );
+ } else {
+ var msg = $.data.Msg;
+ var bonus = [];
+ var coupon = $.datacoupon.Result.StepGiveInfo;
+ for (var i = 0; i < coupon.length; i++) {
+ if (coupon[i].IsFinished == true && coupon[i].IsGive == false) {
+ bonus.push(coupon[i].StepName);
+ }
+ }
+ if (bonus.length == 0) {
+ $.notify("九木杂物社", "", msg);
+ } else {
+ bonus = bonus.join(" ");
+ $.notify("九木杂物社", msg, `已获得 ${bonus}🎉\n请尽快领取~`);
+ }
+ }
+}
+
+function MYERR() {
+ class ParseError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ParseError";
+ }
+ }
+ class EventError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "EventError";
+ }
+ }
+ return {
+ ParseError,
+ EventError,
+ };
+}
+
+function getCookie() {
+ if (
+ $request &&
+ $request.method != "OPTIONS" &&
+ $request.url.match(/SignIn/)
+ ) {
+ const str = $request.headers["SignStr"];
+ $.log(str);
+ $.write(str, "evil_jiumuSignStr");
+ const v_ip = $request.headers["ezr-v-ip"];
+ $.log(v_ip);
+ $.write(v_ip, "evil_jiumuVip");
+ const e_ncrypt = $request.headers["ezr-encrypt"];
+ $.log(e_ncrypt);
+ $.write(e_ncrypt, "evil_jiumuEncrypt");
+ const referer = $request.headers["Referer"];
+ $.log(referer);
+ $.write(referer, "evil_jiumuReferer");
+ const body = $request.body;
+ $.log(body);
+ $.write(body, "evil_jiumuBody");
+ $.notify("九木杂物社", "", "获取签到Cookie成功🎉");
+ }
+}
+
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
+function ENV() {
+ const isQX = typeof $task !== "undefined";
+ const isLoon = typeof $loon !== "undefined";
+ const isSurge = typeof $httpClient !== "undefined" && !isLoon;
+ const isJSBox = typeof require == "function" && typeof $jsbox != "undefined";
+ const isNode = typeof require == "function" && !isJSBox;
+ const isRequest = typeof $request !== "undefined";
+ const isScriptable = typeof importModule !== "undefined";
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
+}
+
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
+ const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
+ const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+
+ function send(method, options) {
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
+ const timeout = options.timeout;
+ const events = {
+ ...{
+ onRequest: () => {},
+ onResponse: (resp) => resp,
+ onTimeout: () => {},
+ },
+ ...options.events,
+ };
+
+ events.onRequest(method, options);
+
+ let worker;
+ if (isQX) {
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
+ } else if (isLoon || isSurge || isNode) {
+ worker = new Promise((resolve, reject) => {
+ const request = isNode ? require("request") : $httpClient;
+ request[method.toLowerCase()](options, (err, response, body) => {
+ if (err) reject(err);
+ else
+ resolve({
+ statusCode: response.status || response.statusCode,
+ headers: response.headers,
+ body,
+ });
+ });
+ });
+ } else if (isScriptable) {
+ const request = new Request(options.url);
+ request.method = method;
+ request.headers = options.headers;
+ request.body = options.body;
+ worker = new Promise((resolve, reject) => {
+ request
+ .loadString()
+ .then((body) => {
+ resolve({
+ statusCode: request.response.statusCode,
+ headers: request.response.headers,
+ body,
+ });
+ })
+ .catch((err) => reject(err));
+ });
+ }
+
+ let timeoutid;
+ const timer = timeout
+ ? new Promise((_, reject) => {
+ timeoutid = setTimeout(() => {
+ events.onTimeout();
+ return reject(
+ `${method} URL: ${options.url} exceeds the timeout ${timeout} ms`
+ );
+ }, timeout);
+ })
+ : null;
+
+ return (timer
+ ? Promise.race([timer, worker]).then((res) => {
+ clearTimeout(timeoutid);
+ return res;
+ })
+ : worker
+ ).then((resp) => events.onResponse(resp));
+ }
+
+ const http = {};
+ methods.forEach(
+ (method) =>
+ (http[method.toLowerCase()] = (options) => send(method, options))
+ );
+ return http;
+}
+
+function API(name = "untitled", debug = false) {
+ const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV();
+ return new (class {
+ constructor(name, debug) {
+ this.name = name;
+ this.debug = debug;
+
+ this.http = HTTP();
+ this.env = ENV();
+
+ this.node = (() => {
+ if (isNode) {
+ const fs = require("fs");
+
+ return {
+ fs,
+ };
+ } else {
+ return null;
+ }
+ })();
+ this.initCache();
+
+ const delay = (t, v) =>
+ new Promise(function (resolve) {
+ setTimeout(resolve.bind(null, v), t);
+ });
+
+ Promise.prototype.delay = function (t) {
+ return this.then(function (v) {
+ return delay(t, v);
+ });
+ };
+ }
+
+ // persistence
+ // initialize cache
+ initCache() {
+ if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
+ if (isLoon || isSurge)
+ this.cache = JSON.parse($persistentStore.read(this.name) || "{}");
+
+ if (isNode) {
+ // create a json for root cache
+ let fpath = "root.json";
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ }
+ this.root = {};
+
+ // create a json file with the given name if not exists
+ fpath = `${this.name}.json`;
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ this.cache = {};
+ } else {
+ this.cache = JSON.parse(
+ this.node.fs.readFileSync(`${this.name}.json`)
+ );
+ }
+ }
+ }
+
+ // store cache
+ persistCache() {
+ const data = JSON.stringify(this.cache, null, 2);
+ if (isQX) $prefs.setValueForKey(data, this.name);
+ if (isLoon || isSurge) $persistentStore.write(data, this.name);
+ if (isNode) {
+ this.node.fs.writeFileSync(
+ `${this.name}.json`,
+ data,
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ this.node.fs.writeFileSync(
+ "root.json",
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ }
+ }
+
+ write(data, key) {
+ this.log(`SET ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
+ }
+ if (isQX) {
+ return $prefs.setValueForKey(data, key);
+ }
+ if (isNode) {
+ this.root[key] = data;
+ }
+ } else {
+ this.cache[key] = data;
+ }
+ this.persistCache();
+ }
+
+ read(key) {
+ this.log(`READ ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.read(key);
+ }
+ if (isQX) {
+ return $prefs.valueForKey(key);
+ }
+ if (isNode) {
+ return this.root[key];
+ }
+ } else {
+ return this.cache[key];
+ }
+ }
+
+ delete(key) {
+ this.log(`DELETE ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
+ }
+ if (isQX) {
+ return $prefs.removeValueForKey(key);
+ }
+ if (isNode) {
+ delete this.root[key];
+ }
+ } else {
+ delete this.cache[key];
+ }
+ this.persistCache();
+ }
+
+ // notification
+ notify(title, subtitle = "", content = "", options = {}) {
+ const openURL = options["open-url"];
+ const mediaURL = options["media-url"];
+
+ if (isQX) $notify(title, subtitle, content, options);
+ if (isSurge) {
+ $notification.post(
+ title,
+ subtitle,
+ content + `${mediaURL ? "\n多媒体:" + mediaURL : ""}`,
+ {
+ url: openURL,
+ }
+ );
+ }
+ if (isLoon) {
+ let opts = {};
+ if (openURL) opts["openUrl"] = openURL;
+ if (mediaURL) opts["mediaUrl"] = mediaURL;
+ if (JSON.stringify(opts) === "{}") {
+ $notification.post(title, subtitle, content);
+ } else {
+ $notification.post(title, subtitle, content, opts);
+ }
+ }
+ if (isNode || isScriptable) {
+ const content_ =
+ content +
+ (openURL ? `\n点击跳转: ${openURL}` : "") +
+ (mediaURL ? `\n多媒体: ${mediaURL}` : "");
+ if (isJSBox) {
+ const push = require("push");
+ push.schedule({
+ title: title,
+ body: (subtitle ? subtitle + "\n" : "") + content_,
+ });
+ } else {
+ console.log(`${title}\n${subtitle}\n${content_}\n\n`);
+ }
+ }
+ }
+
+ // other helper functions
+ log(msg) {
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
+ }
+
+ info(msg) {
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
+ }
+
+ error(msg) {
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
+ }
+
+ wait(millisec) {
+ return new Promise((resolve) => setTimeout(resolve, millisec));
+ }
+
+ done(value = {}) {
+ if (isQX || isLoon || isSurge) {
+ $done(value);
+ } else if (isNode && !isJSBox) {
+ if (typeof $context !== "undefined") {
+ $context.headers = value.headers;
+ $context.statusCode = value.statusCode;
+ $context.body = value.body;
+ }
+ }
+ }
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
+ })(name, debug);
+}
diff --git a/check_in/klcw/klcw-app.js b/check_in/klcw/klcw-app.js
new file mode 100644
index 0000000..ed9cb45
--- /dev/null
+++ b/check_in/klcw/klcw-app.js
@@ -0,0 +1,540 @@
+/*
+【酷乐潮玩App】@evilbutcher
+
+【仓库地址】https://github.com/evilbutcher/Quantumult_X/tree/master(欢迎star🌟)
+
+【BoxJs】https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.boxjs.json
+
+【致谢】
+感谢Peng-YM的OpenAPI.js!
+
+⚠️【免责声明】
+------------------------------------------
+1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
+2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
+3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
+4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
+5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
+6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
+7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
+
+
+【使用说明】
+酷乐潮玩App-我的-任务中心,手动签到获取Cookie即可使用。
+
+【Surge】
+-----------------
+[Script]
+酷乐潮玩App获取Cookie = http-request, pattern = https:\/\/app\.klcw\.net\.cn\/omp\_cmanage\/mallgateway, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js, requires-body=true
+酷乐潮玩App = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js
+
+【Loon】
+-----------------
+[Script]
+http-request https:\/\/app\.klcw\.net\.cn\/omp\_cmanage\/mallgateway tag=酷乐潮玩App获取Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js, requires-body=true
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js, tag=酷乐潮玩App
+
+【Quantumult X】
+-----------------
+[rewrite_local]
+https:\/\/app\.klcw\.net\.cn\/omp\_cmanage\/mallgateway url script-request-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js
+
+[task_local]
+5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js, tag=酷乐潮玩App
+
+【All App MitM】
+hostname = app.klcw.net.cn
+
+【Icon】
+透明:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/klcw_tran.png
+彩色:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/klcw.png
+*/
+
+const $ = new API("klcwapp", true);
+const ERR = MYERR();
+var date = new Date();
+var year = date.getFullYear();
+var month = date.getMonth() + 1;
+if (month < 10) month = "0" + month;
+var day = date.getDate();
+if (day < 10) day = "0" + day;
+var hour = date.getHours();
+if (hour < 10) hour = "0" + hour;
+var minus = date.getMinutes();
+if (minus < 10) minus = "0" + minus;
+var second = date.getSeconds();
+if (second < 10) second = "0" + second;
+$.time = year + month + day + hour + minus + second;
+$.body = $.read("evil_klcwappBody");
+$.nowbody = JSON.stringify($.body)
+ .replace(/×tamp=\d+/, `×tamp=${$.time}`)
+ .replace(/&method\=.*?\&/, `&method=com.xdl.cn.appservice.AppTaskService.signIn&`)
+ .slice(1, -1);
+$.log($.nowbody);
+
+!(async () => {
+ if (typeof $request != "undefined") {
+ getCookie();
+ return;
+ }
+ if ($.body != undefined) {
+ await checkin();
+ showmsg();
+ } else {
+ $.notify("酷乐潮玩App", "", "❌ 请先获取Cookie");
+ }
+})()
+ .catch((err) => {
+ if (err instanceof ERR.ParseError) {
+ $.notify("酷乐潮玩App", "❌ 解析数据出现错误", err.message);
+ } else {
+ $.notify(
+ "酷乐潮玩App",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
+ }
+ })
+ .finally(() => $.done());
+
+function checkin() {
+ const url = `https://app.klcw.net.cn/omp_cmanage/mallgateway`;
+ const headers = {
+ chnflg: `ios`,
+ Accept: `*/*`,
+ Connection: `keep-alive`,
+ "Content-Type": `application/x-www-form-urlencoded`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ Host: `app.klcw.net.cn`,
+ "User-Agent": `KLMemberMobileApp/2.8.1 (iPhone; iOS 14.4; Scale/2.00)`,
+ version: `2.8.1`,
+ "Accept-Language": `zh-Hans-CN;q=1, en-CN;q=0.9`,
+ };
+ const myRequest = {
+ url: url,
+ headers: headers,
+ body: $.nowbody,
+ };
+
+ return $.http.post(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ $.data = JSON.parse(response.body);
+ $.log(JSON.stringify($.data));
+ } else {
+ $.error(JSON.stringify(response));
+ $.notify("酷乐潮玩App", "", "❌ 未知错误,请查看日志");
+ }
+ });
+}
+
+function showmsg() {
+ if ($.data.code == 0) {
+ var continuousDays = $.data.data.continuousDays;
+ var totalDays = $.data.data.totalDays;
+ var continuousAward = $.data.data.continuousAward;
+ $.notify(
+ "酷乐潮玩App",
+ "签到成功🎉",
+ `本次签到获得${continuousAward}积分!\n当前签到已连续${continuousDays}天,总计${totalDays}天!`
+ );
+ } else if ($.data.code == 10000001) {
+ var msg = $.data.message;
+ $.notify("酷乐潮玩App", "", msg);
+ }
+}
+
+function MYERR() {
+ class ParseError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ParseError";
+ }
+ }
+ return {
+ ParseError,
+ };
+}
+
+function getCookie() {
+ if (
+ $request &&
+ $request.method != "OPTIONS" &&
+ $request.url.match(/mallgateway/) &&
+ $request.body.match(/signIn/)
+ ) {
+ const body = $request.body;
+ $.log(body);
+ $.write(body, "evil_klcwappBody");
+ $.notify("酷乐潮玩App", "", "获取签到Cookie成功🎉");
+ }
+}
+
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
+function ENV() {
+ const isQX = typeof $task !== "undefined";
+ const isLoon = typeof $loon !== "undefined";
+ const isSurge = typeof $httpClient !== "undefined" && !isLoon;
+ const isJSBox = typeof require == "function" && typeof $jsbox != "undefined";
+ const isNode = typeof require == "function" && !isJSBox;
+ const isRequest = typeof $request !== "undefined";
+ const isScriptable = typeof importModule !== "undefined";
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
+}
+
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
+ const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
+ const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+
+ function send(method, options) {
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
+ const timeout = options.timeout;
+ const events = {
+ ...{
+ onRequest: () => {},
+ onResponse: (resp) => resp,
+ onTimeout: () => {},
+ },
+ ...options.events,
+ };
+
+ events.onRequest(method, options);
+
+ let worker;
+ if (isQX) {
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
+ } else if (isLoon || isSurge || isNode) {
+ worker = new Promise((resolve, reject) => {
+ const request = isNode ? require("request") : $httpClient;
+ request[method.toLowerCase()](options, (err, response, body) => {
+ if (err) reject(err);
+ else
+ resolve({
+ statusCode: response.status || response.statusCode,
+ headers: response.headers,
+ body,
+ });
+ });
+ });
+ } else if (isScriptable) {
+ const request = new Request(options.url);
+ request.method = method;
+ request.headers = options.headers;
+ request.body = options.body;
+ worker = new Promise((resolve, reject) => {
+ request
+ .loadString()
+ .then((body) => {
+ resolve({
+ statusCode: request.response.statusCode,
+ headers: request.response.headers,
+ body,
+ });
+ })
+ .catch((err) => reject(err));
+ });
+ }
+
+ let timeoutid;
+ const timer = timeout
+ ? new Promise((_, reject) => {
+ timeoutid = setTimeout(() => {
+ events.onTimeout();
+ return reject(
+ `${method} URL: ${options.url} exceeds the timeout ${timeout} ms`
+ );
+ }, timeout);
+ })
+ : null;
+
+ return (timer
+ ? Promise.race([timer, worker]).then((res) => {
+ clearTimeout(timeoutid);
+ return res;
+ })
+ : worker
+ ).then((resp) => events.onResponse(resp));
+ }
+
+ const http = {};
+ methods.forEach(
+ (method) =>
+ (http[method.toLowerCase()] = (options) => send(method, options))
+ );
+ return http;
+}
+
+function API(name = "untitled", debug = false) {
+ const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV();
+ return new (class {
+ constructor(name, debug) {
+ this.name = name;
+ this.debug = debug;
+
+ this.http = HTTP();
+ this.env = ENV();
+
+ this.node = (() => {
+ if (isNode) {
+ const fs = require("fs");
+
+ return {
+ fs,
+ };
+ } else {
+ return null;
+ }
+ })();
+ this.initCache();
+
+ const delay = (t, v) =>
+ new Promise(function (resolve) {
+ setTimeout(resolve.bind(null, v), t);
+ });
+
+ Promise.prototype.delay = function (t) {
+ return this.then(function (v) {
+ return delay(t, v);
+ });
+ };
+ }
+
+ // persistence
+ // initialize cache
+ initCache() {
+ if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
+ if (isLoon || isSurge)
+ this.cache = JSON.parse($persistentStore.read(this.name) || "{}");
+
+ if (isNode) {
+ // create a json for root cache
+ let fpath = "root.json";
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ }
+ this.root = {};
+
+ // create a json file with the given name if not exists
+ fpath = `${this.name}.json`;
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ this.cache = {};
+ } else {
+ this.cache = JSON.parse(
+ this.node.fs.readFileSync(`${this.name}.json`)
+ );
+ }
+ }
+ }
+
+ // store cache
+ persistCache() {
+ const data = JSON.stringify(this.cache, null, 2);
+ if (isQX) $prefs.setValueForKey(data, this.name);
+ if (isLoon || isSurge) $persistentStore.write(data, this.name);
+ if (isNode) {
+ this.node.fs.writeFileSync(
+ `${this.name}.json`,
+ data,
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ this.node.fs.writeFileSync(
+ "root.json",
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ }
+ }
+
+ write(data, key) {
+ this.log(`SET ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
+ }
+ if (isQX) {
+ return $prefs.setValueForKey(data, key);
+ }
+ if (isNode) {
+ this.root[key] = data;
+ }
+ } else {
+ this.cache[key] = data;
+ }
+ this.persistCache();
+ }
+
+ read(key) {
+ this.log(`READ ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.read(key);
+ }
+ if (isQX) {
+ return $prefs.valueForKey(key);
+ }
+ if (isNode) {
+ return this.root[key];
+ }
+ } else {
+ return this.cache[key];
+ }
+ }
+
+ delete(key) {
+ this.log(`DELETE ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
+ }
+ if (isQX) {
+ return $prefs.removeValueForKey(key);
+ }
+ if (isNode) {
+ delete this.root[key];
+ }
+ } else {
+ delete this.cache[key];
+ }
+ this.persistCache();
+ }
+
+ // notification
+ notify(title, subtitle = "", content = "", options = {}) {
+ const openURL = options["open-url"];
+ const mediaURL = options["media-url"];
+
+ if (isQX) $notify(title, subtitle, content, options);
+ if (isSurge) {
+ $notification.post(
+ title,
+ subtitle,
+ content + `${mediaURL ? "\n多媒体:" + mediaURL : ""}`,
+ {
+ url: openURL,
+ }
+ );
+ }
+ if (isLoon) {
+ let opts = {};
+ if (openURL) opts["openUrl"] = openURL;
+ if (mediaURL) opts["mediaUrl"] = mediaURL;
+ if (JSON.stringify(opts) === "{}") {
+ $notification.post(title, subtitle, content);
+ } else {
+ $notification.post(title, subtitle, content, opts);
+ }
+ }
+ if (isNode || isScriptable) {
+ const content_ =
+ content +
+ (openURL ? `\n点击跳转: ${openURL}` : "") +
+ (mediaURL ? `\n多媒体: ${mediaURL}` : "");
+ if (isJSBox) {
+ const push = require("push");
+ push.schedule({
+ title: title,
+ body: (subtitle ? subtitle + "\n" : "") + content_,
+ });
+ } else {
+ console.log(`${title}\n${subtitle}\n${content_}\n\n`);
+ }
+ }
+ }
+
+ // other helper functions
+ log(msg) {
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
+ }
+
+ info(msg) {
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
+ }
+
+ error(msg) {
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
+ }
+
+ wait(millisec) {
+ return new Promise((resolve) => setTimeout(resolve, millisec));
+ }
+
+ done(value = {}) {
+ if (isQX || isLoon || isSurge) {
+ $done(value);
+ } else if (isNode && !isJSBox) {
+ if (typeof $context !== "undefined") {
+ $context.headers = value.headers;
+ $context.statusCode = value.statusCode;
+ $context.body = value.body;
+ }
+ }
+ }
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
+ })(name, debug);
+}
diff --git a/check_in/klcw/klcw.js b/check_in/klcw/klcw.js
new file mode 100644
index 0000000..737074e
--- /dev/null
+++ b/check_in/klcw/klcw.js
@@ -0,0 +1,609 @@
+/*
+【酷乐潮玩小程序】@evilbutcher
+
+【仓库地址】https://github.com/evilbutcher/Quantumult_X/tree/master(欢迎star🌟)
+
+【BoxJs】https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.boxjs.json
+
+【致谢】
+感谢Peng-YM的OpenAPI.js!
+
+⚠️【免责声明】
+------------------------------------------
+1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
+2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
+3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
+4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
+5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
+6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
+7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
+
+
+【使用说明】
+微信小程序-酷乐潮玩+-我的-每日签到,手动签到获取Cookie即可使用。
+
+【Surge】
+-----------------
+[Script]
+酷乐潮玩小程序获取签到Cookie = http-request, pattern = https:\/\/wxavip\-tp\.ezrpro\.cn\/Vip\/SignIn\/SignIn, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js, requires-body=true
+酷乐潮玩小程序 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js
+
+【Loon】
+-----------------
+[Script]
+http-request https:\/\/wxavip\-tp\.ezrpro\.cn\/Vip\/SignIn\/SignIn tag=酷乐潮玩小程序获取签到Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js, requires-body=true
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js, tag=酷乐潮玩小程序
+
+【Quantumult X】
+-----------------
+[rewrite_local]
+https:\/\/wxavip\-tp\.ezrpro\.cn\/Vip\/SignIn\/SignIn url script-request-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js
+
+[task_local]
+5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js, tag=酷乐潮玩小程序
+
+【All App MitM】
+hostname = wxavip-tp.ezrpro.cn
+
+【Icon】
+透明:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/klcw_tran.png
+彩色:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/klcw.png
+*/
+
+const $ = new API("klcw", true);
+const ERR = MYERR();
+$.time = (new Date().getTime() / 1000).toFixed(0);
+$.id = $.read("evil_klcwid");
+$.SignStr = $.read("evil_klcwSignStr");
+$.Referer = $.read("evil_klcwReferer");
+$.vip = $.read("evil_klcwVip");
+$.encrypt = $.read("evil_klcwEncrypt");
+$.body = $.read("evil_klcwBody");
+
+!(async () => {
+ if (typeof $request != "undefined") {
+ getCookie();
+ return;
+ }
+ if (
+ $.id != undefined &&
+ $.SignStr != undefined &&
+ $.Referer != undefined &&
+ $.vip != undefined &&
+ $.encrypt != undefined &&
+ $.body != undefined
+ ) {
+ await checkin();
+ await checkcoupon();
+ showmsg();
+ } else {
+ $.notify("酷乐潮玩小程序", "", "❌ 请先获取Cookie");
+ }
+})()
+ .catch((err) => {
+ if (err instanceof ERR.ParseError) {
+ $.notify("酷乐潮玩小程序", "❌ 解析数据出现错误", err.message);
+ } else if (err instanceof ERR.EventError) {
+ $.notify("酷乐潮玩小程序", "❌ 请尝试重新获取Cookie", err.message);
+ } else {
+ $.notify(
+ "酷乐潮玩小程序",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
+ }
+ })
+ .finally(() => $.done());
+
+function checkin() {
+ const url = `https://wxavip-tp.ezrpro.cn/Vip/SignIn/SignIn`;
+ const headers = {
+ Connection: `keep-alive`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ timestamp: $.time,
+ "uber-trace-id": $.id,
+ "Content-Type": `application/json`,
+ "ezr-v-ip": $.vip,
+ SignStr: $.SignStr,
+ "ezr-encrypt": $.encrypt,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.2(0x18000226) NetType/WIFI Language/zh_CN`,
+ Host: `wxavip-tp.ezrpro.cn`,
+ Referer: $.Referer,
+ "Accept-Language": `zh-cn`,
+ Accept: `*/*`,
+ };
+ const myRequest = {
+ url: url,
+ headers: headers,
+ body: $.body,
+ };
+
+ return $.http.post(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ $.data = JSON.parse(response.body);
+ $.log(JSON.stringify($.data));
+ } else {
+ $.error(JSON.stringify(response));
+ throw new ERR.ParseError("签到数据解析错误,请检查日志");
+ }
+ });
+}
+
+function checkcoupon() {
+ const url = `https://wxavip-tp.ezrpro.cn/Vip/SignIn/GetSignInDtlInfo`;
+ const headers = {
+ Connection: `keep-alive`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ timestamp: $.time,
+ "uber-trace-id": $.id,
+ "Content-Type": `application/json`,
+ "ezr-v-ip": $.vip,
+ SignStr: $.SignStr,
+ "ezr-encrypt": $.encrypt,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.2(0x18000226) NetType/WIFI Language/zh_CN`,
+ Host: `wxavip-tp.ezrpro.cn`,
+ Referer: $.Referer,
+ "Accept-Language": `zh-cn`,
+ Accept: `*/*`,
+ };
+ const myRequest = {
+ url: url,
+ headers: headers,
+ };
+
+ return $.http.get(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ $.datacoupon = JSON.parse(response.body);
+ $.log(JSON.stringify($.datacoupon));
+ } else {
+ $.error(JSON.stringify(response));
+ throw new ERR.ParseError("查询优惠券数据解析错误,请检查日志");
+ }
+ });
+}
+
+function showmsg() {
+ if ($.data.Result.ErrMsg == "今日已签到") {
+ var bonus = [];
+ var coupon = $.datacoupon.Result.StepGiveInfo;
+ for (var i = 0; i < coupon.length; i++) {
+ if (coupon[i].IsFinished == true && coupon[i].IsGive == false) {
+ bonus.push(coupon[i].StepName);
+ }
+ }
+ bonus = bonus.join(" ");
+ $.notify("酷乐潮玩小程序", "今日已签到", `已获得 ${bonus}🎉\n请尽快领取~`);
+ } else if ($.data.Result.ErrMsg != null) {
+ throw new ERR.EventError(
+ `签到错误,请检查日志,原因:${$.data.Result.ErrMsg}`
+ );
+ } else {
+ var msg = $.data.Msg;
+ var bonus = [];
+ var coupon = $.datacoupon.Result.StepGiveInfo;
+ for (var i = 0; i < coupon.length; i++) {
+ if (coupon[i].IsFinished == true && coupon[i].IsGive == false) {
+ bonus.push(coupon[i].StepName);
+ }
+ }
+ bonus = bonus.join(" ");
+ $.notify("酷乐潮玩小程序", msg, `已获得 ${bonus}🎉\n请尽快领取~`);
+ }
+}
+
+function MYERR() {
+ class ParseError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ParseError";
+ }
+ }
+ class EventError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "EventError";
+ }
+ }
+ return {
+ ParseError,
+ EventError,
+ };
+}
+
+function getCookie() {
+ if (
+ $request &&
+ $request.method != "OPTIONS" &&
+ $request.url.match(/SignIn\/SignIn/)
+ ) {
+ const str = $request.headers["SignStr"];
+ $.log(str);
+ $.write(str, "evil_klcwSignStr");
+ const id = $request.headers["uber-trace-id"];
+ $.log(id);
+ $.write(id, "evil_klcwid");
+ const v_ip = $request.headers["ezr-v-ip"];
+ $.log(v_ip);
+ $.write(v_ip, "evil_klcwVip");
+ const e_ncrypt = $request.headers["ezr-encrypt"];
+ $.log(e_ncrypt);
+ $.write(e_ncrypt, "evil_klcwEncrypt");
+ const referer = $request.headers["Referer"];
+ $.log(referer);
+ $.write(referer, "evil_klcwReferer");
+ const body = $request.body;
+ $.log(body);
+ $.write(body, "evil_klcwBody");
+ $.notify("酷乐潮玩小程序", "", "获取签到Cookie成功🎉");
+ }
+}
+
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
+function ENV() {
+ const isQX = typeof $task !== "undefined";
+ const isLoon = typeof $loon !== "undefined";
+ const isSurge = typeof $httpClient !== "undefined" && !isLoon;
+ const isJSBox = typeof require == "function" && typeof $jsbox != "undefined";
+ const isNode = typeof require == "function" && !isJSBox;
+ const isRequest = typeof $request !== "undefined";
+ const isScriptable = typeof importModule !== "undefined";
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
+}
+
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
+ const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
+ const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+
+ function send(method, options) {
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
+ const timeout = options.timeout;
+ const events = {
+ ...{
+ onRequest: () => {},
+ onResponse: (resp) => resp,
+ onTimeout: () => {},
+ },
+ ...options.events,
+ };
+
+ events.onRequest(method, options);
+
+ let worker;
+ if (isQX) {
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
+ } else if (isLoon || isSurge || isNode) {
+ worker = new Promise((resolve, reject) => {
+ const request = isNode ? require("request") : $httpClient;
+ request[method.toLowerCase()](options, (err, response, body) => {
+ if (err) reject(err);
+ else
+ resolve({
+ statusCode: response.status || response.statusCode,
+ headers: response.headers,
+ body,
+ });
+ });
+ });
+ } else if (isScriptable) {
+ const request = new Request(options.url);
+ request.method = method;
+ request.headers = options.headers;
+ request.body = options.body;
+ worker = new Promise((resolve, reject) => {
+ request
+ .loadString()
+ .then((body) => {
+ resolve({
+ statusCode: request.response.statusCode,
+ headers: request.response.headers,
+ body,
+ });
+ })
+ .catch((err) => reject(err));
+ });
+ }
+
+ let timeoutid;
+ const timer = timeout
+ ? new Promise((_, reject) => {
+ timeoutid = setTimeout(() => {
+ events.onTimeout();
+ return reject(
+ `${method} URL: ${options.url} exceeds the timeout ${timeout} ms`
+ );
+ }, timeout);
+ })
+ : null;
+
+ return (timer
+ ? Promise.race([timer, worker]).then((res) => {
+ clearTimeout(timeoutid);
+ return res;
+ })
+ : worker
+ ).then((resp) => events.onResponse(resp));
+ }
+
+ const http = {};
+ methods.forEach(
+ (method) =>
+ (http[method.toLowerCase()] = (options) => send(method, options))
+ );
+ return http;
+}
+
+function API(name = "untitled", debug = false) {
+ const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV();
+ return new (class {
+ constructor(name, debug) {
+ this.name = name;
+ this.debug = debug;
+
+ this.http = HTTP();
+ this.env = ENV();
+
+ this.node = (() => {
+ if (isNode) {
+ const fs = require("fs");
+
+ return {
+ fs,
+ };
+ } else {
+ return null;
+ }
+ })();
+ this.initCache();
+
+ const delay = (t, v) =>
+ new Promise(function (resolve) {
+ setTimeout(resolve.bind(null, v), t);
+ });
+
+ Promise.prototype.delay = function (t) {
+ return this.then(function (v) {
+ return delay(t, v);
+ });
+ };
+ }
+
+ // persistence
+ // initialize cache
+ initCache() {
+ if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
+ if (isLoon || isSurge)
+ this.cache = JSON.parse($persistentStore.read(this.name) || "{}");
+
+ if (isNode) {
+ // create a json for root cache
+ let fpath = "root.json";
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ }
+ this.root = {};
+
+ // create a json file with the given name if not exists
+ fpath = `${this.name}.json`;
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ this.cache = {};
+ } else {
+ this.cache = JSON.parse(
+ this.node.fs.readFileSync(`${this.name}.json`)
+ );
+ }
+ }
+ }
+
+ // store cache
+ persistCache() {
+ const data = JSON.stringify(this.cache, null, 2);
+ if (isQX) $prefs.setValueForKey(data, this.name);
+ if (isLoon || isSurge) $persistentStore.write(data, this.name);
+ if (isNode) {
+ this.node.fs.writeFileSync(
+ `${this.name}.json`,
+ data,
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ this.node.fs.writeFileSync(
+ "root.json",
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ }
+ }
+
+ write(data, key) {
+ this.log(`SET ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
+ }
+ if (isQX) {
+ return $prefs.setValueForKey(data, key);
+ }
+ if (isNode) {
+ this.root[key] = data;
+ }
+ } else {
+ this.cache[key] = data;
+ }
+ this.persistCache();
+ }
+
+ read(key) {
+ this.log(`READ ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.read(key);
+ }
+ if (isQX) {
+ return $prefs.valueForKey(key);
+ }
+ if (isNode) {
+ return this.root[key];
+ }
+ } else {
+ return this.cache[key];
+ }
+ }
+
+ delete(key) {
+ this.log(`DELETE ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
+ }
+ if (isQX) {
+ return $prefs.removeValueForKey(key);
+ }
+ if (isNode) {
+ delete this.root[key];
+ }
+ } else {
+ delete this.cache[key];
+ }
+ this.persistCache();
+ }
+
+ // notification
+ notify(title, subtitle = "", content = "", options = {}) {
+ const openURL = options["open-url"];
+ const mediaURL = options["media-url"];
+
+ if (isQX) $notify(title, subtitle, content, options);
+ if (isSurge) {
+ $notification.post(
+ title,
+ subtitle,
+ content + `${mediaURL ? "\n多媒体:" + mediaURL : ""}`,
+ {
+ url: openURL,
+ }
+ );
+ }
+ if (isLoon) {
+ let opts = {};
+ if (openURL) opts["openUrl"] = openURL;
+ if (mediaURL) opts["mediaUrl"] = mediaURL;
+ if (JSON.stringify(opts) === "{}") {
+ $notification.post(title, subtitle, content);
+ } else {
+ $notification.post(title, subtitle, content, opts);
+ }
+ }
+ if (isNode || isScriptable) {
+ const content_ =
+ content +
+ (openURL ? `\n点击跳转: ${openURL}` : "") +
+ (mediaURL ? `\n多媒体: ${mediaURL}` : "");
+ if (isJSBox) {
+ const push = require("push");
+ push.schedule({
+ title: title,
+ body: (subtitle ? subtitle + "\n" : "") + content_,
+ });
+ } else {
+ console.log(`${title}\n${subtitle}\n${content_}\n\n`);
+ }
+ }
+ }
+
+ // other helper functions
+ log(msg) {
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
+ }
+
+ info(msg) {
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
+ }
+
+ error(msg) {
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
+ }
+
+ wait(millisec) {
+ return new Promise((resolve) => setTimeout(resolve, millisec));
+ }
+
+ done(value = {}) {
+ if (isQX || isLoon || isSurge) {
+ $done(value);
+ } else if (isNode && !isJSBox) {
+ if (typeof $context !== "undefined") {
+ $context.headers = value.headers;
+ $context.statusCode = value.statusCode;
+ $context.body = value.body;
+ }
+ }
+ }
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
+ })(name, debug);
+}
diff --git a/check_in/nasa/nasapic.js b/check_in/nasa/nasapic.js
index 7dc7c3f..8a090b8 100644
--- a/check_in/nasa/nasapic.js
+++ b/check_in/nasa/nasapic.js
@@ -64,10 +64,14 @@ const translate = [true, "true"].includes($.read("translate")) || false;
} else if (err instanceof ERR.TimeError) {
$.notify("NASA - 暂无图片", "", err.message);
} else {
- $.notify("NASA", "❌ 出现错误", JSON.stringify(err));
+ $.notify(
+ "NASA",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
}
})
- .finally($.done());
+ .finally(() => $.done());
function getpic() {
const url = `https://api.nasa.gov/planetary/apod?api_key=${$.read(
@@ -78,7 +82,7 @@ function getpic() {
if (response.statusCode == 200) {
var obj = JSON.parse(response.body);
$.data = obj;
- $.info(obj);
+ $.info(response.body);
} else if (response.statusCode == 404) {
throw new ERR.TimeError(
"❌ 暂无图片,内容在更新,请稍等呦~\n北京时间8:00-13:00为NASA更新时间段。"
@@ -153,7 +157,11 @@ function MYERR() {
};
}
-//From Peng-YM's OpenAPI.js
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
function ENV() {
const isQX = typeof $task !== "undefined";
const isLoon = typeof $loon !== "undefined";
@@ -162,17 +170,41 @@ function ENV() {
const isNode = typeof require == "function" && !isJSBox;
const isRequest = typeof $request !== "undefined";
const isScriptable = typeof importModule !== "undefined";
- return { isQX, isLoon, isSurge, isNode, isJSBox, isRequest, isScriptable };
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
}
-function HTTP(baseURL, defaultOptions = {}) {
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
function send(method, options) {
- options = typeof options === "string" ? { url: options } : options;
- options.url = baseURL ? baseURL + options.url : options.url;
- options = { ...defaultOptions, ...options };
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
const timeout = options.timeout;
const events = {
...{
@@ -187,7 +219,10 @@ function HTTP(baseURL, defaultOptions = {}) {
let worker;
if (isQX) {
- worker = $task.fetch({ method, ...options });
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
} else if (isLoon || isSurge || isNode) {
worker = new Promise((resolve, reject) => {
const request = isNode ? require("request") : $httpClient;
@@ -283,8 +318,8 @@ function API(name = "untitled", debug = false) {
});
};
}
- // persistance
+ // persistence
// initialize cache
initCache() {
if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
@@ -298,7 +333,9 @@ function API(name = "untitled", debug = false) {
this.node.fs.writeFileSync(
fpath,
JSON.stringify({}),
- { flag: "wx" },
+ {
+ flag: "wx",
+ },
(err) => console.log(err)
);
}
@@ -310,7 +347,9 @@ function API(name = "untitled", debug = false) {
this.node.fs.writeFileSync(
fpath,
JSON.stringify({}),
- { flag: "wx" },
+ {
+ flag: "wx",
+ },
(err) => console.log(err)
);
this.cache = {};
@@ -324,20 +363,24 @@ function API(name = "untitled", debug = false) {
// store cache
persistCache() {
- const data = JSON.stringify(this.cache);
+ const data = JSON.stringify(this.cache, null, 2);
if (isQX) $prefs.setValueForKey(data, this.name);
if (isLoon || isSurge) $persistentStore.write(data, this.name);
if (isNode) {
this.node.fs.writeFileSync(
`${this.name}.json`,
data,
- { flag: "w" },
+ {
+ flag: "w",
+ },
(err) => console.log(err)
);
this.node.fs.writeFileSync(
"root.json",
- JSON.stringify(this.root),
- { flag: "w" },
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
(err) => console.log(err)
);
}
@@ -347,11 +390,11 @@ function API(name = "untitled", debug = false) {
this.log(`SET ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
- $persistentStore.write(data, key);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
}
if (isQX) {
- $prefs.setValueForKey(data, key);
+ return $prefs.setValueForKey(data, key);
}
if (isNode) {
this.root[key] = data;
@@ -366,7 +409,7 @@ function API(name = "untitled", debug = false) {
this.log(`READ ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
+ if (isSurge || isLoon) {
return $persistentStore.read(key);
}
if (isQX) {
@@ -384,11 +427,11 @@ function API(name = "untitled", debug = false) {
this.log(`DELETE ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
- $persistentStore.write(null, key);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
}
if (isQX) {
- $prefs.removeValueForKey(key);
+ return $prefs.removeValueForKey(key);
}
if (isNode) {
delete this.root[key];
@@ -419,7 +462,7 @@ function API(name = "untitled", debug = false) {
let opts = {};
if (openURL) opts["openUrl"] = openURL;
if (mediaURL) opts["mediaUrl"] = mediaURL;
- if (JSON.stringify(opts) == "{}") {
+ if (JSON.stringify(opts) === "{}") {
$notification.post(title, subtitle, content);
} else {
$notification.post(title, subtitle, content, opts);
@@ -444,15 +487,15 @@ function API(name = "untitled", debug = false) {
// other helper functions
log(msg) {
- if (this.debug) console.log(msg);
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
}
info(msg) {
- console.log(msg);
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
}
error(msg) {
- console.log("ERROR: " + msg);
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
}
wait(millisec) {
@@ -470,5 +513,16 @@ function API(name = "untitled", debug = false) {
}
}
}
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
})(name, debug);
}
diff --git a/check_in/ssq/ssq.js b/check_in/ssq/ssq.js
new file mode 100644
index 0000000..06f7708
--- /dev/null
+++ b/check_in/ssq/ssq.js
@@ -0,0 +1,666 @@
+/*
+【彩票查询】@evilbutcher, @Phantom
+
+【仓库地址】https://github.com/evilbutcher/Quantumult_X/tree/master(欢迎star🌟);https://github.com/sjzcook/phantom(欢迎star🌟)
+
+【BoxJs】https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.boxjs.json
+
+【致谢】
+感谢Peng-YM的OpenAPI.js!
+
+⚠️【免责声明】
+------------------------------------------
+1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
+2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
+3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
+4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
+5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
+6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
+7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
+
+
+【使用说明】
+添加任务即可使用
+
+【Surge】
+-----------------
+[Script]
+彩票查询 = type=cron,cronexp=0 30 21 * * * ,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/ssq/ssq.js
+
+【Loon】
+-----------------
+[Script]
+cron "0 30 21 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/ssq/ssq.js, tag=彩票查询
+
+【Quantumult X】
+-----------------
+[task_local]
+0 30 21 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/ssq/ssq.js, tag=彩票查询
+
+【Icon】
+透明:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/ssq_tran.png
+彩色:https://raw.githubusercontent.com/58xinian/icon/master/Two_color_ball.png
+*/
+const $ = new API("ssq", true);
+const ERR = MYERR();
+const ssq = $.read("ssq") || true; //默认查询
+const dlt = $.read("dlt") || true; //默认查询
+const fc3d = $.read("3d") || true; //默认查询
+const qlc = $.read("qlc") || true; //默认查询
+const findlatest = $.read("new") || true; //默认仅查询当日开奖的彩票
+
+!(async () => {
+ var week = new Date().getDay();
+ if (ssq == true || ssq == "true") {
+ if (findlatest == true || findlatest == "true") {
+ if (week == 2 || week == 4 || week == 0) {
+ $.log("查询双色球");
+ await checkssq();
+ } else {
+ $.log("双色球今日未开奖");
+ }
+ } else {
+ await checkssq();
+ }
+ }
+ if (dlt == true || dlt == "true") {
+ if (findlatest == true || findlatest == "true") {
+ if (week == 1 || week == 3 || week == 6) {
+ $.log("查询大乐透");
+ await checkdlt();
+ } else {
+ $.log("大乐透今日未开奖");
+ }
+ } else {
+ await checkdlt();
+ }
+ }
+ if (fc3d == true || fc3d == "true") {
+ $.log("查询福彩3D");
+ await check3d();
+ }
+ if (qlc == true || qlc == "true") {
+ if (findlatest == true || findlatest == "true") {
+ if (week == 1 || week == 3 || week == 5) {
+ $.log("查询七乐彩");
+ await checkqlc();
+ } else {
+ $.log("七乐彩今日未开奖");
+ }
+ } else {
+ await checkqlc();
+ }
+ }
+})()
+ .catch((err) => {
+ if (err instanceof ERR.ParseError) {
+ $.notify("彩票查询", "❌ 解析数据出现错误", err.message);
+ } else {
+ $.notify(
+ "彩票查询",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
+ }
+ })
+ .finally(() => $.done());
+
+function checkssq() {
+ const url = `http://www.cwl.gov.cn/cwl_admin/kjxx/findDrawNotice?name=ssq&issueCount=5`;
+ const headers = {
+ "Accept-Encoding": `gzip, deflate`,
+ Connection: `keep-alive`,
+ Referer: `http://www.cwl.gov.cn/kjxx/ssq/`,
+ Accept: `application/json, text/javascript, */*; q=0.01`,
+ Host: `www.cwl.gov.cn`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1`,
+ "Accept-Language": `zh-cn`,
+ "X-Requested-With": `XMLHttpRequest`,
+ };
+
+ const myRequest = {
+ url: url,
+ headers: headers,
+ };
+
+ return $.http.get(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ $.data = JSON.parse(response.body).result[0];
+ var poolmoney = JSON.stringify(
+ ($.data.poolmoney / 10000).toFixed(2)
+ ).slice(1, -1);
+ var content = $.data.content;
+ var date = $.data.date;
+ var name = $.data.name;
+ var red = $.data.red;
+ var blue = $.data.blue;
+ if (content == "") {
+ var detail = "红球:" + red + "\n蓝球:" + blue + "\n奖池信息暂未更新";
+ } else {
+ var detail =
+ date +
+ "\n红球:" +
+ red +
+ "\n蓝球:" +
+ blue +
+ "\n奖池:" +
+ poolmoney +
+ "万元\n一等奖 " +
+ content;
+ }
+ $.notify("彩票查询", name, detail);
+ $.log(name + "\n" + detail);
+ }
+ });
+}
+
+function checkdlt() {
+ const url = `https://webapi.sporttery.cn/gateway/lottery/getDigitalDrawInfoV1.qry?isVerify=1¶m=85%2C0%3B35%2C0%3B350133%2C0%3B04%2C0%3B20%2C23%3B03%2C32%3B06%2C33%3B19%2C33%3B18%2C35%3B19%2C35%3B190001%2C35%3B72%2C35%3B55%2C46`;
+ const headers = {
+ "Accept-Encoding": `gzip, deflate`,
+ Connection: `keep-alive`,
+ Referer: `https://www.lottery.gov.cn/`,
+ Accept: `application/json, text/javascript, */*; q=0.01`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1`,
+ "Accept-Language": `zh-cn`,
+ };
+
+ const myRequest = {
+ url: url,
+ headers: headers,
+ };
+
+ return $.http.get(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ $.data = JSON.parse(response.body).value.dlt;
+ var dltmp = $.data.lotteryDrawResult.split(/\s+/);
+ var redArr = [];
+ var blueArr = [];
+ for (var i = 0; i < dltmp.length; i++) {
+ if (i < 5) {
+ redArr.push(dltmp[i]);
+ } else {
+ blueArr.push(dltmp[i]);
+ }
+ }
+ var date = $.data.lotterySaleEndtime.split(/\s+/)[0];
+ var detail =
+ date + "\n前区:" + redArr.join(",") + "\n后区:" + blueArr.join(",");
+ $.notify("彩票查询", "大乐透", detail);
+ $.log("大乐透" + "\n" + detail);
+ }
+ });
+}
+
+function check3d() {
+ const url = `http://www.cwl.gov.cn/cwl_admin/kjxx/findDrawNotice?name=3d&issueCount=30`;
+ const headers = {
+ "Accept-Encoding": `gzip, deflate`,
+ Connection: `keep-alive`,
+ Referer: `http://www.cwl.gov.cn/kjxx/fc3d/kjgg/`,
+ Accept: `application/json, text/javascript, */*; q=0.01`,
+ Host: `www.cwl.gov.cn`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1`,
+ "Accept-Language": `zh-cn`,
+ "X-Requested-With": `XMLHttpRequest`,
+ };
+
+ const myRequest = {
+ url: url,
+ headers: headers,
+ };
+
+ return $.http.get(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ $.data = JSON.parse(response.body).result[0];
+ var poolmoney = JSON.stringify(
+ ($.data.poolmoney / 10000).toFixed(2)
+ ).slice(1, -1);
+ var date = $.data.date;
+ var name = $.data.name;
+ var red = $.data.red;
+ var num = red.split(",");
+ var all = 0;
+ for (var i = 0; i < num.length; i++) {
+ all = all + parseInt(num[i]);
+ }
+ if (poolmoney == "NaN") {
+ var detail = "结果:" + red + "\n和值:" + all + "\n奖池信息暂未更新";
+ } else {
+ var detail =
+ date +
+ "\n结果:" +
+ red +
+ "\n和值:" +
+ all +
+ "\n奖池:" +
+ poolmoney +
+ "万元";
+ }
+ $.notify("彩票查询", name, detail);
+ $.log(name + "\n" + detail);
+ }
+ });
+}
+
+function checkqlc() {
+ const url = `http://www.cwl.gov.cn/cwl_admin/kjxx/findDrawNotice?name=qlc&issueCount=5`;
+ headers = {
+ "Accept-Encoding": `gzip, deflate`,
+ Connection: `keep-alive`,
+ Referer: `http://www.cwl.gov.cn/kjxx/qlc/`,
+ Accept: `application/json, text/javascript, */*; q=0.01`,
+ Host: `www.cwl.gov.cn`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1`,
+ "Accept-Language": `zh-cn`,
+ "X-Requested-With": `XMLHttpRequest`,
+ };
+
+ const myRequest = {
+ url: url,
+ headers: headers,
+ };
+
+ return $.http.get(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ $.data = JSON.parse(response.body).result[0];
+ var content = $.data.content;
+ var name = $.data.name;
+ var date = $.data.date;
+ var red = $.data.red;
+ var blue = $.data.blue;
+ if (content == undefined) {
+ var detail = "红球:" + red + "\n蓝球:" + blue + "\n信息暂未更新";
+ } else {
+ var detail =
+ date + "\n红球:" + red + "\n蓝球:" + blue + "\n一等奖 " + content;
+ }
+ $.notify("彩票查询", name, detail);
+ $.log(name + "\n" + detail);
+ }
+ });
+}
+
+function MYERR() {
+ class ParseError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ParseError";
+ }
+ }
+ return {
+ ParseError,
+ };
+}
+
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
+function ENV() {
+ const isQX = typeof $task !== "undefined";
+ const isLoon = typeof $loon !== "undefined";
+ const isSurge = typeof $httpClient !== "undefined" && !isLoon;
+ const isJSBox = typeof require == "function" && typeof $jsbox != "undefined";
+ const isNode = typeof require == "function" && !isJSBox;
+ const isRequest = typeof $request !== "undefined";
+ const isScriptable = typeof importModule !== "undefined";
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
+}
+
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
+ const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
+ const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX =
+ /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+
+ function send(method, options) {
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
+ const timeout = options.timeout;
+ const events = {
+ ...{
+ onRequest: () => {},
+ onResponse: (resp) => resp,
+ onTimeout: () => {},
+ },
+ ...options.events,
+ };
+
+ events.onRequest(method, options);
+
+ let worker;
+ if (isQX) {
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
+ } else if (isLoon || isSurge || isNode) {
+ worker = new Promise((resolve, reject) => {
+ const request = isNode ? require("request") : $httpClient;
+ request[method.toLowerCase()](options, (err, response, body) => {
+ if (err) reject(err);
+ else
+ resolve({
+ statusCode: response.status || response.statusCode,
+ headers: response.headers,
+ body,
+ });
+ });
+ });
+ } else if (isScriptable) {
+ const request = new Request(options.url);
+ request.method = method;
+ request.headers = options.headers;
+ request.body = options.body;
+ worker = new Promise((resolve, reject) => {
+ request
+ .loadString()
+ .then((body) => {
+ resolve({
+ statusCode: request.response.statusCode,
+ headers: request.response.headers,
+ body,
+ });
+ })
+ .catch((err) => reject(err));
+ });
+ }
+
+ let timeoutid;
+ const timer = timeout
+ ? new Promise((_, reject) => {
+ timeoutid = setTimeout(() => {
+ events.onTimeout();
+ return reject(
+ `${method} URL: ${options.url} exceeds the timeout ${timeout} ms`
+ );
+ }, timeout);
+ })
+ : null;
+
+ return (
+ timer
+ ? Promise.race([timer, worker]).then((res) => {
+ clearTimeout(timeoutid);
+ return res;
+ })
+ : worker
+ ).then((resp) => events.onResponse(resp));
+ }
+
+ const http = {};
+ methods.forEach(
+ (method) =>
+ (http[method.toLowerCase()] = (options) => send(method, options))
+ );
+ return http;
+}
+
+function API(name = "untitled", debug = false) {
+ const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV();
+ return new (class {
+ constructor(name, debug) {
+ this.name = name;
+ this.debug = debug;
+
+ this.http = HTTP();
+ this.env = ENV();
+
+ this.node = (() => {
+ if (isNode) {
+ const fs = require("fs");
+
+ return {
+ fs,
+ };
+ } else {
+ return null;
+ }
+ })();
+ this.initCache();
+
+ const delay = (t, v) =>
+ new Promise(function (resolve) {
+ setTimeout(resolve.bind(null, v), t);
+ });
+
+ Promise.prototype.delay = function (t) {
+ return this.then(function (v) {
+ return delay(t, v);
+ });
+ };
+ }
+
+ // persistence
+ // initialize cache
+ initCache() {
+ if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
+ if (isLoon || isSurge)
+ this.cache = JSON.parse($persistentStore.read(this.name) || "{}");
+
+ if (isNode) {
+ // create a json for root cache
+ let fpath = "root.json";
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ }
+ this.root = {};
+
+ // create a json file with the given name if not exists
+ fpath = `${this.name}.json`;
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ this.cache = {};
+ } else {
+ this.cache = JSON.parse(
+ this.node.fs.readFileSync(`${this.name}.json`)
+ );
+ }
+ }
+ }
+
+ // store cache
+ persistCache() {
+ const data = JSON.stringify(this.cache, null, 2);
+ if (isQX) $prefs.setValueForKey(data, this.name);
+ if (isLoon || isSurge) $persistentStore.write(data, this.name);
+ if (isNode) {
+ this.node.fs.writeFileSync(
+ `${this.name}.json`,
+ data,
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ this.node.fs.writeFileSync(
+ "root.json",
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ }
+ }
+
+ write(data, key) {
+ this.log(`SET ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
+ }
+ if (isQX) {
+ return $prefs.setValueForKey(data, key);
+ }
+ if (isNode) {
+ this.root[key] = data;
+ }
+ } else {
+ this.cache[key] = data;
+ }
+ this.persistCache();
+ }
+
+ read(key) {
+ this.log(`READ ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.read(key);
+ }
+ if (isQX) {
+ return $prefs.valueForKey(key);
+ }
+ if (isNode) {
+ return this.root[key];
+ }
+ } else {
+ return this.cache[key];
+ }
+ }
+
+ delete(key) {
+ this.log(`DELETE ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
+ }
+ if (isQX) {
+ return $prefs.removeValueForKey(key);
+ }
+ if (isNode) {
+ delete this.root[key];
+ }
+ } else {
+ delete this.cache[key];
+ }
+ this.persistCache();
+ }
+
+ // notification
+ notify(title, subtitle = "", content = "", options = {}) {
+ const openURL = options["open-url"];
+ const mediaURL = options["media-url"];
+
+ if (isQX) $notify(title, subtitle, content, options);
+ if (isSurge) {
+ $notification.post(
+ title,
+ subtitle,
+ content + `${mediaURL ? "\n多媒体:" + mediaURL : ""}`,
+ {
+ url: openURL,
+ }
+ );
+ }
+ if (isLoon) {
+ let opts = {};
+ if (openURL) opts["openUrl"] = openURL;
+ if (mediaURL) opts["mediaUrl"] = mediaURL;
+ if (JSON.stringify(opts) === "{}") {
+ $notification.post(title, subtitle, content);
+ } else {
+ $notification.post(title, subtitle, content, opts);
+ }
+ }
+ if (isNode || isScriptable) {
+ const content_ =
+ content +
+ (openURL ? `\n点击跳转: ${openURL}` : "") +
+ (mediaURL ? `\n多媒体: ${mediaURL}` : "");
+ if (isJSBox) {
+ const push = require("push");
+ push.schedule({
+ title: title,
+ body: (subtitle ? subtitle + "\n" : "") + content_,
+ });
+ } else {
+ console.log(`${title}\n${subtitle}\n${content_}\n\n`);
+ }
+ }
+ }
+
+ // other helper functions
+ log(msg) {
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
+ }
+
+ info(msg) {
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
+ }
+
+ error(msg) {
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
+ }
+
+ wait(millisec) {
+ return new Promise((resolve) => setTimeout(resolve, millisec));
+ }
+
+ done(value = {}) {
+ if (isQX || isLoon || isSurge) {
+ $done(value);
+ } else if (isNode && !isJSBox) {
+ if (typeof $context !== "undefined") {
+ $context.headers = value.headers;
+ $context.statusCode = value.statusCode;
+ $context.body = value.body;
+ }
+ }
+ }
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
+ })(name, debug);
+}
diff --git a/check_in/taobao/tb-name.js b/check_in/taobao/tb-name.js
new file mode 100644
index 0000000..8968342
--- /dev/null
+++ b/check_in/taobao/tb-name.js
@@ -0,0 +1,542 @@
+/*
+【淘宝监控-标题版】@evilbutcher
+
+【仓库地址】https://github.com/evilbutcher/Quantumult_X/tree/master(欢迎star🌟)
+
+【BoxJs】https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.boxjs.json
+
+【致谢】
+感谢Peng-YM的OpenAPI.js!
+
+⚠️【免责声明】
+------------------------------------------
+1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
+2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
+3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
+4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
+5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
+6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
+7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
+
+
+【使用说明】
+在淘宝App对商品进行分享,拷贝链接用Safari打开,自动获取Cookie、监控链接,即可使用。该脚本对应的是对标题变动监控。
+
+【Surge】
+-----------------
+[Script]
+淘宝监控获取Cookie = http-request, pattern = https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdetail, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js, requires-body=false
+淘宝监控-标题版 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js
+
+【Loon】
+-----------------
+[Script]
+http-request https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdetail tag=淘宝监控获取Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js, requires-body=false
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/taobao/tb-name.js, tag=淘宝监控-标题版
+
+【Quantumult X】
+-----------------
+[rewrite_local]
+https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdetail url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js
+
+[task_local]
+5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js, tag=淘宝监控-标题版
+
+【All App MitM】
+hostname =h5api.m.taobao.com
+
+【Icon】
+透明:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/tb_tran.png
+彩色:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/tb.png
+*/
+
+const $ = new API("taobao-name", true);
+const ERR = MYERR();
+$.cookie = $.read("evil_tbnamecookie");
+$.url = $.read("evil_tbnameurl");
+$.record = $.read("evil_tbnamerecord") || "";
+$.price = $.read("evil_tbnameprice") || "";
+
+!(async () => {
+ if (typeof $request != "undefined") {
+ getCookie();
+ return;
+ }
+ if ($.url != undefined && $.cookie != undefined) {
+ await checkin();
+ } else {
+ $.notify("淘宝监控-标题版", "", "❌ 请先获取Cookie");
+ }
+})()
+ .catch((err) => {
+ if (err instanceof ERR.ParseError) {
+ $.notify("淘宝监控-标题版", "❌ 解析数据出现错误", err.message);
+ } else {
+ $.notify(
+ "淘宝监控-标题版",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
+ }
+ })
+ .finally(() => $.done());
+
+function checkin() {
+ const url = $.url;
+ const headers = {
+ Cookie: $.cookie,
+ Accept: `*/*`,
+ Connection: `keep-alive`,
+ Referer: `https://h5.m.taobao.com/`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ Host: `h5api.m.taobao.com`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Mobile/15E148 Safari/604.1`,
+ "Accept-Language": `zh-CN,zh-Hans;q=0.9`,
+ };
+
+ const myRequest = {
+ url: url,
+ headers: headers,
+ };
+
+ return $.http.get(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ var getinfo = /\itemId\"\:\"\d+\"\,\"title\"\:\".*?\"\,/;
+ var body = response.body.slice(11, -1);
+ var obj = JSON.parse(body);
+ var data = obj.data;
+ var preinfo = JSON.stringify(data).match(getinfo);
+ var id = JSON.stringify(preinfo).slice(13, 25);
+ var link = "https://h5.m.taobao.com/awp/core/detail.htm?id=" + id;
+ var title = JSON.stringify(preinfo).slice(40, -5);
+ $.log(title);
+ $.log(id);
+ var getprice = /priceText\\"\:\\\".*?\\/;
+ var preprice = JSON.stringify(data).match(getprice);
+ var price = JSON.stringify(preprice).slice(20, -4);
+ $.log(price);
+ if (title != $.record) {
+ $.record = title;
+ $.write($.record, "evil_tbnamerecord");
+ $.notify("淘宝监控-标题版", "标题更新", title, { "open-url": link });
+ } else {
+ $.log("暂未发现标题更新");
+ }
+ if (JSON.stringify(price) != $.price) {
+ $.price = price;
+ $.write(JSON.stringify($.price), "evil_tbnameprice");
+ $.notify("淘宝监控-标题版", "价格更新", "新价格为" + price, {
+ "open-url": link,
+ });
+ } else {
+ $.log("暂未发现价格更新");
+ }
+ } else {
+ $.error(JSON.stringify(response));
+ throw new ERR.ParseError("数据解析错误,请检查日志");
+ }
+ });
+}
+
+function getCookie() {
+ if (
+ $request &&
+ $request.method != "OPTIONS" &&
+ $request.url.match(/mtop.taobao.detail.getdetail/)
+ ) {
+ const cookie = $request.headers["Cookie"];
+ $.log(cookie);
+ $.write(cookie, "evil_tbnamecookie");
+ const url = $request.url;
+ $.log(url);
+ $.write(url, "evil_tbnameurl");
+ $.notify("淘宝监控-标题版", "", "获取Cookie成功🎉");
+ }
+}
+
+function MYERR() {
+ class ParseError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ParseError";
+ }
+ }
+ return {
+ ParseError,
+ };
+}
+
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
+function ENV() {
+ const isQX = typeof $task !== "undefined";
+ const isLoon = typeof $loon !== "undefined";
+ const isSurge = typeof $httpClient !== "undefined" && !isLoon;
+ const isJSBox = typeof require == "function" && typeof $jsbox != "undefined";
+ const isNode = typeof require == "function" && !isJSBox;
+ const isRequest = typeof $request !== "undefined";
+ const isScriptable = typeof importModule !== "undefined";
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
+}
+
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
+ const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
+ const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX =
+ /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+
+ function send(method, options) {
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ if (options.body && options.headers && !options.headers["Content-Type"]) {
+ options.headers["Content-Type"] = "application/x-www-form-urlencoded";
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
+ const timeout = options.timeout;
+ const events = {
+ ...{
+ onRequest: () => {},
+ onResponse: (resp) => resp,
+ onTimeout: () => {},
+ },
+ ...options.events,
+ };
+
+ events.onRequest(method, options);
+
+ let worker;
+ if (isQX) {
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
+ } else if (isLoon || isSurge || isNode) {
+ worker = new Promise((resolve, reject) => {
+ const request = isNode ? require("request") : $httpClient;
+ request[method.toLowerCase()](options, (err, response, body) => {
+ if (err) reject(err);
+ else
+ resolve({
+ statusCode: response.status || response.statusCode,
+ headers: response.headers,
+ body,
+ });
+ });
+ });
+ } else if (isScriptable) {
+ const request = new Request(options.url);
+ request.method = method;
+ request.headers = options.headers;
+ request.body = options.body;
+ worker = new Promise((resolve, reject) => {
+ request
+ .loadString()
+ .then((body) => {
+ resolve({
+ statusCode: request.response.statusCode,
+ headers: request.response.headers,
+ body,
+ });
+ })
+ .catch((err) => reject(err));
+ });
+ }
+
+ let timeoutid;
+ const timer = timeout
+ ? new Promise((_, reject) => {
+ timeoutid = setTimeout(() => {
+ events.onTimeout();
+ return reject(
+ `${method} URL: ${options.url} exceeds the timeout ${timeout} ms`
+ );
+ }, timeout);
+ })
+ : null;
+
+ return (
+ timer
+ ? Promise.race([timer, worker]).then((res) => {
+ clearTimeout(timeoutid);
+ return res;
+ })
+ : worker
+ ).then((resp) => events.onResponse(resp));
+ }
+
+ const http = {};
+ methods.forEach(
+ (method) =>
+ (http[method.toLowerCase()] = (options) => send(method, options))
+ );
+ return http;
+}
+
+function API(name = "untitled", debug = false) {
+ const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV();
+ return new (class {
+ constructor(name, debug) {
+ this.name = name;
+ this.debug = debug;
+
+ this.http = HTTP();
+ this.env = ENV();
+
+ this.node = (() => {
+ if (isNode) {
+ const fs = require("fs");
+
+ return {
+ fs,
+ };
+ } else {
+ return null;
+ }
+ })();
+ this.initCache();
+
+ const delay = (t, v) =>
+ new Promise(function (resolve) {
+ setTimeout(resolve.bind(null, v), t);
+ });
+
+ Promise.prototype.delay = function (t) {
+ return this.then(function (v) {
+ return delay(t, v);
+ });
+ };
+ }
+
+ // persistence
+ // initialize cache
+ initCache() {
+ if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
+ if (isLoon || isSurge)
+ this.cache = JSON.parse($persistentStore.read(this.name) || "{}");
+
+ if (isNode) {
+ // create a json for root cache
+ let fpath = "root.json";
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ }
+ this.root = {};
+
+ // create a json file with the given name if not exists
+ fpath = `${this.name}.json`;
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ this.cache = {};
+ } else {
+ this.cache = JSON.parse(
+ this.node.fs.readFileSync(`${this.name}.json`)
+ );
+ }
+ }
+ }
+
+ // store cache
+ persistCache() {
+ const data = JSON.stringify(this.cache, null, 2);
+ if (isQX) $prefs.setValueForKey(data, this.name);
+ if (isLoon || isSurge) $persistentStore.write(data, this.name);
+ if (isNode) {
+ this.node.fs.writeFileSync(
+ `${this.name}.json`,
+ data,
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ this.node.fs.writeFileSync(
+ "root.json",
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ }
+ }
+
+ write(data, key) {
+ this.log(`SET ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
+ }
+ if (isQX) {
+ return $prefs.setValueForKey(data, key);
+ }
+ if (isNode) {
+ this.root[key] = data;
+ }
+ } else {
+ this.cache[key] = data;
+ }
+ this.persistCache();
+ }
+
+ read(key) {
+ this.log(`READ ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.read(key);
+ }
+ if (isQX) {
+ return $prefs.valueForKey(key);
+ }
+ if (isNode) {
+ return this.root[key];
+ }
+ } else {
+ return this.cache[key];
+ }
+ }
+
+ delete(key) {
+ this.log(`DELETE ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
+ }
+ if (isQX) {
+ return $prefs.removeValueForKey(key);
+ }
+ if (isNode) {
+ delete this.root[key];
+ }
+ } else {
+ delete this.cache[key];
+ }
+ this.persistCache();
+ }
+
+ // notification
+ notify(title, subtitle = "", content = "", options = {}) {
+ const openURL = options["open-url"];
+ const mediaURL = options["media-url"];
+
+ if (isQX) $notify(title, subtitle, content, options);
+ if (isSurge) {
+ $notification.post(
+ title,
+ subtitle,
+ content + `${mediaURL ? "\n多媒体:" + mediaURL : ""}`,
+ {
+ url: openURL,
+ }
+ );
+ }
+ if (isLoon) {
+ let opts = {};
+ if (openURL) opts["openUrl"] = openURL;
+ if (mediaURL) opts["mediaUrl"] = mediaURL;
+ if (JSON.stringify(opts) === "{}") {
+ $notification.post(title, subtitle, content);
+ } else {
+ $notification.post(title, subtitle, content, opts);
+ }
+ }
+ if (isNode || isScriptable) {
+ const content_ =
+ content +
+ (openURL ? `\n点击跳转: ${openURL}` : "") +
+ (mediaURL ? `\n多媒体: ${mediaURL}` : "");
+ if (isJSBox) {
+ const push = require("push");
+ push.schedule({
+ title: title,
+ body: (subtitle ? subtitle + "\n" : "") + content_,
+ });
+ } else {
+ console.log(`${title}\n${subtitle}\n${content_}\n\n`);
+ }
+ }
+ }
+
+ // other helper functions
+ log(msg) {
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
+ }
+
+ info(msg) {
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
+ }
+
+ error(msg) {
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
+ }
+
+ wait(millisec) {
+ return new Promise((resolve) => setTimeout(resolve, millisec));
+ }
+
+ done(value = {}) {
+ if (isQX || isLoon || isSurge) {
+ $done(value);
+ } else if (isNode && !isJSBox) {
+ if (typeof $context !== "undefined") {
+ $context.headers = value.headers;
+ $context.statusCode = value.statusCode;
+ $context.body = value.body;
+ }
+ }
+ }
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
+ })(name, debug);
+}
diff --git a/check_in/taobao/tb.js b/check_in/taobao/tb.js
new file mode 100644
index 0000000..b49d879
--- /dev/null
+++ b/check_in/taobao/tb.js
@@ -0,0 +1,534 @@
+/*
+【淘宝监控】@evilbutcher
+
+【仓库地址】https://github.com/evilbutcher/Quantumult_X/tree/master(欢迎star🌟)
+
+【BoxJs】https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.boxjs.json
+
+【致谢】
+感谢Peng-YM的OpenAPI.js!
+
+⚠️【免责声明】
+------------------------------------------
+1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
+2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
+3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
+4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
+5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
+6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
+7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
+
+
+【使用说明】
+在淘宝App对商品进行分享,拷贝链接用Safari打开,自动获取Cookie、监控链接,即可使用。该脚本对应的是对颜色分类变动监控。
+
+【Surge】
+-----------------
+[Script]
+淘宝监控获取Cookie = http-request, pattern = https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdesc, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js, requires-body=false
+淘宝监控 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js
+
+【Loon】
+-----------------
+[Script]
+http-request https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdesc tag=淘宝监控获取Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js, requires-body=false
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/taobao/tb.js, tag=淘宝监控
+
+【Quantumult X】
+-----------------
+[rewrite_local]
+https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdesc url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js
+
+[task_local]
+5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js, tag=淘宝监控
+
+【All App MitM】
+hostname =h5api.m.taobao.com
+
+【Icon】
+透明:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/tb_tran.png
+彩色:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/tb.png
+*/
+
+const $ = new API("taobao", true);
+const ERR = MYERR();
+$.cookie = $.read("evil_tbcookie");
+$.url = $.read("evil_tburl");
+$.record = $.read("evil_tbrecord") || [];
+
+!(async () => {
+ if (typeof $request != "undefined") {
+ getCookie();
+ return;
+ }
+ if ($.url != undefined && $.cookie != undefined) {
+ await checkin();
+ } else {
+ $.notify("淘宝监控", "", "❌ 请先获取Cookie");
+ }
+})()
+ .catch((err) => {
+ if (err instanceof ERR.ParseError) {
+ $.notify("淘宝监控", "❌ 解析数据出现错误", err.message);
+ } else {
+ $.notify(
+ "淘宝监控",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
+ }
+ })
+ .finally(() => $.done());
+
+function checkin() {
+ const url = $.url;
+ const headers = {
+ Cookie: $.cookie,
+ Accept: `*/*`,
+ Connection: `keep-alive`,
+ Referer: `https://h5.m.taobao.com/`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ Host: `h5api.m.taobao.com`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Mobile/15E148 Safari/604.1`,
+ "Accept-Language": `zh-CN,zh-Hans;q=0.9`,
+ };
+
+ const myRequest = {
+ url: url,
+ headers: headers,
+ };
+
+ return $.http.get(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ var getid = /id%22%3A%22\d+%22/;
+ var preid = $.url.match(getid);
+ var id = JSON.stringify(preid).slice(13, -5);
+ var link = "https://h5.m.taobao.com/awp/core/detail.htm?id=" + id;
+ var body = response.body.slice(11, -1);
+ var obj = JSON.parse(body);
+ var data = obj.data.itemProperties;
+ var detail;
+ for (i = 0; i < data.length; i++) {
+ if (data[i].name == "颜色分类") {
+ detail = data[i].value;
+ }
+ }
+ var item = detail.split(",");
+ for (j = 0; j < item.length; j++) {
+ if ($.record.indexOf(item[j]) == -1) {
+ $.record.push(item[j]);
+ $.notify("淘宝监控", "", "新增" + item[j], { "open-url": link });
+ } else {
+ $.log("暂未发现更新");
+ }
+ }
+ $.write($.record, "evil_tbrecord");
+ } else {
+ $.error(JSON.stringify(response));
+ throw new ERR.ParseError("数据解析错误,请检查日志");
+ }
+ });
+}
+
+function getCookie() {
+ if (
+ $request &&
+ $request.method != "OPTIONS" &&
+ $request.url.match(/mtop.taobao.detail.getdesc/)
+ ) {
+ const cookie = $request.headers["Cookie"];
+ $.log(cookie);
+ $.write(cookie, "evil_tbcookie");
+ const url = $request.url;
+ $.log(url);
+ $.write(url, "evil_tburl");
+ $.notify("淘宝监控", "", "获取Cookie成功🎉");
+ }
+}
+
+function MYERR() {
+ class ParseError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ParseError";
+ }
+ }
+ return {
+ ParseError,
+ };
+}
+
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
+function ENV() {
+ const isQX = typeof $task !== "undefined";
+ const isLoon = typeof $loon !== "undefined";
+ const isSurge = typeof $httpClient !== "undefined" && !isLoon;
+ const isJSBox = typeof require == "function" && typeof $jsbox != "undefined";
+ const isNode = typeof require == "function" && !isJSBox;
+ const isRequest = typeof $request !== "undefined";
+ const isScriptable = typeof importModule !== "undefined";
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
+}
+
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
+ const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
+ const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX =
+ /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+
+ function send(method, options) {
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ if (options.body && options.headers && !options.headers["Content-Type"]) {
+ options.headers["Content-Type"] = "application/x-www-form-urlencoded";
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
+ const timeout = options.timeout;
+ const events = {
+ ...{
+ onRequest: () => {},
+ onResponse: (resp) => resp,
+ onTimeout: () => {},
+ },
+ ...options.events,
+ };
+
+ events.onRequest(method, options);
+
+ let worker;
+ if (isQX) {
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
+ } else if (isLoon || isSurge || isNode) {
+ worker = new Promise((resolve, reject) => {
+ const request = isNode ? require("request") : $httpClient;
+ request[method.toLowerCase()](options, (err, response, body) => {
+ if (err) reject(err);
+ else
+ resolve({
+ statusCode: response.status || response.statusCode,
+ headers: response.headers,
+ body,
+ });
+ });
+ });
+ } else if (isScriptable) {
+ const request = new Request(options.url);
+ request.method = method;
+ request.headers = options.headers;
+ request.body = options.body;
+ worker = new Promise((resolve, reject) => {
+ request
+ .loadString()
+ .then((body) => {
+ resolve({
+ statusCode: request.response.statusCode,
+ headers: request.response.headers,
+ body,
+ });
+ })
+ .catch((err) => reject(err));
+ });
+ }
+
+ let timeoutid;
+ const timer = timeout
+ ? new Promise((_, reject) => {
+ timeoutid = setTimeout(() => {
+ events.onTimeout();
+ return reject(
+ `${method} URL: ${options.url} exceeds the timeout ${timeout} ms`
+ );
+ }, timeout);
+ })
+ : null;
+
+ return (
+ timer
+ ? Promise.race([timer, worker]).then((res) => {
+ clearTimeout(timeoutid);
+ return res;
+ })
+ : worker
+ ).then((resp) => events.onResponse(resp));
+ }
+
+ const http = {};
+ methods.forEach(
+ (method) =>
+ (http[method.toLowerCase()] = (options) => send(method, options))
+ );
+ return http;
+}
+
+function API(name = "untitled", debug = false) {
+ const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV();
+ return new (class {
+ constructor(name, debug) {
+ this.name = name;
+ this.debug = debug;
+
+ this.http = HTTP();
+ this.env = ENV();
+
+ this.node = (() => {
+ if (isNode) {
+ const fs = require("fs");
+
+ return {
+ fs,
+ };
+ } else {
+ return null;
+ }
+ })();
+ this.initCache();
+
+ const delay = (t, v) =>
+ new Promise(function (resolve) {
+ setTimeout(resolve.bind(null, v), t);
+ });
+
+ Promise.prototype.delay = function (t) {
+ return this.then(function (v) {
+ return delay(t, v);
+ });
+ };
+ }
+
+ // persistence
+ // initialize cache
+ initCache() {
+ if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
+ if (isLoon || isSurge)
+ this.cache = JSON.parse($persistentStore.read(this.name) || "{}");
+
+ if (isNode) {
+ // create a json for root cache
+ let fpath = "root.json";
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ }
+ this.root = {};
+
+ // create a json file with the given name if not exists
+ fpath = `${this.name}.json`;
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ this.cache = {};
+ } else {
+ this.cache = JSON.parse(
+ this.node.fs.readFileSync(`${this.name}.json`)
+ );
+ }
+ }
+ }
+
+ // store cache
+ persistCache() {
+ const data = JSON.stringify(this.cache, null, 2);
+ if (isQX) $prefs.setValueForKey(data, this.name);
+ if (isLoon || isSurge) $persistentStore.write(data, this.name);
+ if (isNode) {
+ this.node.fs.writeFileSync(
+ `${this.name}.json`,
+ data,
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ this.node.fs.writeFileSync(
+ "root.json",
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ }
+ }
+
+ write(data, key) {
+ this.log(`SET ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
+ }
+ if (isQX) {
+ return $prefs.setValueForKey(data, key);
+ }
+ if (isNode) {
+ this.root[key] = data;
+ }
+ } else {
+ this.cache[key] = data;
+ }
+ this.persistCache();
+ }
+
+ read(key) {
+ this.log(`READ ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.read(key);
+ }
+ if (isQX) {
+ return $prefs.valueForKey(key);
+ }
+ if (isNode) {
+ return this.root[key];
+ }
+ } else {
+ return this.cache[key];
+ }
+ }
+
+ delete(key) {
+ this.log(`DELETE ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
+ }
+ if (isQX) {
+ return $prefs.removeValueForKey(key);
+ }
+ if (isNode) {
+ delete this.root[key];
+ }
+ } else {
+ delete this.cache[key];
+ }
+ this.persistCache();
+ }
+
+ // notification
+ notify(title, subtitle = "", content = "", options = {}) {
+ const openURL = options["open-url"];
+ const mediaURL = options["media-url"];
+
+ if (isQX) $notify(title, subtitle, content, options);
+ if (isSurge) {
+ $notification.post(
+ title,
+ subtitle,
+ content + `${mediaURL ? "\n多媒体:" + mediaURL : ""}`,
+ {
+ url: openURL,
+ }
+ );
+ }
+ if (isLoon) {
+ let opts = {};
+ if (openURL) opts["openUrl"] = openURL;
+ if (mediaURL) opts["mediaUrl"] = mediaURL;
+ if (JSON.stringify(opts) === "{}") {
+ $notification.post(title, subtitle, content);
+ } else {
+ $notification.post(title, subtitle, content, opts);
+ }
+ }
+ if (isNode || isScriptable) {
+ const content_ =
+ content +
+ (openURL ? `\n点击跳转: ${openURL}` : "") +
+ (mediaURL ? `\n多媒体: ${mediaURL}` : "");
+ if (isJSBox) {
+ const push = require("push");
+ push.schedule({
+ title: title,
+ body: (subtitle ? subtitle + "\n" : "") + content_,
+ });
+ } else {
+ console.log(`${title}\n${subtitle}\n${content_}\n\n`);
+ }
+ }
+ }
+
+ // other helper functions
+ log(msg) {
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
+ }
+
+ info(msg) {
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
+ }
+
+ error(msg) {
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
+ }
+
+ wait(millisec) {
+ return new Promise((resolve) => setTimeout(resolve, millisec));
+ }
+
+ done(value = {}) {
+ if (isQX || isLoon || isSurge) {
+ $done(value);
+ } else if (isNode && !isJSBox) {
+ if (typeof $context !== "undefined") {
+ $context.headers = value.headers;
+ $context.statusCode = value.statusCode;
+ $context.body = value.body;
+ }
+ }
+ }
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
+ })(name, debug);
+}
diff --git a/check_in/timepop/timepop.js b/check_in/timepop/timepop.js
new file mode 100644
index 0000000..f9688e1
--- /dev/null
+++ b/check_in/timepop/timepop.js
@@ -0,0 +1,711 @@
+/*
+【Timepop】@evilbutcher
+
+【仓库地址】https://github.com/evilbutcher/Quantumult_X/tree/master(欢迎star🌟)
+
+【BoxJs】https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.boxjs.json
+
+【致谢】
+本脚本使用了Chavy的Env.js,感谢!
+
+⚠️【免责声明】
+------------------------------------------
+1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
+2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
+3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
+4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
+5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
+6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
+7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
+
+微信搜索小程序Timepop,如想购买Funko手办可关注。点我的,提示获取积分Cookie成功,手动签到一次,提示获取签到Cookie成功,即可使用。
+⚠️其他基于有赞的小程序也可能触发获取Cookie,请获取完后及时禁用获取Cookie重写/脚本。
+
+【Quantumult X】
+————————————————
+[rewrite_local]
+^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx4a1af22a88a99386 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx4a1af22a88a99386 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+
+[task_local]
+5 8 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+
+【Surge】
+————————————————
+[Script]
+Timepop签到 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+Timepop获取签到Cookie = http-request,pattern=^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx4a1af22a88a99386,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+Timepop获取积分Cookie = http-request,pattern=^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx4a1af22a88a99386,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+
+【Loon】
+————————————————
+[Script]
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js, tag=Timepop签到
+^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx4a1af22a88a99386, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js, tag=Timepop获取签到Cookie
+^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx4a1af22a88a99386, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js, tag=Timepop获取积分Cookie
+
+【All App MitM】
+hostname = h5.youzan.com
+
+*/
+const $ = new Env("Timepop");
+const signurl = "evil_timepopurl";
+const signcookie = "evil_timepopcookie";
+const statusurl = "evil_timepopstatusurl";
+const statuscookie = "evil_timepopstatuscookie";
+
+var siurl = $.getdata(signurl);
+var sicookie = $.getdata(signcookie);
+var sturl = $.getdata(statusurl);
+var stcookie = $.getdata(statuscookie);
+
+var detail;
+var all;
+
+!(async () => {
+ if (typeof $request != "undefined") {
+ getCookie();
+ return;
+ }
+ await checkin();
+ await getall();
+ out();
+})()
+ .catch((e) => {
+ $.log("", `❌失败! 原因: ${e}!`, "");
+ })
+ .finally(() => {
+ $.done();
+ });
+
+function checkin() {
+ const checkRequest = {
+ url: siurl,
+ headers: { "Extra-Data": sicookie },
+ };
+ console.log("checkRequest");
+ console.log(JSON.stringify(checkRequest));
+ return new Promise((resolve) => {
+ $.get(checkRequest, (error, response, data) => {
+ if (response.statusCode == 200) {
+ var body = response.body;
+ var obj = JSON.parse(body);
+ console.log(body);
+ if (obj.code == 0) {
+ var success = obj.data.is_successful;
+ if (success == true) {
+ detail = "签到成功🎉\n";
+ }
+ var prize = obj.data.prizes;
+ var count = obj.data.times
+ if (prize != null || prize != undefined) {
+ var value = 0;
+ for (var i = 0; i < prize.length; i++) {
+ value = value + prize[i].points;
+ }
+ detail = detail + "本次获得" + value + "积分\n当前周期连签天数 " +
+ count +
+ "天 ✅";
+ }
+ console.log(detail);
+ } else {
+ detail = obj.msg;
+ console.log(detail);
+ }
+ resolve();
+ } else {
+ console.log("出错啦⚠️详情查看日志🔎");
+ console.log(response);
+ resolve();
+ }
+ });
+ });
+}
+
+function getall() {
+ const allRequest = {
+ url: sturl,
+ headers: { "Extra-Data": stcookie },
+ };
+ console.log("\nallRequest");
+ console.log(JSON.stringify(allRequest));
+ return new Promise((resolve) => {
+ $.get(allRequest, (error, response, data) => {
+ if (response.statusCode == 200) {
+ var body = response.body;
+ var obj = JSON.parse(body);
+ console.log(body);
+ if (obj.code == 0) {
+ var allpoints = obj.data.stats.points;
+ all = "总积分 " + allpoints + "分 🎉";
+ console.log(all);
+ } else {
+ all = obj.msg;
+ console.log(all);
+ }
+ resolve();
+ } else {
+ console.log("出错啦⚠️详情查看日志🔎");
+ console.log(response);
+ resolve();
+ }
+ });
+ });
+}
+
+function out() {
+ var msg = detail + "\n" + all;
+ $.msg("Timepop", "", msg, {
+ "media-url":
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/img.png",
+ });
+}
+
+function getCookie() {
+ if (
+ $request &&
+ $request.method != "OPTIONS" &&
+ $request.url.match(/checkin\_id/) &&
+ $request.url.match(/wx4a1af22a88a99386/)
+ ) {
+ const siurl = $request.url;
+ $.log(siurl);
+ const sicookie = $request.headers["Extra-Data"];
+ $.log(sicookie);
+ $.setdata(siurl, signurl);
+ $.setdata(sicookie, signcookie);
+ $.msg("Timepop", "", "获取签到Cookie成功🎉");
+ }
+ if (
+ $request &&
+ $request.method != "OPTIONS" &&
+ $request.url.match(/stats/) &&
+ $request.url.match(/wx4a1af22a88a99386/)
+ ) {
+ const sturl = $request.url;
+ $.log(sturl);
+ const stcookie = $request.headers["Extra-Data"];
+ $.log(stcookie);
+ $.setdata(sturl, statusurl);
+ $.setdata(stcookie, statuscookie);
+ $.msg("Timepop", "", "获取积分Cookie成功🎉");
+ }
+}
+
+//From chavyleung's Env.js
+function Env(name, opts) {
+ class Http {
+ constructor(env) {
+ this.env = env;
+ }
+
+ send(opts, method = "GET") {
+ opts = typeof opts === "string" ? { url: opts } : opts;
+ let sender = this.get;
+ if (method === "POST") {
+ sender = this.post;
+ }
+ return new Promise((resolve, reject) => {
+ sender.call(this, opts, (err, resp, body) => {
+ if (err) reject(err);
+ else resolve(resp);
+ });
+ });
+ }
+
+ get(opts) {
+ return this.send.call(this.env, opts);
+ }
+
+ post(opts) {
+ return this.send.call(this.env, opts, "POST");
+ }
+ }
+
+ return new (class {
+ constructor(name, opts) {
+ this.name = name;
+ this.http = new Http(this);
+ this.data = null;
+ this.dataFile = "box.dat";
+ this.logs = [];
+ this.isMute = false;
+ this.isNeedRewrite = false;
+ this.logSeparator = "\n";
+ this.startTime = new Date().getTime();
+ Object.assign(this, opts);
+ this.log("", `🔔${this.name}, 开始!`);
+ }
+
+ isNode() {
+ return "undefined" !== typeof module && !!module.exports;
+ }
+
+ isQuanX() {
+ return "undefined" !== typeof $task;
+ }
+
+ isSurge() {
+ return "undefined" !== typeof $httpClient && "undefined" === typeof $loon;
+ }
+
+ isLoon() {
+ return "undefined" !== typeof $loon;
+ }
+
+ toObj(str, defaultValue = null) {
+ try {
+ return JSON.parse(str);
+ } catch {
+ return defaultValue;
+ }
+ }
+
+ toStr(obj, defaultValue = null) {
+ try {
+ return JSON.stringify(obj);
+ } catch {
+ return defaultValue;
+ }
+ }
+
+ getjson(key, defaultValue) {
+ let json = defaultValue;
+ const val = this.getdata(key);
+ if (val) {
+ try {
+ json = JSON.parse(this.getdata(key));
+ } catch {}
+ }
+ return json;
+ }
+
+ setjson(val, key) {
+ try {
+ return this.setdata(JSON.stringify(val), key);
+ } catch {
+ return false;
+ }
+ }
+
+ getScript(url) {
+ return new Promise((resolve) => {
+ this.get({ url }, (err, resp, body) => resolve(body));
+ });
+ }
+
+ runScript(script, runOpts) {
+ return new Promise((resolve) => {
+ let httpapi = this.getdata("@chavy_boxjs_userCfgs.httpapi");
+ httpapi = httpapi ? httpapi.replace(/\n/g, "").trim() : httpapi;
+ let httpapi_timeout = this.getdata(
+ "@chavy_boxjs_userCfgs.httpapi_timeout"
+ );
+ httpapi_timeout = httpapi_timeout ? httpapi_timeout * 1 : 20;
+ httpapi_timeout =
+ runOpts && runOpts.timeout ? runOpts.timeout : httpapi_timeout;
+ const [key, addr] = httpapi.split("@");
+ const opts = {
+ url: `http://${addr}/v1/scripting/evaluate`,
+ body: {
+ script_text: script,
+ mock_type: "cron",
+ timeout: httpapi_timeout,
+ },
+ headers: { "X-Key": key, Accept: "*/*" },
+ };
+ this.post(opts, (err, resp, body) => resolve(body));
+ }).catch((e) => this.logErr(e));
+ }
+
+ loaddata() {
+ if (this.isNode()) {
+ this.fs = this.fs ? this.fs : require("fs");
+ this.path = this.path ? this.path : require("path");
+ const curDirDataFilePath = this.path.resolve(this.dataFile);
+ const rootDirDataFilePath = this.path.resolve(
+ process.cwd(),
+ this.dataFile
+ );
+ const isCurDirDataFile = this.fs.existsSync(curDirDataFilePath);
+ const isRootDirDataFile =
+ !isCurDirDataFile && this.fs.existsSync(rootDirDataFilePath);
+ if (isCurDirDataFile || isRootDirDataFile) {
+ const datPath = isCurDirDataFile
+ ? curDirDataFilePath
+ : rootDirDataFilePath;
+ try {
+ return JSON.parse(this.fs.readFileSync(datPath));
+ } catch (e) {
+ return {};
+ }
+ } else return {};
+ } else return {};
+ }
+
+ writedata() {
+ if (this.isNode()) {
+ this.fs = this.fs ? this.fs : require("fs");
+ this.path = this.path ? this.path : require("path");
+ const curDirDataFilePath = this.path.resolve(this.dataFile);
+ const rootDirDataFilePath = this.path.resolve(
+ process.cwd(),
+ this.dataFile
+ );
+ const isCurDirDataFile = this.fs.existsSync(curDirDataFilePath);
+ const isRootDirDataFile =
+ !isCurDirDataFile && this.fs.existsSync(rootDirDataFilePath);
+ const jsondata = JSON.stringify(this.data);
+ if (isCurDirDataFile) {
+ this.fs.writeFileSync(curDirDataFilePath, jsondata);
+ } else if (isRootDirDataFile) {
+ this.fs.writeFileSync(rootDirDataFilePath, jsondata);
+ } else {
+ this.fs.writeFileSync(curDirDataFilePath, jsondata);
+ }
+ }
+ }
+
+ lodash_get(source, path, defaultValue = undefined) {
+ const paths = path.replace(/\[(\d+)\]/g, ".$1").split(".");
+ let result = source;
+ for (const p of paths) {
+ result = Object(result)[p];
+ if (result === undefined) {
+ return defaultValue;
+ }
+ }
+ return result;
+ }
+
+ lodash_set(obj, path, value) {
+ if (Object(obj) !== obj) return obj;
+ if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
+ path
+ .slice(0, -1)
+ .reduce(
+ (a, c, i) =>
+ Object(a[c]) === a[c]
+ ? a[c]
+ : (a[c] = Math.abs(path[i + 1]) >> 0 === +path[i + 1] ? [] : {}),
+ obj
+ )[path[path.length - 1]] = value;
+ return obj;
+ }
+
+ getdata(key) {
+ let val = this.getval(key);
+ // 如果以 @
+ if (/^@/.test(key)) {
+ const [, objkey, paths] = /^@(.*?)\.(.*?)$/.exec(key);
+ const objval = objkey ? this.getval(objkey) : "";
+ if (objval) {
+ try {
+ const objedval = JSON.parse(objval);
+ val = objedval ? this.lodash_get(objedval, paths, "") : val;
+ } catch (e) {
+ val = "";
+ }
+ }
+ }
+ return val;
+ }
+
+ setdata(val, key) {
+ let issuc = false;
+ if (/^@/.test(key)) {
+ const [, objkey, paths] = /^@(.*?)\.(.*?)$/.exec(key);
+ const objdat = this.getval(objkey);
+ const objval = objkey
+ ? objdat === "null"
+ ? null
+ : objdat || "{}"
+ : "{}";
+ try {
+ const objedval = JSON.parse(objval);
+ this.lodash_set(objedval, paths, val);
+ issuc = this.setval(JSON.stringify(objedval), objkey);
+ } catch (e) {
+ const objedval = {};
+ this.lodash_set(objedval, paths, val);
+ issuc = this.setval(JSON.stringify(objedval), objkey);
+ }
+ } else {
+ issuc = this.setval(val, key);
+ }
+ return issuc;
+ }
+
+ getval(key) {
+ if (this.isSurge() || this.isLoon()) {
+ return $persistentStore.read(key);
+ } else if (this.isQuanX()) {
+ return $prefs.valueForKey(key);
+ } else if (this.isNode()) {
+ this.data = this.loaddata();
+ return this.data[key];
+ } else {
+ return (this.data && this.data[key]) || null;
+ }
+ }
+
+ setval(val, key) {
+ if (this.isSurge() || this.isLoon()) {
+ return $persistentStore.write(val, key);
+ } else if (this.isQuanX()) {
+ return $prefs.setValueForKey(val, key);
+ } else if (this.isNode()) {
+ this.data = this.loaddata();
+ this.data[key] = val;
+ this.writedata();
+ return true;
+ } else {
+ return (this.data && this.data[key]) || null;
+ }
+ }
+
+ initGotEnv(opts) {
+ 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();
+ if (opts) {
+ opts.headers = opts.headers ? opts.headers : {};
+ if (undefined === opts.headers.Cookie && undefined === opts.cookieJar) {
+ opts.cookieJar = this.ckjar;
+ }
+ }
+ }
+
+ get(opts, callback = () => {}) {
+ if (opts.headers) {
+ delete opts.headers["Content-Type"];
+ delete opts.headers["Content-Length"];
+ }
+ if (this.isSurge() || this.isLoon()) {
+ if (this.isSurge() && this.isNeedRewrite) {
+ opts.headers = opts.headers || {};
+ Object.assign(opts.headers, { "X-Surge-Skip-Scripting": false });
+ }
+ $httpClient.get(opts, (err, resp, body) => {
+ if (!err && resp) {
+ resp.body = body;
+ resp.statusCode = resp.status;
+ }
+ callback(err, resp, body);
+ });
+ } else if (this.isQuanX()) {
+ if (this.isNeedRewrite) {
+ opts.opts = opts.opts || {};
+ Object.assign(opts.opts, { hints: false });
+ }
+ $task.fetch(opts).then(
+ (resp) => {
+ const { statusCode: status, statusCode, headers, body } = resp;
+ callback(null, { status, statusCode, headers, body }, body);
+ },
+ (err) => callback(err)
+ );
+ } else if (this.isNode()) {
+ this.initGotEnv(opts);
+ this.got(opts)
+ .on("redirect", (resp, nextOpts) => {
+ try {
+ if (resp.headers["set-cookie"]) {
+ const ck = resp.headers["set-cookie"]
+ .map(this.cktough.Cookie.parse)
+ .toString();
+ if (ck) {
+ this.ckjar.setCookieSync(ck, null);
+ }
+ nextOpts.cookieJar = this.ckjar;
+ }
+ } catch (e) {
+ this.logErr(e);
+ }
+ // this.ckjar.setCookieSync(resp.headers['set-cookie'].map(Cookie.parse).toString())
+ })
+ .then(
+ (resp) => {
+ const { statusCode: status, statusCode, headers, body } = resp;
+ callback(null, { status, statusCode, headers, body }, body);
+ },
+ (err) => {
+ const { message: error, response: resp } = err;
+ callback(error, resp, resp && resp.body);
+ }
+ );
+ }
+ }
+
+ post(opts, callback = () => {}) {
+ // 如果指定了请求体, 但没指定`Content-Type`, 则自动生成
+ if (opts.body && opts.headers && !opts.headers["Content-Type"]) {
+ opts.headers["Content-Type"] = "application/x-www-form-urlencoded";
+ }
+ if (opts.headers) delete opts.headers["Content-Length"];
+ if (this.isSurge() || this.isLoon()) {
+ if (this.isSurge() && this.isNeedRewrite) {
+ opts.headers = opts.headers || {};
+ Object.assign(opts.headers, { "X-Surge-Skip-Scripting": false });
+ }
+ $httpClient.post(opts, (err, resp, body) => {
+ if (!err && resp) {
+ resp.body = body;
+ resp.statusCode = resp.status;
+ }
+ callback(err, resp, body);
+ });
+ } else if (this.isQuanX()) {
+ opts.method = "POST";
+ if (this.isNeedRewrite) {
+ opts.opts = opts.opts || {};
+ Object.assign(opts.opts, { hints: false });
+ }
+ $task.fetch(opts).then(
+ (resp) => {
+ const { statusCode: status, statusCode, headers, body } = resp;
+ callback(null, { status, statusCode, headers, body }, body);
+ },
+ (err) => callback(err)
+ );
+ } else if (this.isNode()) {
+ this.initGotEnv(opts);
+ const { url, ..._opts } = opts;
+ this.got.post(url, _opts).then(
+ (resp) => {
+ const { statusCode: status, statusCode, headers, body } = resp;
+ callback(null, { status, statusCode, headers, body }, body);
+ },
+ (err) => {
+ const { message: error, response: resp } = err;
+ callback(error, resp, resp && resp.body);
+ }
+ );
+ }
+ }
+ /**
+ *
+ * 示例:$.time('yyyy-MM-dd qq HH:mm:ss.S')
+ * :$.time('yyyyMMddHHmmssS')
+ * y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒
+ * 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符
+ * @param {string} fmt 格式化参数
+ * @param {number} 可选: 根据指定时间戳返回格式化日期
+ *
+ */
+ time(fmt, ts = null) {
+ const date = ts ? new Date(ts) : new Date();
+ let o = {
+ "M+": date.getMonth() + 1,
+ "d+": date.getDate(),
+ "H+": date.getHours(),
+ "m+": date.getMinutes(),
+ "s+": date.getSeconds(),
+ "q+": Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds(),
+ };
+ if (/(y+)/.test(fmt))
+ fmt = fmt.replace(
+ RegExp.$1,
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
+ );
+ for (let k in o)
+ if (new RegExp("(" + k + ")").test(fmt))
+ fmt = fmt.replace(
+ RegExp.$1,
+ RegExp.$1.length == 1
+ ? o[k]
+ : ("00" + o[k]).substr(("" + o[k]).length)
+ );
+ return fmt;
+ }
+
+ /**
+ * 系统通知
+ *
+ * > 通知参数: 同时支持 QuanX 和 Loon 两种格式, EnvJs根据运行环境自动转换, Surge 环境不支持多媒体通知
+ *
+ * 示例:
+ * $.msg(title, subt, desc, 'twitter://')
+ * $.msg(title, subt, desc, { 'open-url': 'twitter://', 'media-url': 'https://github.githubassets.com/images/modules/open_graph/github-mark.png' })
+ * $.msg(title, subt, desc, { 'open-url': 'https://bing.com', 'media-url': 'https://github.githubassets.com/images/modules/open_graph/github-mark.png' })
+ *
+ * @param {*} title 标题
+ * @param {*} subt 副标题
+ * @param {*} desc 通知详情
+ * @param {*} opts 通知参数
+ *
+ */
+ msg(title = name, subt = "", desc = "", opts) {
+ const toEnvOpts = (rawopts) => {
+ if (!rawopts) return rawopts;
+ if (typeof rawopts === "string") {
+ if (this.isLoon()) return rawopts;
+ else if (this.isQuanX()) return { "open-url": rawopts };
+ else if (this.isSurge()) return { url: rawopts };
+ else return undefined;
+ } else if (typeof rawopts === "object") {
+ if (this.isLoon()) {
+ let openUrl = rawopts.openUrl || rawopts.url || rawopts["open-url"];
+ let mediaUrl = rawopts.mediaUrl || rawopts["media-url"];
+ return { openUrl, mediaUrl };
+ } else if (this.isQuanX()) {
+ let openUrl = rawopts["open-url"] || rawopts.url || rawopts.openUrl;
+ let mediaUrl = rawopts["media-url"] || rawopts.mediaUrl;
+ return { "open-url": openUrl, "media-url": mediaUrl };
+ } else if (this.isSurge()) {
+ let openUrl = rawopts.url || rawopts.openUrl || rawopts["open-url"];
+ return { url: openUrl };
+ }
+ } else {
+ return undefined;
+ }
+ };
+ if (!this.isMute) {
+ if (this.isSurge() || this.isLoon()) {
+ $notification.post(title, subt, desc, toEnvOpts(opts));
+ } else if (this.isQuanX()) {
+ $notify(title, subt, desc, toEnvOpts(opts));
+ }
+ }
+ if (!this.isMuteLog) {
+ let logs = ["", "==============📣系统通知📣=============="];
+ logs.push(title);
+ subt ? logs.push(subt) : "";
+ desc ? logs.push(desc) : "";
+ console.log(logs.join("\n"));
+ this.logs = this.logs.concat(logs);
+ }
+ }
+
+ log(...logs) {
+ if (logs.length > 0) {
+ this.logs = [...this.logs, ...logs];
+ }
+ console.log(logs.join(this.logSeparator));
+ }
+
+ logErr(err, msg) {
+ const isPrintSack = !this.isSurge() && !this.isQuanX() && !this.isLoon();
+ if (!isPrintSack) {
+ this.log("", `❗️${this.name}, 错误!`, err);
+ } else {
+ this.log("", `❗️${this.name}, 错误!`, err.stack);
+ }
+ }
+
+ wait(time) {
+ return new Promise((resolve) => setTimeout(resolve, time));
+ }
+
+ done(val = {}) {
+ const endTime = new Date().getTime();
+ const costTime = (endTime - this.startTime) / 1000;
+ this.log("", `🔔${this.name}, 结束! 🕛 ${costTime} 秒`);
+ this.log();
+ if (this.isSurge() || this.isQuanX() || this.isLoon()) {
+ $done(val);
+ }
+ }
+ })(name, opts);
+}
diff --git a/check_in/wechatsubs/gxrcw.js b/check_in/wechatsubs/gxrcw.js
new file mode 100644
index 0000000..52207da
--- /dev/null
+++ b/check_in/wechatsubs/gxrcw.js
@@ -0,0 +1,517 @@
+/*
+【高校人才网招聘监控】@evilbutcher
+
+【仓库地址】https://github.com/evilbutcher/Quantumult_X/tree/master(欢迎star🌟)
+
+【BoxJs】https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.boxjs.json
+
+【致谢】
+感谢Peng-YM的OpenAPI.js!
+
+⚠️【免责声明】
+------------------------------------------
+1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
+2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
+3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
+4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
+5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
+6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
+7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
+
+
+【使用说明】
+添加任务即可使用
+
+【Surge】
+-----------------
+[Script]
+高校人才网招聘监控 = type=cron,cronexp=5 * * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/gxrcw.js
+
+【Loon】
+-----------------
+[Script]
+cron "5 * * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/gxrcw.js, tag=高校人才网招聘监控
+
+【Quantumult X】
+-----------------
+[task_local]
+5 * * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/gxrcw.js, tag=高校人才网招聘监控
+
+【Icon】
+透明:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/gxrcw_tran.png
+彩色:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/gxrcw.png
+*/
+
+const $ = new API("gxrcw", true);
+const ERR = MYERR();
+$.refreshtime = 6; //重复内容默认在6小时内不再通知,之后清空,可自行修改
+$.saveditem = [];
+
+!(async () => {
+ init();
+ await check($.saveditem);
+})()
+ .catch((err) => {
+ if (err instanceof ERR.ParseError) {
+ $.notify("高校人才网招聘监控", "❌ 解析数据出现错误", err.message);
+ } else {
+ $.notify(
+ "高校人才网招聘监控",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
+ }
+ })
+ .finally(() => $.done());
+
+function check(saveditem) {
+ const url = `http://m.gaoxiaojob.com/list.php?tid=93`;
+ const headers = {
+ Accept: `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`,
+ "Accept-Encoding": `gzip, deflate`,
+ Connection: `keep-alive`,
+ Referer: `http://www.gaoxiaojob.com/zhaopin/diqu/beijing/`,
+ Host: `m.gaoxiaojob.com`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1`,
+ "Upgrade-Insecure-Requests": `1`,
+ "Accept-Language": `zh-cn`,
+ };
+
+ const myRequest = {
+ url: url,
+ headers: headers,
+ };
+
+ return $.http.post(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ $.data = response.body;
+ var getitem = /href=\"view.*?\<\/a/g;
+ var geturl = /view.*?\\/;
+ var gettitle = /\>.*?\;
+ var allitem = $.data.match(getitem);
+ for (var i = 0; i < allitem.length; i++) {
+ var preurl = JSON.stringify(allitem[i]).match(geturl);
+ var url =
+ "http://m.gaoxiaojob.com/" + JSON.stringify(preurl).slice(2, -4);
+ var pretitle = JSON.stringify(allitem[i]).match(gettitle);
+ var title = JSON.stringify(pretitle).slice(3, -3);
+ if (saveditem.indexOf(title) == -1) {
+ $.notify("高校人才网招聘监控", title, "", { "open-url": url });
+ saveditem.push(title);
+ }
+ }
+ $.write(JSON.stringify(saveditem), "gxrcwsaveditem");
+ }
+ });
+}
+
+function init() {
+ $.nowtime = new Date().getTime();
+ if ($.read("gxrcwsavedtime") != undefined && $.read("gxrcwsavedtime") != "") {
+ $.savedtime = $.read("gxrcwsavedtime"); //读取保存时间
+ } else {
+ $.savedtime = new Date().getTime(); //保存时间为空时,保存时间=当前时间
+ $.write(JSON.stringify($.nowtime), "gxrcwsavedtime"); //写入时间记录
+ $.write("[]", "gxrcwsaveditem"); //写入本地记录
+ }
+ $.refreshtime = $.read("gxrcwrefreshtime") || $.refreshtime;
+ var minus = $.nowtime - $.savedtime; //判断时间
+ if (minus > $.refreshtime * 3600000) {
+ $.info("达到设定时间清空本地记录并更新时间");
+ $.write(JSON.stringify($.nowtime), "gxrcwsavedtime");
+ $.write("[]", "gxrcwsaveditem");
+ }
+ if ($.read("gxrcwsaveditem") != undefined && $.read("gxrcwsaveditem") != "") {
+ var storeitem = JSON.parse($.read("gxrcwsaveditem"));
+ } else {
+ storeitem = [];
+ }
+ for (var i = 0; i < storeitem.length; i++) {
+ $.saveditem.push(storeitem[i]);
+ }
+ if ($.saveditem.length != 0) {
+ $.info("\n刷新时间内不再通知的内容👇\n" + $.saveditem + "\n");
+ }
+}
+
+function MYERR() {
+ class ParseError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ParseError";
+ }
+ }
+ return {
+ ParseError,
+ };
+}
+
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
+function ENV() {
+ const isQX = typeof $task !== "undefined";
+ const isLoon = typeof $loon !== "undefined";
+ const isSurge = typeof $httpClient !== "undefined" && !isLoon;
+ const isJSBox = typeof require == "function" && typeof $jsbox != "undefined";
+ const isNode = typeof require == "function" && !isJSBox;
+ const isRequest = typeof $request !== "undefined";
+ const isScriptable = typeof importModule !== "undefined";
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
+}
+
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
+ const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
+ const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+
+ function send(method, options) {
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
+ const timeout = options.timeout;
+ const events = {
+ ...{
+ onRequest: () => {},
+ onResponse: (resp) => resp,
+ onTimeout: () => {},
+ },
+ ...options.events,
+ };
+
+ events.onRequest(method, options);
+
+ let worker;
+ if (isQX) {
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
+ } else if (isLoon || isSurge || isNode) {
+ worker = new Promise((resolve, reject) => {
+ const request = isNode ? require("request") : $httpClient;
+ request[method.toLowerCase()](options, (err, response, body) => {
+ if (err) reject(err);
+ else
+ resolve({
+ statusCode: response.status || response.statusCode,
+ headers: response.headers,
+ body,
+ });
+ });
+ });
+ } else if (isScriptable) {
+ const request = new Request(options.url);
+ request.method = method;
+ request.headers = options.headers;
+ request.body = options.body;
+ worker = new Promise((resolve, reject) => {
+ request
+ .loadString()
+ .then((body) => {
+ resolve({
+ statusCode: request.response.statusCode,
+ headers: request.response.headers,
+ body,
+ });
+ })
+ .catch((err) => reject(err));
+ });
+ }
+
+ let timeoutid;
+ const timer = timeout
+ ? new Promise((_, reject) => {
+ timeoutid = setTimeout(() => {
+ events.onTimeout();
+ return reject(
+ `${method} URL: ${options.url} exceeds the timeout ${timeout} ms`
+ );
+ }, timeout);
+ })
+ : null;
+
+ return (timer
+ ? Promise.race([timer, worker]).then((res) => {
+ clearTimeout(timeoutid);
+ return res;
+ })
+ : worker
+ ).then((resp) => events.onResponse(resp));
+ }
+
+ const http = {};
+ methods.forEach(
+ (method) =>
+ (http[method.toLowerCase()] = (options) => send(method, options))
+ );
+ return http;
+}
+
+function API(name = "untitled", debug = false) {
+ const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV();
+ return new (class {
+ constructor(name, debug) {
+ this.name = name;
+ this.debug = debug;
+
+ this.http = HTTP();
+ this.env = ENV();
+
+ this.node = (() => {
+ if (isNode) {
+ const fs = require("fs");
+
+ return {
+ fs,
+ };
+ } else {
+ return null;
+ }
+ })();
+ this.initCache();
+
+ const delay = (t, v) =>
+ new Promise(function (resolve) {
+ setTimeout(resolve.bind(null, v), t);
+ });
+
+ Promise.prototype.delay = function (t) {
+ return this.then(function (v) {
+ return delay(t, v);
+ });
+ };
+ }
+
+ // persistence
+ // initialize cache
+ initCache() {
+ if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
+ if (isLoon || isSurge)
+ this.cache = JSON.parse($persistentStore.read(this.name) || "{}");
+
+ if (isNode) {
+ // create a json for root cache
+ let fpath = "root.json";
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ }
+ this.root = {};
+
+ // create a json file with the given name if not exists
+ fpath = `${this.name}.json`;
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ this.cache = {};
+ } else {
+ this.cache = JSON.parse(
+ this.node.fs.readFileSync(`${this.name}.json`)
+ );
+ }
+ }
+ }
+
+ // store cache
+ persistCache() {
+ const data = JSON.stringify(this.cache, null, 2);
+ if (isQX) $prefs.setValueForKey(data, this.name);
+ if (isLoon || isSurge) $persistentStore.write(data, this.name);
+ if (isNode) {
+ this.node.fs.writeFileSync(
+ `${this.name}.json`,
+ data,
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ this.node.fs.writeFileSync(
+ "root.json",
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ }
+ }
+
+ write(data, key) {
+ this.log(`SET ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
+ }
+ if (isQX) {
+ return $prefs.setValueForKey(data, key);
+ }
+ if (isNode) {
+ this.root[key] = data;
+ }
+ } else {
+ this.cache[key] = data;
+ }
+ this.persistCache();
+ }
+
+ read(key) {
+ this.log(`READ ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.read(key);
+ }
+ if (isQX) {
+ return $prefs.valueForKey(key);
+ }
+ if (isNode) {
+ return this.root[key];
+ }
+ } else {
+ return this.cache[key];
+ }
+ }
+
+ delete(key) {
+ this.log(`DELETE ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
+ }
+ if (isQX) {
+ return $prefs.removeValueForKey(key);
+ }
+ if (isNode) {
+ delete this.root[key];
+ }
+ } else {
+ delete this.cache[key];
+ }
+ this.persistCache();
+ }
+
+ // notification
+ notify(title, subtitle = "", content = "", options = {}) {
+ const openURL = options["open-url"];
+ const mediaURL = options["media-url"];
+
+ if (isQX) $notify(title, subtitle, content, options);
+ if (isSurge) {
+ $notification.post(
+ title,
+ subtitle,
+ content + `${mediaURL ? "\n多媒体:" + mediaURL : ""}`,
+ {
+ url: openURL,
+ }
+ );
+ }
+ if (isLoon) {
+ let opts = {};
+ if (openURL) opts["openUrl"] = openURL;
+ if (mediaURL) opts["mediaUrl"] = mediaURL;
+ if (JSON.stringify(opts) === "{}") {
+ $notification.post(title, subtitle, content);
+ } else {
+ $notification.post(title, subtitle, content, opts);
+ }
+ }
+ if (isNode || isScriptable) {
+ const content_ =
+ content +
+ (openURL ? `\n点击跳转: ${openURL}` : "") +
+ (mediaURL ? `\n多媒体: ${mediaURL}` : "");
+ if (isJSBox) {
+ const push = require("push");
+ push.schedule({
+ title: title,
+ body: (subtitle ? subtitle + "\n" : "") + content_,
+ });
+ } else {
+ console.log(`${title}\n${subtitle}\n${content_}\n\n`);
+ }
+ }
+ }
+
+ // other helper functions
+ log(msg) {
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
+ }
+
+ info(msg) {
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
+ }
+
+ error(msg) {
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
+ }
+
+ wait(millisec) {
+ return new Promise((resolve) => setTimeout(resolve, millisec));
+ }
+
+ done(value = {}) {
+ if (isQX || isLoon || isSurge) {
+ $done(value);
+ } else if (isNode && !isJSBox) {
+ if (typeof $context !== "undefined") {
+ $context.headers = value.headers;
+ $context.statusCode = value.statusCode;
+ $context.body = value.body;
+ }
+ }
+ }
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
+ })(name, debug);
+}
diff --git a/check_in/wechatsubs/sydwzp.js b/check_in/wechatsubs/sydwzp.js
new file mode 100644
index 0000000..3dfafd5
--- /dev/null
+++ b/check_in/wechatsubs/sydwzp.js
@@ -0,0 +1,688 @@
+/*
+【事业单位招聘监控】@evilbutcher
+
+【仓库地址】https://github.com/evilbutcher/Quantumult_X/tree/master(欢迎star🌟)
+
+【BoxJs】https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.boxjs.json
+
+【致谢】
+感谢Peng-YM的OpenAPI.js!
+
+⚠️【免责声明】
+------------------------------------------
+1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
+2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
+3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
+4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
+5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
+6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
+7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
+
+
+【使用说明】
+脚本或BoxJs填入要监控的地区即可。
+
+【Surge】
+-----------------
+[Script]
+事业单位招聘监控 = type=cron,cronexp=5 * * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/sydwzp.js
+
+【Loon】
+-----------------
+[Script]
+cron "5 * * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/sydwzp.js, tag=事业单位招聘监控
+
+【Quantumult X】
+-----------------
+[task_local]
+5 * * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/sydwzp.js, tag=事业单位招聘监控
+
+【Icon】
+透明:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/sydw_tran.png
+彩色:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/sydw.png
+*/
+
+const $ = new API("sydwzp", true);
+const ERR = MYERR();
+
+var area = "北京"; //👈本地关键词在这里设置。
+var ifgetdetail = true; //是否获取附件链接
+$.refreshtime = 6; //重复内容默认在6小时内不再通知,之后清空,可自行修改
+$.saveditem = [];
+$.url = "";
+
+!(async () => {
+ init();
+ await check($.area, $.saveditem);
+ if ($.ifgetdetail == true || $.ifgetdetail == "true") {
+ await getdetail($.url, $.saveditem);
+ }
+ if ($.area == "北京") {
+ await getsecondaddress($.saveditem);
+ if ($.ifgetdetail == true || $.ifgetdetail == "true") {
+ await getseconddetail($.url2, $.saveditem);
+ }
+ }
+})()
+ .catch((err) => {
+ if (err instanceof ERR.ParseError) {
+ $.notify("事业单位招聘监控", "❌ 解析数据出现错误", err.message);
+ } else {
+ $.notify(
+ "事业单位招聘监控",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
+ }
+ })
+ .finally(() => $.done());
+
+function check(area, saveditem) {
+ const url = `https://www.qgsydw.com/api/sys/stl/actions/search`;
+ const headers = {
+ "X-Requested-With": `XMLHttpRequest`,
+ Connection: `keep-alive`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ "Content-Type": `application/json`,
+ Origin: `https://www.qgsydw.com`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1`,
+ Host: `www.qgsydw.com`,
+ Referer: `https://www.qgsydw.com/qgsydw/area.html?word=${encodeURI(
+ area
+ )}&channelID=32&type=GroupNameCollection&date=0`,
+ "Accept-Language": `zh-cn`,
+ Accept: `application/json, text/javascript, */*; q=0.01`,
+ };
+ const body = `{"isallsites":false,"sitename":"","sitedir":"","siteids":"","channelindex":"","channelname":"","channelids":"","type":"GroupNameCollection","word":"${area}","dateattribute":"AddDate","datefrom":"","dateto":"","since":"","pagenum":0,"ishighlight":false,"siteid":"1","ajaxdivid":"ajaxElement_1_259","template":"UGwmJ5V68BHefSYdezE0add0RBWCK0add0Nwtxi2g0add0aI0add0sirknrCZ5W4BIcglBqC0add0A9G7wnL28uewF6obmz7R0add0bcyH54EXzxyYQjFv6JU7EBzLYBV6uOGIBgN0add06ypzf8acobG5OoXe0add0mxJhyJx4R9NOr0add08Ysj1UKz0add0tOrAdGkEwN6ofoirk3XzVBILy4oH1cRqi0add063Z7CiFAiW4V0SnsPLAj99umvkN3tLeEcWrvVP0add0amM6DyuT0add0Y0add0Wrn66oSIu84hlueluJgCbnAv0J5EWZaWk7uot8DH1kCqCYtGRrvg0Zu9L7E0slash0F7BOwl4Ja7NVs67xt6n60add0H2zxiOl9bEXcC8OZlZ4o97j3WeMccRIXaBfW70add0dbuqtqogFFQ0slash0VE5B10add08wODk8A9QBS4R4Bw2WqKCC64HJ4RgR6qleK9bgeLZzsIB21pJFrVHFESHMk3XCy93j0add0BcOhnhJkYIapZF0slash0zwv6gYw0add0MVMAA62Pvp5jY3t0slash00QpPacUtFFhsyqm3y3Legoo3vLIbLz0SZ0DzRVTn1hGNLJkgGTtEZ0slash0S0add0VmBJ22FOa4e78CQ8CyoNvE3SZBj0Kzs3eubwkfGMptwYnlytkIcEYqSwqJIUs89Q7wYzBHHHtrusKtc41ZMVo1HmpFvCQLhb0slash0r8umMyy5Q6F8usY0add0SnLjT7cNNPzIzduLGG50hnW0HsEroc02ldgNTXkiSFWKBtDx7Au0slash0NRC3HbiV4mPQOrJGkq3sAMpPHC6gItWn0OBRRihoPK5zhM4qFCQwg1t0add0VBsDVqrpR5I0add0IaSWZ0eGH0slash0DrdNMGHgY4e4ftRo5IoWrKG0bbUu6RZiM3Y0slash0l8MZyrLH613POrr90add0NLmM0slash0QNFtPTNifU4QP3maCe0add0k8pdFIi6eBhmPYhW89zZEbPL50slash0MOVLrdI4h6uubTwBSfKS1RMl52pJtsRe0add0GmeFoCGOBMCggI6tDCeN0add0xo6UN3FlWyd91O5x0add04Owo4mOuA1gDpeBF0slash0yWLf3JCDE4mBLB3OH0slash01Koj0ThOt5nkFIoEwinkrR0c4TyFvKu23owQNJRkBMG0add0f0add0aoHYaMvRSjw1jF0add0BtlwMznBeo5f34Y0add0t8RDKIQ4q82pDnismPeC2feiRhNJV37wGeED036W6mdU38QI3eTredjwxhrzIJ67FByxvkdiAS5Xf8EbTQB8nUa6QbrWoZYAdQzbXPspVpi1CGcugD1Rpqfeces4tbQKh0slash0mSdjF0add0oDd1YzfJdM3c10add0vyYiQLYEZ3zGjp77XV6u7QHAMpOoMiqejLbGOXAC10add0BTGDZp0slash0h0slash0w0FWuogVS980add0zkjJI3ipZM0SkZQsmCVWtPMWDheBkWUbt5g2GrbLe61TL0add0y4CBNZ4vSlUFfIbORNP0slash0X5MWikADsROqwC6qZ8D2y4A0slash0reJ0g0slash0Gzq5hEdgoz1FZExhKN7SMIpnbA9AxLQ2GD7bG5NfB5Y8rhvY0add0PQaYlOWrjt461z6SUa5g0slash0PDwFvoMXYkg35g2T7WKODD8MpPGZMEpHJhk0AOUBNSCGXRY0arnsULjVhlkKhE7mtOc0add064MwFa0ziE00slash0esFTignYS2s0add0E7q5XmC4G09Zfq0slash00f72FZstIu9yJnMGXXgy8jYC3tDgx21nLIzFF1L0kU5ZScxaQWjf0slash0K0SPaZIgTRhrVecfrBpn0add0LchPEq0zzddUdYxJt7JtmuLLCGEZZk37pkgLTv5j4fy2gBaMswORE1OlB46KVEiYXHHokEzBSrBFt0add0SGgogtkNngvYQ7n17FXTPYjdRVMdxKLjfBnIZweVfzUp9RwmBFD7KvSYU526AhX2FCN0YQCpXZsIYQb3qXl3noe9R17zl0Ksomt0slash043BVWtKyO39Y8Gbt8qPvDKTS1Xpynvnw03s4FJVDjpuxLGUmTaKR8oA5b0add0xvaa0add00o0slash0p0urPoHPY0add0yAL3e1E5R5fdKiR1kUEZdNh5WdqkHABi0slash0r9hP47dqCxpmOYYQ24HT4KedTn0kHDEUSWwCXeMCxBRZ1TDn34N4Dt2mKQS4s13lai0add0HWguO9UvO3GUUFzxHPTVxrevLd6Gi7lijJXSSqVyw8qMKYQwamVxgtwDotb85ZSxWPhDYnGXJ0add0Skdh3AzQgXn0slash0u8h3KOvdkNSnxMHPF6AWCSjvvSN3zlFsHJoYlWEW1zK0add05x3kxAQRSq4B2MKJedX6dVW7tWIAXp2hbvJUHUEWtbiJlzpWnb0add0rVE0add0t3uw3e31wtmi8d5MMT6xyBvddqTb2Z1OW7gLYQC0Ua1fil3c1B60add00njr9pqAiAcFVf3VvbYaH1BpGT0slash0AQLtUIgLNPP1waowAeGSEyV0pSWcNsXwTNgByF0add0A7O9zG30slash0wGa4Nw9deyi1OGsWz6AwJ0add0WtwO599Re0add0dDTaGCvodE3QNgB0slash0sdqieoQbV92i1vER7EwnNPqjHBn0slash0Ai9SwYOd0slash0Kc0slash0FDFBzLGsxKPQ0slash05B8Ix3OacFWRA3JnsB0JxYihSP5Msc0add04Nx70add0QVEWocb0slash0gLMUaUEWtwAPQhpZZECc9Lff4dUl2wBK0slash0sTboCBG0slash0CgINIUvWDdNqy2CvXd30jdOkeF4z7p7QlNOKFctBM252MKZUReuZ1vS2PurU7yqcCw0add0LM0j7vUzwdlH08CpnUbxrA38m8tVel1Nv6SNIMdWd1knkAQ0MX4W906FDAQAD9z9IpAa0add0GBEnUC481y3TxxF3JWEvLRnLy8gxs2yU0dACA3xSvDBPFsjj7YWjOhXolzNf0cEmsrzRz2aZeX2KdpZOmdmrEaHZeBLvQxCYlzU0slash0ZfkPkOno7lQv2uwnY2w5epTlTnMNkT0qVqdrVBsQ4IXXKH21gRlxHKoOPsizvKB8WmHP5wMSCOb3nDiXyd64bqp0slash0Zmo21ynIy8m417i8l7mtVT8VNUBlgVyXr7ElRIM2yfdk5v5ehn6Z60Lo7OmE3Ki4MSmB1eiMC9VjStdxj0add0PuVQEkc2snRPzb0slash0s5WiEr7rgkKvXHwNZKdgMathkM00bZDR83JyVHpDY9o8eYUkFXddac0add0GOpCIuzw0slash0NxoseuqWdo0FqlnOUzlUkR0add0MzPsdvFjykK819KGB1LOIZgjo2mIItEuxr4LokHbaXqLzeE6xyWI3uYJbbQneO8ZhkFKEptHA9MFZxB26qULiG050CZRlr0add0XuBWdAwUKLY84VS7CBtVYa7l5CENLGBaUC40slash0M0add0QPDwQtp3dfAXrBptF5ebWleRH6xdFlS2I6rDYg4noeMxR8mCQvXtaqHy6zFzAaZvl0add0KMJ0add0ZWVwBmufrhGwRnec8kKCsuxK9p42tarqUEG6eadKrj0kr2LNGIa3EAVDX1IV5na8oihpkypW0bkhpfbafQP545dKvRuIhoYfU4bmvg0slash0SUAY4DkND0slash0MncPphoB7vRM0rugOF40add09CS8acMQ1nYuJWkcDLGb0add0zCz6XDek0add0Fx3aREyPM7oWJqfTQNwPFksFjVKEOBe4o0slash0HwqS7L34mb6kuy80DfdW60slash0GQmOFkaeu6Vchg0add0u0slash0vGNCTJ0slash0gLbePJj90add0UeCIb4N0slash0PC0slash01DgCjIBKkaliy0G5clh1nnjE0add0sM0NaKoDm24RiG1uKsFQ20slash0z9di10hsWyKvewaTcZAW38DQTGG0slash0dvukdiT8zMN5YMkWCUfuwuWYgOD0slash0kr6JdRZ0ovaADbn4MRuNAs9ISe6zxLIfqVeafhpoTqOhZiw0add0bK6PVCdZYJlsNwn20slash0zIwQr8ixmM9a8sezorvg3EY8IrwwtkMIgYa0slash0dCJZiFn9XZApnxt6FoPF8tJA6VC8EKZ0slash01187RnwqiJ1douOKejmfiPbPZNJ1Appb2XTD44qVn97yM7y54qfESnMn6QhWlpVah0add0KFEFqERcHEwiMc1kETVXCKJ8tIZJywvT94ZTUL30add0wP1JAdG69EHNs5sPB8B4sZyivH40slash0RoI0AKeoFmS0jMSsvcwlaNxNLtSXlJjAL0TOcQg0slash02NAdiCn1SSVD9TjE5k4LeS20slash0WsdahWwXdoJ2luR9TeNP8mFmG0add0yhAY0slash0yD50slash00UAgmpJ58e0sjQMO5kO4QoFolob0add09zi10slash0Wr5Sw54WY0slash0JkqlGxAOP4NR6tEF7Z1UP1zWnhTlJB3SKqL2joRl7M51FprAPDmdefeYW5MwF8YWV4UBiBDJEP8kMyy5uhHfHlS7x0Z3NT4bLEj5JZMkLnQ6CE0pFBsKzxtziN0add0qErGTzwT2FPcy6G4PDFITbK6VQ0add0NgqiaLbB0F0add08g1djPrg3soJrA9WXW9K4DgvWVMU3kBcAhmmsiPt5ttK2P7UKfwnen8ysPgj8nKC5iSJ0add0xO12BizfpBh8TyLJIkvjM5xNtVmq0846l5O2PVZTVTnAgCrbSE5wwCNLsAq9JpenUGHYP0vOgFIP4oMwAbbEfbDD22zj8tByHLsaGTKQVdMgR7xPMUbpWza2SzXS0add040add0FbUPIA1N0pwK7SAfdoBp2rJ0eOmGNUKuGlXLwO0add0NRIV0add0SiPJ0i81FLEIPVlffnza6FY1SI0add0uc38BTajuTSlX4H5rQfDRAwdUNCYbmhtV42BrPX1WaV5heZbvdHdEXTWIV20slash0EJvxK9VadKIBrOShkvawX8YcVdLglZtwWal4cnIfVEthu41Jo0HspdEvCmE0add0ekAZL40V0MS8VXd4olXUICf0X0add092ksmaAopMVmXaHgQaz1vE23Q4f2MouwieWwuXm50slash0GWZJ7txULe6cMwNiA4gV2Pim2F6tDIFXQSlGAtkn91kv5uqtKfC4asdDn0slash0bDBx38BpwvzyrbP0add0vnBFVgCFOyOgJgeIAVZih0slash0UMEfoFMF9reyJznrGT9lacJgtpza51kn7vZY4ejPNlSB5Iv1qNtx7dixyxXpRnmBUE0pAsypAk47gEeiMGR0add056Ok2c6G7uC74YEcRcgL5jooKnThvE13ii2eOIBD6by9ph70lj5ka5EN5u0slash0Z0slash0bdVGgnMIikDZVyUynCjV5WdS0add07FNAsLG6jmdmczgU0b9TdAHsSautyBXzTFseuCWrae9rvz2T52TOVW8Bl2rsI3zpGGI0add0IU8AYMm547iD19CzuHOPhw8MtG81eODIPMakpfa8Zf1Yb0YS2uRD0add0SzUUzbOqklp6OoLUn1eilWSTWELMFbpNY0add0tYNBh0add0lOiHTOkfp5Acpp7izwnKRe4E1WjG7c6DYzzzLZfeU4L0add0Ovha14VzNscxfQS93TptxwlO0uOXkED1DqAjrSg4btYEA7zGvWbt4QhLVX83V89p9ae0slash0wJFnFKcpwtdPKekorNiPGsGGgTwTgcrm1cD4pIRG9ZJ6eFn3jlJ0slash0fbn5nMrOw0add0IRmnREym20slash0SQ7SSoFQgZMfOfyYXCiZBYe4qTuWjBqF5JfdVheM6ysx4bQqEBBjOX4QjgbTRshscr3WazOFxPcCGF7MU4EVk62nM6D6o98Z6jzrhAaYB60slash0I60add0oDXG23mn0gINZHHaEv3Px5gNTiPXpM3pNxxevTVXt6xZuT6DkFRGCnKlhrtgu0zaHKqvtX5yXV1g9TnMEhr3TmwKnnYSHwF7PAp80add0MHYs1qfDBuRph4ND4KivuSnNX0slash0PEdLfAd4N9Y4QdmTEWET4Cj0add0Qbc2yAty1m0add0QBLijxd4bTDewqQhUYARMd4C7njduxKENTG3VeL9bEaz2UjUCUBNwtGHlLXZJLhuUDeS28GtX1mwEFMtnd0add0M0YCPe8yb1uDzJtsnQH38cCZQPTOnRAnqGhNx8F4HXQdfP4y90RWdEFxRxh37GPlLDjRrx0K5cPt0slash0jNS717ELGyZS73DESG8SMY79d0slash04zXklpLUeHp9o0add0U9dDKh85vNIZIM5dZbWSwS0IDasvoxXSv10CcLoXtvy4t0add0HZYLDnspLul5HM7ecvwM5wUTcgczt1sDi4HPh4rosR1y55Vh3m7IHfrWT6Wco5kINVoAoJTsP0V2HIW51IJB5fzDOHBnjBqpMjBlPLs5FkROp0W8SLdkrbneYvZfCaihOqUOWX0slash0V0add0LvONpIO0slash036KMWjhJ2BZ289PjKWu15BmGNq0add0pOj8x0slash0vBya17aYzC6iXCd9PxzYRyFxBsWTyoB3uavqpmGcVYxiVMTpWqwA58DZjZDZBZHp4tZnG8zEkHgwkv1yMfBfcvoCRuTf8RnKiS4Agj2MfYHX0add0URQUz70add0IFxtE5HnrXNHxo0AQhhuhPkzNh2Rz8F7Vhs4e2jur4qE9f0cYIF7A1lwHwPHtQjpeecQBgCVU8mONhZ2DMx0lSdVe1p3LtXXagN1PMBqwJ5Q1vafsndBi4UCLE0equals00secret0","channelid":"32","date":"0","page":1}`;
+ const myRequest = {
+ url: url,
+ headers: headers,
+ body: body,
+ };
+
+ return $.http.post(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ var geturl = /href\=\\\".*?\\\"/;
+ var gettitle = /html\\\"\>.*?\;
+ $.data = response.body;
+ var pretitle = $.data.match(gettitle);
+ var preurl = $.data.match(geturl);
+ $.firsttitle = JSON.stringify(pretitle).slice(11, -3);
+ var url =
+ "https://www.qgsydw.com" +
+ JSON.stringify(preurl)
+ .slice(11, -6)
+ .replace(new RegExp(/\s/, "gm"), "");
+ $.info($.firsttitle);
+ $.log(url);
+ $.url = url;
+ if (saveditem.indexOf($.firsttitle) == -1) {
+ $.notify("事业单位招聘监控", $.firsttitle, "", { "open-url": url });
+ saveditem.push($.firsttitle);
+ }
+ } else {
+ $.error(JSON.stringify(response));
+ $.notify("事业单位招聘监控", "", "❌ 未知错误,请查看日志");
+ }
+ });
+}
+
+function getdetail(url, saveditem) {
+ const headers2 = {
+ "Accept-Encoding": `gzip, deflate, br`,
+ Connection: `keep-alive`,
+ Accept: `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`,
+ Host: `www.qgsydw.com`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1`,
+ "Accept-Language": `zh-cn`,
+ };
+ const myRequest = {
+ url: url,
+ headers: headers2,
+ };
+
+ return $.http.get(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ var getdurl = /qgsydw\/attachment.*?\"/g;
+ var getdtitle = /title\=\".*?\"/g;
+ $.data2 = response.body;
+ var predtitle = $.data2.match(getdtitle);
+ var predurl = $.data2.match(getdurl);
+ for (var i = 0; i < predtitle.length; i++) {
+ var title = predtitle[i].slice(7, -1);
+ var url =
+ "https://www.qgsydw.com/" +
+ predurl[i].slice(0, -1).replace(new RegExp(/\s/, "gm"), "");
+ if (saveditem.indexOf(url) == -1) {
+ $.notify("事业单位招聘监控", $.firsttitle, "招聘附件", {
+ "open-url": url,
+ });
+ saveditem.push(url);
+ }
+ $.log(title);
+ $.log(url);
+ }
+ } else if (response.statusCode == 404) {
+ $.log("详情不存在,原因:服务器错误,请稍后再尝试获取");
+ } else {
+ $.error(JSON.stringify(response));
+ $.notify(
+ "事业单位招聘监控",
+ "获取详情链接失败",
+ "❌ 未知错误,请查看日志"
+ );
+ }
+ });
+}
+
+function getsecondaddress(saveditem) {
+ const url3 = `http://rsj.beijing.gov.cn/xxgk/gkzp/`;
+ const headers3 = {
+ Cookie: `_trs_uv=kmptt6qp_365_b34g; _va_id=abd539f901538d62.1616734221.2.1616822850.1616822846.; _va_ses=*; _trs_ua_s_1=kmrakrqg_365_4qmq; _va_ref=%5B%22%22%2C%22%22%2C1616822846%2C%22https%3A%2F%2Fwww.google.com%22%5D; __jsluid_h=e7d128e54b27dd1b720e63bd9908c3f1`,
+ Accept: `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`,
+ Connection: `keep-alive`,
+ Referer: `http://rsj.beijing.gov.cn/xxgk/tzgg/`,
+ "Accept-Encoding": `gzip, deflate`,
+ Host: `rsj.beijing.gov.cn`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1`,
+ "Upgrade-Insecure-Requests": `1`,
+ "Accept-Language": `zh-cn`,
+ };
+
+ const myRequest3 = {
+ url: url3,
+ headers: headers3,
+ };
+
+ return $.http.get(myRequest3).then((response) => {
+ if (response.statusCode == 200) {
+ var getitem = /i\>\ {
+ if (response.statusCode == 200) {
+ $.data4 = response.body;
+ var getitem = /\.\ \;\.*?\;
+ var item = $.data4.match(getitem);
+ for (var i = 0; i < item.length; i++) {
+ var preurl = item[i].match(geturl);
+ var posturl = JSON.stringify(preurl).slice(11, -4);
+ var finalurl = url.replace(new RegExp(/t\d+.*/), posturl);
+ var pretitle = item[i].match(gettitle);
+ var title = JSON.stringify(pretitle).slice(5, -3);
+ $.log(title);
+ $.log(finalurl);
+ if (saveditem.indexOf(title) == -1) {
+ $.notify("事业单位招聘监控", $.secondtitle, title, {
+ "open-url": finalurl,
+ });
+ saveditem.push(title);
+ }
+ }
+ $.write(JSON.stringify(saveditem), "sydwsaveditem");
+ } else if (response.statusCode == 404) {
+ $.log("内容不存在,原因:服务器错误,请稍后再尝试获取");
+ } else {
+ $.error(JSON.stringify(response));
+ $.notify(
+ "事业单位招聘监控",
+ "获取新内容附件失败",
+ "❌ 未知错误,请查看日志"
+ );
+ }
+ });
+}
+
+function init() {
+ $.area = $.read("sydwarea") || area;
+ $.ifgetdetail = $.read("sydwdetailsetting") || ifgetdetail;
+ $.nowtime = new Date().getTime();
+ if ($.read("sydwsavedtime") != undefined && $.read("sydwsavedtime") != "") {
+ $.savedtime = $.read("sydwsavedtime"); //读取保存时间
+ } else {
+ $.savedtime = new Date().getTime(); //保存时间为空时,保存时间=当前时间
+ $.write(JSON.stringify($.nowtime), "sydwsavedtime"); //写入时间记录
+ $.write("[]", "sydwsaveditem"); //写入本地记录
+ }
+ $.refreshtime = $.read("sydwrefreshtime") || $.refreshtime;
+ var minus = $.nowtime - $.savedtime; //判断时间
+ if (minus > $.refreshtime * 3600000) {
+ $.info("达到设定时间清空本地记录并更新时间");
+ $.write(JSON.stringify($.nowtime), "sydwsavedtime");
+ $.write("[]", "sydwsaveditem");
+ }
+ if ($.read("sydwsaveditem") != undefined && $.read("sydwsaveditem") != "") {
+ var storeitem = JSON.parse($.read("sydwsaveditem"));
+ } else {
+ storeitem = [];
+ }
+ for (var i = 0; i < storeitem.length; i++) {
+ $.saveditem.push(storeitem[i]);
+ }
+ $.info(`地区:${$.area} 是否获取附件链接:${$.ifgetdetail}`);
+ if ($.saveditem.length != 0) {
+ $.info("\n刷新时间内不再通知的内容👇\n" + $.saveditem + "\n");
+ }
+}
+
+function MYERR() {
+ class ParseError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ParseError";
+ }
+ }
+ return {
+ ParseError,
+ };
+}
+
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
+function ENV() {
+ const isQX = typeof $task !== "undefined";
+ const isLoon = typeof $loon !== "undefined";
+ const isSurge = typeof $httpClient !== "undefined" && !isLoon;
+ const isJSBox = typeof require == "function" && typeof $jsbox != "undefined";
+ const isNode = typeof require == "function" && !isJSBox;
+ const isRequest = typeof $request !== "undefined";
+ const isScriptable = typeof importModule !== "undefined";
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
+}
+
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
+ const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
+ const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+
+ function send(method, options) {
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
+ const timeout = options.timeout;
+ const events = {
+ ...{
+ onRequest: () => {},
+ onResponse: (resp) => resp,
+ onTimeout: () => {},
+ },
+ ...options.events,
+ };
+
+ events.onRequest(method, options);
+
+ let worker;
+ if (isQX) {
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
+ } else if (isLoon || isSurge || isNode) {
+ worker = new Promise((resolve, reject) => {
+ const request = isNode ? require("request") : $httpClient;
+ request[method.toLowerCase()](options, (err, response, body) => {
+ if (err) reject(err);
+ else
+ resolve({
+ statusCode: response.status || response.statusCode,
+ headers: response.headers,
+ body,
+ });
+ });
+ });
+ } else if (isScriptable) {
+ const request = new Request(options.url);
+ request.method = method;
+ request.headers = options.headers;
+ request.body = options.body;
+ worker = new Promise((resolve, reject) => {
+ request
+ .loadString()
+ .then((body) => {
+ resolve({
+ statusCode: request.response.statusCode,
+ headers: request.response.headers,
+ body,
+ });
+ })
+ .catch((err) => reject(err));
+ });
+ }
+
+ let timeoutid;
+ const timer = timeout
+ ? new Promise((_, reject) => {
+ timeoutid = setTimeout(() => {
+ events.onTimeout();
+ return reject(
+ `${method} URL: ${options.url} exceeds the timeout ${timeout} ms`
+ );
+ }, timeout);
+ })
+ : null;
+
+ return (timer
+ ? Promise.race([timer, worker]).then((res) => {
+ clearTimeout(timeoutid);
+ return res;
+ })
+ : worker
+ ).then((resp) => events.onResponse(resp));
+ }
+
+ const http = {};
+ methods.forEach(
+ (method) =>
+ (http[method.toLowerCase()] = (options) => send(method, options))
+ );
+ return http;
+}
+
+function API(name = "untitled", debug = false) {
+ const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV();
+ return new (class {
+ constructor(name, debug) {
+ this.name = name;
+ this.debug = debug;
+
+ this.http = HTTP();
+ this.env = ENV();
+
+ this.node = (() => {
+ if (isNode) {
+ const fs = require("fs");
+
+ return {
+ fs,
+ };
+ } else {
+ return null;
+ }
+ })();
+ this.initCache();
+
+ const delay = (t, v) =>
+ new Promise(function (resolve) {
+ setTimeout(resolve.bind(null, v), t);
+ });
+
+ Promise.prototype.delay = function (t) {
+ return this.then(function (v) {
+ return delay(t, v);
+ });
+ };
+ }
+
+ // persistence
+ // initialize cache
+ initCache() {
+ if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
+ if (isLoon || isSurge)
+ this.cache = JSON.parse($persistentStore.read(this.name) || "{}");
+
+ if (isNode) {
+ // create a json for root cache
+ let fpath = "root.json";
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ }
+ this.root = {};
+
+ // create a json file with the given name if not exists
+ fpath = `${this.name}.json`;
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ this.cache = {};
+ } else {
+ this.cache = JSON.parse(
+ this.node.fs.readFileSync(`${this.name}.json`)
+ );
+ }
+ }
+ }
+
+ // store cache
+ persistCache() {
+ const data = JSON.stringify(this.cache, null, 2);
+ if (isQX) $prefs.setValueForKey(data, this.name);
+ if (isLoon || isSurge) $persistentStore.write(data, this.name);
+ if (isNode) {
+ this.node.fs.writeFileSync(
+ `${this.name}.json`,
+ data,
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ this.node.fs.writeFileSync(
+ "root.json",
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ }
+ }
+
+ write(data, key) {
+ this.log(`SET ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
+ }
+ if (isQX) {
+ return $prefs.setValueForKey(data, key);
+ }
+ if (isNode) {
+ this.root[key] = data;
+ }
+ } else {
+ this.cache[key] = data;
+ }
+ this.persistCache();
+ }
+
+ read(key) {
+ this.log(`READ ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.read(key);
+ }
+ if (isQX) {
+ return $prefs.valueForKey(key);
+ }
+ if (isNode) {
+ return this.root[key];
+ }
+ } else {
+ return this.cache[key];
+ }
+ }
+
+ delete(key) {
+ this.log(`DELETE ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
+ }
+ if (isQX) {
+ return $prefs.removeValueForKey(key);
+ }
+ if (isNode) {
+ delete this.root[key];
+ }
+ } else {
+ delete this.cache[key];
+ }
+ this.persistCache();
+ }
+
+ // notification
+ notify(title, subtitle = "", content = "", options = {}) {
+ const openURL = options["open-url"];
+ const mediaURL = options["media-url"];
+
+ if (isQX) $notify(title, subtitle, content, options);
+ if (isSurge) {
+ $notification.post(
+ title,
+ subtitle,
+ content + `${mediaURL ? "\n多媒体:" + mediaURL : ""}`,
+ {
+ url: openURL,
+ }
+ );
+ }
+ if (isLoon) {
+ let opts = {};
+ if (openURL) opts["openUrl"] = openURL;
+ if (mediaURL) opts["mediaUrl"] = mediaURL;
+ if (JSON.stringify(opts) === "{}") {
+ $notification.post(title, subtitle, content);
+ } else {
+ $notification.post(title, subtitle, content, opts);
+ }
+ }
+ if (isNode || isScriptable) {
+ const content_ =
+ content +
+ (openURL ? `\n点击跳转: ${openURL}` : "") +
+ (mediaURL ? `\n多媒体: ${mediaURL}` : "");
+ if (isJSBox) {
+ const push = require("push");
+ push.schedule({
+ title: title,
+ body: (subtitle ? subtitle + "\n" : "") + content_,
+ });
+ } else {
+ console.log(`${title}\n${subtitle}\n${content_}\n\n`);
+ }
+ }
+ }
+
+ // other helper functions
+ log(msg) {
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
+ }
+
+ info(msg) {
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
+ }
+
+ error(msg) {
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
+ }
+
+ wait(millisec) {
+ return new Promise((resolve) => setTimeout(resolve, millisec));
+ }
+
+ done(value = {}) {
+ if (isQX || isLoon || isSurge) {
+ $done(value);
+ } else if (isNode && !isJSBox) {
+ if (typeof $context !== "undefined") {
+ $context.headers = value.headers;
+ $context.statusCode = value.statusCode;
+ $context.body = value.body;
+ }
+ }
+ }
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
+ })(name, debug);
+}
diff --git a/check_in/wechatsubs/wechatsubs.js b/check_in/wechatsubs/wechatsubs.js
new file mode 100644
index 0000000..602c5c3
--- /dev/null
+++ b/check_in/wechatsubs/wechatsubs.js
@@ -0,0 +1,571 @@
+/*
+【公众号监控】@evilbutcher
+
+【仓库地址】https://github.com/evilbutcher/Quantumult_X/tree/master(欢迎star🌟)
+
+【BoxJs】https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/evilbutcher.boxjs.json
+
+【致谢】
+感谢Peng-YM的OpenAPI.js!
+
+⚠️【免责声明】
+------------------------------------------
+1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
+2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
+3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
+4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
+5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
+6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
+7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
+
+
+【使用说明】
+脚本或BoxJs填入要监控的关键词即可,以中文逗号“,”分隔。
+
+【Surge】
+-----------------
+[Script]
+公众号监控 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/wechatsubs.js
+
+【Loon】
+-----------------
+[Script]
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/wechatsubs.js, tag=公众号监控
+
+【Quantumult X】
+-----------------
+[task_local]
+5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/wechatsubs.js, tag=公众号监控
+
+【Icon】
+透明:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/wechat_tran.png
+彩色:https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/wechat.png
+*/
+
+const $ = new API("Wechatsubs", true);
+const ERR = MYERR();
+
+var keyword1 = [""]; //👈本地关键词在这里设置。
+var keyword2 = [""];
+$.refreshtime = 6; //重复内容默认在6小时内不再通知,之后清空,可自行修改
+$.saveditem = [];
+
+!(async () => {
+ init();
+ await checkall(keyword1, keyword2);
+})()
+ .catch((err) => {
+ if (err instanceof ERR.ParseError) {
+ $.notify("公众号监控", "❌ 解析数据出现错误", err.message);
+ } else {
+ $.notify(
+ "公众号监控",
+ "❌ 出现错误",
+ JSON.stringify(err, Object.getOwnPropertyNames(err))
+ );
+ }
+ })
+ .finally(() => $.done());
+
+async function checkall(group1, group2) {
+ for (var i = 0; i < group1.length; i++) {
+ for (var j = 0; j < group2.length; j++) {
+ await check(group1[i], group2[j], $.saveditem);
+ }
+ }
+ $.write(JSON.stringify($.saveditem), "wechatsaveditem");
+}
+
+function check(word1, word2, saveditem) {
+ const url = `https://wx.sogou.com/weixin?type=2&query=${encodeURIComponent(
+ word1
+ )}+${encodeURIComponent(word2)}`;
+ const headers = {
+ Accept: `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`,
+ Connection: `keep-alive`,
+ Referer: `https://wx.sogou.com/`,
+ "Accept-Encoding": `gzip, deflate, br`,
+ Host: `wx.sogou.com`,
+ "User-Agent": `Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1`,
+ "Accept-Language": `zh-cn`,
+ };
+ const myRequest = {
+ url: url,
+ headers: headers,
+ };
+ $.log(myRequest);
+ return $.http.get(myRequest).then((response) => {
+ if (response.statusCode == 200) {
+ var geturl = /a\starget\=\\\"\_blank\\\"\shref\=\\\"\/.*?\\\"/;
+ var gettitle = /article\_title\_0\\\"\>.*?\<\/a/;
+ var getdescription = /summary\_0\\\"\>.*?\<\/p/;
+ $.data = JSON.stringify(response.body);
+ var pretitle = $.data.match(gettitle);
+ var preurl = $.data.match(geturl);
+ var predescription = $.data.match(getdescription);
+ var title = JSON.stringify(pretitle)
+ .replace(new RegExp(/\\n/, "gm"), "")
+ .replace(new RegExp(/\s/, "gm"), "")
+ .replace(new RegExp(/\<.*?\>/, "gm"), "")
+ .replace(new RegExp(/“/, "gm"), "“")
+ .replace(new RegExp(/”/, "gm"), "”")
+ .replace(new RegExp(/·/, "gm"), "·")
+ .replace(new RegExp(/•/, "gm"), "•")
+ .replace(new RegExp(/—/, "gm"), "—")
+ .replace(new RegExp(/…/, "gm"), "…")
+ .slice(22, -5);
+ var description = JSON.stringify(predescription)
+ .replace(new RegExp(/\\n/, "gm"), "")
+ .replace(new RegExp(/\s/, "gm"), "")
+ .replace(new RegExp(/\<.*?\>/, "gm"), "")
+ .replace(new RegExp(/“/, "gm"), "“")
+ .replace(new RegExp(/”/, "gm"), "”")
+ .replace(new RegExp(/·/, "gm"), "·")
+ .replace(new RegExp(/•/, "gm"), "•")
+ .replace(new RegExp(/—/, "gm"), "—")
+ .replace(new RegExp(/…/, "gm"), "…")
+ .slice(16, -5);
+ var url =
+ "https://wx.sogou.com/" +
+ JSON.stringify(preurl)
+ .slice(36, -6)
+ .replace(new RegExp(/\s/, "gm"), "");
+ $.info(title);
+ $.log(description);
+ $.log(url);
+ if (saveditem.indexOf(title) == -1) {
+ $.notify("公众号监控", title, description, { "open-url": url });
+ saveditem.push(title);
+ }
+ } else {
+ $.error(JSON.stringify(response));
+ $.notify("公众号监控", "", "❌ 未知错误,请查看日志");
+ }
+ });
+}
+
+function init() {
+ if ($.read("wechatkeyword1") != "" && $.read("wechatkeyword1") != undefined) {
+ keyword1 = $.read("wechatkeyword1").split(",");
+ }
+ if ($.read("wechatkeyword2") != "" && $.read("wechatkeyword2") != undefined) {
+ keyword2 = $.read("wechatkeyword2").split(",");
+ }
+ $.nowtime = new Date().getTime();
+ if (
+ $.read("wechatsavedtime") != undefined &&
+ $.read("wechatsavedtime") != ""
+ ) {
+ $.savedtime = $.read("wechatsavedtime"); //读取保存时间
+ } else {
+ $.savedtime = new Date().getTime(); //保存时间为空时,保存时间=当前时间
+ $.write(JSON.stringify($.nowtime), "wechatsavedtime"); //写入时间记录
+ $.write("[]", "wechatsaveditem"); //写入本地记录
+ }
+ $.refreshtime = $.read("wechatrefreshtime") || $.refreshtime;
+ var minus = $.nowtime - $.savedtime; //判断时间
+ if (minus > $.refreshtime * 3600000) {
+ $.info("达到设定时间清空本地记录并更新时间");
+ $.write(JSON.stringify($.nowtime), "wechatsavedtime");
+ $.write("[]", "wechatsaveditem");
+ }
+ if (
+ $.read("wechatsaveditem") != undefined &&
+ $.read("wechatsaveditem") != ""
+ ) {
+ var storeitem = JSON.parse($.read("wechatsaveditem"));
+ } else {
+ storeitem = [];
+ }
+ for (var i = 0; i < storeitem.length; i++) {
+ $.saveditem.push(storeitem[i]);
+ }
+ $.info(`关键词:${keyword1}和${keyword2}`);
+ if ($.saveditem.length != 0) {
+ $.info("\n刷新时间内不再通知的内容👇\n" + $.saveditem + "\n");
+ }
+}
+
+function MYERR() {
+ class ParseError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = "ParseError";
+ }
+ }
+ return {
+ ParseError,
+ };
+}
+
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
+function ENV() {
+ const isQX = typeof $task !== "undefined";
+ const isLoon = typeof $loon !== "undefined";
+ const isSurge = typeof $httpClient !== "undefined" && !isLoon;
+ const isJSBox = typeof require == "function" && typeof $jsbox != "undefined";
+ const isNode = typeof require == "function" && !isJSBox;
+ const isRequest = typeof $request !== "undefined";
+ const isScriptable = typeof importModule !== "undefined";
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
+}
+
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
+ const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
+ const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX =
+ /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+
+ function send(method, options) {
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
+ const timeout = options.timeout;
+ const events = {
+ ...{
+ onRequest: () => {},
+ onResponse: (resp) => resp,
+ onTimeout: () => {},
+ },
+ ...options.events,
+ };
+
+ events.onRequest(method, options);
+
+ let worker;
+ if (isQX) {
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
+ } else if (isLoon || isSurge || isNode) {
+ worker = new Promise((resolve, reject) => {
+ const request = isNode ? require("request") : $httpClient;
+ request[method.toLowerCase()](options, (err, response, body) => {
+ if (err) reject(err);
+ else
+ resolve({
+ statusCode: response.status || response.statusCode,
+ headers: response.headers,
+ body,
+ });
+ });
+ });
+ } else if (isScriptable) {
+ const request = new Request(options.url);
+ request.method = method;
+ request.headers = options.headers;
+ request.body = options.body;
+ worker = new Promise((resolve, reject) => {
+ request
+ .loadString()
+ .then((body) => {
+ resolve({
+ statusCode: request.response.statusCode,
+ headers: request.response.headers,
+ body,
+ });
+ })
+ .catch((err) => reject(err));
+ });
+ }
+
+ let timeoutid;
+ const timer = timeout
+ ? new Promise((_, reject) => {
+ timeoutid = setTimeout(() => {
+ events.onTimeout();
+ return reject(
+ `${method} URL: ${options.url} exceeds the timeout ${timeout} ms`
+ );
+ }, timeout);
+ })
+ : null;
+
+ return (
+ timer
+ ? Promise.race([timer, worker]).then((res) => {
+ clearTimeout(timeoutid);
+ return res;
+ })
+ : worker
+ ).then((resp) => events.onResponse(resp));
+ }
+
+ const http = {};
+ methods.forEach(
+ (method) =>
+ (http[method.toLowerCase()] = (options) => send(method, options))
+ );
+ return http;
+}
+
+function API(name = "untitled", debug = false) {
+ const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV();
+ return new (class {
+ constructor(name, debug) {
+ this.name = name;
+ this.debug = debug;
+
+ this.http = HTTP();
+ this.env = ENV();
+
+ this.node = (() => {
+ if (isNode) {
+ const fs = require("fs");
+
+ return {
+ fs,
+ };
+ } else {
+ return null;
+ }
+ })();
+ this.initCache();
+
+ const delay = (t, v) =>
+ new Promise(function (resolve) {
+ setTimeout(resolve.bind(null, v), t);
+ });
+
+ Promise.prototype.delay = function (t) {
+ return this.then(function (v) {
+ return delay(t, v);
+ });
+ };
+ }
+
+ // persistence
+ // initialize cache
+ initCache() {
+ if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
+ if (isLoon || isSurge)
+ this.cache = JSON.parse($persistentStore.read(this.name) || "{}");
+
+ if (isNode) {
+ // create a json for root cache
+ let fpath = "root.json";
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ }
+ this.root = {};
+
+ // create a json file with the given name if not exists
+ fpath = `${this.name}.json`;
+ if (!this.node.fs.existsSync(fpath)) {
+ this.node.fs.writeFileSync(
+ fpath,
+ JSON.stringify({}),
+ {
+ flag: "wx",
+ },
+ (err) => console.log(err)
+ );
+ this.cache = {};
+ } else {
+ this.cache = JSON.parse(
+ this.node.fs.readFileSync(`${this.name}.json`)
+ );
+ }
+ }
+ }
+
+ // store cache
+ persistCache() {
+ const data = JSON.stringify(this.cache, null, 2);
+ if (isQX) $prefs.setValueForKey(data, this.name);
+ if (isLoon || isSurge) $persistentStore.write(data, this.name);
+ if (isNode) {
+ this.node.fs.writeFileSync(
+ `${this.name}.json`,
+ data,
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ this.node.fs.writeFileSync(
+ "root.json",
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
+ (err) => console.log(err)
+ );
+ }
+ }
+
+ write(data, key) {
+ this.log(`SET ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
+ }
+ if (isQX) {
+ return $prefs.setValueForKey(data, key);
+ }
+ if (isNode) {
+ this.root[key] = data;
+ }
+ } else {
+ this.cache[key] = data;
+ }
+ this.persistCache();
+ }
+
+ read(key) {
+ this.log(`READ ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.read(key);
+ }
+ if (isQX) {
+ return $prefs.valueForKey(key);
+ }
+ if (isNode) {
+ return this.root[key];
+ }
+ } else {
+ return this.cache[key];
+ }
+ }
+
+ delete(key) {
+ this.log(`DELETE ${key}`);
+ if (key.indexOf("#") !== -1) {
+ key = key.substr(1);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
+ }
+ if (isQX) {
+ return $prefs.removeValueForKey(key);
+ }
+ if (isNode) {
+ delete this.root[key];
+ }
+ } else {
+ delete this.cache[key];
+ }
+ this.persistCache();
+ }
+
+ // notification
+ notify(title, subtitle = "", content = "", options = {}) {
+ const openURL = options["open-url"];
+ const mediaURL = options["media-url"];
+
+ if (isQX) $notify(title, subtitle, content, options);
+ if (isSurge) {
+ $notification.post(
+ title,
+ subtitle,
+ content + `${mediaURL ? "\n多媒体:" + mediaURL : ""}`,
+ {
+ url: openURL,
+ }
+ );
+ }
+ if (isLoon) {
+ let opts = {};
+ if (openURL) opts["openUrl"] = openURL;
+ if (mediaURL) opts["mediaUrl"] = mediaURL;
+ if (JSON.stringify(opts) === "{}") {
+ $notification.post(title, subtitle, content);
+ } else {
+ $notification.post(title, subtitle, content, opts);
+ }
+ }
+ if (isNode || isScriptable) {
+ const content_ =
+ content +
+ (openURL ? `\n点击跳转: ${openURL}` : "") +
+ (mediaURL ? `\n多媒体: ${mediaURL}` : "");
+ if (isJSBox) {
+ const push = require("push");
+ push.schedule({
+ title: title,
+ body: (subtitle ? subtitle + "\n" : "") + content_,
+ });
+ } else {
+ console.log(`${title}\n${subtitle}\n${content_}\n\n`);
+ }
+ }
+ }
+
+ // other helper functions
+ log(msg) {
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
+ }
+
+ info(msg) {
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
+ }
+
+ error(msg) {
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
+ }
+
+ wait(millisec) {
+ return new Promise((resolve) => setTimeout(resolve, millisec));
+ }
+
+ done(value = {}) {
+ if (isQX || isLoon || isSurge) {
+ $done(value);
+ } else if (isNode && !isJSBox) {
+ if (typeof $context !== "undefined") {
+ $context.headers = value.headers;
+ $context.statusCode = value.statusCode;
+ $context.body = value.body;
+ }
+ }
+ }
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
+ })(name, debug);
+}
diff --git a/check_in/weibo/deletecookie.js b/check_in/weibo/deletecookie.js
index 6fe7f19..0d74405 100644
--- a/check_in/weibo/deletecookie.js
+++ b/check_in/weibo/deletecookie.js
@@ -331,11 +331,15 @@ function Env(name, opts) {
this.got(opts)
.on("redirect", (resp, nextOpts) => {
try {
- const ck = resp.headers["set-cookie"]
- .map(this.cktough.Cookie.parse)
- .toString();
- this.ckjar.setCookieSync(ck, null);
- nextOpts.cookieJar = this.ckjar;
+ if (resp.headers["set-cookie"]) {
+ const ck = resp.headers["set-cookie"]
+ .map(this.cktough.Cookie.parse)
+ .toString();
+ if (ck) {
+ this.ckjar.setCookieSync(ck, null);
+ }
+ nextOpts.cookieJar = this.ckjar;
+ }
} catch (e) {
this.logErr(e);
}
@@ -406,23 +410,25 @@ function Env(name, opts) {
* :$.time('yyyyMMddHHmmssS')
* y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒
* 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符
- * @param {*} fmt 格式化参数
+ * @param {string} fmt 格式化参数
+ * @param {number} 可选: 根据指定时间戳返回格式化日期
*
*/
- time(fmt) {
+ time(fmt, ts = null) {
+ const date = ts ? new Date(ts) : new Date();
let o = {
- "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(),
+ "M+": date.getMonth() + 1,
+ "d+": date.getDate(),
+ "H+": date.getHours(),
+ "m+": date.getMinutes(),
+ "s+": date.getSeconds(),
+ "q+": Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds(),
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
- (new Date().getFullYear() + "").substr(4 - RegExp.$1.length)
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (let k in o)
if (new RegExp("(" + k + ")").test(fmt))
@@ -483,12 +489,14 @@ function Env(name, opts) {
$notify(title, subt, desc, toEnvOpts(opts));
}
}
- let logs = ["", "==============📣系统通知📣=============="];
- logs.push(title);
- subt ? logs.push(subt) : "";
- desc ? logs.push(desc) : "";
- console.log(logs.join("\n"));
- this.logs = this.logs.concat(logs);
+ if (!this.isMuteLog) {
+ let logs = ["", "==============📣系统通知📣=============="];
+ logs.push(title);
+ subt ? logs.push(subt) : "";
+ desc ? logs.push(desc) : "";
+ console.log(logs.join("\n"));
+ this.logs = this.logs.concat(logs);
+ }
}
log(...logs) {
diff --git a/check_in/weibo/weibotalk.cookie.js b/check_in/weibo/weibotalk.cookie.js
index 521e003..9328480 100644
--- a/check_in/weibo/weibotalk.cookie.js
+++ b/check_in/weibo/weibotalk.cookie.js
@@ -67,7 +67,7 @@
5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/weibo/weibotalk.js, tag=微博超话
[MITM]
- hostname = api.weibo.cn
+ hostname = api.weibo.cn, mapi.weibo.com
*********/
@@ -82,7 +82,7 @@ const tokencheckinheaders = "evil_tokencheckinheaders";
if (
$request &&
$request.method != "OPTIONS" &&
- $request.url.match(/\_\-\_myfollow\&need\_head\_cards/) &&
+ $request.url.match(/\_\-\_myfollow.*?need\_head\_cards/) &&
$request.url.match(/cardlist/)
) {
const listurl = $request.url;
@@ -134,7 +134,7 @@ if (
$.done();
-//chavyleung
+//From chavyleung's Env.js
function Env(name, opts) {
class Http {
constructor(env) {
@@ -452,11 +452,15 @@ function Env(name, opts) {
this.got(opts)
.on("redirect", (resp, nextOpts) => {
try {
- const ck = resp.headers["set-cookie"]
- .map(this.cktough.Cookie.parse)
- .toString();
- this.ckjar.setCookieSync(ck, null);
- nextOpts.cookieJar = this.ckjar;
+ if (resp.headers["set-cookie"]) {
+ const ck = resp.headers["set-cookie"]
+ .map(this.cktough.Cookie.parse)
+ .toString();
+ if (ck) {
+ this.ckjar.setCookieSync(ck, null);
+ }
+ nextOpts.cookieJar = this.ckjar;
+ }
} catch (e) {
this.logErr(e);
}
@@ -527,23 +531,25 @@ function Env(name, opts) {
* :$.time('yyyyMMddHHmmssS')
* y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒
* 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符
- * @param {*} fmt 格式化参数
+ * @param {string} fmt 格式化参数
+ * @param {number} 可选: 根据指定时间戳返回格式化日期
*
*/
- time(fmt) {
+ time(fmt, ts = null) {
+ const date = ts ? new Date(ts) : new Date();
let o = {
- "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(),
+ "M+": date.getMonth() + 1,
+ "d+": date.getDate(),
+ "H+": date.getHours(),
+ "m+": date.getMinutes(),
+ "s+": date.getSeconds(),
+ "q+": Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds(),
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
- (new Date().getFullYear() + "").substr(4 - RegExp.$1.length)
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (let k in o)
if (new RegExp("(" + k + ")").test(fmt))
@@ -604,12 +610,14 @@ function Env(name, opts) {
$notify(title, subt, desc, toEnvOpts(opts));
}
}
- let logs = ["", "==============📣系统通知📣=============="];
- logs.push(title);
- subt ? logs.push(subt) : "";
- desc ? logs.push(desc) : "";
- console.log(logs.join("\n"));
- this.logs = this.logs.concat(logs);
+ if (!this.isMuteLog) {
+ let logs = ["", "==============📣系统通知📣=============="];
+ logs.push(title);
+ subt ? logs.push(subt) : "";
+ desc ? logs.push(desc) : "";
+ console.log(logs.join("\n"));
+ this.logs = this.logs.concat(logs);
+ }
}
log(...logs) {
diff --git a/check_in/weibo/weibotalk.js b/check_in/weibo/weibotalk.js
index f6edf93..6a62fd5 100644
--- a/check_in/weibo/weibotalk.js
+++ b/check_in/weibo/weibotalk.js
@@ -61,7 +61,7 @@
【All App MitM】
- hostname = api.weibo.cn
+ hostname = api.weibo.cn, mapi.weibo.com
*********/
@@ -286,11 +286,12 @@ function getnumber() {
"🚨获取超话页数出现错误或接口返回数据错误",
`⚠️原因:${obj.errmsg}\n👨💻作者提示:若为登陆保护等问题可尝试重新获取Cookie。`
);
+ $.log(JSON.stringify(obj));
$.pagenumber = 0;
resolve();
return;
}
- if (debugurl) console.log(obj);
+ if (debugurl) console.log(JSON.stringify(obj));
allnumber = obj.cardlistInfo.total;
console.log(
"当前已关注超话" +
@@ -301,13 +302,13 @@ function getnumber() {
resolve();
} else {
console.log("请将以下内容发送给作者\n");
- console.log(response);
+ console.log(JSON.stringify(response));
resolve();
}
});
} catch (e) {
console.log("请将以下内容发给作者\n");
- console.log(e);
+ console.log(JSON.stringify(e));
resolve();
}
setTimeout(() => {
@@ -348,6 +349,7 @@ function geturl(i) {
"🚨获取超话URL出现错误或接口返回数据错误",
`⚠️原因:${obj.errmsg}\n👨💻作者提示:若为登陆保护等问题可尝试重新获取Cookie。`
);
+ $.log(JSON.stringify(obj));
resolve();
return;
}
@@ -366,13 +368,13 @@ function geturl(i) {
resolve();
} else {
console.log("请将以下内容发送给作者\n");
- console.log(response);
+ console.log(JSON.stringify(response));
resolve();
}
});
} catch (e) {
console.log("请将以下内容发给作者\n");
- console.log(e);
+ console.log(JSON.stringify(e));
resolve();
}
setTimeout(() => {
@@ -409,6 +411,7 @@ function getSignStatus(i) {
"🚨获取签到状态出现错误或接口返回数据错误",
`⚠️原因:${obj.errmsg}\n👨💻作者提示:若为登陆保护等问题可尝试重新获取Cookie。`
);
+ $.log(JSON.stringify(obj));
resolve();
return;
}
@@ -438,13 +441,13 @@ function getSignStatus(i) {
resolve();
} else {
console.log("请将以下内容发送给作者\n");
- console.log(response);
+ console.log(JSON.stringify(response));
resolve();
}
});
} catch (e) {
console.log("请将以下内容发给作者\n");
- console.log(e);
+ console.log(JSON.stringify(e));
resolve();
}
setTimeout(() => {
@@ -485,6 +488,7 @@ function getid(page) {
"🚨获取超话ID出现错误或接口返回数据错误",
`⚠️原因:${obj.errmsg}\n👨💻作者提示:若为登陆保护等问题可尝试重新获取Cookie。`
);
+ $.log(JSON.stringify(obj));
resolve();
return;
}
@@ -503,13 +507,13 @@ function getid(page) {
resolve();
} else {
console.log("请将以下内容发送给作者\n");
- console.log(response);
+ console.log(JSON.stringify(response));
resolve();
}
});
} catch (e) {
console.log("请将以下内容发给作者\n");
- console.log(e);
+ console.log(JSON.stringify(e));
resolve();
}
setTimeout(() => {
@@ -540,7 +544,7 @@ function checkin(id, name, isSign = false) {
if (error) {
throw new Error(error);
}
- if (debugcheckin) console.log(response);
+ if (debugcheckin) console.log(JSON.stringify(response));
if (response.statusCode == 418) {
$.failNum += 1;
$.message.push(`【${idname}】:太频繁啦,请稍后再试`);
@@ -567,12 +571,13 @@ function checkin(id, name, isSign = false) {
"🚨签到出现错误或接口返回数据错误",
`⚠️原因:${obj.errmsg}\n👨💻作者提示:若为登陆保护等问题可尝试重新获取Cookie。`
);
+ $.log(JSON.stringify(obj));
resolve();
return;
}
- if (debugcheckin) console.log(obj);
+ if (debugcheckin) console.log(JSON.stringify(obj));
var result = obj.result;
- if (debugcheckin) console.log(result);
+ if (debugcheckin) console.log(JSON.stringify(result));
if (result == 1 || result == 382004) {
$.successNum += 1;
} else {
@@ -602,24 +607,24 @@ function checkin(id, name, isSign = false) {
console.log(
`【${idname}】执行签到:签到失败,请重新签到获取Cookie⚠️\n${response}`
);
- if (debugcheckin) console.log(response);
+ if (debugcheckin) console.log(JSON.stringify(response));
} else {
$.message.push(`【${idname}】:未知错误⚠️`);
console.log(`【${idname}】执行签到:未知错误⚠️`);
console.log("请将以下内容发送给作者\n");
- console.log(response);
+ console.log(JSON.stringify(response));
}
resolve();
} else {
$.failNum += 1;
console.log("请将以下内容发送给作者\n");
- console.log(response);
+ console.log(JSON.stringify(response));
resolve();
}
});
} catch (e) {
console.log("请将以下内容发给作者\n");
- console.log(e);
+ console.log(JSON.stringify(e));
resolve();
}
setTimeout(() => {
@@ -946,11 +951,15 @@ function Env(name, opts) {
this.got(opts)
.on("redirect", (resp, nextOpts) => {
try {
- const ck = resp.headers["set-cookie"]
- .map(this.cktough.Cookie.parse)
- .toString();
- this.ckjar.setCookieSync(ck, null);
- nextOpts.cookieJar = this.ckjar;
+ if (resp.headers["set-cookie"]) {
+ const ck = resp.headers["set-cookie"]
+ .map(this.cktough.Cookie.parse)
+ .toString();
+ if (ck) {
+ this.ckjar.setCookieSync(ck, null);
+ }
+ nextOpts.cookieJar = this.ckjar;
+ }
} catch (e) {
this.logErr(e);
}
@@ -1021,23 +1030,25 @@ function Env(name, opts) {
* :$.time('yyyyMMddHHmmssS')
* y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒
* 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符
- * @param {*} fmt 格式化参数
+ * @param {string} fmt 格式化参数
+ * @param {number} 可选: 根据指定时间戳返回格式化日期
*
*/
- time(fmt) {
+ time(fmt, ts = null) {
+ const date = ts ? new Date(ts) : new Date();
let o = {
- "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(),
+ "M+": date.getMonth() + 1,
+ "d+": date.getDate(),
+ "H+": date.getHours(),
+ "m+": date.getMinutes(),
+ "s+": date.getSeconds(),
+ "q+": Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds(),
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
- (new Date().getFullYear() + "").substr(4 - RegExp.$1.length)
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (let k in o)
if (new RegExp("(" + k + ")").test(fmt))
@@ -1098,12 +1109,14 @@ function Env(name, opts) {
$notify(title, subt, desc, toEnvOpts(opts));
}
}
- let logs = ["", "==============📣系统通知📣=============="];
- logs.push(title);
- subt ? logs.push(subt) : "";
- desc ? logs.push(desc) : "";
- console.log(logs.join("\n"));
- this.logs = this.logs.concat(logs);
+ if (!this.isMuteLog) {
+ let logs = ["", "==============📣系统通知📣=============="];
+ logs.push(title);
+ subt ? logs.push(subt) : "";
+ desc ? logs.push(desc) : "";
+ console.log(logs.join("\n"));
+ this.logs = this.logs.concat(logs);
+ }
}
log(...logs) {
diff --git a/evilbutcher.boxjs.json b/evilbutcher.boxjs.json
index 84b7ff8..1281af5 100644
--- a/evilbutcher.boxjs.json
+++ b/evilbutcher.boxjs.json
@@ -12,7 +12,8 @@
"点此直达【脚本地址】",
"Cookie获取指南",
"",
- "Cookie获取分为三步,请仔细查看视频中弹出的三个通知。如果下面应用设置第四个,检查签到开关打开时,第三个Cookie必须获取;关闭时获取前两个即可运行。"
+ "Cookie获取分为三步,请仔细查看视频中弹出的三个通知。如果下面应用设置第四个,检查签到开关打开时,第三个Cookie必须获取;关闭时获取前两个即可运行。",
+ "注意!如果超话数量不足20个无法触发视频流程中第三个重写,请关闭检查签到状态开关运行即可。"
],
"keys": [
"evil_tokenurl",
@@ -49,7 +50,7 @@
"name": "检查签到状态",
"val": false,
"type": "boolean",
- "desc": "打开则先检查签到状态,再签到;否则将直接签到"
+ "desc": "打开则先检查签到状态,再签到(超话数量不足20个请关闭)"
}
],
"author": "@toulanboy, @evilbutcher",
@@ -77,7 +78,10 @@
"只有关闭关键词匹配才会通知最新内容,否则没匹配关键词不会通知。 ",
"Quantumult X用户:B站、豆瓣榜单独立推送时可显示封面;关闭附带跳转链接点击通知也可跳转。"
],
- "keys": ["evil_saveditem", "evil_savedtime"],
+ "keys": [
+ "evil_saveditem",
+ "evil_savedtime"
+ ],
"settings": [
{
"id": "evil_wb_keyword",
@@ -519,7 +523,11 @@
"此版本为尝试用Cookie签到,针对有登陆验证或跳转的机场。",
"可利用BoxJs会话切换功能,一次保存一个机场信息,切换会话签到。"
],
- "keys": ["evil_checkincktitle", "evil_checkinurl", "evil_checkincookie"],
+ "keys": [
+ "evil_checkincktitle",
+ "evil_checkinurl",
+ "evil_checkincookie"
+ ],
"settings": [
{
"id": "evil_checkincktitle",
@@ -566,7 +574,10 @@
"注册地址:https://github.com/glados-network/GLaDOS",
"邀请码:3JRG4-KSGZJ-8QPXF-8PPOO"
],
- "keys": ["evil_gladoscookie"],
+ "keys": [
+ "evil_gladoscookie",
+ "evil_galdosauthorization"
+ ],
"author": "@evilbutcher",
"repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/glados",
"icons": [
@@ -627,7 +638,9 @@
"点此直达【脚本地址】",
"首先前往NASA申请一个API,申请流程非常简单,把得到的API填入脚本即可"
],
- "keys": ["@NASA.nasaapi"],
+ "keys": [
+ "@NASA.nasaapi"
+ ],
"settings": [
{
"id": "@NASA.translate",
@@ -659,9 +672,11 @@
"id": "idaily",
"name": "iDaily",
"descs_html": [
- "点此直达【脚本地址】"
+ "点此直达【脚本地址】"
+ ],
+ "keys": [
+ "@iDaily.random"
],
- "keys": ["@iDaily.random"],
"settings": [
{
"id": "@iDaily.random",
@@ -679,6 +694,128 @@
],
"script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/idaily/idaily.js"
},
+ {
+ "id": "jiumu",
+ "name": "九木杂物社",
+ "descs_html": [
+ "点此直达【脚本地址】"
+ ],
+ "keys": [
+ "@Jiumu.evil_jiumuSignStr",
+ "@Jiumu.evil_jiumuReferer",
+ "@Jiumu.evil_jiumuVip",
+ "@Jiumu.evil_jiumuEncrypt",
+ "@Jiumu.evil_jiumuBody"
+ ],
+ "author": "@evilbutcher",
+ "repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/jiumu",
+ "icons": [
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/jiumu_tran.png",
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/jiumu.png"
+ ],
+ "script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js"
+ },
+ {
+ "id": "wechatsubs",
+ "name": "公众号监控",
+ "descs_html": [
+ "点此直达【脚本地址】"
+ ],
+ "keys": [
+ "@Wechatsubs.wechatkeyword1",
+ "@Wechatsubs.wechatkeyword2",
+ "@Wechatsubs.wechatsavedtime",
+ "@Wechatsubs.wechatrefreshtime",
+ "@Wechatsubs.wechatsaveditem"
+ ],
+ "settings": [
+ {
+ "id": "@Wechatsubs.wechatkeyword1",
+ "name": "关键词-1",
+ "val": "",
+ "placeholder": "",
+ "type": "textarea",
+ "autoGrow": true,
+ "rows": 2,
+ "desc": "请填入要监控的第一组关键词,多个词用中文逗号“,”分隔。"
+ },
+ {
+ "id": "@Wechatsubs.wechatkeyword2",
+ "name": "关键词-2",
+ "val": "",
+ "placeholder": "",
+ "type": "textarea",
+ "autoGrow": true,
+ "rows": 2,
+ "desc": "请填入要监控的第二组关键词,多个词用中文逗号“,”分隔。"
+ },
+ {
+ "id": "@Wechatsubs.wechatrefreshtime",
+ "name": "刷新时间(时)",
+ "val": 6,
+ "type": "number",
+ "desc": "重复内容默认在6小时内不再通知,之后清空,可自行修改"
+ }
+ ],
+ "author": "@evilbutcher",
+ "repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/wechatsubs",
+ "icons": [
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/wechat_tran.png",
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/wechat.png"
+ ],
+ "script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/wechatsubs.js"
+ },
+ {
+ "id": "klcwapp",
+ "name": "酷乐潮玩App",
+ "descs_html": [
+ "点此直达【脚本地址】"
+ ],
+ "keys": [
+ "@klcwapp.evil_klcwappBody"
+ ],
+ "settings": [
+ {
+ "id": "@klcwapp.evil_klcwappBody",
+ "name": "Cookie",
+ "val": "",
+ "placeholder": "",
+ "type": "textarea",
+ "autoGrow": true,
+ "rows": 2,
+ "desc": "可自行抓包填入。"
+ }
+ ],
+ "author": "@evilbutcher",
+ "repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/klcw",
+ "icons": [
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/klcw_tran.png",
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/klcw.png"
+ ],
+ "script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js"
+ },
+ {
+ "id": "klcw",
+ "name": "酷乐潮玩小程序",
+ "descs_html": [
+ "点此直达【脚本地址】"
+ ],
+ "keys": [
+ "@klcw.evil_klcwid",
+ "@klcw.evil_klcwSignStr",
+ "@klcw.evil_klcwReferer",
+ "@klcw.evil_klcwVip",
+ "@klcw.evil_klcwEncrypt",
+ "@klcw.evil_klcwBody"
+ ],
+ "author": "@evilbutcher",
+ "repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/klcw",
+ "icons": [
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/klcw_tran.png",
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/klcw.png"
+ ],
+ "script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js"
+ },
{
"id": "funboat",
"name": "Funboat",
@@ -700,6 +837,211 @@
"https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/funko.png"
],
"script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js"
+ },
+ {
+ "id": "timepop",
+ "name": "Timepop",
+ "descs_html": [
+ "点此直达【脚本地址】",
+ "微信小程序搜索 Timepop,按照脚本提示获取Cookie。",
+ "⚠️其他基于有赞的小程序也可能触发获取Cookie,请获取完后及时禁用获取Cookie重写/脚本。"
+ ],
+ "keys": [
+ "evil_timepopurl",
+ "evil_timepopcookie",
+ "evil_timepopstatusurl",
+ "evil_timepopstatuscookie"
+ ],
+ "author": "@evilbutcher",
+ "repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/timepop",
+ "icons": [
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/timepop_tran.png",
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/timepop.png"
+ ],
+ "script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js"
+ },
+ {
+ "id": "sydwzp",
+ "name": "事业单位招聘监控",
+ "descs_html": [
+ "点此直达【脚本地址】"
+ ],
+ "keys": [
+ "@sydwzp.sydwarea",
+ "@sydwzp.sydwsavedtime",
+ "@sydwzp.sydwrefreshtime",
+ "@sydwzp.sydwsaveditem",
+ "@sydwzp.sydwdetailsetting"
+ ],
+ "settings": [
+ {
+ "id": "@sydwzp.sydwarea",
+ "name": "地区",
+ "val": "",
+ "placeholder": "",
+ "type": "textarea",
+ "autoGrow": true,
+ "rows": 2,
+ "desc": "请填入要监控的地区。"
+ },
+ {
+ "id": "@sydwzp.sydwdetailsetting",
+ "name": "获取附件链接",
+ "val": true,
+ "type": "boolean",
+ "desc": "是否获取附件链接"
+ },
+ {
+ "id": "@sydwzp.sydwrefreshtime",
+ "name": "刷新时间(时)",
+ "val": 6,
+ "type": "number",
+ "desc": "重复内容默认在6小时内不再通知,之后清空,可自行修改"
+ }
+ ],
+ "author": "@evilbutcher",
+ "repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/wechatsubs",
+ "icons": [
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/sydw_tran.png",
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/sydw.png"
+ ],
+ "script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/sydwzp.js"
+ },
+ {
+ "id": "gxrcw",
+ "name": "高校人才网招聘监控",
+ "descs_html": [
+ "点此直达【脚本地址】"
+ ],
+ "keys": [
+ "@gxrcw.gxrcwsavedtime",
+ "@gxrcw.gxrcwrefreshtime",
+ "@gxrcw.gxrcwsaveditem"
+ ],
+ "settings": [
+ {
+ "id": "@gxrcw.gxrcwrefreshtime",
+ "name": "刷新时间(时)",
+ "val": 6,
+ "type": "number",
+ "desc": "重复内容默认在6小时内不再通知,之后清空,可自行修改"
+ }
+ ],
+ "author": "@evilbutcher",
+ "repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/wechatsubs",
+ "icons": [
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/gxrcw_tran.png",
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/gxrcw.png"
+ ],
+ "script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/gxrcw.js"
+ },
+ {
+ "id": "ssq",
+ "name": "彩票结果查询",
+ "descs_html": [
+ "点此直达【脚本地址】"
+ ],
+ "settings": [
+ {
+ "id": "@ssq.ssq",
+ "name": "双色球",
+ "val": true,
+ "type": "boolean",
+ "desc": "打开即可查询双色球开奖结果"
+ },
+ {
+ "id": "@ssq.dlt",
+ "name": "大乐透",
+ "val": true,
+ "type": "boolean",
+ "desc": "打开即可查询大乐透开奖结果"
+ },
+ {
+ "id": "@ssq.3d",
+ "name": "福彩3D",
+ "val": true,
+ "type": "boolean",
+ "desc": "打开即可查询福彩3D开奖结果"
+ },
+ {
+ "id": "@ssq.qlc",
+ "name": "七乐彩",
+ "val": true,
+ "type": "boolean",
+ "desc": "打开即可查询七乐彩开奖结果"
+ },
+ {
+ "id": "@ssq.new",
+ "name": "仅查询当日开奖",
+ "val": true,
+ "type": "boolean",
+ "desc": "打开则会只查询今日开奖的彩票"
+ }
+ ],
+ "author": "@evilbutcher, @Phantom",
+ "repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/ssq",
+ "icons": [
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/ssq_tran.png",
+ "https://raw.githubusercontent.com/58xinian/icon/master/Two_color_ball.png"
+ ],
+ "script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/ssq/ssq.js"
+ },
+ {
+ "id": "hzh",
+ "name": "华住会",
+ "descs_html": [
+ "点此直达【脚本地址】"
+ ],
+ "keys": [
+ "@hzh.evil_hzhCookie",
+ "@hzh.evil_hzhUserToken"
+ ],
+ "author": "@evilbutcher",
+ "repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/hzh",
+ "icons": [
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/hzh_tran.png",
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/hzh.png"
+ ],
+ "script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js"
+ },
+ {
+ "id": "taobao",
+ "name": "淘宝监控",
+ "descs_html": [
+ "点此直达【脚本地址】"
+ ],
+ "keys": [
+ "@taobao.evil_tbcookie",
+ "@taobao.evil_tburl",
+ "@taobao.evil_tbrecord"
+ ],
+ "author": "@evilbutcher",
+ "repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/taobao",
+ "icons": [
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/tb_tran.png",
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/tb.png"
+ ],
+ "script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js"
+ },
+ {
+ "id": "taobao-name",
+ "name": "淘宝监控-标题版",
+ "descs_html": [
+ "点此直达【脚本地址】"
+ ],
+ "keys": [
+ "@taobao-name.evil_tbnamecookie",
+ "@taobao-name.evil_tbnameurl",
+ "@taobao-name.evil_tbnamerecord",
+ "@taobao-name.evil_tbnameprice"
+ ],
+ "author": "@evilbutcher",
+ "repo": "https://github.com/evilbutcher/Quantumult_X/tree/master/check_in/taobao",
+ "icons": [
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/tb_tran.png",
+ "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/tb.png"
+ ],
+ "script": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js"
}
]
}
\ No newline at end of file
diff --git a/picture/gxrcw.png b/picture/gxrcw.png
new file mode 100644
index 0000000..2ca2174
Binary files /dev/null and b/picture/gxrcw.png differ
diff --git a/picture/gxrcw_tran.png b/picture/gxrcw_tran.png
new file mode 100644
index 0000000..53647e5
Binary files /dev/null and b/picture/gxrcw_tran.png differ
diff --git a/picture/hzh.png b/picture/hzh.png
new file mode 100644
index 0000000..31a9797
Binary files /dev/null and b/picture/hzh.png differ
diff --git a/picture/hzh_tran.png b/picture/hzh_tran.png
new file mode 100644
index 0000000..e9f2c5c
Binary files /dev/null and b/picture/hzh_tran.png differ
diff --git a/picture/jiumu.png b/picture/jiumu.png
new file mode 100644
index 0000000..7e752c3
Binary files /dev/null and b/picture/jiumu.png differ
diff --git a/picture/jiumu_tran.png b/picture/jiumu_tran.png
new file mode 100644
index 0000000..e8ef7ac
Binary files /dev/null and b/picture/jiumu_tran.png differ
diff --git a/picture/klcw.png b/picture/klcw.png
new file mode 100644
index 0000000..0bc9aba
Binary files /dev/null and b/picture/klcw.png differ
diff --git a/picture/klcw_tran.png b/picture/klcw_tran.png
new file mode 100644
index 0000000..c9bb7d2
Binary files /dev/null and b/picture/klcw_tran.png differ
diff --git a/picture/photo.jpeg b/picture/photo.jpeg
new file mode 100644
index 0000000..328f5c8
Binary files /dev/null and b/picture/photo.jpeg differ
diff --git a/picture/ssq.png b/picture/ssq.png
new file mode 100644
index 0000000..cd0fa94
Binary files /dev/null and b/picture/ssq.png differ
diff --git a/picture/ssq_tran.png b/picture/ssq_tran.png
new file mode 100644
index 0000000..761437a
Binary files /dev/null and b/picture/ssq_tran.png differ
diff --git a/picture/sydw.png b/picture/sydw.png
new file mode 100644
index 0000000..e950576
Binary files /dev/null and b/picture/sydw.png differ
diff --git a/picture/sydw_tran.png b/picture/sydw_tran.png
new file mode 100644
index 0000000..8c29644
Binary files /dev/null and b/picture/sydw_tran.png differ
diff --git a/picture/tb.png b/picture/tb.png
new file mode 100644
index 0000000..7c12a0f
Binary files /dev/null and b/picture/tb.png differ
diff --git a/picture/tb_tran.png b/picture/tb_tran.png
new file mode 100644
index 0000000..61647c6
Binary files /dev/null and b/picture/tb_tran.png differ
diff --git a/picture/timepop.png b/picture/timepop.png
new file mode 100644
index 0000000..e5a04ce
Binary files /dev/null and b/picture/timepop.png differ
diff --git a/picture/timepop_tran.png b/picture/timepop_tran.png
new file mode 100644
index 0000000..fcf11f7
Binary files /dev/null and b/picture/timepop_tran.png differ
diff --git a/picture/wechat.png b/picture/wechat.png
new file mode 100644
index 0000000..4cf58bb
Binary files /dev/null and b/picture/wechat.png differ
diff --git a/picture/wechat_tran.png b/picture/wechat_tran.png
new file mode 100644
index 0000000..dafc63b
Binary files /dev/null and b/picture/wechat_tran.png differ
diff --git a/profiles/Loon/Loon.scripts.conf b/profiles/Loon/Loon.scripts.conf
new file mode 100644
index 0000000..ce70788
--- /dev/null
+++ b/profiles/Loon/Loon.scripts.conf
@@ -0,0 +1,38 @@
+# evilbutcher 脚本集合
+
+hostname = h5.youzan.com, glados.rocks, api.weibo.cn, mapi.weibo.com, wxavip-up.ezrpro.cn, wxavip-tp.ezrpro.cn, app.klcw.net.cn, hweb-mbf.huazhu.com, h5api.m.taobao.com
+
+
+http-request ^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx9b5caf9d1669dc96, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js, tag=Funboat获取签到Cookie
+http-request ^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx9b5caf9d1669dc96, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js, tag=Funboat获取积分Cookie
+^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx4a1af22a88a99386, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js, tag=Timepop获取签到Cookie
+^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx4a1af22a88a99386, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js, tag=Timepop获取积分Cookie
+http-request https:\/\/glados\.rocks\/api\/user\/checkin, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js, tag=GLaDOS获取Cookie
+http-request ^https?://m?api\.weibo\.c(n|om)\/2\/(cardlist|page\/button|page) script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/weibo/weibotalk.cookie.js,requires-body=false, tag=微博超话获取Cookie
+http-request https:\/\/wxavip\-up\.ezrpro\.cn\/Vip\/SignIn\/SignIn tag=九木杂物社获取Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js, requires-body=true
+http-request https:\/\/wxavip\-tp\.ezrpro\.cn\/Vip\/SignIn\/SignIn tag=酷乐潮玩小程序获取签到Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js, requires-body=true
+http-request https:\/\/app\.klcw\.net\.cn\/omp\_cmanage\/mallgateway tag=酷乐潮玩App获取Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js, requires-body=true
+http-request https:\/\/hweb-mbf\.huazhu\.com\/api\/signIn tag=华住会获取签到Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js, requires-body=false
+http-request https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdetail tag=淘宝监控获取Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js, requires-body=false
+http-request https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdesc tag=淘宝监控获取Cookie, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js, requires-body=false
+
+cron "0 6 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/nasa/nasapic.js, tag=NASA每日一图
+cron "0 6 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/idaily/idaily.js, tag=iDaily每日环球视野
+cron "30 7-22 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/appstore/AppMonitor.js, tag=App价格监控
+cron "30 0 8-22/2 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hotsearch/hot.js, tag=热门监控
+cron "45 3 8 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/weibo/weibotalk.js, tag=微博超话
+cron "25 4 8 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js, tag=GLaDOS签到
+cron "45 4 8 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/checkin_env.js, tag=机场签到
+cron "0 5 8 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/checkincookie_env.js, tag=机场签到Cookie版
+cron "0 4 8 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js, tag=Funboat签到
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js, tag=Timepop签到
+cron "25 4 8 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js, tag=九木杂物社
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js, tag=酷乐潮玩小程序
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js, tag=酷乐潮玩App
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/wechatsubs.js, tag=公众号监控
+cron "5 * * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/sydwzp.js, tag=事业单位招聘监控
+cron "5 * * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/gxrcw.js, tag=高校人才网招聘监控
+cron "0 30 21 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/ssq/ssq.js, tag=彩票监控
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js, tag=华住会
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/taobao/tb-name.js, tag=淘宝监控-标题版
+cron "5 0 * * *" script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/taobao/tb.js, tag=淘宝监控
\ No newline at end of file
diff --git a/profiles/QuantumultX/QuantumultX.rewrite.conf b/profiles/QuantumultX/QuantumultX.rewrite.conf
new file mode 100644
index 0000000..1b4c65b
--- /dev/null
+++ b/profiles/QuantumultX/QuantumultX.rewrite.conf
@@ -0,0 +1,47 @@
+# @evilbutcher 脚本集合
+
+hostname = h5.youzan.com, glados.rocks, api.weibo.cn, api.weibo.com, mapi.weibo.com, 10086.online-cmcc.cn, 121.43.19.216, sapi.beingfine.cn, mobilebj.cn, api.gotokeep.com, wxavip-up.ezrpro.cn, wxavip-tp.ezrpro.cn, app.klcw.net.cn, hweb-mbf.huazhu.com, h5api.m.taobao.com
+
+#淘宝监控获取Cookie
+https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdesc url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js
+https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdetail url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js
+
+#Timepop获取Cookie
+^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx4a1af22a88a99386 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx4a1af22a88a99386 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+
+#华住会获取签到Cookie
+https:\/\/hweb-mbf\.huazhu\.com\/api\/signIn url script-request-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js
+
+#酷乐潮玩小程序获取签到Cookie
+https:\/\/wxavip\-tp\.ezrpro\.cn\/Vip\/SignIn\/SignIn url script-request-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js
+#酷乐潮玩App获取Cookie
+https:\/\/app\.klcw\.net\.cn\/omp\_cmanage\/mallgateway url script-request-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js
+
+#九木杂物社获取Cookie
+https:\/\/wxavip\-up\.ezrpro\.cn\/Vip\/SignIn\/SignIn url script-request-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js
+
+#Funboat获取Cookie
+^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx9b5caf9d1669dc96 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx9b5caf9d1669dc96 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+
+#GLaDOS获取Cookie
+https:\/\/glados\.rocks\/api\/user\/checkin url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
+
+#微博超话获取Cookie
+^https?://m?api\.weibo\.c(n|om)\/2\/(cardlist|page\/button|page) url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/weibo/weibotalk.cookie.js
+
+#10086去开屏广告
+https:\/\/10086\.online\-cmcc\.cn\:20010\/gfms\/front\/hn\/busi3\!getAdvert url script-response-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/remove_ad/10086.js
+
+#不背单词解锁
+^https:\/\/sapi\.beingfine\.cn\/v3\/report\/launch\/ url script-response-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/remove_ad/bbdc.js
+
+#北京移动去开屏广告
+https:\/\/mobilebj\.cn\/app\/appBasicInfo? url script-response-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/remove_ad/bjyd.js
+
+#微博去广告
+https:\/\/api\.weibo\.com\/oauth2\/getaid url reject
+
+#keep去开屏广告
+https:\/\/api\.gotokeep\.com\/ads\/v1\/ads\?spotIds url reject
diff --git a/profiles/QuantumultX/QuantumultX.task.json b/profiles/QuantumultX/QuantumultX.task.json
new file mode 100644
index 0000000..7fd3398
--- /dev/null
+++ b/profiles/QuantumultX/QuantumultX.task.json
@@ -0,0 +1,56 @@
+{
+ "name": "@evilbutcher 脚本集合",
+ "description": "Quantumult X Task Galllery by evilbutcher",
+ "task": [
+ "0 0 6 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/nasa/nasapic.js, tag=NASA每日一图, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/nasa.png, enabled=true",
+ "0 0 6 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/idaily/idaily.js, tag=iDaily每日环球视野, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/idaily.png, enabled=true",
+ "30 7-22 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/appstore/AppMonitor.js, tag=App价格监控, img-url=https://raw.githubusercontent.com/Orz-3/mini/master/Color/appstore.png, enabled=true",
+ "30 0 8-22/2 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hotsearch/hot.js, tag=热门监控, img-url=https://raw.githubusercontent.com/58xinian/icon/master/hot.png, enabled=true",
+ {
+ "config": "45 3 8 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/weibo/weibotalk.js, tag=微博超话, img-url=https://raw.githubusercontent.com/Orz-3/mini/master/Color/weibo.png, enabled=true",
+ "addons": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/profiles/QuantumultX/addons/weibo.conf, tag = 微博超话获取Cookie"
+ },
+ {
+ "config": "25 4 8 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js, tag=GLaDOS, img-url=https://raw.githubusercontent.com/58xinian/icon/master/glados1.png, enabled=true",
+ "addons": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/profiles/QuantumultX/addons/glados.conf, tag = GLaDOS获取Cookie"
+ },
+ "45 4 8 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/checkin_env.js, tag=机场签到, img-url=https://raw.githubusercontent.com/Orz-3/mini/master/Color/airport.png, enabled=true",
+ "0 5 8 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master//check_in/glados/checkincookie_env.js, tag=机场签到Cookie版, img-url=https://raw.githubusercontent.com/58xinian/icon/master/glados.png, enabled=true",
+ {
+ "config": "0 4 8 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js, tag=Funboat, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/funko.png, enabled=true",
+ "addons": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/profiles/QuantumultX/addons/funboat.conf, tag = Funboat获取Cookie"
+ },
+ {
+ "config": "0 4 8 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js, tag=Timepop, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/timepop.png, enabled=true",
+ "addons": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/profiles/QuantumultX/addons/timepop.conf, tag = Timepop获取Cookie"
+ },
+ {
+ "config": "25 4 8 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js, tag=九木杂物社, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/jiumu.png, enabled=true",
+ "addons": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/profiles/QuantumultX/addons/jiumu.conf, tag = 九木杂物社获取Cookie"
+ },
+ {
+ "config": "30 4 8 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js, tag=酷乐潮玩小程序, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/klcw.png",
+ "addons": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/profiles/QuantumultX/addons/klcw.conf, tag = 酷乐潮玩小程序获取Cookie"
+ },
+ {
+ "config": "5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js, tag=酷乐潮玩App, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/klcw.png",
+ "addons": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/profiles/QuantumultX/addons/klcw-app.conf, tag = 酷乐潮玩App获取Cookie"
+ },
+ "0 5 8 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/wechatsubs.js, tag=公众号监控, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/wechat.png",
+ "0 5 * * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/sydwzp.js, tag=事业单位招聘监控, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/sydw.png",
+ "0 5 * * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/gxrcw.js, tag=高校人才网招聘监控, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/gxrcw.png",
+ "0 30 21 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/ssq/ssq.js, tag=彩票监控, img-url=https://raw.githubusercontent.com/58xinian/icon/master/Two_color_ball.png",
+ {
+ "config": "5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js, tag=华住会, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/hzh.png",
+ "addons": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/profiles/QuantumultX/addons/hzh.conf, tag = 华住会获取签到Cookie"
+ },
+ {
+ "config": "5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js, tag=淘宝监控-标题版, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/tb.png",
+ "addons": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/profiles/QuantumultX/addons/taobao.conf, tag = 淘宝监控获取Cookie"
+ },
+ {
+ "config": "5 0 * * * https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js, tag=淘宝监控, img-url=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/picture/tb.png",
+ "addons": "https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/profiles/QuantumultX/addons/taobao.conf, tag = 淘宝监控获取Cookie"
+ }
+ ]
+}
diff --git a/profiles/QuantumultX/addons/funboat.conf b/profiles/QuantumultX/addons/funboat.conf
new file mode 100644
index 0000000..62ae86c
--- /dev/null
+++ b/profiles/QuantumultX/addons/funboat.conf
@@ -0,0 +1,4 @@
+# Funboat获取Cookie
+hostname = h5.youzan.com
+^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx9b5caf9d1669dc96 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx9b5caf9d1669dc96 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
\ No newline at end of file
diff --git a/profiles/QuantumultX/addons/glados.conf b/profiles/QuantumultX/addons/glados.conf
new file mode 100644
index 0000000..a23c984
--- /dev/null
+++ b/profiles/QuantumultX/addons/glados.conf
@@ -0,0 +1,3 @@
+# GLaDOS获取Cookie
+hostname = glados.rocks
+https:\/\/glados\.rocks\/api\/user\/checkin url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
\ No newline at end of file
diff --git a/profiles/QuantumultX/addons/hzh.conf b/profiles/QuantumultX/addons/hzh.conf
new file mode 100644
index 0000000..bf011c6
--- /dev/null
+++ b/profiles/QuantumultX/addons/hzh.conf
@@ -0,0 +1,2 @@
+hostname = hweb-mbf.huazhu.com
+https:\/\/hweb-mbf\.huazhu\.com\/api\/signIn url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js
\ No newline at end of file
diff --git a/profiles/QuantumultX/addons/jiumu.conf b/profiles/QuantumultX/addons/jiumu.conf
new file mode 100644
index 0000000..157927c
--- /dev/null
+++ b/profiles/QuantumultX/addons/jiumu.conf
@@ -0,0 +1,3 @@
+# 九木杂物社获取Cookie
+hostname = wxavip-up.ezrpro.cn
+https:\/\/wxavip\-up\.ezrpro\.cn\/Vip\/SignIn\/SignIn url script-request-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js
\ No newline at end of file
diff --git a/profiles/QuantumultX/addons/klcw-app.conf b/profiles/QuantumultX/addons/klcw-app.conf
new file mode 100644
index 0000000..0178875
--- /dev/null
+++ b/profiles/QuantumultX/addons/klcw-app.conf
@@ -0,0 +1,3 @@
+# 酷乐潮玩App获取Cookie
+hostname = app.klcw.net.cn
+https:\/\/app\.klcw\.net\.cn\/omp\_cmanage\/mallgateway url script-request-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js
\ No newline at end of file
diff --git a/profiles/QuantumultX/addons/klcw.conf b/profiles/QuantumultX/addons/klcw.conf
new file mode 100644
index 0000000..5dd78ab
--- /dev/null
+++ b/profiles/QuantumultX/addons/klcw.conf
@@ -0,0 +1,3 @@
+# 酷乐潮玩小程序获取Cookie
+hostname = wxavip-tp.ezrpro.cn
+https:\/\/wxavip\-tp\.ezrpro\.cn\/Vip\/SignIn\/SignIn url script-request-body https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js
\ No newline at end of file
diff --git a/profiles/QuantumultX/addons/taobao.conf b/profiles/QuantumultX/addons/taobao.conf
new file mode 100644
index 0000000..7f55764
--- /dev/null
+++ b/profiles/QuantumultX/addons/taobao.conf
@@ -0,0 +1,4 @@
+# 淘宝监控获取Cookie
+hostname = h5api.m.taobao.com
+https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdesc url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js
+https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdetail url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js
\ No newline at end of file
diff --git a/profiles/QuantumultX/addons/timepop.conf b/profiles/QuantumultX/addons/timepop.conf
new file mode 100644
index 0000000..41f9433
--- /dev/null
+++ b/profiles/QuantumultX/addons/timepop.conf
@@ -0,0 +1,4 @@
+# Timepop获取Cookie
+hostname = h5.youzan.com
+^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx4a1af22a88a99386 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx4a1af22a88a99386 url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
\ No newline at end of file
diff --git a/profiles/QuantumultX/addons/weibo.conf b/profiles/QuantumultX/addons/weibo.conf
new file mode 100644
index 0000000..495d7b4
--- /dev/null
+++ b/profiles/QuantumultX/addons/weibo.conf
@@ -0,0 +1,3 @@
+# 微博超话获取Cookie
+hostname = api.weibo.cn, mapi.weibo.com
+^https?://m?api\.weibo\.c(n|om)\/2\/(cardlist|page\/button) url script-request-header https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/weibo/weibotalk.cookie.js
\ No newline at end of file
diff --git a/profiles/QuantumultX/evilbuther.list b/profiles/QuantumultX/evilbuther.list
new file mode 100644
index 0000000..3688678
--- /dev/null
+++ b/profiles/QuantumultX/evilbuther.list
@@ -0,0 +1,398 @@
+# > 知乎
+# 知乎去广告,以下规则请放置在filter_local最顶部
+IP-CIDR,118.89.204.198/32,REJECT
+IP6-CIDR,2402:4e00:1200:ed00:0:9089:6dac:96b6/128,REJECT
+HOST,118.89.204.198,REJECT
+# 知乎去广告,以下规则的位置越前方越好
+HOST,appcloud2.in.zhihu.com,REJECT
+HOST,mqtt.zhihu.com,reject
+HOST,sugar.zhihu.com,reject
+USER-AGENT,AVOS*,REJECT
+
+# 小米
+HOST,data.mistat.xiaomi.com, reject
+HOST,tracking.intl.miui.com, reject
+
+# QQ音乐广告
+HOST,tmeadcomm.y.qq.com, reject
+HOST,ad.tencentmusic.com, reject
+HOST,adstats.tencentmusic.com, reject
+HOST,tmead.y.qq.com, reject
+HOST-SUFFIX,rqd.qq.com, reject
+HOST-SUFFIX,wup.imtt.qq.com, reject
+HOST-SUFFIX,gdt.qq.com, reject
+HOST-SUFFIX,android.rqd.qq.com, reject
+HOST-SUFFIX,e.qq.com, reject
+HOST-SUFFIX,beacon.qq.com, reject
+HOST-SUFFIX,v.gdt.qq.com, reject
+
+# 高德
+HOST-SUFFIX,adiu.amap.com,REJECT
+HOST,aboard.apilocate.amap.com,REJECT
+HOST,apiinit.amap.com,REJECT
+HOST,icloud-amap.com,REJECT
+HOST,logs.amap.com,REJECT
+HOST-SUFFIX,dualstack-logs.amap.com,REJECT
+HOST-SUFFIX,logs.amap.com,REJECT
+HOST-SUFFIX,optimus-ads.amap.com,REJECT
+HOST-SUFFIX,page.amap.com,REJECT
+HOST,optimus-ads.amap.com, reject
+HOST,optimus-ads.amap.com.w.alikunlun.com, reject
+HOST-SUFFIX, shouji.sougou.com, reject
+HOST, u51.me, reject
+HOST-SUFFIX, u51.me, reject
+
+# 美团
+HOST, flowplus.meituan.net, reject
+HOST-SUFFIX, analytics.meituan.net, reject
+HOST-SUFFIX, meituan.xn--io0a7i, reject
+HOST-SUFFIX, meituan.yoga, reject
+HOST-SUFFIX, meituangov.cn, reject
+HOST-SUFFIX, report.meituan.com, reject
+HOST-SUFFIX, wmlog.meituan.com, reject
+
+# 交管12123
+host, static.122.gov.cn, reject
+ip-cidr, 203.107.1.1/24, reject
+HOST-SUFFIX, v3.fstats.xyz, reject
+HOST-SUFFIX, wss.haoyundmn.com, reject
+HOST-SUFFIX, new.xiongzhangad.com, reject
+HOST-SUFFIX, alexametrics.com, reject
+HOST-KEYWORD, in-page-push, reject
+
+# > 优酷
+HOST-SUFFIX,atm.youku.com, reject
+HOST,ad.mobile.youku.com, reject
+HOST,iyes.youku.com, reject
+HOST,pl.cp31.ott.cibntv.net, reject
+
+# > 百度
+HOST-SUFFIX,duapps.com, reject
+HOST-SUFFIX,cpro.baidu.com, reject
+HOST-SUFFIX,pos.baidu.com, reject
+HOST,afd.baidu.com, reject
+HOST,als.baidu.com, reject
+HOST,duclick.baidu.com, reject
+HOST,mobads.baidu.com, reject
+HOST,mobads-logs.baidu.com, reject
+HOST,nadvideo2.baidu.com, reject
+HOST,nsclick.baidu.com, reject
+HOST-SUFFIX,bce.baidu.com, reject
+HOST-SUFFIX,bar.baidu.com, reject
+HOST-SUFFIX,baiduyubaidu.com, reject
+HOST-SUFFIX,baidutv.baidu.com, reject
+HOST-SUFFIX,baichuan.baidu.com, reject
+HOST-SUFFIX,appc.baidu.com, reject
+HOST-SUFFIX,anquan.baidu.com, reject
+HOST-SUFFIX,adscdn.baidu.com, reject
+HOST-SUFFIX,adm.baidu.com, reject
+HOST-SUFFIX,ad.player.baidu.com, reject
+HOST-SUFFIX,a.baidu.com, reject
+HOST-SUFFIX,antivirus.baidu.com, reject
+HOST-SUFFIX,baifen.music.baidu.com, reject
+HOST-SUFFIX,banlv.baidu.com, reject
+HOST-SUFFIX,cm.baidu.com, reject
+HOST-SUFFIX,cpro.zhidao.baidu.com, reject
+HOST-SUFFIX,cleaner.baidu.com, reject
+HOST-SUFFIX,cjhq.baidu.com, reject
+HOST-SUFFIX,cb.baidu.com, reject
+HOST-SUFFIX,c.baidu.com, reject
+HOST-SUFFIX,btlaunch.baidu.com, reject
+HOST-SUFFIX,bdplus.baidu.com, reject
+HOST-SUFFIX,cbjs.baidu.com, reject
+HOST-SUFFIX,cpro2.baidu.com, reject
+HOST-SUFFIX,cpu-admin.baidu.com, reject
+
+# >爱奇艺
+HOST,t7z.cupid.iqiyi.com, reject
+HOST,t7z.cupid.ptqy.gitv.tv, reject
+IP-CIDR,203.107.63.154/32, reject
+IP-CIDR,101.227.97.240/32, reject
+IP-CIDR,101.227.200.11/32, reject
+IP-CIDR,101.227.200.28/32, reject
+IP-CIDR,124.192.153.42/32, reject
+
+# > 字节跳动
+HOST-SUFFIX,pangolin-sdk-toutiao.com, reject
+HOST-SUFFIX,pangolin-sdk-toutiao-b.com, reject
+HOST-SUFFIX,api-access.pangolin-sdk-toutiao-b.com, reject
+HOST,ad.toutiao.com, reject
+HOST,dsp.toutiao.com, reject
+host-keyword,pangolin.snssdk.com, reject
+
+# > 谷歌
+HOST-SUFFIX,google-analytics.com, reject
+HOST,safebrowsing.googleapis.com, reject
+HOST-SUFFIX,doubleclick.net, reject
+HOST-SUFFIX,googleadservices.com, reject
+HOST-SUFFIX,googleadsserving.cn, reject
+HOST-SUFFIX,googlesyndication.com, reject
+HOST-SUFFIX,googletagservices.com, reject
+HOST-SUFFIX,googletagmanager.com, reject
+HOST-SUFFIX,video-ad-stats.googlesyndication.com, reject
+HOST-SUFFIX,tpc.googlesyndication.com, reject
+HOST-SUFFIX,pagead.google.com, reject
+HOST-SUFFIX,pagead.l.google.com, reject
+HOST-SUFFIX,pagead2.googlesyndication.com, reject
+HOST-SUFFIX,pagead-tpc.l.google.com, reject
+HOST-SUFFIX,mobileads.google.com, reject
+HOST-SUFFIX,googlecommerce.com, reject
+HOST-SUFFIX,blaaaa12.googlecode.com, reject
+HOST-SUFFIX,badad.googleplex.com, reject
+HOST-SUFFIX,afs.googlesyndication.com, reject
+HOST-SUFFIX,afd.l.google.com, reject
+HOST-SUFFIX,www.googleadservices.com, reject
+HOST-SUFFIX,www.google-analytics.com, reject
+HOST,ads.youtube.com, reject
+
+# > 微软
+HOST-SUFFIX,ads.msn.com, reject
+HOST-SUFFIX,ads1.msn.com, reject
+HOST-SUFFIX,ads2.msn.com, reject
+HOST-SUFFIX,bingads.microsoft.com, reject
+HOST-SUFFIX,rads.msn.com, reject
+HOST,mobileads.msn.com, reject
+
+# > 腾讯视频
+host-suffix, tetrack.qq.com, reject
+host-suffix, tpns.tencent.com, reject
+host-suffix, api.poll.video.qq.com, reject
+host-suffix, static-res.qq.com, reject
+host-suffix, stat.tpns.tencent.com, reject
+host, h.trace.qq.com, reject
+
+# > 爱奇艺
+host, cr-status.iqiyi.com, reject
+host-suffix, cupid.iqiyi.com, reject
+host, f74f7f7765f8a2f6.ngaa.net.cn, reject
+host, ef-dongfeng.tanx.com, reject
+host, iqiyim.adtrack.enlightent.cn, reject
+HOST,dig.bdurl.net, reject
+HOST,ads3-normal-lq.zijieapi.com, reject
+HOST,ads5-normal-lq.zijieapi.com, reject
+
+# > 腾讯
+HOST-SUFFIX,news.ssp.qq.com, reject
+HOST-SUFFIX,news.l.qq.com, reject
+HOST-SUFFIX,activeqq.3g.qq.com, reject
+HOST-SUFFIX,ad.qq.com, reject
+HOST-SUFFIX,adping.qq.com, reject
+HOST-SUFFIX,adpm.app.qq.com, reject
+HOST-SUFFIX,adrdir.qq.com, reject
+HOST-SUFFIX,adsclick.qq.com, reject
+HOST-SUFFIX,adsense.html5.qq.com, reject
+HOST-SUFFIX,adsfile.qq.com, reject
+HOST-SUFFIX,adsgroup.qq.com, reject
+HOST-SUFFIX,adshmct.qq.com, reject
+HOST-SUFFIX,adshmmsg.qq.com, reject
+HOST-SUFFIX,adslvfile.qq.com, reject
+HOST-SUFFIX,adslvseed.qq.com, reject
+HOST-SUFFIX,adsolution.imtt.qq.com, reject
+HOST-SUFFIX,adsqqclick.qq.com, reject
+HOST-SUFFIX,adstextview.qq.com, reject
+HOST-SUFFIX,adsview.qq.com, reject
+HOST-SUFFIX,adsview2.qq.com, reject
+HOST-SUFFIX,adv.app.qq.com, reject
+HOST-SUFFIX,adver.qq.com, reject
+HOST-SUFFIX,aeventlog.beacon.qq.com, reject
+HOST-SUFFIX,analy.qq.com, reject
+HOST-SUFFIX,astrategy.beacon.qq.com, reject
+HOST-SUFFIX,c.gdt.qq.com, reject
+HOST-SUFFIX,c.gj.qq.com, reject
+HOST-SUFFIX,canvas.gdt.qq.com, reject
+HOST-SUFFIX,d.gdt.qq.com, reject
+HOST-SUFFIX,d3g.qq.com, reject
+HOST-SUFFIX,download.sj.qq.com, reject
+HOST-SUFFIX,dp3.qq.com, reject
+HOST-SUFFIX,eventlog.beacon.qq.com, reject
+HOST-SUFFIX,game.html5.qq.com, reject
+HOST-SUFFIX,ggmmqq.com, reject
+HOST-SUFFIX,j.wit.qq.com, reject
+HOST-SUFFIX,jqmt.qq.com, reject
+HOST-SUFFIX,jrlt.beacon.qq.com, reject
+HOST-SUFFIX,jsqmt.qq.com, reject
+HOST-SUFFIX,lives.l.qq.com, reject
+HOST-SUFFIX,livep.l.qq.com, reject
+HOST-SUFFIX,mi.gdt.qq.com, reject
+HOST-SUFFIX,livep.l.ott.video.qq.com, reject
+HOST-SUFFIX,lives.l.ott.video.qq.com, reject
+HOST-SUFFIX,masdk.3g.qq.com, reject
+HOST-SUFFIX,mfm.video.qq.com, reject
+HOST-SUFFIX,mini2015.qq.com, reject
+HOST-SUFFIX,monitor.uu.qq.com, reject
+HOST-SUFFIX,mqqad.cs0309.html5.qq.com, reject
+HOST-SUFFIX,mqqad.html5.qq.com, reject
+HOST-SUFFIX,mqqadr.reader.qq.com, reject
+HOST-SUFFIX,nc.gdt.qq.com, reject
+HOST-SUFFIX,news.mpush.qq.com, reject
+HOST-SUFFIX,news-l.play.ott.video.qq.com, reject
+HOST-SUFFIX,novelsns.html5.qq.com, reject
+HOST-SUFFIX,oth.update.mdt.qq.com, reject
+HOST-SUFFIX,pcbrowser.dd.qq.com, reject
+HOST-SUFFIX,pmir.3g.qq.com, reject
+HOST-SUFFIX,pvstat.html5.qq.com, reject
+HOST-SUFFIX,q.i.gdt.qq.com, reject
+HOST-SUFFIX,qqshow2-item.qq.com, reject
+HOST-SUFFIX,rm.gdt.qq.com, reject
+HOST-SUFFIX,scdown.qq.com, reject
+HOST-SUFFIX,setting.snswin.qq.com, reject
+HOST-SUFFIX,sngmta.qq.com, reject
+HOST-SUFFIX,strategy.beacon.qq.com, reject
+HOST-SUFFIX,t.gdt.qq.com, reject
+HOST-SUFFIX,t.sj.qq.com, reject
+HOST-SUFFIX,ta.qq.com, reject
+HOST-SUFFIX,tcss.qq.com, reject
+HOST-SUFFIX,tpush.html5.qq.com, reject
+HOST-SUFFIX,updatecenter.qq.com, reject
+HOST-SUFFIX,video.ureport.push.qq.com, reject
+HOST-SUFFIX,video.wap.mpush.qq.com, reject
+HOST-SUFFIX,vlive.qqvideo.tc.qq.com, reject
+HOST-SUFFIX,wap.mpush.qq.com, reject
+HOST-SUFFIX,win.gdt.qq.com, reject
+HOST-SUFFIX,ws.sj.qq.com, reject
+HOST-SUFFIX,wxsnsdy.tc.qq.com, reject
+HOST-SUFFIX,wxsnsdy.video.qq.com, reject
+HOST-SUFFIX,adsmind.tc.qq.com, reject
+HOST-SUFFIX,btrace.qq.com, reject
+HOST-SUFFIX,mtrace.qq.com, reject
+HOST-SUFFIX,pingma.qq.com, reject
+HOST-SUFFIX,pingtcss.qq.com, reject
+HOST-SUFFIX,tajs.qq.com, reject
+HOST-SUFFIX,wxsnsdy.wxs.qq.com, reject
+HOST-SUFFIX,wxsnsdythumb.wxs.qq.com, reject
+HOST-SUFFIX,fusion.qq.com, reject
+HOST-SUFFIX,ios.bugly.qq.com, reject
+HOST,safebrowsing.urlsec.qq.com, reject
+HOST-SUFFIX,oth.str.mdt.qq.com, reject
+HOST-SUFFIX,l.qq.com, reject
+HOST,adsmind.apdcdn.tc.qq.com, reject
+HOST,adsmind.tc.qq.com, reject
+HOST,adsmind.ugdtimg.com, reject
+HOST,livep.l.t002.ottcn.com, reject
+HOST,pgdt.ugdtimg.com, reject
+HOST,splashqqlive.gtimg.com, reject
+HOST,vv.video.qq.com, reject
+HOST,wa.gtimg.com, reject
+# HOST,wxsnsdy.wxs.qq.com, reject
+# HOST,wxsnsdythumb.wxs.qq.com, reject
+
+# > 微博
+HOST-KEYWORD,fastimage.uve.weibo.com, reject
+HOST-KEYWORD,adimg.uve.weibo.com, reject
+HOST-SUFFIX,adimg.vue.weibo.com, reject
+HOST-SUFFIX,zymo.mps.weibo.com, reject
+HOST-SUFFIX,weibomingzi.com, reject
+HOST-SUFFIX,sdkapp.uve.weibo.com, reject
+HOST-SUFFIX,s.alitui.weibo.com, reject
+HOST-SUFFIX,promote.biz.weibo.cn, reject
+HOST-SUFFIX,gw5.push.mcp.weibo.cn, reject
+HOST-SUFFIX,game.weibo.cn, reject
+HOST-SUFFIX,biz.weibo.com, reject
+HOST-SUFFIX,adimg.uve.weibo.com, reject
+HOST-SUFFIX,game.weibo.com, reject
+HOST-SUFFIX,gw6.push.mcp.weibo.cn, reject
+HOST-KEYWORD,ads.viber.com, reject
+HOST-KEYWORD,ads-d.viber.com, reject
+HOST-KEYWORD,ads.aws.viber.com, reject
+HOST-SUFFIX,alitui.weibo.com, reject
+HOST,adimg.uve.weibo.com, reject
+HOST,adimg.vue.weibo.com, reject
+HOST-KEYWORD,adimg.uve.weibo.com,REJECT
+HOST-KEYWORD,alitui.weibo.com,REJECT
+HOST-KEYWORD,biz.weibo.com,REJECT
+HOST-KEYWORD,game.weibo.cn,REJECT
+HOST-KEYWORD,game.weibo.com,REJECT
+HOST-KEYWORD,gw5.push.mcp.weibo.cn,REJECT
+HOST-KEYWORD,gw6.push.mcp.weibo.cn,REJECT
+HOST-KEYWORD,promote.biz.weibo.cn,REJECT
+HOST-KEYWORD,s.alitui.weibo.com,REJECT
+HOST-KEYWORD,sdkapp.uve.weibo.com,REJECT
+HOST-KEYWORD,weibomingzi.com,REJECT
+HOST-KEYWORD,zymo.mps.weibo.com,REJECT
+HOST-KEYWORD,adimg.vue.weibo.com,REJECT
+HOST-KEYWORD,dp.im.weibo.cn,REJECT
+HOST-KEYWORD,m.game.weibo.cn,REJECT
+HOST-KEYWORD,c.biz.weibo.com,REJECT
+HOST-KEYWORD,c.wcpt.biz.weibo.com,REJECT
+HOST-KEYWORD,click.uve.weibo.com,REJECT
+HOST-KEYWORD,wax.weibo.com,REJECT
+HOST-KEYWORD,wbapp.uve.weibo.com,REJECT
+HOST-KEYWORD,widget.weibo.com,REJECT
+HOST-KEYWORD,zc.biz.weibo.com,REJECT
+HOST-KEYWORD,dsp.edm.weibo.cn,REJECT
+HOST-KEYWORD,alitui.weibo.com.cn,REJECT
+HOST-KEYWORD,biz.weibo.com.cn,REJECT
+HOST-KEYWORD,game.weibo.com.cn,REJECT
+HOST-KEYWORD,tui.weibo.com,REJECT
+HOST-KEYWORD,wax.weibo.com.cn,REJECT
+HOST-KEYWORD,ad.weibo.com,REJECT
+HOST-KEYWORD,adstrategy.biz.weibo.com,REJECT
+HOST-KEYWORD,s.weibo.com,REJECT
+HOST-KEYWORD,vs.biz.weibo.com,REJECT
+
+# > 喜马拉雅
+HOST,ad.ximalaya.com, reject
+HOST,adbs.ximalaya.com, reject
+HOST,adse.ximalaya.com, reject
+HOST,adse.wsa.ximalaya.com, reject
+HOST,adbehavior.wsa.ximalaya.com, reject
+HOST,adbehavior.ximalaya.com, reject
+HOST,adsebs.ximalaya.com, reject
+HOST,adwbs.ximalaya.com, reject
+
+# >小红书
+HOST,ads-img-qc.xhscdn.com, reject
+HOST,ads-video-al.xhscdn.com, reject
+HOST,ads-video-qc.xhscdn.com, reject
+HOST,t-ads.xiaohongshu.com, reject
+
+# > 淘宝
+HOST-SUFFIX,apoll.m.taobao.com, reject
+HOST-SUFFIX,h-adashx.ut.taobao.com, reject
+HOST-SUFFIX,w.m.taobao.com, reject
+HOST,tunion-api.m.taobao.com, reject
+HOST-SUFFIX,ai.m.taobao.com, reject
+HOST-SUFFIX,re.m.taobao.com, reject
+HOST-SUFFIX,agoodm.m.taobao.com, reject
+HOST-SUFFIX,ai.taobao.com, reject
+HOST-SUFFIX,api.waptest.taobao.com, reject
+HOST-SUFFIX,dsp.simba.taobao.com, reject
+HOST-SUFFIX,fav.simba.taobao.com, reject
+HOST-SUFFIX,m.simba.taobao.com, reject
+HOST-SUFFIX,mclick.simba.taobao.com, reject
+HOST-SUFFIX,re.taobao.com, reject
+HOST-SUFFIX,redirect.simba.taobao.com, reject
+HOST-SUFFIX,simba.m.taobao.com, reject
+HOST-SUFFIX,srd.simba.taobao.com, reject
+HOST-SUFFIX,temai.taobao.com, reject
+HOST-SUFFIX,textlink.simba.taobao.com, reject
+HOST-SUFFIX,unitacs.m.taobao.com, reject
+HOST-SUFFIX,acs4baichuan.m.taobao.com, reject
+HOST-SUFFIX,adashbc.ut.taobao.com, reject
+HOST-SUFFIX,adash-c.ut.taobao.com, reject
+HOST-SUFFIX,adashxgc.ut.taobao.com, reject
+HOST-SUFFIX,adashx4yt.m.taobao.com, reject
+HOST-SUFFIX,tunion-api.m.taobao.com, reject
+HOST-SUFFIX,tns.simba.taobao.com, reject
+HOST-SUFFIX,click.mz.simba.taobao.com, reject
+HOST-SUFFIX,click.simba.taobao.com, reject
+HOST-SUFFIX,click.tz.simba.taobao.com, reject
+HOST-SUFFIX,stat.simba.taobao.com, reject
+HOST-SUFFIX,m-adash.m.taobao.com, reject
+HOST-SUFFIX,adashbc.m.taobao.com, reject
+
+# > 铁路12306
+HOST, ad.12306.cn, REJECT
+
+# > 威锋
+host-keyword, p3-be-pack-sign.pglstatp-toutiao.com, reject
+host-keyword, sf3-be-pack.pglstatp-toutiao.com, reject
+host-keyword,sf1-be-pack.pglstatp-toutiao.com, reject
+host-keyword,sf1-fe-tos.pglstatp-toutiao.com, reject
+host-keyword,sf1-ttcdn-tos.pstatp.com, reject
+host-keyword,sf3-fe-tos.pglstatp-toutiao.com, reject
+host-keyword,sf3-ttcdn-tos.pstatp.com, reject
+host-keyword,sf6-fe-tos.pglstatp-toutiao.com, reject
+host-keyword,s3-fe-scm.pglstatp-toutiao.com, reject
+host-keyword,sf6-be-pack.pglstatp-toutiao.com, reject
+host-keyword,p9-be-pack-sign.pglstatp-toutiao.com, reject
diff --git a/profiles/Surge/Surge.cookies.sgmodule b/profiles/Surge/Surge.cookies.sgmodule
new file mode 100644
index 0000000..83063da
--- /dev/null
+++ b/profiles/Surge/Surge.cookies.sgmodule
@@ -0,0 +1,20 @@
+#!name=evilbutcher Cookies Module
+#!desc=Cookies 合集模块配置
+#!system=ios
+
+[Script]
+Funboat获取签到Cookie = http-request,pattern=^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx9b5caf9d1669dc96,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+Funboat获取积分Cookie = http-request,pattern=^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx9b5caf9d1669dc96,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+Timepop获取签到Cookie = http-request,pattern=^https:\/\/h5\.youzan\.com\/wscump\/checkin\/checkin\.json\?checkin\_id\=.*?app\_id\=wx4a1af22a88a99386,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+Timepop获取积分Cookie = http-request,pattern=^https:\/\/h5\.youzan\.com\/wscuser\/membercenter\/stats\.json\?app\_id\=wx4a1af22a88a99386,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+GLaDOS获取Cookie = http-request,pattern=https:\/\/glados\.rocks\/api\/user\/checkin, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
+微博超话获取Cookie = http-request,pattern=^https?://m?api\.weibo\.c(n|om)\/2\/(cardlist|page\/button), script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/weibo/weibotalk.cookie.js
+九木杂物社获取Cookie = http-request, pattern = https:\/\/wxavip\-up\.ezrpro\.cn\/Vip\/SignIn\/SignIn, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js, requires-body=true
+酷乐潮玩小程序获取签到Cookie = http-request, pattern = https:\/\/wxavip\-tp\.ezrpro\.cn\/Vip\/SignIn\/SignIn, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js, requires-body=true
+酷乐潮玩App获取Cookie = http-request, pattern = https:\/\/app\.klcw\.net\.cn\/omp\_cmanage\/mallgateway, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js, requires-body=true
+华住会获取签到Cookie = http-request, pattern = https:\/\/hweb-mbf\.huazhu\.com\/api\/signIn, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js, requires-body=false
+淘宝监控获取Cookie = http-request, pattern = https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdetail, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js, requires-body=false
+淘宝监控获取Cookie = http-request, pattern = https:\/\/h5api.m.taobao.com\/h5\/mtop.taobao.detail.getdesc, script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js, requires-body=false
+
+[MITM]
+hostname = %INSERT%, h5.youzan.com, glados.rocks, api.weibo.cn, mapi.weibo.com, wxavip-up.ezrpro.cn, wxavip-tp.ezrpro.cn, app.klcw.net.cn, hweb-mbf.huazhu.com, h5api.m.taobao.com
\ No newline at end of file
diff --git a/profiles/Surge/Surge.tasks.sgmodule b/profiles/Surge/Surge.tasks.sgmodule
new file mode 100644
index 0000000..a2aa90a
--- /dev/null
+++ b/profiles/Surge/Surge.tasks.sgmodule
@@ -0,0 +1,25 @@
+#!name=evilbutcher Tasks Module
+#!desc=Tasks 合集模块配置
+#!system=ios
+
+[Script]
+NASA每日一图 = type=cron,cronexp=0 0 6 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/nasa/nasapic.js
+iDaily每日环球视野 = type=cron,cronexp=0 0 6 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/idaily/idaily.js
+App价格监控 = type=cron,cronexp=30 7-22 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/appstore/AppMonitor.js
+热门监控 = type=cron,cronexp=30 0 8-22/2 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hotsearch/hot.js
+微博超话 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/weibo/weibotalk.js
+GLaDOS签到 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/glados.js
+机场签到 = type=cron,cronexp=0 1 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/checkin_env.js
+机场签到Cookie = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/glados/checkincookie_env.js
+Funboat签到 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/funboat/funboat.js
+Timepop签到 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/timepop/timepop.js
+九木杂物社 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/jiumu/jiumu.js
+酷乐潮玩小程序 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw.js
+酷乐潮玩App = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/klcw/klcw-app.js
+公众号监控 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/wechatsubs.js
+事业单位招聘监控 = type=cron,cronexp=5 * * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/sydwzp.js
+高校人才网招聘监控 = type=cron,cronexp=5 * * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/wechatsubs/gxrcw.js
+彩票监控 = type=cron,cronexp=0 30 21 * * * ,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/ssq/ssq.js
+华住会 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/hzh/hzh.js
+淘宝监控-标题版 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb-name.js
+淘宝监控 = type=cron,cronexp=5 0 * * *,script-path=https://raw.githubusercontent.com/evilbutcher/Quantumult_X/master/check_in/taobao/tb.js
\ No newline at end of file
diff --git a/profiles/package.json b/profiles/package.json
new file mode 100644
index 0000000..9175862
--- /dev/null
+++ b/profiles/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "evilbutcher",
+ "version": "1.0.0",
+ "description": "",
+ "main": "checkin_env.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/evilbutcher/Quantumult_X.git"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/evilbutcher/Quantumult_X/issues"
+ },
+ "homepage": "https://github.com/evilbutcher/Quantumult_X#readme",
+ "dependencies": {
+ "got": "^11.5.1",
+ "npm": "^6.14.7",
+ "http-server": "^0.12.3",
+ "node-schedule": "^1.3.2",
+ "tough": "^0.6.0",
+ "tough-cookie": "^4.0.0",
+ "download": "^8.0.0",
+ "request": "^2.88.2",
+ "request-promise": "^4.2.5"
+ }
+}
diff --git a/tools/Env from chavyleung.js b/tools/Env from chavyleung.js
index 8ccf94f..5d63108 100644
--- a/tools/Env from chavyleung.js
+++ b/tools/Env from chavyleung.js
@@ -315,11 +315,15 @@ function Env(name, opts) {
this.got(opts)
.on("redirect", (resp, nextOpts) => {
try {
- const ck = resp.headers["set-cookie"]
- .map(this.cktough.Cookie.parse)
- .toString();
- this.ckjar.setCookieSync(ck, null);
- nextOpts.cookieJar = this.ckjar;
+ if (resp.headers["set-cookie"]) {
+ const ck = resp.headers["set-cookie"]
+ .map(this.cktough.Cookie.parse)
+ .toString();
+ if (ck) {
+ this.ckjar.setCookieSync(ck, null);
+ }
+ nextOpts.cookieJar = this.ckjar;
+ }
} catch (e) {
this.logErr(e);
}
@@ -339,6 +343,7 @@ function Env(name, opts) {
}
post(opts, callback = () => {}) {
+ const method = opts.method ? opts.method.toLocaleLowerCase() : "post";
// 如果指定了请求体, 但没指定`Content-Type`, 则自动生成
if (opts.body && opts.headers && !opts.headers["Content-Type"]) {
opts.headers["Content-Type"] = "application/x-www-form-urlencoded";
@@ -349,7 +354,7 @@ function Env(name, opts) {
opts.headers = opts.headers || {};
Object.assign(opts.headers, { "X-Surge-Skip-Scripting": false });
}
- $httpClient.post(opts, (err, resp, body) => {
+ $httpClient[method](opts, (err, resp, body) => {
if (!err && resp) {
resp.body = body;
resp.statusCode = resp.status;
@@ -357,7 +362,7 @@ function Env(name, opts) {
callback(err, resp, body);
});
} else if (this.isQuanX()) {
- opts.method = "POST";
+ opts.method = method;
if (this.isNeedRewrite) {
opts.opts = opts.opts || {};
Object.assign(opts.opts, { hints: false });
@@ -372,7 +377,7 @@ function Env(name, opts) {
} else if (this.isNode()) {
this.initGotEnv(opts);
const { url, ..._opts } = opts;
- this.got.post(url, _opts).then(
+ this.got[method](url, _opts).then(
(resp) => {
const { statusCode: status, statusCode, headers, body } = resp;
callback(null, { status, statusCode, headers, body }, body);
@@ -390,23 +395,25 @@ function Env(name, opts) {
* :$.time('yyyyMMddHHmmssS')
* y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒
* 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符
- * @param {*} fmt 格式化参数
+ * @param {string} fmt 格式化参数
+ * @param {number} 可选: 根据指定时间戳返回格式化日期
*
*/
- time(fmt) {
+ time(fmt, ts = null) {
+ const date = ts ? new Date(ts) : new Date();
let o = {
- "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(),
+ "M+": date.getMonth() + 1,
+ "d+": date.getDate(),
+ "H+": date.getHours(),
+ "m+": date.getMinutes(),
+ "s+": date.getSeconds(),
+ "q+": Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds(),
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(
RegExp.$1,
- (new Date().getFullYear() + "").substr(4 - RegExp.$1.length)
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
for (let k in o)
if (new RegExp("(" + k + ")").test(fmt))
@@ -467,12 +474,14 @@ function Env(name, opts) {
$notify(title, subt, desc, toEnvOpts(opts));
}
}
- let logs = ["", "==============📣系统通知📣=============="];
- logs.push(title);
- subt ? logs.push(subt) : "";
- desc ? logs.push(desc) : "";
- console.log(logs.join("\n"));
- this.logs = this.logs.concat(logs);
+ if (!this.isMuteLog) {
+ let logs = ["", "==============📣系统通知📣=============="];
+ logs.push(title);
+ subt ? logs.push(subt) : "";
+ desc ? logs.push(desc) : "";
+ console.log(logs.join("\n"));
+ this.logs = this.logs.concat(logs);
+ }
}
log(...logs) {
diff --git a/tools/OpenAPI from Peng-YM.js b/tools/OpenAPI from Peng-YM.js
index 0e19ca1..6842f30 100644
--- a/tools/OpenAPI from Peng-YM.js
+++ b/tools/OpenAPI from Peng-YM.js
@@ -1,3 +1,8 @@
+/**
+ * OpenAPI
+ * @author: Peng-YM
+ * https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
+ */
function ENV() {
const isQX = typeof $task !== "undefined";
const isLoon = typeof $loon !== "undefined";
@@ -6,17 +11,41 @@ function ENV() {
const isNode = typeof require == "function" && !isJSBox;
const isRequest = typeof $request !== "undefined";
const isScriptable = typeof importModule !== "undefined";
- return { isQX, isLoon, isSurge, isNode, isJSBox, isRequest, isScriptable };
+ return {
+ isQX,
+ isLoon,
+ isSurge,
+ isNode,
+ isJSBox,
+ isRequest,
+ isScriptable,
+ };
}
-function HTTP(baseURL, defaultOptions = {}) {
+function HTTP(
+ defaultOptions = {
+ baseURL: "",
+ }
+) {
const { isQX, isLoon, isSurge, isScriptable, isNode } = ENV();
const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
+ const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
function send(method, options) {
- options = typeof options === "string" ? { url: options } : options;
- options.url = baseURL ? baseURL + options.url : options.url;
- options = { ...defaultOptions, ...options };
+ options =
+ typeof options === "string"
+ ? {
+ url: options,
+ }
+ : options;
+ const baseURL = defaultOptions.baseURL;
+ if (baseURL && !URL_REGEX.test(options.url || "")) {
+ options.url = baseURL ? baseURL + options.url : options.url;
+ }
+ options = {
+ ...defaultOptions,
+ ...options,
+ };
const timeout = options.timeout;
const events = {
...{
@@ -31,7 +60,10 @@ function HTTP(baseURL, defaultOptions = {}) {
let worker;
if (isQX) {
- worker = $task.fetch({ method, ...options });
+ worker = $task.fetch({
+ method,
+ ...options,
+ });
} else if (isLoon || isSurge || isNode) {
worker = new Promise((resolve, reject) => {
const request = isNode ? require("request") : $httpClient;
@@ -127,8 +159,8 @@ function API(name = "untitled", debug = false) {
});
};
}
- // persistance
+ // persistence
// initialize cache
initCache() {
if (isQX) this.cache = JSON.parse($prefs.valueForKey(this.name) || "{}");
@@ -142,7 +174,9 @@ function API(name = "untitled", debug = false) {
this.node.fs.writeFileSync(
fpath,
JSON.stringify({}),
- { flag: "wx" },
+ {
+ flag: "wx",
+ },
(err) => console.log(err)
);
}
@@ -154,7 +188,9 @@ function API(name = "untitled", debug = false) {
this.node.fs.writeFileSync(
fpath,
JSON.stringify({}),
- { flag: "wx" },
+ {
+ flag: "wx",
+ },
(err) => console.log(err)
);
this.cache = {};
@@ -168,20 +204,24 @@ function API(name = "untitled", debug = false) {
// store cache
persistCache() {
- const data = JSON.stringify(this.cache);
+ const data = JSON.stringify(this.cache, null, 2);
if (isQX) $prefs.setValueForKey(data, this.name);
if (isLoon || isSurge) $persistentStore.write(data, this.name);
if (isNode) {
this.node.fs.writeFileSync(
`${this.name}.json`,
data,
- { flag: "w" },
+ {
+ flag: "w",
+ },
(err) => console.log(err)
);
this.node.fs.writeFileSync(
"root.json",
- JSON.stringify(this.root),
- { flag: "w" },
+ JSON.stringify(this.root, null, 2),
+ {
+ flag: "w",
+ },
(err) => console.log(err)
);
}
@@ -191,11 +231,11 @@ function API(name = "untitled", debug = false) {
this.log(`SET ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
- $persistentStore.write(data, key);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(data, key);
}
if (isQX) {
- $prefs.setValueForKey(data, key);
+ return $prefs.setValueForKey(data, key);
}
if (isNode) {
this.root[key] = data;
@@ -210,7 +250,7 @@ function API(name = "untitled", debug = false) {
this.log(`READ ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
+ if (isSurge || isLoon) {
return $persistentStore.read(key);
}
if (isQX) {
@@ -228,11 +268,11 @@ function API(name = "untitled", debug = false) {
this.log(`DELETE ${key}`);
if (key.indexOf("#") !== -1) {
key = key.substr(1);
- if (isSurge & isLoon) {
- $persistentStore.write(null, key);
+ if (isSurge || isLoon) {
+ return $persistentStore.write(null, key);
}
if (isQX) {
- $prefs.removeValueForKey(key);
+ return $prefs.removeValueForKey(key);
}
if (isNode) {
delete this.root[key];
@@ -263,7 +303,7 @@ function API(name = "untitled", debug = false) {
let opts = {};
if (openURL) opts["openUrl"] = openURL;
if (mediaURL) opts["mediaUrl"] = mediaURL;
- if (JSON.stringify(opts) == "{}") {
+ if (JSON.stringify(opts) === "{}") {
$notification.post(title, subtitle, content);
} else {
$notification.post(title, subtitle, content, opts);
@@ -288,15 +328,15 @@ function API(name = "untitled", debug = false) {
// other helper functions
log(msg) {
- if (this.debug) console.log(msg);
+ if (this.debug) console.log(`[${this.name}] LOG: ${this.stringify(msg)}`);
}
info(msg) {
- console.log(msg);
+ console.log(`[${this.name}] INFO: ${this.stringify(msg)}`);
}
error(msg) {
- console.log("ERROR: " + msg);
+ console.log(`[${this.name}] ERROR: ${this.stringify(msg)}`);
}
wait(millisec) {
@@ -314,5 +354,16 @@ function API(name = "untitled", debug = false) {
}
}
}
+
+ stringify(obj_or_str) {
+ if (typeof obj_or_str === "string" || obj_or_str instanceof String)
+ return obj_or_str;
+ else
+ try {
+ return JSON.stringify(obj_or_str, null, 2);
+ } catch (err) {
+ return "[object Object]";
+ }
+ }
})(name, debug);
}