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 = /\>.*?\ $.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\\\"\>.*?\ { + 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 = /\.\ \;\.*?\ $.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); }