shawenguan 1 год назад
Родитель
Сommit
b00a1961df

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/ali/aliYunPanSignIn.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/bodian/bodianSignIn.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/buyu/wbankBuYu.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/cmobile/caiyunExchange.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/cmobile/caiyunHelper.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/cmobile/caiyunSignIn.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/damai/damaiHelper.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/elife/ofpayGrab.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/elife/ofpayHelper.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/gandart/gandartCheck.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/gandart/gandartComposite.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/gandart/gandartExchange.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/gandart/gandartGrab.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/gandart/gandartHelper.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/gandart/gandartLock.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/gandart/gandartOrder.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/gandart/gandartPay.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/gandart/gandartStarLight.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/huluwa/huluwaHelper.js


Разница между файлами не показана из-за своего большого размера
+ 703 - 627
Scripts/imaotai/imaotaiHelper.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/jhsh/jhshHelper.js


Разница между файлами не показана из-за своего большого размера
+ 2 - 3
Scripts/manmanbuy/manmanbuyHelper.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/telecom/telecom.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 0
Scripts/test/testHelper.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/tghelper/tgLinksHelper.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/thwj/thwjHelper.js


+ 435 - 276
Scripts/util/MagicJS.js

@@ -1,5 +1,6 @@
-function MagicJS(e = "MagicJS", t = "INFO") {
-    const s = {
+function MagicJS(scriptName = "MagicJS", logLevel = "INFO") {
+    // HTTP/1.1协议头部header字段名大小写不敏感, 但是HTTP/2头部header字段名必须使用小写
+    const headerFieldMap = {
         accept: "Accept",
         "accept-ch": "Accept-CH",
         "accept-charset": "Accept-Charset",
@@ -84,8 +85,9 @@ function MagicJS(e = "MagicJS", t = "INFO") {
     };
     return new class {
         constructor() {
-            this.version = "2.2.3.3";
-            this.scriptName = e;
+            this._startTime = Date.now();
+            this.version = "2.2.3.7";
+            this.scriptName = scriptName;
             this.logLevels = {
                 DEBUG: 5,
                 INFO: 4,
@@ -100,7 +102,6 @@ function MagicJS(e = "MagicJS", t = "INFO") {
             this.isJSBox = typeof $drive !== "undefined";
             this.isNode = typeof module !== "undefined" && !this.isJSBox;
             this.isSurge = typeof $httpClient !== "undefined" && !this.isLoon;
-            this.platform = this.getPlatform();
             this.node = {
                 request: undefined,
                 fs: undefined,
@@ -108,14 +109,16 @@ function MagicJS(e = "MagicJS", t = "INFO") {
             };
             this.iOSUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Mobile/15E148 Safari/604.1";
             this.pcUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36 Edg/84.0.522.59";
-            this.logLevel = t;
-            this._unifiedPushUrl = "";
+            this._logLevel = "INFO";
+            this.logLevel = logLevel;
+            this._barkUrl = "";
+            this._barkKey = "";
             if (this.isNode) {
                 this.node.fs = require("fs");
                 this.node.request = require("request");
                 try {
                     this.node.fs.accessSync("./magic.json", this.node.fs.constants.R_OK | this.node.fs.constants.W_OK);
-                } catch (e) {
+                } catch (err) {
                     this.node.fs.writeFileSync("./magic.json", "{}", {
                         encoding: "utf8"
                     });
@@ -135,11 +138,21 @@ function MagicJS(e = "MagicJS", t = "INFO") {
                 }
             }
         }
-        set unifiedPushUrl(e) {
-            this._unifiedPushUrl = !!e ? e.replace(/\/+$/g, "") : "";
+        /**
+         * @param {string} url
+         */
+        set barkUrl(url) {
+            try {
+                let _url = url.replace(/\/+$/g, "");
+                this._barkUrl = `${/^https?:\/\/([^/]*)/.exec(_url)[0]}/push`;
+                this._barkKey = /\/([^\/]+)\/?$/.exec(_url)[1];
+            } catch (err) {
+                this.logDebug("Bark config error.");
+            }
         }
-        set logLevel(e) {
-            this._logLevel = typeof e === "string" ? e.toUpperCase() : "DEBUG";
+        set logLevel(level) {
+            let magic_loglevel = this.read("magicjs_loglevel");
+            this._logLevel = magic_loglevel ? magic_loglevel : level.toUpperCase();
         }
         get logLevel() {
             return this._logLevel;
@@ -150,6 +163,9 @@ function MagicJS(e = "MagicJS", t = "INFO") {
         get isResponse() {
             return typeof $response !== "undefined";
         }
+        get isDebug() {
+            return this.logLevel === "DEBUG";
+        }
         get request() {
             return typeof $request !== "undefined" ? $request : undefined;
         }
@@ -162,385 +178,528 @@ function MagicJS(e = "MagicJS", t = "INFO") {
                 return undefined;
             }
         }
-        getPlatform() {
-            if (this.isSurge) return "Surge"; else if (this.isQuanX) return "QuantumultX"; else if (this.isLoon) return "Loon"; else if (this.isJSBox) return "JSBox"; else if (this.isNode) return "Node.js"; else return "unknown";
+        get platform() {
+            if (this.isSurge) return "Surge"; else if (this.isQuanX) return "Quantumult X"; else if (this.isLoon) return "Loon"; else if (this.isJSBox) return "JSBox"; else if (this.isNode) return "Node.js"; else return "Unknown";
         }
-        read(e, t = "") {
-            let s = "";
+        read(key, session = "") {
+            let val = "";
+            // 读取原始数据
             if (this.isSurge || this.isLoon) {
-                s = $persistentStore.read(e);
+                val = $persistentStore.read(key);
             } else if (this.isQuanX) {
-                s = $prefs.valueForKey(e);
+                val = $prefs.valueForKey(key);
             } else if (this.isNode) {
-                s = this.node.data;
+                val = this.node.data;
             } else if (this.isJSBox) {
-                s = $file.read("drive://MagicJS/magic.json").string;
+                val = $file.read("drive://MagicJS/magic.json").string;
             }
             try {
-                if (this.isNode) s = s[e];
-                if (this.isJSBox) s = JSON.parse(s)[e];
-                if (!!t) {
-                    if (typeof s === "string") s = JSON.parse(s);
-                    s = !!s && typeof s === "object" ? s[t] : null;
+                // Node 和 JSBox数据处理
+                if (this.isNode) val = val[key];
+                if (this.isJSBox) val = JSON.parse(val)[key];
+                // 带Session的情况
+                if (!!session) {
+                    if (typeof val === "string") val = JSON.parse(val);
+                    val = !!val && typeof val === "object" ? val[session] : null;
                 }
-            } catch (i) {
-                this.logError(i);
-                s = !!t ? {} : null;
-                this.del(e);
+            } catch (err) {
+                this.logError(err);
+                val = !!session ? {} : null;
+                this.del(key);
             }
-            if (typeof s === "undefined") s = null;
+            if (typeof val === "undefined") val = null;
             try {
-                if (!!s && typeof s === "string") s = JSON.parse(s);
-            } catch (e) {}
-            this.logDebug(`READ DATA [${e}]${!!t ? `[${t}]` : ""}(${typeof s})\n${JSON.stringify(s)}`);
-            return s;
-        }
-        write(e, t, s = "") {
-            let i = !!s ? {} : "";
-            if (!!s && (this.isSurge || this.isLoon)) {
-                i = $persistentStore.read(e);
-            } else if (!!s && this.isQuanX) {
-                i = $prefs.valueForKey(e);
+                if (!!val && typeof val === "string") {
+                    var obj = JSON.parse(val);
+                    if (typeof obj == "object" && obj) {
+                        val = obj;
+                    }
+                }
+            } catch (err) {}
+            this.logDebug(`READ DATA [${key}]${!!session ? `[${session}]` : ""}(${typeof val})`+'\n'+`${JSON.stringify(val)}`);
+            return val;
+        }
+        write(key, val, session = "") {
+            let data = !!session ? {} : "";
+            // 读取原先存储的JSON格式数据
+            if (!!session && (this.isSurge || this.isLoon)) {
+                data = $persistentStore.read(key);
+            } else if (!!session && this.isQuanX) {
+                data = $prefs.valueForKey(key);
             } else if (this.isNode) {
-                i = this.node.data;
+                data = this.node.data;
             } else if (this.isJSBox) {
-                i = JSON.parse($file.read("drive://MagicJS/magic.json").string);
+                data = JSON.parse($file.read("drive://MagicJS/magic.json").string);
             }
-            if (!!s) {
+            if (!!session) {
+                // 有Session,所有数据都是Object
                 try {
-                    if (typeof i === "string") i = JSON.parse(i);
-                    i = typeof i === "object" && !!i ? i : {};
-                } catch (t) {
-                    this.logError(t);
-                    this.del(e);
-                    i = {};
+                    if (typeof data === "string") data = JSON.parse(data);
+                    data = typeof data === "object" && !!data ? data : {};
+                } catch (err) {
+                    this.logError(err);
+                    this.del(key);
+                    data = {};
                 }
                 if (this.isJSBox || this.isNode) {
-                    if (!i.hasOwnProperty(e) || typeof i[e] !== "object" || i[e] === null) {
-                        i[e] = {};
+                    // 构造数据
+                    if (!data[key] || typeof data[key] != "object") {
+                        data[key] = {};
                     }
-                    if (!i[e].hasOwnProperty(s)) {
-                        i[e][s] = null;
+                    if (!data[key].hasOwnProperty(session)) {
+                        data[key][session] = null;
                     }
-                    if (typeof t === "undefined") {
-                        delete i[e][s];
+                    // 写入或删除数据
+                    if (typeof val === "undefined") {
+                        delete data[key][session];
                     } else {
-                        i[e][s] = t;
+                        data[key][session] = val;
                     }
                 } else {
-                    if (typeof t === "undefined") {
-                        delete i[s];
+                    // 写入或删除数据
+                    if (typeof val === "undefined") {
+                        delete data[session];
                     } else {
-                        i[s] = t;
+                        data[session] = val;
                     }
                 }
-            } else {
+            }
+            // 没有Session时
+             else {
                 if (this.isNode || this.isJSBox) {
-                    if (typeof t === "undefined") {
-                        delete i[e];
+                    // 删除数据
+                    if (typeof val === "undefined") {
+                        delete data[key];
                     } else {
-                        i[e] = t;
+                        data[key] = val;
                     }
                 } else {
-                    if (typeof t === "undefined") {
-                        i = null;
+                    // 删除数据
+                    if (typeof val === "undefined") {
+                        data = null;
                     } else {
-                        i = t;
+                        data = val;
                     }
                 }
             }
-            if (typeof i === "object") i = JSON.stringify(i);
+            // 数据回写
+            if (typeof data === "object") data = JSON.stringify(data);
             if (this.isSurge || this.isLoon) {
-                $persistentStore.write(i, e);
+                $persistentStore.write(data, key);
             } else if (this.isQuanX) {
-                $prefs.setValueForKey(i, e);
+                $prefs.setValueForKey(data, key);
             } else if (this.isNode) {
-                this.node.fs.writeFileSync("./magic.json", i);
+                this.node.fs.writeFileSync("./magic.json", data);
             } else if (this.isJSBox) {
                 $file.write({
                     data: $data({
-                        string: i
+                        string: data
                     }),
                     path: "drive://MagicJS/magic.json"
                 });
             }
-            this.logDebug(`WRITE DATA [${e}]${!!s ? `[${s}]` : ""}(${typeof t})\n${JSON.stringify(t)}`);
-        }
-        del(e, t = "") {
-            this.logDebug(`DELETE KEY [${e}]${!!t ? `[${t}]` : ""}`);
-            this.write(e, null, t);
-        }
-        notify(e = this.scriptName, t = "", s = "", i = "") {
-            let o = e => {
-                let t = {};
-                if (this.isSurge || this.isQuanX || this.isLoon) {
-                    if (typeof e === "string") {
-                        if (this.isLoon) t = {
-                            openUrl: e
-                        }; else if (this.isQuanX) t = {
-                            "open-url": e
-                        }; else if (this.isSurge) t = {
-                            url: e
-                        };
-                    } else if (typeof e === "object") {
-                        let s = {
-                            Surge: {
-                                openUrl: "url",
-                                "open-url": "url"
-                            },
-                            Loon: {
-                                url: "openUrl",
-                                "open-url": "openUrl",
-                                "media-url": "mediaUrl"
-                            },
-                            QuantumultX: {
-                                url: "open-url",
-                                openUrl: "open-url",
-                                mediaUrl: "media-url"
-                            }
-                        };
-                        let i = Object.keys(e);
-                        for (let o = 0; o < i.length; o++) {
-                            if (!!s[this.platform][i[o]]) {
-                                t[s[this.platform][i[o]]] = e[i[o]];
-                            } else {
-                                t[i[o]] = e[i[o]];
-                            }
+            this.logDebug(`WRITE DATA [${key}]${!!session ? `[${session}]` : ""}(${typeof val})`+'\n'+`${JSON.stringify(val)}`);
+        }
+        del(key, session = "") {
+            this.logDebug(`DELETE KEY [${key}]${!!session ? `[${session}]` : ""}`);
+            this.write(key, null, session);
+        }
+        /**
+         * iOS系统通知
+         * @param {*} title 通知标题
+         * @param {*} subTitle 通知副标题
+         * @param {*} body 通知内容
+         * @param {*} opts 通知选项,目前支持传入超链接或Object
+         * Surge不支持通知选项,Loon和QuantumultX支持打开URL和多媒体通知
+         * opts "applestore://" 打开Apple Store
+         * opts "https://www.apple.com.cn/" 打开Apple.com.cn
+         * opts {'open-url': 'https://www.apple.com.cn/'} 打开Apple.com.cn
+         * opts {'open-url': 'https://www.apple.com.cn/', 'media-url': 'https://raw.githubusercontent.com/Orz-3/mini/master/Apple.png'} 打开Apple.com.cn,显示一个苹果Logo
+         */
+        notify(title = this.scriptName, subTitle = "", body = "", opts = "") {
+            let convertOptions = _opts => {
+                let newOpts = {};
+                if (typeof _opts === "string") {
+                    if(_opts.length > 0){
+                        if (this.isLoon){
+                            newOpts = {
+                                openUrl: _opts
+                            };
+                        }else if (this.isQuanX){
+                            newOpts = {
+                                "open-url": _opts
+                            };
+                        }else if (this.isSurge){
+                            newOpts = {
+                                url: _opts
+                            };
                         }
                     }
+                } else if (typeof _opts === "object") {
+                    if (this.isLoon) {
+                        newOpts["openUrl"] = !!_opts["open-url"] ? _opts["open-url"] : "";
+                        newOpts["mediaUrl"] = !!_opts["media-url"] ? _opts["media-url"] : "";
+                    } else if (this.isQuanX) {
+                        newOpts = !!_opts["open-url"] || !!_opts["media-url"] ? _opts : {};
+                    } else if (this.isSurge) {
+                        let openUrl = _opts["open-url"] || _opts["openUrl"];
+                        newOpts = openUrl ? {
+                            url: openUrl
+                        } : {};
+                    }
                 }
-                return t;
+                return newOpts;
             };
-            i = o(i);
-            this.logNotify(`title:${e}\nsubTitle:${t}\nbody:${s}\noptions:${typeof i === "object" ? JSON.stringify(i) : i}`);
+            opts = convertOptions(opts);
+            // 支持单个参数通知
             if (arguments.length == 1) {
-                e = this.scriptName;
-                t = "", s = arguments[0];
-            }
-            if (!!this._unifiedPushUrl) {
-                let i = encodeURI(`${e}/${t}${!!t ? "\n" : ""}${s}`);
-                this.get(`${this._unifiedPushUrl}/${i}`, () => {});
+                title = this.scriptName;
+                subTitle = "", body = arguments[0];
             }
-            if (this.isSurge || this.isLoon) {
-                $notification.post(e, t, s, i);
+            // 生成通知日志
+            this.logNotify(`title:${title}`+'\n'+`subTitle:${subTitle}`+'\n'+`body:${body}`+'\n'+`options:${typeof opts === "object" ? JSON.stringify(opts) : opts}`);
+            if (this.isSurge) {
+                $notification.post(title, subTitle, body, opts);
+            } else if (this.isLoon) {
+                if (!!opts) $notification.post(title, subTitle, body, opts); else $notification.post(title, subTitle, body);
             } else if (this.isQuanX) {
-                $notify(e, t, s, i);
+                $notify(title, subTitle, body, opts);
             } else if (this.isJSBox) {
-                let i = {
-                    title: e,
-                    body: !!t ? `${t}\n${s}` : s
+                let push = {
+                    title: title,
+                    body: !!subTitle ? `${subTitle}`+'\n'+`${body}` : body
                 };
-                $push.schedule(i);
+                $push.schedule(push);
+            }
+            // 跨设备统一推送
+            if (this._barkUrl && this._barkKey) {
+                this.notifyBark(title, subTitle, body);
             }
         }
-        log(e, t = "INFO") {
-            if (!(this.logLevels[this._logLevel] < this.logLevels[t.toUpperCase()])) console.log(`[${t}] [${this.scriptName}]\n${e}\n`);
+        /**
+         * iOS系统通知,仅在DEBUG模式下推送
+         * @param {*} title 通知标题
+         * @param {*} subTitle 通知副标题
+         * @param {*} body 通知内容
+         * @param {*} opts 通知选项,目前支持传入超链接或Object
+         * Surge不支持通知选项,Loon和QuantumultX支持打开URL和多媒体通知
+         * opts "applestore://" 打开Apple Store
+         * opts "https://www.apple.com.cn/" 打开Apple.com.cn
+         * opts {'open-url': 'https://www.apple.com.cn/'} 打开Apple.com.cn
+         * opts {'open-url': 'https://www.apple.com.cn/', 'media-url': 'https://raw.githubusercontent.com/Orz-3/mini/master/Apple.png'} 打开Apple.com.cn,显示一个苹果Logo
+         */
+        notifyDebug(title = this.scriptName, subTitle = "", body = "", opts = "") {
+            if (this.logLevel === "DEBUG") {
+                // 适配单个参数通知
+                if (arguments.length == 1) {
+                    title = this.scriptName;
+                    subTitle = "", body = arguments[0];
+                }
+                this.notify(title, subTitle, body, opts);
+            }
         }
-        logDebug(e) {
-            this.log(e, "DEBUG");
+        notifyBark(title = this.scriptName, subTitle = "", body = "", opts = "") {
+            let options = {
+                url: this._barkUrl,
+                headers: {
+                    "Content-Type": "application/json; charset=utf-8"
+                },
+                body: {
+                    title: title,
+                    body: subTitle ? `${subTitle}`+'\n'+`${body}` : body,
+                    device_key: this._barkKey
+                }
+            };
+            this.post(options, err => {});
+        }
+        log(msg, level = "INFO") {
+            if (!(this.logLevels[this._logLevel] < this.logLevels[level.toUpperCase()])) console.log(`[${level}] [${this.scriptName}]`+'\n'+`${msg}`+'\n');
+        }
+        logDebug(msg) {
+            this.log(msg, "DEBUG");
+        }
+        logInfo(msg) {
+            this.log(msg, "INFO");
         }
-        logInfo(e) {
-            this.log(e, "INFO");
+        logNotify(msg) {
+            this.log(msg, "NOTIFY");
         }
-        logNotify(e) {
-            this.log(e, "NOTIFY");
+        logWarning(msg) {
+            this.log(msg, "WARNING");
         }
-        logWarning(e) {
-            this.log(e, "WARNING");
+        logError(msg) {
+            this.log(msg, "ERROR");
         }
-        logError(e) {
-            this.log(e, "ERROR");
+        logRetry(msg) {
+            this.log(msg, "RETRY");
         }
-        adapterHttpOptions(e, t) {
-            let i = typeof e === "object" ? Object.assign({}, e) : {
-                url: e,
+        /**
+         * 对传入的Http Options根据不同环境进行适配
+         * @param {*} options
+         */
+        adapterHttpOptions(options, method) {
+            let _options = typeof options === "object" ? Object.assign({}, options) : {
+                url: options,
                 headers: {}
             };
-            if (i.hasOwnProperty("header") && !i.hasOwnProperty("headers")) {
-                i["headers"] = i["header"];
-                delete i["header"];
+            if (_options.hasOwnProperty("header") && !_options.hasOwnProperty("headers")) {
+                _options["headers"] = _options["header"];
+                delete _options["header"];
             }
-            if (typeof i.headers === "object" && !!s) {
-                for (let e in i.headers) {
-                    if (s[e]) {
-                        i.headers[s[e]] = i.headers[e];
-                        delete i.headers[e];
-                    }
-                }
+            // // 将HTTP/2头部header字段统一转成
+            // if (typeof _options.headers === "object" && !!s) {
+            //     for (let key in _options.headers) {
+            //         if (headerFieldMap[key]) {
+            //             _options.headers[headerFieldMap[key]] = _options.headers[key];
+            //             delete _options.headers[key];
+            //         }
+            //     }
+            // }
+            // 自动补完User-Agent,减少请求特征
+            if (!!!_options.headers || typeof _options.headers !== "object" || !!!_options.headers["User-Agent"] && !!!_options.headers["user-agent"]) {
+                if (!!!_options.headers || typeof _options.headers !== "object") _options.headers = {};
+                if (this.isNode) _options.headers["User-Agent"] = this.pcUserAgent; else _options.headers["User-Agent"] = this.iOSUserAgent;
             }
-            if (!!!i.headers || typeof i.headers !== "object" || !!!i.headers["User-Agent"]) {
-                if (!!!i.headers || typeof i.headers !== "object") i.headers = {};
-                if (this.isNode) i.headers["User-Agent"] = this.pcUserAgent; else i.headers["User-Agent"] = this.iOSUserAgent;
+            // 判断是否跳过脚本处理
+            let skipScripting = false;
+            if (typeof _options["opts"] === "object" && (_options["opts"]["hints"] === true || _options["opts"]["Skip-Scripting"] === true) || typeof _options["headers"] === "object" && _options["headers"]["X-Surge-Skip-Scripting"] === true) {
+                skipScripting = true;
             }
-            let o = false;
-            if (typeof i["opts"] === "object" && (i["opts"]["hints"] === true || i["opts"]["Skip-Scripting"] === true) || typeof i["headers"] === "object" && i["headers"]["X-Surge-Skip-Scripting"] === true) {
-                o = true;
-            }
-            if (!o) {
-                if (this.isSurge) i.headers["X-Surge-Skip-Scripting"] = false; else if (this.isLoon) i.headers["X-Requested-With"] = "XMLHttpRequest"; else if (this.isQuanX) {
-                    if (typeof i["opts"] !== "object") i.opts = {};
-                    i.opts["hints"] = false;
+            if (!skipScripting) {
+                if (this.isSurge) _options.headers["X-Surge-Skip-Scripting"] = false; else if (this.isLoon) _options.headers["X-Requested-With"] = "XMLHttpRequest"; else if (this.isQuanX) {
+                    if (typeof _options["opts"] !== "object") _options.opts = {};
+                    _options.opts["hints"] = false;
                 }
             }
-            if (!this.isSurge || o) delete i.headers["X-Surge-Skip-Scripting"];
-            if (!this.isQuanX && i.hasOwnProperty("opts")) delete i["opts"];
-            if (this.isQuanX && i.hasOwnProperty("opts")) delete i["opts"]["Skip-Scripting"];
-            if (t === "GET" && !this.isNode && !!i.body) {
-                let e = Object.keys(i.body).map(e => {
-                    if (typeof i.body === "undefined") return "";
-                    return `${encodeURIComponent(e)}=${encodeURIComponent(i.body[e])}`;
+            // 对请求数据做清理
+            if (!this.isSurge || skipScripting) delete _options.headers["X-Surge-Skip-Scripting"];
+            if (!this.isQuanX && _options.hasOwnProperty("opts")) delete _options["opts"];
+            if (this.isQuanX && _options.hasOwnProperty("opts")) delete _options["opts"]["Skip-Scripting"];
+            // GET请求将body转换成QueryString(beta)
+            if (method === "GET" && !this.isNode && !!_options.body) {
+                let qs = Object.keys(_options.body).map(key => {
+                    if (typeof _options.body === "undefined") return "";
+                    return `${encodeURIComponent(key)}=${encodeURIComponent(_options.body[key])}`;
                 }).join("&");
-                if (i.url.indexOf("?") < 0) i.url += "?";
-                if (i.url.lastIndexOf("&") + 1 != i.url.length && i.url.lastIndexOf("?") + 1 != i.url.length) i.url += "&";
-                i.url += e;
-                delete i.body;
+                if (_options.url.indexOf("?") < 0) _options.url += "?";
+                if (_options.url.lastIndexOf("&") + 1 != _options.url.length && _options.url.lastIndexOf("?") + 1 != _options.url.length) _options.url += "&";
+                _options.url += qs;
+                delete _options.body;
             }
+            // 适配多环境
             if (this.isQuanX) {
-                if (i.hasOwnProperty("body") && typeof i["body"] !== "string") i["body"] = JSON.stringify(i["body"]);
-                i["method"] = t;
+                if (_options.hasOwnProperty("body") && typeof _options["body"] !== "string") _options["body"] = JSON.stringify(_options["body"]);
+                _options["method"] = method;
             } else if (this.isNode) {
-                delete i.headers["Accept-Encoding"];
-                if (typeof i.body === "object") {
-                    if (t === "GET") {
-                        i.qs = i.body;
-                        delete i.body;
-                    } else if (t === "POST") {
-                        i["json"] = true;
-                        i.body = i.body;
+                delete _options.headers["Accept-Encoding"];
+                if (typeof _options.body === "object") {
+                    if (method === "GET") {
+                        _options.qs = _options.body;
+                        delete _options.body;
+                    } else if (method === "POST") {
+                        _options["json"] = true;
+                        _options.body = _options.body;
                     }
                 }
             } else if (this.isJSBox) {
-                i["header"] = i["headers"];
-                delete i["headers"];
+                _options["header"] = _options["headers"];
+                delete _options["headers"];
+            }
+            return _options;
+        }
+        adapterHttpResponse(resp) {
+            let _resp = {
+                body: resp.body,
+                headers: resp.headers,
+                json: () => {
+                    return JSON.parse(_resp.body);
+                }
+            };
+            if (resp.hasOwnProperty("statusCode") && resp.statusCode) {
+                _resp["status"] = resp.statusCode;
             }
-            return i;
+            return _resp;
         }
-        get(e, t) {
-            let s = this.adapterHttpOptions(e, "GET");
-            this.logDebug(`HTTP GET: ${JSON.stringify(s)}`);
+        /**
+         * Http客户端发起GET请求
+         * @param {*} options
+         * @param {*} callback
+         * options可配置参数headers和opts,用于判断由脚本发起的http请求是否跳过脚本处理。
+         * 支持Surge和Quantumult X两种配置方式。
+         * 以下几种配置会跳过脚本处理,options没有opts或opts的值不匹配,则不跳过脚本处理
+         * {opts:{"hints": true}}
+         * {opts:{"Skip-Scripting": true}}
+         * {headers: {"X-Surge-Skip-Scripting": true}}
+         */
+        get(options, callback) {
+            let _options = this.adapterHttpOptions(options, "GET");
+            this.logDebug(`HTTP GET: ${JSON.stringify(_options)}`);
             if (this.isSurge || this.isLoon) {
-                $httpClient.get(s, t);
+                $httpClient.get(_options, callback);
             } else if (this.isQuanX) {
-                $task.fetch(s).then(e => {
-                    e["status"] = e.statusCode;
-                    t(null, e, e.body);
-                }, e => t(e.error, null, null));
+                $task.fetch(_options).then(resp => {
+                    resp["status"] = resp.statusCode;
+                    callback(null, resp, resp.body);
+                }, reason => callback(reason.error, null, null));
             } else if (this.isNode) {
-                return this.node.request.get(s, t);
+                this.node.request.get(_options, (err, resp, data) => {
+                    resp = this.adapterHttpResponse(resp);
+                    callback(err, resp, data);
+                });
             } else if (this.isJSBox) {
-                s["handler"] = e => {
-                    let s = e.error ? JSON.stringify(e.error) : undefined;
-                    let i = typeof e.data === "object" ? JSON.stringify(e.data) : e.data;
-                    t(s, e.response, i);
+                _options["handler"] = resp => {
+                    let err = resp.error ? JSON.stringify(resp.error) : undefined;
+                    let data = typeof resp.data === "object" ? JSON.stringify(resp.data) : resp.data;
+                    callback(err, resp.response, data);
                 };
-                $http.get(s);
+                $http.get(_options);
             }
         }
-        post(e, t) {
-            let s = this.adapterHttpOptions(e, "POST");
-            this.logDebug(`HTTP POST: ${JSON.stringify(s)}`);
+        getPromise(options) {
+            return new Promise((resolve, reject) => {
+                magicJS.get(options, (err, resp) => {
+                    if (err) {
+                        reject(err);
+                    } else {
+                        resolve(resp);
+                    }
+                });
+            });
+        }
+        /**
+         * Http客户端发起POST请求
+         * @param {*} options
+         * @param {*} callback
+         * options可配置参数headers和opts,用于判断由脚本发起的http请求是否跳过脚本处理。
+         * 支持Surge和Quantumult X两种配置方式。
+         * 以下几种配置会跳过脚本处理,options没有opts或opts的值不匹配,则不跳过脚本处理
+         * {opts:{"hints": true}}
+         * {opts:{"Skip-Scripting": true}}
+         * {headers: {"X-Surge-Skip-Scripting": true}}
+         */
+        post(options, callback) {
+            let _options = this.adapterHttpOptions(options, "POST");
+            this.logDebug(`HTTP POST: ${JSON.stringify(_options)}`);
             if (this.isSurge || this.isLoon) {
-                $httpClient.post(s, t);
+                $httpClient.post(_options, callback);
             } else if (this.isQuanX) {
-                $task.fetch(s).then(e => {
-                    e["status"] = e.statusCode;
-                    t(null, e, e.body);
-                }, e => {
-                    t(e.error, null, null);
+                $task.fetch(_options).then(resp => {
+                    resp["status"] = resp.statusCode;
+                    callback(null, resp, resp.body);
+                }, reason => {
+                    callback(reason.error, null, null);
                 });
             } else if (this.isNode) {
-                return this.node.request.post(s, t);
+                let resp = this.node.request.post(_options, callback);
+                resp["status"] = resp.statusCode;
+                delete resp.statusCode;
             } else if (this.isJSBox) {
-                s["handler"] = e => {
-                    let s = e.error ? JSON.stringify(e.error) : undefined;
-                    let i = typeof e.data === "object" ? JSON.stringify(e.data) : e.data;
-                    t(s, e.response, i);
+                _options["handler"] = resp => {
+                    let err = resp.error ? JSON.stringify(resp.error) : undefined;
+                    let data = typeof resp.data === "object" ? JSON.stringify(resp.data) : resp.data;
+                    callback(err, resp.response, data);
                 };
-                $http.post(s);
+                $http.post(_options, {});
             }
         }
-        done(e = {}) {
+        done(value = {}) {
+            this._endTime = Date.now();
+            let span = (this._endTime - this._startTime) / 1e3;
+            magicJS.logDebug(`SCRIPT COMPLETED: ${span}S.`);
             if (typeof $done !== "undefined") {
-                $done(e);
+                $done(value);
             }
         }
-        isToday(e) {
-            if (e == null) {
+        isToday(day) {
+            if (day == null) {
                 return false;
             } else {
-                let t = new Date();
-                if (typeof e == "string") {
-                    e = new Date(e);
+                let today = new Date();
+                if (typeof day == "string") {
+                    day = new Date(day);
                 }
-                if (t.getFullYear() == e.getFullYear() && t.getMonth() == e.getMonth() && t.getDay() == e.getDay()) {
+                if (today.getFullYear() == day.getFullYear() && today.getMonth() == day.getMonth() && today.getDay() == day.getDay()) {
                     return true;
                 } else {
                     return false;
                 }
             }
         }
-        isNumber(e) {
-            return parseFloat(e).toString() === "NaN" ? false : true;
+        isNumber(val) {
+            return parseFloat(val).toString() === "NaN" ? false : true;
         }
-        attempt(e, t = null) {
-            return e.then(e => {
-                return [ null, e ];
-            }).catch(e => {
-                this.logError(e);
-                return [ e, t ];
+        /**
+         * 对await执行中出现的异常进行捕获并返回,避免写过多的try catch语句
+         * 示例:let [err,val] = await magicJS.attempt(func(), 'defaultvalue');
+         * 或者:let [err, [val1,val2]] = await magicJS.attempt(func(), ['defaultvalue1', 'defaultvalue2']);
+         * @param {*} promise Promise 对象
+         * @param {*} defaultValue 出现异常时返回的默认值
+         * @returns 返回两个值,第一个值为异常,第二个值为执行结果
+         */
+        attempt(promise, defaultValue = null) {
+            return promise.then(args => {
+                return [ null, args ];
+            }).catch(ex => {
+                this.logError(ex);
+                return [ ex, defaultValue ];
             });
         }
-        retry(e, t = 5, s = 0, i = null) {
-            return (...o) => {
-                return new Promise((r, n) => {
-                    function a(...o) {
-                        Promise.resolve().then(() => e.apply(this, o)).then(e => {
-                            if (typeof i === "function") {
-                                Promise.resolve().then(() => i(e)).then(() => {
-                                    r(e);
-                                }).catch(e => {
-                                    this.logError(e);
-                                    if (t >= 1 && s > 0) {
-                                        setTimeout(() => a.apply(this, o), s);
-                                    } else if (t >= 1) {
-                                        a.apply(this, o);
+        /**
+         * 重试方法
+         * @param {*} fn 需要重试的函数
+         * @param {number} [retries=5] 重试次数
+         * @param {number} [interval=0] 每次重试间隔
+         * @param {function} [callback=null] 函数没有异常时的回调,会将函数执行结果result传入callback,根据result的值进行判断,如果需要再次重试,在callback中throw一个异常,适用于函数本身没有异常但仍需重试的情况。
+         * @returns 返回一个Promise对象
+         */
+        retry(fn, retries = 5, interval = 0, callback = null) {
+            return (...args) => {
+                return new Promise((resolve, reject) => {
+                    function _retry(...args) {
+                        Promise.resolve().then(() => fn.apply(this, args)).then(result => {
+                            if (typeof callback === "function") {
+                                Promise.resolve().then(() => callback(result)).then(() => {
+                                    resolve(result);
+                                }).catch(ex => {
+                                    if (retries >= 1) {
+                                        if (interval > 0) setTimeout(() => _retry.apply(this, args), interval); else _retry.apply(this, args);
                                     } else {
-                                        n(e);
+                                        reject(ex);
                                     }
-                                    t--;
+                                    retries--;
                                 });
                             } else {
-                                r(e);
+                                resolve(result);
                             }
-                        }).catch(e => {
-                            this.logError(e);
-                            if (t >= 1 && s > 0) {
-                                setTimeout(() => a.apply(this, o), s);
-                            } else if (t >= 1) {
-                                a.apply(this, o);
+                        }).catch(ex => {
+                            this.logRetry(ex);
+                            if (retries >= 1 && interval > 0) {
+                                setTimeout(() => _retry.apply(this, args), interval);
+                            } else if (retries >= 1) {
+                                _retry.apply(this, args);
                             } else {
-                                n(e);
+                                reject(ex);
                             }
-                            t--;
+                            retries--;
                         });
                     }
-                    a.apply(this, o);
+                    _retry.apply(this, args);
                 });
             };
         }
-        formatTime(e, t = "yyyy-MM-dd hh:mm:ss") {
-            var s = {
-                "M+": e.getMonth() + 1,
-                "d+": e.getDate(),
-                "h+": e.getHours(),
-                "m+": e.getMinutes(),
-                "s+": e.getSeconds(),
-                "q+": Math.floor((e.getMonth() + 3) / 3),
-                S: e.getMilliseconds()
+        formatTime(time, fmt = "yyyy-MM-dd hh:mm:ss") {
+            var o = {
+                "M+": time.getMonth() + 1,
+                "d+": time.getDate(),
+                "h+": time.getHours(),
+                "m+": time.getMinutes(),
+                "s+": time.getSeconds(),
+                "q+": Math.floor((time.getMonth() + 3) / 3),
+                S: time.getMilliseconds()
             };
-            if (/(y+)/.test(t)) t = t.replace(RegExp.$1, (e.getFullYear() + "").substr(4 - RegExp.$1.length));
-            for (let e in s) if (new RegExp("(" + e + ")").test(t)) t = t.replace(RegExp.$1, RegExp.$1.length == 1 ? s[e] : ("00" + s[e]).substr(("" + s[e]).length));
-            return t;
+            if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (time.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;
         }
         now() {
             return this.formatTime(new Date(), "yyyy-MM-dd hh:mm:ss");
@@ -548,8 +707,8 @@ function MagicJS(e = "MagicJS", t = "INFO") {
         today() {
             return this.formatTime(new Date(), "yyyy-MM-dd");
         }
-        sleep(e) {
-            return new Promise(t => setTimeout(t, e));
+        sleep(time) {
+            return new Promise(resolve => setTimeout(resolve, time));
         }
-    }(e);
+    }(scriptName);
 }

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
Scripts/util/MagicJS.min.js


Некоторые файлы не были показаны из-за большого количества измененных файлов