diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..25bcb91d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +node_modules/* +.DS_Store + +.vscode +.idea + +test/* +tncj/* +*/unblock/* +*.private.* +*.dat +*copy.js \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index 22ea5aadc..6b1caa4ee 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,6 @@ { + "quoteProps": "consistent", "semi": false, - "arrowParens": "always", "singleQuote": true, - "printWidth": 400 + "trailingComma": "none" } diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index d88f53ef1..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "editor.formatOnPaste": true, - "editor.formatOnSave": true, - "editor.formatOnType": true -} diff --git a/10000/10000.cookie.js b/10000/10000.cookie.js index 3c93746dc..69ddd80f9 100644 --- a/10000/10000.cookie.js +++ b/10000/10000.cookie.js @@ -1,25 +1,14 @@ const cookieName = '电信营业厅' -const cookieKey = 'chavy_cookie_10000' -const mobileKey = 'chavy_mobile_10000' +const KEY_signheader = 'chavy_signheader_10000' +const KEY_signbody = 'chavy_signbody_10000' +const KEY_mobile = 'chavy_mobile_10000' const chavy = init() -if (this.$request && this.$request.headers) { - const cookieVal = $request.headers['Cookie'] - if (cookieVal) { - if (chavy.setdata(cookieVal, cookieKey)) { - chavy.msg(`${cookieName}`, '获取Cookie: 成功', '') - chavy.log(`[${cookieName}] 获取Cookie: 成功, cookie: ${cookieVal}`) - } - } -} -if (this.$response) { - chavy.log(JSON.parse($response.body).data.userInfo.mobile) - const mobileVal = JSON.parse($response.body).data.userInfo.mobile - if (mobileVal) { - if (chavy.setdata(mobileVal, mobileKey)) { - chavy.msg(`${cookieName}`, `获取号码: 成功 (${mobileVal})`, ``) - chavy.log(`[${cookieName}] 获取号码: 成功, 号码: ${mobileVal}`) - } - } +if (this.$request && this.$request.headers && this.$request.body) { + const VAL_signheader = JSON.stringify($request.headers) + const VAL_signbody = this.$request.body + if (VAL_signheader) chavy.setdata(VAL_signheader, KEY_signheader) + if (VAL_signbody) chavy.setdata(VAL_signbody, KEY_signbody) + chavy.msg(cookieName, `获取Cookie: 成功`, ``) } function init() { diff --git a/10000/10000.js b/10000/10000.js index 9dd74f5e6..61d529def 100644 --- a/10000/10000.js +++ b/10000/10000.js @@ -1,81 +1,138 @@ -const cookieName = '电信营业厅' -const cookieKey = 'chavy_cookie_10000' -const mobileKey = 'chavy_mobile_10000' -const chavy = init() -const cookieVal = chavy.getdata(cookieKey) -const mobileVal = chavy.getdata(mobileKey) +// prettier-ignore +!function (t, r) { "object" == typeof exports ? module.exports = exports = r() : "function" == typeof define && define.amd ? define([], r) : t.CryptoJS = r() }(this, function () { + var t = t || function (t, r) { var e = Object.create || function () { function t() { } return function (r) { var e; return t.prototype = r, e = new t, t.prototype = null, e } }(), i = {}, n = i.lib = {}, o = n.Base = function () { return { extend: function (t) { var r = e(this); return t && r.mixIn(t), r.hasOwnProperty("init") && this.init !== r.init || (r.init = function () { r.$super.init.apply(this, arguments) }), r.init.prototype = r, r.$super = this, r }, create: function () { var t = this.extend(); return t.init.apply(t, arguments), t }, init: function () { }, mixIn: function (t) { for (var r in t) t.hasOwnProperty(r) && (this[r] = t[r]); t.hasOwnProperty("toString") && (this.toString = t.toString) }, clone: function () { return this.init.prototype.extend(this) } } }(), s = n.WordArray = o.extend({ init: function (t, e) { t = this.words = t || [], e != r ? this.sigBytes = e : this.sigBytes = 4 * t.length }, toString: function (t) { return (t || c).stringify(this) }, concat: function (t) { var r = this.words, e = t.words, i = this.sigBytes, n = t.sigBytes; if (this.clamp(), i % 4) for (var o = 0; o < n; o++) { var s = e[o >>> 2] >>> 24 - o % 4 * 8 & 255; r[i + o >>> 2] |= s << 24 - (i + o) % 4 * 8 } else for (var o = 0; o < n; o += 4)r[i + o >>> 2] = e[o >>> 2]; return this.sigBytes += n, this }, clamp: function () { var r = this.words, e = this.sigBytes; r[e >>> 2] &= 4294967295 << 32 - e % 4 * 8, r.length = t.ceil(e / 4) }, clone: function () { var t = o.clone.call(this); return t.words = this.words.slice(0), t }, random: function (r) { for (var e, i = [], n = function (r) { var r = r, e = 987654321, i = 4294967295; return function () { e = 36969 * (65535 & e) + (e >> 16) & i, r = 18e3 * (65535 & r) + (r >> 16) & i; var n = (e << 16) + r & i; return n /= 4294967296, n += .5, n * (t.random() > .5 ? 1 : -1) } }, o = 0; o < r; o += 4) { var a = n(4294967296 * (e || t.random())); e = 987654071 * a(), i.push(4294967296 * a() | 0) } return new s.init(i, r) } }), a = i.enc = {}, c = a.Hex = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n++) { var o = r[n >>> 2] >>> 24 - n % 4 * 8 & 255; i.push((o >>> 4).toString(16)), i.push((15 & o).toString(16)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i += 2)e[i >>> 3] |= parseInt(t.substr(i, 2), 16) << 24 - i % 8 * 4; return new s.init(e, r / 2) } }, h = a.Latin1 = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n++) { var o = r[n >>> 2] >>> 24 - n % 4 * 8 & 255; i.push(String.fromCharCode(o)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i++)e[i >>> 2] |= (255 & t.charCodeAt(i)) << 24 - i % 4 * 8; return new s.init(e, r) } }, l = a.Utf8 = { stringify: function (t) { try { return decodeURIComponent(escape(h.stringify(t))) } catch (t) { throw new Error("Malformed UTF-8 data") } }, parse: function (t) { return h.parse(unescape(encodeURIComponent(t))) } }, f = n.BufferedBlockAlgorithm = o.extend({ reset: function () { this._data = new s.init, this._nDataBytes = 0 }, _append: function (t) { "string" == typeof t && (t = l.parse(t)), this._data.concat(t), this._nDataBytes += t.sigBytes }, _process: function (r) { var e = this._data, i = e.words, n = e.sigBytes, o = this.blockSize, a = 4 * o, c = n / a; c = r ? t.ceil(c) : t.max((0 | c) - this._minBufferSize, 0); var h = c * o, l = t.min(4 * h, n); if (h) { for (var f = 0; f < h; f += o)this._doProcessBlock(i, f); var u = i.splice(0, h); e.sigBytes -= l } return new s.init(u, l) }, clone: function () { var t = o.clone.call(this); return t._data = this._data.clone(), t }, _minBufferSize: 0 }), u = (n.Hasher = f.extend({ cfg: o.extend(), init: function (t) { this.cfg = this.cfg.extend(t), this.reset() }, reset: function () { f.reset.call(this), this._doReset() }, update: function (t) { return this._append(t), this._process(), this }, finalize: function (t) { t && this._append(t); var r = this._doFinalize(); return r }, blockSize: 16, _createHelper: function (t) { return function (r, e) { return new t.init(e).finalize(r) } }, _createHmacHelper: function (t) { return function (r, e) { return new u.HMAC.init(t, e).finalize(r) } } }), i.algo = {}); return i }(Math); return function () { function r(t, r, e) { for (var i = [], o = 0, s = 0; s < r; s++)if (s % 4) { var a = e[t.charCodeAt(s - 1)] << s % 4 * 2, c = e[t.charCodeAt(s)] >>> 6 - s % 4 * 2; i[o >>> 2] |= (a | c) << 24 - o % 4 * 8, o++ } return n.create(i, o) } var e = t, i = e.lib, n = i.WordArray, o = e.enc; o.Base64 = { stringify: function (t) { var r = t.words, e = t.sigBytes, i = this._map; t.clamp(); for (var n = [], o = 0; o < e; o += 3)for (var s = r[o >>> 2] >>> 24 - o % 4 * 8 & 255, a = r[o + 1 >>> 2] >>> 24 - (o + 1) % 4 * 8 & 255, c = r[o + 2 >>> 2] >>> 24 - (o + 2) % 4 * 8 & 255, h = s << 16 | a << 8 | c, l = 0; l < 4 && o + .75 * l < e; l++)n.push(i.charAt(h >>> 6 * (3 - l) & 63)); var f = i.charAt(64); if (f) for (; n.length % 4;)n.push(f); return n.join("") }, parse: function (t) { var e = t.length, i = this._map, n = this._reverseMap; if (!n) { n = this._reverseMap = []; for (var o = 0; o < i.length; o++)n[i.charCodeAt(o)] = o } var s = i.charAt(64); if (s) { var a = t.indexOf(s); a !== -1 && (e = a) } return r(t, e, n) }, _map: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" } }(), function (r) { function e(t, r, e, i, n, o, s) { var a = t + (r & e | ~r & i) + n + s; return (a << o | a >>> 32 - o) + r } function i(t, r, e, i, n, o, s) { var a = t + (r & i | e & ~i) + n + s; return (a << o | a >>> 32 - o) + r } function n(t, r, e, i, n, o, s) { var a = t + (r ^ e ^ i) + n + s; return (a << o | a >>> 32 - o) + r } function o(t, r, e, i, n, o, s) { var a = t + (e ^ (r | ~i)) + n + s; return (a << o | a >>> 32 - o) + r } var s = t, a = s.lib, c = a.WordArray, h = a.Hasher, l = s.algo, f = []; !function () { for (var t = 0; t < 64; t++)f[t] = 4294967296 * r.abs(r.sin(t + 1)) | 0 }(); var u = l.MD5 = h.extend({ _doReset: function () { this._hash = new c.init([1732584193, 4023233417, 2562383102, 271733878]) }, _doProcessBlock: function (t, r) { for (var s = 0; s < 16; s++) { var a = r + s, c = t[a]; t[a] = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8) } var h = this._hash.words, l = t[r + 0], u = t[r + 1], d = t[r + 2], v = t[r + 3], p = t[r + 4], _ = t[r + 5], y = t[r + 6], g = t[r + 7], B = t[r + 8], w = t[r + 9], k = t[r + 10], S = t[r + 11], m = t[r + 12], x = t[r + 13], b = t[r + 14], H = t[r + 15], z = h[0], A = h[1], C = h[2], D = h[3]; z = e(z, A, C, D, l, 7, f[0]), D = e(D, z, A, C, u, 12, f[1]), C = e(C, D, z, A, d, 17, f[2]), A = e(A, C, D, z, v, 22, f[3]), z = e(z, A, C, D, p, 7, f[4]), D = e(D, z, A, C, _, 12, f[5]), C = e(C, D, z, A, y, 17, f[6]), A = e(A, C, D, z, g, 22, f[7]), z = e(z, A, C, D, B, 7, f[8]), D = e(D, z, A, C, w, 12, f[9]), C = e(C, D, z, A, k, 17, f[10]), A = e(A, C, D, z, S, 22, f[11]), z = e(z, A, C, D, m, 7, f[12]), D = e(D, z, A, C, x, 12, f[13]), C = e(C, D, z, A, b, 17, f[14]), A = e(A, C, D, z, H, 22, f[15]), z = i(z, A, C, D, u, 5, f[16]), D = i(D, z, A, C, y, 9, f[17]), C = i(C, D, z, A, S, 14, f[18]), A = i(A, C, D, z, l, 20, f[19]), z = i(z, A, C, D, _, 5, f[20]), D = i(D, z, A, C, k, 9, f[21]), C = i(C, D, z, A, H, 14, f[22]), A = i(A, C, D, z, p, 20, f[23]), z = i(z, A, C, D, w, 5, f[24]), D = i(D, z, A, C, b, 9, f[25]), C = i(C, D, z, A, v, 14, f[26]), A = i(A, C, D, z, B, 20, f[27]), z = i(z, A, C, D, x, 5, f[28]), D = i(D, z, A, C, d, 9, f[29]), C = i(C, D, z, A, g, 14, f[30]), A = i(A, C, D, z, m, 20, f[31]), z = n(z, A, C, D, _, 4, f[32]), D = n(D, z, A, C, B, 11, f[33]), C = n(C, D, z, A, S, 16, f[34]), A = n(A, C, D, z, b, 23, f[35]), z = n(z, A, C, D, u, 4, f[36]), D = n(D, z, A, C, p, 11, f[37]), C = n(C, D, z, A, g, 16, f[38]), A = n(A, C, D, z, k, 23, f[39]), z = n(z, A, C, D, x, 4, f[40]), D = n(D, z, A, C, l, 11, f[41]), C = n(C, D, z, A, v, 16, f[42]), A = n(A, C, D, z, y, 23, f[43]), z = n(z, A, C, D, w, 4, f[44]), D = n(D, z, A, C, m, 11, f[45]), C = n(C, D, z, A, H, 16, f[46]), A = n(A, C, D, z, d, 23, f[47]), z = o(z, A, C, D, l, 6, f[48]), D = o(D, z, A, C, g, 10, f[49]), C = o(C, D, z, A, b, 15, f[50]), A = o(A, C, D, z, _, 21, f[51]), z = o(z, A, C, D, m, 6, f[52]), D = o(D, z, A, C, v, 10, f[53]), C = o(C, D, z, A, k, 15, f[54]), A = o(A, C, D, z, u, 21, f[55]), z = o(z, A, C, D, B, 6, f[56]), D = o(D, z, A, C, H, 10, f[57]), C = o(C, D, z, A, y, 15, f[58]), A = o(A, C, D, z, x, 21, f[59]), z = o(z, A, C, D, p, 6, f[60]), D = o(D, z, A, C, S, 10, f[61]), C = o(C, D, z, A, d, 15, f[62]), A = o(A, C, D, z, w, 21, f[63]), h[0] = h[0] + z | 0, h[1] = h[1] + A | 0, h[2] = h[2] + C | 0, h[3] = h[3] + D | 0 }, _doFinalize: function () { var t = this._data, e = t.words, i = 8 * this._nDataBytes, n = 8 * t.sigBytes; e[n >>> 5] |= 128 << 24 - n % 32; var o = r.floor(i / 4294967296), s = i; e[(n + 64 >>> 9 << 4) + 15] = 16711935 & (o << 8 | o >>> 24) | 4278255360 & (o << 24 | o >>> 8), e[(n + 64 >>> 9 << 4) + 14] = 16711935 & (s << 8 | s >>> 24) | 4278255360 & (s << 24 | s >>> 8), t.sigBytes = 4 * (e.length + 1), this._process(); for (var a = this._hash, c = a.words, h = 0; h < 4; h++) { var l = c[h]; c[h] = 16711935 & (l << 8 | l >>> 24) | 4278255360 & (l << 24 | l >>> 8) } return a }, clone: function () { var t = h.clone.call(this); return t._hash = this._hash.clone(), t } }); s.MD5 = h._createHelper(u), s.HmacMD5 = h._createHmacHelper(u) }(Math), function () { var r = t, e = r.lib, i = e.WordArray, n = e.Hasher, o = r.algo, s = [], a = o.SHA1 = n.extend({ _doReset: function () { this._hash = new i.init([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], a = e[3], c = e[4], h = 0; h < 80; h++) { if (h < 16) s[h] = 0 | t[r + h]; else { var l = s[h - 3] ^ s[h - 8] ^ s[h - 14] ^ s[h - 16]; s[h] = l << 1 | l >>> 31 } var f = (i << 5 | i >>> 27) + c + s[h]; f += h < 20 ? (n & o | ~n & a) + 1518500249 : h < 40 ? (n ^ o ^ a) + 1859775393 : h < 60 ? (n & o | n & a | o & a) - 1894007588 : (n ^ o ^ a) - 899497514, c = a, a = o, o = n << 30 | n >>> 2, n = i, i = f } e[0] = e[0] + i | 0, e[1] = e[1] + n | 0, e[2] = e[2] + o | 0, e[3] = e[3] + a | 0, e[4] = e[4] + c | 0 }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; return r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 64 >>> 9 << 4) + 14] = Math.floor(e / 4294967296), r[(i + 64 >>> 9 << 4) + 15] = e, t.sigBytes = 4 * r.length, this._process(), this._hash }, clone: function () { var t = n.clone.call(this); return t._hash = this._hash.clone(), t } }); r.SHA1 = n._createHelper(a), r.HmacSHA1 = n._createHmacHelper(a) }(), function (r) { var e = t, i = e.lib, n = i.WordArray, o = i.Hasher, s = e.algo, a = [], c = []; !function () { function t(t) { for (var e = r.sqrt(t), i = 2; i <= e; i++)if (!(t % i)) return !1; return !0 } function e(t) { return 4294967296 * (t - (0 | t)) | 0 } for (var i = 2, n = 0; n < 64;)t(i) && (n < 8 && (a[n] = e(r.pow(i, .5))), c[n] = e(r.pow(i, 1 / 3)), n++), i++ }(); var h = [], l = s.SHA256 = o.extend({ _doReset: function () { this._hash = new n.init(a.slice(0)) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], s = e[3], a = e[4], l = e[5], f = e[6], u = e[7], d = 0; d < 64; d++) { if (d < 16) h[d] = 0 | t[r + d]; else { var v = h[d - 15], p = (v << 25 | v >>> 7) ^ (v << 14 | v >>> 18) ^ v >>> 3, _ = h[d - 2], y = (_ << 15 | _ >>> 17) ^ (_ << 13 | _ >>> 19) ^ _ >>> 10; h[d] = p + h[d - 7] + y + h[d - 16] } var g = a & l ^ ~a & f, B = i & n ^ i & o ^ n & o, w = (i << 30 | i >>> 2) ^ (i << 19 | i >>> 13) ^ (i << 10 | i >>> 22), k = (a << 26 | a >>> 6) ^ (a << 21 | a >>> 11) ^ (a << 7 | a >>> 25), S = u + k + g + c[d] + h[d], m = w + B; u = f, f = l, l = a, a = s + S | 0, s = o, o = n, n = i, i = S + m | 0 } e[0] = e[0] + i | 0, e[1] = e[1] + n | 0, e[2] = e[2] + o | 0, e[3] = e[3] + s | 0, e[4] = e[4] + a | 0, e[5] = e[5] + l | 0, e[6] = e[6] + f | 0, e[7] = e[7] + u | 0 }, _doFinalize: function () { var t = this._data, e = t.words, i = 8 * this._nDataBytes, n = 8 * t.sigBytes; return e[n >>> 5] |= 128 << 24 - n % 32, e[(n + 64 >>> 9 << 4) + 14] = r.floor(i / 4294967296), e[(n + 64 >>> 9 << 4) + 15] = i, t.sigBytes = 4 * e.length, this._process(), this._hash }, clone: function () { var t = o.clone.call(this); return t._hash = this._hash.clone(), t } }); e.SHA256 = o._createHelper(l), e.HmacSHA256 = o._createHmacHelper(l) }(Math), function () { function r(t) { return t << 8 & 4278255360 | t >>> 8 & 16711935 } var e = t, i = e.lib, n = i.WordArray, o = e.enc; o.Utf16 = o.Utf16BE = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n += 2) { var o = r[n >>> 2] >>> 16 - n % 4 * 8 & 65535; i.push(String.fromCharCode(o)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i++)e[i >>> 1] |= t.charCodeAt(i) << 16 - i % 2 * 16; return n.create(e, 2 * r) } }; o.Utf16LE = { stringify: function (t) { for (var e = t.words, i = t.sigBytes, n = [], o = 0; o < i; o += 2) { var s = r(e[o >>> 2] >>> 16 - o % 4 * 8 & 65535); n.push(String.fromCharCode(s)) } return n.join("") }, parse: function (t) { for (var e = t.length, i = [], o = 0; o < e; o++)i[o >>> 1] |= r(t.charCodeAt(o) << 16 - o % 2 * 16); return n.create(i, 2 * e) } } }(), function () { if ("function" == typeof ArrayBuffer) { var r = t, e = r.lib, i = e.WordArray, n = i.init, o = i.init = function (t) { if (t instanceof ArrayBuffer && (t = new Uint8Array(t)), (t instanceof Int8Array || "undefined" != typeof Uint8ClampedArray && t instanceof Uint8ClampedArray || t instanceof Int16Array || t instanceof Uint16Array || t instanceof Int32Array || t instanceof Uint32Array || t instanceof Float32Array || t instanceof Float64Array) && (t = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), t instanceof Uint8Array) { for (var r = t.byteLength, e = [], i = 0; i < r; i++)e[i >>> 2] |= t[i] << 24 - i % 4 * 8; n.call(this, e, r) } else n.apply(this, arguments) }; o.prototype = i } }(), function (r) { function e(t, r, e) { return t ^ r ^ e } function i(t, r, e) { return t & r | ~t & e } function n(t, r, e) { return (t | ~r) ^ e } function o(t, r, e) { return t & e | r & ~e } function s(t, r, e) { return t ^ (r | ~e) } function a(t, r) { return t << r | t >>> 32 - r } var c = t, h = c.lib, l = h.WordArray, f = h.Hasher, u = c.algo, d = l.create([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]), v = l.create([5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]), p = l.create([11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6]), _ = l.create([8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]), y = l.create([0, 1518500249, 1859775393, 2400959708, 2840853838]), g = l.create([1352829926, 1548603684, 1836072691, 2053994217, 0]), B = u.RIPEMD160 = f.extend({ _doReset: function () { this._hash = l.create([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) }, _doProcessBlock: function (t, r) { for (var c = 0; c < 16; c++) { var h = r + c, l = t[h]; t[h] = 16711935 & (l << 8 | l >>> 24) | 4278255360 & (l << 24 | l >>> 8) } var f, u, B, w, k, S, m, x, b, H, z = this._hash.words, A = y.words, C = g.words, D = d.words, R = v.words, E = p.words, M = _.words; S = f = z[0], m = u = z[1], x = B = z[2], b = w = z[3], H = k = z[4]; for (var F, c = 0; c < 80; c += 1)F = f + t[r + D[c]] | 0, F += c < 16 ? e(u, B, w) + A[0] : c < 32 ? i(u, B, w) + A[1] : c < 48 ? n(u, B, w) + A[2] : c < 64 ? o(u, B, w) + A[3] : s(u, B, w) + A[4], F |= 0, F = a(F, E[c]), F = F + k | 0, f = k, k = w, w = a(B, 10), B = u, u = F, F = S + t[r + R[c]] | 0, F += c < 16 ? s(m, x, b) + C[0] : c < 32 ? o(m, x, b) + C[1] : c < 48 ? n(m, x, b) + C[2] : c < 64 ? i(m, x, b) + C[3] : e(m, x, b) + C[4], F |= 0, F = a(F, M[c]), F = F + H | 0, S = H, H = b, b = a(x, 10), x = m, m = F; F = z[1] + B + b | 0, z[1] = z[2] + w + H | 0, z[2] = z[3] + k + S | 0, z[3] = z[4] + f + m | 0, z[4] = z[0] + u + x | 0, z[0] = F }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 64 >>> 9 << 4) + 14] = 16711935 & (e << 8 | e >>> 24) | 4278255360 & (e << 24 | e >>> 8), t.sigBytes = 4 * (r.length + 1), this._process(); for (var n = this._hash, o = n.words, s = 0; s < 5; s++) { var a = o[s]; o[s] = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8) } return n }, clone: function () { var t = f.clone.call(this); return t._hash = this._hash.clone(), t } }); c.RIPEMD160 = f._createHelper(B), c.HmacRIPEMD160 = f._createHmacHelper(B) }(Math), function () { var r = t, e = r.lib, i = e.Base, n = r.enc, o = n.Utf8, s = r.algo; s.HMAC = i.extend({ init: function (t, r) { t = this._hasher = new t.init, "string" == typeof r && (r = o.parse(r)); var e = t.blockSize, i = 4 * e; r.sigBytes > i && (r = t.finalize(r)), r.clamp(); for (var n = this._oKey = r.clone(), s = this._iKey = r.clone(), a = n.words, c = s.words, h = 0; h < e; h++)a[h] ^= 1549556828, c[h] ^= 909522486; n.sigBytes = s.sigBytes = i, this.reset() }, reset: function () { var t = this._hasher; t.reset(), t.update(this._iKey) }, update: function (t) { return this._hasher.update(t), this }, finalize: function (t) { var r = this._hasher, e = r.finalize(t); r.reset(); var i = r.finalize(this._oKey.clone().concat(e)); return i } }) }(), function () { var r = t, e = r.lib, i = e.Base, n = e.WordArray, o = r.algo, s = o.SHA1, a = o.HMAC, c = o.PBKDF2 = i.extend({ cfg: i.extend({ keySize: 4, hasher: s, iterations: 1 }), init: function (t) { this.cfg = this.cfg.extend(t) }, compute: function (t, r) { for (var e = this.cfg, i = a.create(e.hasher, t), o = n.create(), s = n.create([1]), c = o.words, h = s.words, l = e.keySize, f = e.iterations; c.length < l;) { var u = i.update(r).finalize(s); i.reset(); for (var d = u.words, v = d.length, p = u, _ = 1; _ < f; _++) { p = i.finalize(p), i.reset(); for (var y = p.words, g = 0; g < v; g++)d[g] ^= y[g] } o.concat(u), h[0]++ } return o.sigBytes = 4 * l, o } }); r.PBKDF2 = function (t, r, e) { return c.create(e).compute(t, r) } }(), function () { var r = t, e = r.lib, i = e.Base, n = e.WordArray, o = r.algo, s = o.MD5, a = o.EvpKDF = i.extend({ cfg: i.extend({ keySize: 4, hasher: s, iterations: 1 }), init: function (t) { this.cfg = this.cfg.extend(t) }, compute: function (t, r) { for (var e = this.cfg, i = e.hasher.create(), o = n.create(), s = o.words, a = e.keySize, c = e.iterations; s.length < a;) { h && i.update(h); var h = i.update(t).finalize(r); i.reset(); for (var l = 1; l < c; l++)h = i.finalize(h), i.reset(); o.concat(h) } return o.sigBytes = 4 * a, o } }); r.EvpKDF = function (t, r, e) { return a.create(e).compute(t, r) } }(), function () { var r = t, e = r.lib, i = e.WordArray, n = r.algo, o = n.SHA256, s = n.SHA224 = o.extend({ _doReset: function () { this._hash = new i.init([3238371032, 914150663, 812702999, 4144912697, 4290775857, 1750603025, 1694076839, 3204075428]) }, _doFinalize: function () { var t = o._doFinalize.call(this); return t.sigBytes -= 4, t } }); r.SHA224 = o._createHelper(s), r.HmacSHA224 = o._createHmacHelper(s) }(), function (r) { var e = t, i = e.lib, n = i.Base, o = i.WordArray, s = e.x64 = {}; s.Word = n.extend({ init: function (t, r) { this.high = t, this.low = r } }), s.WordArray = n.extend({ init: function (t, e) { t = this.words = t || [], e != r ? this.sigBytes = e : this.sigBytes = 8 * t.length }, toX32: function () { for (var t = this.words, r = t.length, e = [], i = 0; i < r; i++) { var n = t[i]; e.push(n.high), e.push(n.low) } return o.create(e, this.sigBytes) }, clone: function () { for (var t = n.clone.call(this), r = t.words = this.words.slice(0), e = r.length, i = 0; i < e; i++)r[i] = r[i].clone(); return t } }) }(), function (r) { var e = t, i = e.lib, n = i.WordArray, o = i.Hasher, s = e.x64, a = s.Word, c = e.algo, h = [], l = [], f = []; !function () { for (var t = 1, r = 0, e = 0; e < 24; e++) { h[t + 5 * r] = (e + 1) * (e + 2) / 2 % 64; var i = r % 5, n = (2 * t + 3 * r) % 5; t = i, r = n } for (var t = 0; t < 5; t++)for (var r = 0; r < 5; r++)l[t + 5 * r] = r + (2 * t + 3 * r) % 5 * 5; for (var o = 1, s = 0; s < 24; s++) { for (var c = 0, u = 0, d = 0; d < 7; d++) { if (1 & o) { var v = (1 << d) - 1; v < 32 ? u ^= 1 << v : c ^= 1 << v - 32 } 128 & o ? o = o << 1 ^ 113 : o <<= 1 } f[s] = a.create(c, u) } }(); var u = []; !function () { for (var t = 0; t < 25; t++)u[t] = a.create() }(); var d = c.SHA3 = o.extend({ cfg: o.cfg.extend({ outputLength: 512 }), _doReset: function () { for (var t = this._state = [], r = 0; r < 25; r++)t[r] = new a.init; this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32 }, _doProcessBlock: function (t, r) { for (var e = this._state, i = this.blockSize / 2, n = 0; n < i; n++) { var o = t[r + 2 * n], s = t[r + 2 * n + 1]; o = 16711935 & (o << 8 | o >>> 24) | 4278255360 & (o << 24 | o >>> 8), s = 16711935 & (s << 8 | s >>> 24) | 4278255360 & (s << 24 | s >>> 8); var a = e[n]; a.high ^= s, a.low ^= o } for (var c = 0; c < 24; c++) { for (var d = 0; d < 5; d++) { for (var v = 0, p = 0, _ = 0; _ < 5; _++) { var a = e[d + 5 * _]; v ^= a.high, p ^= a.low } var y = u[d]; y.high = v, y.low = p } for (var d = 0; d < 5; d++)for (var g = u[(d + 4) % 5], B = u[(d + 1) % 5], w = B.high, k = B.low, v = g.high ^ (w << 1 | k >>> 31), p = g.low ^ (k << 1 | w >>> 31), _ = 0; _ < 5; _++) { var a = e[d + 5 * _]; a.high ^= v, a.low ^= p } for (var S = 1; S < 25; S++) { var a = e[S], m = a.high, x = a.low, b = h[S]; if (b < 32) var v = m << b | x >>> 32 - b, p = x << b | m >>> 32 - b; else var v = x << b - 32 | m >>> 64 - b, p = m << b - 32 | x >>> 64 - b; var H = u[l[S]]; H.high = v, H.low = p } var z = u[0], A = e[0]; z.high = A.high, z.low = A.low; for (var d = 0; d < 5; d++)for (var _ = 0; _ < 5; _++) { var S = d + 5 * _, a = e[S], C = u[S], D = u[(d + 1) % 5 + 5 * _], R = u[(d + 2) % 5 + 5 * _]; a.high = C.high ^ ~D.high & R.high, a.low = C.low ^ ~D.low & R.low } var a = e[0], E = f[c]; a.high ^= E.high, a.low ^= E.low } }, _doFinalize: function () { var t = this._data, e = t.words, i = (8 * this._nDataBytes, 8 * t.sigBytes), o = 32 * this.blockSize; e[i >>> 5] |= 1 << 24 - i % 32, e[(r.ceil((i + 1) / o) * o >>> 5) - 1] |= 128, t.sigBytes = 4 * e.length, this._process(); for (var s = this._state, a = this.cfg.outputLength / 8, c = a / 8, h = [], l = 0; l < c; l++) { var f = s[l], u = f.high, d = f.low; u = 16711935 & (u << 8 | u >>> 24) | 4278255360 & (u << 24 | u >>> 8), d = 16711935 & (d << 8 | d >>> 24) | 4278255360 & (d << 24 | d >>> 8), h.push(d), h.push(u) } return new n.init(h, a) }, clone: function () { for (var t = o.clone.call(this), r = t._state = this._state.slice(0), e = 0; e < 25; e++)r[e] = r[e].clone(); return t } }); e.SHA3 = o._createHelper(d), e.HmacSHA3 = o._createHmacHelper(d) }(Math), function () { function r() { return s.create.apply(s, arguments) } var e = t, i = e.lib, n = i.Hasher, o = e.x64, s = o.Word, a = o.WordArray, c = e.algo, h = [r(1116352408, 3609767458), r(1899447441, 602891725), r(3049323471, 3964484399), r(3921009573, 2173295548), r(961987163, 4081628472), r(1508970993, 3053834265), r(2453635748, 2937671579), r(2870763221, 3664609560), r(3624381080, 2734883394), r(310598401, 1164996542), r(607225278, 1323610764), r(1426881987, 3590304994), r(1925078388, 4068182383), r(2162078206, 991336113), r(2614888103, 633803317), r(3248222580, 3479774868), r(3835390401, 2666613458), r(4022224774, 944711139), r(264347078, 2341262773), r(604807628, 2007800933), r(770255983, 1495990901), r(1249150122, 1856431235), r(1555081692, 3175218132), r(1996064986, 2198950837), r(2554220882, 3999719339), r(2821834349, 766784016), r(2952996808, 2566594879), r(3210313671, 3203337956), r(3336571891, 1034457026), r(3584528711, 2466948901), r(113926993, 3758326383), r(338241895, 168717936), r(666307205, 1188179964), r(773529912, 1546045734), r(1294757372, 1522805485), r(1396182291, 2643833823), r(1695183700, 2343527390), r(1986661051, 1014477480), r(2177026350, 1206759142), r(2456956037, 344077627), r(2730485921, 1290863460), r(2820302411, 3158454273), r(3259730800, 3505952657), r(3345764771, 106217008), r(3516065817, 3606008344), r(3600352804, 1432725776), r(4094571909, 1467031594), r(275423344, 851169720), r(430227734, 3100823752), r(506948616, 1363258195), r(659060556, 3750685593), r(883997877, 3785050280), r(958139571, 3318307427), r(1322822218, 3812723403), r(1537002063, 2003034995), r(1747873779, 3602036899), r(1955562222, 1575990012), r(2024104815, 1125592928), r(2227730452, 2716904306), r(2361852424, 442776044), r(2428436474, 593698344), r(2756734187, 3733110249), r(3204031479, 2999351573), r(3329325298, 3815920427), r(3391569614, 3928383900), r(3515267271, 566280711), r(3940187606, 3454069534), r(4118630271, 4000239992), r(116418474, 1914138554), r(174292421, 2731055270), r(289380356, 3203993006), r(460393269, 320620315), r(685471733, 587496836), r(852142971, 1086792851), r(1017036298, 365543100), r(1126000580, 2618297676), r(1288033470, 3409855158), r(1501505948, 4234509866), r(1607167915, 987167468), r(1816402316, 1246189591)], l = []; !function () { for (var t = 0; t < 80; t++)l[t] = r() }(); var f = c.SHA512 = n.extend({ _doReset: function () { this._hash = new a.init([new s.init(1779033703, 4089235720), new s.init(3144134277, 2227873595), new s.init(1013904242, 4271175723), new s.init(2773480762, 1595750129), new s.init(1359893119, 2917565137), new s.init(2600822924, 725511199), new s.init(528734635, 4215389547), new s.init(1541459225, 327033209)]) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], s = e[3], a = e[4], c = e[5], f = e[6], u = e[7], d = i.high, v = i.low, p = n.high, _ = n.low, y = o.high, g = o.low, B = s.high, w = s.low, k = a.high, S = a.low, m = c.high, x = c.low, b = f.high, H = f.low, z = u.high, A = u.low, C = d, D = v, R = p, E = _, M = y, F = g, P = B, W = w, O = k, U = S, I = m, K = x, X = b, L = H, j = z, N = A, T = 0; T < 80; T++) { var Z = l[T]; if (T < 16) var q = Z.high = 0 | t[r + 2 * T], G = Z.low = 0 | t[r + 2 * T + 1]; else { var J = l[T - 15], $ = J.high, Q = J.low, V = ($ >>> 1 | Q << 31) ^ ($ >>> 8 | Q << 24) ^ $ >>> 7, Y = (Q >>> 1 | $ << 31) ^ (Q >>> 8 | $ << 24) ^ (Q >>> 7 | $ << 25), tt = l[T - 2], rt = tt.high, et = tt.low, it = (rt >>> 19 | et << 13) ^ (rt << 3 | et >>> 29) ^ rt >>> 6, nt = (et >>> 19 | rt << 13) ^ (et << 3 | rt >>> 29) ^ (et >>> 6 | rt << 26), ot = l[T - 7], st = ot.high, at = ot.low, ct = l[T - 16], ht = ct.high, lt = ct.low, G = Y + at, q = V + st + (G >>> 0 < Y >>> 0 ? 1 : 0), G = G + nt, q = q + it + (G >>> 0 < nt >>> 0 ? 1 : 0), G = G + lt, q = q + ht + (G >>> 0 < lt >>> 0 ? 1 : 0); Z.high = q, Z.low = G } var ft = O & I ^ ~O & X, ut = U & K ^ ~U & L, dt = C & R ^ C & M ^ R & M, vt = D & E ^ D & F ^ E & F, pt = (C >>> 28 | D << 4) ^ (C << 30 | D >>> 2) ^ (C << 25 | D >>> 7), _t = (D >>> 28 | C << 4) ^ (D << 30 | C >>> 2) ^ (D << 25 | C >>> 7), yt = (O >>> 14 | U << 18) ^ (O >>> 18 | U << 14) ^ (O << 23 | U >>> 9), gt = (U >>> 14 | O << 18) ^ (U >>> 18 | O << 14) ^ (U << 23 | O >>> 9), Bt = h[T], wt = Bt.high, kt = Bt.low, St = N + gt, mt = j + yt + (St >>> 0 < N >>> 0 ? 1 : 0), St = St + ut, mt = mt + ft + (St >>> 0 < ut >>> 0 ? 1 : 0), St = St + kt, mt = mt + wt + (St >>> 0 < kt >>> 0 ? 1 : 0), St = St + G, mt = mt + q + (St >>> 0 < G >>> 0 ? 1 : 0), xt = _t + vt, bt = pt + dt + (xt >>> 0 < _t >>> 0 ? 1 : 0); j = X, N = L, X = I, L = K, I = O, K = U, U = W + St | 0, O = P + mt + (U >>> 0 < W >>> 0 ? 1 : 0) | 0, P = M, W = F, M = R, F = E, R = C, E = D, D = St + xt | 0, C = mt + bt + (D >>> 0 < St >>> 0 ? 1 : 0) | 0 } v = i.low = v + D, i.high = d + C + (v >>> 0 < D >>> 0 ? 1 : 0), _ = n.low = _ + E, n.high = p + R + (_ >>> 0 < E >>> 0 ? 1 : 0), g = o.low = g + F, o.high = y + M + (g >>> 0 < F >>> 0 ? 1 : 0), w = s.low = w + W, s.high = B + P + (w >>> 0 < W >>> 0 ? 1 : 0), S = a.low = S + U, a.high = k + O + (S >>> 0 < U >>> 0 ? 1 : 0), x = c.low = x + K, c.high = m + I + (x >>> 0 < K >>> 0 ? 1 : 0), H = f.low = H + L, f.high = b + X + (H >>> 0 < L >>> 0 ? 1 : 0), A = u.low = A + N, u.high = z + j + (A >>> 0 < N >>> 0 ? 1 : 0) }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 128 >>> 10 << 5) + 30] = Math.floor(e / 4294967296), r[(i + 128 >>> 10 << 5) + 31] = e, t.sigBytes = 4 * r.length, this._process(); var n = this._hash.toX32(); return n }, clone: function () { var t = n.clone.call(this); return t._hash = this._hash.clone(), t }, blockSize: 32 }); e.SHA512 = n._createHelper(f), e.HmacSHA512 = n._createHmacHelper(f) }(), function () { var r = t, e = r.x64, i = e.Word, n = e.WordArray, o = r.algo, s = o.SHA512, a = o.SHA384 = s.extend({ _doReset: function () { this._hash = new n.init([new i.init(3418070365, 3238371032), new i.init(1654270250, 914150663), new i.init(2438529370, 812702999), new i.init(355462360, 4144912697), new i.init(1731405415, 4290775857), new i.init(2394180231, 1750603025), new i.init(3675008525, 1694076839), new i.init(1203062813, 3204075428)]) }, _doFinalize: function () { var t = s._doFinalize.call(this); return t.sigBytes -= 16, t } }); r.SHA384 = s._createHelper(a), r.HmacSHA384 = s._createHmacHelper(a) }(), t.lib.Cipher || function (r) { var e = t, i = e.lib, n = i.Base, o = i.WordArray, s = i.BufferedBlockAlgorithm, a = e.enc, c = (a.Utf8, a.Base64), h = e.algo, l = h.EvpKDF, f = i.Cipher = s.extend({ cfg: n.extend(), createEncryptor: function (t, r) { return this.create(this._ENC_XFORM_MODE, t, r) }, createDecryptor: function (t, r) { return this.create(this._DEC_XFORM_MODE, t, r) }, init: function (t, r, e) { this.cfg = this.cfg.extend(e), this._xformMode = t, this._key = r, this.reset() }, reset: function () { s.reset.call(this), this._doReset() }, process: function (t) { return this._append(t), this._process() }, finalize: function (t) { t && this._append(t); var r = this._doFinalize(); return r }, keySize: 4, ivSize: 4, _ENC_XFORM_MODE: 1, _DEC_XFORM_MODE: 2, _createHelper: function () { function t(t) { return "string" == typeof t ? m : w } return function (r) { return { encrypt: function (e, i, n) { return t(i).encrypt(r, e, i, n) }, decrypt: function (e, i, n) { return t(i).decrypt(r, e, i, n) } } } }() }), u = (i.StreamCipher = f.extend({ _doFinalize: function () { var t = this._process(!0); return t }, blockSize: 1 }), e.mode = {}), d = i.BlockCipherMode = n.extend({ createEncryptor: function (t, r) { return this.Encryptor.create(t, r) }, createDecryptor: function (t, r) { return this.Decryptor.create(t, r) }, init: function (t, r) { this._cipher = t, this._iv = r } }), v = u.CBC = function () { function t(t, e, i) { var n = this._iv; if (n) { var o = n; this._iv = r } else var o = this._prevBlock; for (var s = 0; s < i; s++)t[e + s] ^= o[s] } var e = d.extend(); return e.Encryptor = e.extend({ processBlock: function (r, e) { var i = this._cipher, n = i.blockSize; t.call(this, r, e, n), i.encryptBlock(r, e), this._prevBlock = r.slice(e, e + n) } }), e.Decryptor = e.extend({ processBlock: function (r, e) { var i = this._cipher, n = i.blockSize, o = r.slice(e, e + n); i.decryptBlock(r, e), t.call(this, r, e, n), this._prevBlock = o } }), e }(), p = e.pad = {}, _ = p.Pkcs7 = { pad: function (t, r) { for (var e = 4 * r, i = e - t.sigBytes % e, n = i << 24 | i << 16 | i << 8 | i, s = [], a = 0; a < i; a += 4)s.push(n); var c = o.create(s, i); t.concat(c) }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, y = (i.BlockCipher = f.extend({ cfg: f.cfg.extend({ mode: v, padding: _ }), reset: function () { f.reset.call(this); var t = this.cfg, r = t.iv, e = t.mode; if (this._xformMode == this._ENC_XFORM_MODE) var i = e.createEncryptor; else { var i = e.createDecryptor; this._minBufferSize = 1 } this._mode && this._mode.__creator == i ? this._mode.init(this, r && r.words) : (this._mode = i.call(e, this, r && r.words), this._mode.__creator = i) }, _doProcessBlock: function (t, r) { this._mode.processBlock(t, r) }, _doFinalize: function () { var t = this.cfg.padding; if (this._xformMode == this._ENC_XFORM_MODE) { t.pad(this._data, this.blockSize); var r = this._process(!0) } else { var r = this._process(!0); t.unpad(r) } return r }, blockSize: 4 }), i.CipherParams = n.extend({ init: function (t) { this.mixIn(t) }, toString: function (t) { return (t || this.formatter).stringify(this) } })), g = e.format = {}, B = g.OpenSSL = { stringify: function (t) { var r = t.ciphertext, e = t.salt; if (e) var i = o.create([1398893684, 1701076831]).concat(e).concat(r); else var i = r; return i.toString(c) }, parse: function (t) { var r = c.parse(t), e = r.words; if (1398893684 == e[0] && 1701076831 == e[1]) { var i = o.create(e.slice(2, 4)); e.splice(0, 4), r.sigBytes -= 16 } return y.create({ ciphertext: r, salt: i }) } }, w = i.SerializableCipher = n.extend({ cfg: n.extend({ format: B }), encrypt: function (t, r, e, i) { i = this.cfg.extend(i); var n = t.createEncryptor(e, i), o = n.finalize(r), s = n.cfg; return y.create({ ciphertext: o, key: e, iv: s.iv, algorithm: t, mode: s.mode, padding: s.padding, blockSize: t.blockSize, formatter: i.format }) }, decrypt: function (t, r, e, i) { i = this.cfg.extend(i), r = this._parse(r, i.format); var n = t.createDecryptor(e, i).finalize(r.ciphertext); return n }, _parse: function (t, r) { return "string" == typeof t ? r.parse(t, this) : t } }), k = e.kdf = {}, S = k.OpenSSL = { execute: function (t, r, e, i) { i || (i = o.random(8)); var n = l.create({ keySize: r + e }).compute(t, i), s = o.create(n.words.slice(r), 4 * e); return n.sigBytes = 4 * r, y.create({ key: n, iv: s, salt: i }) } }, m = i.PasswordBasedCipher = w.extend({ cfg: w.cfg.extend({ kdf: S }), encrypt: function (t, r, e, i) { i = this.cfg.extend(i); var n = i.kdf.execute(e, t.keySize, t.ivSize); i.iv = n.iv; var o = w.encrypt.call(this, t, r, n.key, i); return o.mixIn(n), o }, decrypt: function (t, r, e, i) { i = this.cfg.extend(i), r = this._parse(r, i.format); var n = i.kdf.execute(e, t.keySize, t.ivSize, r.salt); i.iv = n.iv; var o = w.decrypt.call(this, t, r, n.key, i); return o } }) }(), t.mode.CFB = function () { function r(t, r, e, i) { var n = this._iv; if (n) { var o = n.slice(0); this._iv = void 0 } else var o = this._prevBlock; i.encryptBlock(o, 0); for (var s = 0; s < e; s++)t[r + s] ^= o[s] } var e = t.lib.BlockCipherMode.extend(); return e.Encryptor = e.extend({ processBlock: function (t, e) { var i = this._cipher, n = i.blockSize; r.call(this, t, e, n, i), this._prevBlock = t.slice(e, e + n) } }), e.Decryptor = e.extend({ processBlock: function (t, e) { var i = this._cipher, n = i.blockSize, o = t.slice(e, e + n); r.call(this, t, e, n, i), this._prevBlock = o } }), e }(), t.mode.ECB = function () { var r = t.lib.BlockCipherMode.extend(); return r.Encryptor = r.extend({ processBlock: function (t, r) { this._cipher.encryptBlock(t, r) } }), r.Decryptor = r.extend({ processBlock: function (t, r) { this._cipher.decryptBlock(t, r) } }), r }(), t.pad.AnsiX923 = { pad: function (t, r) { var e = t.sigBytes, i = 4 * r, n = i - e % i, o = e + n - 1; t.clamp(), t.words[o >>> 2] |= n << 24 - o % 4 * 8, t.sigBytes += n }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, t.pad.Iso10126 = { pad: function (r, e) { var i = 4 * e, n = i - r.sigBytes % i; r.concat(t.lib.WordArray.random(n - 1)).concat(t.lib.WordArray.create([n << 24], 1)) }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, t.pad.Iso97971 = { pad: function (r, e) { r.concat(t.lib.WordArray.create([2147483648], 1)), t.pad.ZeroPadding.pad(r, e) }, unpad: function (r) { t.pad.ZeroPadding.unpad(r), r.sigBytes-- } }, t.mode.OFB = function () { var r = t.lib.BlockCipherMode.extend(), e = r.Encryptor = r.extend({ processBlock: function (t, r) { var e = this._cipher, i = e.blockSize, n = this._iv, o = this._keystream; n && (o = this._keystream = n.slice(0), this._iv = void 0), e.encryptBlock(o, 0); for (var s = 0; s < i; s++)t[r + s] ^= o[s] } }); return r.Decryptor = e, r }(), t.pad.NoPadding = { pad: function () { }, unpad: function () { } }, function (r) { var e = t, i = e.lib, n = i.CipherParams, o = e.enc, s = o.Hex, a = e.format; a.Hex = { stringify: function (t) { return t.ciphertext.toString(s) }, parse: function (t) { var r = s.parse(t); return n.create({ ciphertext: r }) } } }(), function () { var r = t, e = r.lib, i = e.BlockCipher, n = r.algo, o = [], s = [], a = [], c = [], h = [], l = [], f = [], u = [], d = [], v = []; !function () { for (var t = [], r = 0; r < 256; r++)r < 128 ? t[r] = r << 1 : t[r] = r << 1 ^ 283; for (var e = 0, i = 0, r = 0; r < 256; r++) { var n = i ^ i << 1 ^ i << 2 ^ i << 3 ^ i << 4; n = n >>> 8 ^ 255 & n ^ 99, o[e] = n, s[n] = e; var p = t[e], _ = t[p], y = t[_], g = 257 * t[n] ^ 16843008 * n; a[e] = g << 24 | g >>> 8, c[e] = g << 16 | g >>> 16, h[e] = g << 8 | g >>> 24, l[e] = g; var g = 16843009 * y ^ 65537 * _ ^ 257 * p ^ 16843008 * e; f[n] = g << 24 | g >>> 8, u[n] = g << 16 | g >>> 16, d[n] = g << 8 | g >>> 24, v[n] = g, e ? (e = p ^ t[t[t[y ^ p]]], i ^= t[t[i]]) : e = i = 1 } }(); var p = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54], _ = n.AES = i.extend({ _doReset: function () { if (!this._nRounds || this._keyPriorReset !== this._key) { for (var t = this._keyPriorReset = this._key, r = t.words, e = t.sigBytes / 4, i = this._nRounds = e + 6, n = 4 * (i + 1), s = this._keySchedule = [], a = 0; a < n; a++)if (a < e) s[a] = r[a]; else { var c = s[a - 1]; a % e ? e > 6 && a % e == 4 && (c = o[c >>> 24] << 24 | o[c >>> 16 & 255] << 16 | o[c >>> 8 & 255] << 8 | o[255 & c]) : (c = c << 8 | c >>> 24, c = o[c >>> 24] << 24 | o[c >>> 16 & 255] << 16 | o[c >>> 8 & 255] << 8 | o[255 & c], c ^= p[a / e | 0] << 24), s[a] = s[a - e] ^ c } for (var h = this._invKeySchedule = [], l = 0; l < n; l++) { var a = n - l; if (l % 4) var c = s[a]; else var c = s[a - 4]; l < 4 || a <= 4 ? h[l] = c : h[l] = f[o[c >>> 24]] ^ u[o[c >>> 16 & 255]] ^ d[o[c >>> 8 & 255]] ^ v[o[255 & c]] } } }, encryptBlock: function (t, r) { this._doCryptBlock(t, r, this._keySchedule, a, c, h, l, o) }, decryptBlock: function (t, r) { var e = t[r + 1]; t[r + 1] = t[r + 3], t[r + 3] = e, this._doCryptBlock(t, r, this._invKeySchedule, f, u, d, v, s); var e = t[r + 1]; t[r + 1] = t[r + 3], t[r + 3] = e }, _doCryptBlock: function (t, r, e, i, n, o, s, a) { for (var c = this._nRounds, h = t[r] ^ e[0], l = t[r + 1] ^ e[1], f = t[r + 2] ^ e[2], u = t[r + 3] ^ e[3], d = 4, v = 1; v < c; v++) { var p = i[h >>> 24] ^ n[l >>> 16 & 255] ^ o[f >>> 8 & 255] ^ s[255 & u] ^ e[d++], _ = i[l >>> 24] ^ n[f >>> 16 & 255] ^ o[u >>> 8 & 255] ^ s[255 & h] ^ e[d++], y = i[f >>> 24] ^ n[u >>> 16 & 255] ^ o[h >>> 8 & 255] ^ s[255 & l] ^ e[d++], g = i[u >>> 24] ^ n[h >>> 16 & 255] ^ o[l >>> 8 & 255] ^ s[255 & f] ^ e[d++]; h = p, l = _, f = y, u = g } var p = (a[h >>> 24] << 24 | a[l >>> 16 & 255] << 16 | a[f >>> 8 & 255] << 8 | a[255 & u]) ^ e[d++], _ = (a[l >>> 24] << 24 | a[f >>> 16 & 255] << 16 | a[u >>> 8 & 255] << 8 | a[255 & h]) ^ e[d++], y = (a[f >>> 24] << 24 | a[u >>> 16 & 255] << 16 | a[h >>> 8 & 255] << 8 | a[255 & l]) ^ e[d++], g = (a[u >>> 24] << 24 | a[h >>> 16 & 255] << 16 | a[l >>> 8 & 255] << 8 | a[255 & f]) ^ e[d++]; t[r] = p, t[r + 1] = _, t[r + 2] = y, t[r + 3] = g }, keySize: 8 }); r.AES = i._createHelper(_) }(), function () { + function r(t, r) { var e = (this._lBlock >>> t ^ this._rBlock) & r; this._rBlock ^= e, this._lBlock ^= e << t } function e(t, r) { + var e = (this._rBlock >>> t ^ this._lBlock) & r; this._lBlock ^= e, this._rBlock ^= e << t; + } var i = t, n = i.lib, o = n.WordArray, s = n.BlockCipher, a = i.algo, c = [57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4], h = [14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32], l = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28], f = [{ 0: 8421888, 268435456: 32768, 536870912: 8421378, 805306368: 2, 1073741824: 512, 1342177280: 8421890, 1610612736: 8389122, 1879048192: 8388608, 2147483648: 514, 2415919104: 8389120, 2684354560: 33280, 2952790016: 8421376, 3221225472: 32770, 3489660928: 8388610, 3758096384: 0, 4026531840: 33282, 134217728: 0, 402653184: 8421890, 671088640: 33282, 939524096: 32768, 1207959552: 8421888, 1476395008: 512, 1744830464: 8421378, 2013265920: 2, 2281701376: 8389120, 2550136832: 33280, 2818572288: 8421376, 3087007744: 8389122, 3355443200: 8388610, 3623878656: 32770, 3892314112: 514, 4160749568: 8388608, 1: 32768, 268435457: 2, 536870913: 8421888, 805306369: 8388608, 1073741825: 8421378, 1342177281: 33280, 1610612737: 512, 1879048193: 8389122, 2147483649: 8421890, 2415919105: 8421376, 2684354561: 8388610, 2952790017: 33282, 3221225473: 514, 3489660929: 8389120, 3758096385: 32770, 4026531841: 0, 134217729: 8421890, 402653185: 8421376, 671088641: 8388608, 939524097: 512, 1207959553: 32768, 1476395009: 8388610, 1744830465: 2, 2013265921: 33282, 2281701377: 32770, 2550136833: 8389122, 2818572289: 514, 3087007745: 8421888, 3355443201: 8389120, 3623878657: 0, 3892314113: 33280, 4160749569: 8421378 }, { 0: 1074282512, 16777216: 16384, 33554432: 524288, 50331648: 1074266128, 67108864: 1073741840, 83886080: 1074282496, 100663296: 1073758208, 117440512: 16, 134217728: 540672, 150994944: 1073758224, 167772160: 1073741824, 184549376: 540688, 201326592: 524304, 218103808: 0, 234881024: 16400, 251658240: 1074266112, 8388608: 1073758208, 25165824: 540688, 41943040: 16, 58720256: 1073758224, 75497472: 1074282512, 92274688: 1073741824, 109051904: 524288, 125829120: 1074266128, 142606336: 524304, 159383552: 0, 176160768: 16384, 192937984: 1074266112, 209715200: 1073741840, 226492416: 540672, 243269632: 1074282496, 260046848: 16400, 268435456: 0, 285212672: 1074266128, 301989888: 1073758224, 318767104: 1074282496, 335544320: 1074266112, 352321536: 16, 369098752: 540688, 385875968: 16384, 402653184: 16400, 419430400: 524288, 436207616: 524304, 452984832: 1073741840, 469762048: 540672, 486539264: 1073758208, 503316480: 1073741824, 520093696: 1074282512, 276824064: 540688, 293601280: 524288, 310378496: 1074266112, 327155712: 16384, 343932928: 1073758208, 360710144: 1074282512, 377487360: 16, 394264576: 1073741824, 411041792: 1074282496, 427819008: 1073741840, 444596224: 1073758224, 461373440: 524304, 478150656: 0, 494927872: 16400, 511705088: 1074266128, 528482304: 540672 }, { 0: 260, 1048576: 0, 2097152: 67109120, 3145728: 65796, 4194304: 65540, 5242880: 67108868, 6291456: 67174660, 7340032: 67174400, 8388608: 67108864, 9437184: 67174656, 10485760: 65792, 11534336: 67174404, 12582912: 67109124, 13631488: 65536, 14680064: 4, 15728640: 256, 524288: 67174656, 1572864: 67174404, 2621440: 0, 3670016: 67109120, 4718592: 67108868, 5767168: 65536, 6815744: 65540, 7864320: 260, 8912896: 4, 9961472: 256, 11010048: 67174400, 12058624: 65796, 13107200: 65792, 14155776: 67109124, 15204352: 67174660, 16252928: 67108864, 16777216: 67174656, 17825792: 65540, 18874368: 65536, 19922944: 67109120, 20971520: 256, 22020096: 67174660, 23068672: 67108868, 24117248: 0, 25165824: 67109124, 26214400: 67108864, 27262976: 4, 28311552: 65792, 29360128: 67174400, 30408704: 260, 31457280: 65796, 32505856: 67174404, 17301504: 67108864, 18350080: 260, 19398656: 67174656, 20447232: 0, 21495808: 65540, 22544384: 67109120, 23592960: 256, 24641536: 67174404, 25690112: 65536, 26738688: 67174660, 27787264: 65796, 28835840: 67108868, 29884416: 67109124, 30932992: 67174400, 31981568: 4, 33030144: 65792 }, { 0: 2151682048, 65536: 2147487808, 131072: 4198464, 196608: 2151677952, 262144: 0, 327680: 4198400, 393216: 2147483712, 458752: 4194368, 524288: 2147483648, 589824: 4194304, 655360: 64, 720896: 2147487744, 786432: 2151678016, 851968: 4160, 917504: 4096, 983040: 2151682112, 32768: 2147487808, 98304: 64, 163840: 2151678016, 229376: 2147487744, 294912: 4198400, 360448: 2151682112, 425984: 0, 491520: 2151677952, 557056: 4096, 622592: 2151682048, 688128: 4194304, 753664: 4160, 819200: 2147483648, 884736: 4194368, 950272: 4198464, 1015808: 2147483712, 1048576: 4194368, 1114112: 4198400, 1179648: 2147483712, 1245184: 0, 1310720: 4160, 1376256: 2151678016, 1441792: 2151682048, 1507328: 2147487808, 1572864: 2151682112, 1638400: 2147483648, 1703936: 2151677952, 1769472: 4198464, 1835008: 2147487744, 1900544: 4194304, 1966080: 64, 2031616: 4096, 1081344: 2151677952, 1146880: 2151682112, 1212416: 0, 1277952: 4198400, 1343488: 4194368, 1409024: 2147483648, 1474560: 2147487808, 1540096: 64, 1605632: 2147483712, 1671168: 4096, 1736704: 2147487744, 1802240: 2151678016, 1867776: 4160, 1933312: 2151682048, 1998848: 4194304, 2064384: 4198464 }, { 0: 128, 4096: 17039360, 8192: 262144, 12288: 536870912, 16384: 537133184, 20480: 16777344, 24576: 553648256, 28672: 262272, 32768: 16777216, 36864: 537133056, 40960: 536871040, 45056: 553910400, 49152: 553910272, 53248: 0, 57344: 17039488, 61440: 553648128, 2048: 17039488, 6144: 553648256, 10240: 128, 14336: 17039360, 18432: 262144, 22528: 537133184, 26624: 553910272, 30720: 536870912, 34816: 537133056, 38912: 0, 43008: 553910400, 47104: 16777344, 51200: 536871040, 55296: 553648128, 59392: 16777216, 63488: 262272, 65536: 262144, 69632: 128, 73728: 536870912, 77824: 553648256, 81920: 16777344, 86016: 553910272, 90112: 537133184, 94208: 16777216, 98304: 553910400, 102400: 553648128, 106496: 17039360, 110592: 537133056, 114688: 262272, 118784: 536871040, 122880: 0, 126976: 17039488, 67584: 553648256, 71680: 16777216, 75776: 17039360, 79872: 537133184, 83968: 536870912, 88064: 17039488, 92160: 128, 96256: 553910272, 100352: 262272, 104448: 553910400, 108544: 0, 112640: 553648128, 116736: 16777344, 120832: 262144, 124928: 537133056, 129024: 536871040 }, { 0: 268435464, 256: 8192, 512: 270532608, 768: 270540808, 1024: 268443648, 1280: 2097152, 1536: 2097160, 1792: 268435456, 2048: 0, 2304: 268443656, 2560: 2105344, 2816: 8, 3072: 270532616, 3328: 2105352, 3584: 8200, 3840: 270540800, 128: 270532608, 384: 270540808, 640: 8, 896: 2097152, 1152: 2105352, 1408: 268435464, 1664: 268443648, 1920: 8200, 2176: 2097160, 2432: 8192, 2688: 268443656, 2944: 270532616, 3200: 0, 3456: 270540800, 3712: 2105344, 3968: 268435456, 4096: 268443648, 4352: 270532616, 4608: 270540808, 4864: 8200, 5120: 2097152, 5376: 268435456, 5632: 268435464, 5888: 2105344, 6144: 2105352, 6400: 0, 6656: 8, 6912: 270532608, 7168: 8192, 7424: 268443656, 7680: 270540800, 7936: 2097160, 4224: 8, 4480: 2105344, 4736: 2097152, 4992: 268435464, 5248: 268443648, 5504: 8200, 5760: 270540808, 6016: 270532608, 6272: 270540800, 6528: 270532616, 6784: 8192, 7040: 2105352, 7296: 2097160, 7552: 0, 7808: 268435456, 8064: 268443656 }, { 0: 1048576, 16: 33555457, 32: 1024, 48: 1049601, 64: 34604033, 80: 0, 96: 1, 112: 34603009, 128: 33555456, 144: 1048577, 160: 33554433, 176: 34604032, 192: 34603008, 208: 1025, 224: 1049600, 240: 33554432, 8: 34603009, 24: 0, 40: 33555457, 56: 34604032, 72: 1048576, 88: 33554433, 104: 33554432, 120: 1025, 136: 1049601, 152: 33555456, 168: 34603008, 184: 1048577, 200: 1024, 216: 34604033, 232: 1, 248: 1049600, 256: 33554432, 272: 1048576, 288: 33555457, 304: 34603009, 320: 1048577, 336: 33555456, 352: 34604032, 368: 1049601, 384: 1025, 400: 34604033, 416: 1049600, 432: 1, 448: 0, 464: 34603008, 480: 33554433, 496: 1024, 264: 1049600, 280: 33555457, 296: 34603009, 312: 1, 328: 33554432, 344: 1048576, 360: 1025, 376: 34604032, 392: 33554433, 408: 34603008, 424: 0, 440: 34604033, 456: 1049601, 472: 1024, 488: 33555456, 504: 1048577 }, { 0: 134219808, 1: 131072, 2: 134217728, 3: 32, 4: 131104, 5: 134350880, 6: 134350848, 7: 2048, 8: 134348800, 9: 134219776, 10: 133120, 11: 134348832, 12: 2080, 13: 0, 14: 134217760, 15: 133152, 2147483648: 2048, 2147483649: 134350880, 2147483650: 134219808, 2147483651: 134217728, 2147483652: 134348800, 2147483653: 133120, 2147483654: 133152, 2147483655: 32, 2147483656: 134217760, 2147483657: 2080, 2147483658: 131104, 2147483659: 134350848, 2147483660: 0, 2147483661: 134348832, 2147483662: 134219776, 2147483663: 131072, 16: 133152, 17: 134350848, 18: 32, 19: 2048, 20: 134219776, 21: 134217760, 22: 134348832, 23: 131072, 24: 0, 25: 131104, 26: 134348800, 27: 134219808, 28: 134350880, 29: 133120, 30: 2080, 31: 134217728, 2147483664: 131072, 2147483665: 2048, 2147483666: 134348832, 2147483667: 133152, 2147483668: 32, 2147483669: 134348800, 2147483670: 134217728, 2147483671: 134219808, 2147483672: 134350880, 2147483673: 134217760, 2147483674: 134219776, 2147483675: 0, 2147483676: 133120, 2147483677: 2080, 2147483678: 131104, 2147483679: 134350848 }], u = [4160749569, 528482304, 33030144, 2064384, 129024, 8064, 504, 2147483679], d = a.DES = s.extend({ _doReset: function () { for (var t = this._key, r = t.words, e = [], i = 0; i < 56; i++) { var n = c[i] - 1; e[i] = r[n >>> 5] >>> 31 - n % 32 & 1 } for (var o = this._subKeys = [], s = 0; s < 16; s++) { for (var a = o[s] = [], f = l[s], i = 0; i < 24; i++)a[i / 6 | 0] |= e[(h[i] - 1 + f) % 28] << 31 - i % 6, a[4 + (i / 6 | 0)] |= e[28 + (h[i + 24] - 1 + f) % 28] << 31 - i % 6; a[0] = a[0] << 1 | a[0] >>> 31; for (var i = 1; i < 7; i++)a[i] = a[i] >>> 4 * (i - 1) + 3; a[7] = a[7] << 5 | a[7] >>> 27 } for (var u = this._invSubKeys = [], i = 0; i < 16; i++)u[i] = o[15 - i] }, encryptBlock: function (t, r) { this._doCryptBlock(t, r, this._subKeys) }, decryptBlock: function (t, r) { this._doCryptBlock(t, r, this._invSubKeys) }, _doCryptBlock: function (t, i, n) { this._lBlock = t[i], this._rBlock = t[i + 1], r.call(this, 4, 252645135), r.call(this, 16, 65535), e.call(this, 2, 858993459), e.call(this, 8, 16711935), r.call(this, 1, 1431655765); for (var o = 0; o < 16; o++) { for (var s = n[o], a = this._lBlock, c = this._rBlock, h = 0, l = 0; l < 8; l++)h |= f[l][((c ^ s[l]) & u[l]) >>> 0]; this._lBlock = c, this._rBlock = a ^ h } var d = this._lBlock; this._lBlock = this._rBlock, this._rBlock = d, r.call(this, 1, 1431655765), e.call(this, 8, 16711935), e.call(this, 2, 858993459), r.call(this, 16, 65535), r.call(this, 4, 252645135), t[i] = this._lBlock, t[i + 1] = this._rBlock }, keySize: 2, ivSize: 2, blockSize: 2 }); i.DES = s._createHelper(d); var v = a.TripleDES = s.extend({ _doReset: function () { var t = this._key, r = t.words; this._des1 = d.createEncryptor(o.create(r.slice(0, 2))), this._des2 = d.createEncryptor(o.create(r.slice(2, 4))), this._des3 = d.createEncryptor(o.create(r.slice(4, 6))) }, encryptBlock: function (t, r) { this._des1.encryptBlock(t, r), this._des2.decryptBlock(t, r), this._des3.encryptBlock(t, r) }, decryptBlock: function (t, r) { this._des3.decryptBlock(t, r), this._des2.encryptBlock(t, r), this._des1.decryptBlock(t, r) }, keySize: 6, ivSize: 2, blockSize: 2 }); i.TripleDES = s._createHelper(v) + }(), function () { function r() { for (var t = this._S, r = this._i, e = this._j, i = 0, n = 0; n < 4; n++) { r = (r + 1) % 256, e = (e + t[r]) % 256; var o = t[r]; t[r] = t[e], t[e] = o, i |= t[(t[r] + t[e]) % 256] << 24 - 8 * n } return this._i = r, this._j = e, i } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = o.RC4 = n.extend({ _doReset: function () { for (var t = this._key, r = t.words, e = t.sigBytes, i = this._S = [], n = 0; n < 256; n++)i[n] = n; for (var n = 0, o = 0; n < 256; n++) { var s = n % e, a = r[s >>> 2] >>> 24 - s % 4 * 8 & 255; o = (o + i[n] + a) % 256; var c = i[n]; i[n] = i[o], i[o] = c } this._i = this._j = 0 }, _doProcessBlock: function (t, e) { t[e] ^= r.call(this) }, keySize: 8, ivSize: 0 }); e.RC4 = n._createHelper(s); var a = o.RC4Drop = s.extend({ cfg: s.cfg.extend({ drop: 192 }), _doReset: function () { s._doReset.call(this); for (var t = this.cfg.drop; t > 0; t--)r.call(this) } }); e.RC4Drop = n._createHelper(a) }(), t.mode.CTRGladman = function () { function r(t) { if (255 === (t >> 24 & 255)) { var r = t >> 16 & 255, e = t >> 8 & 255, i = 255 & t; 255 === r ? (r = 0, 255 === e ? (e = 0, 255 === i ? i = 0 : ++i) : ++e) : ++r, t = 0, t += r << 16, t += e << 8, t += i } else t += 1 << 24; return t } function e(t) { return 0 === (t[0] = r(t[0])) && (t[1] = r(t[1])), t } var i = t.lib.BlockCipherMode.extend(), n = i.Encryptor = i.extend({ processBlock: function (t, r) { var i = this._cipher, n = i.blockSize, o = this._iv, s = this._counter; o && (s = this._counter = o.slice(0), this._iv = void 0), e(s); var a = s.slice(0); i.encryptBlock(a, 0); for (var c = 0; c < n; c++)t[r + c] ^= a[c] } }); return i.Decryptor = n, i }(), function () { function r() { for (var t = this._X, r = this._C, e = 0; e < 8; e++)a[e] = r[e]; r[0] = r[0] + 1295307597 + this._b | 0, r[1] = r[1] + 3545052371 + (r[0] >>> 0 < a[0] >>> 0 ? 1 : 0) | 0, r[2] = r[2] + 886263092 + (r[1] >>> 0 < a[1] >>> 0 ? 1 : 0) | 0, r[3] = r[3] + 1295307597 + (r[2] >>> 0 < a[2] >>> 0 ? 1 : 0) | 0, r[4] = r[4] + 3545052371 + (r[3] >>> 0 < a[3] >>> 0 ? 1 : 0) | 0, r[5] = r[5] + 886263092 + (r[4] >>> 0 < a[4] >>> 0 ? 1 : 0) | 0, r[6] = r[6] + 1295307597 + (r[5] >>> 0 < a[5] >>> 0 ? 1 : 0) | 0, r[7] = r[7] + 3545052371 + (r[6] >>> 0 < a[6] >>> 0 ? 1 : 0) | 0, this._b = r[7] >>> 0 < a[7] >>> 0 ? 1 : 0; for (var e = 0; e < 8; e++) { var i = t[e] + r[e], n = 65535 & i, o = i >>> 16, s = ((n * n >>> 17) + n * o >>> 15) + o * o, h = ((4294901760 & i) * i | 0) + ((65535 & i) * i | 0); c[e] = s ^ h } t[0] = c[0] + (c[7] << 16 | c[7] >>> 16) + (c[6] << 16 | c[6] >>> 16) | 0, t[1] = c[1] + (c[0] << 8 | c[0] >>> 24) + c[7] | 0, t[2] = c[2] + (c[1] << 16 | c[1] >>> 16) + (c[0] << 16 | c[0] >>> 16) | 0, t[3] = c[3] + (c[2] << 8 | c[2] >>> 24) + c[1] | 0, t[4] = c[4] + (c[3] << 16 | c[3] >>> 16) + (c[2] << 16 | c[2] >>> 16) | 0, t[5] = c[5] + (c[4] << 8 | c[4] >>> 24) + c[3] | 0, t[6] = c[6] + (c[5] << 16 | c[5] >>> 16) + (c[4] << 16 | c[4] >>> 16) | 0, t[7] = c[7] + (c[6] << 8 | c[6] >>> 24) + c[5] | 0 } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = [], a = [], c = [], h = o.Rabbit = n.extend({ _doReset: function () { for (var t = this._key.words, e = this.cfg.iv, i = 0; i < 4; i++)t[i] = 16711935 & (t[i] << 8 | t[i] >>> 24) | 4278255360 & (t[i] << 24 | t[i] >>> 8); var n = this._X = [t[0], t[3] << 16 | t[2] >>> 16, t[1], t[0] << 16 | t[3] >>> 16, t[2], t[1] << 16 | t[0] >>> 16, t[3], t[2] << 16 | t[1] >>> 16], o = this._C = [t[2] << 16 | t[2] >>> 16, 4294901760 & t[0] | 65535 & t[1], t[3] << 16 | t[3] >>> 16, 4294901760 & t[1] | 65535 & t[2], t[0] << 16 | t[0] >>> 16, 4294901760 & t[2] | 65535 & t[3], t[1] << 16 | t[1] >>> 16, 4294901760 & t[3] | 65535 & t[0]]; this._b = 0; for (var i = 0; i < 4; i++)r.call(this); for (var i = 0; i < 8; i++)o[i] ^= n[i + 4 & 7]; if (e) { var s = e.words, a = s[0], c = s[1], h = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8), l = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8), f = h >>> 16 | 4294901760 & l, u = l << 16 | 65535 & h; o[0] ^= h, o[1] ^= f, o[2] ^= l, o[3] ^= u, o[4] ^= h, o[5] ^= f, o[6] ^= l, o[7] ^= u; for (var i = 0; i < 4; i++)r.call(this) } }, _doProcessBlock: function (t, e) { var i = this._X; r.call(this), s[0] = i[0] ^ i[5] >>> 16 ^ i[3] << 16, s[1] = i[2] ^ i[7] >>> 16 ^ i[5] << 16, s[2] = i[4] ^ i[1] >>> 16 ^ i[7] << 16, s[3] = i[6] ^ i[3] >>> 16 ^ i[1] << 16; for (var n = 0; n < 4; n++)s[n] = 16711935 & (s[n] << 8 | s[n] >>> 24) | 4278255360 & (s[n] << 24 | s[n] >>> 8), t[e + n] ^= s[n] }, blockSize: 4, ivSize: 2 }); e.Rabbit = n._createHelper(h) }(), t.mode.CTR = function () { var r = t.lib.BlockCipherMode.extend(), e = r.Encryptor = r.extend({ processBlock: function (t, r) { var e = this._cipher, i = e.blockSize, n = this._iv, o = this._counter; n && (o = this._counter = n.slice(0), this._iv = void 0); var s = o.slice(0); e.encryptBlock(s, 0), o[i - 1] = o[i - 1] + 1 | 0; for (var a = 0; a < i; a++)t[r + a] ^= s[a] } }); return r.Decryptor = e, r }(), function () { function r() { for (var t = this._X, r = this._C, e = 0; e < 8; e++)a[e] = r[e]; r[0] = r[0] + 1295307597 + this._b | 0, r[1] = r[1] + 3545052371 + (r[0] >>> 0 < a[0] >>> 0 ? 1 : 0) | 0, r[2] = r[2] + 886263092 + (r[1] >>> 0 < a[1] >>> 0 ? 1 : 0) | 0, r[3] = r[3] + 1295307597 + (r[2] >>> 0 < a[2] >>> 0 ? 1 : 0) | 0, r[4] = r[4] + 3545052371 + (r[3] >>> 0 < a[3] >>> 0 ? 1 : 0) | 0, r[5] = r[5] + 886263092 + (r[4] >>> 0 < a[4] >>> 0 ? 1 : 0) | 0, r[6] = r[6] + 1295307597 + (r[5] >>> 0 < a[5] >>> 0 ? 1 : 0) | 0, r[7] = r[7] + 3545052371 + (r[6] >>> 0 < a[6] >>> 0 ? 1 : 0) | 0, this._b = r[7] >>> 0 < a[7] >>> 0 ? 1 : 0; for (var e = 0; e < 8; e++) { var i = t[e] + r[e], n = 65535 & i, o = i >>> 16, s = ((n * n >>> 17) + n * o >>> 15) + o * o, h = ((4294901760 & i) * i | 0) + ((65535 & i) * i | 0); c[e] = s ^ h } t[0] = c[0] + (c[7] << 16 | c[7] >>> 16) + (c[6] << 16 | c[6] >>> 16) | 0, t[1] = c[1] + (c[0] << 8 | c[0] >>> 24) + c[7] | 0, t[2] = c[2] + (c[1] << 16 | c[1] >>> 16) + (c[0] << 16 | c[0] >>> 16) | 0, t[3] = c[3] + (c[2] << 8 | c[2] >>> 24) + c[1] | 0, t[4] = c[4] + (c[3] << 16 | c[3] >>> 16) + (c[2] << 16 | c[2] >>> 16) | 0, t[5] = c[5] + (c[4] << 8 | c[4] >>> 24) + c[3] | 0, t[6] = c[6] + (c[5] << 16 | c[5] >>> 16) + (c[4] << 16 | c[4] >>> 16) | 0, t[7] = c[7] + (c[6] << 8 | c[6] >>> 24) + c[5] | 0 } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = [], a = [], c = [], h = o.RabbitLegacy = n.extend({ _doReset: function () { var t = this._key.words, e = this.cfg.iv, i = this._X = [t[0], t[3] << 16 | t[2] >>> 16, t[1], t[0] << 16 | t[3] >>> 16, t[2], t[1] << 16 | t[0] >>> 16, t[3], t[2] << 16 | t[1] >>> 16], n = this._C = [t[2] << 16 | t[2] >>> 16, 4294901760 & t[0] | 65535 & t[1], t[3] << 16 | t[3] >>> 16, 4294901760 & t[1] | 65535 & t[2], t[0] << 16 | t[0] >>> 16, 4294901760 & t[2] | 65535 & t[3], t[1] << 16 | t[1] >>> 16, 4294901760 & t[3] | 65535 & t[0]]; this._b = 0; for (var o = 0; o < 4; o++)r.call(this); for (var o = 0; o < 8; o++)n[o] ^= i[o + 4 & 7]; if (e) { var s = e.words, a = s[0], c = s[1], h = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8), l = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8), f = h >>> 16 | 4294901760 & l, u = l << 16 | 65535 & h; n[0] ^= h, n[1] ^= f, n[2] ^= l, n[3] ^= u, n[4] ^= h, n[5] ^= f, n[6] ^= l, n[7] ^= u; for (var o = 0; o < 4; o++)r.call(this) } }, _doProcessBlock: function (t, e) { var i = this._X; r.call(this), s[0] = i[0] ^ i[5] >>> 16 ^ i[3] << 16, s[1] = i[2] ^ i[7] >>> 16 ^ i[5] << 16, s[2] = i[4] ^ i[1] >>> 16 ^ i[7] << 16, s[3] = i[6] ^ i[3] >>> 16 ^ i[1] << 16; for (var n = 0; n < 4; n++)s[n] = 16711935 & (s[n] << 8 | s[n] >>> 24) | 4278255360 & (s[n] << 24 | s[n] >>> 8), t[e + n] ^= s[n] }, blockSize: 4, ivSize: 2 }); e.RabbitLegacy = n._createHelper(h) }(), t.pad.ZeroPadding = { pad: function (t, r) { var e = 4 * r; t.clamp(), t.sigBytes += e - (t.sigBytes % e || e) }, unpad: function (t) { for (var r = t.words, e = t.sigBytes - 1; !(r[e >>> 2] >>> 24 - e % 4 * 8 & 255);)e--; t.sigBytes = e + 1 } }, t +}); -sign() +const $ = new Env('中国电信') +$.KEY_mobile = 'chavy_mobile_10000' +$.KEY_signbody = 'chavy_signbody_10000' -function sign() { - let url = { url: `https://wapside.189.cn:9001/api/home/sign`, headers: { Cookie: cookieVal } } - url.headers['Content-Type'] = 'application/json;charset=utf-8' - url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;CtClient;7.6.0;iOS;13.3;iPhone XR' - url.headers['Host'] = 'wapside.189.cn:9001' - url.headers['Origin'] = 'https://wapside.189.cn:9001' - url.headers['Referer'] = 'https://wapside.189.cn:9001/resources/dist/signInActivity.html?cmpid=jt-khd-my-zygn&ticket=0ab000281b4a8139f264620ae1d8b1ce067a6587921f90a6260dca4389a4e01a&version=7.6.0' - url.body = JSON.stringify({ phone: mobileVal }) - chavy.post(url, (error, response, data) => { - chavy.log(`${cookieName}, data: ${data}`) - let result = JSON.parse(data) - const title = `${cookieName}` - let subTitle = `` - let detail = `` - if (result.data.code == 1) { - subTitle = `签到结果: 成功 (${mobileVal})` - detail = `获得金币${result.data.coin}, 金豆${result.data.flow}` - } else if (result.data.code == 0) { - subTitle = `签到结果: 重复 (${mobileVal})` - detail = `说明: ${result.data.msg}` +!(async () => { + $.CryptoJS = $.isNode() ? require('crypto-js') : CryptoJS + await signapp() + await gethomeinfo() + await showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +async function signapp() { + const phonedat = $.getdata($.KEY_mobile) + const phones = [undefined, null, 'null', ''].includes(phonedat) ? [] : phonedat.replace(/\n/, '').split(',') + const signacts = [] + $.info = { + allcnt: 0, + succnt: 0, + repeatcnt: 0, + failcnt: 0, + signs: [] + } + for (let phoneIdx = 0; phoneIdx < phones.length; phoneIdx++) { + signacts.push( + await new Promise((resolve) => { + const phone = phones[phoneIdx].trim() + const bodystr = `{"phone":"${phone}","date":${new Date().getTime()},"signSource":"smlprgrm"}` + const body = JSON.stringify({ encode: encrypt(bodystr) }) + const url = { url: 'https://wapside.189.cn:9001/api/home/sign', body, headers: {} } + url.headers['Content-Type'] = 'application/json;charset=UTF-8' + $.post(url, (err, resp, data) => { + try { + const _data = JSON.parse(data) + const _code = $.lodash_get(_data, 'data.code') + const _msg = $.lodash_get(_data, 'data.msg') + const sign = {} + sign._raw = _data + sign.idx = phoneIdx + 1 + sign.phone = phone + sign.isSuc = _code === 1 + sign.isRepeat = _code === 0 && /已签到/.test(_msg) + sign.msg = _msg + $.info.signs.push(sign) + $.info.allcnt += 1 + if (sign.isSuc) $.info.succnt += 1 + else if (sign.isRepeat) $.info.repeatcnt += 1 + else $.info.failcnt += 1 + } catch (e) { + const sign = {} + sign._raw = data + sign.idx = phoneIdx + 1 + sign.phone = phone + sign.isSuc = false + sign.msg = e + $.info.signs.push(sign) + $.info.failcnt += 1 + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) + ) + } + return await Promise.all(signacts) +} + +function gethomeinfo() { + return new Promise((resolve) => { + const homebody = $.getdata($.KEY_signbody) + const url = { url: 'https://wapside.189.cn:9001/api/home/homeInfo', body : homebody, headers: {} } + url.headers['Content-Type'] = 'application/json;charset=UTF-8' + if (!homebody) + { + resolve() + return; + } + $.post(url, (err, resp, data) => { + try { + const _data = JSON.parse(data); + if (_data.resoultCode == "0") + { + $.info.signs[0].homeinfo = `金币总数:${_data.data.userInfo.totalCoin},${_data.data.tipInfo.tipInfoLeft}` + } else + { + $.info.signs[0].homeinfo = `获取金币信息失败:${_data.resoultMsg}`; + } + } catch (e) { + $.info.signs[0].homeinfo = `获取金币信息失败:${e.message}`; + } finally { + resolve() + } + }) + }) +} + +function showmsg() { + return new Promise((resolve) => { + if ($.info.signs.length === 0) { + $.subt = '请在 BoxJs 填写手机号码!' + $.desc = '' } else { - subTitle = `签到结果: 失败 (${mobileVal})` - detail = `说明: ${result.data.msg}` + $.subt = `共签: ${$.info.succnt + $.info.repeatcnt}/${$.info.allcnt}, 本次成功: ${$.info.succnt}, 本次失败: ${$.info.failcnt}` + $.desc = [] + $.desc.push('点击查看详情') + for (let signIdx = 0; signIdx < $.info.signs.length; signIdx++) { + const sign = $.info.signs[signIdx] + $.desc.push('', `${sign.idx}. ${sign.phone}`) + $.desc.push(` ${sign.msg}`) + $.desc.push(`${typeof(sign.homeinfo) == "undefined" ? '' : sign.homeinfo}`) + } + $.desc = $.desc.join('\n') } - chavy.msg(title, subTitle, detail) + $.msg($.name, $.subt, $.desc) + resolve() }) - chavy.done() } -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) - } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) - } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +function encrypt(word) { + const srcs = $.CryptoJS.enc.Utf8.parse(word) + const key = $.CryptoJS.enc.Utf8.parse('34d7cb0bcdf07523') + const encrypted = $.CryptoJS.AES.encrypt(srcs, key, { mode: $.CryptoJS.mode.ECB, padding: $.CryptoJS.pad.Pkcs7 }) + return $.CryptoJS.enc.Hex.stringify($.CryptoJS.enc.Base64.parse(encrypted.toString())) } + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/10000/README.md b/10000/README.md index f34e36e31..bda7e8449 100644 --- a/10000/README.md +++ b/10000/README.md @@ -1,12 +1,7 @@ # 电信营业厅 -> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 - -> 不需要手动编辑脚本 (获取 Cookie 和手机号码都由脚本自动完成) - -> 需要`两条`重写脚本, 且两条脚本`都是不同的` (请完整复制! 请完整复制! 请完整复制!) - -> Surge 与 QuanX 的 `MITM` 不一样! 不一样! 不一样! +> 2020.5.6 更新签到脚本 (正则和 rewrite 类型都有变化, 需要重取 Cookie) +> 2020.8.7 更新获取金币body ## 配置 (Surge) @@ -15,8 +10,7 @@ wapside.189.cn:9001 [Script] -http-request ^https:\/\/wapside.189.cn:9001\/api\/home\/homeInfo script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.cookie.js -http-response ^https:\/\/wapside.189.cn:9001\/api\/home\/homeInfo script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.cookie.js, requires-body=true +http-request ^https:\/\/wapside.189.cn:9001\/jt-sign\/api\/home\/homeInfo script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.cookie.js, requires-body=true cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.js ``` @@ -28,8 +22,7 @@ wapside.189.cn [rewrite_local] # 190及以后版本 -^https:\/\/wapside.189.cn:9001\/api\/home\/homeInfo url script-request-header 10000.cookie.js -^https:\/\/wapside.189.cn:9001\/api\/home\/homeInfo url script-response-body 10000.cookie.js +^https:\/\/wapside.189.cn:9001\/api\/home\/homeInfo url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.cookie.js [task_local] 1 0 * * * 10000.js diff --git a/10010/10010.cookie.js b/10010/10010.cookie.js index 94ffa29fc..a121f17a0 100644 --- a/10010/10010.cookie.js +++ b/10010/10010.cookie.js @@ -3,6 +3,10 @@ const tokenurlKey = 'chavy_tokenurl_10010' const tokenheaderKey = 'chavy_tokenheader_10010' const signurlKey = 'chavy_signurl_10010' const signheaderKey = 'chavy_signheader_10010' +const loginlotteryurlKey = 'chavy_loginlotteryurl_10010' +const loginlotteryheaderKey = 'chavy_loginlotteryheader_10010' +const findlotteryurlKey = 'chavy_findlotteryurl_10010' +const findlotteryheaderKey = 'chavy_findlotteryheader_10010' const chavy = init() if ($request && $request.method != 'OPTIONS' && $request.url.indexOf('querySigninActivity.htm') >= 0) { @@ -10,13 +14,25 @@ if ($request && $request.method != 'OPTIONS' && $request.url.indexOf('querySigni const tokenheaderVal = JSON.stringify($request.headers) if (tokenurlVal) chavy.setdata(tokenurlVal, tokenurlKey) if (tokenheaderVal) chavy.setdata(tokenheaderVal, tokenheaderKey) - title = chavy.msg(cookieName, `获取刷新链接: 成功`, ``) -} else if ($request && $request.method != 'OPTIONS' && $request.url.indexOf('daySign.do') >= 0) { + chavy.msg(cookieName, `获取刷新链接: 成功`, ``) +} else if ($request && $request.method != 'OPTIONS' && $request.url.indexOf('daySign') >= 0) { const signurlVal = $request.url const signheaderVal = JSON.stringify($request.headers) if (signurlVal) chavy.setdata(signurlVal, signurlKey) if (signheaderVal) chavy.setdata(signheaderVal, signheaderKey) - title = chavy.msg(cookieName, `获取Cookie: 成功`, ``) + chavy.msg(cookieName, `获取Cookie: 成功 (每日签到)`, ``) +} else if ($request && $request.method != 'OPTIONS' && $request.url.indexOf('userLogin') >= 0) { + const loginlotteryurlVal = $request.url + const loginlotteryheaderVal = JSON.stringify($request.headers) + if (loginlotteryurlVal) chavy.setdata(loginlotteryurlVal, loginlotteryurlKey) + if (loginlotteryheaderVal) chavy.setdata(loginlotteryheaderVal, loginlotteryheaderKey) + chavy.msg(cookieName, `获取Cookie: 成功 (登录抽奖)`, ``) +} else if ($request && $request.method != 'OPTIONS' && $request.url.indexOf('findActivityInfo') >= 0) { + const findlotteryurlVal = $request.url + const findlotteryheaderVal = JSON.stringify($request.headers) + if (findlotteryurlVal) chavy.setdata(findlotteryurlVal, findlotteryurlKey) + if (findlotteryheaderVal) chavy.setdata(findlotteryheaderVal, findlotteryheaderKey) + chavy.msg(cookieName, `获取Cookie: 成功 (抽奖次数)`, ``) } function init() { diff --git a/10010/10010.js b/10010/10010.js index d5669f93a..3180a18e0 100644 --- a/10010/10010.js +++ b/10010/10010.js @@ -1,165 +1,268 @@ -const cookieName = '中国联通' -const tokenurlKey = 'chavy_tokenurl_10010' -const tokenheaderKey = 'chavy_tokenheader_10010' -const signurlKey = 'chavy_signurl_10010' -const signheaderKey = 'chavy_signheader_10010' const chavy = init() -const tokenurlVal = chavy.getdata(tokenurlKey) -const tokenheaderVal = chavy.getdata(tokenheaderKey) -const signurlVal = chavy.getdata(signurlKey) -let signheaderVal = chavy.getdata(signheaderKey) +const cookieName = '中国联通' +const KEY_loginurl = 'chavy_tokenurl_10010' +const KEY_loginheader = 'chavy_tokenheader_10010' +const KEY_signurl = 'chavy_signurl_10010' +const KEY_signheader = 'chavy_signheader_10010' +const KEY_loginlotteryurl = 'chavy_loginlotteryurl_10010' +const KEY_loginlotteryheader = 'chavy_loginlotteryheader_10010' +const KEY_findlotteryurl = 'chavy_findlotteryurl_10010' +const KEY_findlotteryheader = 'chavy_findlotteryheader_10010' +const chavygolottery = true +const chavygosign = true + const signinfo = {} +let VAL_loginurl = chavy.getdata(KEY_loginurl) +let VAL_loginheader = chavy.getdata(KEY_loginheader) +let VAL_signurl = chavy.getdata(KEY_signurl) +let VAL_signheader = chavy.getdata(KEY_signheader) +let VAL_loginlotteryurl = chavy.getdata(KEY_loginlotteryurl) +let VAL_loginlotteryheader = chavy.getdata(KEY_loginlotteryheader) +let VAL_findlotteryurl = chavy.getdata(KEY_findlotteryurl) +let VAL_findlotteryheader = chavy.getdata(KEY_findlotteryheader) +let golottery = JSON.parse(chavy.getdata("chavy_golottery_10010")||chavygolottery) +let gosign = JSON.parse(chavy.getdata("chavy_gosign_10010")||chavygosign) -sign() +;(sign = async () => { + chavy.log(`🔔 ${cookieName}`) + await loginapp() + if (gosign == true) await signapp() + if (golottery == true) { + if (VAL_loginlotteryurl && VAL_findlotteryurl) await loginlottery() + if (signinfo.encryptmobile) { + await findlottery() + if (signinfo.findlottery && signinfo.findlottery.acFrequency && signinfo.findlottery.acFrequency.usableAcFreq) { + for (let i = 0; i < signinfo.findlottery.acFrequency.usableAcFreq; i++) { + await lottery() + } + } + } + } + await getinfo() + showmsg() +})() + .catch((e) => chavy.log(`❌ ${cookieName} 签到失败: ${e}`)) + .finally(() => chavy.done()) -function sign() { - signapp() - getinfo() - // getdetail() - check() +function loginapp() { + return new Promise((resolve, reject) => { + const url = { url: VAL_loginurl, headers: JSON.parse(VAL_loginheader) } + chavy.post(url, (error, response, data) => { + try { + resolve() + } catch (e) { + chavy.msg(cookieName, `登录结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} loginapp - 登录失败: ${e}`) + chavy.log(`❌ ${cookieName} loginapp - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) } -function gettel() { - const reqheaders = JSON.parse(signheaderVal) - const reqreferer = reqheaders.Referer - const reqCookie = reqheaders.Cookie - let tel = '' - if (reqreferer.indexOf(`desmobile=`) >= 0) tel = reqreferer.match(/desmobile=(.*?)(&|$)/)[1] - if (tel == '' && reqCookie.indexOf(`u_account=`) >= 0) tel = reqCookie.match(/u_account=(.*?);/)[1] - return tel +function signapp() { + return new Promise((resolve, reject) => { + if (VAL_signurl.endsWith('.do')) VAL_signurl = VAL_signurl.replace('.do', '') + const url = { url: 'https://act.10010.com/SigninApp/signin/daySign', headers: JSON.parse(VAL_signheader) } + chavy.post(url, (error, response, data) => { + try { + signinfo.signapp = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `签到结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} signapp - 签到失败: ${e}`) + chavy.log(`❌ ${cookieName} signapp - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) } -function loginapp(cb) { - const url = { url: tokenurlVal, headers: JSON.parse(tokenheaderVal) } - chavy.get(url, (error, response, data) => { - const respcookie = response.headers['Set-Cookie'] - const signheaderObj = JSON.parse(signheaderVal) - let signcookie = signheaderObj['Cookie'] - signcookie = signcookie.replace(/route5=([^;]*)/, respcookie.match(/route5=([^;]*)/)[0]) - signcookie = signcookie.replace(/JSESSIONID=([^;]*)/, respcookie.match(/JSESSIONID=([^;]*)/)[0]) - signheaderObj['Cookie'] = signcookie - signheaderVal = JSON.stringify(signheaderObj) - cb() - }) +function loginlottery() { + return new Promise((resolve, reject) => { + const url = { url: VAL_loginlotteryurl, headers: JSON.parse(VAL_loginlotteryheader) } + chavy.get(url, (error, response, data) => { + try { + const encryptmobileMatch = data.match(/encryptmobile=([^('|")]*)/) + if (encryptmobileMatch) { + signinfo.encryptmobile = encryptmobileMatch[1] + } else { + chavy.msg(cookieName, `获取抽奖令牌: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} loginlottery - 获取抽奖令牌失败: ${e}`) + chavy.log(`❌ ${cookieName} loginlottery - response: ${JSON.stringify(response)}`) + } + resolve() + } catch (e) { + chavy.msg(cookieName, `登录抽奖: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} loginlottery - 登录抽奖失败: ${e}`) + chavy.log(`❌ ${cookieName} loginlottery - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) } -function signapp() { - loginapp(() => { - chavy.log(`${cookieName}, signapp - signheaderVal: ${signheaderVal}`) - const url = { url: signurlVal, headers: JSON.parse(signheaderVal) } - url.body = `className=signinIndex` - chavy.post(url, (error, response, data) => (signinfo.signapp = data)) - }) +function findlottery() { + return new Promise((resolve, reject) => { + VAL_findlotteryurl = VAL_findlotteryurl.replace(/encryptmobile=[^(&|$)]*/, `encryptmobile=${signinfo.encryptmobile}`) + VAL_findlotteryurl = VAL_findlotteryurl.replace(/mobile=[^(&|$)]*/, `mobile=${signinfo.encryptmobile}`) + const url = { url: VAL_findlotteryurl, headers: JSON.parse(VAL_findlotteryheader) } + chavy.get(url, (error, response, data) => { + try { + signinfo.findlottery = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `获取抽奖次数: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} findlottery - 获取抽奖次数失败: ${e}`) + chavy.log(`❌ ${cookieName} findlottery - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) } -function getinfo() { - const tel = gettel() - const url = { url: `https://mina.10010.com/wxapplet/bind/getIndexData/alipay/alipaymini?user_id=${tel}` } - chavy.log(`${cookieName}, getinfo - tel: ${tel}`) - chavy.get(url, (error, response, data) => (signinfo.info = data)) +function lottery() { + return new Promise((resolve, reject) => { + const url = { url: `https://m.client.10010.com/dailylottery/static/doubleball/choujiang?usernumberofjsp=${signinfo.encryptmobile}`, headers: JSON.parse(VAL_loginlotteryheader) } + url.headers['Referer'] = `https://m.client.10010.com/dailylottery/static/doubleball/firstpage?encryptmobile=${signinfo.encryptmobile}` + chavy.post(url, (error, response, data) => { + try { + signinfo.lotterylist = signinfo.lotterylist ? signinfo.lotterylist : [] + signinfo.lotterylist.push(JSON.parse(data)) + resolve() + } catch (e) { + chavy.msg(cookieName, `抽奖结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} lottery - 抽奖失败: ${e}`) + chavy.log(`❌ ${cookieName} lottery - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) } -function getdetail() { - const url = { url: `https://mina.10010.com/wxapplet/bind/getCombospare/alipay/alipaymini?stoken=&user_id=${gettel()}` } - chavy.get(url, (error, response, data) => (signinfo.detail = data)) +function gettel() { + const reqheaders = JSON.parse(VAL_signheader) + const reqreferer = reqheaders.Referer + const reqCookie = reqheaders.Cookie + let tel = '' + if (reqreferer.indexOf(`desmobile=`) >= 0) tel = reqreferer.match(/desmobile=(.*?)(&|$)/)[1] + if (tel == '' && reqCookie.indexOf(`u_account=`) >= 0) tel = reqCookie.match(/u_account=(.*?);/)[1] + return tel } -function check(checkms = 0) { - if (signinfo.signapp && signinfo.info) { - chavy.log(`${cookieName}, signapp: ${signinfo.signapp}`) - chavy.log(`${cookieName}, info: ${signinfo.info}`) - // chavy.log(`${cookieName}, detail: ${signinfo.detail}`) - signinfo.signapp = JSON.parse(signinfo.signapp) - signinfo.info = JSON.parse(signinfo.info) - // signinfo.detail = JSON.parse(signinfo.detail) - showmsg() - } else { - if (checkms > 5000) { - chavy.log(`${cookieName}, signapp: ${signinfo.signapp}`) - chavy.log(`${cookieName}, info: ${signinfo.info}`) - // chavy.log(`${cookieName}, detail: ${signinfo.detail}`) - chavy.msg(`${cookieName}`, `签到失败: 超时退出`, ``) - chavy.done() - } else { - setTimeout(() => check(checkms + 100), 100) - } - } + +function getinfo() { + return new Promise((resolve, reject) => { + const url = { url: `https://m.client.10010.com/mobileService/home/queryUserInfoSeven.htm?version=iphone_c@7.0403&desmobiel=${gettel()}&showType=3`, headers: {"Cookie": JSON.parse(VAL_loginheader)["Cookie"]}} + chavy.get(url, (error, response, data) => { + try { + signinfo.info = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `获取余量: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} getinfo - 获取余量失败: ${e}`) + chavy.log(`❌ ${cookieName} getinfo - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) } function showmsg() { - let subTitle = '' - let detail = '' - let signday = '' - - // 签到结果 - if (signinfo.signapp.msgCode == '0000') { - subTitle = `签到结果: 成功` - signday = ` (连签${signinfo.signapp.continuCount}天)` - detail = `连签: ${signinfo.signapp.continuCount}天, 积分: +${signinfo.signapp.prizeCount}` - } else if (signinfo.signapp.msgCode == '0008') { - subTitle = `签到结果: 成功 (重复签到)` - } else { - subTitle = `签到结果: 失败` - } + let subTitle = '' + let detail = '' + console.log(signinfo) + // 签到结果 + if (gosign == true) { + if (signinfo.signapp.status == '0000') { + subTitle = `签到: 成功 ` + detail = `积分: +${signinfo.signapp.data.prizeCount}, 成长值: +${signinfo.signapp.data.growthV}, 鲜花: +${signinfo.signapp.data.flowerCount}` + } else if (signinfo.signapp.status == '0002') { + subTitle = `签到: 重复 ` + } else { + subTitle = `签到: 失败 ` + chavy.log(`❌ ${cookieName} signapp - response: ${JSON.stringify(signinfo.signapp)}`) + } + } - // 基本信息 - if (signinfo.info.code == '0000') { - subTitle += signday - detail = detail ? `${detail}\n` : `` - const free = signinfo.info.dataList[0] - const flow = signinfo.info.dataList[1] - const voice = signinfo.info.dataList[2] - detail = `话费: ${free.number}${free.unit}, 已用: ${flow.number}${flow.unit}, 剩余: ${voice.number}${voice.unit}` - } + if (signinfo.info.code == 'Y') { + // 基本信息 + detail = detail ? `${detail}\n` : `` + const traffic = signinfo.info.data.dataList[0] + const flow = signinfo.info.data.dataList[1] + const voice = signinfo.info.data.dataList[2] + const credit = signinfo.info.data.dataList[3] + const back = signinfo.info.data.dataList[4] + const money = signinfo.info.data.dataList[5] + detail = `${traffic.remainTitle}: ${traffic.number}${traffic.unit}, ${flow.remainTitle}: ${flow.number}${flow.unit}, ${voice.remainTitle}: ${voice.number}${voice.unit}, ${credit.remainTitle}: ${credit.number}${credit.unit}, ${back.remainTitle}: ${back.number}${back.unit}, ${money.remainTitle}: ${money.number}${money.unit}` + } else { + chavy.log(`❌ ${cookieName} signapp - response: ${JSON.stringify(signinfo.info)}`) + } + + if (golottery == true) { + if (signinfo.findlottery && signinfo.findlottery.acFrequency && signinfo.lotterylist) { + subTitle += `抽奖: ${signinfo.findlottery.acFrequency.usableAcFreq}次` + detail += '\n查看详情\n' - // 详细信息 - // if (signinfo.detail.code == '0000') { - // } + for (let i = 0; i < signinfo.findlottery.acFrequency.usableAcFreq; i++) { + detail += `\n抽奖 (${i + 1}): ${signinfo.lotterylist[i].RspMsg}` + } + } else { + chavy.log(`❌ ${cookieName} signapp - response: ${JSON.stringify(signinfo.findlottery)}`) + } + } - chavy.msg(cookieName, subTitle, detail) - chavy.done() + chavy.msg(cookieName, subTitle, detail) } function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + log = (message) => console.log(message) + get = (url, cb) => { + if (url['headers'] != undefined) { + delete url['headers']['Content-Length'] + console.log(url['headers']) + } + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } } - } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) + post = (url, cb) => { + if (url['headers'] != undefined) { + delete url['headers']['Content-Length'] + console.log(url['headers']) + } + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + done = (value = {}) => { + $done(value) } - } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } } diff --git a/10010/README.md b/10010/README.md index 6e29fdd89..70e719429 100644 --- a/10010/README.md +++ b/10010/README.md @@ -6,16 +6,21 @@ > 如果你希望显示话费、语音、流量信息,请在支付宝中搜索小程序“中国联通”并授权登录一次 +> 2020.3.12 增加每日抽奖 (需要进抽奖页面获取 Cookie) (进抽奖页会弹两个获取 Cookie 成功的消息) (签到 Cookie 不用重新获取) (增加了 rewrite 和 mitm), 注意看操作步骤说明 + +> 2020.5.6 修复签到报错问题 + ## 配置 (Surge) ```properties [MITM] -act.10010.com +hostname = act.10010.com, m.client.10010.com [Script] # 注意获取Cookie有两条脚本 -http-request ^https:\/\/act.10010.com\/SigninApp\/signin\/querySigninActivity.htm script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js -http-request ^https:\/\/act.10010.com\/SigninApp(.*?)\/signin\/daySign.do script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js +http-request ^https?:\/\/act.10010.com\/SigninApp\/signin\/querySigninActivity.htm script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js +http-request ^https?:\/\/act.10010.com\/SigninApp(.*?)\/signin\/daySign script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js +http-request ^https?:\/\/m.client.10010.com\/dailylottery\/static\/(textdl\/userLogin|active\/findActivityInfo) script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.js ``` @@ -23,12 +28,13 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr ```properties [MITM] -act.10010.com +hostname = act.10010.com, m.client.10010.com [rewrite_local] # 注意获取Cookie有两条脚本 -^https:\/\/act.10010.com\/SigninApp\/signin\/querySigninActivity.htm url script-request-header 10010.cookie.js -^https:\/\/act.10010.com\/SigninApp(.*?)\/signin\/daySign.do url script-request-header 10010.cookie.js +^https?:\/\/act.10010.com\/SigninApp\/signin\/querySigninActivity.htm url script-request-header 10010.cookie.js +^https?:\/\/act.10010.com\/SigninApp(.*?)\/signin\/daySign url script-request-header 10010.cookie.js +^https?:\/\/m.client.10010.com\/dailylottery\/static\/(textdl\/userLogin|active\/findActivityInfo) url script-request-header 10010.cookie.js [task_local] 1 0 * * * 10010.js @@ -36,14 +42,15 @@ act.10010.com ## 说明 -1. 先把`act.10010.com`加到`[MITM]` +1. 先把`act.10010.com, m.client.10010.com`加到`[MITM]` 2. 再配置重写规则: - Surge: 把两条远程脚本放到`[Script]` - QuanX: 把`10010.cookie.js`和`10010.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) 3. 打开 APP , 进入签到页面, 系统提示: `获取刷新链接: 成功` -4. 然后手动签到 1 次, 系统提示: `获取Cookie: 成功` -5. 把获取 Cookie 的脚本注释掉 -6. 运行一次脚本, 如果提示重复签到, 那就算成功了! +4. 然后手动签到 1 次, 系统提示: `获取Cookie: 成功 (每日签到)` +5. 首页>天天抽奖, 系统提示 `2` 次: `获取Cookie: 成功 (登录抽奖)` 和 `获取Cookie: 成功 (抽奖次数)` +6. 把获取 Cookie 的脚本注释掉 +7. 运行一次脚本, 如果提示重复签到, 那就算成功了! > 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. diff --git a/BOXJS.png b/BOXJS.png new file mode 100644 index 000000000..c4d3f5876 Binary files /dev/null and b/BOXJS.png differ diff --git a/BoxJS.gif b/BoxJS.gif new file mode 100644 index 000000000..8a5bb919c Binary files /dev/null and b/BoxJS.gif differ diff --git a/Env.js b/Env.js new file mode 100644 index 000000000..f445263c8 --- /dev/null +++ b/Env.js @@ -0,0 +1,910 @@ +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 + } + + const delayPromise = (promise, delay = 1000) => { + return Promise.race([ + promise, + new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error('请求超时')) + }, delay) + }) + ]) + } + + const call = new Promise((resolve, reject) => { + sender.call(this, opts, (err, resp, body) => { + if (err) reject(err) + else resolve(resp) + }) + }) + + return opts.timeout ? delayPromise(call, opts.timeout) : call + } + + 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.logLevels = { debug: 0, info: 1, warn: 2, error: 3 } + this.logLevelPrefixs = { + debug: '[DEBUG] ', + info: '[INFO] ', + warn: '[WARN] ', + error: '[ERROR] ' + } + this.logLevel = 'info' + 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.encoding = 'utf-8' + this.startTime = new Date().getTime() + Object.assign(this, opts) + this.log('', `🔔${this.name}, 开始!`) + } + + getEnv() { + if ('undefined' !== typeof Egern) return 'Egern' + if ('undefined' !== typeof $environment && $environment['surge-version']) + return 'Surge' + if ('undefined' !== typeof $environment && $environment['stash-version']) + return 'Stash' + if ('undefined' !== typeof module && !!module.exports) return 'Node.js' + if ('undefined' !== typeof $task) return 'Quantumult X' + if ('undefined' !== typeof $loon) return 'Loon' + if ('undefined' !== typeof $rocket) return 'Shadowrocket' + } + + isNode() { + return 'Node.js' === this.getEnv() + } + + isQuanX() { + return 'Quantumult X' === this.getEnv() + } + + isSurge() { + return 'Surge' === this.getEnv() + } + + isLoon() { + return 'Loon' === this.getEnv() + } + + isShadowrocket() { + return 'Shadowrocket' === this.getEnv() + } + + isStash() { + return 'Stash' === this.getEnv() + } + + isEgern() { + return 'Egern' === this.getEnv() + } + + toObj(str, defaultValue = null) { + try { + return JSON.parse(str) + } catch { + return defaultValue + } + } + + toStr(obj, defaultValue = null, ...args) { + try { + return JSON.stringify(obj, ...args) + } 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': '*/*' + }, + policy: 'DIRECT', + timeout: httpapi_timeout + } + 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) { + switch (this.getEnv()) { + case 'Surge': + case 'Loon': + case 'Stash': + case 'Shadowrocket': + case 'Egern': + return $persistentStore.read(key) + case 'Quantumult X': + return $prefs.valueForKey(key) + case 'Node.js': + this.data = this.loaddata() + return this.data[key] + default: + return (this.data && this.data[key]) || null + } + } + + setval(val, key) { + switch (this.getEnv()) { + case 'Surge': + case 'Loon': + case 'Stash': + case 'Shadowrocket': + case 'Egern': + return $persistentStore.write(val, key) + case 'Quantumult X': + return $prefs.setValueForKey(val, key) + case 'Node.js': + this.data = this.loaddata() + this.data[key] = val + this.writedata() + return true + default: + 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 (opts) { + opts.headers = opts.headers ? opts.headers : {} + if ( + undefined === opts.headers.cookie && + undefined === opts.headers.Cookie && + undefined === opts.cookieJar + ) { + opts.cookieJar = this.ckjar + } + } + } + } + + get(request, callback = () => {}) { + if (request.headers) { + delete request.headers['Content-Type'] + delete request.headers['Content-Length'] + + // HTTP/2 全是小写 + delete request.headers['content-type'] + delete request.headers['content-length'] + } + if (request.params) { + request.url += '?' + this.queryStr(request.params) + } + // followRedirect 禁止重定向 + if ( + typeof request.followRedirect !== 'undefined' && + !request['followRedirect'] + ) { + if (this.isSurge() || this.isLoon()) request['auto-redirect'] = false // Surge & Loon + if (this.isQuanX()) + request.opts + ? (request['opts']['redirection'] = false) + : (request.opts = { redirection: false }) // Quantumult X + } + switch (this.getEnv()) { + case 'Surge': + case 'Loon': + case 'Stash': + case 'Shadowrocket': + case 'Egern': + default: + if (this.isSurge() && this.isNeedRewrite) { + request.headers = request.headers || {} + Object.assign(request.headers, { 'X-Surge-Skip-Scripting': false }) + } + $httpClient.get(request, (err, resp, body) => { + if (!err && resp) { + resp.body = body + resp.statusCode = resp.status ? resp.status : resp.statusCode + resp.status = resp.statusCode + } + callback(err, resp, body) + }) + break + case 'Quantumult X': + if (this.isNeedRewrite) { + request.opts = request.opts || {} + Object.assign(request.opts, { hints: false }) + } + $task.fetch(request).then( + (resp) => { + const { + statusCode: status, + statusCode, + headers, + body, + bodyBytes + } = resp + callback( + null, + { status, statusCode, headers, body, bodyBytes }, + body, + bodyBytes + ) + }, + (err) => callback((err && err.error) || 'UndefinedError') + ) + break + case 'Node.js': + let iconv = require('iconv-lite') + this.initGotEnv(request) + this.got(request) + .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, + rawBody + } = resp + const body = iconv.decode(rawBody, this.encoding) + callback( + null, + { status, statusCode, headers, rawBody, body }, + body + ) + }, + (err) => { + const { message: error, response: resp } = err + callback( + error, + resp, + resp && iconv.decode(resp.rawBody, this.encoding) + ) + } + ) + break + } + } + + post(request, callback = () => {}) { + const method = request.method + ? request.method.toLocaleLowerCase() + : 'post' + + // 如果指定了请求体, 但没指定 `Content-Type`、`content-type`, 则自动生成。 + if ( + request.body && + request.headers && + !request.headers['Content-Type'] && + !request.headers['content-type'] + ) { + // HTTP/1、HTTP/2 都支持小写 headers + request.headers['content-type'] = 'application/x-www-form-urlencoded' + } + // 为避免指定错误 `content-length` 这里删除该属性,由工具端 (HttpClient) 负责重新计算并赋值 + if (request.headers) { + delete request.headers['Content-Length'] + delete request.headers['content-length'] + } + // followRedirect 禁止重定向 + if ( + typeof request.followRedirect !== 'undefined' && + !request['followRedirect'] + ) { + if (this.isSurge() || this.isLoon()) request['auto-redirect'] = false // Surge & Loon + if (this.isQuanX()) + request.opts + ? (request['opts']['redirection'] = false) + : (request.opts = { redirection: false }) // Quantumult X + } + switch (this.getEnv()) { + case 'Surge': + case 'Loon': + case 'Stash': + case 'Shadowrocket': + case 'Egern': + default: + if (this.isSurge() && this.isNeedRewrite) { + request.headers = request.headers || {} + Object.assign(request.headers, { 'X-Surge-Skip-Scripting': false }) + } + $httpClient[method](request, (err, resp, body) => { + if (!err && resp) { + resp.body = body + resp.statusCode = resp.status ? resp.status : resp.statusCode + resp.status = resp.statusCode + } + callback(err, resp, body) + }) + break + case 'Quantumult X': + request.method = method + if (this.isNeedRewrite) { + request.opts = request.opts || {} + Object.assign(request.opts, { hints: false }) + } + $task.fetch(request).then( + (resp) => { + const { + statusCode: status, + statusCode, + headers, + body, + bodyBytes + } = resp + callback( + null, + { status, statusCode, headers, body, bodyBytes }, + body, + bodyBytes + ) + }, + (err) => callback((err && err.error) || 'UndefinedError') + ) + break + case 'Node.js': + let iconv = require('iconv-lite') + this.initGotEnv(request) + const { url, ..._request } = request + this.got[method](url, _request).then( + (resp) => { + const { statusCode: status, statusCode, headers, rawBody } = resp + const body = iconv.decode(rawBody, this.encoding) + callback( + null, + { status, statusCode, headers, rawBody, body }, + body + ) + }, + (err) => { + const { message: error, response: resp } = err + callback( + error, + resp, + resp && iconv.decode(resp.rawBody, this.encoding) + ) + } + ) + break + } + } + /** + * + * 示例:$.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 + } + + /** + * + * @param {Object} options + * @returns {String} 将 Object 对象 转换成 queryStr: key=val&name=senku + */ + queryStr(options) { + let queryString = '' + + for (const key in options) { + let value = options[key] + if (value != null && value !== '') { + if (typeof value === 'object') { + value = JSON.stringify(value) + } + queryString += `${key}=${value}&` + } + } + queryString = queryString.substring(0, queryString.length - 1) + + return queryString + } + + /** + * 系统通知 + * + * > 通知参数: 同时支持 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) => { + const { $open, $copy, $media, $mediaMime } = rawopts + switch (typeof rawopts) { + case undefined: + return rawopts + case 'string': + switch (this.getEnv()) { + case 'Surge': + case 'Stash': + case 'Egern': + default: + return { url: rawopts } + case 'Loon': + case 'Shadowrocket': + return rawopts + case 'Quantumult X': + return { 'open-url': rawopts } + case 'Node.js': + return undefined + } + case 'object': + switch (this.getEnv()) { + case 'Surge': + case 'Stash': + case 'Shadowrocket': + case 'Egern': + default: { + const options = {} + + // 打开URL + let openUrl = + rawopts.openUrl || rawopts.url || rawopts['open-url'] || $open + if (openUrl) + Object.assign(options, { action: 'open-url', url: openUrl }) + + // 粘贴板 + let copy = + rawopts['update-pasteboard'] || + rawopts.updatePasteboard || + $copy + if (copy) { + Object.assign(options, { action: 'clipboard', text: copy }) + } + + // 图片通知 + let mediaUrl = + rawopts.mediaUrl || rawopts['media-url'] || $media + if (mediaUrl) { + let media = undefined + let mime = undefined + // http 开头的网络地址 + if (mediaUrl.startsWith('http')) { + //不做任何操作 + } + // 带标识的 Base64 字符串 + // data:image/png;base64,iVBORw0KGgo... + else if (mediaUrl.startsWith('data:')) { + const [data] = mediaUrl.split(';') + const [, base64str] = mediaUrl.split(',') + media = base64str + mime = data.replace('data:', '') + } + // 没有标识的 Base64 字符串 + // iVBORw0KGgo... + else { + // https://stackoverflow.com/questions/57976898/how-to-get-mime-type-from-base-64-string + const getMimeFromBase64 = (encoded) => { + const signatures = { + 'JVBERi0': 'application/pdf', + 'R0lGODdh': 'image/gif', + 'R0lGODlh': 'image/gif', + 'iVBORw0KGgo': 'image/png', + '/9j/': 'image/jpg' + } + for (var s in signatures) { + if (encoded.indexOf(s) === 0) { + return signatures[s] + } + } + return null + } + media = mediaUrl + mime = getMimeFromBase64(mediaUrl) + } + + Object.assign(options, { + 'media-url': mediaUrl, + 'media-base64': media, + 'media-base64-mime': $mediaMime ?? mime + }) + } + + Object.assign(options, { + 'auto-dismiss': rawopts['auto-dismiss'], + 'sound': rawopts['sound'] + }) + return options + } + case 'Loon': { + const options = {} + + let openUrl = + rawopts.openUrl || rawopts.url || rawopts['open-url'] || $open + if (openUrl) Object.assign(options, { openUrl }) + + let mediaUrl = + rawopts.mediaUrl || rawopts['media-url'] || $media + if (mediaUrl) Object.assign(options, { mediaUrl }) + + console.log(JSON.stringify(options)) + return options + } + case 'Quantumult X': { + const options = {} + + let openUrl = + rawopts['open-url'] || rawopts.url || rawopts.openUrl || $open + if (openUrl) Object.assign(options, { 'open-url': openUrl }) + + let mediaUrl = + rawopts.mediaUrl || rawopts['media-url'] || $media + if (mediaUrl) Object.assign(options, { 'media-url': mediaUrl }) + + let copy = + rawopts['update-pasteboard'] || + rawopts.updatePasteboard || + $copy + if (copy) Object.assign(options, { 'update-pasteboard': copy }) + + console.log(JSON.stringify(options)) + return options + } + case 'Node.js': + return undefined + } + default: + return undefined + } + } + if (!this.isMute) { + switch (this.getEnv()) { + case 'Surge': + case 'Loon': + case 'Stash': + case 'Shadowrocket': + case 'Egern': + default: + $notification.post(title, subt, desc, toEnvOpts(opts)) + break + case 'Quantumult X': + $notify(title, subt, desc, toEnvOpts(opts)) + break + case 'Node.js': + break + } + } + 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) + } + } + + debug(...logs) { + if (this.logLevels[this.logLevel] <= this.logLevels.debug) { + if (logs.length > 0) { + this.logs = [...this.logs, ...logs] + } + console.log( + `${this.logLevelPrefixs.debug}${logs.map((l) => l ?? String(l)).join(this.logSeparator)}` + ) + } + } + + info(...logs) { + if (this.logLevels[this.logLevel] <= this.logLevels.info) { + if (logs.length > 0) { + this.logs = [...this.logs, ...logs] + } + console.log( + `${this.logLevelPrefixs.info}${logs.map((l) => l ?? String(l)).join(this.logSeparator)}` + ) + } + } + + warn(...logs) { + if (this.logLevels[this.logLevel] <= this.logLevels.warn) { + if (logs.length > 0) { + this.logs = [...this.logs, ...logs] + } + console.log( + `${this.logLevelPrefixs.warn}${logs.map((l) => l ?? String(l)).join(this.logSeparator)}` + ) + } + } + + error(...logs) { + if (this.logLevels[this.logLevel] <= this.logLevels.error) { + if (logs.length > 0) { + this.logs = [...this.logs, ...logs] + } + console.log( + `${this.logLevelPrefixs.error}${logs.map((l) => l ?? String(l)).join(this.logSeparator)}` + ) + } + } + + log(...logs) { + if (logs.length > 0) { + this.logs = [...this.logs, ...logs] + } + console.log(logs.map((l) => l ?? String(l)).join(this.logSeparator)) + } + + logErr(err, msg) { + switch (this.getEnv()) { + case 'Surge': + case 'Loon': + case 'Stash': + case 'Shadowrocket': + case 'Egern': + case 'Quantumult X': + default: + this.log('', `❗️${this.name}, 错误!`, msg, err) + break + case 'Node.js': + this.log( + '', + `❗️${this.name}, 错误!`, + msg, + typeof err.message !== 'undefined' ? err.message : err, + err.stack + ) + break + } + } + + 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() + switch (this.getEnv()) { + case 'Surge': + case 'Loon': + case 'Stash': + case 'Shadowrocket': + case 'Egern': + case 'Quantumult X': + default: + $done(val) + break + case 'Node.js': + process.exit(1) + } + } + })(name, opts) +} diff --git a/Env.min.js b/Env.min.js new file mode 100644 index 000000000..615711747 --- /dev/null +++ b/Env.min.js @@ -0,0 +1 @@ +function Env(e,t){class s{constructor(e){this.env=e}send(e,t="GET"){e="string"==typeof e?{url:e}:e;let s=this.get;"POST"===t&&(s=this.post);const i=new Promise((t,i)=>{s.call(this,e,(e,s,o)=>{e?i(e):t(s)})});return e.timeout?((e,t=1e3)=>Promise.race([e,new Promise((e,s)=>{setTimeout(()=>{s(new Error("请求超时"))},t)})]))(i,e.timeout):i}get(e){return this.send.call(this.env,e)}post(e){return this.send.call(this.env,e,"POST")}}return new class{constructor(e,t){this.logLevels={debug:0,info:1,warn:2,error:3},this.logLevelPrefixs={debug:"[DEBUG] ",info:"[INFO] ",warn:"[WARN] ",error:"[ERROR] "},this.logLevel="info",this.name=e,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,t),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof Egern?"Egern":"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}isEgern(){return"Egern"===this.getEnv()}toObj(e,t=null){try{return JSON.parse(e)}catch{return t}}toStr(e,t=null,...s){try{return JSON.stringify(e,...s)}catch{return t}}getjson(e,t){let s=t;if(this.getdata(e))try{s=JSON.parse(this.getdata(e))}catch{}return s}setjson(e,t){try{return this.setdata(JSON.stringify(e),t)}catch{return!1}}getScript(e){return new Promise(t=>{this.get({url:e},(e,s,i)=>t(i))})}runScript(e,t){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let o=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");o=o?1*o:20,o=t&&t.timeout?t.timeout:o;const[r,a]=i.split("@"),n={url:`http://${a}/v1/scripting/evaluate`,body:{script_text:e,mock_type:"cron",timeout:o},headers:{"X-Key":r,Accept:"*/*"},policy:"DIRECT",timeout:o};this.post(n,(e,t,i)=>s(i))}).catch(e=>this.logErr(e))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const e=this.path.resolve(this.dataFile),t=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(e),i=!s&&this.fs.existsSync(t);if(!s&&!i)return{};{const i=s?e:t;try{return JSON.parse(this.fs.readFileSync(i))}catch(e){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const e=this.path.resolve(this.dataFile),t=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(e),i=!s&&this.fs.existsSync(t),o=JSON.stringify(this.data);s?this.fs.writeFileSync(e,o):i?this.fs.writeFileSync(t,o):this.fs.writeFileSync(e,o)}}lodash_get(e,t,s=void 0){const i=t.replace(/\[(\d+)\]/g,".$1").split(".");let o=e;for(const e of i)if(o=Object(o)[e],void 0===o)return s;return o}lodash_set(e,t,s){return Object(e)!==e||(Array.isArray(t)||(t=t.toString().match(/[^.[\]]+/g)||[]),t.slice(0,-1).reduce((e,s,i)=>Object(e[s])===e[s]?e[s]:e[s]=(Math.abs(t[i+1])|0)===+t[i+1]?[]:{},e)[t[t.length-1]]=s),e}getdata(e){let t=this.getval(e);if(/^@/.test(e)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(e),o=s?this.getval(s):"";if(o)try{const e=JSON.parse(o);t=e?this.lodash_get(e,i,""):t}catch(e){t=""}}return t}setdata(e,t){let s=!1;if(/^@/.test(t)){const[,i,o]=/^@(.*?)\.(.*?)$/.exec(t),r=this.getval(i),a=i?"null"===r?null:r||"{}":"{}";try{const t=JSON.parse(a);this.lodash_set(t,o,e),s=this.setval(JSON.stringify(t),i)}catch(t){const r={};this.lodash_set(r,o,e),s=this.setval(JSON.stringify(r),i)}}else s=this.setval(e,t);return s}getval(e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":return $persistentStore.read(e);case"Quantumult X":return $prefs.valueForKey(e);case"Node.js":return this.data=this.loaddata(),this.data[e];default:return this.data&&this.data[e]||null}}setval(e,t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":return $persistentStore.write(e,t);case"Quantumult X":return $prefs.setValueForKey(e,t);case"Node.js":return this.data=this.loaddata(),this.data[t]=e,this.writedata(),!0;default:return this.data&&this.data[t]||null}}initGotEnv(e){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,e&&(e.headers=e.headers?e.headers:{},e&&(e.headers=e.headers?e.headers:{},void 0===e.headers.cookie&&void 0===e.headers.Cookie&&void 0===e.cookieJar&&(e.cookieJar=this.ckjar)))}get(e,t=()=>{}){switch(e.headers&&(delete e.headers["Content-Type"],delete e.headers["Content-Length"],delete e.headers["content-type"],delete e.headers["content-length"]),e.params&&(e.url+="?"+this.queryStr(e.params)),void 0===e.followRedirect||e.followRedirect||((this.isSurge()||this.isLoon())&&(e["auto-redirect"]=!1),this.isQuanX()&&(e.opts?e.opts.redirection=!1:e.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":default:this.isSurge()&&this.isNeedRewrite&&(e.headers=e.headers||{},Object.assign(e.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(e,(e,s,i)=>{!e&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),t(e,s,i)});break;case"Quantumult X":this.isNeedRewrite&&(e.opts=e.opts||{},Object.assign(e.opts,{hints:!1})),$task.fetch(e).then(e=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=e;t(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)},e=>t(e&&e.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(e),this.got(e).on("redirect",(e,t)=>{try{if(e.headers["set-cookie"]){const s=e.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),t.cookieJar=this.ckjar}}catch(e){this.logErr(e)}}).then(e=>{const{statusCode:i,statusCode:o,headers:r,rawBody:a}=e,n=s.decode(a,this.encoding);t(null,{status:i,statusCode:o,headers:r,rawBody:a,body:n},n)},e=>{const{message:i,response:o}=e;t(i,o,o&&s.decode(o.rawBody,this.encoding))})}}post(e,t=()=>{}){const s=e.method?e.method.toLocaleLowerCase():"post";switch(e.body&&e.headers&&!e.headers["Content-Type"]&&!e.headers["content-type"]&&(e.headers["content-type"]="application/x-www-form-urlencoded"),e.headers&&(delete e.headers["Content-Length"],delete e.headers["content-length"]),void 0===e.followRedirect||e.followRedirect||((this.isSurge()||this.isLoon())&&(e["auto-redirect"]=!1),this.isQuanX()&&(e.opts?e.opts.redirection=!1:e.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":default:this.isSurge()&&this.isNeedRewrite&&(e.headers=e.headers||{},Object.assign(e.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](e,(e,s,i)=>{!e&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),t(e,s,i)});break;case"Quantumult X":e.method=s,this.isNeedRewrite&&(e.opts=e.opts||{},Object.assign(e.opts,{hints:!1})),$task.fetch(e).then(e=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=e;t(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)},e=>t(e&&e.error||"UndefinedError"));break;case"Node.js":let i=require("iconv-lite");this.initGotEnv(e);const{url:o,...r}=e;this.got[s](o,r).then(e=>{const{statusCode:s,statusCode:o,headers:r,rawBody:a}=e,n=i.decode(a,this.encoding);t(null,{status:s,statusCode:o,headers:r,rawBody:a,body:n},n)},e=>{const{message:s,response:o}=e;t(s,o,o&&i.decode(o.rawBody,this.encoding))})}}time(e,t=null){const s=t?new Date(t):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(e)&&(e=e.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let t in i)new RegExp("("+t+")").test(e)&&(e=e.replace(RegExp.$1,1==RegExp.$1.length?i[t]:("00"+i[t]).substr((""+i[t]).length)));return e}queryStr(e){let t="";for(const s in e){let i=e[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),t+=`${s}=${i}&`)}return t=t.substring(0,t.length-1),t}msg(t=e,s="",i="",o={}){const r=e=>{const{$open:t,$copy:s,$media:i,$mediaMime:o}=e;switch(typeof e){case void 0:return e;case"string":switch(this.getEnv()){case"Surge":case"Stash":case"Egern":default:return{url:e};case"Loon":case"Shadowrocket":return e;case"Quantumult X":return{"open-url":e};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":case"Egern":default:{const r={};let a=e.openUrl||e.url||e["open-url"]||t;a&&Object.assign(r,{action:"open-url",url:a});let n=e["update-pasteboard"]||e.updatePasteboard||s;n&&Object.assign(r,{action:"clipboard",text:n});let h=e.mediaUrl||e["media-url"]||i;if(h){let e,t;if(h.startsWith("http"));else if(h.startsWith("data:")){const[s]=h.split(";"),[,i]=h.split(",");e=i,t=s.replace("data:","")}else{e=h,t=(e=>{const t={JVBERi0:"application/pdf",R0lGODdh:"image/gif",R0lGODlh:"image/gif",iVBORw0KGgo:"image/png","/9j/":"image/jpg"};for(var s in t)if(0===e.indexOf(s))return t[s];return null})(h)}Object.assign(r,{"media-url":h,"media-base64":e,"media-base64-mime":o??t})}return Object.assign(r,{"auto-dismiss":e["auto-dismiss"],sound:e.sound}),r}case"Loon":{const s={};let o=e.openUrl||e.url||e["open-url"]||t;o&&Object.assign(s,{openUrl:o});let r=e.mediaUrl||e["media-url"]||i;return r&&Object.assign(s,{mediaUrl:r}),console.log(JSON.stringify(s)),s}case"Quantumult X":{const o={};let r=e["open-url"]||e.url||e.openUrl||t;r&&Object.assign(o,{"open-url":r});let a=e.mediaUrl||e["media-url"]||i;a&&Object.assign(o,{"media-url":a});let n=e["update-pasteboard"]||e.updatePasteboard||s;return n&&Object.assign(o,{"update-pasteboard":n}),console.log(JSON.stringify(o)),o}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":default:$notification.post(t,s,i,r(o));break;case"Quantumult X":$notify(t,s,i,r(o));case"Node.js":}if(!this.isMuteLog){let e=["","==============📣系统通知📣=============="];e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n")),this.logs=this.logs.concat(e)}}debug(...e){this.logLevels[this.logLevel]<=this.logLevels.debug&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.debug}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}info(...e){this.logLevels[this.logLevel]<=this.logLevels.info&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.info}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}warn(...e){this.logLevels[this.logLevel]<=this.logLevels.warn&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.warn}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}error(...e){this.logLevels[this.logLevel]<=this.logLevels.error&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.error}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}log(...e){e.length>0&&(this.logs=[...this.logs,...e]),console.log(e.map(e=>e??String(e)).join(this.logSeparator))}logErr(e,t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,t,e);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,t,void 0!==e.message?e.message:e,e.stack)}}wait(e){return new Promise(t=>setTimeout(t,e))}done(e={}){const t=((new Date).getTime()-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${t} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":case"Quantumult X":default:$done(e);break;case"Node.js":process.exit(1)}}}(e,t)} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..d43a18cdc --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Scripts Copyright (C) 2019-present chavyleung + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Loon.cookie.conf b/Loon.cookie.conf new file mode 100644 index 000000000..89181cf35 --- /dev/null +++ b/Loon.cookie.conf @@ -0,0 +1,66 @@ +# Chavyleung +http-request ^https?:\/\/tieba\.baidu\.com\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/tieba/tieba.cookie.js, tag=百度签到(网页) +http-request ^https:\/\/music.163.com\/weapi\/user\/level script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasemusic/neteasemusic.cookie.js, requires-body=true, tag=网易云音乐 +http-request ^https:\/\/www\.smzdm\.com\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/smzdm/smzdm.cookie.js, tag=什么值得买 +http-request ^https:\/\/www\.v2ex\.com\/mission\/daily script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/v2ex/v2ex.cookie.js, tag=V2ex +http-request ^https:\/\/(www|live)\.bilibili\.com\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.cookie.js, tag=哔哩哔哩 +http-request ^https:\/\/(www\.)?feng\.com\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.cookie.js, tag=威锋论坛 +http-request ^https:\/\/access.video.qq.com\/user\/auth_refresh script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.cookie.js, tag=腾讯视频 +http-request ^https:\/\/api\-new\.app\.acfun\.cn\/rest\/app\/user\/personalInfo script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/acfun/acfun.cookie.js, tag=AcFun +# http-request ^https?:\/\/(www\.)?rrys2020\.com\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/achived/zimuzu/zimuzu.cookie.js, tag=字幕组 [archived] +# http-request ^http:\/\/ios.zmzapi.com\/index.php.*a=(mobile_)?login script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/achived/zimuzu/zimuzu.cookie.js, tag=字幕组 [archived] +http-request ^https?:\/\/.*\/mobile\-user\/(v1\/)?homePage\/.* script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ximalaya/ximalaya.cookie.js,tag=喜马拉雅 +# http-request ^https:\/\/api\.rr\.tv\/user\/profile script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/achived/rrtv/rrtv.cookie.js, tag=人人视频 [archived] +http-request ^https:\/\/www\.flyertea\.com\/source\/plugin\/mobile\/mobile\.php\?module=getdata&.* script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/flyertea/flyertea.cookie.js, tag=飞客茶馆 +http-request ^https:\/\/sf-integral-sign-in.weixinjia.net\/app\/index script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.cookie.js, tag=顺丰速运 +http-request ^https:\/\/mcs-mimp-web.sf-express.com\/mcs-mimp\/share\/(.*?)Redirect script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.cookie.js, tag=顺丰速运 +http-request ^https:\/\/wapside.189.cn:9001\/api\/home\/homeInfo script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.cookie.js, requires-body=true, tag=中国电信 +http-request ^https:\/\/api\.dongqiudi\.com\/v2\/user\/is_login script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/dongqiudi/dongqiudi.cookie.js, tag=懂球帝 +http-request ^https:\/\/m\.you\.163\.com\/xhr\/points\/index\.json script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/yanxuan/yanxuan.cookie.js, tag=网易严选 +http-request ^https:\/\/apk\.tw\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/apktw/apktw.cookie.js, tag=APK.TW +http-request ^https:\/\/user.qunar.com\/webapi\/member\/signIndexV2.htm script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qunar/qunar.cookie.js, tag=去哪儿 +http-request ^https:\/\/passport.csdn.net\/v2\/api\/app\/login\/checkAndRefreshToken script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.cookie.js, tag=CSDN +http-request ^https:\/\/gw.csdn.net\/mini-app\/v2\/lucky_draw\/login\/sign_in\? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.cookie.js, tag=CSDN +http-request ^https:\/\/credits.bz.mgtv.com\/user\/creditsTake script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mgtv/mgtv.cookie.js, tag=芒果tv +http-request ^https:\/\/m.gdoil.cn\/webapi\/usersign\/addusersign script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/gdoil/gdoil.cookie.js, tag=加油广东 +http-request https:\/\/www.maomicd.com\/plugin.php\?id=k_misign:sign&operation=qiandao script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/maomicd/maomicd.cookie.js, tag=猫咪音乐 +# http-request ^http:\/\/wx.10086.cn\/website\/taskCenter\/index\? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.cookie.js, requires-body=true, tag=10086 +# http-request ^http:\/\/wx.10086.cn\/website\/taskCenter\/sign\? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.cookie.js, requires-body=true, tag=10086 +http-request ^https?:\/\/act.10010.com\/SigninApp\/signin\/querySigninActivity.htm script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js, tag=中国联通 +http-request ^https?:\/\/act.10010.com\/SigninApp(.*?)\/signin\/daySign script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js, tag=中国联通 +http-request ^https?:\/\/m.client.10010.com\/dailylottery\/static\/(textdl\/userLogin|active\/findActivityInfo) script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js, tag=中国联通 +http-request ^https:\/\/promotion.waimai.meituan.com\/playcenter\/signIn\/entry script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wmmeituan/wmmeituan.cookie.js, tag=美团外卖 +http-request ^https:\/\/promotion.waimai.meituan.com\/playcenter\/signIn\/doaction script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wmmeituan/wmmeituan.cookie.js, requires-body=true, tag=美团外卖 +http-request ^https:\/\/(.*?)c\.m\.163\.com\/uc\/api\/sign\/v3\/commit script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.cookie.js, requires-body=true, tag=网易新闻 +http-request ^https:\/\/i.meituan.com\/evolve\/signin\/signpost\/ script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/meituan/meituan.cookie.js, requires-body=true, tag=美团 +http-request ^https:\/\/api.everphoto.cn\/users\/self\/checkin\/v2 script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/everphoto/everphoto.cookie.js, tag=时光相册 +# http-request ^https://group\.baicizhan\.com/group/rewards? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bcz/bcz.cookie.js, tag=百词斩 +http-request ^https:\/\/maicai.api.ddxq.mobi\/point\/home script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mcdd/mcdd.cookie.js, tag=叮咚买菜 +http-request ^https://api\.dushu\.io/CheckIn script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/fandeng/fandeng.cookie.js, requires-body=true, tag=樊登读书 +http-request ^https://node\.kg\.qq\.com/webapp/proxy? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qmkg/qmkg.cookie.js, requires-body=true, tag=全民K歌 +http-request ^https:\/\/app\.nio\.com\/api\/1\/app\/daily_checkin script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/nio/nio.cookie.js, tag=蔚来 +http-request ^https:\/\/wxprdapplet\.gac-nio\.com\/community\/userSignIn\/simpleAuth\/front\/.*\/sign$ script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/hycan/hycan.cookie.js, tag=合创 +http-request ^https:\/\/activity-1\.m\.duiba\.com\.cn\/signactivity\/doSign$ requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/haidilao/hdl.js, tag=海底捞 +http-request ^https:\/\/m-bean\.kaola\.com/m/point/sign\.html script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wykl/wykl.cookie.js, requires-body=true, tag=网易考拉 +http-request ^https:\/\/zt.wps.cn\/2018\/docer_check_in\/api\/act_list script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wps/wps.cookie.js, tag=WPS +http-request ^https:\/\/xiaoshuo\.qm989\.com script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qimao/qmnovel.js, tag=七猫小说 +http-request ^https:\/\/passport.suning.com\/ids\/login$ script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js, requires-body=true, tag=苏宁易购 +http-request ^https:\/\/luckman.suning.com\/luck-web\/sign\/api\/clock_sign.do script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js, tag=苏宁易购 +http-request ^https:\/\/sign.suning.com\/sign-web\/m\/promotion\/sign\/doSign.do script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js, tag=苏宁易购 +http-request ^https:\/\/gameapi.suning.com\/sngame-web\/(api\/signin\/private\/customerSignOperation.do|gateway\/api\/queryPrize.do) script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js, tag=苏宁易购 +http-request ^https:\/\/iphone\.myzaker\.com\/zaker\/sign_in\/\/api\/sign_in\.php script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zaker/zaker.js, tag=Zaker +# http-request ^https:\/\/sapi\.beingfine\.cn\/v3\/bb\/reward\/by-sign-in script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bubei/bubei.js, tag=不背单词 [archived] +http-request ^https:\/\/gameapi\.hellobike\.com\/api script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/hellobike/hellobike.js, requires-body=true, tag=哈啰出行 +http-request ^https:\/\/mwegame\.qq\.com\/ams\/sign\/doSign\/month script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js, tag=掌上飞车 +http-request ^https:\/\/apiwz\.midukanshu\.com script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/midu/midu.cookie.js, requires-body=true, tag=米读 +http-request ^https:\/\/www\.duokan\.com\/checkin\/v0\/status script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/duokan/duokan.cookie.js, requires-body=true, tag=多看 +http-request ^https:\/\/note.youdao.com\/yws\/mapi\/user\?method=checkin script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/noteyoudao/noteyoudao.cookie.js, requires-body=true, tag=有道云笔记 +http-response ^https:\/\/clientaccess.10086.cn\/biz-orange\/LN\/uamrandcodelogin\/autoLogin script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.cookie.js, tag=中国移动-查话费 +http-response ^https:\/\/clientaccess.10086.cn\/biz-orange\/BN\/realFeeQuery\/getRealFee script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.cookie.js, tag=中国移动-查话费 +http-request ^https:\/\/user-api-prd-mx\.wandafilm\.com script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wanda/wanda.cookie.js, tag=万达电影 +http-request ^https:\/\/wx-mini.pagoda.com.cn\/api\/v1\/wxmini\/signIn\/customer script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/pagoda/pagoda.cookie.js, tag=百果园 +http-response ^https:\/\/my\.ruanmei\.com\/api\/usersign\/getsigninfo? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ithome/ithome.cookie.js, tag=IT之家 +http-response ^http:\/\/api\.infzm\.com\/mobile\/pumpkin_task\/complete? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/nfzm/nfzm.cookie.js ,tag=南方周末 +http-request ^https:\/\/m\.suanya\.cn/restapi/soa2/\d+/attendanceDay script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zxhc/zxhc.cookie.js, tag=智行火车票 + +hostname = apiwz.midukanshu.com, api.1sapp.com, frodo.douban.com, luckman.suning.com, passport.suning.com, sign.suning.com, gameapi.suning.com, m.suanya.cn, 110.43.90.61, zt.wps.cn, m-bean.kaola.com, daojia.jd.com, app.nio.com, wxprdapplet.gac-nio.com, node.kg.qq.com, api.dushu.io, pm.m.fenqile.com, maicai.api.ddxq.mobi, group.baicizhan.com, api.everphoto.cn, i.meituan.com, promotion.waimai.meituan.com, wx.10086.cn, www.maomicd.com, m.client.10010.com, act.10010.com, api-takumi.mihoyo.com, m.gdoil.cn, credits.bz.mgtv.com, *.csdn.net, wapside.189.cn, *.acfun.cn, apk.tw, *.bilibili.com, api.dongqiudi.com, *.feng.com, www.flyertea.com, music.163.com, *.m.163.com, user.qunar.com, *.rr.tv, sf-integral-sign-in.weixinjia.net, mcs-mimp-web.sf-express.com, *.smzdm.com, tieba.baidu.com, *.v2ex.com, *.video.qq.com, 113.96.156.178, *.ximalaya.com, *.you.163.com, *.rrys2020.com, ios.zmzapi.com diff --git a/Loon.task.conf b/Loon.task.conf new file mode 100644 index 000000000..07ccf6470 --- /dev/null +++ b/Loon.task.conf @@ -0,0 +1,57 @@ +# By chavyleung GitHub:https://github.com/chavyleung/scripts +cron "5 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/JD_BaiTiao.js, tag=京东白条 +cron "10 0 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/tieba/tieba.js,tag=百度签到(网页) +cron "50 0 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.js,tag=电信营业厅 +cron "0 1 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/acfun/acfun.js,tag=AcFun +cron "10 1 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/apktw/apktw.js,tag=APK.TW +cron "20 1 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.js,tag=哔哩哔哩 +cron "30 1 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.silver2coin.js,tag=哔哩哔哩 +cron "40 1 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/dongqiudi/dongqiudi.js,tag=懂球帝 +cron "50 1 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.js,tag=威锋网 +cron "0 2 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/flyertea/flyertea.js,tag=飞客茶馆 +cron "10 2 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasemusic/neteasemusic.js,tag=网易云音乐 +cron "30 2 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.js,tag=网易新闻 +cron "40 2 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qunar/qunar.js,tag=去哪儿 +# cron "50 2 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/achived/rrtv/rrtv.js,tag=人人视频 [archived] +cron "0 3 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.js,tag= 顺丰速运 +cron "10 3 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/smzdm/smzdm.js,tag=什么值得买 +cron "20 3 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/v2ex/v2ex.js,tag=V2EX +cron "30 3 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.js,tag=腾讯视频 +cron "40 3 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ximalaya/ximalaya.js,tag=喜马拉雅 +cron "50 3 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/yanxuan/yanxuan.js,tag=网易严选 +# cron "0 4 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/achived/zimuzu/zimuzu.js,tag=字幕组 [archived] +cron "10 4 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qqmusic/qqmusic.js,tag=QQ音乐 +cron "20 4 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.js,tag=CSDN +cron "30 4 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/gdoil/gdoil.js,tag=加油广东 +cron "40 4 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mgtv/mgtv.js,tag=芒果TV +cron "50 4 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mihoyo/mihoyo.js,tag=米游社 +cron "0 5 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.js,tag=中国联通 +cron "10 5 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/maomicd/maomicd.js,tag=猫咪音乐 +# cron "20 5 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.js,tag=中国移动 +cron "30 5 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wmmeituan/wmmeituan.js,tag= 美团外卖 +cron "40 5 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/meituan/meituan.js,tag=美团 +cron "50 5 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/everphoto/everphoto.js,tag=时光相册 +# cron "0 6 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bcz/bcz.js,tag=百词斩 +cron "10 6 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mcdd/mcdd.js,tag=叮咚买菜 +cron "30 6 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/fandeng/fandeng.js,tag=樊登读书 +cron "40 6 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qmkg/qmkg.js,tag=全民K歌 +cron "50 6 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/hycan/hycan.js,tag=合创 +cron "0 7 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/nio/nio.js,tag=蔚来 +cron "10 7 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/haidilao/hdl.js,tag=海底捞 +cron "20 7 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wykl/wykl.js,tag=网易考拉 +cron "30 7 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wps/wps.js,tag=WPS +cron "40 7 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qimao/qmnovel.js,tag=七猫小说 +cron "50 7 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zxhc/zxhc.js,tag=智行火车 +cron "0 8 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.js,tag=苏宁易购 +cron "10 8 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zaker/zaker.js,tag=Zaker +# cron "20 8 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bubei/bubei.js,tag=不背单词 [archived] +cron "40 8 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/hellobike/hellobike.js,tag=哈啰出行 +cron "50 8 8 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js,tag=掌上飞车 +cron "0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/duokan/duokan.js,tag=多看 +cron "3 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/noteyoudao/noteyoudao.js, tag=有道云笔记 +cron "0 12 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/box/switcher/box.switcher.js, tag=切换会话 +# cron "10 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.js, tag=中国移动-查话费 +cron "10 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wanda/wanda.js, tag=万达电影 +cron "10 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/pagoda/pagoda.js, tag=百果园 +cron "10 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ithome/ithome.js, tag=IT之家 +cron "10 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/nfzm/nfzm.js, tag=南方周末 \ No newline at end of file diff --git a/QuantumultX_AppStore_Local_Cookie.conf b/QuantumultX_AppStore_Local_Cookie.conf index bd042078a..dd05f7183 100644 --- a/QuantumultX_AppStore_Local_Cookie.conf +++ b/QuantumultX_AppStore_Local_Cookie.conf @@ -1,23 +1,22 @@ # 本配置适用于: QuanX 商店版 v1.0.6-build194 及之前版本 # 如果你是TF版, 请使用: QuantumultX_Local_Cookie.conf -hostname = promotion.waimai.meituan.com, wx.10086.cn, www.maomicd.com, act.10010.com, api-takumi.mihoyo.com, gdws.nsenz.com, credits.bz.mgtv.com, *.csdn.net, wapside.189.cn, *.acfun.cn, apk.tw, *.bilibili.com, api.dongqiudi.com, *.feng.com, www.flyertea.com, music.163.com, *.m.163.com, user.qunar.com, *.rr.tv, *.weixinjia.net, *.smzdm.com, tieba.baidu.com, *.v2ex.com, *.video.qq.com, v.qq.com, mobwsa.ximalaya.com, *.you.163.com, *.rrys2019.com, ios.zmzapi.com +hostname = apiwz.midukanshu.com, api.1sapp.com, frodo.douban.com, luckman.suning.com, passport.suning.com, sign.suning.com, gameapi.suning.com, m.suanya.cn, 110.43.90.61, zt.wps.cn, daojia.jd.com, app.nio.com, wxprdapplet.gac-nio.com, maicai.api.ddxq.mobi, group.baicizhan.com, api.everphoto.cn, promotion.waimai.meituan.com, wx.10086.cn, www.maomicd.com, m.client.10010.com, act.10010.com, api-takumi.mihoyo.com, gdws.nsenz.com, credits.bz.mgtv.com, *.csdn.net, wapside.189.cn, *.acfun.cn, apk.tw, *.bilibili.com, api.dongqiudi.com, *.feng.com, www.flyertea.com, music.163.com, *.m.163.com, user.qunar.com, *.rr.tv, sf-integral-sign-in.weixinjia.net, mcs-mimp-web.sf-express.com, *.smzdm.com, tieba.baidu.com, *.v2ex.com, *.video.qq.com, 113.96.156.178, *.ximalaya.com, *.you.163.com, *.rrys2020.com, ios.zmzapi.com # 电信营业厅 -^https:\/\/wapside.189.cn:9001\/api\/home\/homeInfo url script-request-header chavyleung/10000/10000.cookie.js -^https:\/\/wapside.189.cn:9001\/api\/home\/homeInfo url script-response-body chavyleung/10000/10000.cookie.js +^https:\/\/wapside.189.cn:9001\/api\/home\/sign url script-request-body chavyleung/10000/10000.cookie.js # AcFun ^https:\/\/api\-new\.app\.acfun\.cn\/rest\/app\/user\/personalInfo url script-request-header chavyleung/acfun/acfun.cookie.js # APK.TW -^https:\/\/apk\.tw\/?.? url script-request-header chavyleung/apktw/apktw.cookie.js +^https://apk.tw\/member.php(.*?)action=login url script-request-body chavyleung/apktw/apktw.cookie.js # bilibili ^https:\/\/(www|live)\.bilibili\.com\/?.? url script-request-header chavyleung/bilibili/bilibili.cookie.js # CSDN -^https:\/\/passport.csdn.net\/v1\/api\/app\/login\/checkToken url script-request-header chavyleung/csdn/csdn.cookie.js +^https:\/\/passport.csdn.net\/v2\/api\/app\/login\/checkAndRefreshToken url script-request-header chavyleung/csdn/csdn.cookie.js ^https:\/\/gw.csdn.net\/mini-app\/v2\/lucky_draw\/login\/sign_in\? url script-request-header chavyleung/csdn/csdn.cookie.js # 懂球帝 @@ -30,19 +29,20 @@ hostname = promotion.waimai.meituan.com, wx.10086.cn, www.maomicd.com, act.10010 ^https:\/\/www\.flyertea\.com\/source\/plugin\/mobile\/mobile\.php\?module=getdata&.* url script-request-header chavyleung/flyertea/flyertea.cookie.js # 网易云音乐 -^https:\/\/music\.163\.com\/m\/?.? url script-request-header chavyleung/neteasemusic/quanx/neteasemusic.cookie.js +^https:\/\/music.163.com\/weapi\/user\/level url script-request-body chavyleung/neteasemusic/quanx/neteasemusic.cookie.js # 网易新闻 ^https:\/\/user\.m\.163.com\/api\/v1\/commons\/fav\/topic\/allList url script-request-header chavyleung/neteasenews/neteasenews.cookie.js # 去哪儿 -^https:\/\/user.qunar.com\/webapi\/member\/signNewIndex.htm url script-request-header chavyleung/qunar/qunar.cookie.js +^https:\/\/user.qunar.com\/webapi\/member\/signIndexV2.htm url script-request-header chavyleung/qunar/qunar.cookie.js # 人人视频 -^https:\/\/api\.rr\.tv\/user\/profile url script-request-header chavyleung/rrtv/rrtv.cookie.js +# ^https:\/\/api\.rr\.tv\/user\/profile url script-request-header chavyleung/achived/rrtv/rrtv.cookie.js [archived] # 顺丰速运 -# ^https:\/\/sf\-integral\-sign\-in\.weixinjia\.net\/app\/init url script-request-header chavyleung/sfexpress/sfexpress.cookie.js +^https:\/\/sf-integral-sign-in.weixinjia.net\/app\/index url script-request-header chavyleung/sfexpress/sfexpress.cookie.js +^https:\/\/mcs-mimp-web.sf-express.com\/mcs-mimp\/share\/(.*?)Redirect url script-request-header chavyleung/sfexpress/sfexpress.cookie.js # 什么值得买 ^https:\/\/www\.smzdm\.com\/?.? url script-request-header chavyleung/smzdm/quanx/smzdm.cookie.js @@ -55,17 +55,16 @@ hostname = promotion.waimai.meituan.com, wx.10086.cn, www.maomicd.com, act.10010 # 腾讯视频 ^https:\/\/access.video.qq.com\/user\/auth_refresh url script-request-header chavyleung/videoqq/videoqq.cookie.js -^https?:\/\/v.qq.com\/x\/bu\/mobile_checkin url script-request-header chavyleung/videoqq/videoqq.cookie.js # 喜马拉雅 -^https?:\/\/.*\/mobile\-user\/homePage\/.* url script-request-header chavyleung/ximalaya/ximalaya.cookie.js +^https?:\/\/.*\/mobile\-user\/(v1\/)?homePage\/.* url script-request-header chavyleung/ximalaya/ximalaya.cookie.js # 网易严选 # ^https:\/\/m\.you\.163\.com\/xhr\/points\/index\.json url script-request-header chavyleung/yanxuan/yanxuan.cookie.js # 字幕组 -^https?:\/\/(www\.)?rrys2019\.com\/?.? url script-request-header chavyleung/zimuzu/zimuzu.cookie.js -^http:\/\/ios.zmzapi.com\/index.php.*a=(mobile_)?login url script-request-header chavyleung/zimuzu/zimuzu.cookie.js +# ^https?:\/\/(www\.)?rrys2020\.com\/?.? url script-request-header chavyleung/achived/zimuzu/zimuzu.cookie.js [archived] +# ^http:\/\/ios.zmzapi.com\/index.php.*a=(mobile_)?login url script-request-header chavyleung/achived/zimuzu/zimuzu.cookie.js [archived] # 加油广东 ^https:\/\/gdws.nsenz.com\/webapi\/usersign\/addusersign url script-request-header chavyleung/gdoil/gdoil.cookie.js @@ -76,17 +75,68 @@ hostname = promotion.waimai.meituan.com, wx.10086.cn, www.maomicd.com, act.10010 # 米游社 ^https:\/\/api-takumi.mihoyo.com\/apihub\/api\/getGameList url script-request-header chavyleung/mihoyo/mihoyo.cookie.js + # 中国联通 ^https:\/\/act.10010.com\/SigninApp\/signin\/querySigninActivity.htm url script-request-header chavyleung/10010/10010.cookie.js -^https:\/\/act.10010.com\/SigninApp(.*?)\/signin\/daySign.do url script-request-header chavyleung/10010/10010.cookie.js +^https:\/\/act.10010.com\/SigninApp(.*?)\/signin\/daySign url script-request-header chavyleung/10010/10010.cookie.js +^https:\/\/m.client.10010.com\/dailylottery\/static\/(textdl\/userLogin|active\/findActivityInfo) url script-request-header chavyleung/10010/10010.cookie.js # 中国移动 -^http:\/\/wx.10086.cn\/website\/taskCenter\/index\? url script-request-header chavyleung/10086/10086.cookie.js -^http:\/\/wx.10086.cn\/website\/taskCenter\/sign\? url script-request-header chavyleung/10086/10086.cookie.js +# ^http:\/\/wx.10086.cn\/website\/taskCenter\/index\? url script-request-header chavyleung/10086/10086.cookie.js +# ^http:\/\/wx.10086.cn\/website\/taskCenter\/sign\? url script-request-header chavyleung/10086/10086.cookie.js # 猫咪音乐网 https:\/\/www.maomicd.com\/plugin.php\?id=k_misign:sign&operation=qiandao url script-request-header chavyleung/maomicd/maomicd.cookie.js # 美团外卖 ^https:\/\/promotion.waimai.meituan.com\/playcenter\/signIn\/entry url script-request-header chavyleung/wmmeituan/wmmeituan.cookie.js -^https:\/\/promotion.waimai.meituan.com\/playcenter\/signIn\/doaction url script-request-header chavyleung/wmmeituan/wmmeituan.cookie.js \ No newline at end of file +^https:\/\/promotion.waimai.meituan.com\/playcenter\/signIn\/doaction url script-request-header chavyleung/wmmeituan/wmmeituan.cookie.js + +# 时光相册 +^https:\/\/api.everphoto.cn\/users\/self\/checkin\/v2 url script-request-header chavyleung/everphoto/everphoto.cookie.js + +# 百词斩 +# ^https://group\.baicizhan\.com/group/rewards? url script-request-header chavyleung/bcz/bcz.cookie.js + +# 叮咚买菜 +^https:\/\/maicai.api.ddxq.mobi\/point\/home url script-request-header chavyleung/mcdd/mcdd.cookie.js + +# 合创 +^https:\/\/wxprdapplet\.gac-nio\.com\/community\/userSignIn\/simpleAuth\/front\/v3\.1\.3\.5\/signV2$ url script-request-header chavyleung/hycan/hycan.cookie.js + +# 蔚来 +^https:\/\/app\.nio\.com\/api\/1\/app\/daily_checkin url script-request-header chavyleung/nio/nio.cookie.js + +# 京东到家 +^https:\/\/daojia.jd.com/client(.*?)functionId=signin(.*?)userSigninNew url script-request-header chavyleung/jddj/jddj.cookie.js + +# 全民K歌 +^https://node\.kg\.qq\.com/webapp/proxy? url script-request-body chavyleung/qmkg/qmkg.cookie.js + +# 樊登读书 +^https://api\.dushu\.io/CheckIn url script-request-body chavyleung/fandeng/fandeng.cookie.js + +# 分期乐 +# ^https://pm\.m\.fenqile\.com/route0014/star/sign/sign.json url script-request-body chavyleung/fenqile/fenqile.cookie.js +# ^https:\/\/pm\.m\.fenqile\.com/route0014\/app\/tab\/privilege\/convertTaskReward.json url script-request-body chavyleung/fenqile/fenqile.cookie.js + +# 美团 +^https:\/\/i.meituan.com\/evolve\/signin\/signpost\/ url script-request-body chavyleung/meituan/meituan.cookie.js + +# 网易新闻 +^https:\/\/(.*?)c\.m\.163\.com\/uc\/api\/sign\/v3\/commit url script-request-body chavyleung/neteasenews/neteasenews.cookie.js + +# 网易考拉 +^https:\/\/m-bean\.kaola\.com/m/point/sign\.html url script-request-body chavyleung/wykl/wykl.cookie.js + +# WPS +^https:\/\/zt.wps.cn\/2018\/docer_check_in\/api\/act_list url script-request-header chavyleung/wps/wps.cookie.js + +#智行火车 +^https:\/\/m\.suanya\.cn/restapi/soa2/\d+/attendanceDay url script-request-body chavyleung/zxhc/zxhc.cookie.js + +# 苏宁易购 +^https:\/\/passport.suning.com\/ids\/login$ url script-request-body chavyleung/suning/suning.cookie.js +^https:\/\/luckman.suning.com\/luck-web\/sign\/api\/clock_sign.do url script-request-header chavyleung/suning/suning.cookie.js +^https:\/\/sign.suning.com\/sign-web\/m\/promotion\/sign\/doSign.do url script-request-header chavyleung/suning/suning.cookie.js +^https:\/\/gameapi.suning.com\/sngame-web\/(api\/signin\/private\/customerSignOperation.do|gateway\/api\/queryPrize.do) url script-request-header chavyleung/suning/suning.cookie.js diff --git a/QuantumultX_Local_Cookie.conf b/QuantumultX_Local_Cookie.conf index 320bf90d3..af36a0ede 100644 --- a/QuantumultX_Local_Cookie.conf +++ b/QuantumultX_Local_Cookie.conf @@ -1,95 +1,134 @@ # 本配置适用于: QuanX TestFlight v1.0.6-build195 及以后版本 # 如果你是商店版, 请使用: QuantumultX_AppStore_Local_Cookie.conf -hostname = i.meituan.com, promotion.waimai.meituan.com, wx.10086.cn, www.maomicd.com, act.10010.com, api-takumi.mihoyo.com, m.gdoil.cn, credits.bz.mgtv.com, *.csdn.net, wapside.189.cn, *.acfun.cn, apk.tw, *.bilibili.com, api.dongqiudi.com, *.feng.com, www.flyertea.com, music.163.com, *.m.163.com, user.qunar.com, *.rr.tv, *.weixinjia.net, *.smzdm.com, tieba.baidu.com, *.v2ex.com, *.video.qq.com, v.qq.com, mobwsa.ximalaya.com, *.you.163.com, *.rrys2019.com, ios.zmzapi.com +hostname = apiwz.midukanshu.com, api.1sapp.com, frodo.douban.com, luckman.suning.com, passport.suning.com, sign.suning.com, gameapi.suning.com, m.suanya.cn, 110.43.90.61, zt.wps.cn, m-bean.kaola.com, daojia.jd.com, app.nio.com, wxprdapplet.gac-nio.com, node.kg.qq.com, api.dushu.io, pm.m.fenqile.com, maicai.api.ddxq.mobi, group.baicizhan.com, api.everphoto.cn, i.meituan.com, promotion.waimai.meituan.com, wx.10086.cn, www.maomicd.com, m.client.10010.com, act.10010.com, api-takumi.mihoyo.com, m.gdoil.cn, credits.bz.mgtv.com, *.csdn.net, wapside.189.cn, *.acfun.cn, apk.tw, *.bilibili.com, api.dongqiudi.com, *.feng.com, www.flyertea.com, music.163.com, *.m.163.com, user.qunar.com, *.rr.tv, sf-integral-sign-in.weixinjia.net, mcs-mimp-web.sf-express.com, *.smzdm.com, tieba.baidu.com, *.v2ex.com, *.video.qq.com, 113.96.156.178, *.ximalaya.com, *.you.163.com, *.rrys2020.com, ios.zmzapi.com # 电信营业厅 -^https:\/\/wapside.189.cn:9001\/api\/home\/homeInfo url script-request-header chavyleung/10000/10000.cookie.js -^https:\/\/wapside.189.cn:9001\/api\/home\/homeInfo url script-response-body chavyleung/10000/10000.cookie.js +^https:\/\/wapside.189.cn:9001\/api\/home\/sign url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.cookie.js # AcFun -^https:\/\/api\-new\.app\.acfun\.cn\/rest\/app\/user\/personalInfo url script-request-header chavyleung/acfun/acfun.cookie.js +^https:\/\/api\-new\.app\.acfun\.cn\/rest\/app\/user\/personalInfo url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/acfun/acfun.cookie.js # APK.TW -^https:\/\/apk\.tw\/?.? url script-request-header chavyleung/apktw/apktw.cookie.js +^https://apk.tw\/member.php(.*?)action=login url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/apktw/apktw.cookie.js # bilibili -^https:\/\/(www|live)\.bilibili\.com\/?.? url script-request-header chavyleung/bilibili/bilibili.cookie.js +^https:\/\/(www|live)\.bilibili\.com\/?.? url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.cookie.js # CSDN -^https:\/\/passport.csdn.net\/v1\/api\/app\/login\/checkToken url script-request-header chavyleung/csdn/csdn.cookie.js -^https:\/\/gw.csdn.net\/mini-app\/v2\/lucky_draw\/login\/sign_in\? url script-request-header chavyleung/csdn/csdn.cookie.js +^https:\/\/passport.csdn.net\/v2\/api\/app\/login\/checkAndRefreshToken url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.cookie.js +^https:\/\/gw.csdn.net\/mini-app\/v2\/lucky_draw\/login\/sign_in\? url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.cookie.js # 懂球帝 -^https:\/\/api\.dongqiudi\.com\/v2\/user\/is_login url script-request-header chavyleung/dongqiudi/dongqiudi.cookie.js +^https:\/\/api\.dongqiudi\.com\/v2\/user\/is_login url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/dongqiudi/dongqiudi.cookie.js # 威锋网 -# ^https:\/\/(www\.)?feng\.com\/?.? url script-request-header chavyleung/feng/feng.cookie.js +# ^https:\/\/(www\.)?feng\.com\/?.? url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.cookie.js # 飞客茶馆 -^https:\/\/www\.flyertea\.com\/source\/plugin\/mobile\/mobile\.php\?module=getdata&.* url script-request-header chavyleung/flyertea/flyertea.cookie.js +^https:\/\/www\.flyertea\.com\/source\/plugin\/mobile\/mobile\.php\?module=getdata&.* url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/flyertea/flyertea.cookie.js # 网易云音乐 -^https:\/\/music\.163\.com\/m\/?.? url script-request-header chavyleung/neteasemusic/quanx/neteasemusic.cookie.js +^https:\/\/music.163.com\/weapi\/user\/level url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/neteasemusic/quanx/neteasemusic.cookie.js # 网易新闻 -^https:\/\/c\.m\.163\.com\/uc\/api\/sign\/v2\/commit url script-request-body chavyleung/neteasenews/neteasenews.cookie.js +^https:\/\/(.*?)c\.m\.163\.com\/uc\/api\/sign\/v3\/commit url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.cookie.js # 去哪儿 -^https:\/\/user.qunar.com\/webapi\/member\/signNewIndex.htm url script-request-header chavyleung/qunar/qunar.cookie.js +^https:\/\/user.qunar.com\/webapi\/member\/signIndexV2.htm url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/qunar/qunar.cookie.js # 人人视频 -^https:\/\/api\.rr\.tv\/user\/profile url script-request-header chavyleung/rrtv/rrtv.cookie.js +# ^https:\/\/api\.rr\.tv\/user\/profile url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/achived/rrtv/rrtv.cookie.js [archived] # 顺丰速运 -# ^https:\/\/sf\-integral\-sign\-in\.weixinjia\.net\/app\/init url script-request-header chavyleung/sfexpress/sfexpress.cookie.js +^https:\/\/sf-integral-sign-in.weixinjia.net\/app\/index url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.cookie.js +^https:\/\/mcs-mimp-web.sf-express.com\/mcs-mimp\/share\/(.*?)Redirect url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.cookie.js # 什么值得买 -^https:\/\/www\.smzdm\.com\/?.? url script-request-header chavyleung/smzdm/quanx/smzdm.cookie.js +^https:\/\/www\.smzdm\.com\/?.? url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/smzdm/quanx/smzdm.cookie.js # 百度签到 -^https?:\/\/tieba\.baidu\.com\/?.? url script-request-header chavyleung/tieba/tieba.cookie.js +^https?:\/\/tieba\.baidu\.com\/?.? url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/tieba/tieba.cookie.js # V2EX -^https:\/\/www\.v2ex\.com\/mission\/daily url script-request-header chavyleung/v2ex/quanx/v2ex.cookie.js +^https:\/\/www\.v2ex\.com\/mission\/daily url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/v2ex/quanx/v2ex.cookie.js # 腾讯视频 -^https:\/\/access.video.qq.com\/user\/auth_refresh url script-request-header chavyleung/videoqq/videoqq.cookie.js -^https?:\/\/v.qq.com\/x\/bu\/mobile_checkin url script-request-header chavyleung/videoqq/videoqq.cookie.js +^https:\/\/access.video.qq.com\/user\/auth_refresh url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.cookie.js # 喜马拉雅 -^https?:\/\/.*\/mobile\-user\/homePage\/.* url script-request-header chavyleung/ximalaya/ximalaya.cookie.js +^https?:\/\/.*\/mobile\-user\/(v1\/)?homePage\/.* url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/ximalaya/ximalaya.cookie.js # 网易严选 -# ^https:\/\/m\.you\.163\.com\/xhr\/points\/index\.json url script-request-header chavyleung/yanxuan/yanxuan.cookie.js +# ^https:\/\/m\.you\.163\.com\/xhr\/points\/index\.json url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/yanxuan/yanxuan.cookie.js # 字幕组 -^https?:\/\/(www\.)?rrys2019\.com\/?.? url script-request-header chavyleung/zimuzu/zimuzu.cookie.js -^http:\/\/ios.zmzapi.com\/index.php.*a=(mobile_)?login url script-request-header chavyleung/zimuzu/zimuzu.cookie.js +# ^https?:\/\/(www\.)?rrys2020\.com\/?.? url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/achived/zimuzu/zimuzu.cookie.js [archived] +# ^http:\/\/ios.zmzapi.com\/index.php.*a=(mobile_)?login url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/achived/zimuzu/zimuzu.cookie.js [archived] # 加油广东 -^https:\/\/m.gdoil.cn\/webapi\/usersign\/addusersign url script-request-header chavyleung/gdoil/gdoil.cookie.js +^https:\/\/m.gdoil.cn\/webapi\/usersign\/addusersign url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/gdoil/gdoil.cookie.js # 芒果TV -^https:\/\/credits.bz.mgtv.com\/user\/creditsTake url script-request-header chavyleung/mgtv/mgtv.cookie.js +^https:\/\/credits.bz.mgtv.com\/user\/creditsTake url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/mgtv/mgtv.cookie.js # 米游社 -^https:\/\/api-takumi.mihoyo.com\/apihub\/api\/getGameList url script-request-header chavyleung/mihoyo/mihoyo.cookie.js +^https:\/\/api-takumi.mihoyo.com\/apihub\/api\/getGameList url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/mihoyo/mihoyo.cookie.js # 中国联通 -^https:\/\/act.10010.com\/SigninApp\/signin\/querySigninActivity.htm url script-request-header chavyleung/10010/10010.cookie.js -^https:\/\/act.10010.com\/SigninApp(.*?)\/signin\/daySign.do url script-request-header chavyleung/10010/10010.cookie.js +^https:\/\/act.10010.com\/SigninApp\/signin\/querySigninActivity.htm url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js +^https:\/\/act.10010.com\/SigninApp(.*?)\/signin\/daySign url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js +^https:\/\/m.client.10010.com\/dailylottery\/static\/(textdl\/userLogin|active\/findActivityInfo) url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js # 中国移动 -^http:\/\/wx.10086.cn\/website\/taskCenter\/index\? url script-request-header chavyleung/10086/10086.cookie.js -^http:\/\/wx.10086.cn\/website\/taskCenter\/sign\? url script-request-header chavyleung/10086/10086.cookie.js +# ^http:\/\/wx.10086.cn\/website\/taskCenter\/index\? url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.cookie.js +# ^http:\/\/wx.10086.cn\/website\/taskCenter\/sign\? url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.cookie.js # 猫咪音乐网 -https:\/\/www.maomicd.com\/plugin.php\?id=k_misign:sign&operation=qiandao url script-request-header chavyleung/maomicd/maomicd.cookie.js +https:\/\/www.maomicd.com\/plugin.php\?id=k_misign:sign&operation=qiandao url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/maomicd/maomicd.cookie.js # 美团外卖 -^https:\/\/promotion.waimai.meituan.com\/playcenter\/signIn\/entry url script-request-header chavyleung/wmmeituan/wmmeituan.cookie.js -^https:\/\/promotion.waimai.meituan.com\/playcenter\/signIn\/doaction url script-request-body chavyleung/wmmeituan/wmmeituan.cookie.js +^https:\/\/promotion.waimai.meituan.com\/playcenter\/signIn\/entry url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/wmmeituan/wmmeituan.cookie.js +^https:\/\/promotion.waimai.meituan.com\/playcenter\/signIn\/doaction url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/wmmeituan/wmmeituan.cookie.js # 美团 -^https:\/\/i.meituan.com\/evolve\/signin\/signpost\/ url script-request-body chavyleung/meituan/meituan.cookie.js \ No newline at end of file +^https:\/\/i.meituan.com\/evolve\/signin\/signpost\/ url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/meituan/meituan.cookie.js + +# 时光相册 +^https:\/\/api.everphoto.cn\/users\/self\/checkin\/v2 url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/everphoto/everphoto.cookie.js + +# 百词斩 +# ^https://group\.baicizhan\.com/group/rewards? url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/bcz/bcz.cookie.js + +# 叮咚买菜 +^https:\/\/maicai.api.ddxq.mobi\/point\/home url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/mcdd/mcdd.cookie.js + +#樊登读书 +^https://api\.dushu\.io/CheckIn url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/fandeng/fandeng.cookie.js + +#全民K歌 +^https://node\.kg\.qq\.com/webapp/proxy? url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/qmkg/qmkg.cookie.js + +#蔚来 +^https:\/\/app\.nio\.com\/api\/1\/app\/daily_checkin url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/nio/nio.cookie.js + +#合创 +^https:\/\/wxprdapplet\.gac-nio\.com\/community\/userSignIn\/simpleAuth\/front\/v3\.1\.3\.5\/signV2$ url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/hycan/hycan.cookie.js + +#京东到家 +^https:\/\/daojia.jd.com/client(.*?)functionId=signin(.*?)userSigninNew url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/jddj/jddj.cookie.js + +#网易考拉 +^https:\/\/m-bean\.kaola\.com/m/point/sign\.html url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/wykl/wykl.cookie.js + +# WPS +^https:\/\/zt.wps.cn\/2018\/docer_check_in\/api\/act_list url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/wps/wps.cookie.js + +#智行火车 +^https:\/\/m\.suanya\.cn/restapi/soa2/\d+/attendanceDay url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/zxhc/zxhc.cookie.js + +# 苏宁易购 +^https:\/\/passport.suning.com\/ids\/login$ url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js +^https:\/\/luckman.suning.com\/luck-web\/sign\/api\/clock_sign.do url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js +^https:\/\/sign.suning.com\/sign-web\/m\/promotion\/sign\/doSign.do url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js +^https:\/\/gameapi.suning.com\/sngame-web\/(api\/signin\/private\/customerSignOperation.do|gateway\/api\/queryPrize.do) url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js diff --git a/QuantumultX_Local_Task.conf b/QuantumultX_Local_Task.conf index 47c7edb5e..c0f5087b7 100644 --- a/QuantumultX_Local_Task.conf +++ b/QuantumultX_Local_Task.conf @@ -1,5 +1,8 @@ [task_local] # @chavyleung +# @GideonSenku +# @barrymchen +# @danchaw # 电信营业厅 5 0 * * * chavyleung/10000/10000.js # AcFun @@ -8,6 +11,8 @@ 10 0 * * * chavyleung/apktw/apktw.js # bilibili 2 0 * * * chavyleung/bilibili/bilibili.js +# bilibili 如需银瓜子转硬币,添加下方内容 +1 0 * * * chavyleung/bilibili/bilibili.silver2coin.js # 懂球帝 4 0 * * * chavyleung/dongqiudi/dongqiudi.js # 威锋网 @@ -21,9 +26,9 @@ # 去哪儿 4 0 * * * chavyleung/qunar/qunar.js # 人人视频 -5 0 * * * chavyleung/rrtv/rrtv.js +# 10 0 * * * chavyleung/achived/rrtv/rrtv.js [archived] # 顺丰速运 -# 10 0 * * * chavyleung/sfexpress/sfexpress.js +10 0 * * * chavyleung/sfexpress/sfexpress.js # 什么值得买 2 0 * * * chavyleung/smzdm/quanx/smzdm.js # 百度签到 @@ -37,7 +42,7 @@ # 网易严选 # 4 0 * * * chavyleung/yanxuan/yanxuan.js # 字幕组 -3 0 * * * chavyleung/zimuzu/zimuzu.js +# 3 0 * * * chavyleung/achived/zimuzu/zimuzu.js [archived] # CSDN 4 0 * * * chavyleung/csdn/csdn.js # 加油广东 @@ -50,9 +55,29 @@ 9 0 * * * chavyleung/10010/10010.js # 猫咪音乐网 2 0 * * * chavyleung/maomicd/maomicd.js -# 中国移动 -7 0 * * * chavyleung/10086/10086.js +# # 中国移动 +# 7 0 * * * chavyleung/10086/10086.js # 美团外卖 8 0 * * * chavyleung/wmmeituan/wmmeituan.js # 美团 -7 0 * * * chavyleung/meituan/meituan.js \ No newline at end of file +7 0 * * * chavyleung/meituan/meituan.js +# 时光相册 +7 0 * * * chavyleung/everphoto/everphoto.js +# 叮咚买菜 +7 0 * * * chavyleung/mcdd/mcdd.js +#樊登读书 +1 0 * * * chavyleung/fandeng/fandeng.js +#全民K歌 +1 0 * * * chavyleung/qmkg/qmkg.js +#合创 +1 0 * * * chavyleung/hycan/hycan.js +#蔚来 +1 0 * * * chavyleung/nio/nio.js +#京东到家 +1 0 * * * chavyleung/jddj/jddj.js +# WPS +0 9 * * * chavyleung/wps/wps.js +#智行火车 +1 0 * * * chavyleung/zxhc/zxhc.js +# 苏宁易购 +7 0 * * * chavyleung/suning/suning.js \ No newline at end of file diff --git a/QuantumultX_Remote_Task.conf b/QuantumultX_Remote_Task.conf new file mode 100644 index 000000000..5a11b7249 --- /dev/null +++ b/QuantumultX_Remote_Task.conf @@ -0,0 +1,165 @@ +# @chavyleung + +# 电信营业厅 +#打开 APP 手动签到一次: 访问下右下角 `我` > `签到` (头像下面) +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.js + +# AcFun +#打开 APP, 访问下`我的` +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/acfun/acfun.js + +# APK.TW +#打开浏览器访问: https://apk.tw `(先登录! 把页面切换为电脑版)` +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/apktw/apktw.js + +# bilibili +#打开浏览器访问: https://www.bilibili.com 或 https://live.bilibili.com +2 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.js +#如需银瓜子转硬币,取消下方注释 +;1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.silver2coin.js + +# 懂球帝 +#打开懂球帝 (打开前先杀掉 APP) +2 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/dongqiudi/dongqiudi.js + +# 威锋网 +#打开浏览器访问: https://www.feng.com`(先登录! 把页面切换为电脑版)` +2 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.js + +# 飞客茶馆 +#打开 APP, 访问下`个人中心` +3 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/flyertea/flyertea.js + +# 网易云音乐 +#浏览器访问并登录: https://music.163.com/m/login +3 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/neteasemusic/quanx/neteasemusic.js + +# 网易新闻 +#打开 APP 然后手动签到 1 次 +3 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.js + +# 去哪儿 +#打开 APP 然后手动签到 1 次 +4 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/qunar/qunar.js + +# 人人视频 +#打开 APP, 访问下`个人中心` +# 4 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/achived/rrtv/rrtv.js [archived] + +# 顺丰速运 +#打开 APP, 访问下`我的顺丰` > `去签到` (访问下`去签到`的页面即可, 不用点`签到`) +10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.js + +# 什么值得买 +#浏览器访问并登录: https://zhiyou.smzdm.com/user/login +5 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/smzdm/quanx/smzdm.js + +# 百度签到 +#先登录,浏览器访问一下: https://tieba.baidu.com 或者 https://tieba.baidu.com/index/ +5 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/tieba/tieba.js + +# V2EX +#浏览器打开https://www.v2ex.com/mission/daily ,待弹出获取成功即可 +5 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/v2ex/quanx/v2ex.js + +# 腾讯视频 +#1.手机浏览器访问并登录: https://film.qq.com/,2. 随便选 1 部电影观看3.访问http://v.qq.com/x/bu/mobile_checkin +6 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.js + +# 喜马拉雅 +#打开 APP, 访问下右下角`账号` +6 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/ximalaya/ximalaya.js + +# 网易严选 +#打开 APP, 访问下`个人`>`每日签到`(右上角) +# 6 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/yanxuan/yanxuan.js + +# 字幕组 +#网页:打开浏览器访问: http://www.rrys2020.com, App: 打开 APP 即可 +# 7 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/achived/zimuzu/zimuzu.js [archived] + +# QQ音乐 +#打开 APP 然后手动签到 1 次 +7 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/qqmusic/qqmusic.js + +# CSDN +# 打开 APP , 系统提示: `获取刷新链接: 成功`,然后手动签到 1 次, 系统提示: `获取Cookie: 成功` +7 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.js + +# 加油广东 +#打开 APP 然后手动签到 1 次 +1 7 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/gdoil/gdoil.js + +# 芒果TV +#打开 APP 然后手动签到 1 次 +8 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/mgtv/mgtv.js + +# 米游社 +#打开 APP +8 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/mihoyo/mihoyo.js + +# 中国联通 +#打开 APP , 进入签到页面, 系统提示: `获取刷新链接: 成功`,然后手动签到 1 次 +8 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.js + +# 猫咪音乐 +#打开 网站 `https://www.maomicd.com` 然后手动签到 1 次 +9 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/maomicd/maomicd.js + +# 美团外卖 +#打开 APP , 进入签到页面, 系统提示: `获取刷新链接: 成功`,然后手动签到 1 次 +9 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/wmmeituan/wmmeituan.js + +# 美团 +#打开 APP , 然后手动签到 1 次, (`首页` > `红包签到`) +10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/meituan/meituan.js + +# 时光相册 +#打开 APP 然后手动签到 1 次 +10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/everphoto/everphoto.js + +# 叮咚买菜 +#打开 APP, 访问下`我的`>`积分` +10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/mcdd/mcdd.js + +# 樊登读书 +#打开 APP 手动签到一次: 访问下右下角 `我的` > `签到` +10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/fandeng/fandeng.js + +# 全民K歌 +#打开 APP 手动签到一次: 访问下右下角 `我的` > `任务中心` > `签到` +10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/qmkg/qmkg.js + +# 合创 +#打开 APP 然后手动签到 1 次 +11 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/hycan/hycan.js + +# 蔚来 +#打开 APP 手动签到一次 +11 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/nio/nio.js + +# 京东到家 +#打开 APP 手动签到一次: `首页` > `签到` 或者 手机浏览器打开`https://daojia.jd.com/html/index.html` 点击签到 +11 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/jddj/jddj.js + +# 海底捞 +#打开APP 然后手动签到 1 次 +12 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/haidilao/hdl.js + +#网易考拉 +#打开 APP 手动签到一次: 访问下右下角 `我的考拉` > `领考拉豆` > `签到` +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/wykl/wykl.js + +# WPS +# 打开 APP 我 > 签到 (右上角, 不用手动签到) +# 打开 `我的WPS会员` 小程序 (手动签到) +0 9 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/wps/wps.js + +#智行火车 +# 打开 APP 手动签到一次: 访问下右下角 `个人中心` > `签到` +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/zxhc/zxhc.js + +# 苏宁易购 +# 首页 > 签到有礼 +# 首页 > 领取红包 +7 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.js diff --git a/README.md b/README.md index 1229b9420..0cea240e6 100644 --- a/README.md +++ b/README.md @@ -1 +1,107 @@ # Chavy Scripts + +![](https://img.shields.io/badge/license-GPL-blueviolet.svg) +![GitHub release (latest by date)](https://img.shields.io/github/v/release/chavyleung/scripts?color=%23c694ff) +![](https://badgen.net/github/stars/chavyleung/scripts) +![](https://tokei.rs/b1/github/chavyleung/scripts?category=code) +![GitHub contributors](https://img.shields.io/github/contributors/chavyleung/scripts) + +Telegram讨论组:[Chavy Scripts Group](https://t.me/chavyscripts) + +--- + +- [Chavy Scripts](#chavy-scripts) +- [🧰BoxJs](#boxjs) + - [简介](#简介) + - [使用方式](#使用方式) + - [安装链接](#安装链接) + - [正式版](#正式版) + - [🧪测试版](#测试版) +- [🛠️Env.js](#️envjs) + - [调用方式](#调用方式) + - [功能列表](#功能列表) + - [HttpClient](#httpclient) + - [持久化数据](#持久化数据) + - [安装链接](#安装链接-1) + - [正式版](#正式版-1) +- [📃LICENSE](#license) + +--- + +# 🧰BoxJs + + +## 简介 +A SPA Appliction be used for scripts utils + +## 使用方式 +安装对应模块/插件后,浏览器访问: [boxjs.com](http://boxjs.com "BoxJs") + +## 安装链接 + * Shadowrocket: [boxjs.rewrite.surge.sgmodule](https://github.com/chavyleung/scripts/raw/master/box/rewrite/boxjs.rewrite.surge.sgmodule "BoxJs") + * Loon: [boxjs.rewrite.loon.plugin](https://github.com/chavyleung/scripts/raw/master/box/rewrite/boxjs.rewrite.loon.plugin "BoxJs") + * Quantumult X: [boxjs.rewrite.quanx.conf](https://github.com/chavyleung/scripts/raw/master/box/rewrite/boxjs.rewrite.quanx.conf "BoxJs") + * Surge: [boxjs.rewrite.surge.sgmodule](https://github.com/chavyleung/scripts/raw/master/box/rewrite/boxjs.rewrite.surge.sgmodule "BoxJs") + * Stash: [boxjs.rewrite.stash.stoverride](https://github.com/chavyleung/scripts/raw/master/box/rewrite/boxjs.rewrite.stash.stoverride "BoxJs") + +--- + +# 🛠️Env.js + +## 调用方式 + * Env.min.js放置于嵌入式脚本底端,然后头部调用功能 + ``` + const $ = new Env("你的脚本名称"); + ``` + +## 功能列表 +### HttpClient + + * 支持方法: get, post, put, delete, head, options, patch + ```javascript + let option = { + url: "http://www.example.com/", // URL,必须 + headers: { // 请求头,可选 + "Accept": "*/*", + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Mobile/15E148 Safari/605.1.15", + "Content-Type": "application/json; charset=utf-8" + "" + }, + body: `auth_key=1234567&source_lang=EN&target_lang=ZH` // 请求体,POST等方法必须,字符串或对象 + } + let result = $.get(URL or options, callback(error, response, data)) // 不支持异步 + let result = $.post(URL or options, callback(error, response, data)) // 不支持异步 + …… + + let result = await $.http.get(URL or options).then(callback(response)) + let result = await $.http.post(URL or options).then(response => response.body) + let result = await $.http.put(URL or options).then(response => { + $.log(JSON.stringify(response.headers)); + return response.body + }) + …… + ``` + +### 持久化数据 + ```javascript + + $.getdata(‘chavy’) // 读取持久化数据 (string格式) + $.setdata(string, ‘chavy’) // 写入持久化数据 (string格式) + $.getjson(‘chavy’, default_value) // 读取持久化数据 (object格式),当读取失败后返回默认值 + $.setjson(object, ‘chavy’) // 写入持久化数据 (object格式) + + ``` + +## 安装链接 +### 正式版 + * 用于集成:[Env.min.js](./Env.min.js?raw=true "Env.min.js") + * 便于阅读:[Env.js](./Env.js?raw=true "Env.js") + +--- + +# 赞助 + +1. [CloudFlare](https://www.cloudflare.com/) + +# 📃LICENSE +Copyright © 2019-present chavyleung. This project is [GPL](https://github.com/chavyleung/scripts/blob/master/LICENSE) licensed. diff --git a/acfun/acfun.js b/acfun/acfun.js index f294ccc4c..f5d55121a 100644 --- a/acfun/acfun.js +++ b/acfun/acfun.js @@ -27,7 +27,6 @@ function sign() { } chavy.log(`${cookieName}, data: ${data}`) }) - chavy.done() } function getinfo(signresult) { @@ -49,6 +48,7 @@ function getinfo(signresult) { detail = `共签: ${result.cumulativeDays}次, 连签: ${result.continuousDays}次, 说明: ${signresult.msg}` chavy.msg(title, subTitle, detail) chavy.log(`${cookieName}, data: ${data}`) + chavy.done() }) } diff --git a/10086/10086.cookie.js b/achived/10086/10086.cookie.js similarity index 100% rename from 10086/10086.cookie.js rename to achived/10086/10086.cookie.js diff --git a/achived/10086/10086.fee.cookie.js b/achived/10086/10086.fee.cookie.js new file mode 100644 index 000000000..13daf286f --- /dev/null +++ b/achived/10086/10086.fee.cookie.js @@ -0,0 +1,48 @@ +/** + * + * hostname = clientaccess.10086.cn + * + * # Surge + * Rewrite: CMCC = type=http-request,pattern=^https:\/\/clientaccess.10086.cn\/biz-orange\/LN\/uamrandcodelogin\/autoLogin,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.cookie.js,requires-body=true,debug=true + * Rewrite: CMCC = type=http-request,pattern=^https:\/\/clientaccess.10086.cn\/biz-orange\/BN\/realFeeQuery\/getRealFee,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.cookie.js,requires-body=true,debug=true + * Tasks: 10086-查话费 = type=cron,cronexp=10 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.js,wake-system=true + * + * # QuanX + * ^https:\/\/clientaccess.10086.cn\/biz-orange\/LN\/uamrandcodelogin\/autoLogin url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.cookie.js + * ^https:\/\/clientaccess.10086.cn\/biz-orange\/BN\/realFeeQuery\/getRealFee url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.cookie.js + * 10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.js, tag=10086-查话费 + * + * # Loon + * http-request ^https:\/\/clientaccess.10086.cn\/biz-orange\/LN\/uamrandcodelogin\/autoLogin script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.cookie.js, requires-body=true, tag=中国移动-查话费 + * http-request ^https:\/\/clientaccess.10086.cn\/biz-orange\/BN\/realFeeQuery\/getRealFee script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.cookie.js, requires-body=true, tag=中国移动-查话费 + * cron "10 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10086/10086.fee.js + * + */ + +const $ = new Env('中国移动') +$.KEY_autologin = 'chavy_autologin_cmcc' +$.KEY_getfee = 'chavy_getfee_cmcc' + +!(async () => { + const session = {} + session.url = $request.url + session.body = $request.body + session.headers = $request.headers + let key = '' + if (/autoLogin/.test(session.url)) { + key = $.KEY_autologin + } else if (/getRealFee/.test(session.url)) { + key = $.KEY_getfee + } + if ($.setdata(JSON.stringify(session), key)) { + $.subt = `获取会话: 成功! (${key})` + } else { + $.subt = `获取会话: 失败! (${key})` + } + $.msg($.name, $.subt, $.desc) +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/achived/10086/10086.fee.js b/achived/10086/10086.fee.js new file mode 100644 index 000000000..74afa8fe5 --- /dev/null +++ b/achived/10086/10086.fee.js @@ -0,0 +1,124 @@ +// prettier-ignore +!function (t, r) { "object" == typeof exports ? module.exports = exports = r() : "function" == typeof define && define.amd ? define([], r) : t.CryptoJS = r() }(this, function () { + var t = t || function (t, r) { var e = Object.create || function () { function t() { } return function (r) { var e; return t.prototype = r, e = new t, t.prototype = null, e } }(), i = {}, n = i.lib = {}, o = n.Base = function () { return { extend: function (t) { var r = e(this); return t && r.mixIn(t), r.hasOwnProperty("init") && this.init !== r.init || (r.init = function () { r.$super.init.apply(this, arguments) }), r.init.prototype = r, r.$super = this, r }, create: function () { var t = this.extend(); return t.init.apply(t, arguments), t }, init: function () { }, mixIn: function (t) { for (var r in t) t.hasOwnProperty(r) && (this[r] = t[r]); t.hasOwnProperty("toString") && (this.toString = t.toString) }, clone: function () { return this.init.prototype.extend(this) } } }(), s = n.WordArray = o.extend({ init: function (t, e) { t = this.words = t || [], e != r ? this.sigBytes = e : this.sigBytes = 4 * t.length }, toString: function (t) { return (t || c).stringify(this) }, concat: function (t) { var r = this.words, e = t.words, i = this.sigBytes, n = t.sigBytes; if (this.clamp(), i % 4) for (var o = 0; o < n; o++) { var s = e[o >>> 2] >>> 24 - o % 4 * 8 & 255; r[i + o >>> 2] |= s << 24 - (i + o) % 4 * 8 } else for (var o = 0; o < n; o += 4)r[i + o >>> 2] = e[o >>> 2]; return this.sigBytes += n, this }, clamp: function () { var r = this.words, e = this.sigBytes; r[e >>> 2] &= 4294967295 << 32 - e % 4 * 8, r.length = t.ceil(e / 4) }, clone: function () { var t = o.clone.call(this); return t.words = this.words.slice(0), t }, random: function (r) { for (var e, i = [], n = function (r) { var r = r, e = 987654321, i = 4294967295; return function () { e = 36969 * (65535 & e) + (e >> 16) & i, r = 18e3 * (65535 & r) + (r >> 16) & i; var n = (e << 16) + r & i; return n /= 4294967296, n += .5, n * (t.random() > .5 ? 1 : -1) } }, o = 0; o < r; o += 4) { var a = n(4294967296 * (e || t.random())); e = 987654071 * a(), i.push(4294967296 * a() | 0) } return new s.init(i, r) } }), a = i.enc = {}, c = a.Hex = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n++) { var o = r[n >>> 2] >>> 24 - n % 4 * 8 & 255; i.push((o >>> 4).toString(16)), i.push((15 & o).toString(16)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i += 2)e[i >>> 3] |= parseInt(t.substr(i, 2), 16) << 24 - i % 8 * 4; return new s.init(e, r / 2) } }, h = a.Latin1 = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n++) { var o = r[n >>> 2] >>> 24 - n % 4 * 8 & 255; i.push(String.fromCharCode(o)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i++)e[i >>> 2] |= (255 & t.charCodeAt(i)) << 24 - i % 4 * 8; return new s.init(e, r) } }, l = a.Utf8 = { stringify: function (t) { try { return decodeURIComponent(escape(h.stringify(t))) } catch (t) { throw new Error("Malformed UTF-8 data") } }, parse: function (t) { return h.parse(unescape(encodeURIComponent(t))) } }, f = n.BufferedBlockAlgorithm = o.extend({ reset: function () { this._data = new s.init, this._nDataBytes = 0 }, _append: function (t) { "string" == typeof t && (t = l.parse(t)), this._data.concat(t), this._nDataBytes += t.sigBytes }, _process: function (r) { var e = this._data, i = e.words, n = e.sigBytes, o = this.blockSize, a = 4 * o, c = n / a; c = r ? t.ceil(c) : t.max((0 | c) - this._minBufferSize, 0); var h = c * o, l = t.min(4 * h, n); if (h) { for (var f = 0; f < h; f += o)this._doProcessBlock(i, f); var u = i.splice(0, h); e.sigBytes -= l } return new s.init(u, l) }, clone: function () { var t = o.clone.call(this); return t._data = this._data.clone(), t }, _minBufferSize: 0 }), u = (n.Hasher = f.extend({ cfg: o.extend(), init: function (t) { this.cfg = this.cfg.extend(t), this.reset() }, reset: function () { f.reset.call(this), this._doReset() }, update: function (t) { return this._append(t), this._process(), this }, finalize: function (t) { t && this._append(t); var r = this._doFinalize(); return r }, blockSize: 16, _createHelper: function (t) { return function (r, e) { return new t.init(e).finalize(r) } }, _createHmacHelper: function (t) { return function (r, e) { return new u.HMAC.init(t, e).finalize(r) } } }), i.algo = {}); return i }(Math); return function () { function r(t, r, e) { for (var i = [], o = 0, s = 0; s < r; s++)if (s % 4) { var a = e[t.charCodeAt(s - 1)] << s % 4 * 2, c = e[t.charCodeAt(s)] >>> 6 - s % 4 * 2; i[o >>> 2] |= (a | c) << 24 - o % 4 * 8, o++ } return n.create(i, o) } var e = t, i = e.lib, n = i.WordArray, o = e.enc; o.Base64 = { stringify: function (t) { var r = t.words, e = t.sigBytes, i = this._map; t.clamp(); for (var n = [], o = 0; o < e; o += 3)for (var s = r[o >>> 2] >>> 24 - o % 4 * 8 & 255, a = r[o + 1 >>> 2] >>> 24 - (o + 1) % 4 * 8 & 255, c = r[o + 2 >>> 2] >>> 24 - (o + 2) % 4 * 8 & 255, h = s << 16 | a << 8 | c, l = 0; l < 4 && o + .75 * l < e; l++)n.push(i.charAt(h >>> 6 * (3 - l) & 63)); var f = i.charAt(64); if (f) for (; n.length % 4;)n.push(f); return n.join("") }, parse: function (t) { var e = t.length, i = this._map, n = this._reverseMap; if (!n) { n = this._reverseMap = []; for (var o = 0; o < i.length; o++)n[i.charCodeAt(o)] = o } var s = i.charAt(64); if (s) { var a = t.indexOf(s); a !== -1 && (e = a) } return r(t, e, n) }, _map: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" } }(), function (r) { function e(t, r, e, i, n, o, s) { var a = t + (r & e | ~r & i) + n + s; return (a << o | a >>> 32 - o) + r } function i(t, r, e, i, n, o, s) { var a = t + (r & i | e & ~i) + n + s; return (a << o | a >>> 32 - o) + r } function n(t, r, e, i, n, o, s) { var a = t + (r ^ e ^ i) + n + s; return (a << o | a >>> 32 - o) + r } function o(t, r, e, i, n, o, s) { var a = t + (e ^ (r | ~i)) + n + s; return (a << o | a >>> 32 - o) + r } var s = t, a = s.lib, c = a.WordArray, h = a.Hasher, l = s.algo, f = []; !function () { for (var t = 0; t < 64; t++)f[t] = 4294967296 * r.abs(r.sin(t + 1)) | 0 }(); var u = l.MD5 = h.extend({ _doReset: function () { this._hash = new c.init([1732584193, 4023233417, 2562383102, 271733878]) }, _doProcessBlock: function (t, r) { for (var s = 0; s < 16; s++) { var a = r + s, c = t[a]; t[a] = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8) } var h = this._hash.words, l = t[r + 0], u = t[r + 1], d = t[r + 2], v = t[r + 3], p = t[r + 4], _ = t[r + 5], y = t[r + 6], g = t[r + 7], B = t[r + 8], w = t[r + 9], k = t[r + 10], S = t[r + 11], m = t[r + 12], x = t[r + 13], b = t[r + 14], H = t[r + 15], z = h[0], A = h[1], C = h[2], D = h[3]; z = e(z, A, C, D, l, 7, f[0]), D = e(D, z, A, C, u, 12, f[1]), C = e(C, D, z, A, d, 17, f[2]), A = e(A, C, D, z, v, 22, f[3]), z = e(z, A, C, D, p, 7, f[4]), D = e(D, z, A, C, _, 12, f[5]), C = e(C, D, z, A, y, 17, f[6]), A = e(A, C, D, z, g, 22, f[7]), z = e(z, A, C, D, B, 7, f[8]), D = e(D, z, A, C, w, 12, f[9]), C = e(C, D, z, A, k, 17, f[10]), A = e(A, C, D, z, S, 22, f[11]), z = e(z, A, C, D, m, 7, f[12]), D = e(D, z, A, C, x, 12, f[13]), C = e(C, D, z, A, b, 17, f[14]), A = e(A, C, D, z, H, 22, f[15]), z = i(z, A, C, D, u, 5, f[16]), D = i(D, z, A, C, y, 9, f[17]), C = i(C, D, z, A, S, 14, f[18]), A = i(A, C, D, z, l, 20, f[19]), z = i(z, A, C, D, _, 5, f[20]), D = i(D, z, A, C, k, 9, f[21]), C = i(C, D, z, A, H, 14, f[22]), A = i(A, C, D, z, p, 20, f[23]), z = i(z, A, C, D, w, 5, f[24]), D = i(D, z, A, C, b, 9, f[25]), C = i(C, D, z, A, v, 14, f[26]), A = i(A, C, D, z, B, 20, f[27]), z = i(z, A, C, D, x, 5, f[28]), D = i(D, z, A, C, d, 9, f[29]), C = i(C, D, z, A, g, 14, f[30]), A = i(A, C, D, z, m, 20, f[31]), z = n(z, A, C, D, _, 4, f[32]), D = n(D, z, A, C, B, 11, f[33]), C = n(C, D, z, A, S, 16, f[34]), A = n(A, C, D, z, b, 23, f[35]), z = n(z, A, C, D, u, 4, f[36]), D = n(D, z, A, C, p, 11, f[37]), C = n(C, D, z, A, g, 16, f[38]), A = n(A, C, D, z, k, 23, f[39]), z = n(z, A, C, D, x, 4, f[40]), D = n(D, z, A, C, l, 11, f[41]), C = n(C, D, z, A, v, 16, f[42]), A = n(A, C, D, z, y, 23, f[43]), z = n(z, A, C, D, w, 4, f[44]), D = n(D, z, A, C, m, 11, f[45]), C = n(C, D, z, A, H, 16, f[46]), A = n(A, C, D, z, d, 23, f[47]), z = o(z, A, C, D, l, 6, f[48]), D = o(D, z, A, C, g, 10, f[49]), C = o(C, D, z, A, b, 15, f[50]), A = o(A, C, D, z, _, 21, f[51]), z = o(z, A, C, D, m, 6, f[52]), D = o(D, z, A, C, v, 10, f[53]), C = o(C, D, z, A, k, 15, f[54]), A = o(A, C, D, z, u, 21, f[55]), z = o(z, A, C, D, B, 6, f[56]), D = o(D, z, A, C, H, 10, f[57]), C = o(C, D, z, A, y, 15, f[58]), A = o(A, C, D, z, x, 21, f[59]), z = o(z, A, C, D, p, 6, f[60]), D = o(D, z, A, C, S, 10, f[61]), C = o(C, D, z, A, d, 15, f[62]), A = o(A, C, D, z, w, 21, f[63]), h[0] = h[0] + z | 0, h[1] = h[1] + A | 0, h[2] = h[2] + C | 0, h[3] = h[3] + D | 0 }, _doFinalize: function () { var t = this._data, e = t.words, i = 8 * this._nDataBytes, n = 8 * t.sigBytes; e[n >>> 5] |= 128 << 24 - n % 32; var o = r.floor(i / 4294967296), s = i; e[(n + 64 >>> 9 << 4) + 15] = 16711935 & (o << 8 | o >>> 24) | 4278255360 & (o << 24 | o >>> 8), e[(n + 64 >>> 9 << 4) + 14] = 16711935 & (s << 8 | s >>> 24) | 4278255360 & (s << 24 | s >>> 8), t.sigBytes = 4 * (e.length + 1), this._process(); for (var a = this._hash, c = a.words, h = 0; h < 4; h++) { var l = c[h]; c[h] = 16711935 & (l << 8 | l >>> 24) | 4278255360 & (l << 24 | l >>> 8) } return a }, clone: function () { var t = h.clone.call(this); return t._hash = this._hash.clone(), t } }); s.MD5 = h._createHelper(u), s.HmacMD5 = h._createHmacHelper(u) }(Math), function () { var r = t, e = r.lib, i = e.WordArray, n = e.Hasher, o = r.algo, s = [], a = o.SHA1 = n.extend({ _doReset: function () { this._hash = new i.init([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], a = e[3], c = e[4], h = 0; h < 80; h++) { if (h < 16) s[h] = 0 | t[r + h]; else { var l = s[h - 3] ^ s[h - 8] ^ s[h - 14] ^ s[h - 16]; s[h] = l << 1 | l >>> 31 } var f = (i << 5 | i >>> 27) + c + s[h]; f += h < 20 ? (n & o | ~n & a) + 1518500249 : h < 40 ? (n ^ o ^ a) + 1859775393 : h < 60 ? (n & o | n & a | o & a) - 1894007588 : (n ^ o ^ a) - 899497514, c = a, a = o, o = n << 30 | n >>> 2, n = i, i = f } e[0] = e[0] + i | 0, e[1] = e[1] + n | 0, e[2] = e[2] + o | 0, e[3] = e[3] + a | 0, e[4] = e[4] + c | 0 }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; return r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 64 >>> 9 << 4) + 14] = Math.floor(e / 4294967296), r[(i + 64 >>> 9 << 4) + 15] = e, t.sigBytes = 4 * r.length, this._process(), this._hash }, clone: function () { var t = n.clone.call(this); return t._hash = this._hash.clone(), t } }); r.SHA1 = n._createHelper(a), r.HmacSHA1 = n._createHmacHelper(a) }(), function (r) { var e = t, i = e.lib, n = i.WordArray, o = i.Hasher, s = e.algo, a = [], c = []; !function () { function t(t) { for (var e = r.sqrt(t), i = 2; i <= e; i++)if (!(t % i)) return !1; return !0 } function e(t) { return 4294967296 * (t - (0 | t)) | 0 } for (var i = 2, n = 0; n < 64;)t(i) && (n < 8 && (a[n] = e(r.pow(i, .5))), c[n] = e(r.pow(i, 1 / 3)), n++), i++ }(); var h = [], l = s.SHA256 = o.extend({ _doReset: function () { this._hash = new n.init(a.slice(0)) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], s = e[3], a = e[4], l = e[5], f = e[6], u = e[7], d = 0; d < 64; d++) { if (d < 16) h[d] = 0 | t[r + d]; else { var v = h[d - 15], p = (v << 25 | v >>> 7) ^ (v << 14 | v >>> 18) ^ v >>> 3, _ = h[d - 2], y = (_ << 15 | _ >>> 17) ^ (_ << 13 | _ >>> 19) ^ _ >>> 10; h[d] = p + h[d - 7] + y + h[d - 16] } var g = a & l ^ ~a & f, B = i & n ^ i & o ^ n & o, w = (i << 30 | i >>> 2) ^ (i << 19 | i >>> 13) ^ (i << 10 | i >>> 22), k = (a << 26 | a >>> 6) ^ (a << 21 | a >>> 11) ^ (a << 7 | a >>> 25), S = u + k + g + c[d] + h[d], m = w + B; u = f, f = l, l = a, a = s + S | 0, s = o, o = n, n = i, i = S + m | 0 } e[0] = e[0] + i | 0, e[1] = e[1] + n | 0, e[2] = e[2] + o | 0, e[3] = e[3] + s | 0, e[4] = e[4] + a | 0, e[5] = e[5] + l | 0, e[6] = e[6] + f | 0, e[7] = e[7] + u | 0 }, _doFinalize: function () { var t = this._data, e = t.words, i = 8 * this._nDataBytes, n = 8 * t.sigBytes; return e[n >>> 5] |= 128 << 24 - n % 32, e[(n + 64 >>> 9 << 4) + 14] = r.floor(i / 4294967296), e[(n + 64 >>> 9 << 4) + 15] = i, t.sigBytes = 4 * e.length, this._process(), this._hash }, clone: function () { var t = o.clone.call(this); return t._hash = this._hash.clone(), t } }); e.SHA256 = o._createHelper(l), e.HmacSHA256 = o._createHmacHelper(l) }(Math), function () { function r(t) { return t << 8 & 4278255360 | t >>> 8 & 16711935 } var e = t, i = e.lib, n = i.WordArray, o = e.enc; o.Utf16 = o.Utf16BE = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n += 2) { var o = r[n >>> 2] >>> 16 - n % 4 * 8 & 65535; i.push(String.fromCharCode(o)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i++)e[i >>> 1] |= t.charCodeAt(i) << 16 - i % 2 * 16; return n.create(e, 2 * r) } }; o.Utf16LE = { stringify: function (t) { for (var e = t.words, i = t.sigBytes, n = [], o = 0; o < i; o += 2) { var s = r(e[o >>> 2] >>> 16 - o % 4 * 8 & 65535); n.push(String.fromCharCode(s)) } return n.join("") }, parse: function (t) { for (var e = t.length, i = [], o = 0; o < e; o++)i[o >>> 1] |= r(t.charCodeAt(o) << 16 - o % 2 * 16); return n.create(i, 2 * e) } } }(), function () { if ("function" == typeof ArrayBuffer) { var r = t, e = r.lib, i = e.WordArray, n = i.init, o = i.init = function (t) { if (t instanceof ArrayBuffer && (t = new Uint8Array(t)), (t instanceof Int8Array || "undefined" != typeof Uint8ClampedArray && t instanceof Uint8ClampedArray || t instanceof Int16Array || t instanceof Uint16Array || t instanceof Int32Array || t instanceof Uint32Array || t instanceof Float32Array || t instanceof Float64Array) && (t = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), t instanceof Uint8Array) { for (var r = t.byteLength, e = [], i = 0; i < r; i++)e[i >>> 2] |= t[i] << 24 - i % 4 * 8; n.call(this, e, r) } else n.apply(this, arguments) }; o.prototype = i } }(), function (r) { function e(t, r, e) { return t ^ r ^ e } function i(t, r, e) { return t & r | ~t & e } function n(t, r, e) { return (t | ~r) ^ e } function o(t, r, e) { return t & e | r & ~e } function s(t, r, e) { return t ^ (r | ~e) } function a(t, r) { return t << r | t >>> 32 - r } var c = t, h = c.lib, l = h.WordArray, f = h.Hasher, u = c.algo, d = l.create([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]), v = l.create([5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]), p = l.create([11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6]), _ = l.create([8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]), y = l.create([0, 1518500249, 1859775393, 2400959708, 2840853838]), g = l.create([1352829926, 1548603684, 1836072691, 2053994217, 0]), B = u.RIPEMD160 = f.extend({ _doReset: function () { this._hash = l.create([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) }, _doProcessBlock: function (t, r) { for (var c = 0; c < 16; c++) { var h = r + c, l = t[h]; t[h] = 16711935 & (l << 8 | l >>> 24) | 4278255360 & (l << 24 | l >>> 8) } var f, u, B, w, k, S, m, x, b, H, z = this._hash.words, A = y.words, C = g.words, D = d.words, R = v.words, E = p.words, M = _.words; S = f = z[0], m = u = z[1], x = B = z[2], b = w = z[3], H = k = z[4]; for (var F, c = 0; c < 80; c += 1)F = f + t[r + D[c]] | 0, F += c < 16 ? e(u, B, w) + A[0] : c < 32 ? i(u, B, w) + A[1] : c < 48 ? n(u, B, w) + A[2] : c < 64 ? o(u, B, w) + A[3] : s(u, B, w) + A[4], F |= 0, F = a(F, E[c]), F = F + k | 0, f = k, k = w, w = a(B, 10), B = u, u = F, F = S + t[r + R[c]] | 0, F += c < 16 ? s(m, x, b) + C[0] : c < 32 ? o(m, x, b) + C[1] : c < 48 ? n(m, x, b) + C[2] : c < 64 ? i(m, x, b) + C[3] : e(m, x, b) + C[4], F |= 0, F = a(F, M[c]), F = F + H | 0, S = H, H = b, b = a(x, 10), x = m, m = F; F = z[1] + B + b | 0, z[1] = z[2] + w + H | 0, z[2] = z[3] + k + S | 0, z[3] = z[4] + f + m | 0, z[4] = z[0] + u + x | 0, z[0] = F }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 64 >>> 9 << 4) + 14] = 16711935 & (e << 8 | e >>> 24) | 4278255360 & (e << 24 | e >>> 8), t.sigBytes = 4 * (r.length + 1), this._process(); for (var n = this._hash, o = n.words, s = 0; s < 5; s++) { var a = o[s]; o[s] = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8) } return n }, clone: function () { var t = f.clone.call(this); return t._hash = this._hash.clone(), t } }); c.RIPEMD160 = f._createHelper(B), c.HmacRIPEMD160 = f._createHmacHelper(B) }(Math), function () { var r = t, e = r.lib, i = e.Base, n = r.enc, o = n.Utf8, s = r.algo; s.HMAC = i.extend({ init: function (t, r) { t = this._hasher = new t.init, "string" == typeof r && (r = o.parse(r)); var e = t.blockSize, i = 4 * e; r.sigBytes > i && (r = t.finalize(r)), r.clamp(); for (var n = this._oKey = r.clone(), s = this._iKey = r.clone(), a = n.words, c = s.words, h = 0; h < e; h++)a[h] ^= 1549556828, c[h] ^= 909522486; n.sigBytes = s.sigBytes = i, this.reset() }, reset: function () { var t = this._hasher; t.reset(), t.update(this._iKey) }, update: function (t) { return this._hasher.update(t), this }, finalize: function (t) { var r = this._hasher, e = r.finalize(t); r.reset(); var i = r.finalize(this._oKey.clone().concat(e)); return i } }) }(), function () { var r = t, e = r.lib, i = e.Base, n = e.WordArray, o = r.algo, s = o.SHA1, a = o.HMAC, c = o.PBKDF2 = i.extend({ cfg: i.extend({ keySize: 4, hasher: s, iterations: 1 }), init: function (t) { this.cfg = this.cfg.extend(t) }, compute: function (t, r) { for (var e = this.cfg, i = a.create(e.hasher, t), o = n.create(), s = n.create([1]), c = o.words, h = s.words, l = e.keySize, f = e.iterations; c.length < l;) { var u = i.update(r).finalize(s); i.reset(); for (var d = u.words, v = d.length, p = u, _ = 1; _ < f; _++) { p = i.finalize(p), i.reset(); for (var y = p.words, g = 0; g < v; g++)d[g] ^= y[g] } o.concat(u), h[0]++ } return o.sigBytes = 4 * l, o } }); r.PBKDF2 = function (t, r, e) { return c.create(e).compute(t, r) } }(), function () { var r = t, e = r.lib, i = e.Base, n = e.WordArray, o = r.algo, s = o.MD5, a = o.EvpKDF = i.extend({ cfg: i.extend({ keySize: 4, hasher: s, iterations: 1 }), init: function (t) { this.cfg = this.cfg.extend(t) }, compute: function (t, r) { for (var e = this.cfg, i = e.hasher.create(), o = n.create(), s = o.words, a = e.keySize, c = e.iterations; s.length < a;) { h && i.update(h); var h = i.update(t).finalize(r); i.reset(); for (var l = 1; l < c; l++)h = i.finalize(h), i.reset(); o.concat(h) } return o.sigBytes = 4 * a, o } }); r.EvpKDF = function (t, r, e) { return a.create(e).compute(t, r) } }(), function () { var r = t, e = r.lib, i = e.WordArray, n = r.algo, o = n.SHA256, s = n.SHA224 = o.extend({ _doReset: function () { this._hash = new i.init([3238371032, 914150663, 812702999, 4144912697, 4290775857, 1750603025, 1694076839, 3204075428]) }, _doFinalize: function () { var t = o._doFinalize.call(this); return t.sigBytes -= 4, t } }); r.SHA224 = o._createHelper(s), r.HmacSHA224 = o._createHmacHelper(s) }(), function (r) { var e = t, i = e.lib, n = i.Base, o = i.WordArray, s = e.x64 = {}; s.Word = n.extend({ init: function (t, r) { this.high = t, this.low = r } }), s.WordArray = n.extend({ init: function (t, e) { t = this.words = t || [], e != r ? this.sigBytes = e : this.sigBytes = 8 * t.length }, toX32: function () { for (var t = this.words, r = t.length, e = [], i = 0; i < r; i++) { var n = t[i]; e.push(n.high), e.push(n.low) } return o.create(e, this.sigBytes) }, clone: function () { for (var t = n.clone.call(this), r = t.words = this.words.slice(0), e = r.length, i = 0; i < e; i++)r[i] = r[i].clone(); return t } }) }(), function (r) { var e = t, i = e.lib, n = i.WordArray, o = i.Hasher, s = e.x64, a = s.Word, c = e.algo, h = [], l = [], f = []; !function () { for (var t = 1, r = 0, e = 0; e < 24; e++) { h[t + 5 * r] = (e + 1) * (e + 2) / 2 % 64; var i = r % 5, n = (2 * t + 3 * r) % 5; t = i, r = n } for (var t = 0; t < 5; t++)for (var r = 0; r < 5; r++)l[t + 5 * r] = r + (2 * t + 3 * r) % 5 * 5; for (var o = 1, s = 0; s < 24; s++) { for (var c = 0, u = 0, d = 0; d < 7; d++) { if (1 & o) { var v = (1 << d) - 1; v < 32 ? u ^= 1 << v : c ^= 1 << v - 32 } 128 & o ? o = o << 1 ^ 113 : o <<= 1 } f[s] = a.create(c, u) } }(); var u = []; !function () { for (var t = 0; t < 25; t++)u[t] = a.create() }(); var d = c.SHA3 = o.extend({ cfg: o.cfg.extend({ outputLength: 512 }), _doReset: function () { for (var t = this._state = [], r = 0; r < 25; r++)t[r] = new a.init; this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32 }, _doProcessBlock: function (t, r) { for (var e = this._state, i = this.blockSize / 2, n = 0; n < i; n++) { var o = t[r + 2 * n], s = t[r + 2 * n + 1]; o = 16711935 & (o << 8 | o >>> 24) | 4278255360 & (o << 24 | o >>> 8), s = 16711935 & (s << 8 | s >>> 24) | 4278255360 & (s << 24 | s >>> 8); var a = e[n]; a.high ^= s, a.low ^= o } for (var c = 0; c < 24; c++) { for (var d = 0; d < 5; d++) { for (var v = 0, p = 0, _ = 0; _ < 5; _++) { var a = e[d + 5 * _]; v ^= a.high, p ^= a.low } var y = u[d]; y.high = v, y.low = p } for (var d = 0; d < 5; d++)for (var g = u[(d + 4) % 5], B = u[(d + 1) % 5], w = B.high, k = B.low, v = g.high ^ (w << 1 | k >>> 31), p = g.low ^ (k << 1 | w >>> 31), _ = 0; _ < 5; _++) { var a = e[d + 5 * _]; a.high ^= v, a.low ^= p } for (var S = 1; S < 25; S++) { var a = e[S], m = a.high, x = a.low, b = h[S]; if (b < 32) var v = m << b | x >>> 32 - b, p = x << b | m >>> 32 - b; else var v = x << b - 32 | m >>> 64 - b, p = m << b - 32 | x >>> 64 - b; var H = u[l[S]]; H.high = v, H.low = p } var z = u[0], A = e[0]; z.high = A.high, z.low = A.low; for (var d = 0; d < 5; d++)for (var _ = 0; _ < 5; _++) { var S = d + 5 * _, a = e[S], C = u[S], D = u[(d + 1) % 5 + 5 * _], R = u[(d + 2) % 5 + 5 * _]; a.high = C.high ^ ~D.high & R.high, a.low = C.low ^ ~D.low & R.low } var a = e[0], E = f[c]; a.high ^= E.high, a.low ^= E.low } }, _doFinalize: function () { var t = this._data, e = t.words, i = (8 * this._nDataBytes, 8 * t.sigBytes), o = 32 * this.blockSize; e[i >>> 5] |= 1 << 24 - i % 32, e[(r.ceil((i + 1) / o) * o >>> 5) - 1] |= 128, t.sigBytes = 4 * e.length, this._process(); for (var s = this._state, a = this.cfg.outputLength / 8, c = a / 8, h = [], l = 0; l < c; l++) { var f = s[l], u = f.high, d = f.low; u = 16711935 & (u << 8 | u >>> 24) | 4278255360 & (u << 24 | u >>> 8), d = 16711935 & (d << 8 | d >>> 24) | 4278255360 & (d << 24 | d >>> 8), h.push(d), h.push(u) } return new n.init(h, a) }, clone: function () { for (var t = o.clone.call(this), r = t._state = this._state.slice(0), e = 0; e < 25; e++)r[e] = r[e].clone(); return t } }); e.SHA3 = o._createHelper(d), e.HmacSHA3 = o._createHmacHelper(d) }(Math), function () { function r() { return s.create.apply(s, arguments) } var e = t, i = e.lib, n = i.Hasher, o = e.x64, s = o.Word, a = o.WordArray, c = e.algo, h = [r(1116352408, 3609767458), r(1899447441, 602891725), r(3049323471, 3964484399), r(3921009573, 2173295548), r(961987163, 4081628472), r(1508970993, 3053834265), r(2453635748, 2937671579), r(2870763221, 3664609560), r(3624381080, 2734883394), r(310598401, 1164996542), r(607225278, 1323610764), r(1426881987, 3590304994), r(1925078388, 4068182383), r(2162078206, 991336113), r(2614888103, 633803317), r(3248222580, 3479774868), r(3835390401, 2666613458), r(4022224774, 944711139), r(264347078, 2341262773), r(604807628, 2007800933), r(770255983, 1495990901), r(1249150122, 1856431235), r(1555081692, 3175218132), r(1996064986, 2198950837), r(2554220882, 3999719339), r(2821834349, 766784016), r(2952996808, 2566594879), r(3210313671, 3203337956), r(3336571891, 1034457026), r(3584528711, 2466948901), r(113926993, 3758326383), r(338241895, 168717936), r(666307205, 1188179964), r(773529912, 1546045734), r(1294757372, 1522805485), r(1396182291, 2643833823), r(1695183700, 2343527390), r(1986661051, 1014477480), r(2177026350, 1206759142), r(2456956037, 344077627), r(2730485921, 1290863460), r(2820302411, 3158454273), r(3259730800, 3505952657), r(3345764771, 106217008), r(3516065817, 3606008344), r(3600352804, 1432725776), r(4094571909, 1467031594), r(275423344, 851169720), r(430227734, 3100823752), r(506948616, 1363258195), r(659060556, 3750685593), r(883997877, 3785050280), r(958139571, 3318307427), r(1322822218, 3812723403), r(1537002063, 2003034995), r(1747873779, 3602036899), r(1955562222, 1575990012), r(2024104815, 1125592928), r(2227730452, 2716904306), r(2361852424, 442776044), r(2428436474, 593698344), r(2756734187, 3733110249), r(3204031479, 2999351573), r(3329325298, 3815920427), r(3391569614, 3928383900), r(3515267271, 566280711), r(3940187606, 3454069534), r(4118630271, 4000239992), r(116418474, 1914138554), r(174292421, 2731055270), r(289380356, 3203993006), r(460393269, 320620315), r(685471733, 587496836), r(852142971, 1086792851), r(1017036298, 365543100), r(1126000580, 2618297676), r(1288033470, 3409855158), r(1501505948, 4234509866), r(1607167915, 987167468), r(1816402316, 1246189591)], l = []; !function () { for (var t = 0; t < 80; t++)l[t] = r() }(); var f = c.SHA512 = n.extend({ _doReset: function () { this._hash = new a.init([new s.init(1779033703, 4089235720), new s.init(3144134277, 2227873595), new s.init(1013904242, 4271175723), new s.init(2773480762, 1595750129), new s.init(1359893119, 2917565137), new s.init(2600822924, 725511199), new s.init(528734635, 4215389547), new s.init(1541459225, 327033209)]) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], s = e[3], a = e[4], c = e[5], f = e[6], u = e[7], d = i.high, v = i.low, p = n.high, _ = n.low, y = o.high, g = o.low, B = s.high, w = s.low, k = a.high, S = a.low, m = c.high, x = c.low, b = f.high, H = f.low, z = u.high, A = u.low, C = d, D = v, R = p, E = _, M = y, F = g, P = B, W = w, O = k, U = S, I = m, K = x, X = b, L = H, j = z, N = A, T = 0; T < 80; T++) { var Z = l[T]; if (T < 16) var q = Z.high = 0 | t[r + 2 * T], G = Z.low = 0 | t[r + 2 * T + 1]; else { var J = l[T - 15], $ = J.high, Q = J.low, V = ($ >>> 1 | Q << 31) ^ ($ >>> 8 | Q << 24) ^ $ >>> 7, Y = (Q >>> 1 | $ << 31) ^ (Q >>> 8 | $ << 24) ^ (Q >>> 7 | $ << 25), tt = l[T - 2], rt = tt.high, et = tt.low, it = (rt >>> 19 | et << 13) ^ (rt << 3 | et >>> 29) ^ rt >>> 6, nt = (et >>> 19 | rt << 13) ^ (et << 3 | rt >>> 29) ^ (et >>> 6 | rt << 26), ot = l[T - 7], st = ot.high, at = ot.low, ct = l[T - 16], ht = ct.high, lt = ct.low, G = Y + at, q = V + st + (G >>> 0 < Y >>> 0 ? 1 : 0), G = G + nt, q = q + it + (G >>> 0 < nt >>> 0 ? 1 : 0), G = G + lt, q = q + ht + (G >>> 0 < lt >>> 0 ? 1 : 0); Z.high = q, Z.low = G } var ft = O & I ^ ~O & X, ut = U & K ^ ~U & L, dt = C & R ^ C & M ^ R & M, vt = D & E ^ D & F ^ E & F, pt = (C >>> 28 | D << 4) ^ (C << 30 | D >>> 2) ^ (C << 25 | D >>> 7), _t = (D >>> 28 | C << 4) ^ (D << 30 | C >>> 2) ^ (D << 25 | C >>> 7), yt = (O >>> 14 | U << 18) ^ (O >>> 18 | U << 14) ^ (O << 23 | U >>> 9), gt = (U >>> 14 | O << 18) ^ (U >>> 18 | O << 14) ^ (U << 23 | O >>> 9), Bt = h[T], wt = Bt.high, kt = Bt.low, St = N + gt, mt = j + yt + (St >>> 0 < N >>> 0 ? 1 : 0), St = St + ut, mt = mt + ft + (St >>> 0 < ut >>> 0 ? 1 : 0), St = St + kt, mt = mt + wt + (St >>> 0 < kt >>> 0 ? 1 : 0), St = St + G, mt = mt + q + (St >>> 0 < G >>> 0 ? 1 : 0), xt = _t + vt, bt = pt + dt + (xt >>> 0 < _t >>> 0 ? 1 : 0); j = X, N = L, X = I, L = K, I = O, K = U, U = W + St | 0, O = P + mt + (U >>> 0 < W >>> 0 ? 1 : 0) | 0, P = M, W = F, M = R, F = E, R = C, E = D, D = St + xt | 0, C = mt + bt + (D >>> 0 < St >>> 0 ? 1 : 0) | 0 } v = i.low = v + D, i.high = d + C + (v >>> 0 < D >>> 0 ? 1 : 0), _ = n.low = _ + E, n.high = p + R + (_ >>> 0 < E >>> 0 ? 1 : 0), g = o.low = g + F, o.high = y + M + (g >>> 0 < F >>> 0 ? 1 : 0), w = s.low = w + W, s.high = B + P + (w >>> 0 < W >>> 0 ? 1 : 0), S = a.low = S + U, a.high = k + O + (S >>> 0 < U >>> 0 ? 1 : 0), x = c.low = x + K, c.high = m + I + (x >>> 0 < K >>> 0 ? 1 : 0), H = f.low = H + L, f.high = b + X + (H >>> 0 < L >>> 0 ? 1 : 0), A = u.low = A + N, u.high = z + j + (A >>> 0 < N >>> 0 ? 1 : 0) }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 128 >>> 10 << 5) + 30] = Math.floor(e / 4294967296), r[(i + 128 >>> 10 << 5) + 31] = e, t.sigBytes = 4 * r.length, this._process(); var n = this._hash.toX32(); return n }, clone: function () { var t = n.clone.call(this); return t._hash = this._hash.clone(), t }, blockSize: 32 }); e.SHA512 = n._createHelper(f), e.HmacSHA512 = n._createHmacHelper(f) }(), function () { var r = t, e = r.x64, i = e.Word, n = e.WordArray, o = r.algo, s = o.SHA512, a = o.SHA384 = s.extend({ _doReset: function () { this._hash = new n.init([new i.init(3418070365, 3238371032), new i.init(1654270250, 914150663), new i.init(2438529370, 812702999), new i.init(355462360, 4144912697), new i.init(1731405415, 4290775857), new i.init(2394180231, 1750603025), new i.init(3675008525, 1694076839), new i.init(1203062813, 3204075428)]) }, _doFinalize: function () { var t = s._doFinalize.call(this); return t.sigBytes -= 16, t } }); r.SHA384 = s._createHelper(a), r.HmacSHA384 = s._createHmacHelper(a) }(), t.lib.Cipher || function (r) { var e = t, i = e.lib, n = i.Base, o = i.WordArray, s = i.BufferedBlockAlgorithm, a = e.enc, c = (a.Utf8, a.Base64), h = e.algo, l = h.EvpKDF, f = i.Cipher = s.extend({ cfg: n.extend(), createEncryptor: function (t, r) { return this.create(this._ENC_XFORM_MODE, t, r) }, createDecryptor: function (t, r) { return this.create(this._DEC_XFORM_MODE, t, r) }, init: function (t, r, e) { this.cfg = this.cfg.extend(e), this._xformMode = t, this._key = r, this.reset() }, reset: function () { s.reset.call(this), this._doReset() }, process: function (t) { return this._append(t), this._process() }, finalize: function (t) { t && this._append(t); var r = this._doFinalize(); return r }, keySize: 4, ivSize: 4, _ENC_XFORM_MODE: 1, _DEC_XFORM_MODE: 2, _createHelper: function () { function t(t) { return "string" == typeof t ? m : w } return function (r) { return { encrypt: function (e, i, n) { return t(i).encrypt(r, e, i, n) }, decrypt: function (e, i, n) { return t(i).decrypt(r, e, i, n) } } } }() }), u = (i.StreamCipher = f.extend({ _doFinalize: function () { var t = this._process(!0); return t }, blockSize: 1 }), e.mode = {}), d = i.BlockCipherMode = n.extend({ createEncryptor: function (t, r) { return this.Encryptor.create(t, r) }, createDecryptor: function (t, r) { return this.Decryptor.create(t, r) }, init: function (t, r) { this._cipher = t, this._iv = r } }), v = u.CBC = function () { function t(t, e, i) { var n = this._iv; if (n) { var o = n; this._iv = r } else var o = this._prevBlock; for (var s = 0; s < i; s++)t[e + s] ^= o[s] } var e = d.extend(); return e.Encryptor = e.extend({ processBlock: function (r, e) { var i = this._cipher, n = i.blockSize; t.call(this, r, e, n), i.encryptBlock(r, e), this._prevBlock = r.slice(e, e + n) } }), e.Decryptor = e.extend({ processBlock: function (r, e) { var i = this._cipher, n = i.blockSize, o = r.slice(e, e + n); i.decryptBlock(r, e), t.call(this, r, e, n), this._prevBlock = o } }), e }(), p = e.pad = {}, _ = p.Pkcs7 = { pad: function (t, r) { for (var e = 4 * r, i = e - t.sigBytes % e, n = i << 24 | i << 16 | i << 8 | i, s = [], a = 0; a < i; a += 4)s.push(n); var c = o.create(s, i); t.concat(c) }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, y = (i.BlockCipher = f.extend({ cfg: f.cfg.extend({ mode: v, padding: _ }), reset: function () { f.reset.call(this); var t = this.cfg, r = t.iv, e = t.mode; if (this._xformMode == this._ENC_XFORM_MODE) var i = e.createEncryptor; else { var i = e.createDecryptor; this._minBufferSize = 1 } this._mode && this._mode.__creator == i ? this._mode.init(this, r && r.words) : (this._mode = i.call(e, this, r && r.words), this._mode.__creator = i) }, _doProcessBlock: function (t, r) { this._mode.processBlock(t, r) }, _doFinalize: function () { var t = this.cfg.padding; if (this._xformMode == this._ENC_XFORM_MODE) { t.pad(this._data, this.blockSize); var r = this._process(!0) } else { var r = this._process(!0); t.unpad(r) } return r }, blockSize: 4 }), i.CipherParams = n.extend({ init: function (t) { this.mixIn(t) }, toString: function (t) { return (t || this.formatter).stringify(this) } })), g = e.format = {}, B = g.OpenSSL = { stringify: function (t) { var r = t.ciphertext, e = t.salt; if (e) var i = o.create([1398893684, 1701076831]).concat(e).concat(r); else var i = r; return i.toString(c) }, parse: function (t) { var r = c.parse(t), e = r.words; if (1398893684 == e[0] && 1701076831 == e[1]) { var i = o.create(e.slice(2, 4)); e.splice(0, 4), r.sigBytes -= 16 } return y.create({ ciphertext: r, salt: i }) } }, w = i.SerializableCipher = n.extend({ cfg: n.extend({ format: B }), encrypt: function (t, r, e, i) { i = this.cfg.extend(i); var n = t.createEncryptor(e, i), o = n.finalize(r), s = n.cfg; return y.create({ ciphertext: o, key: e, iv: s.iv, algorithm: t, mode: s.mode, padding: s.padding, blockSize: t.blockSize, formatter: i.format }) }, decrypt: function (t, r, e, i) { i = this.cfg.extend(i), r = this._parse(r, i.format); var n = t.createDecryptor(e, i).finalize(r.ciphertext); return n }, _parse: function (t, r) { return "string" == typeof t ? r.parse(t, this) : t } }), k = e.kdf = {}, S = k.OpenSSL = { execute: function (t, r, e, i) { i || (i = o.random(8)); var n = l.create({ keySize: r + e }).compute(t, i), s = o.create(n.words.slice(r), 4 * e); return n.sigBytes = 4 * r, y.create({ key: n, iv: s, salt: i }) } }, m = i.PasswordBasedCipher = w.extend({ cfg: w.cfg.extend({ kdf: S }), encrypt: function (t, r, e, i) { i = this.cfg.extend(i); var n = i.kdf.execute(e, t.keySize, t.ivSize); i.iv = n.iv; var o = w.encrypt.call(this, t, r, n.key, i); return o.mixIn(n), o }, decrypt: function (t, r, e, i) { i = this.cfg.extend(i), r = this._parse(r, i.format); var n = i.kdf.execute(e, t.keySize, t.ivSize, r.salt); i.iv = n.iv; var o = w.decrypt.call(this, t, r, n.key, i); return o } }) }(), t.mode.CFB = function () { function r(t, r, e, i) { var n = this._iv; if (n) { var o = n.slice(0); this._iv = void 0 } else var o = this._prevBlock; i.encryptBlock(o, 0); for (var s = 0; s < e; s++)t[r + s] ^= o[s] } var e = t.lib.BlockCipherMode.extend(); return e.Encryptor = e.extend({ processBlock: function (t, e) { var i = this._cipher, n = i.blockSize; r.call(this, t, e, n, i), this._prevBlock = t.slice(e, e + n) } }), e.Decryptor = e.extend({ processBlock: function (t, e) { var i = this._cipher, n = i.blockSize, o = t.slice(e, e + n); r.call(this, t, e, n, i), this._prevBlock = o } }), e }(), t.mode.ECB = function () { var r = t.lib.BlockCipherMode.extend(); return r.Encryptor = r.extend({ processBlock: function (t, r) { this._cipher.encryptBlock(t, r) } }), r.Decryptor = r.extend({ processBlock: function (t, r) { this._cipher.decryptBlock(t, r) } }), r }(), t.pad.AnsiX923 = { pad: function (t, r) { var e = t.sigBytes, i = 4 * r, n = i - e % i, o = e + n - 1; t.clamp(), t.words[o >>> 2] |= n << 24 - o % 4 * 8, t.sigBytes += n }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, t.pad.Iso10126 = { pad: function (r, e) { var i = 4 * e, n = i - r.sigBytes % i; r.concat(t.lib.WordArray.random(n - 1)).concat(t.lib.WordArray.create([n << 24], 1)) }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, t.pad.Iso97971 = { pad: function (r, e) { r.concat(t.lib.WordArray.create([2147483648], 1)), t.pad.ZeroPadding.pad(r, e) }, unpad: function (r) { t.pad.ZeroPadding.unpad(r), r.sigBytes-- } }, t.mode.OFB = function () { var r = t.lib.BlockCipherMode.extend(), e = r.Encryptor = r.extend({ processBlock: function (t, r) { var e = this._cipher, i = e.blockSize, n = this._iv, o = this._keystream; n && (o = this._keystream = n.slice(0), this._iv = void 0), e.encryptBlock(o, 0); for (var s = 0; s < i; s++)t[r + s] ^= o[s] } }); return r.Decryptor = e, r }(), t.pad.NoPadding = { pad: function () { }, unpad: function () { } }, function (r) { var e = t, i = e.lib, n = i.CipherParams, o = e.enc, s = o.Hex, a = e.format; a.Hex = { stringify: function (t) { return t.ciphertext.toString(s) }, parse: function (t) { var r = s.parse(t); return n.create({ ciphertext: r }) } } }(), function () { var r = t, e = r.lib, i = e.BlockCipher, n = r.algo, o = [], s = [], a = [], c = [], h = [], l = [], f = [], u = [], d = [], v = []; !function () { for (var t = [], r = 0; r < 256; r++)r < 128 ? t[r] = r << 1 : t[r] = r << 1 ^ 283; for (var e = 0, i = 0, r = 0; r < 256; r++) { var n = i ^ i << 1 ^ i << 2 ^ i << 3 ^ i << 4; n = n >>> 8 ^ 255 & n ^ 99, o[e] = n, s[n] = e; var p = t[e], _ = t[p], y = t[_], g = 257 * t[n] ^ 16843008 * n; a[e] = g << 24 | g >>> 8, c[e] = g << 16 | g >>> 16, h[e] = g << 8 | g >>> 24, l[e] = g; var g = 16843009 * y ^ 65537 * _ ^ 257 * p ^ 16843008 * e; f[n] = g << 24 | g >>> 8, u[n] = g << 16 | g >>> 16, d[n] = g << 8 | g >>> 24, v[n] = g, e ? (e = p ^ t[t[t[y ^ p]]], i ^= t[t[i]]) : e = i = 1 } }(); var p = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54], _ = n.AES = i.extend({ _doReset: function () { if (!this._nRounds || this._keyPriorReset !== this._key) { for (var t = this._keyPriorReset = this._key, r = t.words, e = t.sigBytes / 4, i = this._nRounds = e + 6, n = 4 * (i + 1), s = this._keySchedule = [], a = 0; a < n; a++)if (a < e) s[a] = r[a]; else { var c = s[a - 1]; a % e ? e > 6 && a % e == 4 && (c = o[c >>> 24] << 24 | o[c >>> 16 & 255] << 16 | o[c >>> 8 & 255] << 8 | o[255 & c]) : (c = c << 8 | c >>> 24, c = o[c >>> 24] << 24 | o[c >>> 16 & 255] << 16 | o[c >>> 8 & 255] << 8 | o[255 & c], c ^= p[a / e | 0] << 24), s[a] = s[a - e] ^ c } for (var h = this._invKeySchedule = [], l = 0; l < n; l++) { var a = n - l; if (l % 4) var c = s[a]; else var c = s[a - 4]; l < 4 || a <= 4 ? h[l] = c : h[l] = f[o[c >>> 24]] ^ u[o[c >>> 16 & 255]] ^ d[o[c >>> 8 & 255]] ^ v[o[255 & c]] } } }, encryptBlock: function (t, r) { this._doCryptBlock(t, r, this._keySchedule, a, c, h, l, o) }, decryptBlock: function (t, r) { var e = t[r + 1]; t[r + 1] = t[r + 3], t[r + 3] = e, this._doCryptBlock(t, r, this._invKeySchedule, f, u, d, v, s); var e = t[r + 1]; t[r + 1] = t[r + 3], t[r + 3] = e }, _doCryptBlock: function (t, r, e, i, n, o, s, a) { for (var c = this._nRounds, h = t[r] ^ e[0], l = t[r + 1] ^ e[1], f = t[r + 2] ^ e[2], u = t[r + 3] ^ e[3], d = 4, v = 1; v < c; v++) { var p = i[h >>> 24] ^ n[l >>> 16 & 255] ^ o[f >>> 8 & 255] ^ s[255 & u] ^ e[d++], _ = i[l >>> 24] ^ n[f >>> 16 & 255] ^ o[u >>> 8 & 255] ^ s[255 & h] ^ e[d++], y = i[f >>> 24] ^ n[u >>> 16 & 255] ^ o[h >>> 8 & 255] ^ s[255 & l] ^ e[d++], g = i[u >>> 24] ^ n[h >>> 16 & 255] ^ o[l >>> 8 & 255] ^ s[255 & f] ^ e[d++]; h = p, l = _, f = y, u = g } var p = (a[h >>> 24] << 24 | a[l >>> 16 & 255] << 16 | a[f >>> 8 & 255] << 8 | a[255 & u]) ^ e[d++], _ = (a[l >>> 24] << 24 | a[f >>> 16 & 255] << 16 | a[u >>> 8 & 255] << 8 | a[255 & h]) ^ e[d++], y = (a[f >>> 24] << 24 | a[u >>> 16 & 255] << 16 | a[h >>> 8 & 255] << 8 | a[255 & l]) ^ e[d++], g = (a[u >>> 24] << 24 | a[h >>> 16 & 255] << 16 | a[l >>> 8 & 255] << 8 | a[255 & f]) ^ e[d++]; t[r] = p, t[r + 1] = _, t[r + 2] = y, t[r + 3] = g }, keySize: 8 }); r.AES = i._createHelper(_) }(), function () { + function r(t, r) { var e = (this._lBlock >>> t ^ this._rBlock) & r; this._rBlock ^= e, this._lBlock ^= e << t } function e(t, r) { + var e = (this._rBlock >>> t ^ this._lBlock) & r; this._lBlock ^= e, this._rBlock ^= e << t; + } var i = t, n = i.lib, o = n.WordArray, s = n.BlockCipher, a = i.algo, c = [57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4], h = [14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32], l = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28], f = [{ 0: 8421888, 268435456: 32768, 536870912: 8421378, 805306368: 2, 1073741824: 512, 1342177280: 8421890, 1610612736: 8389122, 1879048192: 8388608, 2147483648: 514, 2415919104: 8389120, 2684354560: 33280, 2952790016: 8421376, 3221225472: 32770, 3489660928: 8388610, 3758096384: 0, 4026531840: 33282, 134217728: 0, 402653184: 8421890, 671088640: 33282, 939524096: 32768, 1207959552: 8421888, 1476395008: 512, 1744830464: 8421378, 2013265920: 2, 2281701376: 8389120, 2550136832: 33280, 2818572288: 8421376, 3087007744: 8389122, 3355443200: 8388610, 3623878656: 32770, 3892314112: 514, 4160749568: 8388608, 1: 32768, 268435457: 2, 536870913: 8421888, 805306369: 8388608, 1073741825: 8421378, 1342177281: 33280, 1610612737: 512, 1879048193: 8389122, 2147483649: 8421890, 2415919105: 8421376, 2684354561: 8388610, 2952790017: 33282, 3221225473: 514, 3489660929: 8389120, 3758096385: 32770, 4026531841: 0, 134217729: 8421890, 402653185: 8421376, 671088641: 8388608, 939524097: 512, 1207959553: 32768, 1476395009: 8388610, 1744830465: 2, 2013265921: 33282, 2281701377: 32770, 2550136833: 8389122, 2818572289: 514, 3087007745: 8421888, 3355443201: 8389120, 3623878657: 0, 3892314113: 33280, 4160749569: 8421378 }, { 0: 1074282512, 16777216: 16384, 33554432: 524288, 50331648: 1074266128, 67108864: 1073741840, 83886080: 1074282496, 100663296: 1073758208, 117440512: 16, 134217728: 540672, 150994944: 1073758224, 167772160: 1073741824, 184549376: 540688, 201326592: 524304, 218103808: 0, 234881024: 16400, 251658240: 1074266112, 8388608: 1073758208, 25165824: 540688, 41943040: 16, 58720256: 1073758224, 75497472: 1074282512, 92274688: 1073741824, 109051904: 524288, 125829120: 1074266128, 142606336: 524304, 159383552: 0, 176160768: 16384, 192937984: 1074266112, 209715200: 1073741840, 226492416: 540672, 243269632: 1074282496, 260046848: 16400, 268435456: 0, 285212672: 1074266128, 301989888: 1073758224, 318767104: 1074282496, 335544320: 1074266112, 352321536: 16, 369098752: 540688, 385875968: 16384, 402653184: 16400, 419430400: 524288, 436207616: 524304, 452984832: 1073741840, 469762048: 540672, 486539264: 1073758208, 503316480: 1073741824, 520093696: 1074282512, 276824064: 540688, 293601280: 524288, 310378496: 1074266112, 327155712: 16384, 343932928: 1073758208, 360710144: 1074282512, 377487360: 16, 394264576: 1073741824, 411041792: 1074282496, 427819008: 1073741840, 444596224: 1073758224, 461373440: 524304, 478150656: 0, 494927872: 16400, 511705088: 1074266128, 528482304: 540672 }, { 0: 260, 1048576: 0, 2097152: 67109120, 3145728: 65796, 4194304: 65540, 5242880: 67108868, 6291456: 67174660, 7340032: 67174400, 8388608: 67108864, 9437184: 67174656, 10485760: 65792, 11534336: 67174404, 12582912: 67109124, 13631488: 65536, 14680064: 4, 15728640: 256, 524288: 67174656, 1572864: 67174404, 2621440: 0, 3670016: 67109120, 4718592: 67108868, 5767168: 65536, 6815744: 65540, 7864320: 260, 8912896: 4, 9961472: 256, 11010048: 67174400, 12058624: 65796, 13107200: 65792, 14155776: 67109124, 15204352: 67174660, 16252928: 67108864, 16777216: 67174656, 17825792: 65540, 18874368: 65536, 19922944: 67109120, 20971520: 256, 22020096: 67174660, 23068672: 67108868, 24117248: 0, 25165824: 67109124, 26214400: 67108864, 27262976: 4, 28311552: 65792, 29360128: 67174400, 30408704: 260, 31457280: 65796, 32505856: 67174404, 17301504: 67108864, 18350080: 260, 19398656: 67174656, 20447232: 0, 21495808: 65540, 22544384: 67109120, 23592960: 256, 24641536: 67174404, 25690112: 65536, 26738688: 67174660, 27787264: 65796, 28835840: 67108868, 29884416: 67109124, 30932992: 67174400, 31981568: 4, 33030144: 65792 }, { 0: 2151682048, 65536: 2147487808, 131072: 4198464, 196608: 2151677952, 262144: 0, 327680: 4198400, 393216: 2147483712, 458752: 4194368, 524288: 2147483648, 589824: 4194304, 655360: 64, 720896: 2147487744, 786432: 2151678016, 851968: 4160, 917504: 4096, 983040: 2151682112, 32768: 2147487808, 98304: 64, 163840: 2151678016, 229376: 2147487744, 294912: 4198400, 360448: 2151682112, 425984: 0, 491520: 2151677952, 557056: 4096, 622592: 2151682048, 688128: 4194304, 753664: 4160, 819200: 2147483648, 884736: 4194368, 950272: 4198464, 1015808: 2147483712, 1048576: 4194368, 1114112: 4198400, 1179648: 2147483712, 1245184: 0, 1310720: 4160, 1376256: 2151678016, 1441792: 2151682048, 1507328: 2147487808, 1572864: 2151682112, 1638400: 2147483648, 1703936: 2151677952, 1769472: 4198464, 1835008: 2147487744, 1900544: 4194304, 1966080: 64, 2031616: 4096, 1081344: 2151677952, 1146880: 2151682112, 1212416: 0, 1277952: 4198400, 1343488: 4194368, 1409024: 2147483648, 1474560: 2147487808, 1540096: 64, 1605632: 2147483712, 1671168: 4096, 1736704: 2147487744, 1802240: 2151678016, 1867776: 4160, 1933312: 2151682048, 1998848: 4194304, 2064384: 4198464 }, { 0: 128, 4096: 17039360, 8192: 262144, 12288: 536870912, 16384: 537133184, 20480: 16777344, 24576: 553648256, 28672: 262272, 32768: 16777216, 36864: 537133056, 40960: 536871040, 45056: 553910400, 49152: 553910272, 53248: 0, 57344: 17039488, 61440: 553648128, 2048: 17039488, 6144: 553648256, 10240: 128, 14336: 17039360, 18432: 262144, 22528: 537133184, 26624: 553910272, 30720: 536870912, 34816: 537133056, 38912: 0, 43008: 553910400, 47104: 16777344, 51200: 536871040, 55296: 553648128, 59392: 16777216, 63488: 262272, 65536: 262144, 69632: 128, 73728: 536870912, 77824: 553648256, 81920: 16777344, 86016: 553910272, 90112: 537133184, 94208: 16777216, 98304: 553910400, 102400: 553648128, 106496: 17039360, 110592: 537133056, 114688: 262272, 118784: 536871040, 122880: 0, 126976: 17039488, 67584: 553648256, 71680: 16777216, 75776: 17039360, 79872: 537133184, 83968: 536870912, 88064: 17039488, 92160: 128, 96256: 553910272, 100352: 262272, 104448: 553910400, 108544: 0, 112640: 553648128, 116736: 16777344, 120832: 262144, 124928: 537133056, 129024: 536871040 }, { 0: 268435464, 256: 8192, 512: 270532608, 768: 270540808, 1024: 268443648, 1280: 2097152, 1536: 2097160, 1792: 268435456, 2048: 0, 2304: 268443656, 2560: 2105344, 2816: 8, 3072: 270532616, 3328: 2105352, 3584: 8200, 3840: 270540800, 128: 270532608, 384: 270540808, 640: 8, 896: 2097152, 1152: 2105352, 1408: 268435464, 1664: 268443648, 1920: 8200, 2176: 2097160, 2432: 8192, 2688: 268443656, 2944: 270532616, 3200: 0, 3456: 270540800, 3712: 2105344, 3968: 268435456, 4096: 268443648, 4352: 270532616, 4608: 270540808, 4864: 8200, 5120: 2097152, 5376: 268435456, 5632: 268435464, 5888: 2105344, 6144: 2105352, 6400: 0, 6656: 8, 6912: 270532608, 7168: 8192, 7424: 268443656, 7680: 270540800, 7936: 2097160, 4224: 8, 4480: 2105344, 4736: 2097152, 4992: 268435464, 5248: 268443648, 5504: 8200, 5760: 270540808, 6016: 270532608, 6272: 270540800, 6528: 270532616, 6784: 8192, 7040: 2105352, 7296: 2097160, 7552: 0, 7808: 268435456, 8064: 268443656 }, { 0: 1048576, 16: 33555457, 32: 1024, 48: 1049601, 64: 34604033, 80: 0, 96: 1, 112: 34603009, 128: 33555456, 144: 1048577, 160: 33554433, 176: 34604032, 192: 34603008, 208: 1025, 224: 1049600, 240: 33554432, 8: 34603009, 24: 0, 40: 33555457, 56: 34604032, 72: 1048576, 88: 33554433, 104: 33554432, 120: 1025, 136: 1049601, 152: 33555456, 168: 34603008, 184: 1048577, 200: 1024, 216: 34604033, 232: 1, 248: 1049600, 256: 33554432, 272: 1048576, 288: 33555457, 304: 34603009, 320: 1048577, 336: 33555456, 352: 34604032, 368: 1049601, 384: 1025, 400: 34604033, 416: 1049600, 432: 1, 448: 0, 464: 34603008, 480: 33554433, 496: 1024, 264: 1049600, 280: 33555457, 296: 34603009, 312: 1, 328: 33554432, 344: 1048576, 360: 1025, 376: 34604032, 392: 33554433, 408: 34603008, 424: 0, 440: 34604033, 456: 1049601, 472: 1024, 488: 33555456, 504: 1048577 }, { 0: 134219808, 1: 131072, 2: 134217728, 3: 32, 4: 131104, 5: 134350880, 6: 134350848, 7: 2048, 8: 134348800, 9: 134219776, 10: 133120, 11: 134348832, 12: 2080, 13: 0, 14: 134217760, 15: 133152, 2147483648: 2048, 2147483649: 134350880, 2147483650: 134219808, 2147483651: 134217728, 2147483652: 134348800, 2147483653: 133120, 2147483654: 133152, 2147483655: 32, 2147483656: 134217760, 2147483657: 2080, 2147483658: 131104, 2147483659: 134350848, 2147483660: 0, 2147483661: 134348832, 2147483662: 134219776, 2147483663: 131072, 16: 133152, 17: 134350848, 18: 32, 19: 2048, 20: 134219776, 21: 134217760, 22: 134348832, 23: 131072, 24: 0, 25: 131104, 26: 134348800, 27: 134219808, 28: 134350880, 29: 133120, 30: 2080, 31: 134217728, 2147483664: 131072, 2147483665: 2048, 2147483666: 134348832, 2147483667: 133152, 2147483668: 32, 2147483669: 134348800, 2147483670: 134217728, 2147483671: 134219808, 2147483672: 134350880, 2147483673: 134217760, 2147483674: 134219776, 2147483675: 0, 2147483676: 133120, 2147483677: 2080, 2147483678: 131104, 2147483679: 134350848 }], u = [4160749569, 528482304, 33030144, 2064384, 129024, 8064, 504, 2147483679], d = a.DES = s.extend({ _doReset: function () { for (var t = this._key, r = t.words, e = [], i = 0; i < 56; i++) { var n = c[i] - 1; e[i] = r[n >>> 5] >>> 31 - n % 32 & 1 } for (var o = this._subKeys = [], s = 0; s < 16; s++) { for (var a = o[s] = [], f = l[s], i = 0; i < 24; i++)a[i / 6 | 0] |= e[(h[i] - 1 + f) % 28] << 31 - i % 6, a[4 + (i / 6 | 0)] |= e[28 + (h[i + 24] - 1 + f) % 28] << 31 - i % 6; a[0] = a[0] << 1 | a[0] >>> 31; for (var i = 1; i < 7; i++)a[i] = a[i] >>> 4 * (i - 1) + 3; a[7] = a[7] << 5 | a[7] >>> 27 } for (var u = this._invSubKeys = [], i = 0; i < 16; i++)u[i] = o[15 - i] }, encryptBlock: function (t, r) { this._doCryptBlock(t, r, this._subKeys) }, decryptBlock: function (t, r) { this._doCryptBlock(t, r, this._invSubKeys) }, _doCryptBlock: function (t, i, n) { this._lBlock = t[i], this._rBlock = t[i + 1], r.call(this, 4, 252645135), r.call(this, 16, 65535), e.call(this, 2, 858993459), e.call(this, 8, 16711935), r.call(this, 1, 1431655765); for (var o = 0; o < 16; o++) { for (var s = n[o], a = this._lBlock, c = this._rBlock, h = 0, l = 0; l < 8; l++)h |= f[l][((c ^ s[l]) & u[l]) >>> 0]; this._lBlock = c, this._rBlock = a ^ h } var d = this._lBlock; this._lBlock = this._rBlock, this._rBlock = d, r.call(this, 1, 1431655765), e.call(this, 8, 16711935), e.call(this, 2, 858993459), r.call(this, 16, 65535), r.call(this, 4, 252645135), t[i] = this._lBlock, t[i + 1] = this._rBlock }, keySize: 2, ivSize: 2, blockSize: 2 }); i.DES = s._createHelper(d); var v = a.TripleDES = s.extend({ _doReset: function () { var t = this._key, r = t.words; this._des1 = d.createEncryptor(o.create(r.slice(0, 2))), this._des2 = d.createEncryptor(o.create(r.slice(2, 4))), this._des3 = d.createEncryptor(o.create(r.slice(4, 6))) }, encryptBlock: function (t, r) { this._des1.encryptBlock(t, r), this._des2.decryptBlock(t, r), this._des3.encryptBlock(t, r) }, decryptBlock: function (t, r) { this._des3.decryptBlock(t, r), this._des2.encryptBlock(t, r), this._des1.decryptBlock(t, r) }, keySize: 6, ivSize: 2, blockSize: 2 }); i.TripleDES = s._createHelper(v) + }(), function () { function r() { for (var t = this._S, r = this._i, e = this._j, i = 0, n = 0; n < 4; n++) { r = (r + 1) % 256, e = (e + t[r]) % 256; var o = t[r]; t[r] = t[e], t[e] = o, i |= t[(t[r] + t[e]) % 256] << 24 - 8 * n } return this._i = r, this._j = e, i } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = o.RC4 = n.extend({ _doReset: function () { for (var t = this._key, r = t.words, e = t.sigBytes, i = this._S = [], n = 0; n < 256; n++)i[n] = n; for (var n = 0, o = 0; n < 256; n++) { var s = n % e, a = r[s >>> 2] >>> 24 - s % 4 * 8 & 255; o = (o + i[n] + a) % 256; var c = i[n]; i[n] = i[o], i[o] = c } this._i = this._j = 0 }, _doProcessBlock: function (t, e) { t[e] ^= r.call(this) }, keySize: 8, ivSize: 0 }); e.RC4 = n._createHelper(s); var a = o.RC4Drop = s.extend({ cfg: s.cfg.extend({ drop: 192 }), _doReset: function () { s._doReset.call(this); for (var t = this.cfg.drop; t > 0; t--)r.call(this) } }); e.RC4Drop = n._createHelper(a) }(), t.mode.CTRGladman = function () { function r(t) { if (255 === (t >> 24 & 255)) { var r = t >> 16 & 255, e = t >> 8 & 255, i = 255 & t; 255 === r ? (r = 0, 255 === e ? (e = 0, 255 === i ? i = 0 : ++i) : ++e) : ++r, t = 0, t += r << 16, t += e << 8, t += i } else t += 1 << 24; return t } function e(t) { return 0 === (t[0] = r(t[0])) && (t[1] = r(t[1])), t } var i = t.lib.BlockCipherMode.extend(), n = i.Encryptor = i.extend({ processBlock: function (t, r) { var i = this._cipher, n = i.blockSize, o = this._iv, s = this._counter; o && (s = this._counter = o.slice(0), this._iv = void 0), e(s); var a = s.slice(0); i.encryptBlock(a, 0); for (var c = 0; c < n; c++)t[r + c] ^= a[c] } }); return i.Decryptor = n, i }(), function () { function r() { for (var t = this._X, r = this._C, e = 0; e < 8; e++)a[e] = r[e]; r[0] = r[0] + 1295307597 + this._b | 0, r[1] = r[1] + 3545052371 + (r[0] >>> 0 < a[0] >>> 0 ? 1 : 0) | 0, r[2] = r[2] + 886263092 + (r[1] >>> 0 < a[1] >>> 0 ? 1 : 0) | 0, r[3] = r[3] + 1295307597 + (r[2] >>> 0 < a[2] >>> 0 ? 1 : 0) | 0, r[4] = r[4] + 3545052371 + (r[3] >>> 0 < a[3] >>> 0 ? 1 : 0) | 0, r[5] = r[5] + 886263092 + (r[4] >>> 0 < a[4] >>> 0 ? 1 : 0) | 0, r[6] = r[6] + 1295307597 + (r[5] >>> 0 < a[5] >>> 0 ? 1 : 0) | 0, r[7] = r[7] + 3545052371 + (r[6] >>> 0 < a[6] >>> 0 ? 1 : 0) | 0, this._b = r[7] >>> 0 < a[7] >>> 0 ? 1 : 0; for (var e = 0; e < 8; e++) { var i = t[e] + r[e], n = 65535 & i, o = i >>> 16, s = ((n * n >>> 17) + n * o >>> 15) + o * o, h = ((4294901760 & i) * i | 0) + ((65535 & i) * i | 0); c[e] = s ^ h } t[0] = c[0] + (c[7] << 16 | c[7] >>> 16) + (c[6] << 16 | c[6] >>> 16) | 0, t[1] = c[1] + (c[0] << 8 | c[0] >>> 24) + c[7] | 0, t[2] = c[2] + (c[1] << 16 | c[1] >>> 16) + (c[0] << 16 | c[0] >>> 16) | 0, t[3] = c[3] + (c[2] << 8 | c[2] >>> 24) + c[1] | 0, t[4] = c[4] + (c[3] << 16 | c[3] >>> 16) + (c[2] << 16 | c[2] >>> 16) | 0, t[5] = c[5] + (c[4] << 8 | c[4] >>> 24) + c[3] | 0, t[6] = c[6] + (c[5] << 16 | c[5] >>> 16) + (c[4] << 16 | c[4] >>> 16) | 0, t[7] = c[7] + (c[6] << 8 | c[6] >>> 24) + c[5] | 0 } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = [], a = [], c = [], h = o.Rabbit = n.extend({ _doReset: function () { for (var t = this._key.words, e = this.cfg.iv, i = 0; i < 4; i++)t[i] = 16711935 & (t[i] << 8 | t[i] >>> 24) | 4278255360 & (t[i] << 24 | t[i] >>> 8); var n = this._X = [t[0], t[3] << 16 | t[2] >>> 16, t[1], t[0] << 16 | t[3] >>> 16, t[2], t[1] << 16 | t[0] >>> 16, t[3], t[2] << 16 | t[1] >>> 16], o = this._C = [t[2] << 16 | t[2] >>> 16, 4294901760 & t[0] | 65535 & t[1], t[3] << 16 | t[3] >>> 16, 4294901760 & t[1] | 65535 & t[2], t[0] << 16 | t[0] >>> 16, 4294901760 & t[2] | 65535 & t[3], t[1] << 16 | t[1] >>> 16, 4294901760 & t[3] | 65535 & t[0]]; this._b = 0; for (var i = 0; i < 4; i++)r.call(this); for (var i = 0; i < 8; i++)o[i] ^= n[i + 4 & 7]; if (e) { var s = e.words, a = s[0], c = s[1], h = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8), l = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8), f = h >>> 16 | 4294901760 & l, u = l << 16 | 65535 & h; o[0] ^= h, o[1] ^= f, o[2] ^= l, o[3] ^= u, o[4] ^= h, o[5] ^= f, o[6] ^= l, o[7] ^= u; for (var i = 0; i < 4; i++)r.call(this) } }, _doProcessBlock: function (t, e) { var i = this._X; r.call(this), s[0] = i[0] ^ i[5] >>> 16 ^ i[3] << 16, s[1] = i[2] ^ i[7] >>> 16 ^ i[5] << 16, s[2] = i[4] ^ i[1] >>> 16 ^ i[7] << 16, s[3] = i[6] ^ i[3] >>> 16 ^ i[1] << 16; for (var n = 0; n < 4; n++)s[n] = 16711935 & (s[n] << 8 | s[n] >>> 24) | 4278255360 & (s[n] << 24 | s[n] >>> 8), t[e + n] ^= s[n] }, blockSize: 4, ivSize: 2 }); e.Rabbit = n._createHelper(h) }(), t.mode.CTR = function () { var r = t.lib.BlockCipherMode.extend(), e = r.Encryptor = r.extend({ processBlock: function (t, r) { var e = this._cipher, i = e.blockSize, n = this._iv, o = this._counter; n && (o = this._counter = n.slice(0), this._iv = void 0); var s = o.slice(0); e.encryptBlock(s, 0), o[i - 1] = o[i - 1] + 1 | 0; for (var a = 0; a < i; a++)t[r + a] ^= s[a] } }); return r.Decryptor = e, r }(), function () { function r() { for (var t = this._X, r = this._C, e = 0; e < 8; e++)a[e] = r[e]; r[0] = r[0] + 1295307597 + this._b | 0, r[1] = r[1] + 3545052371 + (r[0] >>> 0 < a[0] >>> 0 ? 1 : 0) | 0, r[2] = r[2] + 886263092 + (r[1] >>> 0 < a[1] >>> 0 ? 1 : 0) | 0, r[3] = r[3] + 1295307597 + (r[2] >>> 0 < a[2] >>> 0 ? 1 : 0) | 0, r[4] = r[4] + 3545052371 + (r[3] >>> 0 < a[3] >>> 0 ? 1 : 0) | 0, r[5] = r[5] + 886263092 + (r[4] >>> 0 < a[4] >>> 0 ? 1 : 0) | 0, r[6] = r[6] + 1295307597 + (r[5] >>> 0 < a[5] >>> 0 ? 1 : 0) | 0, r[7] = r[7] + 3545052371 + (r[6] >>> 0 < a[6] >>> 0 ? 1 : 0) | 0, this._b = r[7] >>> 0 < a[7] >>> 0 ? 1 : 0; for (var e = 0; e < 8; e++) { var i = t[e] + r[e], n = 65535 & i, o = i >>> 16, s = ((n * n >>> 17) + n * o >>> 15) + o * o, h = ((4294901760 & i) * i | 0) + ((65535 & i) * i | 0); c[e] = s ^ h } t[0] = c[0] + (c[7] << 16 | c[7] >>> 16) + (c[6] << 16 | c[6] >>> 16) | 0, t[1] = c[1] + (c[0] << 8 | c[0] >>> 24) + c[7] | 0, t[2] = c[2] + (c[1] << 16 | c[1] >>> 16) + (c[0] << 16 | c[0] >>> 16) | 0, t[3] = c[3] + (c[2] << 8 | c[2] >>> 24) + c[1] | 0, t[4] = c[4] + (c[3] << 16 | c[3] >>> 16) + (c[2] << 16 | c[2] >>> 16) | 0, t[5] = c[5] + (c[4] << 8 | c[4] >>> 24) + c[3] | 0, t[6] = c[6] + (c[5] << 16 | c[5] >>> 16) + (c[4] << 16 | c[4] >>> 16) | 0, t[7] = c[7] + (c[6] << 8 | c[6] >>> 24) + c[5] | 0 } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = [], a = [], c = [], h = o.RabbitLegacy = n.extend({ _doReset: function () { var t = this._key.words, e = this.cfg.iv, i = this._X = [t[0], t[3] << 16 | t[2] >>> 16, t[1], t[0] << 16 | t[3] >>> 16, t[2], t[1] << 16 | t[0] >>> 16, t[3], t[2] << 16 | t[1] >>> 16], n = this._C = [t[2] << 16 | t[2] >>> 16, 4294901760 & t[0] | 65535 & t[1], t[3] << 16 | t[3] >>> 16, 4294901760 & t[1] | 65535 & t[2], t[0] << 16 | t[0] >>> 16, 4294901760 & t[2] | 65535 & t[3], t[1] << 16 | t[1] >>> 16, 4294901760 & t[3] | 65535 & t[0]]; this._b = 0; for (var o = 0; o < 4; o++)r.call(this); for (var o = 0; o < 8; o++)n[o] ^= i[o + 4 & 7]; if (e) { var s = e.words, a = s[0], c = s[1], h = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8), l = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8), f = h >>> 16 | 4294901760 & l, u = l << 16 | 65535 & h; n[0] ^= h, n[1] ^= f, n[2] ^= l, n[3] ^= u, n[4] ^= h, n[5] ^= f, n[6] ^= l, n[7] ^= u; for (var o = 0; o < 4; o++)r.call(this) } }, _doProcessBlock: function (t, e) { var i = this._X; r.call(this), s[0] = i[0] ^ i[5] >>> 16 ^ i[3] << 16, s[1] = i[2] ^ i[7] >>> 16 ^ i[5] << 16, s[2] = i[4] ^ i[1] >>> 16 ^ i[7] << 16, s[3] = i[6] ^ i[3] >>> 16 ^ i[1] << 16; for (var n = 0; n < 4; n++)s[n] = 16711935 & (s[n] << 8 | s[n] >>> 24) | 4278255360 & (s[n] << 24 | s[n] >>> 8), t[e + n] ^= s[n] }, blockSize: 4, ivSize: 2 }); e.RabbitLegacy = n._createHelper(h) }(), t.pad.ZeroPadding = { pad: function (t, r) { var e = 4 * r; t.clamp(), t.sigBytes += e - (t.sigBytes % e || e) }, unpad: function (t) { for (var r = t.words, e = t.sigBytes - 1; !(r[e >>> 2] >>> 24 - e % 4 * 8 & 255);)e--; t.sigBytes = e + 1 } }, t +}); + +const $ = new Env('中国移动') +$.KEY_autologin = 'chavy_autologin_cmcc' +$.KEY_getfee = 'chavy_getfee_cmcc' + +!(async () => { + $.CryptoJS = $.isNode() ? require('crypto-js') : CryptoJS + await loginapp() + await queryfee() + await querymeal() + await showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +function loginapp() { + return new Promise((resolve) => { + const url = JSON.parse($.getdata($.KEY_autologin)) + $.post(url, (err, resp, data) => { + try { + $.setck = $.isNode() ? resp.headers['set-cookie'] : resp.headers['Set-Cookie'] + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function queryfee() { + return new Promise((resolve) => { + const url = JSON.parse($.getdata($.KEY_getfee)) + const body = JSON.parse(decrypt(url.body, 'bAIgvwAuA4tbDr9d')) + const cellNum = body.reqBody.cellNum + const bodystr = `{"t":"${$.CryptoJS.MD5($.setck).toString()}","cv":"9.9.9","reqBody":{"cellNum":"${cellNum}"}}` + url.body = encrypt(bodystr, 'bAIgvwAuA4tbDr9d') + url.headers['Cookie'] = $.setck + url.headers['xs'] = $.CryptoJS.MD5(url.url + '_' + bodystr + '_Leadeon/SecurityOrganization').toString() + $.post(url, (err, resp, data) => { + try { + $.fee = JSON.parse(decrypt(data, 'GS7VelkJl5IT1uwQ')) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} +function querymeal() { + return new Promise((resolve) => { + const url = JSON.parse($.getdata($.KEY_getfee)) + url.url = 'https://clientaccess.10086.cn/biz-orange/BN/newComboMealResouceUnite/getNewComboMealResource' + const body = JSON.parse(decrypt(url.body, 'bAIgvwAuA4tbDr9d')) + const cellNum = body.reqBody.cellNum + const bodystr = `{"t":"${$.CryptoJS.MD5($.setck).toString()}","cv":"9.9.9","reqBody":{"cellNum":"${cellNum}","tag":"3"}}` + url.body = encrypt(bodystr, 'bAIgvwAuA4tbDr9d') + url.headers['Cookie'] = $.setck + url.headers['xs'] = $.CryptoJS.MD5(url.url + '_' + bodystr + '_Leadeon/SecurityOrganization').toString() + $.post(url, (err, resp, data) => { + try { + $.meal = JSON.parse(decrypt(data, 'GS7VelkJl5IT1uwQ')) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function encrypt(str, key) { + return $.CryptoJS.AES.encrypt($.CryptoJS.enc.Utf8.parse(str), $.CryptoJS.enc.Utf8.parse(key), { + iv: $.CryptoJS.enc.Utf8.parse('9791027341711819'), + mode: $.CryptoJS.mode.CBC, + padding: $.CryptoJS.pad.Pkcs7 + }).toString() +} + +function decrypt(str, key) { + return $.CryptoJS.AES.decrypt(str, $.CryptoJS.enc.Utf8.parse(key), { + iv: $.CryptoJS.enc.Utf8.parse('9791027341711819'), + mode: $.CryptoJS.mode.CBC, + padding: $.CryptoJS.pad.Pkcs7 + }).toString($.CryptoJS.enc.Utf8) +} + +function showmsg() { + return new Promise((resolve) => { + $.subt = `话费: ${$.fee.rspBody.curFeeTotal}, 剩余: ${$.fee.rspBody.curFee}, 已用: ${$.fee.rspBody.realFee}` + const res = $.meal.rspBody.qryInfoRsp[0].resourcesTotal + + const flowRes = res.find((r) => r.resourcesCode === '04') + const voiceRes = res.find((r) => r.resourcesCode === '01') + console.log(JSON.stringify(flowRes)) + $.desc = [] + if (flowRes) { + const remUnit = flowRes.remUnit === '05' ? 'GB' : 'MB' + const usedUnit = flowRes.usedUnit === '05' ? 'GB' : 'MB' + const unit = flowRes.allUnit === '05' ? 'GB' : 'MB' + $.desc.push(`流量: ${flowRes.allUsedRes}${usedUnit}/${flowRes.allTotalRes}${unit}, 剩余: ${flowRes.allRemainRes}${remUnit}`) + } + if (voiceRes) { + const remUnit = flowRes.remUnit === '01' ? '分钟' : '' + const usedUnit = flowRes.usedUnit === '01' ? '分钟' : '' + const allUnit = '分钟' + $.desc.push(`语音: ${voiceRes.allUsedRes}/${voiceRes.allTotalRes}${allUnit}, 剩余: ${voiceRes.allRemainRes}${allUnit}`) + } + $.msg($.name, $.subt, $.desc.join('\n')) + resolve() + }) +} + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/10086/10086.js b/achived/10086/10086.js similarity index 100% rename from 10086/10086.js rename to achived/10086/10086.js diff --git a/10086/README.md b/achived/10086/README.md similarity index 100% rename from 10086/README.md rename to achived/10086/README.md diff --git a/achived/bcz/README.md b/achived/bcz/README.md new file mode 100644 index 000000000..86dc3bf15 --- /dev/null +++ b/achived/bcz/README.md @@ -0,0 +1,105 @@ +# 百词斩 + +> 参考 chavy 签到脚本制作的百词斩领取铜板的脚本 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> 不需要手动编辑脚本 (获取 Cookie 和手机号码都由脚本自动完成) + +> 感谢 [@GideonSenku](https://github.com/GideonSenku) PR + +## 配置 (Surge) + +```properties +[MITM] +group.baicizhan.com + +[Script] +http-request ^https://group\.baicizhan\.com/group/rewards? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bcz/bcz.cookie.js + +cron "0 50 23 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bcz/bcz.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +group.baicizhan.com + +[rewrite_local] +# 190及以后版本 +^https://group\.baicizhan\.com/group/rewards? url script-request-header bcz.cookie.js + +[task_local] +50 23 * * * bcz.js +``` + +## 说明 + +> 先在登录成功后, 再打开获取 Cookie 的脚本 + +1. 先配置`[MITM]` + - Surge&QuanX: group.baicizhan.com +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`bcz.cookie.js`和`bcz.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP 手动签到一次: 访问下右下角 `我` > `我的铜板` > `加入百词斩小班` > `去查看` > `我的小班进去 领铜板` +4. 系统提示: `获取Cookie: 成功` +5. 最后就可以把第 1 条脚本注释掉了 + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`23:50`执行一次. +7. 也可将脚本的cron语法自行更改,如我设置成 `0 */4 * * *` 则每4小时可提醒我背单词 + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@GideonSenku](https://github.com/GideonSenku) diff --git a/achived/bcz/bcz.cookie.js b/achived/bcz/bcz.cookie.js new file mode 100644 index 000000000..315057368 --- /dev/null +++ b/achived/bcz/bcz.cookie.js @@ -0,0 +1,62 @@ +const cookieName = '百词斩' +const cookieKey = 'senku_cookie_bcz' +const shareKey = 'senku_key_bcz' +const senku = init() + +if (this.$request && this.$request.headers) { + const cookieVal = $request.headers['Cookie'] + const url = $request.url + const index1 = url.indexOf('=') + const index2 = url.indexOf('&') + const shareVal = url.substring(index1 + 1, index2) + if (cookieVal && shareVal) { + if (senku.setdata(cookieVal, cookieKey) && senku.setdata(shareVal, shareKey)) { + senku.msg(`${cookieName}`, '获取Cookie: 成功', '') + senku.log(`[${cookieName}] 获取Cookie: 成功, cookie: ${cookieVal}`) + } + } +} +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} +senku.done() diff --git a/achived/bcz/bcz.js b/achived/bcz/bcz.js new file mode 100644 index 000000000..5942565ff --- /dev/null +++ b/achived/bcz/bcz.js @@ -0,0 +1,82 @@ +const cookieName = '百词斩' +const cookieKey = 'senku_cookie_bcz' +const shareKey = 'senku_key_bcz' +const senku = init() +const cookieVal = senku.getdata(cookieKey) +const shareVal = senku.getdata(shareKey) + +let signinfo = {} +senku.log() +check() +function check(cb) { + const url = { url: `https://group.baicizhan.com/group/apply_reward`, headers: { Cookie: cookieVal } } + url.headers['Content-Type'] = `text/plain;charset=utf-8` + url.headers['User-Agent'] = `Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/7.0.10(0x17000a21) NetType/4G Language/zh_CN` + const key = { share_key: shareVal } + url.body = JSON.stringify(key) + senku.log(url.body) + senku.post(url, (error, response, data) => { + signinfo = JSON.parse(data) + senku.log(JSON.stringify(signinfo)) + const title = `${cookieName}` + let subTitle = `` + let detail = '' + if (signinfo.code == 1) { + if (signinfo.data.is_new) { + subTitle += `成功` + detail = `获取铜板数${signinfo.data.reward[2]}` + } else { + subTitle += `今天的铜板已经领取,但是单词还是可以继续背的` + } + } else { + detail = `状态: 还玩手机?快去背单词` + subTitle += '失败' + } + senku.msg(title, subTitle, detail) + senku.done() + }) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/achived/bubei/README.md b/achived/bubei/README.md new file mode 100644 index 000000000..3e58d3ee2 --- /dev/null +++ b/achived/bubei/README.md @@ -0,0 +1,104 @@ +# 不背单词 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> 感谢[@danchaw](https://github.com/danchaw) PR +## 配置 (Surge) + +```properties +[MITM] +sapi.beingfine.cn + +[Script] +http-request ^https:\/\/sapi\.beingfine\.cn\/v3\/bb\/reward\/by-sign-in script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bubei/bubei.js +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bubei/bubei.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +sapi.beingfine.cn + +[rewrite_local] + +# [商店版] +^https:\/\/sapi\.beingfine\.cn\/v3\/bb\/reward\/by-sign-in url script-request-header bubei.js + +# [TestFlight] +^https:\/\/sapi\.beingfine\.cn\/v3\/bb\/reward\/by-sign-in url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/bubei/bubei.js + +[task_local] + +# [商店版] +1 0 * * * bubei.js + +# [TestFlight] +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/bubei/bubei.js +``` + +## 说明 + +1. 先把`sapi.beingfine.cn`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`bubei.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP[不背单词](https://apps.apple.com/cn/app/%E4%B8%8D%E8%83%8C%E5%8D%95%E8%AF%8D-%E7%9C%9F%E5%AE%9E%E8%AF%AD%E5%A2%83%E5%AD%A6%E8%8B%B1%E8%AF%AD%E5%8D%95%E8%AF%8D/id698570469) 然后手动签到 1 次, 系统提示: `首次写入不背单词Url成功🎉`和`首次写入不背单词Cookie成功🎉` +4. 最后就可以把第 1 条脚本注释掉了 +5. 运行一次脚本, 如果提示说明:aceess_denied#30103, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@danchaw](https://github.com/danchaw) diff --git a/achived/bubei/bubei.js b/achived/bubei/bubei.js new file mode 100644 index 000000000..9dfe49f8d --- /dev/null +++ b/achived/bubei/bubei.js @@ -0,0 +1,142 @@ +var appName = '不背单词' +var bubei = init() +var URL = bubei.getdata("UrlBB") +var KEY = bubei.getdata("CookieBB") + +let isGetCookie = typeof $request !== 'undefined' + +if (isGetCookie) { + getcookie() +} else { + sign() +} + +function getcookie() { + var url = $request.url; + if (url) { + var UrlKeyBB = "UrlBB"; + var UrlValueBB = url; + if (bubei.getdata(UrlKeyBB) != (undefined || null)) { + if (bubei.getdata(UrlKeyBB) != UrlValueBB) { + var url = bubei.setdata(UrlValueBB, UrlKeyBB); + if (!url) { + bubei.msg("更新" + appName + "Url失败‼️", "", ""); + } else { + bubei.msg("更新" + appName + "Url成功🎉", "", ""); + } + } else { + bubei.msg(appName + "Url未变化❗️", "", ""); + } + } else { + var url = bubei.setdata(UrlValueBB, UrlKeyBB); + if (!url) { + bubei.msg("首次写入" + appName + "Url失败‼️", "", ""); + } else { + bubei.msg("首次写入" + appName + "Url成功🎉", "", ""); + } + } + } else { + bubei.msg("写入" + appName + "Url失败‼️", "", "配置错误, 无法读取URL, "); + } + if ($request.headers) { + var CookieKeyBB = "CookieBB"; + var CookieValueBB = JSON.stringify($request.headers); + if (bubei.getdata(CookieKeyBB) != (undefined || null)) { + if (bubei.getdata(CookieKeyBB) != CookieValueBB) { + var cookie = bubei.setdata(CookieValueBB, CookieKeyBB); + if (!cookie) { + bubei.msg("更新" + appName + "Cookie失败‼️", "", ""); + } else { + bubei.msg("更新" + appName + "Cookie成功🎉", "", ""); + } + } else { + bubei.msg(appName + "Cookie未变化❗️", "", ""); + } + } else { + var cookie = bubei.setdata(CookieValueBB, CookieKeyBB); + if (!cookie) { + bubei.msg("首次写入" + appName + "Cookie失败‼️", "", ""); + } else { + bubei.msg("首次写入" + appName + "Cookie成功🎉", "", ""); + } + } + } else { + bubei.msg("写入" + appName + "Cookie失败‼️", "", "配置错误, 无法读取请求头, "); + } + bubei.done() +} + +function sign() { + var t1 = new Date().getTime() + var t2 = t1 + 1 + URL = URL.replace(/by-sign-in\/\d*/g,"by-sign-in/" + t1).replace(/timestamp=\d*/g,"timestamp=" + t2) + const url = { url: URL, headers: JSON.parse(KEY) } + bubei.get(url, (error, response, data) => { + bubei.log(`${appName}, data: ${data}`) + const title = `${appName}` + let subTitle = '' + let detail = '' + const result = JSON.parse(data) + if (result.result_code == 200) { + subTitle = `签到结果: 成功` + } else { + subTitle = `签到结果: 未知` + detail = `说明: ${result.error_body.user_msg}` + } + bubei.msg(title, subTitle, detail) + bubei.done() + }) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + put = (url, cb) => { + if (isSurge()) { + $httpClient.put(url, cb) + } + if (isQuanX()) { + url.method = 'PUT' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, put, done } +} \ No newline at end of file diff --git a/achived/dbsj/README.md b/achived/dbsj/README.md new file mode 100644 index 000000000..50a3ab0fc --- /dev/null +++ b/achived/dbsj/README.md @@ -0,0 +1,105 @@ +# 豆瓣时间 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> QuanX 需要: v1.0.6-build195 及以后版本 (TestFlight) + +> 感谢 [@GideonSenku](https://github.com/GideonSenku) Commit + +> 实现过程[nocoding.xyz](http://nocoding.xyz/2020/03/28/build-check/) +## 配置 (Surge) + +```properties +[MITM] +frodo.douban.com + +[Script] +http-request ^https:\/\/frodo\.douban\.com\/api\/v2\/niffler\/check_in\/status script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/dbsj/dbsj.cookie.js + +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/dbsj/dbsj.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +frodo.douban.com + +[rewrite_local] + +# [商店版] QuanX v1.0.6-build194 及更早版本 +^https:\/\/frodo\.douban\.com\/api\/v2\/niffler\/check_in\/status url script-request-header dbsj.cookie.js + +# [TestFlight] QuanX v1.0.6-build195 及以后版本 +^https:\/\/frodo\.douban\.com\/api\/v2\/niffler\/check_in\/status url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/dbsj/dbsj.cookie.js + +[task_local] +1 0 * * * dbsj.js +``` + +## 说明 + +1. 先把`frodo.douban.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`dbsj.cookie.js`和`dbsj.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP 手动签到一次: `市集` > `豆瓣时间` > `签到` +4. 系统提示: `获取Cookie: 成功` +5. 把获取 Cookie 的脚本注释掉 +6. 运行一次脚本, 如果提示重复签到, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@GideonSenku](https://github.com/GideonSenku) diff --git a/achived/dbsj/dbsj.cookie.js b/achived/dbsj/dbsj.cookie.js new file mode 100644 index 000000000..a3d654c1c --- /dev/null +++ b/achived/dbsj/dbsj.cookie.js @@ -0,0 +1,60 @@ +const cookieName = '豆瓣时间' +const signurlKey = 'senku_signurl_dbsj' +const signheaderKey = 'senku_signheader_dbsj' +const signbodyKey = 'senku_signbody_dbsj' +const senku = init() + +const requrl = $request.url +if ($request && $request.method != 'OPTIONS') { + const signurlVal = requrl + const signheaderVal = JSON.stringify($request.headers) + + if (signurlVal) senku.setdata(signurlVal, signurlKey) + if (signheaderVal) senku.setdata(signheaderVal, signheaderKey) + senku.msg(cookieName, `获取Cookie: 成功`, ``) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} +senku.done() diff --git a/achived/dbsj/dbsj.js b/achived/dbsj/dbsj.js new file mode 100644 index 000000000..01713f3b7 --- /dev/null +++ b/achived/dbsj/dbsj.js @@ -0,0 +1,76 @@ +const cookieName = '豆瓣时间' +const signurlKey = 'senku_signurl_dbsj' +const signheaderKey = 'senku_signheader_dbsj' +const signbodyKey = 'senku_signbody_dbsj' +const senku = init() +const signurlVal = senku.getdata(signurlKey) +const signheaderVal = senku.getdata(signheaderKey) + +sign() + +function sign() { + + const url = { url: signurlVal, headers: JSON.parse(signheaderVal)} + senku.get(url, (error, response, data) => { + const result = JSON.parse(data) + let subTitle = `` + let detail = `` + const has_checked = result.today_status.has_checked + const continuous_check_in_count = result.continuous_check_in_count + const status = result.auto_check.status + if (status == "success") { + subTitle = `签到结果: 成功` + detail = `连续签到天数${continuous_check_in_count}天` + } else if (has_checked == 1) { + const date = result.today_check.created_at + subTitle = `签到结果: 重复 签到时间${date}` + } + senku.msg(cookieName, subTitle, detail) + senku.done() + }) +} + + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/achived/fenqile/README.md b/achived/fenqile/README.md new file mode 100644 index 000000000..e3eea0498 --- /dev/null +++ b/achived/fenqile/README.md @@ -0,0 +1,109 @@ +# 分期乐 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> QuanX 需要: v1.0.6-build195 及以后版本 (TestFlight) + +> 感谢 [@GideonSenku](https://github.com/GideonSenku) Commit + +> 2020.03.18 添加超级乐星日/天天领乐星 +## 配置 (Surge) + +```properties +[MITM] +pm.m.fenqile.com + +[Script] +http-request ^https://pm\.m\.fenqile\.com/route0014/star/sign/sign.json script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/fenqile/fenqile.cookie.js, requires-body=true + +http-request ^https:\/\/pm\.m\.fenqile\.com/route0014\/app\/tab\/privilege\/convertTaskReward.json script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/fenqile/fenqile.cookie.js, requires-body=true + + +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/fenqile/fenqile.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +pm.m.fenqile.com + +[rewrite_local] + +# [商店版] QuanX v1.0.6-build194 及更早版本 +# 支持request-body 脚本可食用,换成本地 + +# [TestFlight] QuanX v1.0.6-build195 及以后版本 +^https://pm\.m\.fenqile\.com/route0014/star/sign/sign.json url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/fenqile/fenqile.cookie.js +^https:\/\/pm\.m\.fenqile\.com/route0014\/app\/tab\/privilege\/convertTaskReward.json url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/fenqile/fenqile.cookie.js + +[task_local] +1 0 * * * fenqile.js +``` + +## 说明 + +1. 先把`pm.m.fenqile.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`fenqile.cookie.js`和`fenqile.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP 手动签到一次: 访问下右下角 `我的` > `乐星` > `签到`,`我的` > `账单点击` > `超级乐星日/天天领乐星` +4. 系统提示: `获取Cookie: 成功` +5. 把获取 Cookie 的脚本注释掉 +6. 运行一次脚本, 如果提示重复签到, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@GideonSenku](https://github.com/GideonSenku) diff --git a/achived/fenqile/fenqile.cookie.js b/achived/fenqile/fenqile.cookie.js new file mode 100644 index 000000000..9904a6984 --- /dev/null +++ b/achived/fenqile/fenqile.cookie.js @@ -0,0 +1,70 @@ +const cookieName = '分期乐' +const signurlKey = 'senku_signurl_fenqile' +const signheaderKey = 'senku_signheader_fenqile' +const signbodyKey = 'senku_signbody_fenqile' +const signDailyKey = 'senku_signDailyKey_fenqile' +const signDailyUrlKey = 'senku_signDailyUrlKey_fenqile' +const senku = init() + +const requrl = $request.url +if ($request && $request.method != 'OPTIONS' && requrl.match(/\/route0014\/star\/sign\//)) { + const signurlVal = requrl + const signheaderVal = JSON.stringify($request.headers) + const signbodyVal = $request.body + if (signurlVal) senku.setdata(signurlVal, signurlKey) + if (signheaderVal) senku.setdata(signheaderVal, signheaderKey) + if (signbodyVal) senku.setdata(signbodyVal, signbodyKey) + senku.msg(cookieName, `获取Cookie: 成功`, `签到领乐星`) +} else { + const signDailyUrlVal = $request.url + const signDailyVal = $request.body; + if (signDailyUrlVal) senku.setdata(signDailyUrlVal,signDailyUrlKey) + if (signDailyVal) senku.setdata(signDailyVal,signDailyKey) + senku.msg(cookieName, `获取Cookie: 成功`, `天天领乐星`) + senku.log() +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} +senku.done() diff --git a/achived/fenqile/fenqile.js b/achived/fenqile/fenqile.js new file mode 100644 index 000000000..2f84d4d2b --- /dev/null +++ b/achived/fenqile/fenqile.js @@ -0,0 +1,132 @@ +const cookieName = '分期乐' +const signurlKey = 'senku_signurl_fenqile' +const signheaderKey = 'senku_signheader_fenqile' +const signbodyKey = 'senku_signbody_fenqile' +const signDailyKey = 'senku_signDailyKey_fenqile' +const signDailyUrlKey = 'senku_signDailyUrlKey_fenqile' +const senku = init() + +const signurlVal = senku.getdata(signurlKey) +const signheaderVal = senku.getdata(signheaderKey) +const signBodyVal = senku.getdata(signbodyKey) +const signDailyUrlVal = senku.getdata(signDailyUrlKey) +const signDailyVal = senku.getdata(signDailyKey) + +const signinfo = {} + + +check() + +function check(){ + signDaily() + sign() + checkin() +} + +function sign() { + const url = { url: signurlVal, headers: JSON.parse(signheaderVal), body: signBodyVal } + senku.post(url, (error, response, data) => { + senku.log(`${cookieName}, 🔔sign--data: ${data}`) + signinfo.sign = JSON.parse(data) + }) +} + +function signDaily(){ + const url = { url: signDailyUrlVal, headers: JSON.parse(signheaderVal), body: signDailyVal } + senku.post(url, (error, response, data) => { + senku.log(`${cookieName}, 🔔signDaily--data: ${data}`) + signinfo.signDaily = JSON.parse(data) + }) +} + + +function getinfo(){ + const title = `${cookieName}` + let subTitle = `天天领乐星:` + let detail = `` + + //signDaily + if (signinfo.signDaily.data.result == 0) { + subTitle += `成功` + } + else if (signinfo.signDaily.data.result == 11650011) { + subTitle += `重复签到` + } + else { + subTitle += `失败` + detail += `编码: ${signinfo.signDaily.data.result}, 说明: ${signinfo.signDaily.data.res_info}` + } + + //sign + subTitle += ` 签到领乐星:` + if (signinfo.sign.data.result == 0) { + subTitle += `成功` + detail += `账户乐星总数: ${signinfo.sign.data.result_rows.postStar}` + } + else if (signinfo.sign.data.result == 12130022) { + subTitle += `重复签到` + } + else { + subTitle += `失败` + detail += `编码: ${signinfo.sign.data.result}, 说明: ${signinfo.sign.data.res_info}` + } + senku.msg(title, subTitle, detail) + senku.done() +} + +function checkin(checkms = 0) { + if (signinfo.sign && signinfo.signDaily) { + getinfo() + } else { + if (checkms > 5000) { + chavy.msg(`${cookieName}`, `签到失败: 超时退出`, ``) + chavy.done() + } else { + setTimeout(() => check(checkms + 100), 100) + } + } +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/achived/rrtv/README.md b/achived/rrtv/README.md new file mode 100644 index 000000000..571b03ce2 --- /dev/null +++ b/achived/rrtv/README.md @@ -0,0 +1,108 @@ +# 人人视频 [已归档] + +> **归档说明**:脚本已归档,仅作存档。若需使用请将配置中的路径改为 `achived/rrtv/`。 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> 2020.8.24 增加随机观看请求,以获得足够活跃值开金宝箱。增加每周礼包抽奖,若未达到抽奖条件,则尝试使用骰子进行刷新卡片以满足条件直至骰子用完(为了节省骰子,此过程设定为周日进行,测试版)。 + +> 2020.8.21 删去多余 header,去除版本信息以绕过验证,并修正开宝箱请求体 + +> 2020.1.11 QuanX 在`190`版本开始, 获取 Cookie 方式需要从`script-response-body`改为`script-request-header` + +> 2020.1.31 增加自动领取每日福利 (无需重新获取 Cookie, 直接更新脚本即可!) + +> 2020.3.4 (1) 增加每日答题 (无需重新获取 Cookie, 直接更新脚本即可!) (答题是判断哪个选项回答的人数最多来选择的,所以建议把签到时间放在 00:10 以后!) + +> 2020.3.4 (2) 增加自动开启宝箱 (60 活跃可开`铜箱`和`银箱`, 100 活跃开`金箱`) ~~(仅靠脚本能自动开`铜箱`和`银箱`, `金箱`需要观看视频达一定分钟数, 平常有看视频的朋友可以把签到时间压后一点, 如: `50 23 * * *` )~~ + +## 配置 (Surge) + +```properties +[MITM] +*.rr.tv + +[Script] +http-request ^https:\/\/api\.rr\.tv\/user\/profile script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/rrtv/rrtv.cookie.js +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/rrtv/rrtv.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +*.rr.tv + +[rewrite_local] +# 189及以前版本 +^https:\/\/api\.rr\.tv\/user\/profile url script-response-body rrtv.cookie.js +# 190及以后版本 +^https:\/\/api\.rr\.tv\/user\/profile url script-request-header rrtv.cookie.js + +[task_local] +10 0 * * * rrtv.js +``` + +## 说明 + +1. 先把`*.rr.tv`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`rrtv.cookie.js`和`rrtv.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP, 访问下`个人中心` +4. 系统提示: `获取Cookie: 成功` (如果不提示获取成功, 尝试杀进程再进个人中心) +5. 最后就可以把第 1 条脚本注释掉了 + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "0 0 * * * *" script-path=xxx.js # 每60分整点执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + 0 * * * * xxx.js # 每60分整点执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) diff --git a/rrtv/rrtv.cookie.js b/achived/rrtv/rrtv.cookie.js similarity index 100% rename from rrtv/rrtv.cookie.js rename to achived/rrtv/rrtv.cookie.js diff --git a/achived/rrtv/rrtv.js b/achived/rrtv/rrtv.js new file mode 100644 index 000000000..c60f5a9de --- /dev/null +++ b/achived/rrtv/rrtv.js @@ -0,0 +1,6 @@ +const $ = new Env('人人视频') + +$.msg($.name, '脚本失效, 请移除!', '原因: emm...') + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/zimuzu/README.md b/achived/zimuzu/README.md similarity index 76% rename from zimuzu/README.md rename to achived/zimuzu/README.md index 80adba307..2f51e5cd8 100644 --- a/zimuzu/README.md +++ b/achived/zimuzu/README.md @@ -1,23 +1,15 @@ -# 字幕组 +# 字幕组 [已归档] -> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 - -> 2020.1.11 QuanX 在`190`版本开始, 获取 Cookie 方式需要从`script-response-body`改为`script-request-header` - -> 2020.1.28 适配人人影视新域名`http://www.rrys2019.com` - -> 2020.2.8 双端签到 (增加 APP 签到) - -> 2020.2.8 19:40 更新 App 端 Cookie 获取方式 (旧方式容易失效) (需要更新: MITM, 两个脚本, 正则) +> **归档说明**:脚本已失效,仅作存档。若需使用请将配置中的路径改为 `achived/zimuzu/`。 ## 配置 (Surge) ```properties [MITM] -*.rrys2019.com, ios.zmzapi.com +*.rrys2020.com, ios.zmzapi.com [Script] -http-request ^https?:\/\/(www\.)?rrys2019\.com\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zimuzu/zimuzu.cookie.js +http-request ^https?:\/\/(www\.)?rrys2020\.com\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zimuzu/zimuzu.cookie.js http-request ^http:\/\/ios.zmzapi.com\/index.php.*a=(mobile_)?login script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zimuzu/zimuzu.cookie.js cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zimuzu/zimuzu.js ``` @@ -26,14 +18,10 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr ```properties [MITM] -*.rrys2019.com, ios.zmzapi.com +*.rrys2020.com, ios.zmzapi.com [rewrite_local] -# 189及以前版本 -^https?:\/\/(www\.)?rrys2019\.com\/?.? url script-response-body zimuzu.cookie.js -^http:\/\/ios.zmzapi.com\/index.php.*a=(mobile_)?login url script-response-body zimuzu.cookie.js -# 190及以后版本 -^https?:\/\/(www\.)?rrys2019\.com\/?.? url script-request-header zimuzu.cookie.js +^https?:\/\/(www\.)?rrys2020\.com\/?.? url script-request-header zimuzu.cookie.js ^http:\/\/ios.zmzapi.com\/index.php.*a=(mobile_)?login url script-request-header zimuzu.cookie.js [task_local] @@ -43,18 +31,18 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr ## 说明 (网页) 1. 先在浏览器登录 `(先登录! 先登录! 先登录!)` -2. 先把`*.rrys2019.com, ios.zmzapi.com`加到`[MITM]` +2. 先把`*.rrys2020.com, ios.zmzapi.com`加到`[MITM]` 3. 再配置重写规则: - Surge: 把两条远程脚本放到`[Script]` - QuanX: 把`zimuzu.cookie.js`和`zimuzu.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) -4. 打开浏览器访问: http://www.rrys2019.com +4. 打开浏览器访问: http://www.rrys2020.com 5. 系统提示: `获取Cookie: 成功` 6. 最后就可以把第 1 条脚本注释掉了 ## 说明 (APP) 1. 先在浏览器登录 `(先登录! 先登录! 先登录!)` -2. 先把`*.rrys2019.com, ios.zmzapi.com`加到`[MITM]` +2. 先把`*.rrys2020.com, ios.zmzapi.com`加到`[MITM]` 3. 再配置重写规则: - Surge: 把两条远程脚本放到`[Script]` - QuanX: 把`zimuzu.cookie.js`和`zimuzu.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) diff --git a/zimuzu/zimuzu.cookie.js b/achived/zimuzu/zimuzu.cookie.js similarity index 100% rename from zimuzu/zimuzu.cookie.js rename to achived/zimuzu/zimuzu.cookie.js diff --git a/achived/zimuzu/zimuzu.js b/achived/zimuzu/zimuzu.js new file mode 100644 index 000000000..a06654dfe --- /dev/null +++ b/achived/zimuzu/zimuzu.js @@ -0,0 +1,6 @@ +const $ = new Env('字幕组') + +$.msg($.name, '脚本失效, 请移除!', '原因: emm...') + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/apktw/README.md b/apktw/README.md index 9f35b5a1d..8b9d55b98 100644 --- a/apktw/README.md +++ b/apktw/README.md @@ -1,22 +1,6 @@ # APK.TW -> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 - -> iOS 需要网关级翻墙! - -> iOS 需要网关级翻墙! - -> iOS 需要网关级翻墙! - -> surge mac 环节下无需网关级翻墙, 可直接运行 (可能需要打开增强模式)! - -> 目前尚不清楚 Cookie 有效期如何 - -> 如果你看到这里还没放弃, 请仔细下面的操作说明 (需要点骚操作) - -解释: - -由于 apk.tw 需要翻墙, 又由于 iOS 的限制, Surge & QuanX 在脚本内的请求都无法走代理, 所以 iOS 环境下, 请保证本脚本在路由或网关级翻墙环境下运行! +> 调整获取会话正则 (使用账号密码登录获取) ## 配置 (Surge) @@ -25,7 +9,7 @@ apk.tw [Script] -http-request ^https:\/\/apk\.tw\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/apktw/apktw.cookie.js +http-request ^https://apk.tw\/member.php(.*?)action=login script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/apktw/apktw.cookie.js,requires-body=true cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/apktw/apktw.js ``` @@ -36,10 +20,7 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr apk.tw [rewrite_local] -# 189及以前版本 -^https:\/\/apk\.tw\/?.? url script-response-body apktw.cookie.js -# 190及以后版本 -^https:\/\/apk\.tw\/?.? url script-request-header apktw.cookie.js +^https://apk.tw\/member.php(.*?)action=login url script-request-body apktw.cookie.js [task_local] 1 0 * * * apktw.js @@ -47,17 +28,9 @@ apk.tw ## 说明 -> 先在登录成功后, 再打开获取 Cookie 的脚本 - -1. 先在浏览器登录 `(先登录! 先登录! 先登录!)`, https://apk.tw/ -2. 滑到页面底部, 点击`电脑版`, 把页面切换为电脑版, 确认登录成功后再执行下面步骤 -3. 先把`apk.tw`加到`[MITM]` -4. 再配置重写规则: - - Surge: 把两条远程脚本放到`[Script]` - - QuanX: 把`apktw.cookie.js`和`apktw.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) -5. 打开浏览器访问: https://apk.tw -6. 系统提示: `获取Cookie: 成功` -7. 最后就可以把第 1 条脚本注释掉了 +1. 访问: `https://apk.tw/` (如果你已经登录, 请先注销) +2. 使用账号密码登录 +3. 系统提示: `获取会话: 成功` (以登录成功后弹出的通知为准!) > 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. diff --git a/apktw/apktw.cookie.js b/apktw/apktw.cookie.js index 9bcd2c23c..dff37e73a 100644 --- a/apktw/apktw.cookie.js +++ b/apktw/apktw.cookie.js @@ -1,54 +1,28 @@ -const cookieName = "APK.TW"; -const cookieKey = "chavy_cookie_apktw"; -const chavy = init(); -const cookieVal = $request.headers["Cookie"]; -if (cookieVal) { - if (chavy.setdata(cookieVal, cookieKey)) { - chavy.msg(`${cookieName}`, "获取Cookie: 成功", ""); - chavy.log(`[${cookieName}] 获取Cookie: 成功, cookie: ${cookieVal}`); +const $ = new Env('ApkTw') + +!(async () => { + $.log('', `🔔 ${$.name}, 获取会话: 开始!`, '') + const session = {} + session.url = $request.url + session.body = $request.body + session.headers = $request.headers + delete session.headers['Content-Length'] + delete session.headers['Cookie'] + $.log('', `url: ${session.url}`, `body: ${session.body}`, `headers: ${JSON.stringify(session.headers)}`) + if ($.setdata(JSON.stringify(session), 'chavy_cookie_apktw')) { + $.subt = '获取会话: 成功!' + } else { + $.subt = '获取会话: 失败!' } -} -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true; - }; - isQuanX = () => { - return undefined === this.$task ? false : true; - }; - getdata = key => { - if (isSurge()) return $persistentStore.read(key); - if (isQuanX()) return $prefs.valueForKey(key); - }; - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val); - if (isQuanX()) return $prefs.setValueForKey(key, val); - }; - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body); - if (isQuanX()) $notify(title, subtitle, body); - }; - log = message => console.log(message); - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb); - } - if (isQuanX()) { - url.method = "GET"; - $task.fetch(url).then(resp => cb(null, {}, resp.body)); - } - }; - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb); - } - if (isQuanX()) { - url.method = "POST"; - $task.fetch(url).then(resp => cb(null, {}, resp.body)); - } - }; - done = (value = {}) => { - $done(value); - }; - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done }; -} -chavy.done(); +})() + .catch((e) => { + $.subt = '获取会话: 失败!' + $.desc = `原因: ${e}` + $.log(`❌ ${$.name}, 获取会话: 失败! 原因: ${e}!`) + }) + .finally(() => { + $.msg($.name, $.subt, $.desc), $.log('', `🔔 ${$.name}, 获取会话: 结束!`, ''), $.done() + }) + +// prettier-ignore +function Env(t){this.name=t,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.log=((...t)=>{this.logs=[...this.logs,...t],t?console.log(t.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((t=this.name,s="",i="")=>{this.isSurge()&&$notification.post(t,s,i),this.isQuanX()&&$notify(t,s,i);const e=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t&&e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n"))}),this.getdata=(t=>this.isSurge()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):void 0),this.setdata=((t,s)=>this.isSurge()?$persistentStore.write(t,s):this.isQuanX()?$prefs.setValueForKey(t,s):void 0),this.get=((t,s)=>this.send(t,"GET",s)),this.wait=((t,s=t)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(s-t+1)+t))),this.post=((t,s)=>this.send(t,"POST",s)),this.send=((t,s,i)=>{if(this.isSurge()){const e="POST"==s?$httpClient.post:$httpClient.get;e(t,(t,s,e)=>{s&&(s.body=e,s.statusCode=s.status),i(t,s,e)})}this.isQuanX()&&(t.method=s,$task.fetch(t).then(t=>{t.status=t.statusCode,i(null,t,t.body)},t=>i(t.error,t,t)))}),this.done=((t={})=>$done(t))} diff --git a/apktw/apktw.js b/apktw/apktw.js index 57e8a5956..087d5e85b 100644 --- a/apktw/apktw.js +++ b/apktw/apktw.js @@ -1,93 +1,96 @@ -const cookieName = 'APK.TW' -const cookieKey = 'chavy_cookie_apktw' -const chavy = init() -const cookieVal = chavy.getdata(cookieKey) +const $ = new Env('ApkTw') +$.VAL_login = $.getdata('chavy_cookie_apktw') -sign() +!(async () => { + $.log('', `🔔 ${$.name}, 开始!`, '') + await login() + await getHash() + await sign() + await showmsg() +})() + .catch((e) => { + $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') + }) + .finally(() => { + $.msg($.name, $.subt, ''), $.log('', `🔔 ${$.name}, 结束!`, ''), $.done() + }) -function sign() { - let url = { url: `https://apk.tw/`, headers: { Cookie: cookieVal } } - url.headers['Host'] = 'apk.tw' - url.headers['Referer'] = 'https://apk.tw/forum.php' - url.headers['Accept'] = '*/*' - url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' - chavy.get(url, (error, response, data) => { - signbbs(data.match(/\/source\/plugin\/dsu_amupper\/images\/wb\.gif/), data) +// 登录 +function login() { + const url = JSON.parse($.VAL_login) + return new Promise((resove) => $.post(url, (error, response, data) => resove())) +} + +function getHash() { + return new Promise((resove) => { + const url = { url: 'https://apk.tw/', headers: {} } + url.headers['Host'] = 'apk.tw' + url.headers['Referer'] = 'https://apk.tw/forum.php' + url.headers['Accept'] = '*/*' + url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' + $.get(url, (error, response, data) => { + try { + if (error) throw new Error(error) + if (/\/source\/plugin\/dsu_amupper\/images\/wb\.gif/.test(data)) { + $.isSigned = true + $.isSignSuc = true + } else { + $.isSigned = false + const [hash] = /plugin.php\?id=dsu_amupper:pper([^('|")]*)/.exec(data) + if (hash) { + $.hash = hash + } else { + $.isSignSuc = false + } + } + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, '') + } finally { + resove() + } + }) }) - chavy.done() } -function signbbs(signedmatch, homedata) { - const title = `${cookieName}` - let subTitle = `` - let detail = `` - if (signedmatch) { - subTitle = `签到结果: 成功 (重复签到)` - chavy.msg(title, subTitle, detail) - } else { - const signmatch = homedata.match(/plugin.php\?id=dsu_amupper:pper([^\']*)/) - if (signmatch) { - let url = { url: `https://apk.tw/${signmatch[0]}&inajax=1&ajaxtarget=my_amupper`, headers: { Cookie: cookieVal } } - url.headers['Host'] = 'apk.tw' - url.headers['Referer'] = 'https://apk.tw/forum.php' - url.headers['Accept'] = '*/*' - url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' - chavy.get(url, (error, response, data) => { - chavy.log(`${cookieName}, data: ${data}`) - if (data.match(/\/source\/plugin\/dsu_amupper\/images\/wb\.gif/)) { - subTitle = `签到结果: 成功` +function sign() { + if ($.isSigned && !$.hash) return + return new Promise((resove) => { + const url = { url: `https://apk.tw/${$.hash}&inajax=1&ajaxtarget=my_amupper`, headers: {} } + $.log(`❕ ${url.url}!`) + url.headers['Host'] = 'apk.tw' + url.headers['Referer'] = 'https://apk.tw/forum.php' + url.headers['Accept'] = '*/*' + url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' + $.get(url, (error, response, data) => { + try { + if (error) throw new Error(error) + if (/\/source\/plugin\/dsu_amupper\/images\/wb\.gif/.test(data)) { + $.isSignSuc = true } else { - subTitle = `签到结果: 失败 (未知)` + $.isSignSuc = false } - chavy.msg(title, subTitle, detail) - }) - } else { - subTitle = `签到结果: 失败 (未知)` - chavy.log(`${cookieName}, homedata: ${homedata}`) - chavy.msg(title, subTitle, detail) - } - } + } catch (e) { + $.isSignSuc = false + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, '') + } finally { + resove() + } + }) + }) } -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) - } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) - } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + +function showmsg() { + return new Promise((resove) => { + if ($.isSigned) { + $.subt = '签到: 重复' + } else if (!$.isSigned && $.isSignSuc) { + $.subt = '签到: 成功' + } else { + $.subt = '签到: 失败' } - } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } + resove() + }) } + +// prettier-ignore +function Env(t){this.name=t,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.log=((...t)=>{this.logs=[...this.logs,...t],t?console.log(t.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((t=this.name,s="",i="")=>{this.isSurge()&&$notification.post(t,s,i),this.isQuanX()&&$notify(t,s,i);const e=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t&&e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n"))}),this.getdata=(t=>this.isSurge()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):void 0),this.setdata=((t,s)=>this.isSurge()?$persistentStore.write(t,s):this.isQuanX()?$prefs.setValueForKey(t,s):void 0),this.get=((t,s)=>this.send(t,"GET",s)),this.wait=((t,s=t)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(s-t+1)+t))),this.post=((t,s)=>this.send(t,"POST",s)),this.send=((t,s,i)=>{if(this.isSurge()){const e="POST"==s?$httpClient.post:$httpClient.get;e(t,(t,s,e)=>{s&&(s.body=e,s.statusCode=s.status),i(t,s,e)})}this.isQuanX()&&(t.method=s,$task.fetch(t).then(t=>{t.status=t.statusCode,i(null,t,t.body)},t=>i(t.error,t,t)))}),this.done=((t={})=>$done(t))} diff --git a/bilibili/README.md b/bilibili/README.md index cd034bc1a..01937b3c2 100644 --- a/bilibili/README.md +++ b/bilibili/README.md @@ -2,10 +2,13 @@ > 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 -> 目前只签 bilibili 直播 (直播!直播!直播!) +> 目前可签 bilibili 直播 (直播!直播!直播!) + 银瓜子转硬币 > 2020.1.11 QuanX 在`190`版本开始, 获取 Cookie 方式需要从`script-response-body`改为`script-request-header` +> 2020.3.16 添加银瓜子转硬币脚本 感谢[@lcandy2](https://github.com/lcandy2) PR + +> 2022.7.7 添加粉丝牌升级任务 ## 配置 (Surge) ```properties @@ -14,7 +17,14 @@ [Script] http-request ^https:\/\/(www|live)\.bilibili\.com\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.cookie.js -cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.js + +bilibili = type=cron,cronexp=10 0 0 * * *,wake-system=1,timeout=100,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.js + +# 如需银瓜子转硬币,添加以下内容 +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.silver2coin.js + +# 如需抽直播红包,添加以下内容 +bilibili = type=cron,cronexp=10 10 0 * * *,wake-system=1,timeout=100,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/redpocket.js ``` ## 配置 (QuanX) @@ -31,6 +41,8 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr [task_local] 1 0 * * * bilibili.js +# 如需银瓜子转硬币,添加以下内容 +1 0 * * * bilibili.silver2coin.js ``` ## 说明 @@ -43,6 +55,7 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr 4. 打开浏览器访问: https://www.bilibili.com 或 https://live.bilibili.com 5. 系统提示: `获取Cookie: 成功` 6. 最后就可以把第 1 条脚本注释掉了 +7. 请根据自己的粉丝牌数设置脚本超时时间,一个粉丝牌预计执行20s > 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. @@ -97,3 +110,5 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr [@lhie1](https://github.com/lhie1) [@ConnersHua](https://github.com/ConnersHua) + +[@lcandy2](https://github.com/lcandy2) diff --git a/bilibili/bilibili.js b/bilibili/bilibili.js index fb3854602..439ab8831 100644 --- a/bilibili/bilibili.js +++ b/bilibili/bilibili.js @@ -1,108 +1,223 @@ -const cookieName = 'bilibili' -const cookieKey = 'chavy_cookie_bilibili' -const chavy = init() -const cookieVal = chavy.getdata(cookieKey) +const $ = new Env('B站直播') +$.bilibiliLive = 'chavy_cookie_bilibili' +const cookie = $.getdata($.bilibiliLive) +const csrf = cookie.match(/.*?bili_jct=(.*?);/)?.[1] -sign() +$.desc = [] -function sign() { - let url = { - url: `https://api.live.bilibili.com/sign/doSign`, - headers: { - Cookie: cookieVal +!(async () => { + await sign() + if ($.sign?.code == 1011040) { + await getSignInfo() + } + await getMedalList() + for (let i = 0; i < $.medalList.length; i++) { + const roomId = $.medalList[i].roomId + $.desc.push(`执行粉丝牌任务(${i+1}/${$.medalList.length}): ${$.medalList[i].nickname}`) + for (let index = 0; index < 5; index++) { + await like(roomId) + await $.wait(1600) + await share(roomId) + await $.wait(1600) } + await $.wait(1600) + await sendMsg(roomId) } - url.headers['Origin'] = 'api.live.bilibili.com' - url.headers['Referer'] = 'http://live.bilibili.com/' - url.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01' - url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' + await notify() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) - chavy.get(url, (error, response, data) => { - let result = JSON.parse(data) - let title = `${cookieName}` - // 签到成功 - if (result && result.code == 0) { - let subTitle = `签到结果: 成功` - let detail = `本月累计: ${result.data.hadSignDays}/${result.data.allDays}次, 说明: ${result.data.text}` - chavy.msg(title, subTitle, detail) - } - // 签到重复 - else if (result && result.code == 1011040) { - getsigninfo() +function notify() { + return new Promise((resolve) => { + $.subt = `签到:${$.sign.message}` + $.msg($.name, $.subt, $.desc.join('\n')) + resolve() + }) +} + +function sign() { + return new Promise((resolve) => { + const url = { + url: 'https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/DoSign', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36', + 'origin': 'https://www.bilibili.com', + 'sec-fetch-site': 'same-site', + 'cookie': cookie + } } - // 签到失败 - else { - let subTitle = `签到结果: 失败` - let detail = `说明: ${result.message}` - chavy.msg(title, subTitle, detail) + $.get(url, (err, resp, data) => { + try { + $.sign = JSON.parse(data) + const result = JSON.parse(data) + if (result?.code == 0) { + $.desc.push(`本月累计: ${result.data.hadSignDays}/${result.data.allDays}次, 说明: ${result.data.text}`) + } else if (result?.code == -101) { + $.desc.push('Cookie已过期, 请重新获取Cookie') + } + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function getSignInfo() { + return new Promise((resolve) => { + const url = { + url: 'https://api.live.bilibili.com/sign/GetSignInfo', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15', + 'cookie': cookie + } } - chavy.log(`${cookieName}, data: ${data}`) + $.get(url, (err, resp, data) => { + try { + const result = JSON.parse(data) + if (result && result.code == 0) { + $.desc.push(`本月累计: ${result.data.hadSignDays}/${result.data.allDays}次, 说明: ${result.data.text}`) + } + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) }) +} - chavy.done() +function getMedalList() { + return new Promise((resolve) => { + const url = { + url: 'https://api.live.bilibili.com/xlive/app-ucenter/v1/fansMedal/panel?page_size=50&page=1', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36', + 'origin': 'https://www.bilibili.com', + 'sec-fetch-site': 'same-site', + 'cookie': cookie + } + } + $.get(url, (err, resp, data) => { + try { + const res = JSON.parse(data) + const items = [...res.data.list, ...res.data.special_list] + $.medalList = items.filter(e => e?.medal?.level < 21).map((e) => { + return { + roomId: e?.room_info?.room_id, + nickname: e?.medal?.medal_name, + } + }) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) } -function getsigninfo() { - let url = { - url: `https://api.live.bilibili.com/sign/GetSignInfo`, - headers: { - Cookie: cookieVal + +function sendMsg(roomId) { + return new Promise((resolve) => { + const body = { + bubble: 0, + msg: '打卡', + color: 16777215, + mode: 2, + fontsize: 25, + rnd: Math.round(new Date().getTime() / 1000).toString(), + roomid: roomId, + csrf: csrf, + csrf_token: csrf + } + const url = { + url: 'https://api.live.bilibili.com/msg/send', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36', + 'cookie': cookie, + 'content-type': 'multipart/form-data' + }, + body: $.queryStr(body) } - } - url.headers['Host'] = 'api.live.bilibili.com' - url.headers['Origin'] = 'http://live.bilibili.com' - url.headers['Referer'] = 'http://live.bilibili.com/' - url.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01' - url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' - chavy.get(url, (error, response, data) => { - let title = `${cookieName}` - let subTitle = `签到结果: 成功 (重复签到)` - let detail = `` - let result = JSON.parse(data) - if (result && result.code == 0) detail = `本月累计: ${result.data.hadSignDays}/${result.data.allDays}次, 说明: ${result.data.text}` - chavy.msg(title, subTitle, detail) + $.post(url, (err, resp, data) => { + try { + $.log('sendMsg: ', roomId) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) }) } -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) + +function like(roomId) { + return new Promise((resolve) => { + const body = { + roomid: roomId, + csrf: csrf } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + const url = { + url: 'https://api.live.bilibili.com/xlive/web-ucenter/v1/interact/likeInteract', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36', + 'origin': 'https://www.bilibili.com', + 'sec-fetch-site': 'same-site', + 'cookie': cookie + }, + body: $.queryStr(body) } - } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) + $.post(url, (err, resp, data) => { + try { + $.log('sendMsg: ', roomId) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function share(roomId) { + return new Promise((resolve) => { + const body = { + roomid: roomId, + csrf: csrf, + interact_type: 3 } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + const url = { + url: 'https://api.live.bilibili.com/xlive/app-room/v1/index/TrigerInteract', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36', + 'cookie': cookie, + 'content-type': 'multipart/form-data', + 'sec-fetch-site': 'same-site', + 'origin': 'https://www.bilibili.com' + }, + body: $.queryStr(body) } - } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } + + $.post(url, (err, resp, data) => { + try { + $.log('sendMsg: ', roomId) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) } + +// pre-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}isStash(){return"undefined"!=typeof $environment&&$environment["stash-version"]}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,n]=i.split("@"),a={url:`http://${n}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),n=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(n);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){if(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:i,statusCode:r,headers:o,rawBody:n}=t,a=s.decode(n,this.encoding);e(null,{status:i,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:i,response:r}=t;e(i,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let i=require("iconv-lite");this.initGotEnv(t);const{url:r,...o}=t;this.got[s](r,o).then(t=>{const{statusCode:s,statusCode:r,headers:o,rawBody:n}=t,a=i.decode(n,this.encoding);e(null,{status:s,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:s,response:r}=t;e(s,r,r&&i.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}queryStr(t){let e="";for(const s in t){let i=t[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),e+=`${s}=${i}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,i=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":i}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),this.isSurge()||this.isQuanX()||this.isLoon()?$done(t):this.isNode()&&process.exit(1)}}(t,e)} \ No newline at end of file diff --git a/bilibili/bilibili.silver2coin.js b/bilibili/bilibili.silver2coin.js new file mode 100644 index 000000000..c6f039ed9 --- /dev/null +++ b/bilibili/bilibili.silver2coin.js @@ -0,0 +1,88 @@ +const cookieName = 'bilibili' +const cookieKey = 'chavy_cookie_bilibili' +const chavy = init() +const cookieVal = chavy.getdata(cookieKey) + +sign() + +function sign() { + let url = { + url: `https://api.live.bilibili.com/pay/v1/Exchange/silver2coin`, + headers: { + Cookie: cookieVal + } + } + url.headers['Origin'] = 'api.live.bilibili.com' + url.headers['Referer'] = 'http://live.bilibili.com/' + url.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01' + url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' + + chavy.get(url, (error, response, data) => { + let result = JSON.parse(data) + let title = `${cookieName} 银瓜子转硬币` + // 兑换成功 + if (result && result.code == 0) { + let subTitle = `${result.message}` + let detail = `成功兑换: ${result.data.coin} 个硬币\n当前银瓜子: ${result.data.silver} , 当前金瓜子: ${result.data.gold}` + chavy.msg(title, subTitle, detail) + } + // 兑换中止(重复兑换&银瓜子不足) + else if (result && result.code == 403) { + let subTitle = `未成功兑换` + let detail = `${result.message}` + chavy.msg(title, subTitle, detail) + } + // 兑换失败 + else { + let subTitle = `兑换失败` + let detail = `说明: ${result.message}` + chavy.msg(title, subTitle, detail) + } + chavy.log(`${cookieName}, data: ${data}`) + }) + + chavy.done() +} +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/bilibili/redpocket.js b/bilibili/redpocket.js new file mode 100644 index 000000000..9136750b2 --- /dev/null +++ b/bilibili/redpocket.js @@ -0,0 +1,152 @@ +const $ = new Env('B站抽红包') +$.bilibiliLive = 'chavy_cookie_bilibili' +const cookie = $.getdata($.bilibiliLive) +const csrf = cookie.match(/.*?bili_jct=(.*?);/)?.[1] + +$.desc = [] + +!(async () => { + await getRedPocketList() + for (let i = 0; i < $.list.length; i++) { + const redPocket = $.list[i] + await getLotteryInfoWeb(redPocket.roomId, redPocket.runame) + await redPocketDraw(redPocket) + await sendMsg(redPocket.roomId) + await $.wait(1000) + } + await notify() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +function notify() { + return new Promise((resolve) => { + $.subt = `红包主播列表` + $.msg($.name, $.subt, $.desc.join('\n')) + resolve() + }) +} + +function getRedPocketList() { + return new Promise((resolve) => { + const url = { + url: 'https://api.live.bilibili.com/xlive/fuxi-interface/JuneRedPacket2022Controller/redPocketPlaying', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36', + 'sec-fetch-site': 'same-site', + "Referer": "https://live.bilibili.com/", + 'cookie': cookie + } + } + $.get(url, (err, resp, data) => { + try { + const { _ts_rpc_return_ } = JSON.parse(data) + $.list = _ts_rpc_return_?.data?.list.filter(e => e.countDown > 10) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function getLotteryInfoWeb(roomid, runame) { + return new Promise((resolve) => { + const url = { + url: 'https://api.live.bilibili.com/xlive/lottery-interface/v1/lottery/getLotteryInfoWeb?roomid=' + roomid, + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15', + 'cookie': cookie + } + } + $.get(url, (err, resp, data) => { + try { + const result = JSON.parse(data) + if (result?.code == 0) { + const { popularity_red_pocket } = result?.data + const total_price = popularity_red_pocket?.[0]?.total_price / 1000 || 0 + $.desc.push(`${runame}: 电池价值${total_price}元`) + } + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + + +function redPocketDraw(redPocket) { + return new Promise((resolve) => { + const body = { + ruid: redPocket.ruid, + room_id: redPocket.roomId, + lot_id: redPocket.lotId, + csrf: csrf, + csrf_token: csrf, + } + const url = { + url: 'https://api.live.bilibili.com/xlive/lottery-interface/v1/popularityRedPocket/RedPocketDraw', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36', + 'origin': 'https://www.bilibili.com', + 'sec-fetch-site': 'same-site', + 'cookie': cookie + }, + body: $.queryStr(body) + } + $.post(url, (err, resp, data) => { + try { + // nothing + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function sendMsg(roomId) { + return new Promise((resolve) => { + const body = { + bubble: 0, + msg: '老板大气!点点红包抽礼物!', + color: 16777215, + mode: 2, + fontsize: 25, + rnd: Math.round(new Date().getTime() / 1000).toString(), + roomid: roomId, + csrf: csrf, + csrf_token: csrf + } + const url = { + url: 'https://api.live.bilibili.com/msg/send', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36', + 'cookie': cookie, + 'content-type': 'multipart/form-data' + }, + body: $.queryStr(body) + } + + $.post(url, (err, resp, data) => { + try { + $.log('sendMsg: ', roomId) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +// pre-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}isStash(){return"undefined"!=typeof $environment&&$environment["stash-version"]}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,n]=i.split("@"),a={url:`http://${n}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),n=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(n);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){if(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:i,statusCode:r,headers:o,rawBody:n}=t,a=s.decode(n,this.encoding);e(null,{status:i,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:i,response:r}=t;e(i,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let i=require("iconv-lite");this.initGotEnv(t);const{url:r,...o}=t;this.got[s](r,o).then(t=>{const{statusCode:s,statusCode:r,headers:o,rawBody:n}=t,a=i.decode(n,this.encoding);e(null,{status:s,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:s,response:r}=t;e(s,r,r&&i.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}queryStr(t){let e="";for(const s in t){let i=t[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),e+=`${s}=${i}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,i=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":i}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),this.isSurge()||this.isQuanX()||this.isLoon()?$done(t):this.isNode()&&process.exit(1)}}(t,e)} \ No newline at end of file diff --git a/box/chavy.boxjs.html b/box/chavy.boxjs.html new file mode 100644 index 000000000..bc516cad4 --- /dev/null +++ b/box/chavy.boxjs.html @@ -0,0 +1,3159 @@ + + + + BoxJs + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + mdi-chevron-left + + + + + + + + + + + + + {{`${app.name} (${app.id})`}} + {{app.repo}} + {{app.author}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{c.login}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mdi-image + + + + + + + + mdi-dock-top + + + + + + + + mdi-format-align-top + + + + + + + + mdi-dock-bottom + + + + + + + + mdi-format-align-bottom + + + + + + + mdi-volume-off + + + + + + + mdi-volume-off + + + + + + + mdi-help + + + + + + + + + + + + + + + + + + + mdi-face-profile + + + + + + + mdi-code-tags + + + + + + + mdi-refresh + + + + + + + mdi-language-html5 + + + + + + + + + + + + + + + + + + + + + + {{ui.snackbar.msg}} + + +
🎉 BoxJS 已有 iOS 客户端啦
+
+ 推荐使用原生 iOS 客户端 Relay,体验更流畅。TestFlight 加入地址: + https://testflight.apple.com/join/2yES8TuF +
+
+ + + + +
+ mdi-close-circle-outline + + + + +

+ {{app.name}} +

+
+
+
+
+ + + + + + {{ $t('apps.fav') }} ({{favApps.length}}) + + + + + + + + + + + {{sub.name}} ({{sub.apps.length}}) + + + + + + + + + + + {{ $t('apps.sysApps') }} ({{sysApps.length}}) + + + + + + + + + + + + + + + {{ $t('subs.appSubs') }} ({{appSubs.length}}) + + + mdi-cloud-circle + + + mdi-refresh-circle + + + mdi-plus-circle + + + + + + + + {{ $t('subs.addDialog.title') }} + + + + + + + + {{$t('base.dialog.close')}} + + {{$t('base.dialog.save')}} + + + + + + + {{ ui.installConfirmDialog.title }} + {{ ui.installConfirmDialog.message }} + + + {{$t('base.dialog.close')}} + + {{$t('base.dialog.ok')}} + + + + + + + + + + {{box.usercfgs.name ? box.usercfgs.name : $t('profile.leaveName')}} + + + + + {{ $t('profile.editor.title') }} + + + + + + + + + {{ $t('base.dialog.close') }} + + {{ $t('base.dialog.save') }} + + + + + + + + {{ $t('profile.datas') }} + + {{ $t('profile.apps') }}: {{this.apps.length}} + {{ $t('profile.subs') }}: {{this.appSubs.length}} + {{ $t('profile.sessions') }}: {{this.sessions.length}} + + + + + {{ $t('profile.dataviewer')}} + + + + {{ $t('profile.impDialog.title') }} + + + + + + + + {{ $t('base.dialog.close') }} + {{ $t('profile.imp') }} + + + + {{ $t('profile.bak') }} + + + + + + + + + + + + {{ $t('viewer.dataUnsubscribed') }} ({{gistkeys.length}}) + + + + + + + + + + + {{ $t('viewer.dataRecentlyViewed') }} ({{viewkeys.length}}) + + + + + + + + + + {{ $t('viewer.dataViewer') }} + + {{ $t('base.cmd.cp') }} + + + + + + + + + {{ $t('base.dialog.view') }} + + + + + {{ $t('viewer.dataEditor') }} + + {{ $t('base.cmd.cp') }} + + + + + + + + + + {{ + $t('base.dialog.save') }} + + + + + + + +

{{ $t('codding.title') }}

+ + + mdi-play-circle + +
+
+
+
+ + + +

{{curapp.name}}

+ + + mdi-play-circle + +
+ + +

+

+

+
+
+
+ + + + + + + + + {{ $t('appDetail.curSession') }} + {{curapp.curSession ? curapp.curSession.name : ''}} + + + + + + {{ $t('base.cmd.cp') }} + + + + + {{ $t('appDetail.impDialog.title') }} + + + + + + + + + {{ $t('base.dialog.close') }} + + + {{ $t('base.cmd.imp') }} + + + + + + {{ $t('appDetail.copyDatas') }} + + + + {{ $t('appDetail.clearDatas') }} + + + + + + + {{data.key}} + {{data.val ? data.val : $t('appDetail.noDatas')}} + + + + mdi-close + + + + + + + {{ $t('base.cmd.duplicate') }} + + + + + #{{sessionIdx + 1}} {{session.name}} + + + + + + + + + {{ $t('appDetail.sessionEditor.title') }} + + + + + + + + + {{ $t('base.dialog.close') }} + {{ $t('base.dialog.save') }} + + + + + + {{ $t('base.cmd.del') }} + + + + + + + {{data.key}} + {{data.val ? data.val : $t('appDetail.noDatas')}} + + + + + {{dayjs(session.createTime).format('YYYY-MM-DD HH:mm:ss')}} + + {{ $t('base.dialog.use') }} + {{ $t('base.dialog.link') }} + + +
+ + + +

{{curbak.name}}

+ + {{ $t('base.cmd.recovery') }} +
+ + {{ $t('bakDetail.title') }} + + + + + + + + {{ $t('base.cmd.del') }} + + + + + {{ $t('bakDetail.dataTitle') }} + + {{ $t('base.cmd.cp') }} + + +
+ + + mdi-content-save + + +
+ + + + {{ $t('menus.home') }}mdi-home + {{ $t('menus.apps') }}mdi-application + {{ $t('menus.subs') }}mdi-database + + + + + + + + + + mdi-delete-circle-outline + + + mdi-help + + + mdi-new-box + + + {{box.usercfgs.isLeftBoxIcon ? 'mdi-format-horizontal-align-right' : 'mdi-format-horizontal-align-left'}} + + + mdi-refresh + + + mdi-code-tags + + + mdi-magnify + + + + + + + + mdi-help-circle + + + + + + + mdi-chevron-double-down + + + + +
+

v{{ver.version}}

+
+ {{note.name}} +
    +
  • {{desc}}
  • +
+
+
+
+ + + {{ $t('reloadDialog.title') }} + {{ $t('reloadDialog.text') }} + + + {{ $t('base.dialog.close') }} + {{ $t('reloadDialog.reload') }} + + + +
+
+ + + + 执行结果 + + + mdi-chevron-double-down + + + + +
+

+

+

+
+
+
+
+
+
+ + + + + + + + + + + + + diff --git a/box/chavy.boxjs.js b/box/chavy.boxjs.js new file mode 100644 index 000000000..a3122d663 --- /dev/null +++ b/box/chavy.boxjs.js @@ -0,0 +1,1207 @@ +const $ = new Env('BoxJs') + +// 为 eval 准备的上下文环境 +const $eval_env = {} + +$.version = '0.19.29' +$.versionType = 'beta' + +// 发出的请求需要需要 Surge、QuanX 的 rewrite +$.isNeedRewrite = true + +/** + * =================================== + * 持久化属性: BoxJs 自有的数据结构 + * =================================== + */ + +// 存储`用户偏好` +$.KEY_usercfgs = 'chavy_boxjs_userCfgs' +// 存储`应用会话` +$.KEY_sessions = 'chavy_boxjs_sessions' +// 存储`页面缓存` +$.KEY_web_cache = 'chavy_boxjs_web_cache' +// 存储`应用订阅缓存` +$.KEY_app_subCaches = 'chavy_boxjs_app_subCaches' +// 存储`全局备份` (弃用, 改用 `chavy_boxjs_backups`) +$.KEY_globalBaks = 'chavy_boxjs_globalBaks' +// 存储`备份索引` +$.KEY_backups = 'chavy_boxjs_backups' +// 存储`当前会话` (配合切换会话, 记录当前切换到哪个会话) +$.KEY_cursessions = 'chavy_boxjs_cur_sessions' + +/** + * =================================== + * 持久化属性: BoxJs 公开的数据结构 + * =================================== + */ + +// 存储用户访问`BoxJs`时使用的域名 +$.KEY_boxjs_host = 'boxjs_host' + +// 请求响应体 (返回至页面的结果) +$.json = $.name // `接口`类请求的响应体 +$.html = $.name // `页面`类请求的响应体 + +// 页面源码地址 +$.web = `https://cdn.jsdelivr.net/gh/chavyleung/scripts@${ + $.version +}/box/chavy.boxjs.html?_=${new Date().getTime()}` +// 版本说明地址 (Release Note) +$.ver = `https://raw.githubusercontent.com/chavyleung/scripts/master/box/release/box.release.json` + +!(async () => { + // 勿扰模式 + $.isMute = [true, 'true'].includes($.getdata('@chavy_boxjs_userCfgs.isMute')) + + // 请求路径 + $.path = getPath($request.url) + + // 请求参数 /api/save?id=xx&name=xx => {id: 'xx', name: 'xx'} + const [, query] = $.path.split('?') + $.queries = query + ? query.split('&').reduce((obj, cur) => { + const [key, val] = cur.split('=') + obj[key] = val + return obj + }, {}) + : {} + + // 请求类型: GET + $.isGet = $request.method === 'GET' + // 请求类型: POST + $.isPost = $request.method === 'POST' + // 请求类型: OPTIONS + $.isOptions = $request.method === 'OPTIONS' + + // 请求类型: page、api、query + $.type = 'page' + // 查询请求: /query/xxx + $.isQuery = $.isGet && /^\/query\/.*?/.test($.path) + // 接口请求: /api/xxx + $.isApi = $.isPost && /^\/api\/.*?/.test($.path) + // 页面请求: /xxx + $.isPage = $.isGet && !$.isQuery && !$.isApi + + // 升级用户数据 + upgradeUserData() + // 升级备份数据 + upgradeGlobalBaks() + + // 处理预检请求 + if ($.isOptions) { + $.type = 'options' + await handleOptions() + } + // 处理`页面`请求 + else if ($.isPage) { + $.type = 'page' + await handlePage() + } + // 处理`查询`请求 + else if ($.isQuery) { + $.type = 'query' + await handleQuery() + } + // 处理`接口`请求 + else if ($.isApi) { + $.type = 'api' + await handleApi() + } +})() + .catch((e) => $.logErr(e)) + .finally(() => doneBox()) + +/** + * http://boxjs.com/ => `http://boxjs.com` + * http://boxjs.com/app/jd => `http://boxjs.com` + */ +function getHost(url) { + return url.slice(0, url.indexOf('/', 8)) +} + +/** + * http://boxjs.com/ => `` + * http://boxjs.com/api/getdata => `/api/getdata` + */ +function getPath(url) { + // 如果以`/`结尾, 去掉最后一个`/` + const end = url.lastIndexOf('/') === url.length - 1 ? -1 : undefined + // slice第二个参数传 undefined 会直接截到最后 + // indexOf第二个参数用来跳过前面的 "https://" + return url.slice(url.indexOf('/', 8), end) +} + +/** + * =================================== + * 处理前端请求 + * =================================== + */ + +/** + * 处理`页面`请求 + */ +async function handlePage() { + // 获取 BoxJs 数据 + const boxdata = getBoxData() + boxdata.syscfgs.isDebugMode = false + + // 调试模式: 是否每次都获取新的页面 + const isDebugWeb = [true, 'true'].includes( + $.getdata('@chavy_boxjs_userCfgs.isDebugWeb') + ) + const debugger_web = $.getdata('@chavy_boxjs_userCfgs.debugger_web') + const cache = $.getjson($.KEY_web_cache, null) + + // 如果没有开启调试模式,且当前版本与缓存版本一致,且直接取缓存 + if (!isDebugWeb && cache && cache.version === $.version) { + $.html = cache.cache + } + // 如果开启了调试模式,并指定了 `debugger_web` 则从指定的地址获取页面 + else { + if (isDebugWeb && debugger_web) { + // 调试地址后面拼时间缀, 避免 GET 缓存 + const isQueryUrl = debugger_web.includes('?') + $.web = `${debugger_web}${ + isQueryUrl ? '&' : '?' + }_=${new Date().getTime()}` + boxdata.syscfgs.isDebugMode = true + console.log(`[WARN] 调试模式: $.web = : ${$.web}`) + } + // 如果调用这个方法来获取缓存, 且标记为`非调试模式` + const getcache = () => { + console.log(`[ERROR] 调试模式: 正在使用缓存的页面!`) + boxdata.syscfgs.isDebugMode = false + return $.getjson($.KEY_web_cache).cache + } + await $.http.get($.web).then( + (resp) => { + if (/BoxJs<\/title>/.test(resp.body)) { + // 返回页面源码, 并马上存储到持久化仓库 + $.html = resp.body + const cache = { version: $.version, cache: $.html } + $.setjson(cache, $.KEY_web_cache) + } else { + // 如果返回的页面源码不是预期的, 则从持久化仓库中获取 + $.html = getcache() + } + }, + // 如果获取页面源码失败, 则从持久化仓库中获取 + () => ($.html = getcache()) + ) + } + // 根据偏好设置, 替换首屏颜色 (如果是`auto`则交由页面自适应) + const theme = $.getdata('@chavy_boxjs_userCfgs.theme') + if (theme === 'light') { + $.html = $.html.replace('#121212', '#fff') + } else if (theme === 'dark') { + $.html = $.html.replace('#fff', '#121212') + } + /** + * 后端渲染数据, 感谢 https://t.me/eslint 提供帮助 + * + * 如果直接渲染到 box: null 会出现双向绑定问题 + * 所以先渲染到 `boxServerData: null` 再由前端 `this.box = this.boxServerData` 实现双向绑定 + */ + $.html = $.html.replace( + 'boxServerData: null', + 'boxServerData:' + JSON.stringify(boxdata) + ) + + // 调试模式支持 vue Devtools (只有在同时开启调试模式和指定了调试地址才生效) + // vue.min.js 生效时, 会导致 @click="window.open()" 报 "window" is not defined 错误 + if (isDebugWeb && debugger_web) { + $.html = $.html.replace('vue.min.js', 'vue.js') + } +} + +/** + * 处理`查询`请求 + */ +async function handleQuery() { + const referer = $request.headers.referer || $request.headers.Referer + if (!/^https?:\/\/(.+\.)?boxjs\.(com|net)\//.test(referer)) { + const isMuteQueryAlert = [true, 'true'].includes( + $.getdata('@chavy_boxjs_userCfgs.isMuteQueryAlert') + ) + + if (!isMuteQueryAlert) { + // 关闭静默状态 + const _isMute = $.isMute + $.isMute = false + + $.msg( + $.name, + '❗️发现有脚本或人正在读取你的数据', + [ + '请注意数据安全, 你可以: ', + '1. 在 BoxJs 的脚本日志中查看详情', + '2. 在 BoxJs 的页面 (侧栏) 中 "不显示查询警告"' + ].join('\n') + ) + + // 还原静默状态 + $.isMute = _isMute + } + + $.log( + [ + '', + '❗️❗️❗️ 发现有脚本或人正在读取你的数据 ❗️❗️❗️', + JSON.stringify($request), + '' + ].join('\n') + ) + } + + const [, query] = $.path.split('/query') + if (/^\/boxdata/.test(query)) { + $.json = getBoxData() + } else if (/^\/baks/.test(query)) { + const [, backupId] = query.split('/baks/') + $.json = $.getjson(backupId) + } else if (/^\/versions$/.test(query)) { + await getVersions(true) + } else if (/^\/data/.test(query)) { + const [, dataKey] = query.split('/data/') + $.json = { + key: dataKey, + val: $.getdata(dataKey) + } + } +} + +/** + * 处理 API 请求 + */ +async function handleApi() { + const [, api] = $.path.split('/api') + + const apiHandlers = { + '/save': apiSave, + '/addAppSub': apiAddAppSub, + '/deleteAppSub': apiDeleteAppSub, + '/reloadAppSub': apiReloadAppSub, + '/delGlobalBak': apiDelGlobalBak, + '/updateGlobalBak': apiUpdateGlobalBak, + '/saveGlobalBak': apiSaveGlobalBak, + '/impGlobalBak': apiImpGlobalBak, + '/revertGlobalBak': apiRevertGlobalBak, + '/runScript': apiRunScript, + '/saveData': apiSaveData, + '/surge': apiSurge, + '/update': apiUpdate + } + + for (const [key, handler] of Object.entries(apiHandlers)) { + if (api === key || api.startsWith(`${key}?`)) { + await handler() + break + } + } +} + +async function handleOptions() {} + +/** + * =================================== + * 获取基础数据 + * =================================== + */ + +function getBoxData() { + const datas = {} + + const extraDatas = + $.getdata(`${$.KEY_usercfgs.replace('#', '@')}.gist_cache_key`) || [] + + extraDatas.forEach((key) => { + datas[key] = $.getdata(key) + }) + + const usercfgs = getUserCfgs() + const sessions = getAppSessions() + const curSessions = getCurSessions() + const sysapps = getSystemApps() + const syscfgs = getSystemCfgs() + const appSubCaches = getAppSubCaches() + const globalbaks = getGlobalBaks() + + // 把 `内置应用`和`订阅应用` 里需要持久化属性放到`datas` + sysapps.forEach((app) => { + const newDatas = getAppDatas(app) + Object.assign(datas, newDatas) + }) + usercfgs.appsubs.forEach((sub) => { + const subcache = appSubCaches[sub.url] + if (subcache && subcache.apps && Array.isArray(subcache.apps)) { + subcache.apps.forEach((app) => { + const newDatas = getAppDatas(app) + Object.assign(datas, newDatas) + }) + } + }) + + const box = { + datas, + usercfgs, + sessions, + curSessions, + sysapps, + syscfgs, + appSubCaches, + globalbaks + } + + return box +} + +/** + * 获取系统配置 + */ +function getSystemCfgs() { + // prettier-ignore + return { + env: $.isStash() ? 'Stash' : $.isShadowrocket() ? 'Shadowrocket' : $.isLoon() ? 'Loon' : $.isQuanX() ? 'QuanX' : $.isEgern() ? 'Egern' : $.isSurge() ? 'Surge' : 'Node', + version: $.version, + versionType: $.versionType, + envs: [ + { id: 'Surge', icons: ['https://raw.githubusercontent.com/Orz-3/mini/none/surge.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/surge.png'] }, + { id: 'QuanX', icons: ['https://raw.githubusercontent.com/Orz-3/mini/none/quanX.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/quantumultx.png'] }, + { id: 'Loon', icons: ['https://raw.githubusercontent.com/Orz-3/mini/none/loon.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/loon.png'] }, + { id: 'Shadowrocket', icons: ['https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/shadowrocket.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/shadowrocket.png'] }, + { id: 'Stash', icons: ['https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/stash.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/stash.png'] }, + { id: 'Egern', icons: ['https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/appstore.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/appstore.png'] } + ], + chavy: { id: 'ChavyLeung', icon: 'https://avatars3.githubusercontent.com/u/29748519', repo: 'https://github.com/chavyleung/scripts' }, + senku: { id: 'GideonSenku', icon: 'https://avatars1.githubusercontent.com/u/39037656', repo: 'https://github.com/GideonSenku' }, + id77: { id: 'id77', icon: 'https://avatars0.githubusercontent.com/u/9592236', repo: 'https://github.com/id77' }, + orz3: { id: 'Orz-3', icon: 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/Orz-3.png', repo: 'https://github.com/Orz-3/' }, + boxjs: { id: 'BoxJs', show: false, icon: 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/box.png', icons: ['https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/box.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/box.png'], repo: 'https://github.com/chavyleung/scripts' }, + defaultIcons: ['https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/appstore.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/appstore.png'] + } +} + +/** + * 获取内置应用 + */ +function getSystemApps() { + // prettier-ignore + const sysapps = [ + { + id: 'BoxSetting', + name: '偏好设置', + descs: ['可手动执行一些抹掉数据的脚本', '可设置明暗两种主题下的主色调', '可设置壁纸清单'], + keys: [ + '@chavy_boxjs_userCfgs.httpapi', + '@chavy_boxjs_userCfgs.bgimg', + '@chavy_boxjs_userCfgs.http_backend', + '@chavy_boxjs_userCfgs.color_dark_primary', + '@chavy_boxjs_userCfgs.color_light_primary' + ], + settings: [ + { id: '@chavy_boxjs_userCfgs.httpapis', name: 'HTTP-API (Surge)', val: '', type: 'textarea', placeholder: ',examplekey@127.0.0.1:6166', autoGrow: true, rows: 2, persistentHint:true, desc: '示例: ,examplekey@127.0.0.1:6166! 注意: 以逗号开头, 逗号分隔多个地址, 可加回车' }, + { id: '@chavy_boxjs_userCfgs.httpapi_timeout', name: 'HTTP-API Timeout (Surge)', val: 20, type: 'number', persistentHint:true, desc: '如果脚本作者指定了超时时间, 会优先使用脚本指定的超时时间.' }, + { id: '@chavy_boxjs_userCfgs.http_backend', name: 'HTTP Backend (Quantumult X)', val: '', type: 'text',placeholder: 'http://127.0.0.1:9999', persistentHint:true, desc: '示例: http://127.0.0.1:9999 ! 注意: 必须是以 http 开头的完整路径, 不能是 / 结尾' }, + { id: '@chavy_boxjs_userCfgs.debugger_webs', name: '调试地址', val: 'Dev体验,https://raw.githubusercontent.com/chavyleung/scripts/boxjs.dev/box/chavy.boxjs.html', type: 'textarea', placeholder: '每行一个配置,用逗号分割每个配置的名字和链接:配置,url', persistentHint:true, autoGrow: true, rows: 2, desc: '逗号分隔名字和链接, 回车分隔多个地址' }, + { id: '@chavy_boxjs_userCfgs.bgimgs', name: '背景图片清单', val: '无,\n跟随系统,跟随系统\nlight,http://api.btstu.cn/sjbz/zsy.php\ndark,https://uploadbeta.com/api/pictures/random\n妹子,http://api.btstu.cn/sjbz/zsy.php', type: 'textarea', placeholder: '无,{回车} 跟随系统,跟随系统{回车} light,图片地址{回车} dark,图片地址{回车} 妹子,图片地址', persistentHint:true, autoGrow: true, rows: 2, desc: '逗号分隔名字和链接, 回车分隔多个地址' }, + { id: '@chavy_boxjs_userCfgs.bgimg', name: '背景图片', val: '', type: 'text', placeholder: 'http://api.btstu.cn/sjbz/zsy.php', persistentHint:true, desc: '输入背景图标的在线链接' }, + { id: '@chavy_boxjs_userCfgs.changeBgImgEnterDefault', name: '手势进入壁纸模式默认背景图片', val: '', type: 'text', placeholder: '填写上面背景图片清单的值', persistentHint:true, desc: '' }, + { id: '@chavy_boxjs_userCfgs.changeBgImgOutDefault', name: '手势退出壁纸模式默认背景图片', val: '', type: 'text', placeholder: '填写上面背景图片清单的值', persistentHint:true, desc: '' }, + { id: '@chavy_boxjs_userCfgs.color_light_primary', name: '明亮色调', canvas: true, val: '#F7BB0E', type: 'colorpicker', desc: '' }, + { id: '@chavy_boxjs_userCfgs.color_dark_primary', name: '暗黑色调', canvas: true, val: '#2196F3', type: 'colorpicker', desc: '' } + ], + scripts: [ + { + name: "抹掉:所有缓存", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.caches.js" + }, + { + name: "抹掉:收藏应用", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.usercfgs.favapps.js" + }, + { + name: "抹掉:用户偏好", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.usercfgs.js" + }, + { + name: "抹掉:所有会话", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.usercfgs.sessions.js" + }, + { + name: "抹掉:所有备份", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.baks.js" + }, + { + name: "抹掉:BoxJs (注意备份)", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.boxjs.js" + } + ], + author: '@chavyleung', + repo: 'https://github.com/chavyleung/scripts/blob/master/box/switcher/box.switcher.js', + icons: [ + 'https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxSetting.mini.png', + 'https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxSetting.png' + ] + }, + { + id: 'BoxSwitcher', + name: '会话切换', + desc: '打开静默运行后, 切换会话将不再发出系统通知 \n注: 不影响日志记录', + keys: [], + settings: [{ id: 'CFG_BoxSwitcher_isSilent', name: '静默运行', val: false, type: 'boolean', desc: '切换会话时不发出系统通知!' }], + author: '@chavyleung', + repo: 'https://github.com/chavyleung/scripts/blob/master/box/switcher/box.switcher.js', + icons: [ + 'https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxSwitcher.mini.png', + 'https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxSwitcher.png' + ], + script: 'https://raw.githubusercontent.com/chavyleung/scripts/master/box/switcher/box.switcher.js' + }, + { + id: "BoxGist", + name: "Gist备份", + keys: [ + "@gist.token", + "@gist.username", + "@gist.split", + "@gist.revision_options", + "@gist.backup_type" + ], + author: "@dompling", + repo: "https://github.com/dompling/Script/tree/master/gist", + icons: [ + "https://raw.githubusercontent.com/Former-Years/icon/master/github-bf.png", + "https://raw.githubusercontent.com/Former-Years/icon/master/github-bf.png" + ], + descs_html: [ + "<h2>Token的获取方式</h2>", + "<ol>头像菜单 -></ol>", + "<ol>Settings -></ol>", + "<ol>Developer settings -></ol>", + "<ol>Personal access tokens -></ol>", + "<ol>Generate new token -></ol>", + "<ol>在里面找到 gist 勾选提交</ol>", + "<h2>Gist Revision Id</h2>", + "<ol>打开Gist项目</ol>", + "<ol>默认为Code,选择Revisions</ol>", + "<ol>找到需要恢复的版本文件</ol>", + "<ol>点击右上角【...】>【View file】</ol>", + "<ol>浏览器地址最后一串为 RevisionId</ol>" + ], + scripts: [ + { + name: "备份 Gist", + script: "https://raw.githubusercontent.com/dompling/Script/master/gist/backup.js" + }, + { + name: "从 Gist 恢复", + script: "https://raw.githubusercontent.com/dompling/Script/master/gist/restore.js" + }, + { + name: "更新历史版本", + script: "https://raw.githubusercontent.com/dompling/Script/master/gist/commit.js" + } + ], + settings: [ + { + id: "@gist.split", + name: "用户数据分段", + val: null, + type: "number", + placeholder: "用户数据过大时,请进行拆分防止内存警告⚠️", + desc: "值为数字,拆分段数比如 2 就拆分成两个 datas." + }, + { + id: "@gist.revision_id", + type: "modalSelects", + name: "历史版本RevisionId", + desc: "不填写时,默认获取最新,恢复后会自动清空。选择无内容时,请运行上方更新历史版本", + items: "@gist.revision_options" + }, + { + id: "@gist.backup_type", + name: "备份/恢复内容", + val: "usercfgs,datas,sessions,curSessions,backups,appSubCaches", + type: "checkboxes", + items: [ + { + key: "usercfgs", + label: "用户偏好" + }, + { + key: "datas", + label: "用户数据" + }, + { + key: "sessions", + label: "应用会话" + }, + { + key: "curSessions", + label: "当前会话" + }, + { + key: "backups", + label: "备份索引" + }, + { + key: "appSubCaches", + label: "应用订阅缓存" + } + ] + }, + { + id: "@gist.username", + name: "用户名", + val: null, + type: "text", + placeholder: "github 用户名", + desc: "必填" + }, + { + id: "@gist.token", + name: "Personal access tokens", + val: null, + type: "text", + placeholder: "github personal access tokens", + desc: "必填" + } + ] + } + ] + return sysapps +} + +/** + * 获取用户配置 + */ +function getUserCfgs() { + const defcfgs = { + gist_cache_key: [], + + favapps: [], + appsubs: [], + viewkeys: [], + isPinedSearchBar: true, + httpapi: 'examplekey@127.0.0.1:6166', + http_backend: '' + } + const usercfgs = Object.assign(defcfgs, $.getjson($.KEY_usercfgs, {})) + + // 处理异常数据:删除所有为 null 的订阅 + if (usercfgs.appsubs.includes(null)) { + usercfgs.appsubs = usercfgs.appsubs.filter((sub) => sub) + $.setjson(usercfgs, $.KEY_usercfgs) + } + + return usercfgs +} + +/** + * 获取`应用订阅`缓存 + */ +function getAppSubCaches() { + return $.getjson($.KEY_app_subCaches, {}) +} + +/** + * 获取全局备份列表 + */ +function getGlobalBaks() { + let backups = $.getjson($.KEY_backups, []) + + // 处理异常数据:删除所有为 null 的备份 + if (backups.includes(null)) { + backups = backups.filter((bak) => bak) + $.setjson(backups, $.KEY_backups) + } + + return backups +} + +/** + * 获取版本清单 + */ +function getVersions() { + return $.http.get($.ver).then( + (resp) => { + try { + $.json = $.toObj(resp.body) + } catch { + $.json = {} + } + }, + () => ($.json = {}) + ) +} + +/** + * 获取应用会话 + */ +function getAppSessions() { + return $.getjson($.KEY_sessions, []) || [] +} + +/** + * 获取当前切换到哪个会话 + */ +function getCurSessions() { + return $.getjson($.KEY_cursessions, {}) || {} +} + +/** + * =================================== + * 接口类函数 + * =================================== + */ + +function getAppDatas(app) { + const datas = {} + const nulls = [null, undefined, 'null', 'undefined'] + if (app.keys && Array.isArray(app.keys)) { + app.keys.forEach((key) => { + const val = $.getdata(key) + datas[key] = nulls.includes(val) ? null : val + }) + } + if (app.settings && Array.isArray(app.settings)) { + app.settings.forEach((setting) => { + const key = setting.id + const dataval = $.getdata(key) + datas[key] = nulls.includes(dataval) ? null : dataval + + if (setting.type === 'boolean') { + setting.val = nulls.includes(dataval) + ? setting.val + : dataval === 'true' || dataval === true + } else if (setting.type === 'int') { + setting.val = dataval * 1 || setting.val + } else if (setting.type === 'checkboxes') { + if (!nulls.includes(dataval) && typeof dataval === 'string') { + setting.val = dataval ? dataval.split(',') : [] + } else { + setting.val = Array.isArray(setting.val) + ? setting.val + : setting.val.split(',') + } + } else { + setting.val = dataval || setting.val + } + + if (setting.type === 'modalSelects') { + setting.items = datas?.[setting.items] || [] + } + }) + } + return datas +} + +function dealKey(str) { + const [rootKey, delIndex] = str.split('.') + if (rootKey && rootKey.indexOf('@') > -1 && delIndex !== undefined) { + const key = rootKey.replace('@', '') + const datas = JSON.parse($.getdata(key)) + if (Array.isArray(datas) && delIndex <= datas.length - 1) { + datas.splice(delIndex, 1) + $.setdata(JSON.stringify(datas), key) + } + } +} + +async function apiSave() { + const data = $.toObj($request.body) + if (Array.isArray(data)) { + data.forEach((dat) => { + if (dat.val === null) { + dealKey(dat.key) + } else { + $.setdata(dat.val, dat.key) + } + }) + } else { + if (data.val === null) { + dealKey(data.key) + } else { + $.setdata(data.val, data.key) + } + } + + const appId = $.queries['appid'] + if (appId) { + updateCurSesssions(appId, data) + } + + $.json = getBoxData() +} + +async function apiUpdate() { + const data = $.toObj($request.body) + const path = data.path.split('.') + const val = data.val + const key = path.shift() + // 必须用 hasOwnProperty:val 为 false 时 data.val && … 会误判为跳过更新 + if (path.join('.') && Object.prototype.hasOwnProperty.call(data, 'val')) { + switch (key) { + case 'usercfgs': + const usercfgs = getUserCfgs() + update(usercfgs, path.join('.'), val) + $.setjson(usercfgs, $.KEY_usercfgs) + break + default: + break + } + } + $.json = getBoxData() +} + +async function apiAddAppSub() { + const sub = $.toObj($request.body) + // 添加订阅 + const usercfgs = getUserCfgs() + usercfgs.appsubs.push(sub) + $.setjson(usercfgs, $.KEY_usercfgs) + // 加载订阅缓存 + await reloadAppSubCache(sub.url) + $.json = getBoxData() +} + +async function apiDeleteAppSub() { + const sub = $.toObj($request.body) + // 添加订阅 + const usercfgs = getUserCfgs() + usercfgs.appsubs = usercfgs.appsubs.filter((e) => e.url !== sub.url) + $.setjson(usercfgs, $.KEY_usercfgs) + $.json = getBoxData() +} + +async function apiReloadAppSub() { + const sub = $.toObj($request.body) + if (sub) { + await reloadAppSubCache(sub.url) + } else { + await reloadAppSubCaches() + } + $.json = getBoxData() +} + +async function apiDelGlobalBak() { + const backup = $.toObj($request.body) + const backups = $.getjson($.KEY_backups, []) + const bakIdx = backups.findIndex((b) => b.id === backup.id) + if (bakIdx > -1) { + backups.splice(bakIdx, 1) + $.setdata('', backup.id) + $.setjson(backups, $.KEY_backups) + } + $.json = getBoxData() +} + +async function apiUpdateGlobalBak() { + const { id: backupId, name: backupName } = $.toObj($request.body) + const backups = $.getjson($.KEY_backups, []) + const backup = backups.find((b) => b.id === backupId) + if (backup) { + backup.name = backupName + $.setjson(backups, $.KEY_backups) + } + $.json = getBoxData() +} + +async function apiRevertGlobalBak() { + const { id: bakcupId } = $.toObj($request.body) + const backup = $.getjson(bakcupId) + if (backup) { + const { + chavy_boxjs_sysCfgs, + chavy_boxjs_sysApps, + chavy_boxjs_sessions, + chavy_boxjs_userCfgs, + chavy_boxjs_cur_sessions, + chavy_boxjs_app_subCaches, + ...datas + } = backup + $.setdata(JSON.stringify(chavy_boxjs_sessions), $.KEY_sessions) + $.setdata(JSON.stringify(chavy_boxjs_userCfgs), $.KEY_usercfgs) + $.setdata(JSON.stringify(chavy_boxjs_cur_sessions), $.KEY_cursessions) + $.setdata(JSON.stringify(chavy_boxjs_app_subCaches), $.KEY_app_subCaches) + const isNull = (val) => + [undefined, null, 'null', 'undefined', ''].includes(val) + Object.keys(datas).forEach((datkey) => + $.setdata(isNull(datas[datkey]) ? '' : `${datas[datkey]}`, datkey) + ) + } + const boxdata = getBoxData() + $.json = boxdata +} + +async function apiSaveGlobalBak() { + const backups = $.getjson($.KEY_backups, []) + const boxdata = getBoxData() + const backup = $.toObj($request.body) + const backupData = {} + backupData['chavy_boxjs_userCfgs'] = boxdata.usercfgs + backupData['chavy_boxjs_sessions'] = boxdata.sessions + backupData['chavy_boxjs_cur_sessions'] = boxdata.curSessions + backupData['chavy_boxjs_app_subCaches'] = boxdata.appSubCaches + Object.assign(backupData, boxdata.datas) + backups.push(backup) + $.setjson(backups, $.KEY_backups) + $.setjson(backupData, backup.id) + $.json = getBoxData() +} + +async function apiImpGlobalBak() { + const backups = $.getjson($.KEY_backups, []) + const backup = $.toObj($request.body) + const backupData = backup.bak + delete backup.bak + backups.push(backup) + $.setjson(backups, $.KEY_backups) + $.setjson(backupData, backup.id) + $.json = getBoxData() +} + +async function apiRunScript() { + // 取消勿扰模式 + $.isMute = false + const opts = $.toObj($request.body) + const httpapi = $.getdata('@chavy_boxjs_userCfgs.httpapi') + const ishttpapi = /.*?@.*?:[0-9]+/.test(httpapi) + let script_text = null + if (opts.isRemote) { + await $.getScript(opts.url).then((script) => (script_text = script)) + } else { + script_text = opts.script + } + if (opts.argument) { + script_text = `globalThis.$argument=\`${opts.argument}\`;${script_text}` + } + if ( + $.isSurge() && + !$.isLoon() && + !$.isShadowrocket() && + !$.isStash() && + ishttpapi + ) { + const runOpts = { timeout: opts.timeout } + await $.runScript(script_text, runOpts).then( + (resp) => ($.json = JSON.parse(resp)) + ) + } else { + const result = await new Promise((resolve) => { + $eval_env.resolve = resolve + // 避免被执行脚本误认为是 rewrite 环境 + // 所以需要 `$request = undefined` + $eval_env.request = $request + $request = undefined + // 重写 console.log, 把日志记录到 $eval_env.cached_logs + $eval_env.cached_logs = [] + console.cloned_log = console.log + console.log = (l) => { + console.cloned_log(l) + $eval_env.cached_logs.push(l) + } + // 重写脚本内的 $done, 调用 $done() 即是调用 $eval_env.resolve() + script_text = script_text.replace(/\$done/g, '$eval_env.resolve') + script_text = script_text.replace(/\$\.done/g, '$eval_env.resolve') + try { + eval(script_text) + } catch (e) { + $eval_env.cached_logs.push(e) + resolve() + } + }) + // 还原 console.log + console.log = console.cloned_log + // 还原 $request + $request = $eval_env.request + // 返回数据 + $.json = { + result, + output: $eval_env.cached_logs.join('\n') + } + } +} + +async function apiSurge() { + const opts = $.toObj($request.body) + const httpapi = $.getdata('@chavy_boxjs_userCfgs.httpapi') + const ishttpapi = /.*?@.*?:[0-9]+/.test(httpapi) + if ( + $.isSurge() && + !$.isLoon() && + !$.isShadowrocket() && + !$.isStash() && + ishttpapi + ) { + const [key, prefix] = httpapi.split('@') + opts.url = `http://${prefix}/${opts.url}` + opts.headers = { + 'X-Key': key, + 'Accept': 'application/json, text/plain, */*' + } + await new Promise((resolve) => { + $[opts.method.toLowerCase()](opts, (_, __, resp) => { + $.json = JSON.parse(resp) + resolve($.json) + }) + }) + } +} + +async function apiSaveData() { + const { key: dataKey, val: dataVal } = $.toObj($request.body) + $.setdata(dataVal, dataKey) + $.json = { + key: dataKey, + val: $.getdata(dataKey) + } +} + +/** + * =================================== + * 工具类函数 + * =================================== + */ + +function reloadAppSubCache(url) { + // 地址后面拼时间缀, 避免 GET 缓存 + const requrl = `${url}${ + url.includes('?') ? '&' : '?' + }_=${new Date().getTime()}` + return $.http.get(requrl).then((resp) => { + try { + const subcaches = getAppSubCaches() + subcaches[url] = $.toObj(resp.body) + subcaches[url].updateTime = new Date() + // 仅缓存存在 id 的订阅 + Object.keys(subcaches).forEach((key) => { + if (!subcaches[key].hasOwnProperty('id')) { + delete subcaches[key] + } + }) + $.setjson(subcaches, $.KEY_app_subCaches) + $.log(`更新订阅, 成功! ${url}`) + } catch (e) { + $.logErr(e) + $.log(`更新订阅, 失败! ${url}`) + } + }) +} + +function update(obj, path, value) { + const keys = path.split('.') + let current = obj + + for (let i = 0; i < keys.length - 1; i++) { + if (!current[keys[i]]) { + current[keys[i]] = {} + } + current = current[keys[i]] + } + + current[keys[keys.length - 1]] = value +} + +// 自定义并发控制函数 +async function limitConcurrency(tasks, limit) { + const results = []; + const executing = []; + + for (const task of tasks) { + const promise = task(); // 执行任务 + results.push(promise); + + if (executing.length >= limit) { + await Promise.race(executing); + } + + executing.push(promise); + promise.then(() => { + const index = executing.indexOf(promise); + if (index !== -1) executing.splice(index, 1); + }).catch(() => { + const index = executing.indexOf(promise); + if (index !== -1) executing.splice(index, 1); + }); + } + + return Promise.all(results); +} + +async function reloadAppSubCaches() { + $.msg($.name, '更新订阅: 开始!'); + const reloadActs = []; + const usercfgs = getUserCfgs(); + + // 收集所有任务(函数形式) + usercfgs.appsubs.forEach((sub) => { + reloadActs.push(() => reloadAppSubCache(sub.url)); // 存储函数而不是立即执行的 Promise + }); + + // 使用并发限制执行任务 + await limitConcurrency(reloadActs, 20); // 限制并发数为 20 + + $.log(`全部订阅, 完成!`); + const endTime = new Date().getTime(); + const costTime = (endTime - $.startTime) / 1000; + $.msg($.name, `更新订阅: 完成! 🕛 ${costTime} 秒`); +} + +function upgradeUserData() { + const usercfgs = getUserCfgs() + // 如果存在`usercfgs.appsubCaches`则需要升级数据 + const isNeedUpgrade = !!usercfgs.appsubCaches + if (isNeedUpgrade) { + // 迁移订阅缓存至独立的持久化空间 + $.setjson(usercfgs.appsubCaches, $.KEY_app_subCaches) + // 移除用户偏好中的订阅缓存 + delete usercfgs.appsubCaches + usercfgs.appsubs.forEach((sub) => { + delete sub._raw + delete sub.apps + delete sub.isErr + delete sub.updateTime + }) + } + if (isNeedUpgrade) { + $.setjson(usercfgs, $.KEY_usercfgs) + } +} + +/** + * 升级备份数据 + * + * 升级前: 把所有备份都存到一个持久化空间 + * 升级后: 把每个备份都独立存到一个空间, `$.KEY_backups` 仅记录必要的数据索引 + */ +function upgradeGlobalBaks() { + let oldbaks = $.getdata($.KEY_globalBaks) + let newbaks = $.getjson($.KEY_backups, []) + const isEmpty = (bak) => [undefined, null, ''].includes(bak) + const isExistsInNew = (backupId) => newbaks.find((bak) => bak.id === backupId) + + // 存在旧备份数据时, 升级备份数据格式 + if (!isEmpty(oldbaks)) { + oldbaks = JSON.parse(oldbaks) + oldbaks.forEach((bak) => { + if (isEmpty(bak)) return + if (isEmpty(bak.bak)) return + if (isExistsInNew(bak.id)) return + + console.log(`正在迁移: ${bak.name}`) + const backupId = bak.id + const backupData = bak.bak + + // 删除旧的备份数据, 仅保留索引信息 + delete bak.bak + newbaks.push(bak) + + // 提取旧备份数据, 存入独立的持久化空间 + $.setjson(backupData, backupId) + }) + $.setjson(newbaks, $.KEY_backups) + } + + // 清空所有旧备份的数据 + $.setdata('', $.KEY_globalBaks) +} + +function updateCurSesssions(appId, data) { + if (!appId) { + console.log(`[updateCurSesssions] 跳过! 没有指定 appId!`) + return + } + + const curSessions = getCurSessions() + const curSessionId = curSessions[appId] + if (!curSessionId) { + console.log( + `[updateCurSesssions] 跳过! 应用 [${appId}] 找不到当前会话, 请先应用会话!` + ) + return + } + + const sessions = getAppSessions() + const session = sessions.find((session) => session.id === curSessionId) + if (!session) { + console.log( + `[updateCurSesssions] 跳过! 应用 [${appId}] 找不到当前会话, 请先应用会话!` + ) + return + } + + session.datas = data + $.setjson(sessions, $.KEY_sessions) +} + +/** + * =================================== + * 结束类函数 + * =================================== + */ +function doneBox() { + // 记录当前使用哪个域名访问 + $.setdata(getHost($request.url), $.KEY_boxjs_host) + if ($.isOptions) doneOptions() + else if ($.isPage) donePage() + else if ($.isQuery) doneQuery() + else if ($.isApi) doneApi() + else $.done() +} + +function getBaseDoneHeaders(mixHeaders = {}) { + return Object.assign( + { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'POST,GET,OPTIONS,PUT,DELETE', + 'Access-Control-Allow-Headers': + 'Origin, X-Requested-With, Content-Type, Accept' + }, + mixHeaders + ) +} + +function getHtmlDoneHeaders() { + return getBaseDoneHeaders({ + 'Content-Type': 'text/html;charset=UTF-8' + }) +} +function getJsonDoneHeaders() { + return getBaseDoneHeaders({ + 'Content-Type': 'application/json; charset=utf-8' + }) +} + +function doneOptions() { + const headers = getBaseDoneHeaders() + if ($.isQuanX()) $.done({ headers }) + else $.done({ response: { headers } }) +} + +function donePage() { + const headers = getHtmlDoneHeaders() + if ($.isQuanX()) $.done({ status: 'HTTP/1.1 200', headers, body: $.html }) + else $.done({ response: { status: 200, headers, body: $.html } }) +} + +function doneQuery() { + $.json = $.toStr($.json) + const headers = getJsonDoneHeaders() + if ($.isQuanX()) $.done({ status: 'HTTP/1.1 200', headers, body: $.json }) + else $.done({ response: { status: 200, headers, body: $.json } }) +} + +function doneApi() { + $.json = $.toStr($.json) + const headers = getJsonDoneHeaders() + if ($.isQuanX()) $.done({ status: 'HTTP/1.1 200', headers, body: $.json }) + else $.done({ response: { status: 200, headers, body: $.json } }) +} + +/** + * EnvJs + */ +//prettier-ignore +function Env(e,t){class s{constructor(e){this.env=e}send(e,t="GET"){e="string"==typeof e?{url:e}:e;let s=this.get;"POST"===t&&(s=this.post);const i=new Promise((t,i)=>{s.call(this,e,(e,s,o)=>{e?i(e):t(s)})});return e.timeout?((e,t=1e3)=>Promise.race([e,new Promise((e,s)=>{setTimeout(()=>{s(new Error("请求超时"))},t)})]))(i,e.timeout):i}get(e){return this.send.call(this.env,e)}post(e){return this.send.call(this.env,e,"POST")}}return new class{constructor(e,t){this.logLevels={debug:0,info:1,warn:2,error:3},this.logLevelPrefixs={debug:"[DEBUG] ",info:"[INFO] ",warn:"[WARN] ",error:"[ERROR] "},this.logLevel="info",this.name=e,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,t),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof Egern?"Egern":"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}isEgern(){return"Egern"===this.getEnv()}toObj(e,t=null){try{return JSON.parse(e)}catch{return t}}toStr(e,t=null,...s){try{return JSON.stringify(e,...s)}catch{return t}}getjson(e,t){let s=t;if(this.getdata(e))try{s=JSON.parse(this.getdata(e))}catch{}return s}setjson(e,t){try{return this.setdata(JSON.stringify(e),t)}catch{return!1}}getScript(e){return new Promise(t=>{this.get({url:e},(e,s,i)=>t(i))})}runScript(e,t){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let o=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");o=o?1*o:20,o=t&&t.timeout?t.timeout:o;const[r,a]=i.split("@"),n={url:`http://${a}/v1/scripting/evaluate`,body:{script_text:e,mock_type:"cron",timeout:o},headers:{"X-Key":r,Accept:"*/*"},policy:"DIRECT",timeout:o};this.post(n,(e,t,i)=>s(i))}).catch(e=>this.logErr(e))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const e=this.path.resolve(this.dataFile),t=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(e),i=!s&&this.fs.existsSync(t);if(!s&&!i)return{};{const i=s?e:t;try{return JSON.parse(this.fs.readFileSync(i))}catch(e){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const e=this.path.resolve(this.dataFile),t=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(e),i=!s&&this.fs.existsSync(t),o=JSON.stringify(this.data);s?this.fs.writeFileSync(e,o):i?this.fs.writeFileSync(t,o):this.fs.writeFileSync(e,o)}}lodash_get(e,t,s=void 0){const i=t.replace(/\[(\d+)\]/g,".$1").split(".");let o=e;for(const e of i)if(o=Object(o)[e],void 0===o)return s;return o}lodash_set(e,t,s){return Object(e)!==e||(Array.isArray(t)||(t=t.toString().match(/[^.[\]]+/g)||[]),t.slice(0,-1).reduce((e,s,i)=>Object(e[s])===e[s]?e[s]:e[s]=(Math.abs(t[i+1])|0)===+t[i+1]?[]:{},e)[t[t.length-1]]=s),e}getdata(e){let t=this.getval(e);if(/^@/.test(e)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(e),o=s?this.getval(s):"";if(o)try{const e=JSON.parse(o);t=e?this.lodash_get(e,i,""):t}catch(e){t=""}}return t}setdata(e,t){let s=!1;if(/^@/.test(t)){const[,i,o]=/^@(.*?)\.(.*?)$/.exec(t),r=this.getval(i),a=i?"null"===r?null:r||"{}":"{}";try{const t=JSON.parse(a);this.lodash_set(t,o,e),s=this.setval(JSON.stringify(t),i)}catch(t){const r={};this.lodash_set(r,o,e),s=this.setval(JSON.stringify(r),i)}}else s=this.setval(e,t);return s}getval(e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":return $persistentStore.read(e);case"Quantumult X":return $prefs.valueForKey(e);case"Node.js":return this.data=this.loaddata(),this.data[e];default:return this.data&&this.data[e]||null}}setval(e,t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":return $persistentStore.write(e,t);case"Quantumult X":return $prefs.setValueForKey(e,t);case"Node.js":return this.data=this.loaddata(),this.data[t]=e,this.writedata(),!0;default:return this.data&&this.data[t]||null}}initGotEnv(e){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,e&&(e.headers=e.headers?e.headers:{},e&&(e.headers=e.headers?e.headers:{},void 0===e.headers.cookie&&void 0===e.headers.Cookie&&void 0===e.cookieJar&&(e.cookieJar=this.ckjar)))}get(e,t=()=>{}){switch(e.headers&&(delete e.headers["Content-Type"],delete e.headers["Content-Length"],delete e.headers["content-type"],delete e.headers["content-length"]),e.params&&(e.url+="?"+this.queryStr(e.params)),void 0===e.followRedirect||e.followRedirect||((this.isSurge()||this.isLoon())&&(e["auto-redirect"]=!1),this.isQuanX()&&(e.opts?e.opts.redirection=!1:e.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":default:this.isSurge()&&this.isNeedRewrite&&(e.headers=e.headers||{},Object.assign(e.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(e,(e,s,i)=>{!e&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),t(e,s,i)});break;case"Quantumult X":this.isNeedRewrite&&(e.opts=e.opts||{},Object.assign(e.opts,{hints:!1})),$task.fetch(e).then(e=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=e;t(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)},e=>t(e&&e.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(e),this.got(e).on("redirect",(e,t)=>{try{if(e.headers["set-cookie"]){const s=e.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),t.cookieJar=this.ckjar}}catch(e){this.logErr(e)}}).then(e=>{const{statusCode:i,statusCode:o,headers:r,rawBody:a}=e,n=s.decode(a,this.encoding);t(null,{status:i,statusCode:o,headers:r,rawBody:a,body:n},n)},e=>{const{message:i,response:o}=e;t(i,o,o&&s.decode(o.rawBody,this.encoding))})}}post(e,t=()=>{}){const s=e.method?e.method.toLocaleLowerCase():"post";switch(e.body&&e.headers&&!e.headers["Content-Type"]&&!e.headers["content-type"]&&(e.headers["content-type"]="application/x-www-form-urlencoded"),e.headers&&(delete e.headers["Content-Length"],delete e.headers["content-length"]),void 0===e.followRedirect||e.followRedirect||((this.isSurge()||this.isLoon())&&(e["auto-redirect"]=!1),this.isQuanX()&&(e.opts?e.opts.redirection=!1:e.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":default:this.isSurge()&&this.isNeedRewrite&&(e.headers=e.headers||{},Object.assign(e.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](e,(e,s,i)=>{!e&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),t(e,s,i)});break;case"Quantumult X":e.method=s,this.isNeedRewrite&&(e.opts=e.opts||{},Object.assign(e.opts,{hints:!1})),$task.fetch(e).then(e=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=e;t(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)},e=>t(e&&e.error||"UndefinedError"));break;case"Node.js":let i=require("iconv-lite");this.initGotEnv(e);const{url:o,...r}=e;this.got[s](o,r).then(e=>{const{statusCode:s,statusCode:o,headers:r,rawBody:a}=e,n=i.decode(a,this.encoding);t(null,{status:s,statusCode:o,headers:r,rawBody:a,body:n},n)},e=>{const{message:s,response:o}=e;t(s,o,o&&i.decode(o.rawBody,this.encoding))})}}time(e,t=null){const s=t?new Date(t):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(e)&&(e=e.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let t in i)new RegExp("("+t+")").test(e)&&(e=e.replace(RegExp.$1,1==RegExp.$1.length?i[t]:("00"+i[t]).substr((""+i[t]).length)));return e}queryStr(e){let t="";for(const s in e){let i=e[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),t+=`${s}=${i}&`)}return t=t.substring(0,t.length-1),t}msg(t=e,s="",i="",o={}){const r=e=>{const{$open:t,$copy:s,$media:i,$mediaMime:o}=e;switch(typeof e){case void 0:return e;case"string":switch(this.getEnv()){case"Surge":case"Stash":case"Egern":default:return{url:e};case"Loon":case"Shadowrocket":return e;case"Quantumult X":return{"open-url":e};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":case"Egern":default:{const r={};let a=e.openUrl||e.url||e["open-url"]||t;a&&Object.assign(r,{action:"open-url",url:a});let n=e["update-pasteboard"]||e.updatePasteboard||s;n&&Object.assign(r,{action:"clipboard",text:n});let h=e.mediaUrl||e["media-url"]||i;if(h){let e,t;if(h.startsWith("http"));else if(h.startsWith("data:")){const[s]=h.split(";"),[,i]=h.split(",");e=i,t=s.replace("data:","")}else{e=h,t=(e=>{const t={JVBERi0:"application/pdf",R0lGODdh:"image/gif",R0lGODlh:"image/gif",iVBORw0KGgo:"image/png","/9j/":"image/jpg"};for(var s in t)if(0===e.indexOf(s))return t[s];return null})(h)}Object.assign(r,{"media-url":h,"media-base64":e,"media-base64-mime":o??t})}return Object.assign(r,{"auto-dismiss":e["auto-dismiss"],sound:e.sound}),r}case"Loon":{const s={};let o=e.openUrl||e.url||e["open-url"]||t;o&&Object.assign(s,{openUrl:o});let r=e.mediaUrl||e["media-url"]||i;return r&&Object.assign(s,{mediaUrl:r}),console.log(JSON.stringify(s)),s}case"Quantumult X":{const o={};let r=e["open-url"]||e.url||e.openUrl||t;r&&Object.assign(o,{"open-url":r});let a=e.mediaUrl||e["media-url"]||i;a&&Object.assign(o,{"media-url":a});let n=e["update-pasteboard"]||e.updatePasteboard||s;return n&&Object.assign(o,{"update-pasteboard":n}),console.log(JSON.stringify(o)),o}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":default:$notification.post(t,s,i,r(o));break;case"Quantumult X":$notify(t,s,i,r(o));case"Node.js":}if(!this.isMuteLog){let e=["","==============📣系统通知📣=============="];e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n")),this.logs=this.logs.concat(e)}}debug(...e){this.logLevels[this.logLevel]<=this.logLevels.debug&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.debug}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}info(...e){this.logLevels[this.logLevel]<=this.logLevels.info&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.info}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}warn(...e){this.logLevels[this.logLevel]<=this.logLevels.warn&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.warn}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}error(...e){this.logLevels[this.logLevel]<=this.logLevels.error&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.error}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}log(...e){e.length>0&&(this.logs=[...this.logs,...e]),console.log(e.map(e=>e??String(e)).join(this.logSeparator))}logErr(e,t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,t,e);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,t,void 0!==e.message?e.message:e,e.stack)}}wait(e){return new Promise(t=>setTimeout(t,e))}done(e={}){const t=((new Date).getTime()-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${t} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":case"Quantumult X":default:$done(e);break;case"Node.js":process.exit(1)}}}(e,t)} diff --git a/box/chavy.boxjs.json b/box/chavy.boxjs.json new file mode 100644 index 000000000..5d5045658 --- /dev/null +++ b/box/chavy.boxjs.json @@ -0,0 +1,639 @@ +{ + "id": "chavyleung.app.sub", + "name": "chavyleung应用订阅", + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519?s=460&u=392a19e85465abbcb1791c9b8b32184a16e6795e&v=4", + "repo": "https://github.com/chavyleung/scripts", + "apps": [ + { + "id": "10000", + "name": "10000", + "keys": ["chavy_signheader_10000"], + "settings": [ + { + "id": "chavy_mobile_10000", + "name": "手机号码", + "val": "", + "type": "textarea", + "placeholder": "18918920000,\n18918920000", + "autoGrow": true, + "rows": 5, + "desc": "以英文逗号分隔多个号码, 可加回车" + } + ], + "author": "@wangfei021325, @chavyleung", + "repo": "https://github.com/chavyleung/scripts/blob/master/10000/10000.js", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/10000.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/10000.png" + ] + }, + { + "id": "10010", + "name": "10010", + "keys": [ + "chavy_tokenurl_10010", + "chavy_tokenheader_10010", + "chavy_signurl_10010", + "chavy_signheader_10010", + "chavy_loginlotteryurl_10010", + "chavy_loginlotteryheader_10010", + "chavy_findlotteryurl_10010", + "chavy_findlotteryheader_10010" + ], + "settings": [ + { + "id": "chavy_golottery_10010", + "name": "天天抽奖", + "val": true, + "type": "boolean", + "desc": "天天抽奖开关" + }, + { + "id": "chavy_gosign_10010", + "name": "签到", + "val": true, + "type": "boolean", + "desc": "签到开关" + } + ], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/10010", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/10010.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/10010.png" + ] + }, + { + "id": "BAIDU", + "name": "百度签到", + "keys": ["chavy_cookie_tieba"], + "settings": [ + { + "id": "CFG_tieba_isOrderBars", + "name": "按连签排序", + "val": false, + "type": "boolean", + "desc": "默认按经验排序" + }, + { + "id": "CFG_tieba_maxShowBars", + "name": "每页显示数", + "val": 15, + "type": "number", + "desc": "每页最显示多少个吧信息" + }, + { + "id": "CFG_tieba_maxSignBars", + "name": "每次并发", + "val": 5, + "type": "number", + "desc": "每次并发签到多少个吧" + }, + { + "id": "CFG_tieba_signWaitTime", + "name": "并发间隔 (毫秒)", + "val": 2000, + "type": "number", + "desc": "每次并发间隔时间" + } + ], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/tieba", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/tieba/tieba.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/baidu.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/baidu.png" + ] + }, + { + "id": "pagoda", + "name": "百果园", + "keys": ["chavy_sign_pagoda"], + "author": "@chavyleung", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/pagoda/pagoda.js", + "repo": "https://github.com/chavyleung/scripts/blob/master/pagoda", + "icons": [ + "https://raw.githubusercontent.com/58xinian/icon/master/pagoda_mini.png", + "https://raw.githubusercontent.com/58xinian/icon/master/pagoda.png" + ] + }, + { + "id": "fandeng", + "name": "樊登读书", + "keys": [ + "senku_signurl_pandeng", + "senku_signheader_pandeng", + "senku_signbody_pandeng" + ], + "author": "@gideonsenku", + "repo": "https://github.com/chavyleung/scripts/tree/master/fandeng", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/fandeng/fandeng.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/fandeng.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/fandeng.png" + ] + }, + { + "id": "gdoil", + "name": "加油广东", + "keys": ["chavy_signurl_gdoil", "chavy_signheader_gdoil"], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/gdoil", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/gdoil/gdoil.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/gdoil.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/gdoil.png" + ] + }, + { + "id": "JD618", + "name": "京东618", + "keys": ["chavy_url_jd816", "chavy_body_jd816", "chavy_headers_jd816"], + "settings": [ + { + "id": "CFG_618_radomms_min", + "name": "最小随机等待 (毫秒)", + "val": 2000, + "type": "text", + "desc": "在任务默认的等待时间基础上,再增加的随机等待时间!" + }, + { + "id": "CFG_618_radomms_max", + "name": "最大随机等待 (毫秒)", + "val": 5000, + "type": "text", + "desc": "在任务默认的等待时间基础上,再增加的随机等待时间!" + }, + { + "id": "CFG_618_isSignShop", + "name": "商店签到", + "val": true, + "type": "boolean", + "desc": "71 家商店, 如果每天都签不上, 可以关掉了! 默认: true" + }, + { + "id": "CFG_618_isJoinBrand", + "name": "品牌会员", + "val": false, + "type": "boolean", + "desc": "25 个品牌, 会自动加入品牌会员! 默认: true" + }, + { + "id": "CFG_BOOM_times_JD618", + "name": "炸弹次数", + "val": 1, + "type": "text", + "desc": "总共发送多少次炸弹! 默认: 1" + }, + { + "id": "CFG_BOOM_interval_JD618", + "name": "炸弹间隔 (毫秒)", + "val": 100, + "type": "text", + "desc": "每次间隔多少毫秒! 默认: 100" + } + ], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/jd", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/jd.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/jd.png" + ] + }, + { + "id": "chavyleung.mgtv", + "name": "芒果TV", + "keys": ["chavy_signurl_mgtv", "chavy_signheader_mgtv"], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/blob/master/mgtv/mgtv.js", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/mgtv/mgtv.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/mgtv.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/mgtv.png" + ] + }, + { + "id": "chavyleung.meituan", + "name": "美团", + "keys": [ + "chavy_tokenurl_meituan", + "chavy_tokenheader_meituan", + "chavy_signurl_meituan", + "chavy_signheader_meituan", + "chavy_signbody_meituan" + ], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/blob/master/meituan/meituan.js", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/meituan/meituan.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/meituan.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/meituan.png" + ] + }, + { + "id": "qmkg", + "name": "全民K歌", + "keys": [ + "senku_signurl_qmkg", + "senku_signheader_qmkg", + "senku_signbody_qmkg" + ], + "author": "@gideonsenku", + "repo": "https://github.com/chavyleung/scripts/tree/master/qmkg", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/qmkg/qmkg.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/qmkg.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/qmkg.png" + ] + }, + { + "id": "smzdm", + "name": "什么值得买", + "keys": ["chavy_cookie_smzdm"], + "author": "@wangfei021325, @chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/smzdm", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/smzdm/smzdm.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/smzdm.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/smzdm.png" + ] + }, + { + "id": "sfexpress", + "name": "顺丰速运", + "keys": ["chavy_login_sfexpress"], + "author": "@wangfei021325, @chavyleung", + "repo": "https://github.com/chavyleung/scripts/blob/master/sfexpress", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/sfexpress.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/sfexpress.png" + ] + }, + { + "id": "flyertea", + "name": "飞客茶馆", + "keys": ["chavy_cookie_flyertea", "chavy_token_flyertea"], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/flyertea", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/flyertea/flyertea.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/flyertea.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/flyertea.png" + ] + }, + { + "id": "chavyleung.suning", + "name": "苏宁易购", + "settings": [ + { + "id": "chavy_logflag_suning", + "name": "响应日志", + "val": false, + "type": "boolean", + "desc": "是否输出响应返回体" + } + ], + "keys": [ + "chavy_login_url_suning", + "chavy_login_body_suning", + "chavy_login_header_suning", + "chavy_sign_url_suning", + "chavy_sign_header_suning", + "chavy_signweb_url_suning", + "snyg_userTokenKey", + "chavy_signweb_header_suning", + "chavy_signgame_url_suning", + "chavy_signgame_header_suning", + "chavy_signgetgame_url_suning", + "chavy_signgetgame_header_suning" + ], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/blob/master/suning/suning.js", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/suning.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/suning.png" + ] + }, + { + "id": "videoqq", + "name": "腾讯视频", + "keys": [ + "chavy_cookie_videoqq", + "chavy_auth_url_videoqq", + "chavy_auth_header_videoqq", + "chavy_msign_url_videoqq", + "chavy_msign_header_videoqq" + ], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/videoqq", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/videoqq.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/videoqq.png" + ] + }, + { + "id": "wanda", + "name": "万达电影", + "keys": ["senku_wanda_mi_"], + "author": "@gideonsenku", + "repo": "https://github.com/chavyleung/scripts/tree/master/wanda", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/wanda/wanda.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/wanda.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/wanda.png" + ] + }, + { + "id": "ithome", + "name": "IT之家", + "keys": ["senku_ithome_userHash"], + "author": "@gideonsenku", + "repo": "https://github.com/chavyleung/scripts/tree/master/ithome", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/ithome/ithome.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/ithome.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/ithome.png" + ] + }, + { + "id": "nfzm", + "name": "南方周末", + "keys": ["senku_nfzm_url"], + "author": "@gideonsenku", + "repo": "https://github.com/chavyleung/scripts/tree/master/nfzm", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/nfzm/nfzm.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/nfzm.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/nfzm.png" + ] + }, + { + "id": "NeteaseNews", + "name": "网易新闻", + "keys": ["chavy_cookie_neteasenews", "chavy_body_neteasenews"], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/neteasenews", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/neteasenews.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/neteasenews.png" + ] + }, + { + "id": "NeteaseMusic", + "name": "网易云音乐", + "keys": ["chavy_cookie_neteasemusic"], + "settings": [ + { + "id": "CFG_neteasemusic_retryCnt", + "name": "重试次数", + "val": 10, + "type": "text", + "desc": "一直尝试签到直至出现“重复签到”标识!" + }, + { + "id": "CFG_neteasemusic_retryInterval", + "name": "重试间隔 (毫秒)", + "val": 500, + "type": "text", + "desc": "每次重试间隔时间 (毫秒)!" + } + ], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/neteasemusic", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/neteasemusic/neteasemusic.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/neteasemusic.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/neteasemusic.png" + ] + }, + { + "id": "feng", + "name": "威锋网", + "keys": ["chavy_login_feng"], + "author": "@wangfei021325, @chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/feng", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/feng.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/feng.png" + ] + }, + { + "id": "NoteYoudao", + "name": "有道云笔记", + "keys": [ + "chavy_signurl_noteyoudao", + "chavy_signbody_noteyoudao", + "chavy_signheaders_noteyoudao" + ], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/noteyoudao", + "url": "https://apps.apple.com/cn/app/有道云笔记-扫描王版/id450748070", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/noteyoudao/noteyoudao.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/noteyoudao.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/noteyoudao.png" + ], + "tasks": [{ "cron": "3 0 * * *", "script": "noteyoudao.js" }], + "rewrites": [ + { + "type": "request", + "pattern": "^https://note.youdao.com/yws/mapi/user?method=checkin", + "script": "noteyoudao.cookie.js", + "body": true + } + ] + }, + { + "id": "zxhc", + "name": "智行火车票", + "keys": [ + "senku_signurl_zxhc", + "senku_signheader_zxhc", + "senku_signbody_zxhc" + ], + "author": "@gideonsenku", + "repo": "https://github.com/chavyleung/scripts/tree/master/zxhc", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/zxhc/zxhc.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/zxhc.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/zxhc.png" + ] + }, + { + "id": "tongcheng-trip", + "name": "同程旅行", + "keys": ["tongcheng_trip_signheader"], + "author": "@gideonsenku", + "repo": "https://github.com/chavyleung/scripts/tree/master/tongcheng-trip", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/tongcheng-trip/tongcheng-trip.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/tongcheng.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/tongcheng.png" + ] + }, + { + "id": "AcFun", + "name": "AcFun", + "keys": ["chavy_cookie_acfun", "chavy_token_acfun"], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/acfun", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/acfun/acfun.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/acfun.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/acfun.png" + ] + }, + { + "id": "ApkTw", + "name": "ApkTw", + "keys": ["chavy_cookie_apktw"], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/apktw", + "url": "https://apk.tw/", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/apktw/apktw.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/apktw.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/apktw.png" + ], + "tasks": [{ "cron": "3 0 * * *", "script": "apktw.js" }], + "rewrites": [ + { + "type": "request", + "pattern": "^https://apk.tw/member.php(.*?)action=login", + "script": "apktw.cookie.js", + "body": true + } + ] + }, + { + "id": "chavyleung.bilibili.live", + "name": "bilibili直播", + "keys": ["chavy_cookie_bilibili"], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/blob/master/bilibili/bilibili.js", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/bilibili.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/bilibili.png" + ] + }, + { + "id": "V2EX", + "name": "V2EX", + "keys": ["chavy_cookie_v2ex"], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/v2ex", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/v2ex/v2ex.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/v2ex.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/v2ex.png" + ] + }, + { + "id": "WPS", + "name": "WPS", + "keys": ["chavy_signhomeurl_wps", "chavy_signhomeheader_wps"], + "settings": [ + { + "id": "CFG_wps_inviteTime", + "name": "邀请间隔 (毫秒)", + "val": 2000, + "type": "number", + "desc": "每次邀请间隔时间" + } + ], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/wps", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/wps/wps.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/wps.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/wps.png" + ] + }, + { + "id": "ximalaya", + "name": "喜马拉雅", + "keys": ["chavy_cookie_ximalaya"], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/ximalaya", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/ximalaya.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/ximalaya.png" + ], + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/ximalaya/ximalaya.js" + }, + { + "id": "everphoto", + "name": "时光相册", + "keys": ["chavy_sign_url_everphoto", "chavy_sign_header_everphoto"], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/tree/master/everphoto", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/everphoto.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/everphoto.png" + ], + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/everphoto/everphoto.js" + }, + { + "id": "testflight", + "name": "TestFlight", + "keys": ["boxapp_testflight_har"], + "settings": [ + { + "id": "boxapp_testflight_app", + "name": "应用编号", + "val": "", + "type": "textarea", + "placeholder": "McBV96Wi,lNmLTx8d,ZfyeFB1S,srPJRks9,uEXBDwt2", + "autoGrow": true, + "rows": 5, + "desc": "以英文逗号分隔多个号码" + } + ], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts/blob/master/testflight", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/testflight/testflight.js", + "icons": [ + "https://raw.githubusercontent.com/githubdulong/Script/master/Images/testflight.png", + "https://raw.githubusercontent.com/githubdulong/Script/master/Images/testflight.png" + ] + }, + { + "id": "follow", + "name": "follow", + "keys": ["follow_csrfToken", "follow_cookie"], + "settings": [ + { + "id": "follow_csrfToken", + "name": "csrfToken", + "val": "", + "type": "text", + "desc": "请输入follow的csrfToken" + }, + { + "id": "follow_cookie", + "name": "cookie", + "val": "", + "type": "text", + "desc": "请输入follow的cookie" + } + ], + "author": "@gideonsenku", + "repo": "https://github.com/chavyleung/scripts/tree/master/follow", + "script": "https://raw.githubusercontent.com/chavyleung/scripts/master/follow/follow.js", + "icons": [ + "https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/follow.png", + "https://raw.githubusercontent.com/Orz-3/mini/master/Color/follow.png" + ] + } + ] +} diff --git a/box/chavy.boxjs.test.json b/box/chavy.boxjs.test.json new file mode 100644 index 000000000..c8b33236b --- /dev/null +++ b/box/chavy.boxjs.test.json @@ -0,0 +1,29 @@ +{ + "id": "chavyleung.app.test.sub", + "name": "测试一键订阅 (请自行删除)", + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519?s=460&u=392a19e85465abbcb1791c9b8b32184a16e6795e&v=4", + "repo": "https://github.com/chavyleung/scripts", + "onInstall": { + "title": "安装确认", + "message": "本订阅包含重写资源, 是否需要自动安装?", + "install": { + "QuanX": "quantumult-x:///add-resource?remote-resource=%7B%22rewrite_remote%22%3A%5B%22https%3A%2F%2Fgithub.com%2Fchavyleung%2Fscripts%2Fraw%2Fmaster%2Fbox%2Frewrite%2Fboxjs.rewrite.quanx.conf%2Ctag%3Dboxjs%22%5D%7D", + "Loon": "loon://import?plugin=https://raw.githubusercontent.com/chavyleung/scripts/master/box/rewrite/boxjs.rewrite.loon.plugin" + } + }, + "apps": [ + { + "id": "chavy_test_sub", + "name": "测试应用 (请删除)", + "keys": [], + "settings": [], + "author": "@chavyleung", + "repo": "https://github.com/chavyleung/scripts", + "icons": [ + "https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxSetting.mini.png", + "https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxSetting.png" + ] + } + ] +} diff --git a/box/icons/BoxJs.dark.png b/box/icons/BoxJs.dark.png new file mode 100644 index 000000000..fd509f7ab Binary files /dev/null and b/box/icons/BoxJs.dark.png differ diff --git a/box/icons/BoxJs.light.png b/box/icons/BoxJs.light.png new file mode 100644 index 000000000..d8ac3c2e6 Binary files /dev/null and b/box/icons/BoxJs.light.png differ diff --git a/box/icons/BoxJs.png b/box/icons/BoxJs.png new file mode 100644 index 000000000..c4d3f5876 Binary files /dev/null and b/box/icons/BoxJs.png differ diff --git a/box/icons/BoxSetting.mini.png b/box/icons/BoxSetting.mini.png new file mode 100644 index 000000000..424f3b448 Binary files /dev/null and b/box/icons/BoxSetting.mini.png differ diff --git a/box/icons/BoxSetting.png b/box/icons/BoxSetting.png new file mode 100644 index 000000000..563ee3ab2 Binary files /dev/null and b/box/icons/BoxSetting.png differ diff --git a/box/icons/BoxSwitcher.mini.png b/box/icons/BoxSwitcher.mini.png new file mode 100644 index 000000000..be8ada904 Binary files /dev/null and b/box/icons/BoxSwitcher.mini.png differ diff --git a/box/icons/BoxSwitcher.png b/box/icons/BoxSwitcher.png new file mode 100644 index 000000000..0de496787 Binary files /dev/null and b/box/icons/BoxSwitcher.png differ diff --git a/box/release/box.release.json b/box/release/box.release.json new file mode 100644 index 000000000..dddaa894e --- /dev/null +++ b/box/release/box.release.json @@ -0,0 +1,2995 @@ +{ + "releases": [ + { + "version": "0.19.29", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "feat(boxjs): 顶部提示 iOS 客户端 Relay", + "notes": [ + { + "name": "功能", + "descs": ["主页顶部新增可关闭提示条,引导使用 iOS 原生客户端 Relay (TestFlight: https://testflight.apple.com/join/2yES8TuF)"] + } + ] + }, + { + "version": "0.19.28", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 同步 chavy.boxjs.js 内嵌 Env 至最新版本", + "notes": [ + { + "name": "修复", + "descs": ["同步 chavy.boxjs.js 内嵌 Env 函数,补全 Egern 环境检测及所有相关分支"] + } + ] + }, + { + "version": "0.19.27", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "feat(boxjs): 适配 Egern 代理工具", + "notes": [ + { + "name": "功能", + "descs": ["Env.js 新增 Egern 代理工具适配,支持持久化存储、HTTP 请求、系统通知等完整功能"] + } + ] + }, + { + "version": "0.19.26", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 保存设置时 val 为 false 仍应写入", + "notes": [ + { + "name": "修复", + "descs": ["保存路径数据时用 hasOwnProperty 判断 val,避免 false 被当作未传值而跳过更新"] + } + ] + }, + { + "version": "0.19.25", + "tags": ["beta"], + "author": "@id77", + "msg": "feat(boxjs): 会话支持仅使用和关联使用", + "notes": [ + { + "name": "优化", + "descs": ["仅使用会话数据,应用设置修改保存不更新原会话;关联使用会话数据,应用设置修改保存会更新原会话"] + } + ] + }, + { + "version": "0.19.24", + "tags": ["beta"], + "author": "@id77", + "msg": "feat(boxjs): isEditFavApp 只在主页才显示", + "notes": [ + { + "name": "优化", + "descs": ["悬浮按钮的收藏编辑功能只在主页才显示"] + } + ] + }, + { + "version": "0.19.23", + "tags": ["beta"], + "author": "@id77", + "msg": "feat(boxjs): 添加应用设置固定保存按钮", + "notes": [ + { + "name": "功能", + "descs": ["应用设置表单数据过多时,滚动到应用设置底部才能保存,添加应用设置固定保存按钮方便保存"] + } + ] + }, + { + "version": "0.19.22", + "tags": ["beta"], + "author": "@id77", + "msg": "fix(boxjs): 会话对话框修改&关闭功能", + "notes": [ + { + "name": "修复", + "descs": ["修复点修改A会话显示会话B的情况,每一个会话修改表单都应该有独立的控制key"] + } + ] + }, + { + "version": "0.19.21", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 订阅更新问题", + "notes": [ + { + "name": "修复", + "descs": ["订阅更新问题"] + } + ] + }, + { + "version": "0.19.20", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "feat(ui): 支持首页删除收藏应用", + "notes": [ + { + "name": "UI 更新", + "descs": ["支持首页删除收藏应用,开启方式在悬浮按钮上"] + } + ] + }, + { + "version": "0.19.17", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(env): 撤回 Surge 强制使用 https 执行脚本逻辑", + "notes": [ + { + "name": "撤回", + "descs": [ + "撤回 Surge 强制使用 https 执行脚本逻辑", + "后续增加配置方式来支持 https" + ] + } + ] + }, + { + "version": "0.19.16", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(env): console.log 问题", + "notes": [ + { + "name": "修复", + "descs": ["EnvJs console.log 问题"] + } + ] + }, + { + "version": "0.19.15", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "chore(boxjs): update EnvJs", + "notes": [ + { + "name": "更新", + "descs": ["EnvJs 更新至最新版本"] + } + ] + }, + { + "version": "0.19.14", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 白屏问题", + "notes": [ + { + "name": "修复", + "descs": ["部分场景下白屏"] + } + ] + }, + { + "version": "0.19.13", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 会话数据不展示", + "notes": [ + { + "name": "修复", + "descs": ["代码逻辑问题导致会话数据不展示"] + } + ] + }, + { + "version": "0.19.12", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 优化数据载入", + "notes": [ + { + "name": "优化", + "descs": ["对数据载入优化,以适配 app 版本"] + } + ] + }, + { + "version": "0.19.11", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "feat(boxjs): 新增 /api/deleteAppSub 删除订阅", + "notes": [ + { + "name": "新增 API", + "descs": ["本次更新主要面向开发者"] + } + ] + }, + { + "version": "0.19.10", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 修复 /api/update 进行局部数据更新", + "notes": [ + { + "name": "修复", + "descs": ["不存在 key 和 val 的情况"] + } + ] + }, + { + "version": "0.19.9", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 修复 /api/update 进行局部数据更新", + "notes": [ + { + "name": "修复", + "descs": ["不存在 key 和 val 的情况"] + } + ] + }, + { + "version": "0.19.8", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 修复 /api/update 进行局部数据更新", + "notes": [ + { + "name": "修复接口", + "descs": ["本次更新主要面向开发者"] + } + ] + }, + { + "version": "0.19.7", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "feat(boxjs): 新增 /api/update 进行局部数据更新", + "notes": [ + { + "name": "新增接口", + "descs": ["本次更新主要面向开发者"] + } + ] + }, + { + "version": "0.19.6", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 订阅缓存问题", + "notes": [ + { + "name": "修复", + "descs": ["脏数据处理,部分订阅已经 404 或者 403,仅缓存有数据的订阅"] + } + ] + }, + { + "version": "0.19.3", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 首页拖拽数据问题", + "notes": [ + { + "name": "修复", + "descs": ["首页拖拽数组数据中会出现 null"] + } + ] + }, + { + "version": "0.19.2", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 127.0.0.1 被代理时, boxjs 无法运行脚本", + "notes": [ + { + "name": "修复", + "descs": ["127.0.0.1 走代理时, 无法运行脚本"] + }, + { + "name": "感谢", + "descs": ["@mieqq", "@xream"] + } + ] + }, + { + "version": "0.19.1", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): /api/runScritp 接受 argument 参数", + "notes": [ + { + "name": "功能", + "descs": [ + "/api/runScritp 接受 argument 参数", + "更新: argument 支持 JSON 格式的参数" + ] + }, + { + "name": "感谢", + "descs": ["@is_bo 建议"] + } + ] + }, + { + "version": "0.19.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): /api/runScritp 接受 argument 参数", + "notes": [ + { + "name": "功能", + "descs": [ + "/api/runScritp 接受 argument 参数", + "作用: 非 Surge 用户可通过快捷方式请求 URL 的方式来执行切换会话" + ] + }, + { + "name": "感谢", + "descs": ["@is_bo 建议"] + } + ] + }, + { + "version": "0.18.1", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 数据编辑器无法保存数据问题", + "notes": [ + { + "name": "修复", + "descs": ["修复数据编辑器无法保存数据问题"] + } + ] + }, + { + "version": "0.18.0", + "tags": ["beta"], + "author": "@dompling", + "msg": "fix(boxjs): appid 重复", + "notes": [ + { + "name": "appid重复问题", + "descs": ["修复无法正常跳转问题", "修复无法正常收藏"] + } + ] + }, + { + "version": "0.17.0", + "tags": ["beta"], + "author": "@dompling", + "msg": "feat(viewer): 数据查看器", + "notes": [ + { + "name": "数据查看器", + "descs": ["近期查看样式调整", "非订阅数据查看和保存"] + } + ] + }, + { + "version": "0.16.0", + "tags": ["beta"], + "author": "@dompling", + "msg": "feat(boxjs): 下拉框的选项可以动态从持久化数据中读取", + "notes": [ + { + "name": "面向开发者", + "descs": [ + "Items 选项可以动态从持久化数据中读取", + "{..., \"type\": \"select\", \"items\": \"@gist.revision_options\", ...}" + ] + }, + { + "name": "感谢", + "descs": ["@dompling PR"] + } + ] + }, + { + "version": "0.15.0", + "tags": ["beta"], + "author": "@dompling", + "msg": "feat(boxjs): 通过数据查看器查询过的数据,会加入全局备份的名单中", + "notes": [ + { + "name": "新增", + "descs": ["通过数据查看器查询过的数据,会加入全局备份的名单中"] + }, + { + "name": "感谢", + "descs": ["@dompling PR"] + } + ] + }, + { + "version": "0.14.2", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 全局静默状态下没有发出查询警告", + "notes": [ + { + "name": "修复", + "descs": ["全局静默状态下没有发出查询警告"] + }, + { + "name": "感谢", + "descs": ["@MuTu888 反馈"] + } + ] + }, + { + "version": "0.14.1", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): boxjs 自身的请求仍发出警告问题", + "notes": [ + { + "name": "数据查询警告", + "descs": [ + "为保护用户数据,当发现不是 boxjs 自身发起的数据查询时,会发出警告 (默认开启)", + "可以在 boxjs 页面侧栏中关闭警告 (但仍会记录日志)" + ] + }, + { + "name": "感谢", + "descs": ["@xream 反馈"] + } + ] + }, + { + "version": "0.14.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): 增加数据查询警告", + "notes": [ + { + "name": "数据查询警告", + "descs": [ + "为保护用户数据,当发现不是 boxjs 自身发起的数据查询时,会发出警告 (默认开启)", + "可以在 boxjs 页面侧栏中关闭警告 (但仍会记录日志)" + ] + }, + { + "name": "感谢", + "descs": ["@xream 反馈"] + } + ] + }, + { + "version": "0.13.1", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 数据查看器无法对空数据进行编辑问题", + "notes": [ + { + "name": "修复", + "descs": ["数据查看器无法对空数据进行编辑问题"] + }, + { + "name": "感谢", + "descs": ["@xream 反馈"] + } + ] + }, + { + "version": "0.13.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): 数据查看器显示历史查询记录", + "notes": [ + { + "name": "功能", + "descs": ["数据查看器显示历史查询记录"] + }, + { + "name": "感谢", + "descs": ["@xream 反馈"] + } + ] + }, + { + "version": "0.12.14", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): qx 执行脚本后无法获取结果问题", + "notes": [ + { + "name": "修复", + "descs": ["qx 执行脚本后无法获取结果问题"] + }, + { + "name": "感谢", + "descs": ["@xream 反馈"] + } + ] + }, + { + "version": "0.12.13", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 编辑会话时数据显示 [object Object] 问题", + "notes": [ + { + "name": "修复", + "descs": ["编辑会话时数据显示 [object Object] 问题"] + }, + { + "name": "感谢", + "descs": ["@VirgilClyne 反馈"] + } + ] + }, + { + "version": "0.12.12", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "修复无法备份问题", + "notes": [ + { + "name": "修复", + "descs": ["无法备份问题"] + } + ] + }, + { + "version": "0.12.11", + "tags": ["beta"], + "author": "@lowking", + "msg": "修复保存设置时,没有自动同步到当前会话问题", + "notes": [ + { + "name": "修复", + "descs": ["保存设置时,没有自动同步到当前会话问题"] + }, + { + "name": "感谢", + "descs": ["@lowking PR"] + } + ] + }, + { + "version": "0.12.10", + "tags": ["beta"], + "author": "@dompling", + "msg": "临时优化会话 JSON 过大,导致所有会话操作失效", + "notes": [ + { + "name": "修复", + "descs": ["临时优化会话 JSON 过大,导致所有会话操作失效"] + } + ] + }, + { + "version": "0.12.9", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "让 openAI 写了个 Surge 费用计算器", + "notes": [ + { + "name": "实验", + "descs": ["Surge 费用计算器"] + } + ] + }, + { + "version": "0.12.6", + "tags": ["beta"], + "author": "@VirgilClyne", + "msg": "fix(boxjs): msg() on Shadowrocket", + "notes": [ + { + "name": "修复", + "descs": ["小火箭环境下消息提示问题"] + }, + { + "name": "感谢", + "descs": ["@VirgilClyne PR"] + } + ] + }, + { + "version": "0.12.5", + "tags": ["beta"], + "author": "@VirgilClyne", + "msg": "fix(boxjs): 修复 Stash & ShadowRocket 报错问题", + "notes": [ + { + "name": "修复", + "descs": ["修复 Stash & ShadowRocket 报错问题"] + }, + { + "name": "感谢", + "descs": ["@VirgilClyne PR", "Stash 团队反馈及协助定位问题"] + } + ] + }, + { + "version": "0.12.4", + "tags": ["beta"], + "author": "@lowking", + "msg": "fix(boxjs): 修复 Surge 环境下执行脚本超时问题", + "notes": [ + { + "name": "修复", + "descs": ["Surge 环境下执行脚本超时问题"] + }, + { + "name": "感谢", + "descs": ["@lowking PR"] + } + ] + }, + { + "version": "0.12.3", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 修复 开关控件 及 多选控件 不正确显示默认值问题", + "notes": [ + { + "name": "修复", + "descs": ["开关控件 及 多选控件 不正确显示默认值问题"] + }, + { + "name": "感谢", + "descs": ["@Virgil_C 反馈及协助"] + } + ] + }, + { + "version": "0.12.2", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 修复 stash 无法运行脚本问题", + "notes": [ + { + "name": "修复", + "descs": ["stash 无法运行脚本问题"] + } + ] + }, + { + "version": "0.12.1", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 还原 gist 可能导致的白屏", + "notes": [ + { + "name": "修复", + "descs": ["还原 gist 可能导致的白屏"] + } + ] + }, + { + "version": "0.12.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): 添加订阅事件 onInstall", + "notes": [ + { + "name": "新增 (本次更新主要面向开发者)", + "descs": [ + "添加订阅时, 可自动触发资源安装, 如: 自动安装重写等)", + "订阅列表中, 可通过`更多 > 安装`来手动触发安装", + "", + "开发文档:", + "https://docs.boxjs.app/dev/configure#scenes-oninstall", + "", + "目前支持 (TestFlight):", + "1. Loon: v2.1.19 (386) 及以上", + "2. Quantumult X: v1.0.29 (670) 及以上" + ] + } + ] + }, + { + "version": "0.11.3", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "typo(boxjs): 修复一处拼写错误", + "notes": [ + { + "name": "修复", + "descs": ["一处拼写错误"] + } + ] + }, + { + "version": "0.11.2", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): 发现新版本时可跳转至 app 内触发资源更新", + "notes": [ + { + "name": "新增", + "descs": [ + "发现新版本时可跳转至 app 内触发资源更新", + "目前支持 (TestFlight):", + "1. Loon: v2.1.19 (386) 及以上", + "2. Quantumult X: v1.0.29 (670) 及以上" + ] + } + ] + }, + { + "version": "0.10.2", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 尝试修复删除订阅问题", + "notes": [ + { + "name": "修复", + "descs": ["部分情况删除订阅引发的问题"] + } + ] + }, + { + "version": "0.10.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): 一键订阅", + "notes": [ + { + "name": "新增", + "descs": [ + "一键订阅", + "点击链接就可以自动添加订阅, 免去手动添加的麻烦", + "制作一键订阅地址: ", + "http://boxjs.com/#/sub/add/经过encodeURIComponent()订阅地址", + "如: http://boxjs.com/#/sub/add/https%3A%2F%2Fraw.githubusercontent.com%2Fchavyleung%2Fscripts%2Fmaster%2Fbox%2Fchavy.boxjs.json" + ] + }, + { + "name": "新增", + "descs": [ + "可以`分享`订阅", + "复制与分享的区别: ", + "复制: 仅复制订阅地址", + "分享: 生成并复制一键订阅地址, 别人仅需点击该地址则可自动添加订阅" + ] + }, + { + "name": "QX 用户注意", + "descs": [ + "仅配置 httpbackend 的 QX 用户无法使用一键订阅", + "需要配置 `重写` 或同时配置 `重写` 及 `httpbackend` 才能使用一键订阅" + ] + }, + { + "name": "其他", + "descs": ["合并了稳定版和测试版, 两个版本已经没有区别"] + } + ] + }, + { + "version": "0.9.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "新增(BoxJs): 支持 Stash", + "notes": [ + { + "name": "新增", + "descs": [ + "支持 Stash TF (v1.5.0 Build 203+)", + "https://chavyleung.gitbook.io/boxjs/#stash" + ] + } + ] + }, + { + "version": "0.8.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "新增(BoxJs): selects (下拉) 控件", + "notes": [ + { + "name": "新增", + "descs": [ + "新增 selects (下拉) 控件", + "type: 'selects'", + "items: [{key: '', label: ''}]" + ] + } + ] + }, + { + "version": "0.7.92", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "新增(BoxJs): 内置 Gist 备份及还原脚本. @dompling", + "notes": [ + { + "name": "新增", + "descs": ["内置 Gist 备份及还原脚本. @dompling"] + }, + { + "name": "感谢", + "descs": ["@dompling"] + } + ] + }, + { + "version": "0.7.91", + "tags": ["beta"], + "author": "@NobyDa", + "msg": "修复(BoxJs): 部分情况手动运行脚本异常", + "notes": [ + { + "name": "修复", + "descs": ["部分情况手动运行脚本异常"] + }, + { + "name": "感谢", + "descs": ["@NobyDa PR"] + } + ] + }, + { + "version": "0.7.90", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): backup data display bug", + "notes": [ + { + "name": "修复", + "descs": ["备份数据太大导致无法进入备份详情"] + } + ] + }, + { + "version": "0.7.89", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): add data viewer", + "notes": [ + { + "name": "新增", + "descs": ["数据编辑 & 查看器"] + } + ] + }, + { + "version": "0.7.88", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): store each backup separately", + "notes": [ + { + "name": "优化", + "descs": ["独立存储每份备份数据, 避免备份数据过大问题"] + } + ] + }, + { + "version": "0.7.87", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): language switching bug", + "notes": [ + { + "name": "修复", + "descs": ["语言切换问题"] + } + ] + }, + { + "version": "0.7.85", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): add language (zh-CN & en-US)", + "notes": [ + { + "name": "多语言 (beta)", + "descs": ["增加语言: 简中、英文 "] + }, + { + "name": "Languages (beta)", + "descs": ["add zh-CN & en-US"] + } + ] + }, + { + "version": "0.7.84", + "tags": ["beta"], + "author": "@lowking", + "msg": "更新[BoxJs]: 修复部分情况下壁纸模式上滑手势失效问题", + "notes": [ + { + "name": "修复", + "descs": ["部分情况下壁纸模式上滑手势失效问题"] + }, + { + "name": "感谢", + "descs": ["@lowking PR"] + } + ] + }, + { + "version": "0.7.83", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 增加图标拖拽动画", + "notes": [ + { + "name": "优化", + "descs": ["增加图标拖拽动画"] + } + ] + }, + { + "version": "0.7.82", + "tags": ["beta"], + "author": "@chouchoui", + "msg": "更新[BoxJs]: 格式不正确的HTTP Backend不会生效", + "notes": [ + { + "name": "优化", + "descs": ["格式不正确的HTTP Backend不会生效"] + } + ] + }, + { + "version": "0.7.81", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 修复拖拽图标的时候出现文本选择光标问题", + "notes": [ + { + "name": "修复", + "descs": ["拖拽图标的时候出现文本选择光标问题"] + } + ] + }, + { + "version": "0.7.80", + "tags": ["beta"], + "author": "@Senku", + "msg": "更新[BoxJs]: 调整拖拽延迟", + "notes": [ + { + "name": "修复", + "descs": ["降低首页图标拖拽灵敏度,长按拖动"] + } + ] + }, + { + "version": "0.7.79", + "tags": ["beta"], + "author": "@Senku", + "msg": "更新[BoxJs]: 首页图标可自定义顺序", + "notes": [ + { + "name": "新增", + "descs": ["首页图标可拖拽自定义顺序"] + } + ] + }, + { + "version": "0.7.78", + "tags": ["beta"], + "author": "@chouchoui", + "msg": "更新[BoxJs]: 增加版本说明", + "notes": [ + { + "name": "新增", + "descs": [ + "偏好设置增加 HTTP Backend (Quantumult X)", + "说明: ", + "发现: Quantumult X 通过重写的方式访问 BoxJs 可能会导致无法删除备份的问题, 但通过 HTTP Backend 方式访问则正常。", + "建议: 改用 HTTP Backend 或 重写与 HTTP Backend 结合的方式访问 BoxJs", + "姿势: 见 使用文档 (悬浮按钮 > ?)" + ] + }, + { + "name": "优化", + "descs": ["增加底部空间避免悬浮按钮遮挡空间"] + }, + { + "name": "感谢", + "descs": ["@chouchoui PR"] + } + ] + }, + { + "version": "0.7.77", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 更新文案", + "notes": [ + { + "name": "更新", + "descs": ["部分文案"] + } + ] + }, + { + "version": "0.7.76", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 偏好设置内可以抹掉数据", + "notes": [ + { + "name": "新增", + "descs": ["偏好设置内可以抹掉数据"] + }, + { + "name": "说明", + "descs": [ + "抹掉:所有缓存", + "抹掉订阅及页面缓存,会导致所有订阅显示格式错误,双击底栏'订阅'菜单或更新订阅即可恢复", + "", + "抹掉:收藏应用", + "抹掉所有收藏的应用,排序出现问题时可尝试抹掉", + "", + "抹掉:用户偏好", + "抹掉头像、设置、收藏等个人相关的数据, 注意:不含会话、备份、缓存", + "", + "抹掉:所有会话", + "抹掉所有应用下的会话, 注意:不会抹掉当前会话", + "", + "抹掉:所有备份", + "抹掉所有全局备份, 注意:抹掉前可先把备份复制到其他文本类应用内", + "", + "抹掉:BoxJs", + "抹掉所有由 BoxJs 管理的数据, 如:备份、会话、偏好、缓存等 (不包含当前会话)" + ] + } + ] + }, + { + "version": "0.7.75", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 修复退出壁纸模式后壁纸无法还原问题", + "notes": [ + { + "name": "修复", + "descs": ["修复退出壁纸模式后壁纸无法还原问题"] + } + ] + }, + { + "version": "0.7.74", + "tags": ["beta"], + "author": "@lowking", + "msg": "更新[BoxJs]: 更方便快捷的看小姐姐", + "notes": [ + { + "name": "新增特性", + "descs": ["悬浮图标下滑进入壁纸模式自动切换到配置好的壁纸,退出同理"] + }, + { + "name": "感谢", + "descs": ["@lowking PR"] + } + ] + }, + { + "version": "0.7.73", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 修复小火箭环境下手动运行脚本报错问题", + "notes": [ + { + "name": "修复", + "descs": ["小火箭环境下手动运行脚本报错问题"] + } + ] + }, + { + "version": "0.7.72", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 适配小火箭, 感谢 @Orz-3 提供图标", + "notes": [ + { + "name": "适配", + "descs": ["Shadowrocket (小火箭)"] + }, + { + "name": "感谢", + "descs": ["@Orz-3 提供图标"] + } + ] + }, + { + "version": "0.7.71", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 修复备份数据异常导致无法进入页面问题", + "notes": [ + { + "name": "修复", + "descs": ["备份数据异常导致无法进入页面问题"] + } + ] + }, + { + "version": "0.7.69", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 移除 gitee 链接, 改用 github raw 及 jsdelivr", + "notes": [ + { + "name": "说明", + "descs": [ + "由于通过 gitee 访问部分仓库资源时出现 `根据相关法律政策,该内容无法显示`", + "虽然我手动同步 github 代码后已经可以正常访问", + "但为避免以后出现不可预知的情况:", + "我们把全部 gitee 链接替换为 github raw 及 jsdelivr", + "----", + "大家只需正常更新订阅并重启代理即可" + ] + }, + { + "name": "感谢", + "descs": ["@zZPiglet PR"] + } + ] + }, + { + "version": "0.7.68", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 订阅格式错误导致无法进入页面问题", + "notes": [ + { + "name": "修复", + "descs": ["订阅格式错误导致无法进入页面问题"] + } + ] + }, + { + "version": "0.7.67", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 自动替换 BoxJs 订阅中 Orz-3/mini 库的图标路径", + "notes": [ + { + "name": "修复", + "descs": ["Orz-3/mini 库图标路径"] + }, + { + "name": "注意", + "descs": [ + "如果订阅里有旧的图标路径,BoxJs 会自动转换为新路径,有问题请反馈" + ] + } + ] + }, + { + "version": "0.7.66", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 更新 Orz-3/mini 库图标路径", + "notes": [ + { + "name": "修复", + "descs": ["Orz-3/mini 库图标路径"] + } + ] + }, + { + "version": "0.7.65", + "tags": ["beta"], + "author": "@id77", + "msg": "更新[BoxJs]: 应用会话前,清空当前会话数据", + "notes": [ + { + "name": "优化", + "descs": ["应用会话前,清空当前会话数据"] + }, + { + "name": "感谢", + "descs": ["@id77 PR"] + } + ] + }, + { + "version": "0.7.64", + "tags": ["beta"], + "author": "@whyour", + "msg": "更新[BoxJs]: 优化底栏按钮高亮样式", + "notes": [ + { + "name": "增加", + "descs": ["只复制 App 数据为对象功能"] + }, + { + "name": "感谢", + "descs": ["@whyour PR"] + } + ] + }, + { + "version": "0.7.62", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 优化底栏按钮高亮样式", + "notes": [ + { + "name": "优化", + "descs": ["去掉底栏按钮高亮时的背景色"] + } + ] + }, + { + "version": "0.7.61", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 修复订阅为 null 时数据加载报错", + "notes": [ + { + "name": "修复", + "descs": [ + "由于网络问题,导致订阅数据异常后,访问页面时仅显示 BoxJs 字样问题。" + ] + } + ] + }, + { + "version": "0.7.60", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 增加判断 BoxJs 订阅格式判断", + "notes": [ + { + "name": "修复", + "descs": ["添加非 BoxJs 订阅时导致白屏问题"] + } + ] + }, + { + "version": "0.7.59", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: Vuetify 升级至 v2.4", + "notes": [ + { + "name": "优化", + "descs": ["升级 Vuetify 版本"] + } + ] + }, + { + "version": "0.7.58", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 刷新订阅添加时间缀避免网络缓存", + "notes": [ + { + "name": "优化", + "descs": [ + "BoxJs 内的请求会可以被重写", + "刷新订阅添加时间缀避免网络缓存" + ] + } + ] + }, + { + "version": "0.7.56", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs TF]: 修复一处导致白屏逻辑", + "notes": [ + { + "name": "修复", + "descs": ["修复一处导致白屏逻辑"] + } + ] + }, + { + "version": "0.7.55", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs TF]: 顶栏和底栏可以设置跟随滚动", + "notes": [ + { + "name": "新增", + "descs": ["顶栏和底栏可以设置跟随滚动"] + } + ] + }, + { + "version": "0.7.54", + "tags": ["beta"], + "author": "@id77", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 侧栏增加新的贡献者 @id77", + "notes": [ + { + "name": "贡献者", + "descs": ["新的贡献者 @id77"] + } + ] + }, + { + "version": "0.7.53", + "tags": ["beta"], + "author": "@GideonSenku", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 跟随系统壁纸设置同时支持中英文", + "notes": [ + { + "name": "新增", + "descs": ["跟随系统壁纸设置支持中英文,且优先考虑中文关键字"] + }, + { + "name": "说明", + "descs": ["中文关键字为`暗黑`和`明亮`,英文关键字不变"] + } + ] + }, + { + "version": "0.7.52", + "tags": ["beta"], + "author": "@id77 @chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 删除备份后直接回到首页问题", + "notes": [ + { + "name": "移除", + "descs": [ + "主屏幕的左右滑动手势", + "原因: 与浏览器前进后退容易发生冲突" + ] + }, + { + "name": "修复", + "descs": ["删除备份后直接回到首页问题"] + }, + { + "name": "优化", + "descs": ["页面后退事件逻辑", "部分侧栏设置的小字说明"] + } + ] + }, + { + "version": "0.7.49", + "tags": ["beta"], + "author": "@GideonSenku", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复主屏左滑时与侧栏冲突问题", + "notes": [ + { + "name": "新增", + "descs": ["背景图片可跟随系统调整"] + }, + { + "name": "调整", + "descs": ["背景清单图片默认`无`更改为`跟随系统`"] + }, + { + "name": "修复", + "descs": ["主屏左滑时与侧栏冲突问题"] + }, + { + "name": "说明", + "descs": [ + "背景图片清单中设置:无{换行} 跟随系统,跟随系统{换行} light,图片地址{换行} dark,图片地址{换行}", + "如果不设置`跟随系统,跟随系统`,则默认跟随系统为无背景" + ] + } + ] + }, + { + "version": "0.7.47", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复代码编辑器高度, 部分界面左右滑动范围问题", + "notes": [ + { + "name": "修复", + "descs": [ + "代码编辑器高度问题", + "部分界面只能在有内容的范围左右滑动问题" + ] + } + ] + }, + { + "version": "0.7.46", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 移除滑动动画, 勿扰模式不弹脚本执行结果页, 操作优化", + "notes": [ + { + "name": "优化", + "descs": [ + "勿扰模式下运行脚本不弹出结果页", + "壁纸模式下滑更容易退出壁纸模式" + ] + }, + { + "name": "移除", + "descs": ["左右滑动切换页面的动画"] + } + ] + }, + { + "version": "0.7.45", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复脚本执行结果、更新日志页面位置不正确, 主页左滑进入壁纸模式", + "notes": [ + { + "name": "新增", + "descs": ["主页左滑进入壁纸模式"] + }, + { + "name": "修复", + "descs": ["脚本执行结果、更新日志页面位置不正确"] + } + ] + }, + { + "version": "0.7.44", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 主屏幕左右滑动可切换 首页、应用、订阅、我的 页面", + "notes": [ + { + "name": "新增", + "descs": [ + "Surge、QuanX、Loon 手动运行脚本时都可以显示执行结果", + "主屏幕左右滑动可切换 首页、应用、订阅、我的 页面" + ] + }, + { + "name": "修复", + "descs": ["全局搜索结果位置不正确问题"] + } + ] + }, + { + "version": "0.7.43", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复非壁纸模式下上滑仍然重新渲染壁纸", + "notes": [ + { + "name": "新增", + "descs": [ + "在顶栏上滑可隐藏顶栏", + "在底栏下滑可以隐藏底栏", + "壁纸模式上滑可以重新渲染壁纸" + ] + }, + { + "name": "修复", + "descs": [ + "代码编辑器不显示问题", + "二次进入搜索界面无法自动获取焦点", + "非壁纸模式下上滑仍然重新渲染壁纸" + ] + } + ] + }, + { + "version": "0.7.41", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复顶栏隐藏时图标没往上挪, 悬浮按钮上滑切壁纸, 壁纸模式隐藏悬浮按钮", + "notes": [ + { + "name": "优化", + "descs": ["壁纸模式会把悬浮按钮也隐藏起来"] + }, + { + "name": "修复", + "descs": ["顶栏隐藏时图标没有往上挪"] + }, + { + "name": "悬浮按钮手势", + "descs": [ + "上滑: 重渲染&切换壁纸", + "左滑: 悬浮按钮左靠", + "右滑: 悬浮按钮右靠", + "下滑: 切换壁纸模式" + ] + }, + { + "name": "说明", + "descs": [ + "壁纸模式下: 下滑取消壁纸模式", + "非壁纸模式: 下滑显示\\隐藏顶栏" + ] + } + ] + }, + { + "version": "0.7.40", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 新增壁纸模式、悬浮按钮手势", + "notes": [ + { + "name": "新增", + "descs": ["壁纸模式", "悬浮按钮手势"] + }, + { + "name": "悬浮按钮手势", + "descs": [ + "上滑: 刷新页面 (效果同双击)", + "左滑: 悬浮按钮左靠", + "右滑: 悬浮按钮右靠", + "下滑: 切换壁纸模式" + ] + } + ] + }, + { + "version": "0.7.39", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复部分情况下拉出顶栏事件失效问题", + "notes": [ + { + "name": "修复", + "descs": ["部分情况下拉出顶栏事件失效问题"] + }, + { + "name": "优化", + "descs": ["原来顶部的加载条移到底栏上方"] + } + ] + }, + { + "version": "0.7.38", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 新增 Surge HTTP-API 环境下运行脚本会显示运行结果", + "notes": [ + { + "name": "新增", + "descs": ["Surge HTTP-API 环境下运行脚本会显示运行结果"] + }, + { + "name": "优化", + "descs": ["页面样式"] + }, + { + "name": "移除", + "descs": ["顶栏跟随滚动"] + } + ] + }, + { + "version": "0.7.37", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 应用标题加阴影, 优化调试代码, 单击首页重渲染壁纸", + "notes": [ + { + "name": "优化", + "descs": ["应用标题加阴影"] + }, + { + "name": "调试", + "descs": ["优化代码"] + }, + { + "name": "新增", + "descs": ["单击首页回到顶部, 再单击一次重新渲染壁纸"] + }, + { + "name": "壁纸", + "descs": [ + "无背景,", + "随机,https://uploadbeta.com/api/pictures/random", + "推女郎,https://uploadbeta.com/api/pictures/random/?key=推女郎", + "性感,https://uploadbeta.com/api/pictures/random/?key=性感", + "车模,https://uploadbeta.com/api/pictures/random/?key=车模", + "美腿,https://uploadbeta.com/api/pictures/random/?key=美腿", + "美女,https://uploadbeta.com/api/pictures/random/?key=美女", + "手机妹子,http://api.btstu.cn/sjbz/zsy.php", + "手机美女,http://api.btstu.cn/sjbz/?m_lx=suiji" + ] + } + ] + }, + { + "version": "0.7.36", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["下拉显示&隐藏搜索栏"] + }, + { + "name": "优化", + "descs": ["固定背景"] + }, + { + "name": "修复", + "descs": ["搜索栏高度问题"] + } + ] + }, + { + "version": "0.7.35", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "调试", + "descs": ["调试模式下支持自定义页面源码地址"] + }, + { + "name": "修复", + "descs": [ + "底栏事件无效问题", + "部分情况下贡献者重复加载问题", + "手势前进后退会白屏&卡屏问题" + ] + } + ] + }, + { + "version": "0.7.33", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["支持前进、后退", "WebApp 状态下刷新能留在当前页面"] + }, + { + "name": "修复", + "descs": ["侧栏拉不到底缺陷"] + }, + { + "name": "调试", + "descs": ["支持 vue devtool (侧栏开启调试模式)"] + }, + { + "name": "感谢", + "descs": ["感谢 @id77 大佬 PR"] + } + ] + }, + { + "version": "0.7.30", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["首页背景可以一直固定住"] + }, + { + "name": "感谢", + "descs": ["感谢 @id77 大佬 PR"] + } + ] + }, + { + "version": "0.7.29", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "代码编辑器", + "descs": ["Surge HTTP-API 环境下执行的代码能显示响应内容"] + } + ] + }, + { + "version": "0.7.28", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["数据后端渲染", "更快更平顺的首页加载", "不闪屏了"] + }, + { + "name": "感谢", + "descs": ["感谢 @eslint 大佬提供帮助"] + } + ] + }, + { + "version": "0.7.27", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["首页样式", "操作体验"] + }, + { + "name": "首页", + "descs": ["顶栏透明", "可以隐藏顶栏", "顶栏可以固定或跟随滚动"] + }, + { + "name": "悬浮按钮", + "descs": ["增加搜索入口"] + } + ] + }, + { + "version": "0.7.26", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "调整", + "descs": ["搜索条样式", "搜索操作界面"] + } + ] + }, + { + "version": "0.7.24", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["解决首屏闪屏问题", "解决图标白边问题", "导入会话报错"] + }, + { + "name": "感谢", + "descs": ["感谢 @eslint 大佬提供帮助"] + } + ] + }, + { + "version": "0.7.21", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["一键清空会话数据"] + }, + { + "name": "优化", + "descs": ["壁纸状态下图标字体颜色为白色", "其他样式优化"] + } + ] + }, + { + "version": "0.7.20", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["勿扰模式下, 不再忽略手动执行脚本时发出的系统通知"] + }, + { + "name": "新增", + "descs": ["可以设置多张壁纸 (偏好设置)"] + }, + { + "name": "注意", + "descs": ["设置多张壁纸后,在侧栏切换"] + } + ] + }, + { + "version": "0.7.18", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["代码编辑器 (入口: 悬浮按钮)"] + }, + { + "name": "说明", + "descs": [ + "除了本机运行外", + "可以使用 PC 连上 QuanX 的 HTTP Backend", + "实现在 PC 上写代码然后发送到 QuanX 执行", + "Surge、Loon 同理" + ] + } + ] + }, + { + "version": "0.7.17", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["首页壁纸 (偏好设置)"] + } + ] + }, + { + "version": "0.7.16", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["首页图标样式"] + }, + { + "name": "修复", + "descs": [ + "首页图标点击无效问题", + "首页图标有轻微位移问题", + "帮助页面打开空白" + ] + } + ] + }, + { + "version": "0.7.11", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["首页显示收藏应用", "订阅中的更多按钮可以链接到作者仓库"] + } + ] + }, + { + "version": "0.7.9", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["可以修改会话", "增加帮忙手册入口", "推荐订阅入口"] + }, + { + "name": "调整", + "descs": ["调整加载动态效果"] + }, + { + "name": "修复", + "descs": ["boolean 控件偶尔触发键盘问题"] + } + ] + }, + { + "version": "0.7.7", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["全程无刷新", "独立分离页面", "优化数据结构减少内存占用"] + }, + { + "name": "操作", + "descs": [ + "可以修复全局备份的名字", + "点击'应用'回到顶部,再次单击折叠面板", + "点击'订阅'回到顶部,再次单击刷新订阅", + "点击具体订阅可刷新" + ] + } + ] + }, + { + "version": "0.6.20", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: BoxJs 内的请求会可以被重写", + "notes": [ + { + "name": "优化", + "descs": [ + "BoxJs 内的请求会可以被重写", + "刷新订阅添加时间缀避免网络缓存" + ] + } + ] + }, + { + "version": "0.6.18", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["清空设置时一直转圈问题"] + } + ] + }, + { + "version": "0.6.17", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["勿扰模式", "应用界面双击底栏能返回应用列表"] + }, + { + "name": "注意", + "descs": ["勿扰模式下仍然可以通过日志查看通过内容"] + } + ] + }, + { + "version": "0.6.16", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "订阅配置", + "descs": [ + "新增: desc、descs、desc_html、descs_html 属性", + "与 id、name 同级" + ] + }, + { + "name": "示例", + "descs": [ + "https://gist.githubusercontent.com/chavyleung/9d53fc4809eb41dca5f5923790ec5554/raw/09742d3473420d8e0bd7b02a910849f65af879fa/chavy.app.sub.simple.json" + ] + }, + { + "name": "注意", + "descs": ["本次更新主要面向开发者"] + } + ] + }, + { + "version": "0.6.15", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "偏好设置", + "descs": ["新增: http-api 超时时间, 默认 20 秒"] + }, + { + "name": "订阅配置", + "descs": [ + "增加 script_timeout 属性, 与 script 同级, 可指定 http-api 超时时间, 单位: 秒" + ] + } + ] + }, + { + "version": "0.6.14", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["可能导致白屏的问题"] + } + ] + }, + { + "version": "0.6.13", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["开关控件可以显示详情信息"] + }, + { + "name": "域名", + "descs": ["新增: http://boxjs.com"] + }, + { + "name": "新的重写订阅", + "descs": [ + "Surge: https://raw.githubusercontent.com/chavyleung/scripts/master/box/rewrite/boxjs.rewrite.surge.sgmodule", + "QuanX: https://raw.githubusercontent.com/chavyleung/scripts/master/box/rewrite/boxjs.rewrite.quanx.conf", + "Loon: https://raw.githubusercontent.com/chavyleung/scripts/master/box/rewrite/boxjs.rewrite.loon.conf" + ] + }, + { + "name": "注意", + "descs": [ + "新的重写订阅只有 boxjs.com", + "旧的重写订阅仍然保留 8888 1111 和新增的 boxjs.com", + "可以直接访问 http://boxjs.com 不加/home" + ] + } + ] + }, + { + "version": "0.6.12", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": [ + "双击底栏'应用'可以收缩面板并回到顶部", + "双击底栏'订阅'可以刷新订阅并回到顶部", + "双击'BoxJs'按钮可以刷新页面", + "保存应用设置、清存会话数据能马上生效 (不用刷新页面)", + "可以隐藏刷新按钮" + ] + }, + { + "name": "主题", + "descs": ["页面更多元素会跟随主题色调"] + }, + { + "name": "重写", + "descs": [ + "BoxJs 的重写已经去除代码级依赖", + "意味着仅通过修改正则和主机名即可替换 BoxJs 的访问地址", + "同时征集一个比较理想的国内域名作为 BoxJs 的免翻墙访问地址", + "iOS14 Surge TF 下提示私密连接的问题, 可以找一个 http 的域名来试试" + ] + } + ] + }, + { + "version": "0.6.11", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["底栏颜色会跟随主题色调"] + } + ] + }, + { + "version": "0.6.10", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "调整", + "descs": ["内置应用 偏好设置、切换会话 图标"] + }, + { + "name": "感谢", + "descs": ["感谢 @Orz-3 制作图标"] + } + ] + }, + { + "version": "0.6.9", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": [ + "内置应用: 偏好设置", + "可以设置多个 http-api (设置完后在侧栏选择)", + "可以分别设置暗黑、明亮主题下的主色调" + ] + }, + { + "name": "控件", + "descs": ["拾色器: colorpicker"] + }, + { + "name": "注意", + "descs": [ + "设置多个 http-api 时, 建议以逗号开头, 侧栏中选择空白的那个就是走 eval() 方案" + ] + } + ] + }, + { + "version": "0.6.8", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "调整", + "descs": ["运行按钮位置"] + }, + { + "name": "新增", + "descs": [ + "可以显示当前切换至哪个会话", + "应用可以设定多个运行脚本 scripts: {name: '', script: ''}", + "示例: https://gist.githubusercontent.com/chavyleung/9d53fc4809eb41dca5f5923790ec5554/raw/4d8b140ba149c33aa1fc622e93c4035ae74a73bb/chavy.app.sub.simple.json" + ] + } + ] + }, + { + "version": "0.6.7", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "重写", + "descs": [ + "BoxJs Surge 的重写超时改为 120 秒 (避免手动运行脚本容易超时)" + ] + }, + { + "name": "调整", + "descs": [ + "迁移 吾爱破解、爱奇艺 至原作者订阅: @NobyDa (野比)", + "https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json" + ] + } + ] + }, + { + "version": "0.6.6", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "调整", + "descs": [ + "迁移 腾讯新闻 至原作者订阅: @Sunert", + "https://raw.githubusercontent.com/Sunert/Scripts/master/Task/sunert.boxjs.json" + ] + } + ] + }, + { + "version": "0.6.5", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["Surge、QuanX、Loon 都可以在 BoxJs 中手动运行脚本"] + }, + { + "name": "说明", + "descs": [ + "手动运行脚本采用 eval() 方案", + "Surge 在配置了 http-api 参数下会使用 http-api 方案运行脚本", + "因为手法有点特殊, 不保证所有脚本都能良好" + ] + }, + { + "name": "感谢", + "descs": ["感谢 @NobyDa 野比大佬提醒可以使用 eval() 方案"] + } + ] + }, + { + "version": "0.6.4", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["应用订阅可以排序"] + } + ] + }, + { + "version": "0.6.3", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "主题", + "descs": ["非全屏状态下使用白色头部"] + }, + { + "name": "感谢", + "descs": ["感谢 @chouchoui 的 PR"] + } + ] + }, + { + "version": "0.6.2", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "主题", + "descs": ["浅色主题下使用黄色头部", "全屏状态下使用透明头部"] + }, + { + "name": "注意", + "descs": ["需要重新添加到桌面才能生效"] + }, + { + "name": "感谢", + "descs": ["感谢 @chouchoui 的 PR"] + } + ] + }, + { + "version": "0.6.0", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["可在 BoxJs 下直接运行脚本 (Surge TF)"] + }, + { + "name": "注意", + "descs": [ + "目前仅支持 Surge iOS TF & Surge mac 4.x", + "需要在 Surge配置文件中指定 http-api", + "然后在 BoxJs 侧栏中设置 http-api 路径", + "目前内置应用和 chavy.boxjs.json 内的应用都可以手动运行, 其他订阅需订阅作者更新订阅", + "资料: https://community.nssurge.com/d/327-http-api" + ] + } + ] + }, + { + "version": "0.5.8", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["明亮主题下收藏按钮样式问题"] + } + ] + }, + { + "version": "0.5.7", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["Rewrite 地址换成 Gitee (更新 BoxJs 后注意重启)"] + }, + { + "name": "教程", + "descs": ["QuanX 购买超 (90 > 30) 天即可一键更新"] + } + ] + }, + { + "version": "0.5.6", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["版本判断地址调整为 Gitee"] + } + ] + }, + { + "version": "0.5.4", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["版本刷新速度"] + } + ] + }, + { + "version": "0.5.2", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["可以单独更新订阅"] + } + ] + }, + { + "version": "0.5.1", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["版本判断速度 (jsdelivr)"] + } + ] + }, + { + "version": "0.5.0", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": [ + "抹掉数据: https://8.8.8.8/revert (更新完需要重启代理)", + "出现问题时可单独访问页面抹掉数据" + ] + }, + { + "name": "调整", + "descs": [ + "迁移内置应用至订阅: https://raw.githubusercontent.com/chavyleung/scripts/master/box/chavy.boxjs.json (需要手动更新订阅)" + ] + } + ] + }, + { + "version": "0.4.23", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["侧栏样式 (紧凑化)"] + } + ] + }, + { + "version": "0.4.22", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["后台日志报 illegal 问题"] + } + ] + }, + { + "version": "0.4.21", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["颜色主题可跟随系统 (明亮主题下强制使用彩色图标)"] + }, + { + "name": "修复", + "descs": ["有新版本但没有提示问题"] + } + ] + }, + { + "version": "0.4.20", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["明暗主题切换"] + }, + { + "name": "优化", + "descs": ["页面渲染资源"] + } + ] + }, + { + "version": "0.4.19", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["v0.4.18 白屏问题 (百果园空图标导致)"] + } + ] + }, + { + "version": "0.4.18", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": [ + "仓库协作者&贡献者信息 (带跳转)", + "点击订阅可以跳转至作者仓库" + ] + }, + { + "name": "修复", + "descs": ["删除多余日志输出"] + } + ] + }, + { + "version": "0.4.17", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["Loon升级教程字眼错误问题"] + } + ] + }, + { + "version": "0.4.16", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["iPhone X 底栏样式优化 (避免 bar 遮挡)"] + }, + { + "name": "修复", + "descs": ["多行文本控件 rows 属性无效问题"] + } + ] + }, + { + "version": "0.4.15", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["多选组控件全部取消时会恢复到默认问题"] + } + ] + }, + { + "version": "0.4.14", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增 (面向开发者)", + "descs": ["数字控件 (number)"] + } + ] + }, + { + "version": "0.4.13", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "性能", + "descs": ["优化订阅刷新性能 (并行)"] + } + ] + }, + { + "version": "0.4.12", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["部分情况下刷新&添加订阅无效问题"] + } + ] + }, + { + "version": "0.4.11", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["收藏应用排序异常问题"] + } + ] + }, + { + "version": "0.4.10", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "调整", + "descs": [ + "京东, 请使用野比大佬的订阅: https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json" + ] + } + ] + }, + { + "version": "0.4.9", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增 (面向开发者)", + "descs": ["单选组控件", "多选组控件"] + } + ] + }, + { + "version": "0.4.8", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["添加&刷新订阅的消息通知"] + }, + { + "name": "修复", + "descs": ["添加订阅时显示格式错误", "刷新订阅有时不生效"] + }, + { + "name": "移除", + "descs": ["刷新等待秒数"] + } + ] + }, + { + "version": "0.4.7", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": [ + "部分情况下无法清空会话数值问题 (更新脚本后, 需要手动刷新下订阅)" + ] + } + ] + }, + { + "version": "0.4.6", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["透明图标处理"] + } + ] + }, + { + "version": "0.4.5", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["部分情况下内置应用不显示问题"] + } + ] + }, + { + "version": "0.4.4", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["应用分类可以收纳"] + } + ] + }, + { + "version": "0.4.3", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["删除&导入会话时 Loading 动画不能自动消失问题"] + } + ] + }, + { + "version": "0.4.2", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": [ + "部分情况下保存数据不生效问题 (实验)", + "Rewrite正则 (注意更新正则)" + ] + }, + { + "name": "移除", + "descs": ["修复VPN断连设置项", "自动更新订阅 (可手动更新)"] + } + ] + }, + { + "version": "0.4.1", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "增加", + "descs": ["修复VPN断连设置项 (实验)"] + } + ] + }, + { + "version": "0.4.0", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["可以修改已保存的会话"] + } + ] + }, + { + "version": "0.3.10", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": [ + "可以把当前会话保存至指定会话 (注意先保存设置再使用`保存至`)", + "可以设置刷新等待秒数 (为 0 时直接刷新不弹窗)" + ] + } + ] + }, + { + "version": "0.3.9", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": [ + "可以复制单个应用订阅地址", + "增加底部间距避免界面被悬浮按钮遮挡" + ] + } + ] + }, + { + "version": "0.3.8", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": [ + "刷新窗口增加 3 秒倒数自动刷新", + "添加订阅能马上刷新订阅", + "刷新窗口弹出时会顺便发起更新应用订阅", + "可以隐藏手动更新订阅的提示" + ] + } + ] + }, + { + "version": "0.3.7", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": [ + "部分情况下导入空数据产生的问题 (如: 京东没有账号2, 导入后提示账号 2 签到失败问题)" + ] + } + ] + }, + { + "version": "0.3.6", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["部分情况下当前会话变双份问题"] + } + ] + }, + { + "version": "0.3.5", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["获取会话、应用会话、清空会话不生效问题"] + } + ] + }, + { + "version": "0.3.4", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": [ + "页面渲染时会先出现一串代码问题", + "进入应用订阅页面提示手动刷新", + "可以隐藏|显示`我的`标题" + ] + } + ] + }, + { + "version": "0.3.3", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["Loon环境判断错误问题"] + } + ] + }, + { + "version": "0.3.2", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "调整", + "descs": ["应用订阅启用缓存机制 (需要手动更新)"] + } + ] + }, + { + "version": "0.3.1", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["手动切换会话会导致自动切换顺序错误问题"] + } + ] + }, + { + "version": "0.3.0", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["全局搜索"] + } + ] + }, + { + "version": "0.2.4", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["帮助页面样式", "订阅链接多余空格&换行等字符"] + } + ] + }, + { + "version": "0.2.2", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["悬浮按钮刷新不用确认", "侧栏可以隐藏帮助按钮"] + } + ] + }, + { + "version": "0.2.1", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["可以设置悬浮按钮的位置"] + } + ] + }, + { + "version": "0.2.0", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["版本更新提醒", "BoxJs升级教程"] + } + ] + }, + { + "version": "0.1.3", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["长文本控件", "读写表达式"] + } + ] + } + ] +} diff --git a/box/release/box.release.tf.json b/box/release/box.release.tf.json new file mode 100644 index 000000000..6fc664f25 --- /dev/null +++ b/box/release/box.release.tf.json @@ -0,0 +1,1890 @@ +{ + "releases": [ + { + "version": "0.19.29", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "feat(boxjs): 顶部提示 iOS 客户端 Relay", + "notes": [ + { + "name": "功能", + "descs": ["主页顶部新增可关闭提示条,引导使用 iOS 原生客户端 Relay (TestFlight: https://testflight.apple.com/join/2yES8TuF)"] + } + ] + }, + { + "version": "0.19.28", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 同步 chavy.boxjs.js 内嵌 Env 至最新版本", + "notes": [ + { + "name": "修复", + "descs": ["同步 chavy.boxjs.js 内嵌 Env 函数,补全 Egern 环境检测及所有相关分支"] + } + ] + }, + { + "version": "0.19.27", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "feat(boxjs): 适配 Egern 代理工具", + "notes": [ + { + "name": "功能", + "descs": ["Env.js 新增 Egern 代理工具适配,支持持久化存储、HTTP 请求、系统通知等完整功能"] + } + ] + }, + { + "version": "0.19.26", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 保存设置时 val 为 false 仍应写入", + "notes": [ + { + "name": "修复", + "descs": ["保存路径数据时用 hasOwnProperty 判断 val,避免 false 被当作未传值而跳过更新"] + } + ] + }, + { + "version": "0.19.25", + "tags": ["beta"], + "author": "@id77", + "msg": "feat(boxjs): 会话支持仅使用和关联使用", + "notes": [ + { + "name": "优化", + "descs": ["仅使用会话数据,应用设置修改保存不更新原会话;关联使用会话数据,应用设置修改保存会更新原会话"] + } + ] + }, + { + "version": "0.19.24", + "tags": ["beta"], + "author": "@id77", + "msg": "feat(boxjs): isEditFavApp 只在主页才显示", + "notes": [ + { + "name": "优化", + "descs": ["悬浮按钮的收藏编辑功能只在主页才显示"] + } + ] + }, + { + "version": "0.19.23", + "tags": ["beta"], + "author": "@id77", + "msg": "feat(boxjs): 添加应用设置固定保存按钮", + "notes": [ + { + "name": "功能", + "descs": ["应用设置表单数据过多时,滚动到应用设置底部才能保存,添加应用设置固定保存按钮方便保存"] + } + ] + }, + { + "version": "0.19.22", + "tags": ["beta"], + "author": "@id77", + "msg": "fix(boxjs): 会话对话框修改&关闭功能", + "notes": [ + { + "name": "修复", + "descs": ["修复点修改A会话显示会话B的情况,每一个会话修改表单都应该有独立的控制key"] + } + ] + }, + { + "version": "0.19.21", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 订阅更新问题", + "notes": [ + { + "name": "修复", + "descs": ["订阅更新问题"] + } + ] + }, + { + "version": "0.19.20", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "feat(ui): 支持首页删除收藏应用", + "notes": [ + { + "name": "UI 更新", + "descs": ["支持首页删除收藏应用,开启方式在悬浮按钮上"] + } + ] + }, + { + "version": "0.19.17", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(env): 撤回 Surge 强制使用 https 执行脚本逻辑", + "notes": [ + { + "name": "撤回", + "descs": [ + "撤回 Surge 强制使用 https 执行脚本逻辑", + "后续增加配置方式来支持 https" + ] + } + ] + }, + { + "version": "0.19.16", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(env): console.log 问题", + "notes": [ + { + "name": "修复", + "descs": ["EnvJs console.log 问题"] + } + ] + }, + { + "version": "0.19.15", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "chore(boxjs): update EnvJs", + "notes": [ + { + "name": "更新", + "descs": ["EnvJs 更新至最新版本"] + } + ] + }, + { + "version": "0.19.14", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 白屏问题", + "notes": [ + { + "name": "修复", + "descs": ["部分场景下白屏"] + } + ] + }, + { + "version": "0.19.13", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 会话数据不展示", + "notes": [ + { + "name": "修复", + "descs": ["代码逻辑问题导致会话数据不展示"] + } + ] + }, + { + "version": "0.19.12", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 优化数据载入", + "notes": [ + { + "name": "优化", + "descs": ["对数据载入优化,以适配 app 版本"] + } + ] + }, + { + "version": "0.19.11", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "feat(boxjs): 新增 /api/deleteAppSub 删除订阅", + "notes": [ + { + "name": "新增 API", + "descs": ["本次更新主要面向开发者"] + } + ] + }, + { + "version": "0.19.10", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 修复 /api/update 进行局部数据更新", + "notes": [ + { + "name": "修复", + "descs": ["不存在 key 和 val 的情况"] + } + ] + }, + { + "version": "0.19.7", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "feat(boxjs): 新增 /api/update 进行局部数据更新", + "notes": [ + { + "name": "新增接口", + "descs": ["本次更新主要面向开发者"] + } + ] + }, + { + "version": "0.19.6", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 订阅缓存问题", + "notes": [ + { + "name": "修复", + "descs": ["脏数据处理,部分订阅已经 404 或者 403,仅缓存有数据的订阅"] + } + ] + }, + { + "version": "0.19.3", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "fix(boxjs): 首页拖拽数据问题", + "notes": [ + { + "name": "修复", + "descs": ["首页拖拽数组数据中会出现 null"] + } + ] + }, + { + "version": "0.19.2", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 127.0.0.1 被代理时, boxjs 无法运行脚本", + "notes": [ + { + "name": "修复", + "descs": ["127.0.0.1 走代理时, 无法运行脚本"] + }, + { + "name": "感谢", + "descs": ["@mieqq", "@xream"] + } + ] + }, + { + "version": "0.19.1", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 127.0.0.1 被代理时, boxjs 无法运行脚本", + "notes": [ + { + "name": "修复", + "descs": ["127.0.0.1 走代理时, 无法运行脚本"] + }, + { + "name": "感谢", + "descs": ["@mieqq", "@xream"] + } + ] + }, + { + "version": "0.19.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): /api/runScritp 接受 argument 参数", + "notes": [ + { + "name": "功能", + "descs": [ + "/api/runScritp 接受 argument 参数", + "作用: 非 Surge 用户可通过快捷方式请求 URL 的方式来执行切换会话" + ] + }, + { + "name": "感谢", + "descs": ["@is_bo 建议"] + } + ] + }, + { + "version": "0.18.1", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 数据编辑器无法保存数据问题", + "notes": [ + { + "name": "修复", + "descs": ["修复数据编辑器无法保存数据问题"] + } + ] + }, + { + "version": "0.18.0", + "tags": ["beta"], + "author": "@dompling", + "msg": "fix(boxjs): appid 重复", + "notes": [ + { + "name": "appid重复问题", + "descs": ["修复无法正常跳转", "修复无法正常收藏"] + } + ] + }, + { + "version": "0.16.0", + "tags": ["beta"], + "author": "@dompling", + "msg": "feat(boxjs): 下拉框的选项可以动态从持久化数据中读取", + "notes": [ + { + "name": "面向开发者", + "descs": [ + "Items 选项可以动态从持久化数据中读取", + "{..., \"type\": \"select\", \"items\": \"@gist.revision_options\", ...}" + ] + }, + { + "name": "感谢", + "descs": ["@dompling PR"] + } + ] + }, + { + "version": "0.15.0", + "tags": ["beta"], + "author": "@dompling", + "msg": "feat(boxjs): 通过数据查看器查询过的数据,会加入全局备份的名单中", + "notes": [ + { + "name": "新增", + "descs": ["通过数据查看器查询过的数据,会加入全局备份的名单中"] + }, + { + "name": "感谢", + "descs": ["@dompling PR"] + } + ] + }, + { + "version": "0.14.2", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 全局静默状态下没有发出查询警告", + "notes": [ + { + "name": "修复", + "descs": ["全局静默状态下没有发出查询警告"] + }, + { + "name": "感谢", + "descs": ["@MuTu888 反馈"] + } + ] + }, + { + "version": "0.14.1", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): boxjs 自身的请求仍发出警告问题", + "notes": [ + { + "name": "数据查询警告", + "descs": [ + "为保护用户数据,当发现不是 boxjs 自身发起的数据查询时,会发出警告 (默认开启)", + "可以在 boxjs 页面侧栏中关闭警告 (但仍会记录日志)" + ] + }, + { + "name": "感谢", + "descs": ["@xream 反馈"] + } + ] + }, + { + "version": "0.14.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): 增加数据查询警告", + "notes": [ + { + "name": "数据查询警告", + "descs": [ + "为保护用户数据,当发现不是 boxjs 自身发起的数据查询时,会发出警告 (默认开启)", + "可以在 boxjs 页面侧栏中关闭警告 (但仍会记录日志)" + ] + }, + { + "name": "感谢", + "descs": ["@xream 反馈"] + } + ] + }, + { + "version": "0.13.1", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 数据查看器无法对空数据进行编辑问题", + "notes": [ + { + "name": "修复", + "descs": ["数据查看器无法对空数据进行编辑问题"] + }, + { + "name": "感谢", + "descs": ["@xream 反馈"] + } + ] + }, + { + "version": "0.13.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): 数据查看器显示历史查询记录", + "notes": [ + { + "name": "功能", + "descs": ["数据查看器显示历史查询记录"] + } + ] + }, + { + "version": "0.12.14", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): qx 执行脚本后无法获取结果问题", + "notes": [ + { + "name": "修复", + "descs": ["qx 执行脚本后无法获取结果问题"] + }, + { + "name": "感谢", + "descs": ["@xream 反馈"] + } + ] + }, + { + "version": "0.12.13", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 编辑会话时数据显示 [object Object] 问题", + "notes": [ + { + "name": "修复", + "descs": ["编辑会话时数据显示 [object Object] 问题"] + }, + { + "name": "感谢", + "descs": ["@VirgilClyne 反馈"] + } + ] + }, + { + "version": "0.12.12", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "修复无法备份问题", + "notes": [ + { + "name": "修复", + "descs": ["无法备份问题"] + } + ] + }, + { + "version": "0.12.11", + "tags": ["beta"], + "author": "@lowking", + "msg": "修复保存设置时,没有自动同步到当前会话问题", + "notes": [ + { + "name": "修复", + "descs": ["保存设置时,没有自动同步到当前会话问题"] + }, + { + "name": "感谢", + "descs": ["@lowking PR"] + } + ] + }, + { + "version": "0.12.10", + "tags": ["beta"], + "author": "@dompling", + "msg": "fix(chavy.box.js): 临时优化会话 JSON 过大,导致所有会话操作失效", + "notes": [ + { + "name": "修复", + "descs": ["临时优化会话 JSON 过大,导致所有会话操作失效"] + } + ] + }, + { + "version": "0.12.9", + "tags": ["beta"], + "author": "@GideonSenku", + "msg": "让 openAI 写了个 Surge 费用计算器", + "notes": [ + { + "name": "实验", + "descs": ["Surge 费用计算器"] + } + ] + }, + { + "version": "0.12.6", + "tags": ["beta"], + "author": "@VirgilClyne", + "msg": "fix(boxjs): msg() on Shadowrocket", + "notes": [ + { + "name": "修复", + "descs": ["小火箭环境下消息提示问题"] + }, + { + "name": "感谢", + "descs": ["@VirgilClyne PR"] + } + ] + }, + { + "version": "0.12.5", + "tags": ["beta"], + "author": "@VirgilClyne", + "msg": "fix(boxjs): 修复 Stash & ShadowRocket 报错问题", + "notes": [ + { + "name": "修复", + "descs": ["修复 Stash & ShadowRocket 报错问题"] + }, + { + "name": "感谢", + "descs": ["@VirgilClyne PR", "Stash 团队反馈及协助定位问题"] + } + ] + }, + { + "version": "0.12.4", + "tags": ["beta"], + "author": "@lowking", + "msg": "fix(boxjs): 修复 Surge 环境下执行脚本超时问题", + "notes": [ + { + "name": "修复", + "descs": ["Surge 环境下执行脚本超时问题"] + }, + { + "name": "感谢", + "descs": ["@lowking PR"] + } + ] + }, + { + "version": "0.12.3", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 修复 开关控件 及 多选控件 不正确显示默认值问题", + "notes": [ + { + "name": "修复", + "descs": ["开关控件 及 多选控件 不正确显示默认值问题"] + }, + { + "name": "感谢", + "descs": ["@Virgil_C 反馈及协助"] + } + ] + }, + { + "version": "0.12.2", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 修复 stash 无法运行脚本问题", + "notes": [ + { + "name": "修复", + "descs": ["stash 无法运行脚本问题"] + } + ] + }, + { + "version": "0.12.1", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 还原 gist 可能导致的白屏", + "notes": [ + { + "name": "修复", + "descs": ["还原 gist 可能导致的白屏"] + } + ] + }, + { + "version": "0.12.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): 订阅添加事件 onInstall", + "notes": [ + { + "name": "新增", + "descs": [ + "添加订阅时, 可自动触发重写安装 (需要 App 支持)", + "订阅列表中, 可通过`更多 > 安装`来手动触发安装", + "", + "开发文档:", + "https://docs.boxjs.app/dev/configure#scenes-oninstall", + "", + "目前支持 (TestFlight):", + "1. Loon: v2.1.19 (386) 及以上", + "2. Quantumult X: v1.0.29 (670) 及以上" + ] + } + ] + }, + { + "version": "0.11.3", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "typo(boxjs): 修复一处拼写错误", + "notes": [ + { + "name": "修复", + "descs": ["一处拼写错误"] + } + ] + }, + { + "version": "0.11.2", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): 发现新版本时可跳转至 app 内触发资源更新", + "notes": [ + { + "name": "新增", + "descs": [ + "发现新版本时可跳转至 app 内触发资源更新", + "目前支持 (TestFlight):", + "1. Loon: v2.1.19 (386) 及以上", + "2. Quantumult X: v1.0.29 (670) 及以上" + ] + } + ] + }, + { + "version": "0.10.2", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): 尝试修复删除订阅问题", + "notes": [ + { + "name": "修复", + "descs": ["部分情况删除订阅引发的问题"] + } + ] + }, + { + "version": "0.10.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): 一键订阅", + "notes": [ + { + "name": "新增", + "descs": [ + "一键订阅", + "点击链接就可以自动添加订阅, 免去手动添加的麻烦", + "制作一键订阅地址: ", + "http://boxjs.com/#/sub/add/经过encodeURIComponent()订阅地址", + "如: http://boxjs.com/#/sub/add/https%3A%2F%2Fraw.githubusercontent.com%2Fchavyleung%2Fscripts%2Fmaster%2Fbox%2Fchavy.boxjs.json" + ] + }, + { + "name": "新增", + "descs": [ + "可以`分享`订阅", + "复制与分享的区别: ", + "复制: 仅复制订阅地址", + "分享: 生成并复制一键订阅地址, 别人仅需点击该地址则可自动添加订阅" + ] + }, + { + "name": "QX 用户注意", + "descs": [ + "仅配置 httpbackend 的 QX 用户无法使用一键订阅", + "需要配置 `重写` 或同时配置 `重写` 及 `httpbackend` 才能使用一键订阅" + ] + }, + { + "name": "其他", + "descs": ["合并了稳定版和测试版, 两个版本已经没有区别"] + } + ] + }, + { + "version": "0.9.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "新增(BoxJs): 支持 Stash", + "notes": [ + { + "name": "新增", + "descs": [ + "支持 Stash TF (v1.5.0 Build 203+)", + "https://chavyleung.gitbook.io/boxjs/#stash" + ] + } + ] + }, + { + "version": "0.8.0", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "新增(BoxJs): selects (下拉) 控件", + "notes": [ + { + "name": "新增", + "descs": [ + "新增 selects (下拉) 控件", + "type: 'selects'", + "items: [{key: '', label: ''}]" + ] + } + ] + }, + { + "version": "0.7.92", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "新增(BoxJs): 内置 Gist 备份及还原脚本. @dompling", + "notes": [ + { + "name": "新增", + "descs": ["内置 Gist 备份及还原脚本. @dompling"] + }, + { + "name": "感谢", + "descs": ["@dompling"] + } + ] + }, + { + "version": "0.7.91", + "tags": ["beta"], + "author": "@NobyDa", + "msg": "修复(BoxJs): 部分情况手动运行脚本异常", + "notes": [ + { + "name": "修复", + "descs": ["部分情况手动运行脚本异常"] + }, + { + "name": "感谢", + "descs": ["@NobyDa PR"] + } + ] + }, + { + "version": "0.7.90", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): backup data display bug", + "notes": [ + { + "name": "修复", + "descs": ["备份数据太大导致无法进入备份详情"] + } + ] + }, + { + "version": "0.7.89", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): add data viewer", + "notes": [ + { + "name": "新增", + "descs": ["数据编辑 & 查看器"] + } + ] + }, + { + "version": "0.7.88", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): store each backup separately", + "notes": [ + { + "name": "优化", + "descs": ["独立存储每份备份数据, 避免备份数据过大问题"] + } + ] + }, + { + "version": "0.7.87", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "fix(boxjs): language switching bug", + "notes": [ + { + "name": "修复", + "descs": ["语言切换问题"] + } + ] + }, + { + "version": "0.7.85", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "feat(boxjs): add languages (zh-CN & en-US)", + "notes": [ + { + "name": "多语言 (beta)", + "descs": ["增加语言: 简中、英文 "] + }, + { + "name": "Languages (beta)", + "descs": ["add zh-CN & en-US"] + } + ] + }, + { + "version": "0.7.84", + "tags": ["beta"], + "author": "@lowking", + "msg": "更新[BoxJs]: 修复部分情况下壁纸模式上滑手势失效问题", + "notes": [ + { + "name": "修复", + "descs": ["部分情况下壁纸模式上滑手势失效问题"] + }, + { + "name": "感谢", + "descs": ["@lowking PR"] + } + ] + }, + { + "version": "0.7.83", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 增加图标拖拽动画", + "notes": [ + { + "name": "优化", + "descs": ["增加图标拖拽动画"] + } + ] + }, + { + "version": "0.7.82", + "tags": ["beta"], + "author": "@chouchoui", + "msg": "更新[BoxJs]: 格式不正确的HTTP Backend不会生效", + "notes": [ + { + "name": "优化", + "descs": ["格式不正确的HTTP Backend不会生效"] + } + ] + }, + { + "version": "0.7.81", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 修复拖拽图标的时候出现文本选择光标问题", + "notes": [ + { + "name": "修复", + "descs": ["拖拽图标的时候出现文本选择光标问题"] + } + ] + }, + { + "version": "0.7.80", + "tags": ["beta"], + "author": "@Senku", + "msg": "更新[BoxJs]: 调整拖拽延迟", + "notes": [ + { + "name": "修复", + "descs": ["降低首页图标拖拽灵敏度,长按拖动"] + } + ] + }, + { + "version": "0.7.79", + "tags": ["beta"], + "author": "@Senku", + "msg": "更新[BoxJs]: 首页图标可自定义顺序", + "notes": [ + { + "name": "新增", + "descs": ["首页图标可拖拽自定义顺序"] + } + ] + }, + { + "version": "0.7.78", + "tags": ["beta"], + "author": "@chouchoui", + "msg": "更新[BoxJs]: 增加版本说明", + "notes": [ + { + "name": "新增", + "descs": [ + "偏好设置增加 HTTP Backend (Quantumult X)", + "说明: ", + "发现: Quantumult X 通过重写的方式访问 BoxJs 可能会导致无法删除备份的问题, 但通过 HTTP Backend 方式访问则正常。", + "建议: 改用 HTTP Backend 或 重写与 HTTP Backend 结合的方式访问 BoxJs", + "姿势: 见 使用文档 (悬浮按钮 > ?)" + ] + }, + { + "name": "优化", + "descs": ["增加底部空间避免悬浮按钮遮挡空间"] + }, + { + "name": "感谢", + "descs": ["@chouchoui PR"] + } + ] + }, + { + "version": "0.7.77", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 更新文案", + "notes": [ + { + "name": "更新", + "descs": ["部分文案"] + } + ] + }, + { + "version": "0.7.76", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 偏好设置内可以抹掉数据", + "notes": [ + { + "name": "新增", + "descs": ["偏好设置内可以抹掉数据"] + }, + { + "name": "说明", + "descs": [ + "抹掉:所有缓存", + "抹掉订阅及页面缓存,会导致所有订阅显示格式错误,双击底栏'订阅'菜单或更新订阅即可恢复", + "", + "抹掉:收藏应用", + "抹掉所有收藏的应用,排序出现问题时可尝试抹掉", + "", + "抹掉:用户偏好", + "抹掉头像、设置、收藏等个人相关的数据, 注意:不含会话、备份、缓存", + "", + "抹掉:所有会话", + "抹掉所有应用下的会话, 注意:不会抹掉当前会话", + "", + "抹掉:所有备份", + "抹掉所有全局备份, 注意:抹掉前可先把备份复制到其他文本类应用内", + "", + "抹掉:BoxJs", + "抹掉所有由 BoxJs 管理的数据, 如:备份、会话、偏好、缓存等 (不包含当前会话)" + ] + } + ] + }, + { + "version": "0.7.75", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 修复退出壁纸模式后壁纸无法还原问题", + "notes": [ + { + "name": "修复", + "descs": ["修复退出壁纸模式后壁纸无法还原问题"] + } + ] + }, + { + "version": "0.7.74", + "tags": ["beta"], + "author": "@lowking", + "msg": "更新[BoxJs]: 更方便快捷的看小姐姐", + "notes": [ + { + "name": "新增特性", + "descs": ["悬浮图标下滑进入壁纸模式自动切换到配置好的壁纸,退出同理"] + }, + { + "name": "感谢", + "descs": ["@lowking PR"] + } + ] + }, + { + "version": "0.7.73", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 修复小火箭环境下手动运行脚本报错问题", + "notes": [ + { + "name": "修复", + "descs": ["小火箭环境下手动运行脚本报错问题"] + } + ] + }, + { + "version": "0.7.72", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 适配小火箭, 感谢 @Orz-3 提供图标", + "notes": [ + { + "name": "适配", + "descs": ["Shadowrocket (小火箭)"] + }, + { + "name": "感谢", + "descs": ["@Orz-3 提供图标"] + } + ] + }, + { + "version": "0.7.71", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 修复备份数据异常导致无法进入页面问题", + "notes": [ + { + "name": "修复", + "descs": ["备份数据异常导致无法进入页面问题"] + } + ] + }, + { + "version": "0.7.69", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 移除 gitee 链接, 改用 github raw 及 jsdelivr", + "notes": [ + { + "name": "说明", + "descs": [ + "由于通过 gitee 访问部分仓库资源时出现 `根据相关法律政策,该内容无法显示`", + "虽然我手动同步 github 代码后已经可以正常访问", + "但为避免以后出现不可预知的情况:", + "我们把全部 gitee 链接替换为 github raw 及 jsdelivr", + "----", + "大家只需正常更新订阅并重启代理即可" + ] + }, + { + "name": "感谢", + "descs": ["@zZPiglet PR"] + } + ] + }, + { + "version": "0.7.68", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 订阅格式错误导致无法进入页面问题", + "notes": [ + { + "name": "修复", + "descs": ["订阅格式错误导致无法进入页面问题"] + } + ] + }, + { + "version": "0.7.67", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 自动替换 BoxJs 订阅中 Orz-3/mini 库的图标路径", + "notes": [ + { + "name": "修复", + "descs": ["Orz-3/mini 库图标路径"] + }, + { + "name": "注意", + "descs": [ + "如果订阅里有旧的图标路径,BoxJs 会自动转换为新路径,有问题请反馈" + ] + } + ] + }, + { + "version": "0.7.66", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 更新 Orz-3/mini 库图标路径", + "notes": [ + { + "name": "修复", + "descs": ["Orz-3/mini 库图标路径"] + } + ] + }, + { + "version": "0.7.65", + "tags": ["beta"], + "author": "@id77", + "msg": "更新[BoxJs]: 应用会话前,清空当前会话数据", + "notes": [ + { + "name": "优化", + "descs": ["应用会话前,清空当前会话数据"] + }, + { + "name": "感谢", + "descs": ["@id77 PR"] + } + ] + }, + { + "version": "0.7.64", + "tags": ["beta"], + "author": "@whyour", + "msg": "更新[BoxJs]: 增加只复制 App 数据为对象功能", + "notes": [ + { + "name": "增加", + "descs": ["只复制 App 数据为对象功能"] + }, + { + "name": "感谢", + "descs": ["@whyour PR"] + } + ] + }, + { + "version": "0.7.62", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 优化底栏按钮高亮样式", + "notes": [ + { + "name": "优化", + "descs": ["去掉底栏按钮高亮时的背景色"] + } + ] + }, + { + "version": "0.7.61", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 修复订阅为 null 时数据加载报错", + "notes": [ + { + "name": "修复", + "descs": [ + "由于网络问题,导致订阅数据异常后,访问页面时仅显示 BoxJs 字样问题。" + ] + } + ] + }, + { + "version": "0.7.60", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 增加判断 BoxJs 订阅格式判断", + "notes": [ + { + "name": "修复", + "descs": ["添加非 BoxJs 订阅时导致白屏问题"] + } + ] + }, + { + "version": "0.7.59", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: Vuetify 升级至 v2.4", + "notes": [ + { + "name": "优化", + "descs": ["升级 Vuetify 版本"] + } + ] + }, + { + "version": "0.7.58", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs]: 刷新订阅添加时间缀避免网络缓存", + "notes": [ + { + "name": "优化", + "descs": [ + "BoxJs 内的请求会可以被重写", + "刷新订阅添加时间缀避免网络缓存" + ] + } + ] + }, + { + "version": "0.7.56", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs TF]: 修复一处导致白屏逻辑", + "notes": [ + { + "name": "修复", + "descs": ["修复一处导致白屏逻辑"] + } + ] + }, + { + "version": "0.7.55", + "tags": ["beta"], + "author": "@chavyleung", + "msg": "更新[BoxJs TF]: 顶栏和底栏可以设置跟随滚动", + "notes": [ + { + "name": "新增", + "descs": ["顶栏和底栏可以设置跟随滚动"] + } + ] + }, + { + "version": "0.7.54", + "tags": ["beta"], + "author": "@id77", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 侧栏增加新的贡献者 @id77", + "notes": [ + { + "name": "贡献者", + "descs": ["新的贡献者 @id77"] + } + ] + }, + { + "version": "0.7.53", + "tags": ["beta"], + "author": "@GideonSenku", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 跟随系统壁纸设置同时支持中英文", + "notes": [ + { + "name": "新增", + "descs": ["跟随系统壁纸设置支持中英文,且优先考虑中文关键字"] + }, + { + "name": "说明", + "descs": ["中文关键字为`暗黑`和`明亮`,英文关键字不变"] + } + ] + }, + { + "version": "0.7.52", + "tags": ["beta"], + "author": "@id77 @chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 删除备份后直接回到首页问题", + "notes": [ + { + "name": "移除", + "descs": [ + "主屏幕的左右滑动手势", + "原因: 与浏览器前进后退容易发生冲突" + ] + }, + { + "name": "修复", + "descs": ["删除备份后直接回到首页问题"] + }, + { + "name": "优化", + "descs": ["页面后退事件逻辑", "部分侧栏设置的小字说明"] + } + ] + }, + { + "version": "0.7.49", + "tags": ["beta"], + "author": "@GideonSenku", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复主屏左滑时与侧栏冲突问题", + "notes": [ + { + "name": "新增", + "descs": ["背景图片可跟随系统调整"] + }, + { + "name": "调整", + "descs": ["背景清单图片默认`无`更改为`跟随系统`"] + }, + { + "name": "修复", + "descs": ["主屏左滑时与侧栏冲突问题"] + }, + { + "name": "说明", + "descs": [ + "背景图片清单中设置:无{换行} 跟随系统,跟随系统{换行} light,图片地址{换行} dark,图片地址{换行}", + "如果不设置`跟随系统,跟随系统`,则默认跟随系统为无背景" + ] + } + ] + }, + { + "version": "0.7.47", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复代码编辑器高度, 部分界面左右滑动范围问题", + "notes": [ + { + "name": "修复", + "descs": [ + "代码编辑器高度问题", + "部分界面只能在有内容的范围左右滑动问题" + ] + } + ] + }, + { + "version": "0.7.46", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 移除滑动动画, 勿扰模式不弹脚本执行结果页, 操作优化", + "notes": [ + { + "name": "优化", + "descs": [ + "勿扰模式下运行脚本不弹出结果页", + "壁纸模式下滑更容易退出壁纸模式" + ] + }, + { + "name": "移除", + "descs": ["左右滑动切换页面的动画"] + } + ] + }, + { + "version": "0.7.45", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复脚本执行结果、更新日志页面位置不正确, 主页左滑进入壁纸模式", + "notes": [ + { + "name": "新增", + "descs": ["主页左滑进入壁纸模式"] + }, + { + "name": "修复", + "descs": ["脚本执行结果、更新日志页面位置不正确"] + } + ] + }, + { + "version": "0.7.44", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 主屏幕左右滑动可切换 首页、应用、订阅、我的 页面", + "notes": [ + { + "name": "新增", + "descs": [ + "Surge、QuanX、Loon 手动运行脚本时都可以显示执行结果", + "主屏幕左右滑动可切换 首页、应用、订阅、我的 页面" + ] + }, + { + "name": "修复", + "descs": ["全局搜索结果位置不正确问题"] + } + ] + }, + { + "version": "0.7.43", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复非壁纸模式下上滑仍然重新渲染壁纸", + "notes": [ + { + "name": "新增", + "descs": [ + "在顶栏上滑可隐藏顶栏", + "在底栏下滑可以隐藏底栏", + "壁纸模式上滑可以重新渲染壁纸" + ] + }, + { + "name": "修复", + "descs": [ + "代码编辑器不显示问题", + "二次进入搜索界面无法自动获取焦点", + "非壁纸模式下上滑仍然重新渲染壁纸" + ] + } + ] + }, + { + "version": "0.7.41", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复顶栏隐藏时图标没往上挪, 悬浮按钮上滑切壁纸, 壁纸模式隐藏悬浮按钮", + "notes": [ + { + "name": "优化", + "descs": ["壁纸模式会把悬浮按钮也隐藏起来"] + }, + { + "name": "修复", + "descs": ["顶栏隐藏时图标没有往上挪"] + }, + { + "name": "悬浮按钮手势", + "descs": [ + "上滑: 重渲染&切换壁纸", + "左滑: 悬浮按钮左靠", + "右滑: 悬浮按钮右靠", + "下滑: 切换壁纸模式" + ] + }, + { + "name": "说明", + "descs": [ + "壁纸模式下: 下滑取消壁纸模式", + "非壁纸模式: 下滑显示\\隐藏顶栏" + ] + } + ] + }, + { + "version": "0.7.40", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 新增壁纸模式、悬浮按钮手势", + "notes": [ + { + "name": "新增", + "descs": ["壁纸模式", "悬浮按钮手势"] + }, + { + "name": "悬浮按钮手势", + "descs": [ + "上滑: 刷新页面 (效果同双击)", + "左滑: 悬浮按钮左靠", + "右滑: 悬浮按钮右靠", + "下滑: 切换壁纸模式" + ] + } + ] + }, + { + "version": "0.7.39", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 修复部分情况下拉出顶栏事件失效问题", + "notes": [ + { + "name": "修复", + "descs": ["部分情况下拉出顶栏事件失效问题"] + }, + { + "name": "优化", + "descs": ["原来顶部的加载条移到底栏上方"] + } + ] + }, + { + "version": "0.7.38", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 新增 Surge HTTP-API 环境下运行脚本会显示运行结果", + "notes": [ + { + "name": "新增", + "descs": ["Surge HTTP-API 环境下运行脚本会显示运行结果"] + }, + { + "name": "优化", + "descs": ["页面样式"] + }, + { + "name": "移除", + "descs": ["顶栏跟随滚动"] + } + ] + }, + { + "version": "0.7.37", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "msg": "更新[BoxJs TF]: 应用标题加阴影, 优化调试代码, 单击首页重渲染壁纸", + "notes": [ + { + "name": "优化", + "descs": ["应用标题加阴影"] + }, + { + "name": "调试", + "descs": ["优化代码"] + }, + { + "name": "新增", + "descs": ["单击首页回到顶部, 再单击一次重新渲染壁纸"] + }, + { + "name": "壁纸", + "descs": [ + "无背景,", + "随机,https://uploadbeta.com/api/pictures/random", + "推女郎,https://uploadbeta.com/api/pictures/random/?key=推女郎", + "性感,https://uploadbeta.com/api/pictures/random/?key=性感", + "车模,https://uploadbeta.com/api/pictures/random/?key=车模", + "美腿,https://uploadbeta.com/api/pictures/random/?key=美腿", + "美女,https://uploadbeta.com/api/pictures/random/?key=美女", + "手机妹子,http://api.btstu.cn/sjbz/zsy.php", + "手机美女,http://api.btstu.cn/sjbz/?m_lx=suiji" + ] + } + ] + }, + { + "version": "0.7.36", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["下拉显示&隐藏搜索栏"] + }, + { + "name": "优化", + "descs": ["固定背景"] + }, + { + "name": "修复", + "descs": ["搜索栏高度问题"] + } + ] + }, + { + "version": "0.7.35", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "调试", + "descs": ["调试模式下支持自定义页面源码地址"] + }, + { + "name": "修复", + "descs": [ + "底栏事件无效问题", + "部分情况下贡献者重复加载问题", + "手势前进后退会白屏&卡屏问题" + ] + } + ] + }, + { + "version": "0.7.33", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["支持前进、后退", "WebApp 状态下刷新能留在当前页面"] + }, + { + "name": "修复", + "descs": ["侧栏拉不到底缺陷"] + }, + { + "name": "调试", + "descs": ["支持 vue devtool (侧栏开启调试模式)"] + }, + { + "name": "感谢", + "descs": ["感谢 @id77 大佬 PR"] + } + ] + }, + { + "version": "0.7.30", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["首页背景可以一直固定住"] + }, + { + "name": "感谢", + "descs": ["感谢 @id77 大佬 PR"] + } + ] + }, + { + "version": "0.7.29", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "代码编辑器", + "descs": ["Surge HTTP-API 环境下执行的代码能显示响应内容"] + } + ] + }, + { + "version": "0.7.28", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["数据后端渲染", "更快更平顺的首页加载", "不闪屏了"] + }, + { + "name": "感谢", + "descs": ["感谢 @eslint 大佬提供帮助"] + } + ] + }, + { + "version": "0.7.27", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["首页样式", "操作体验"] + }, + { + "name": "首页", + "descs": ["顶栏透明", "可以隐藏顶栏", "顶栏可以固定或跟随滚动"] + }, + { + "name": "悬浮按钮", + "descs": ["增加搜索入口"] + } + ] + }, + { + "version": "0.7.26", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "调整", + "descs": ["搜索条样式", "搜索操作界面"] + } + ] + }, + { + "version": "0.7.24", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "修复", + "descs": ["解决首屏闪屏问题", "解决图标白边问题", "导入会话报错"] + }, + { + "name": "感谢", + "descs": ["感谢 @eslint 大佬提供帮助"] + } + ] + }, + { + "version": "0.7.21", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["一键清空会话数据"] + }, + { + "name": "优化", + "descs": ["壁纸状态下图标字体颜色为白色", "其他样式优化"] + } + ] + }, + { + "version": "0.7.20", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["勿扰模式下, 不再忽略手动执行脚本时发出的系统通知"] + }, + { + "name": "新增", + "descs": ["可以设置多张壁纸 (偏好设置)"] + }, + { + "name": "注意", + "descs": ["设置多张壁纸后,在侧栏切换"] + } + ] + }, + { + "version": "0.7.18", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["代码编辑器 (入口: 悬浮按钮)"] + }, + { + "name": "说明", + "descs": [ + "除了本机运行外", + "可以使用 PC 连上 QuanX 的 HTTP Backend", + "实现在 PC 上写代码然后发送到 QuanX 执行", + "Surge、Loon 同理" + ] + } + ] + }, + { + "version": "0.7.17", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["首页壁纸 (偏好设置)"] + } + ] + }, + { + "version": "0.7.16", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["首页图标样式"] + }, + { + "name": "修复", + "descs": [ + "首页图标点击无效问题", + "首页图标有轻微位移问题", + "帮助页面打开空白" + ] + } + ] + }, + { + "version": "0.7.11", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["首页显示收藏应用", "订阅中的更多按钮可以链接到作者仓库"] + } + ] + }, + { + "version": "0.7.9", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "新增", + "descs": ["可以修改会话", "增加帮忙手册入口", "推荐订阅入口"] + }, + { + "name": "调整", + "descs": ["调整加载动态效果"] + }, + { + "name": "修复", + "descs": ["boolean 控件偶尔触发键盘问题"] + } + ] + }, + { + "version": "0.7.7", + "tags": ["beta"], + "author": "@chavyleung", + "icon": "https://avatars3.githubusercontent.com/u/29748519", + "repo": "https://github.com/chavyleung", + "notes": [ + { + "name": "优化", + "descs": ["全程无刷新", "独立分离页面", "优化数据结构减少内存占用"] + }, + { + "name": "操作", + "descs": [ + "可以修复全局备份的名字", + "点击'应用'回到顶部,再次单击折叠面板", + "点击'订阅'回到顶部,再次单击刷新订阅", + "点击具体订阅可刷新" + ] + } + ] + } + ] +} diff --git a/box/rewrite/boxjs.rewrite.loon.plugin b/box/rewrite/boxjs.rewrite.loon.plugin new file mode 100644 index 000000000..7ba1bb70d --- /dev/null +++ b/box/rewrite/boxjs.rewrite.loon.plugin @@ -0,0 +1,15 @@ +#!name=BoxJs +#!desc=Data manager +#!openUrl=http://boxjs.com +#!author=chavyleung +#!homepage=https://chavyleung.gitbook.io/boxjs/ +#!icon=https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxJs.png + +[Rule] +DOMAIN-SUFFIX,jsdelivr.net,PROXY + +[Script] +http-request ^https?:\/\/(.+\.)?boxjs\.(com|net) script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/box/chavy.boxjs.js, requires-body=true, timeout=120, tag=BoxJs + +[MITM] +hostname = boxjs.com, boxjs.net, *.boxjs.com, *.boxjs.net diff --git a/box/rewrite/boxjs.rewrite.loon.tf.plugin b/box/rewrite/boxjs.rewrite.loon.tf.plugin new file mode 100644 index 000000000..78b01baf9 --- /dev/null +++ b/box/rewrite/boxjs.rewrite.loon.tf.plugin @@ -0,0 +1,15 @@ +#!name=BoxJs +#!desc=(TF)Data manager +#!openUrl=http://boxjs.net +#!author=chavyleung +#!homepage=https://chavyleung.gitbook.io/boxjs/ +#!icon=https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxJs.png + +[Rule] +DOMAIN-SUFFIX,jsdelivr.net,PROXY + +[Script] +http-request ^https?:\/\/(.+\.)?boxjs\.(com|net) script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/box/chavy.boxjs.js, requires-body=true, timeout=120, tag=BoxJs + +[MITM] +hostname = boxjs.com, boxjs.net, *.boxjs.com, *.boxjs.net diff --git a/box/rewrite/boxjs.rewrite.quanx.conf b/box/rewrite/boxjs.rewrite.quanx.conf new file mode 100644 index 000000000..0955c0896 --- /dev/null +++ b/box/rewrite/boxjs.rewrite.quanx.conf @@ -0,0 +1,3 @@ +hostname = boxjs.com, boxjs.net, *.boxjs.com, *.boxjs.net + +^https?:\/\/(.+\.)?boxjs\.(com|net) url script-analyze-echo-response https://raw.githubusercontent.com/chavyleung/scripts/master/box/chavy.boxjs.js diff --git a/box/rewrite/boxjs.rewrite.quanx.tf.conf b/box/rewrite/boxjs.rewrite.quanx.tf.conf new file mode 100644 index 000000000..0955c0896 --- /dev/null +++ b/box/rewrite/boxjs.rewrite.quanx.tf.conf @@ -0,0 +1,3 @@ +hostname = boxjs.com, boxjs.net, *.boxjs.com, *.boxjs.net + +^https?:\/\/(.+\.)?boxjs\.(com|net) url script-analyze-echo-response https://raw.githubusercontent.com/chavyleung/scripts/master/box/chavy.boxjs.js diff --git a/box/rewrite/boxjs.rewrite.stash.stoverride b/box/rewrite/boxjs.rewrite.stash.stoverride new file mode 100644 index 000000000..f974aa92a --- /dev/null +++ b/box/rewrite/boxjs.rewrite.stash.stoverride @@ -0,0 +1,31 @@ +name: "BoxJs" +desc: "http://boxjs.com" +openUrl: "http://boxjs.com" +author: "ChavyLeung" +homepage: "https://docs.boxjs.app/" +manual: "https://docs.boxjs.app/" +icon: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxJs.png" +category: "BoxJs" + +http: + force-http-engine: + - "boxjs.com:80" + - "boxjs.net:80" + - "*.boxjs.com:80" + - "*.boxjs.net:80" + mitm: + - "boxjs.com" + - "boxjs.net" + - "*.boxjs.com" + - "*.boxjs.net" + script: + - match: ^https?:\/\/(.+\.)?boxjs\.(com|net) + name: BoxJs + type: request + require-body: true + timeout: 120 + +script-providers: + BoxJs: + url: https://raw.githubusercontent.com/chavyleung/scripts/master/box/chavy.boxjs.js + interval: 86400 diff --git a/box/rewrite/boxjs.rewrite.stash.tf.stoverride b/box/rewrite/boxjs.rewrite.stash.tf.stoverride new file mode 100644 index 000000000..f974aa92a --- /dev/null +++ b/box/rewrite/boxjs.rewrite.stash.tf.stoverride @@ -0,0 +1,31 @@ +name: "BoxJs" +desc: "http://boxjs.com" +openUrl: "http://boxjs.com" +author: "ChavyLeung" +homepage: "https://docs.boxjs.app/" +manual: "https://docs.boxjs.app/" +icon: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxJs.png" +category: "BoxJs" + +http: + force-http-engine: + - "boxjs.com:80" + - "boxjs.net:80" + - "*.boxjs.com:80" + - "*.boxjs.net:80" + mitm: + - "boxjs.com" + - "boxjs.net" + - "*.boxjs.com" + - "*.boxjs.net" + script: + - match: ^https?:\/\/(.+\.)?boxjs\.(com|net) + name: BoxJs + type: request + require-body: true + timeout: 120 + +script-providers: + BoxJs: + url: https://raw.githubusercontent.com/chavyleung/scripts/master/box/chavy.boxjs.js + interval: 86400 diff --git a/box/rewrite/boxjs.rewrite.surge.sgmodule b/box/rewrite/boxjs.rewrite.surge.sgmodule new file mode 100644 index 000000000..b4d0c6c98 --- /dev/null +++ b/box/rewrite/boxjs.rewrite.surge.sgmodule @@ -0,0 +1,15 @@ +#!name=BoxJs +#!desc=http://boxjs.com +#!author=ChavyLeung +#!homepage=https://docs.boxjs.app/ +#!icon=https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxJs.png +#!category=BoxJs + +[General] +force-http-engine-hosts = %APPEND% boxjs.com, boxjs.net, *.boxjs.com, *.boxjs.net + +[Script] +Rewrite: BoxJs = type=http-request,pattern=^https?:\/\/(.+\.)?boxjs\.(com|net),script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/box/chavy.boxjs.js, requires-body=true, timeout=120 + +[MITM] +hostname = %INSERT% boxjs.com, boxjs.net, *.boxjs.com, *.boxjs.net diff --git a/box/rewrite/boxjs.rewrite.surge.tf.sgmodule b/box/rewrite/boxjs.rewrite.surge.tf.sgmodule new file mode 100644 index 000000000..b4d0c6c98 --- /dev/null +++ b/box/rewrite/boxjs.rewrite.surge.tf.sgmodule @@ -0,0 +1,15 @@ +#!name=BoxJs +#!desc=http://boxjs.com +#!author=ChavyLeung +#!homepage=https://docs.boxjs.app/ +#!icon=https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxJs.png +#!category=BoxJs + +[General] +force-http-engine-hosts = %APPEND% boxjs.com, boxjs.net, *.boxjs.com, *.boxjs.net + +[Script] +Rewrite: BoxJs = type=http-request,pattern=^https?:\/\/(.+\.)?boxjs\.(com|net),script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/box/chavy.boxjs.js, requires-body=true, timeout=120 + +[MITM] +hostname = %INSERT% boxjs.com, boxjs.net, *.boxjs.com, *.boxjs.net diff --git a/box/scripts/boxjs.revert.baks.js b/box/scripts/boxjs.revert.baks.js new file mode 100644 index 000000000..67eb234c8 --- /dev/null +++ b/box/scripts/boxjs.revert.baks.js @@ -0,0 +1,17 @@ +const $ = new Env('BoxJs - 抹掉备份') + +$.KEY_globalBaks = 'chavy_boxjs_globalBaks' +$.KEY_backups = 'chavy_boxjs_backups' + +const backups = $.getjson($.KEY_backups, []) +backups.forEach((backup) => $.setdata('', backup.id)) + +$.setdata('', $.KEY_backups) +$.setdata('', $.KEY_globalBaks) +$.done() + +/** + * EnvJs + */ +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/box/scripts/boxjs.revert.boxjs.js b/box/scripts/boxjs.revert.boxjs.js new file mode 100644 index 000000000..e1e16a951 --- /dev/null +++ b/box/scripts/boxjs.revert.boxjs.js @@ -0,0 +1,33 @@ +const $ = new Env('BoxJs - 抹掉 BoxJs') + +// 抹掉 订阅缓存 +$.KEY_app_subCaches = 'chavy_boxjs_app_subCaches' +$.setjson({}, $.KEY_app_subCaches) + +// 抹掉 页面缓存 +$.KEY_web_cache = 'chavy_boxjs_web_cache' +$.setjson({}, $.KEY_web_cache) + +// 抹掉 当前会话 +$.KEY_cursessions = 'chavy_boxjs_cur_sessions' +$.setjson({}, $.chavy_boxjs_cur_sessions) + +// 抹掉 全局备份 +$.KEY_globalBaks = 'chavy_boxjs_globalBaks' +$.setdata('', $.KEY_globalBaks) + +// 抹掉 应用会话 +$.KEY_sessions = 'chavy_boxjs_sessions' +$.setjson([], $.KEY_sessions) + +// 抹掉 用户编好 +$.KEY_usercfgs = 'chavy_boxjs_userCfgs' +$.setjson({}, $.KEY_usercfgs) + +$.done() + +/** + * EnvJs + */ +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/box/scripts/boxjs.revert.caches.js b/box/scripts/boxjs.revert.caches.js new file mode 100644 index 000000000..4331803ac --- /dev/null +++ b/box/scripts/boxjs.revert.caches.js @@ -0,0 +1,14 @@ +const $ = new Env('BoxJs - 抹掉缓存') + +$.KEY_app_subCaches = 'chavy_boxjs_app_subCaches' +$.setjson({}, $.KEY_app_subCaches) + +$.KEY_web_cache = 'chavy_boxjs_web_cache' +$.setjson({}, $.KEY_web_cache) +$.done() + +/** + * EnvJs + */ +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/box/scripts/boxjs.revert.usercfgs.debugger.js b/box/scripts/boxjs.revert.usercfgs.debugger.js new file mode 100644 index 000000000..5f54210e8 --- /dev/null +++ b/box/scripts/boxjs.revert.usercfgs.debugger.js @@ -0,0 +1,18 @@ +const $ = new Env('BoxJs - 抹掉调试地址') + +$.KEY_web_cache = 'chavy_boxjs_web_cache' +$.KEY_usercfgs = 'chavy_boxjs_userCfgs' + +const usercfgs = $.getjson($.KEY_usercfgs, {}) +usercfgs.isDebugWeb = false +usercfgs.debugger_web = '' + +$.setjson(usercfgs, $.KEY_usercfgs) +$.setjson({}, $.KEY_web_cache) +$.done() + +/** + * EnvJs + */ +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/box/scripts/boxjs.revert.usercfgs.favapps.js b/box/scripts/boxjs.revert.usercfgs.favapps.js new file mode 100644 index 000000000..80c8d2e98 --- /dev/null +++ b/box/scripts/boxjs.revert.usercfgs.favapps.js @@ -0,0 +1,15 @@ +const $ = new Env('BoxJs - 抹掉收藏应用') + +$.KEY_usercfgs = 'chavy_boxjs_userCfgs' + +const usercfgs = $.getjson($.KEY_usercfgs, {}) +usercfgs.favapps = [] + +$.setjson(usercfgs, $.KEY_usercfgs) +$.done() + +/** + * EnvJs + */ +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/box/scripts/boxjs.revert.usercfgs.httpbackend.js b/box/scripts/boxjs.revert.usercfgs.httpbackend.js new file mode 100644 index 000000000..7f4692b81 --- /dev/null +++ b/box/scripts/boxjs.revert.usercfgs.httpbackend.js @@ -0,0 +1,15 @@ +const $ = new Env('BoxJs - 抹掉 HTTP-Backend') + +$.KEY_usercfgs = 'chavy_boxjs_userCfgs' + +const usercfgs = $.getjson($.KEY_usercfgs, {}) +usercfgs.http_backend = '' + +$.setjson(usercfgs, $.KEY_usercfgs) +$.done() + +/** + * EnvJs + */ +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/box/scripts/boxjs.revert.usercfgs.js b/box/scripts/boxjs.revert.usercfgs.js new file mode 100644 index 000000000..bb67b018c --- /dev/null +++ b/box/scripts/boxjs.revert.usercfgs.js @@ -0,0 +1,12 @@ +const $ = new Env('BoxJs - 抹掉用户偏好') + +$.KEY_usercfgs = 'chavy_boxjs_userCfgs' + +$.setjson({}, $.KEY_usercfgs) +$.done() + +/** + * EnvJs + */ +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/box/scripts/boxjs.revert.usercfgs.sessions.js b/box/scripts/boxjs.revert.usercfgs.sessions.js new file mode 100644 index 000000000..d5ee0852b --- /dev/null +++ b/box/scripts/boxjs.revert.usercfgs.sessions.js @@ -0,0 +1,14 @@ +const $ = new Env('BoxJs - 抹掉会话') + +$.KEY_sessions = 'chavy_boxjs_sessions' +$.KEY_cursessions = 'chavy_boxjs_cur_sessions' + +$.setdata('[]', $.KEY_sessions) +$.setdata('{}', $.chavy_boxjs_cur_sessions) +$.done() + +/** + * EnvJs + */ +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/box/switcher/box.switcher.js b/box/switcher/box.switcher.js new file mode 100644 index 000000000..3f0dcd903 --- /dev/null +++ b/box/switcher/box.switcher.js @@ -0,0 +1,134 @@ +const $ = new Env('会话切换') +$.KEY_sessions = 'chavy_boxjs_sessions' +$.KEY_curSessions = 'chavy_boxjs_cur_sessions' +$.CFG_isSilent = $.getdata('CFG_BoxSwitcher_isSilent') + +$.appIds = + (globalThis.$intent?.parameter ?? globalThis.$argument)?.split(',') ?? [] + +!(async () => { + await execSwitch() + await showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +function execSwitch() { + if (Array.isArray($.appIds) && $.appIds.length) { + $.log(`指定切换: ${$.appIds.join(',')}`) + } + $.subt = '' + $.desc = [] + return new Promise((resove) => { + const sessions = getSessions() + const curSessions = getCurSessions() + // 会话排序: `创建时间`升序 + sessions.sort( + (a, b) => + a.createTime.replace(/-|:| /g, '') - b.createTime.replace(/-|:| /g, '') + ) + const apps = {} + sessions.forEach((session) => { + const appId = session.appId + if ($.appIds.length == 0 || $.appIds.includes(appId)) { + const appName = session.appName + apps[appId] = apps[appId] + ? apps[appId] + : { id: appId, name: appName, sessions: [] } + const app = apps[appId] + app.sessions.push(session) + } + }) + const switchkeys = {} + Object.keys(apps).forEach((appId) => { + const app = apps[appId] + if (app.sessions.length <= 1) { + $.desc.push(`${app.name}: 跳过! 原因: 只有 1 个会话?`) + return true + } + let curSessionIdx = app.sessions.findIndex( + (session) => session.id === curSessions[appId] + ) + if (curSessionIdx === -1) { + curSessionIdx = app.sessions.length - 1 + } + const curSession = app.sessions[curSessionIdx] + const isNewRound = curSessionIdx + 1 === app.sessions.length + const nextSessionIdx = isNewRound ? 0 : curSessionIdx + 1 + const nextSession = app.sessions[nextSessionIdx] + nextSession.datas.forEach((_data) => { + const key = _data.key + const val = [undefined, null, 'undefined', 'null', ''].includes( + _data.val + ) + ? '' + : _data.val + if (switchkeys[key]) { + const swData = switchkeys[key] + const isClash = swData.val !== val ? true : false + if (isClash) { + nextSession.isClash = true + $.log( + '', + `⚠️【${key}】冲突: `, + ` ${nextSession.appName}.${nextSession.name} => ${swData.session.appName}.${swData.session.name}` + ) + } + } else { + switchkeys[key] = {} + const swData = switchkeys[key] + swData.val = val + swData.session = nextSession + } + $.setdata(val, key) + }) + curSessions[appId] = nextSession.id + const clashstr = nextSession.isClash === true ? ' (冲突)' : '' + $.desc.push( + `${curSession.appName}: ${curSession.name} => #${nextSessionIdx + 1} ${nextSession.name}${clashstr} ${isNewRound ? '(新一轮)' : ''}` + ) + }) + $.setdata(JSON.stringify(curSessions), $.KEY_curSessions) + resove() + }) +} + +function getSessions() { + const sessionstr = $.getdata($.KEY_sessions) + const sessions = ![undefined, null, 'null', ''].includes(sessionstr) ? JSON.parse(sessionstr) : [] + return Array.isArray(sessions) ? sessions : [] +} + +function getCurSessions() { + const sessionstr = $.getdata($.KEY_curSessions) + return ![undefined, null, 'null', ''].includes(sessionstr) ? JSON.parse(sessionstr) : {} +} + +function showmsg() { + return new Promise((resolve) => { + const msgContent = $.desc.join('\n') + // 只有在Surge环境中,才使用特定的通知选项 + if ($.isSurge()) { + const options = { + "auto-dismiss": 2, // 2秒后自动消除通知 + "sound": true // 使用默认推送消息提示音 + } + if (!$.CFG_isSilent || $.CFG_isSilent === 'false') { + $notification.post($.name, $.subt, msgContent, options) + } else { + $.log('', ...$.desc) + } + } else { + // 在其他环境下,维持原有的消息显示逻辑 + if (!$.CFG_isSilent || $.CFG_isSilent === 'false') { + $.msg($.name, $.subt, msgContent) + } else { + $.log('', ...$.desc) + } + } + resolve() + }) +} + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise(((e,i)=>{s.call(this,t,((t,s,o)=>{t?i(t):e(s)}))}))}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.logLevels={debug:0,info:1,warn:2,error:3},this.logLevelPrefixs={debug:"[DEBUG] ",info:"[INFO] ",warn:"[WARN] ",error:"[ERROR] "},this.logLevel="info",this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null,...s){try{return JSON.stringify(t,...s)}catch{return e}}getjson(t,e){let s=e;if(this.getdata(t))try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise((e=>{this.get({url:t},((t,s,i)=>e(i)))}))}runScript(t,e){return new Promise((s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let o=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");o=o?1*o:20,o=e&&e.timeout?e.timeout:o;const[r,a]=i.split("@"),n={url:`http://${a}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:o},headers:{"X-Key":r,Accept:"*/*"},timeout:o};this.post(n,((t,e,i)=>s(i)))})).catch((t=>this.logErr(t)))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),o=JSON.stringify(this.data);s?this.fs.writeFileSync(t,o):i?this.fs.writeFileSync(e,o):this.fs.writeFileSync(t,o)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let o=t;for(const t of i)if(o=Object(o)[t],void 0===o)return s;return o}lodash_set(t,e,s){return Object(t)!==t||(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce(((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{}),t)[e[e.length-1]]=s),t}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),o=s?this.getval(s):"";if(o)try{const t=JSON.parse(o);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,o]=/^@(.*?)\.(.*?)$/.exec(e),r=this.getval(i),a=i?"null"===r?null:r||"{}":"{}";try{const e=JSON.parse(a);this.lodash_set(e,o,t),s=this.setval(JSON.stringify(e),i)}catch(e){const r={};this.lodash_set(r,o,t),s=this.setval(JSON.stringify(r),i)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.cookie&&void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar)))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),t.params&&(t.url+="?"+this.queryStr(t.params)),void 0===t.followRedirect||t.followRedirect||((this.isSurge()||this.isLoon())&&(t["auto-redirect"]=!1),this.isQuanX()&&(t.opts?t.opts.redirection=!1:t.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,((t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)}));break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then((t=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=t;e(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)}),(t=>e(t&&t.error||"UndefinedError")));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",((t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}})).then((t=>{const{statusCode:i,statusCode:o,headers:r,rawBody:a}=t,n=s.decode(a,this.encoding);e(null,{status:i,statusCode:o,headers:r,rawBody:a,body:n},n)}),(t=>{const{message:i,response:o}=t;e(i,o,o&&s.decode(o.rawBody,this.encoding))}));break}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),void 0===t.followRedirect||t.followRedirect||((this.isSurge()||this.isLoon())&&(t["auto-redirect"]=!1),this.isQuanX()&&(t.opts?t.opts.redirection=!1:t.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,((t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)}));break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then((t=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=t;e(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)}),(t=>e(t&&t.error||"UndefinedError")));break;case"Node.js":let i=require("iconv-lite");this.initGotEnv(t);const{url:o,...r}=t;this.got[s](o,r).then((t=>{const{statusCode:s,statusCode:o,headers:r,rawBody:a}=t,n=i.decode(a,this.encoding);e(null,{status:s,statusCode:o,headers:r,rawBody:a,body:n},n)}),(t=>{const{message:s,response:o}=t;e(s,o,o&&i.decode(o.rawBody,this.encoding))}));break}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}queryStr(t){let e="";for(const s in t){let i=t[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),e+=`${s}=${i}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",i="",o={}){const r=t=>{const{$open:e,$copy:s,$media:i,$mediaMime:o}=t;switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{const r={};let a=t.openUrl||t.url||t["open-url"]||e;a&&Object.assign(r,{action:"open-url",url:a});let n=t["update-pasteboard"]||t.updatePasteboard||s;if(n&&Object.assign(r,{action:"clipboard",text:n}),i){let t,e,s;if(i.startsWith("http"))t=i;else if(i.startsWith("data:")){const[t]=i.split(";"),[,o]=i.split(",");e=o,s=t.replace("data:","")}else{e=i,s=(t=>{const e={JVBERi0:"application/pdf",R0lGODdh:"image/gif",R0lGODlh:"image/gif",iVBORw0KGgo:"image/png","/9j/":"image/jpg"};for(var s in e)if(0===t.indexOf(s))return e[s];return null})(i)}Object.assign(r,{"media-url":t,"media-base64":e,"media-base64-mime":o??s})}return Object.assign(r,{"auto-dismiss":t["auto-dismiss"],sound:t.sound}),r}case"Loon":{const s={};let o=t.openUrl||t.url||t["open-url"]||e;o&&Object.assign(s,{openUrl:o});let r=t.mediaUrl||t["media-url"];return i?.startsWith("http")&&(r=i),r&&Object.assign(s,{mediaUrl:r}),console.log(JSON.stringify(s)),s}case"Quantumult X":{const o={};let r=t["open-url"]||t.url||t.openUrl||e;r&&Object.assign(o,{"open-url":r});let a=t["media-url"]||t.mediaUrl;i?.startsWith("http")&&(a=i),a&&Object.assign(o,{"media-url":a});let n=t["update-pasteboard"]||t.updatePasteboard||s;return n&&Object.assign(o,{"update-pasteboard":n}),console.log(JSON.stringify(o)),o}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,i,r(o));break;case"Quantumult X":$notify(e,s,i,r(o));break;case"Node.js":break}if(!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}debug(...t){this.logLevels[this.logLevel]<=this.logLevels.debug&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`${this.logLevelPrefixs.debug}${t.map((t=>t??String(t))).join(this.logSeparator)}`))}info(...t){this.logLevels[this.logLevel]<=this.logLevels.info&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`${this.logLevelPrefixs.info}${t.map((t=>t??String(t))).join(this.logSeparator)}`))}warn(...t){this.logLevels[this.logLevel]<=this.logLevels.warn&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`${this.logLevelPrefixs.warn}${t.map((t=>t??String(t))).join(this.logSeparator)}`))}error(...t){this.logLevels[this.logLevel]<=this.logLevels.error&&(t.length>0&&(this.logs=[...this.logs,...t]),console.log(`${this.logLevelPrefixs.error}${t.map((t=>t??String(t))).join(this.logSeparator)}`))}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.map((t=>t??String(t))).join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,e,t);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,e,void 0!==t.message?t.message:t,t.stack);break}}wait(t){return new Promise((e=>setTimeout(e,t)))}done(t={}){const e=((new Date).getTime()-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${e} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} \ No newline at end of file diff --git a/chavy.box.js b/chavy.box.js new file mode 100644 index 000000000..eb53b6468 --- /dev/null +++ b/chavy.box.js @@ -0,0 +1,1209 @@ +const $ = new Env('BoxJs') + +// 为 eval 准备的上下文环境 +const $eval_env = {} + +$.version = '0.19.29' +$.versionType = 'beta' + +// 发出的请求需要需要 Surge、QuanX 的 rewrite +$.isNeedRewrite = true + +/** + * =================================== + * 持久化属性: BoxJs 自有的数据结构 + * =================================== + */ + +// 存储`用户偏好` +$.KEY_usercfgs = 'chavy_boxjs_userCfgs' +// 存储`应用会话` +$.KEY_sessions = 'chavy_boxjs_sessions' +// 存储`页面缓存` +$.KEY_web_cache = 'chavy_boxjs_web_cache' +// 存储`应用订阅缓存` +$.KEY_app_subCaches = 'chavy_boxjs_app_subCaches' +// 存储`全局备份` (弃用, 改用 `chavy_boxjs_backups`) +$.KEY_globalBaks = 'chavy_boxjs_globalBaks' +// 存储`备份索引` +$.KEY_backups = 'chavy_boxjs_backups' +// 存储`当前会话` (配合切换会话, 记录当前切换到哪个会话) +$.KEY_cursessions = 'chavy_boxjs_cur_sessions' + +/** + * =================================== + * 持久化属性: BoxJs 公开的数据结构 + * =================================== + */ + +// 存储用户访问`BoxJs`时使用的域名 +$.KEY_boxjs_host = 'boxjs_host' + +// 请求响应体 (返回至页面的结果) +$.json = $.name // `接口`类请求的响应体 +$.html = $.name // `页面`类请求的响应体 + +// 页面源码地址 +$.web = `https://cdn.jsdelivr.net/gh/chavyleung/scripts@${ + $.version +}/box/chavy.boxjs.html?_=${new Date().getTime()}` +// 版本说明地址 (Release Note) +$.ver = `https://raw.githubusercontent.com/chavyleung/scripts/master/box/release/box.release.json` + +!(async () => { + // 勿扰模式 + $.isMute = [true, 'true'].includes($.getdata('@chavy_boxjs_userCfgs.isMute')) + + // 请求路径 + $.path = getPath($request.url) + + // 请求参数 /api/save?id=xx&name=xx => {id: 'xx', name: 'xx'} + const [, query] = $.path.split('?') + $.queries = query + ? query.split('&').reduce((obj, cur) => { + const [key, val] = cur.split('=') + obj[key] = val + return obj + }, {}) + : {} + + // 请求类型: GET + $.isGet = $request.method === 'GET' + // 请求类型: POST + $.isPost = $request.method === 'POST' + // 请求类型: OPTIONS + $.isOptions = $request.method === 'OPTIONS' + + // 请求类型: page、api、query + $.type = 'page' + // 查询请求: /query/xxx + $.isQuery = $.isGet && /^\/query\/.*?/.test($.path) + // 接口请求: /api/xxx + $.isApi = $.isPost && /^\/api\/.*?/.test($.path) + // 页面请求: /xxx + $.isPage = $.isGet && !$.isQuery && !$.isApi + + // 升级用户数据 + upgradeUserData() + // 升级备份数据 + upgradeGlobalBaks() + + // 处理预检请求 + if ($.isOptions) { + $.type = 'options' + await handleOptions() + } + // 处理`页面`请求 + else if ($.isPage) { + $.type = 'page' + await handlePage() + } + // 处理`查询`请求 + else if ($.isQuery) { + $.type = 'query' + await handleQuery() + } + // 处理`接口`请求 + else if ($.isApi) { + $.type = 'api' + await handleApi() + } +})() + .catch((e) => $.logErr(e)) + .finally(() => doneBox()) + +/** + * http://boxjs.com/ => `http://boxjs.com` + * http://boxjs.com/app/jd => `http://boxjs.com` + */ +function getHost(url) { + return url.slice(0, url.indexOf('/', 8)) +} + +/** + * http://boxjs.com/ => `` + * http://boxjs.com/api/getdata => `/api/getdata` + */ +function getPath(url) { + // 如果以`/`结尾, 去掉最后一个`/` + const end = url.lastIndexOf('/') === url.length - 1 ? -1 : undefined + // slice第二个参数传 undefined 会直接截到最后 + // indexOf第二个参数用来跳过前面的 "https://" + return url.slice(url.indexOf('/', 8), end) +} + +/** + * =================================== + * 处理前端请求 + * =================================== + */ + +/** + * 处理`页面`请求 + */ +async function handlePage() { + // 获取 BoxJs 数据 + const boxdata = getBoxData() + boxdata.syscfgs.isDebugMode = false + + // 调试模式: 是否每次都获取新的页面 + const isDebugWeb = [true, 'true'].includes( + $.getdata('@chavy_boxjs_userCfgs.isDebugWeb') + ) + const debugger_web = $.getdata('@chavy_boxjs_userCfgs.debugger_web') + const cache = $.getjson($.KEY_web_cache, null) + + // 如果没有开启调试模式,且当前版本与缓存版本一致,且直接取缓存 + if (!isDebugWeb && cache && cache.version === $.version) { + $.html = cache.cache + } + // 如果开启了调试模式,并指定了 `debugger_web` 则从指定的地址获取页面 + else { + if (isDebugWeb && debugger_web) { + // 调试地址后面拼时间缀, 避免 GET 缓存 + const isQueryUrl = debugger_web.includes('?') + $.web = `${debugger_web}${ + isQueryUrl ? '&' : '?' + }_=${new Date().getTime()}` + boxdata.syscfgs.isDebugMode = true + console.log(`[WARN] 调试模式: $.web = : ${$.web}`) + } + // 如果调用这个方法来获取缓存, 且标记为`非调试模式` + const getcache = () => { + console.log(`[ERROR] 调试模式: 正在使用缓存的页面!`) + boxdata.syscfgs.isDebugMode = false + return $.getjson($.KEY_web_cache).cache + } + await $.http.get($.web).then( + (resp) => { + if (/<title>BoxJs<\/title>/.test(resp.body)) { + // 返回页面源码, 并马上存储到持久化仓库 + $.html = resp.body + const cache = { version: $.version, cache: $.html } + $.setjson(cache, $.KEY_web_cache) + } else { + // 如果返回的页面源码不是预期的, 则从持久化仓库中获取 + $.html = getcache() + } + }, + // 如果获取页面源码失败, 则从持久化仓库中获取 + () => ($.html = getcache()) + ) + } + // 根据偏好设置, 替换首屏颜色 (如果是`auto`则交由页面自适应) + const theme = $.getdata('@chavy_boxjs_userCfgs.theme') + if (theme === 'light') { + $.html = $.html.replace('#121212', '#fff') + } else if (theme === 'dark') { + $.html = $.html.replace('#fff', '#121212') + } + /** + * 后端渲染数据, 感谢 https://t.me/eslint 提供帮助 + * + * 如果直接渲染到 box: null 会出现双向绑定问题 + * 所以先渲染到 `boxServerData: null` 再由前端 `this.box = this.boxServerData` 实现双向绑定 + */ + $.html = $.html.replace( + 'boxServerData: null', + 'boxServerData:' + JSON.stringify(boxdata) + ) + + // 调试模式支持 vue Devtools (只有在同时开启调试模式和指定了调试地址才生效) + // vue.min.js 生效时, 会导致 @click="window.open()" 报 "window" is not defined 错误 + if (isDebugWeb && debugger_web) { + $.html = $.html.replace('vue.min.js', 'vue.js') + } +} + +/** + * 处理`查询`请求 + */ +async function handleQuery() { + const referer = $request.headers.referer || $request.headers.Referer + if (!/^https?:\/\/(.+\.)?boxjs\.(com|net)\//.test(referer)) { + const isMuteQueryAlert = [true, 'true'].includes( + $.getdata('@chavy_boxjs_userCfgs.isMuteQueryAlert') + ) + + if (!isMuteQueryAlert) { + // 关闭静默状态 + const _isMute = $.isMute + $.isMute = false + + $.msg( + $.name, + '❗️发现有脚本或人正在读取你的数据', + [ + '请注意数据安全, 你可以: ', + '1. 在 BoxJs 的脚本日志中查看详情', + '2. 在 BoxJs 的页面 (侧栏) 中 "不显示查询警告"' + ].join('\n') + ) + + // 还原静默状态 + $.isMute = _isMute + } + + $.log( + [ + '', + '❗️❗️❗️ 发现有脚本或人正在读取你的数据 ❗️❗️❗️', + JSON.stringify($request), + '' + ].join('\n') + ) + } + + const [, query] = $.path.split('/query') + if (/^\/boxdata/.test(query)) { + $.json = getBoxData() + } else if (/^\/baks/.test(query)) { + const [, backupId] = query.split('/baks/') + $.json = $.getjson(backupId) + } else if (/^\/versions$/.test(query)) { + await getVersions(true) + } else if (/^\/data/.test(query)) { + const [, dataKey] = query.split('/data/') + $.json = { + key: dataKey, + val: $.getdata(dataKey) + } + } +} + +/** + * 处理 API 请求 + */ +async function handleApi() { + const [, api] = $.path.split('/api') + + const apiHandlers = { + '/save': apiSave, + '/addAppSub': apiAddAppSub, + '/deleteAppSub': apiDeleteAppSub, + '/reloadAppSub': apiReloadAppSub, + '/delGlobalBak': apiDelGlobalBak, + '/updateGlobalBak': apiUpdateGlobalBak, + '/saveGlobalBak': apiSaveGlobalBak, + '/impGlobalBak': apiImpGlobalBak, + '/revertGlobalBak': apiRevertGlobalBak, + '/runScript': apiRunScript, + '/saveData': apiSaveData, + '/surge': apiSurge, + '/update': apiUpdate + } + + for (const [key, handler] of Object.entries(apiHandlers)) { + if (api === key || api.startsWith(`${key}?`)) { + await handler() + break + } + } +} + +async function handleOptions() {} + +/** + * =================================== + * 获取基础数据 + * =================================== + */ + +function getBoxData() { + const datas = {} + + const extraDatas = + $.getdata(`${$.KEY_usercfgs.replace('#', '@')}.gist_cache_key`) || [] + + extraDatas.forEach((key) => { + datas[key] = $.getdata(key) + }) + + const usercfgs = getUserCfgs() + const sessions = getAppSessions() + const curSessions = getCurSessions() + const sysapps = getSystemApps() + const syscfgs = getSystemCfgs() + const appSubCaches = getAppSubCaches() + const globalbaks = getGlobalBaks() + + // 把 `内置应用`和`订阅应用` 里需要持久化属性放到`datas` + sysapps.forEach((app) => { + const newDatas = getAppDatas(app) + Object.assign(datas, newDatas) + }) + usercfgs.appsubs.forEach((sub) => { + const subcache = appSubCaches[sub.url] + if (subcache && subcache.apps && Array.isArray(subcache.apps)) { + subcache.apps.forEach((app) => { + const newDatas = getAppDatas(app) + Object.assign(datas, newDatas) + }) + } + }) + + const box = { + datas, + usercfgs, + sessions, + curSessions, + sysapps, + syscfgs, + appSubCaches, + globalbaks + } + + return box +} + +/** + * 获取系统配置 + */ +function getSystemCfgs() { + // prettier-ignore + return { + env: $.isStash() ? 'Stash' : $.isShadowrocket() ? 'Shadowrocket' : $.isLoon() ? 'Loon' : $.isQuanX() ? 'QuanX' : $.isEgern() ? 'Egern' : $.isSurge() ? 'Surge' : 'Node', + version: $.version, + versionType: $.versionType, + envs: [ + { id: 'Surge', icons: ['https://raw.githubusercontent.com/Orz-3/mini/none/surge.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/surge.png'] }, + { id: 'QuanX', icons: ['https://raw.githubusercontent.com/Orz-3/mini/none/quanX.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/quantumultx.png'] }, + { id: 'Loon', icons: ['https://raw.githubusercontent.com/Orz-3/mini/none/loon.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/loon.png'] }, + { id: 'Shadowrocket', icons: ['https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/shadowrocket.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/shadowrocket.png'] }, + { id: 'Stash', icons: ['https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/stash.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/stash.png'] }, + { id: 'Egern', icons: ['https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/appstore.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/appstore.png'] } + ], + chavy: { id: 'ChavyLeung', icon: 'https://avatars3.githubusercontent.com/u/29748519', repo: 'https://github.com/chavyleung/scripts' }, + senku: { id: 'GideonSenku', icon: 'https://avatars1.githubusercontent.com/u/39037656', repo: 'https://github.com/GideonSenku' }, + id77: { id: 'id77', icon: 'https://avatars0.githubusercontent.com/u/9592236', repo: 'https://github.com/id77' }, + orz3: { id: 'Orz-3', icon: 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/Orz-3.png', repo: 'https://github.com/Orz-3/' }, + boxjs: { id: 'BoxJs', show: false, icon: 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/box.png', icons: ['https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/box.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/box.png'], repo: 'https://github.com/chavyleung/scripts' }, + defaultIcons: ['https://raw.githubusercontent.com/Orz-3/mini/master/Alpha/appstore.png', 'https://raw.githubusercontent.com/Orz-3/mini/master/Color/appstore.png'] + } +} + +/** + * 获取内置应用 + */ +function getSystemApps() { + // prettier-ignore + const sysapps = [ + { + id: 'BoxSetting', + name: '偏好设置', + descs: ['可手动执行一些抹掉数据的脚本', '可设置明暗两种主题下的主色调', '可设置壁纸清单'], + keys: [ + '@chavy_boxjs_userCfgs.httpapi', + '@chavy_boxjs_userCfgs.bgimg', + '@chavy_boxjs_userCfgs.http_backend', + '@chavy_boxjs_userCfgs.color_dark_primary', + '@chavy_boxjs_userCfgs.color_light_primary' + ], + settings: [ + { id: '@chavy_boxjs_userCfgs.httpapis', name: 'HTTP-API (Surge)', val: '', type: 'textarea', placeholder: ',examplekey@127.0.0.1:6166', autoGrow: true, rows: 2, persistentHint:true, desc: '示例: ,examplekey@127.0.0.1:6166! 注意: 以逗号开头, 逗号分隔多个地址, 可加回车' }, + { id: '@chavy_boxjs_userCfgs.httpapi_timeout', name: 'HTTP-API Timeout (Surge)', val: 20, type: 'number', persistentHint:true, desc: '如果脚本作者指定了超时时间, 会优先使用脚本指定的超时时间.' }, + { id: '@chavy_boxjs_userCfgs.http_backend', name: 'HTTP Backend (Quantumult X)', val: '', type: 'text',placeholder: 'http://127.0.0.1:9999', persistentHint:true, desc: '示例: http://127.0.0.1:9999 ! 注意: 必须是以 http 开头的完整路径, 不能是 / 结尾' }, + { id: '@chavy_boxjs_userCfgs.debugger_webs', name: '调试地址', val: 'Dev体验,https://raw.githubusercontent.com/chavyleung/scripts/boxjs.dev/box/chavy.boxjs.html', type: 'textarea', placeholder: '每行一个配置,用逗号分割每个配置的名字和链接:配置,url', persistentHint:true, autoGrow: true, rows: 2, desc: '逗号分隔名字和链接, 回车分隔多个地址' }, + { id: '@chavy_boxjs_userCfgs.bgimgs', name: '背景图片清单', val: '无,\n跟随系统,跟随系统\nlight,http://api.btstu.cn/sjbz/zsy.php\ndark,https://uploadbeta.com/api/pictures/random\n妹子,http://api.btstu.cn/sjbz/zsy.php', type: 'textarea', placeholder: '无,{回车} 跟随系统,跟随系统{回车} light,图片地址{回车} dark,图片地址{回车} 妹子,图片地址', persistentHint:true, autoGrow: true, rows: 2, desc: '逗号分隔名字和链接, 回车分隔多个地址' }, + { id: '@chavy_boxjs_userCfgs.bgimg', name: '背景图片', val: '', type: 'text', placeholder: 'http://api.btstu.cn/sjbz/zsy.php', persistentHint:true, desc: '输入背景图标的在线链接' }, + { id: '@chavy_boxjs_userCfgs.changeBgImgEnterDefault', name: '手势进入壁纸模式默认背景图片', val: '', type: 'text', placeholder: '填写上面背景图片清单的值', persistentHint:true, desc: '' }, + { id: '@chavy_boxjs_userCfgs.changeBgImgOutDefault', name: '手势退出壁纸模式默认背景图片', val: '', type: 'text', placeholder: '填写上面背景图片清单的值', persistentHint:true, desc: '' }, + { id: '@chavy_boxjs_userCfgs.color_light_primary', name: '明亮色调', canvas: true, val: '#F7BB0E', type: 'colorpicker', desc: '' }, + { id: '@chavy_boxjs_userCfgs.color_dark_primary', name: '暗黑色调', canvas: true, val: '#2196F3', type: 'colorpicker', desc: '' } + ], + scripts: [ + { + name: "抹掉:所有缓存", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.caches.js" + }, + { + name: "抹掉:收藏应用", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.usercfgs.favapps.js" + }, + { + name: "抹掉:用户偏好", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.usercfgs.js" + }, + { + name: "抹掉:所有会话", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.usercfgs.sessions.js" + }, + { + name: "抹掉:所有备份", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.baks.js" + }, + { + name: "抹掉:BoxJs (注意备份)", + script: "https://raw.githubusercontent.com/chavyleung/scripts/master/box/scripts/boxjs.revert.boxjs.js" + } + ], + author: '@chavyleung', + repo: 'https://github.com/chavyleung/scripts/blob/master/box/switcher/box.switcher.js', + icons: [ + 'https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxSetting.mini.png', + 'https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxSetting.png' + ] + }, + { + id: 'BoxSwitcher', + name: '会话切换', + desc: '打开静默运行后, 切换会话将不再发出系统通知 \n注: 不影响日志记录', + keys: [], + settings: [{ id: 'CFG_BoxSwitcher_isSilent', name: '静默运行', val: false, type: 'boolean', desc: '切换会话时不发出系统通知!' }], + author: '@chavyleung', + repo: 'https://github.com/chavyleung/scripts/blob/master/box/switcher/box.switcher.js', + icons: [ + 'https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxSwitcher.mini.png', + 'https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxSwitcher.png' + ], + script: 'https://raw.githubusercontent.com/chavyleung/scripts/master/box/switcher/box.switcher.js' + }, + { + id: "BoxGist", + name: "Gist备份", + keys: [ + "@gist.token", + "@gist.username", + "@gist.split", + "@gist.revision_options", + "@gist.backup_type" + ], + author: "@dompling", + repo: "https://github.com/dompling/Script/tree/master/gist", + icons: [ + "https://raw.githubusercontent.com/Former-Years/icon/master/github-bf.png", + "https://raw.githubusercontent.com/Former-Years/icon/master/github-bf.png" + ], + descs_html: [ + "<h2>Token的获取方式</h2>", + "<ol>头像菜单 -></ol>", + "<ol>Settings -></ol>", + "<ol>Developer settings -></ol>", + "<ol>Personal access tokens -></ol>", + "<ol>Generate new token -></ol>", + "<ol>在里面找到 gist 勾选提交</ol>", + "<h2>Gist Revision Id</h2>", + "<ol>打开Gist项目</ol>", + "<ol>默认为Code,选择Revisions</ol>", + "<ol>找到需要恢复的版本文件</ol>", + "<ol>点击右上角【...】>【View file】</ol>", + "<ol>浏览器地址最后一串为 RevisionId</ol>" + ], + scripts: [ + { + name: "备份 Gist", + script: "https://raw.githubusercontent.com/dompling/Script/master/gist/backup.js" + }, + { + name: "从 Gist 恢复", + script: "https://raw.githubusercontent.com/dompling/Script/master/gist/restore.js" + }, + { + name: "更新历史版本", + script: "https://raw.githubusercontent.com/dompling/Script/master/gist/commit.js" + } + ], + settings: [ + { + id: "@gist.split", + name: "用户数据分段", + val: null, + type: "number", + placeholder: "用户数据过大时,请进行拆分防止内存警告⚠️", + desc: "值为数字,拆分段数比如 2 就拆分成两个 datas." + }, + { + id: "@gist.revision_id", + type: "modalSelects", + name: "历史版本RevisionId", + desc: "不填写时,默认获取最新,恢复后会自动清空。选择无内容时,请运行上方更新历史版本", + items: "@gist.revision_options" + }, + { + id: "@gist.backup_type", + name: "备份/恢复内容", + val: "usercfgs,datas,sessions,curSessions,backups,appSubCaches", + type: "checkboxes", + items: [ + { + key: "usercfgs", + label: "用户偏好" + }, + { + key: "datas", + label: "用户数据" + }, + { + key: "sessions", + label: "应用会话" + }, + { + key: "curSessions", + label: "当前会话" + }, + { + key: "backups", + label: "备份索引" + }, + { + key: "appSubCaches", + label: "应用订阅缓存" + } + ] + }, + { + id: "@gist.username", + name: "用户名", + val: null, + type: "text", + placeholder: "github 用户名", + desc: "必填" + }, + { + id: "@gist.token", + name: "Personal access tokens", + val: null, + type: "text", + placeholder: "github personal access tokens", + desc: "必填" + } + ] + } + ] + return sysapps +} + +/** + * 获取用户配置 + */ +function getUserCfgs() { + const defcfgs = { + gist_cache_key: [], + + favapps: [], + appsubs: [], + viewkeys: [], + isPinedSearchBar: true, + httpapi: 'examplekey@127.0.0.1:6166', + http_backend: '' + } + const usercfgs = Object.assign(defcfgs, $.getjson($.KEY_usercfgs, {})) + + // 处理异常数据:删除所有为 null 的订阅 + if (usercfgs.appsubs.includes(null)) { + usercfgs.appsubs = usercfgs.appsubs.filter((sub) => sub) + $.setjson(usercfgs, $.KEY_usercfgs) + } + + return usercfgs +} + +/** + * 获取`应用订阅`缓存 + */ +function getAppSubCaches() { + return $.getjson($.KEY_app_subCaches, {}) +} + +/** + * 获取全局备份列表 + */ +function getGlobalBaks() { + let backups = $.getjson($.KEY_backups, []) + + // 处理异常数据:删除所有为 null 的备份 + if (backups.includes(null)) { + backups = backups.filter((bak) => bak) + $.setjson(backups, $.KEY_backups) + } + + return backups +} + +/** + * 获取版本清单 + */ +function getVersions() { + return $.http.get($.ver).then( + (resp) => { + try { + $.json = $.toObj(resp.body) + } catch { + $.json = {} + } + }, + () => ($.json = {}) + ) +} + +/** + * 获取应用会话 + */ +function getAppSessions() { + return $.getjson($.KEY_sessions, []) || [] +} + +/** + * 获取当前切换到哪个会话 + */ +function getCurSessions() { + return $.getjson($.KEY_cursessions, {}) || {} +} + +/** + * =================================== + * 接口类函数 + * =================================== + */ + +function getAppDatas(app) { + const datas = {} + const nulls = [null, undefined, 'null', 'undefined'] + if (app.keys && Array.isArray(app.keys)) { + app.keys.forEach((key) => { + const val = $.getdata(key) + datas[key] = nulls.includes(val) ? null : val + }) + } + if (app.settings && Array.isArray(app.settings)) { + app.settings.forEach((setting) => { + const key = setting.id + const dataval = $.getdata(key) + datas[key] = nulls.includes(dataval) ? null : dataval + + if (setting.type === 'boolean') { + setting.val = nulls.includes(dataval) + ? setting.val + : dataval === 'true' || dataval === true + } else if (setting.type === 'int') { + setting.val = dataval * 1 || setting.val + } else if (setting.type === 'checkboxes') { + if (!nulls.includes(dataval) && typeof dataval === 'string') { + setting.val = dataval ? dataval.split(',') : [] + } else { + setting.val = Array.isArray(setting.val) + ? setting.val + : setting.val.split(',') + } + } else { + setting.val = dataval || setting.val + } + + if (setting.type === 'modalSelects') { + setting.items = datas?.[setting.items] || [] + } + }) + } + return datas +} + +function dealKey(str) { + const [rootKey, delIndex] = str.split('.') + if (rootKey && rootKey.indexOf('@') > -1 && delIndex !== undefined) { + const key = rootKey.replace('@', '') + const datas = JSON.parse($.getdata(key)) + if (Array.isArray(datas) && delIndex <= datas.length - 1) { + datas.splice(delIndex, 1) + $.setdata(JSON.stringify(datas), key) + } + } +} + +async function apiSave() { + const data = $.toObj($request.body) + if (Array.isArray(data)) { + data.forEach((dat) => { + if (dat.val === null) { + dealKey(dat.key) + } else { + $.setdata(dat.val, dat.key) + } + }) + } else { + if (data.val === null) { + dealKey(data.key) + } else { + $.setdata(data.val, data.key) + } + } + + const appId = $.queries['appid'] + if (appId) { + updateCurSesssions(appId, data) + } + + $.json = getBoxData() +} + +async function apiUpdate() { + const data = $.toObj($request.body) + const path = data.path.split('.') + const val = data.val + const key = path.shift() + // 必须用 hasOwnProperty:val 为 false 时 data.val && … 会误判为跳过更新 + if (path.join('.') && Object.prototype.hasOwnProperty.call(data, 'val')) { + switch (key) { + case 'usercfgs': + const usercfgs = getUserCfgs() + update(usercfgs, path.join('.'), val) + $.setjson(usercfgs, $.KEY_usercfgs) + break + default: + break + } + } + $.json = getBoxData() +} + +async function apiAddAppSub() { + const sub = $.toObj($request.body) + // 添加订阅 + const usercfgs = getUserCfgs() + usercfgs.appsubs.push(sub) + $.setjson(usercfgs, $.KEY_usercfgs) + // 加载订阅缓存 + await reloadAppSubCache(sub.url) + $.json = getBoxData() +} + +async function apiDeleteAppSub() { + const sub = $.toObj($request.body) + // 添加订阅 + const usercfgs = getUserCfgs() + usercfgs.appsubs = usercfgs.appsubs.filter((e) => e.url !== sub.url) + $.setjson(usercfgs, $.KEY_usercfgs) + $.json = getBoxData() +} + +async function apiReloadAppSub() { + const sub = $.toObj($request.body) + if (sub) { + await reloadAppSubCache(sub.url) + } else { + await reloadAppSubCaches() + } + $.json = getBoxData() +} + +async function apiDelGlobalBak() { + const backup = $.toObj($request.body) + const backups = $.getjson($.KEY_backups, []) + const bakIdx = backups.findIndex((b) => b.id === backup.id) + if (bakIdx > -1) { + backups.splice(bakIdx, 1) + $.setdata('', backup.id) + $.setjson(backups, $.KEY_backups) + } + $.json = getBoxData() +} + +async function apiUpdateGlobalBak() { + const { id: backupId, name: backupName } = $.toObj($request.body) + const backups = $.getjson($.KEY_backups, []) + const backup = backups.find((b) => b.id === backupId) + if (backup) { + backup.name = backupName + $.setjson(backups, $.KEY_backups) + } + $.json = getBoxData() +} + +async function apiRevertGlobalBak() { + const { id: bakcupId } = $.toObj($request.body) + const backup = $.getjson(bakcupId) + if (backup) { + const { + chavy_boxjs_sysCfgs, + chavy_boxjs_sysApps, + chavy_boxjs_sessions, + chavy_boxjs_userCfgs, + chavy_boxjs_cur_sessions, + chavy_boxjs_app_subCaches, + ...datas + } = backup + $.setdata(JSON.stringify(chavy_boxjs_sessions), $.KEY_sessions) + $.setdata(JSON.stringify(chavy_boxjs_userCfgs), $.KEY_usercfgs) + $.setdata(JSON.stringify(chavy_boxjs_cur_sessions), $.KEY_cursessions) + $.setdata(JSON.stringify(chavy_boxjs_app_subCaches), $.KEY_app_subCaches) + const isNull = (val) => + [undefined, null, 'null', 'undefined', ''].includes(val) + Object.keys(datas).forEach((datkey) => + $.setdata(isNull(datas[datkey]) ? '' : `${datas[datkey]}`, datkey) + ) + } + const boxdata = getBoxData() + $.json = boxdata +} + +async function apiSaveGlobalBak() { + const backups = $.getjson($.KEY_backups, []) + const boxdata = getBoxData() + const backup = $.toObj($request.body) + const backupData = {} + backupData['chavy_boxjs_userCfgs'] = boxdata.usercfgs + backupData['chavy_boxjs_sessions'] = boxdata.sessions + backupData['chavy_boxjs_cur_sessions'] = boxdata.curSessions + backupData['chavy_boxjs_app_subCaches'] = boxdata.appSubCaches + Object.assign(backupData, boxdata.datas) + backups.push(backup) + $.setjson(backups, $.KEY_backups) + $.setjson(backupData, backup.id) + $.json = getBoxData() +} + +async function apiImpGlobalBak() { + const backups = $.getjson($.KEY_backups, []) + const backup = $.toObj($request.body) + const backupData = backup.bak + delete backup.bak + backups.push(backup) + $.setjson(backups, $.KEY_backups) + $.setjson(backupData, backup.id) + $.json = getBoxData() +} + +async function apiRunScript() { + // 取消勿扰模式 + $.isMute = false + const opts = $.toObj($request.body) + const httpapi = $.getdata('@chavy_boxjs_userCfgs.httpapi') + const ishttpapi = /.*?@.*?:[0-9]+/.test(httpapi) + let script_text = null + if (opts.isRemote) { + await $.getScript(opts.url).then((script) => (script_text = script)) + } else { + script_text = opts.script + } + if (opts.argument) { + script_text = `globalThis.$argument=\`${opts.argument}\`;${script_text}` + } + if ( + $.isSurge() && + !$.isLoon() && + !$.isShadowrocket() && + !$.isStash() && + ishttpapi + ) { + const runOpts = { timeout: opts.timeout } + await $.runScript(script_text, runOpts).then( + (resp) => ($.json = JSON.parse(resp)) + ) + } else { + const result = await new Promise((resolve) => { + $eval_env.resolve = resolve + // 避免被执行脚本误认为是 rewrite 环境 + // 所以需要 `$request = undefined` + $eval_env.request = $request + $request = undefined + // 重写 console.log, 把日志记录到 $eval_env.cached_logs + $eval_env.cached_logs = [] + console.cloned_log = console.log + console.log = (l) => { + console.cloned_log(l) + $eval_env.cached_logs.push(l) + } + // 重写脚本内的 $done, 调用 $done() 即是调用 $eval_env.resolve() + script_text = script_text.replace(/\$done/g, '$eval_env.resolve') + script_text = script_text.replace(/\$\.done/g, '$eval_env.resolve') + try { + eval(script_text) + } catch (e) { + $eval_env.cached_logs.push(e) + resolve() + } + }) + // 还原 console.log + console.log = console.cloned_log + // 还原 $request + $request = $eval_env.request + // 返回数据 + $.json = { + result, + output: $eval_env.cached_logs.join('\n') + } + } +} + +async function apiSurge() { + const opts = $.toObj($request.body) + const httpapi = $.getdata('@chavy_boxjs_userCfgs.httpapi') + const ishttpapi = /.*?@.*?:[0-9]+/.test(httpapi) + if ( + $.isSurge() && + !$.isLoon() && + !$.isShadowrocket() && + !$.isStash() && + ishttpapi + ) { + const [key, prefix] = httpapi.split('@') + opts.url = `http://${prefix}/${opts.url}` + opts.headers = { + 'X-Key': key, + 'Accept': 'application/json, text/plain, */*' + } + await new Promise((resolve) => { + $[opts.method.toLowerCase()](opts, (_, __, resp) => { + $.json = JSON.parse(resp) + resolve($.json) + }) + }) + } +} + +async function apiSaveData() { + const { key: dataKey, val: dataVal } = $.toObj($request.body) + $.setdata(dataVal, dataKey) + $.json = { + key: dataKey, + val: $.getdata(dataKey) + } +} + +/** + * =================================== + * 工具类函数 + * =================================== + */ + +function reloadAppSubCache(url) { + // 地址后面拼时间缀, 避免 GET 缓存 + const requrl = `${url}${ + url.includes('?') ? '&' : '?' + }_=${new Date().getTime()}` + return $.http.get(requrl).then((resp) => { + try { + const subcaches = getAppSubCaches() + subcaches[url] = $.toObj(resp.body) + subcaches[url].updateTime = new Date() + // 仅缓存存在 id 的订阅 + Object.keys(subcaches).forEach((key) => { + if (!subcaches[key].hasOwnProperty('id')) { + delete subcaches[key] + } + }) + $.setjson(subcaches, $.KEY_app_subCaches) + $.log(`更新订阅, 成功! ${url}`) + } catch (e) { + $.logErr(e) + $.log(`更新订阅, 失败! ${url}`) + } + }) +} + +function update(obj, path, value) { + const keys = path.split('.') + let current = obj + + for (let i = 0; i < keys.length - 1; i++) { + if (!current[keys[i]]) { + current[keys[i]] = {} + } + current = current[keys[i]] + } + + current[keys[keys.length - 1]] = value +} + +// 自定义并发控制函数 +async function limitConcurrency(tasks, limit) { + const results = [] + const executing = [] + + for (const task of tasks) { + const promise = task() // 执行任务 + results.push(promise) + + if (executing.length >= limit) { + await Promise.race(executing) + } + + executing.push(promise) + promise + .then(() => { + const index = executing.indexOf(promise) + if (index !== -1) executing.splice(index, 1) + }) + .catch(() => { + const index = executing.indexOf(promise) + if (index !== -1) executing.splice(index, 1) + }) + } + + return Promise.all(results) +} + +async function reloadAppSubCaches() { + $.msg($.name, '更新订阅: 开始!') + const reloadActs = [] + const usercfgs = getUserCfgs() + + // 收集所有任务(函数形式) + usercfgs.appsubs.forEach((sub) => { + reloadActs.push(() => reloadAppSubCache(sub.url)) // 存储函数而不是立即执行的 Promise + }) + + // 使用并发限制执行任务 + await limitConcurrency(reloadActs, 20) // 限制并发数为 20 + + $.log(`全部订阅, 完成!`) + const endTime = new Date().getTime() + const costTime = (endTime - $.startTime) / 1000 + $.msg($.name, `更新订阅: 完成! 🕛 ${costTime} 秒`) +} + +function upgradeUserData() { + const usercfgs = getUserCfgs() + // 如果存在`usercfgs.appsubCaches`则需要升级数据 + const isNeedUpgrade = !!usercfgs.appsubCaches + if (isNeedUpgrade) { + // 迁移订阅缓存至独立的持久化空间 + $.setjson(usercfgs.appsubCaches, $.KEY_app_subCaches) + // 移除用户偏好中的订阅缓存 + delete usercfgs.appsubCaches + usercfgs.appsubs.forEach((sub) => { + delete sub._raw + delete sub.apps + delete sub.isErr + delete sub.updateTime + }) + } + if (isNeedUpgrade) { + $.setjson(usercfgs, $.KEY_usercfgs) + } +} + +/** + * 升级备份数据 + * + * 升级前: 把所有备份都存到一个持久化空间 + * 升级后: 把每个备份都独立存到一个空间, `$.KEY_backups` 仅记录必要的数据索引 + */ +function upgradeGlobalBaks() { + let oldbaks = $.getdata($.KEY_globalBaks) + let newbaks = $.getjson($.KEY_backups, []) + const isEmpty = (bak) => [undefined, null, ''].includes(bak) + const isExistsInNew = (backupId) => newbaks.find((bak) => bak.id === backupId) + + // 存在旧备份数据时, 升级备份数据格式 + if (!isEmpty(oldbaks)) { + oldbaks = JSON.parse(oldbaks) + oldbaks.forEach((bak) => { + if (isEmpty(bak)) return + if (isEmpty(bak.bak)) return + if (isExistsInNew(bak.id)) return + + console.log(`正在迁移: ${bak.name}`) + const backupId = bak.id + const backupData = bak.bak + + // 删除旧的备份数据, 仅保留索引信息 + delete bak.bak + newbaks.push(bak) + + // 提取旧备份数据, 存入独立的持久化空间 + $.setjson(backupData, backupId) + }) + $.setjson(newbaks, $.KEY_backups) + } + + // 清空所有旧备份的数据 + $.setdata('', $.KEY_globalBaks) +} + +function updateCurSesssions(appId, data) { + if (!appId) { + console.log(`[updateCurSesssions] 跳过! 没有指定 appId!`) + return + } + + const curSessions = getCurSessions() + const curSessionId = curSessions[appId] + if (!curSessionId) { + console.log( + `[updateCurSesssions] 跳过! 应用 [${appId}] 找不到当前会话, 请先应用会话!` + ) + return + } + + const sessions = getAppSessions() + const session = sessions.find((session) => session.id === curSessionId) + if (!session) { + console.log( + `[updateCurSesssions] 跳过! 应用 [${appId}] 找不到当前会话, 请先应用会话!` + ) + return + } + + session.datas = data + $.setjson(sessions, $.KEY_sessions) +} + +/** + * =================================== + * 结束类函数 + * =================================== + */ +function doneBox() { + // 记录当前使用哪个域名访问 + $.setdata(getHost($request.url), $.KEY_boxjs_host) + if ($.isOptions) doneOptions() + else if ($.isPage) donePage() + else if ($.isQuery) doneQuery() + else if ($.isApi) doneApi() + else $.done() +} + +function getBaseDoneHeaders(mixHeaders = {}) { + return Object.assign( + { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'POST,GET,OPTIONS,PUT,DELETE', + 'Access-Control-Allow-Headers': + 'Origin, X-Requested-With, Content-Type, Accept' + }, + mixHeaders + ) +} + +function getHtmlDoneHeaders() { + return getBaseDoneHeaders({ + 'Content-Type': 'text/html;charset=UTF-8' + }) +} +function getJsonDoneHeaders() { + return getBaseDoneHeaders({ + 'Content-Type': 'application/json; charset=utf-8' + }) +} + +function doneOptions() { + const headers = getBaseDoneHeaders() + if ($.isQuanX()) $.done({ headers }) + else $.done({ response: { headers } }) +} + +function donePage() { + const headers = getHtmlDoneHeaders() + if ($.isQuanX()) $.done({ status: 'HTTP/1.1 200', headers, body: $.html }) + else $.done({ response: { status: 200, headers, body: $.html } }) +} + +function doneQuery() { + $.json = $.toStr($.json) + const headers = getJsonDoneHeaders() + if ($.isQuanX()) $.done({ status: 'HTTP/1.1 200', headers, body: $.json }) + else $.done({ response: { status: 200, headers, body: $.json } }) +} + +function doneApi() { + $.json = $.toStr($.json) + const headers = getJsonDoneHeaders() + if ($.isQuanX()) $.done({ status: 'HTTP/1.1 200', headers, body: $.json }) + else $.done({ response: { status: 200, headers, body: $.json } }) +} + +/** + * EnvJs + */ +//prettier-ignore +function Env(e,t){class s{constructor(e){this.env=e}send(e,t="GET"){e="string"==typeof e?{url:e}:e;let s=this.get;"POST"===t&&(s=this.post);const i=new Promise((t,i)=>{s.call(this,e,(e,s,o)=>{e?i(e):t(s)})});return e.timeout?((e,t=1e3)=>Promise.race([e,new Promise((e,s)=>{setTimeout(()=>{s(new Error("请求超时"))},t)})]))(i,e.timeout):i}get(e){return this.send.call(this.env,e)}post(e){return this.send.call(this.env,e,"POST")}}return new class{constructor(e,t){this.logLevels={debug:0,info:1,warn:2,error:3},this.logLevelPrefixs={debug:"[DEBUG] ",info:"[INFO] ",warn:"[WARN] ",error:"[ERROR] "},this.logLevel="info",this.name=e,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,t),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof Egern?"Egern":"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}isEgern(){return"Egern"===this.getEnv()}toObj(e,t=null){try{return JSON.parse(e)}catch{return t}}toStr(e,t=null,...s){try{return JSON.stringify(e,...s)}catch{return t}}getjson(e,t){let s=t;if(this.getdata(e))try{s=JSON.parse(this.getdata(e))}catch{}return s}setjson(e,t){try{return this.setdata(JSON.stringify(e),t)}catch{return!1}}getScript(e){return new Promise(t=>{this.get({url:e},(e,s,i)=>t(i))})}runScript(e,t){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let o=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");o=o?1*o:20,o=t&&t.timeout?t.timeout:o;const[r,a]=i.split("@"),n={url:`http://${a}/v1/scripting/evaluate`,body:{script_text:e,mock_type:"cron",timeout:o},headers:{"X-Key":r,Accept:"*/*"},policy:"DIRECT",timeout:o};this.post(n,(e,t,i)=>s(i))}).catch(e=>this.logErr(e))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const e=this.path.resolve(this.dataFile),t=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(e),i=!s&&this.fs.existsSync(t);if(!s&&!i)return{};{const i=s?e:t;try{return JSON.parse(this.fs.readFileSync(i))}catch(e){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const e=this.path.resolve(this.dataFile),t=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(e),i=!s&&this.fs.existsSync(t),o=JSON.stringify(this.data);s?this.fs.writeFileSync(e,o):i?this.fs.writeFileSync(t,o):this.fs.writeFileSync(e,o)}}lodash_get(e,t,s=void 0){const i=t.replace(/\[(\d+)\]/g,".$1").split(".");let o=e;for(const e of i)if(o=Object(o)[e],void 0===o)return s;return o}lodash_set(e,t,s){return Object(e)!==e||(Array.isArray(t)||(t=t.toString().match(/[^.[\]]+/g)||[]),t.slice(0,-1).reduce((e,s,i)=>Object(e[s])===e[s]?e[s]:e[s]=(Math.abs(t[i+1])|0)===+t[i+1]?[]:{},e)[t[t.length-1]]=s),e}getdata(e){let t=this.getval(e);if(/^@/.test(e)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(e),o=s?this.getval(s):"";if(o)try{const e=JSON.parse(o);t=e?this.lodash_get(e,i,""):t}catch(e){t=""}}return t}setdata(e,t){let s=!1;if(/^@/.test(t)){const[,i,o]=/^@(.*?)\.(.*?)$/.exec(t),r=this.getval(i),a=i?"null"===r?null:r||"{}":"{}";try{const t=JSON.parse(a);this.lodash_set(t,o,e),s=this.setval(JSON.stringify(t),i)}catch(t){const r={};this.lodash_set(r,o,e),s=this.setval(JSON.stringify(r),i)}}else s=this.setval(e,t);return s}getval(e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":return $persistentStore.read(e);case"Quantumult X":return $prefs.valueForKey(e);case"Node.js":return this.data=this.loaddata(),this.data[e];default:return this.data&&this.data[e]||null}}setval(e,t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":return $persistentStore.write(e,t);case"Quantumult X":return $prefs.setValueForKey(e,t);case"Node.js":return this.data=this.loaddata(),this.data[t]=e,this.writedata(),!0;default:return this.data&&this.data[t]||null}}initGotEnv(e){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,e&&(e.headers=e.headers?e.headers:{},e&&(e.headers=e.headers?e.headers:{},void 0===e.headers.cookie&&void 0===e.headers.Cookie&&void 0===e.cookieJar&&(e.cookieJar=this.ckjar)))}get(e,t=()=>{}){switch(e.headers&&(delete e.headers["Content-Type"],delete e.headers["Content-Length"],delete e.headers["content-type"],delete e.headers["content-length"]),e.params&&(e.url+="?"+this.queryStr(e.params)),void 0===e.followRedirect||e.followRedirect||((this.isSurge()||this.isLoon())&&(e["auto-redirect"]=!1),this.isQuanX()&&(e.opts?e.opts.redirection=!1:e.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":default:this.isSurge()&&this.isNeedRewrite&&(e.headers=e.headers||{},Object.assign(e.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(e,(e,s,i)=>{!e&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),t(e,s,i)});break;case"Quantumult X":this.isNeedRewrite&&(e.opts=e.opts||{},Object.assign(e.opts,{hints:!1})),$task.fetch(e).then(e=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=e;t(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)},e=>t(e&&e.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(e),this.got(e).on("redirect",(e,t)=>{try{if(e.headers["set-cookie"]){const s=e.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),t.cookieJar=this.ckjar}}catch(e){this.logErr(e)}}).then(e=>{const{statusCode:i,statusCode:o,headers:r,rawBody:a}=e,n=s.decode(a,this.encoding);t(null,{status:i,statusCode:o,headers:r,rawBody:a,body:n},n)},e=>{const{message:i,response:o}=e;t(i,o,o&&s.decode(o.rawBody,this.encoding))})}}post(e,t=()=>{}){const s=e.method?e.method.toLocaleLowerCase():"post";switch(e.body&&e.headers&&!e.headers["Content-Type"]&&!e.headers["content-type"]&&(e.headers["content-type"]="application/x-www-form-urlencoded"),e.headers&&(delete e.headers["Content-Length"],delete e.headers["content-length"]),void 0===e.followRedirect||e.followRedirect||((this.isSurge()||this.isLoon())&&(e["auto-redirect"]=!1),this.isQuanX()&&(e.opts?e.opts.redirection=!1:e.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":default:this.isSurge()&&this.isNeedRewrite&&(e.headers=e.headers||{},Object.assign(e.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](e,(e,s,i)=>{!e&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),t(e,s,i)});break;case"Quantumult X":e.method=s,this.isNeedRewrite&&(e.opts=e.opts||{},Object.assign(e.opts,{hints:!1})),$task.fetch(e).then(e=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=e;t(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)},e=>t(e&&e.error||"UndefinedError"));break;case"Node.js":let i=require("iconv-lite");this.initGotEnv(e);const{url:o,...r}=e;this.got[s](o,r).then(e=>{const{statusCode:s,statusCode:o,headers:r,rawBody:a}=e,n=i.decode(a,this.encoding);t(null,{status:s,statusCode:o,headers:r,rawBody:a,body:n},n)},e=>{const{message:s,response:o}=e;t(s,o,o&&i.decode(o.rawBody,this.encoding))})}}time(e,t=null){const s=t?new Date(t):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(e)&&(e=e.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let t in i)new RegExp("("+t+")").test(e)&&(e=e.replace(RegExp.$1,1==RegExp.$1.length?i[t]:("00"+i[t]).substr((""+i[t]).length)));return e}queryStr(e){let t="";for(const s in e){let i=e[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),t+=`${s}=${i}&`)}return t=t.substring(0,t.length-1),t}msg(t=e,s="",i="",o={}){const r=e=>{const{$open:t,$copy:s,$media:i,$mediaMime:o}=e;switch(typeof e){case void 0:return e;case"string":switch(this.getEnv()){case"Surge":case"Stash":case"Egern":default:return{url:e};case"Loon":case"Shadowrocket":return e;case"Quantumult X":return{"open-url":e};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":case"Egern":default:{const r={};let a=e.openUrl||e.url||e["open-url"]||t;a&&Object.assign(r,{action:"open-url",url:a});let n=e["update-pasteboard"]||e.updatePasteboard||s;n&&Object.assign(r,{action:"clipboard",text:n});let h=e.mediaUrl||e["media-url"]||i;if(h){let e,t;if(h.startsWith("http"));else if(h.startsWith("data:")){const[s]=h.split(";"),[,i]=h.split(",");e=i,t=s.replace("data:","")}else{e=h,t=(e=>{const t={JVBERi0:"application/pdf",R0lGODdh:"image/gif",R0lGODlh:"image/gif",iVBORw0KGgo:"image/png","/9j/":"image/jpg"};for(var s in t)if(0===e.indexOf(s))return t[s];return null})(h)}Object.assign(r,{"media-url":h,"media-base64":e,"media-base64-mime":o??t})}return Object.assign(r,{"auto-dismiss":e["auto-dismiss"],sound:e.sound}),r}case"Loon":{const s={};let o=e.openUrl||e.url||e["open-url"]||t;o&&Object.assign(s,{openUrl:o});let r=e.mediaUrl||e["media-url"]||i;return r&&Object.assign(s,{mediaUrl:r}),console.log(JSON.stringify(s)),s}case"Quantumult X":{const o={};let r=e["open-url"]||e.url||e.openUrl||t;r&&Object.assign(o,{"open-url":r});let a=e.mediaUrl||e["media-url"]||i;a&&Object.assign(o,{"media-url":a});let n=e["update-pasteboard"]||e.updatePasteboard||s;return n&&Object.assign(o,{"update-pasteboard":n}),console.log(JSON.stringify(o)),o}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":default:$notification.post(t,s,i,r(o));break;case"Quantumult X":$notify(t,s,i,r(o));case"Node.js":}if(!this.isMuteLog){let e=["","==============📣系统通知📣=============="];e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n")),this.logs=this.logs.concat(e)}}debug(...e){this.logLevels[this.logLevel]<=this.logLevels.debug&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.debug}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}info(...e){this.logLevels[this.logLevel]<=this.logLevels.info&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.info}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}warn(...e){this.logLevels[this.logLevel]<=this.logLevels.warn&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.warn}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}error(...e){this.logLevels[this.logLevel]<=this.logLevels.error&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.error}${e.map(e=>e??String(e)).join(this.logSeparator)}`))}log(...e){e.length>0&&(this.logs=[...this.logs,...e]),console.log(e.map(e=>e??String(e)).join(this.logSeparator))}logErr(e,t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,t,e);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,t,void 0!==e.message?e.message:e,e.stack)}}wait(e){return new Promise(t=>setTimeout(t,e))}done(e={}){const t=((new Date).getTime()-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${t} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Egern":case"Quantumult X":default:$done(e);break;case"Node.js":process.exit(1)}}}(e,t)} diff --git a/citybox/citybox.cookie.js b/citybox/citybox.cookie.js new file mode 100644 index 000000000..4c66d42c7 --- /dev/null +++ b/citybox/citybox.cookie.js @@ -0,0 +1,32 @@ +/** + * + * hostname = api.icitybox.cn + * + * # Surge + * Rewrite: citybox = type=http-request,pattern=^https:\/\/api\.icitybox\/api\/user\/get_user_info,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/citybox/citybox.cookie.js,debug=true + * Tasks: citybox-签到 = type=cron,cronexp=10 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/citybox/citybox.js,wake-system=true + * + * # QuanX + * ^https:\/\/api\.icitybox\/api\/user\/get_user_info url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/citybox/citybox.cookie.js + * 10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/citybox/citybox.js, tag=citybox-签到 + * + * # Loon + * http-request ^https:\/\/api\.icitybox\/api\/user\/get_user_infoscript-path=https://raw.githubusercontent.com/chavyleung/scripts/master/citybox/citybox.cookie.js, tag=citybox + * cron "10 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/citybox/citybox.js + * + * # 获取方式:进入签到页面获取,进入citybox小程序即可 + */ + +const $ = new Env('魔盒') + +!(async () => { + const KEY = 'boxapp_citybox_har' + const har = { url: $request.url, headers: $request.headers } + $.setjson(har, KEY) + $.msg($.name, '获取 CityBox 账户成功') +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}isStash(){return"undefined"!=typeof $environment&&$environment["stash-version"]}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,n]=i.split("@"),a={url:`http://${n}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),n=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(n);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){if(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:i,statusCode:r,headers:o,rawBody:n}=t,a=s.decode(n,this.encoding);e(null,{status:i,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:i,response:r}=t;e(i,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let i=require("iconv-lite");this.initGotEnv(t);const{url:r,...o}=t;this.got[s](r,o).then(t=>{const{statusCode:s,statusCode:r,headers:o,rawBody:n}=t,a=i.decode(n,this.encoding);e(null,{status:s,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:s,response:r}=t;e(s,r,r&&i.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}queryStr(t){let e="";for(const s in t){let i=t[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),e+=`${s}=${i}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,i=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":i}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),this.isSurge()||this.isQuanX()||this.isLoon()?$done(t):this.isNode()&&process.exit(1)}}(t,e)} \ No newline at end of file diff --git a/citybox/citybox.js b/citybox/citybox.js new file mode 100644 index 000000000..1461bd71e --- /dev/null +++ b/citybox/citybox.js @@ -0,0 +1,61 @@ +const $ = new Env('魔盒') +const hostApi = 'https://api.icitybox.cn/api' +const drawRes = [] + +!(async () => { + const KEY_har = 'boxapp_citybox_har' + const har = $.getjson(KEY_har) + const headers = har?.headers + await sign(headers) + await draw(headers) + await draw(headers) + if ($.sign?.signnum) { + $.msg($.name, `第${$.sign.signnum}天 签到成功`, drawRes.join('\n')) + } else if ($.sign?.message) { + $.msg($.name, $.sign?.message) + } else { + $.msg($.name, '签到失败') + } +})() +.catch((e) => $.logErr(e)) +.finally(() => $.done()) + +function sign(headers) { + return new Promise((resolve) => { + const url = { + url: hostApi + '/user/up_sign', + headers, + } + $.get(url, (err, resp, data) => { + try { + $.sign = JSON.parse(data) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function draw(headers) { + return new Promise((resolve) => { + const index = Math.floor(Math.random() * 10) + const url = { + url: hostApi + '/roulette_draw/draw_results?click_num=' + index, + headers, + } + $.post(url, (err, resp, data) => { + try { + const data = JSON.parse(data) + drawRes.push(data.winning_desc) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}isStash(){return"undefined"!=typeof $environment&&$environment["stash-version"]}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,n]=i.split("@"),a={url:`http://${n}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),n=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(n);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){if(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:i,statusCode:r,headers:o,rawBody:n}=t,a=s.decode(n,this.encoding);e(null,{status:i,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:i,response:r}=t;e(i,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let i=require("iconv-lite");this.initGotEnv(t);const{url:r,...o}=t;this.got[s](r,o).then(t=>{const{statusCode:s,statusCode:r,headers:o,rawBody:n}=t,a=i.decode(n,this.encoding);e(null,{status:s,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:s,response:r}=t;e(s,r,r&&i.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}queryStr(t){let e="";for(const s in t){let i=t[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),e+=`${s}=${i}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,i=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":i}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),this.isSurge()||this.isQuanX()||this.isLoon()?$done(t):this.isNode()&&process.exit(1)}}(t,e)} diff --git a/csdn/README.md b/csdn/README.md index 468567132..49ad0011d 100644 --- a/csdn/README.md +++ b/csdn/README.md @@ -2,6 +2,12 @@ > 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 +> 2020.3.11 更新获取刷新链接正则 (更新后打开 App 即可获取刷新链接, 无需重新获取 Cookie) + +> 2020.3.12 增加自动抽奖 (如果有抽奖机会的话) (无需重新获取 Cookie) + +> 2020.3.12 如果发现无法签到 (后台日志报错), 注销一下 csdn 账号重新登录, 再重新获取下刷新链接 + ## 配置 (Surge) ```properties @@ -10,7 +16,7 @@ [Script] # 注意获取Cookie有两条脚本 -http-request ^https:\/\/passport.csdn.net\/v1\/api\/app\/login\/checkToken script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.cookie.js +http-request ^https:\/\/passport.csdn.net\/v2\/api\/app\/login\/checkAndRefreshToken script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.cookie.js http-request ^https:\/\/gw.csdn.net\/mini-app\/v2\/lucky_draw\/login\/sign_in\? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.cookie.js cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.js ``` @@ -23,7 +29,7 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr [rewrite_local] # 注意获取Cookie有两条脚本 -^https:\/\/passport.csdn.net\/v1\/api\/app\/login\/checkToken url script-request-header csdn.cookie.js +^https:\/\/passport.csdn.net\/v2\/api\/app\/login\/checkAndRefreshToken url script-request-header csdn.cookie.js ^https:\/\/gw.csdn.net\/mini-app\/v2\/lucky_draw\/login\/sign_in\? url script-request-header csdn.cookie.js [task_local] diff --git a/csdn/csdn.js b/csdn/csdn.js index 8f734440d..d5d78e715 100644 --- a/csdn/csdn.js +++ b/csdn/csdn.js @@ -1,69 +1,167 @@ -const cookieName = 'CSDN' -const tokenurlKey = 'chavy_tokenurl_csdn' -const tokenheaderKey = 'chavy_tokenheader_csdn' -const signurlKey = 'chavy_signurl_csdn' -const signheaderKey = 'chavy_signheader_csdn' const chavy = init() -const tokenurlVal = chavy.getdata(tokenurlKey) -const tokenheaderVal = chavy.getdata(tokenheaderKey) -const signurlVal = chavy.getdata(signurlKey) -let signheaderVal = chavy.getdata(signheaderKey) +const cookieName = 'CSDN' +const KEY_loginurl = 'chavy_tokenurl_csdn' +const KEY_loginheader = 'chavy_tokenheader_csdn' +const KEY_signurl = 'chavy_signurl_csdn' +const KEY_signheader = 'chavy_signheader_csdn' -sign() +const signinfo = {} +let VAL_loginurl = chavy.getdata(KEY_loginurl) +let VAL_loginheader = chavy.getdata(KEY_loginheader) +let VAL_signurl = chavy.getdata(KEY_signurl) +let VAL_signheader = chavy.getdata(KEY_signheader) -function sign() { - loginapp((logininfo) => { - if (logininfo.code == '0') { - const url = { url: signurlVal, headers: JSON.parse(signheaderVal) } - url.body = '{}' - chavy.post(url, (error, response, data) => { - chavy.log(`${cookieName}, data: ${data}`) - const title = `${cookieName}` - let subTitle = '' - let detail = '' - let result = JSON.parse(data) - if (result.code == 200) { - if (result.data.isSigned === false) { - subTitle = `签到结果: 成功` - detail = `共签: ${result.data.totalCount}天, 连签: ${result.data.keepCount}天` - } else if (result.data.isSigned === true) { - subTitle = `签到结果: 成功 (重复签到)` - } else { - subTitle = `签到结果: 失败` - detail = `编码: ${result.code}, 说明: ${result.msg}` - } - } else { - subTitle = `签到结果: 失败` - detail = `说明: 详见日志` - } - chavy.msg(title, subTitle, detail) - chavy.done() - }) - chavy.done() - } else { - const title = `${cookieName}` - const subTitle = '签到结果: 失败' - const detail = `原因: ${logininfo.message}` - chavy.msg(title, subTitle, detail) - chavy.log(`${cookieName}, ${subTitle}, ${detail}`) - chavy.done() - } +;(sign = async () => { + chavy.log(`🔔 ${cookieName}`) + await loginapp() + await signapp() + await getlucky() + for (let i = 0; i < signinfo.lucky.data.drawTimes; i++) { + await luckyapp() + } + showmsg() +})() +.catch((e) => chavy.log(`❌ ${cookieName} 签到失败: ${e}`)) +.finally(() => chavy.done()) + +function loginapp() { + return new Promise((resolve, reject) => { + const url = { url: VAL_loginurl, headers: JSON.parse(VAL_loginheader) } + chavy.get(url, (error, response, data) => { + try { + signinfo.loginapp = JSON.parse(data) + updateSignAppCookies() + resolve() + } catch (e) { + chavy.msg(cookieName, `登录结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} loginapp - 登录失败: ${e}`) + chavy.log(`❌ ${cookieName} loginapp - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function updateSignAppCookies() { + if (signinfo.loginapp) { + const signheaderObj = JSON.parse(VAL_signheader) + signheaderObj['JWT-TOKEN'] = signinfo.loginapp.data.token + signheaderObj['Cookie'] = signheaderObj['Cookie'].replace(/JWT-TOKEN=[^;]*/, `JWT-TOKEN=${signinfo.loginapp.data.token}`) + VAL_signheader = JSON.stringify(signheaderObj) + } else { + chavy.log(`⚠ ${cookieName} updateSignAppCookies: 请先获取 Cookies`) + } +} + +function signapp() { + return new Promise((resolve, reject) => { + const url = { url: VAL_signurl, body: '{}', headers: JSON.parse(VAL_signheader) } + chavy.post(url, (error, response, data) => { + try { + signinfo.signapp = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `签到结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} signapp - 签到失败: ${e}`) + chavy.log(`❌ ${cookieName} signapp - response: ${JSON.stringify(response)}`) + resolve() + } + }) }) } -function loginapp(cb) { - const url = { url: tokenurlVal, headers: JSON.parse(tokenheaderVal) } - chavy.get(url, (error, response, data) => { - chavy.log(`${cookieName}, loginapp: ${data}`) - let result = JSON.parse(data) - let signheaderObj = JSON.parse(signheaderVal) - signheaderObj['JWT-TOKEN'] = result.data.token - signheaderObj['Cookie'] = signheaderObj['Cookie'].replace(/JWT-TOKEN=[^;]*/, `JWT-TOKEN=${result.data.token}`) - signheaderVal = JSON.stringify(signheaderObj) - cb(result) +function getlucky() { + return new Promise((resolve, reject) => { + const VAL_getluckyurl = `https://gw.csdn.net/mini-app/v2/lucky_draw/login/sign_info?projectVersion=1.0.0` + const url = { url: VAL_getluckyurl, headers: JSON.parse(VAL_signheader) } + delete url.headers['Content-Length'] + url.headers['Connection'] = 'keep-alive' + url.headers['Accept-Encoding'] = 'gzip, deflate, br' + url.headers['X-OS'] = 'iOS' + url.headers['Content-Type'] = 'application/json' + url.headers['X-App-ID'] = 'CSDN-APP' + url.headers['Origin'] = 'https://webapp.csdn.net' + url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 CSDNApp/4.1.5(iOS) AnalysysAgent/Hybrid' + url.headers['Referer'] = 'https://webapp.csdn.net/' + url.headers['Host'] = 'gw.csdn.net' + url.headers['Accept-Language'] = 'zh-cn' + url.headers['Accept'] = '*/*' + + chavy.get(url, (error, response, data) => { + try { + signinfo.lucky = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `获取抽奖次数: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} getlucky - 获取抽奖次数失败: ${e}`) + chavy.log(`❌ ${cookieName} getlucky - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function luckyapp() { + return new Promise((resolve, reject) => { + const VAL_luckyappurl = `https://gw.csdn.net/mini-app/v2/lucky_draw/login/good_luck?projectVersion=1.0.0` + const url = { url: VAL_luckyappurl, body: '{}', headers: JSON.parse(VAL_signheader) } + url.headers['Connection'] = 'keep-alive' + url.headers['Accept-Encoding'] = 'gzip, deflate, br' + url.headers['X-OS'] = 'iOS' + url.headers['Content-Type'] = 'application/json' + url.headers['X-App-ID'] = 'CSDN-APP' + url.headers['Origin'] = 'https://webapp.csdn.net' + url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 CSDNApp/4.1.5(iOS) AnalysysAgent/Hybrid' + url.headers['Referer'] = 'https://webapp.csdn.net/' + url.headers['Host'] = 'gw.csdn.net' + url.headers['Accept-Language'] = 'zh-cn' + url.headers['Accept'] = '*/*' + chavy.post(url, (error, response, data) => { + try { + chavy.log(`❕ ${cookieName} luckyapp - response: ${JSON.stringify(response)}`) + signinfo.luckylist = signinfo.luckylist ? signinfo.luckylist : [] + signinfo.luckylist.push(JSON.parse(data)) + resolve() + } catch (e) { + chavy.msg(cookieName, `抽奖结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} luckyapp - 抽奖失败: ${e}`) + chavy.log(`❌ ${cookieName} luckyapp - response: ${JSON.stringify(response)}`) + resolve() + } + }) }) } +function showmsg() { + let subTitle = '' + let detail = '' + if (signinfo.signapp.code == 200) { + if (signinfo.signapp.data.isSigned === false) { + subTitle = `签到结果: 成功` + detail = `共签: ${signinfo.signapp.data.totalCount}天, 连签: ${signinfo.signapp.data.keepCount}天` + } else if (signinfo.signapp.data.isSigned === true) { + subTitle = `签到结果: 重复` + } else { + subTitle = `签到结果: 失败` + detail = `编码: ${signinfo.signapp.code}, 说明: ${signinfo.signapp.msg}` + } + } else { + subTitle = `签到结果: 失败` + detail = `说明: 详见日志` + } + + if (signinfo.lucky && signinfo.lucky.data && signinfo.lucky.data.drawTimes && signinfo.lucky.data.drawTimes > 0) { + subTitle += `; 抽奖次数: ${signinfo.lucky.data.drawTimes}` + detail += `\n查看抽奖详情\n` + for (let i = 0; i < signinfo.luckylist.length; i++) { + const can_draw = signinfo.luckylist[i].data.can_draw + if (can_draw) detail += `\n抽奖 ${i + 1}: ${signinfo.luckylist[i].data.title}` + else detail += `\n抽奖 ${i + 1}: ${signinfo.luckylist[i].data.msg}` + } + } + chavy.msg(cookieName, subTitle, detail) +} + function init() { isSurge = () => { return undefined === this.$httpClient ? false : true @@ -90,7 +188,7 @@ function init() { } if (isQuanX()) { url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) } } post = (url, cb) => { @@ -99,7 +197,7 @@ function init() { } if (isQuanX()) { url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) } } done = (value = {}) => { diff --git a/duokan/README.md b/duokan/README.md new file mode 100644 index 000000000..9cb8ba315 --- /dev/null +++ b/duokan/README.md @@ -0,0 +1,94 @@ +# 多看阅读 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> QuanX 需要: v1.0.6-build195 及以后版本 (TestFlight) + +## 配置 (Surge) + +```properties +[MITM] +www.duokan.com + +[Script] +http-request ^https:\/\/www\.duokan\.com\/checkin\/v0\/status script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/duokan/duokan.cookie.js, requires-body=true + +cron "0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/duokan/duokan.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +www.duokan.com + +[rewrite_local] +# [商店版] QuanX v1.0.6-build194 及更早版本 +^https:\/\/www\.duokan\.com\/checkin\/v0\/status url script-request-body duokan.cookie.js + +# [TestFlight] QuanX v1.0.6-build195 及以后版本 +^https:\/\/www\.duokan\.com\/checkin\/v0\/status url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/duokan/duokan.cookie.js + +[task_local] +0 0 * * * duokan.js +``` + +## 说明 +1. 先把 `www.duokan.com` 加到 `[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到 `[Script]` + - QuanX: 把 `duokan.cookie.js` 和 `duokan.js` 传到 `On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 获取 Cookie: `我的` > `签到任务` 等到提示获取 Cookie 成功即可 +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天 `00:00` 执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天 00:00:10 执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天 00:00:20 执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天 00:00:30 执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每 60 分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天 00:01 执行一次 + 2 0 * * * xxx.js # 每天 00:02 执行一次 + 3 0 * * * xxx.js # 每天 00:03 执行一次 + + */60 * * * * xxx.js # 每 60 分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) \ No newline at end of file diff --git a/duokan/duokan.cookie.js b/duokan/duokan.cookie.js new file mode 100644 index 000000000..1643f5fe9 --- /dev/null +++ b/duokan/duokan.cookie.js @@ -0,0 +1,81 @@ +const DUOKAN_COOKIE_KEY = 'duokan_cookie' +const DUOKAN_DEVICE_ID_KEY = 'duokan_device_id' + +let $util = init() + +if (typeof $request !== 'undefined') { + getCookie() +} +$util.done({}) + +function getCookie() { + let cookieVal = $request.headers['Cookie'] + $util.log(`cookie: ${cookieVal}`) + if (cookieVal.indexOf('token=') !== -1 && cookieVal.indexOf('device_id=') !== -1) { + let regexp = /device_id=(.*?);/g + let matched = regexp.exec(cookieVal) + if (matched) { + let deviceId = matched[1] + $util.log(`deviceId: ${deviceId}`) + if ($util.setdata(cookieVal, DUOKAN_COOKIE_KEY) && $util.setdata(deviceId, DUOKAN_DEVICE_ID_KEY)) { + $util.msg(`获取多看阅读 Cookie 成功 🎉`) + } + } + } +} + +function init() { + isSurge = () => { + return undefined !== this.$httpClient + } + isQuanX = () => { + return undefined !== this.$task + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle = '', body = '') => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (msg) => { + console.log(`${msg}\n`) + } + get = (options, callback) => { + if (isQuanX()) { + if (typeof options == 'string') options = { url: options } + options['method'] = 'GET' + return $task.fetch(options).then( + (response) => { + response['status'] = response.statusCode + callback(null, response, response.body) + }, + (reason) => callback(reason.error, null, null) + ) + } + if (isSurge()) return $httpClient.get(options, callback) + } + post = (options, callback) => { + if (isQuanX()) { + if (typeof options == 'string') options = { url: options } + options['method'] = 'POST' + $task.fetch(options).then( + (response) => { + response['status'] = response.statusCode + callback(null, response, response.body) + }, + (reason) => callback(reason.error, null, null) + ) + } + if (isSurge()) $httpClient.post(options, callback) + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/duokan/duokan.js b/duokan/duokan.js new file mode 100644 index 000000000..91ce34080 --- /dev/null +++ b/duokan/duokan.js @@ -0,0 +1,123 @@ +const DUOKAN_COOKIE_KEY = 'duokan_cookie' +const DUOKAN_DEVICE_ID_KEY = 'duokan_device_id' +const API_HOST = 'https://www.duokan.com' +const TASK_NAME = '多看阅读' + +let $util = init() + +;(async () => { + let cookieVal = $util.getdata(DUOKAN_COOKIE_KEY) + let deviceId = $util.getdata(DUOKAN_DEVICE_ID_KEY) + if (!cookieVal || !deviceId) { + $util.msg(TASK_NAME, '⚠️ 请先获取 Cookie') + $util.done({}) + return + } + await checkin(cookieVal, deviceId).then(() => { + $util.done({}) + }) +})() + +function checkin(cookieVal, deviceId) { + return new Promise((resolve, reject) => { + let options = { + url: `${API_HOST}/checkin/v0/checkin`, + headers: { + 'User-Agent': + 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148', + Cookie: cookieVal + }, + body: signature(deviceId) + } + $util.post(options, (error, response, data) => { + if (error) { + $util.log(`签到失败,error:${error}`) + $util.msg(TASK_NAME, '⚠️ 签到失败,详情请查看日志') + resolve() + return + } + let result = JSON.parse(data) + if (result && result.result === 0 && result.data) { + $util.log(`签到成功,response: ${data}`) + let subtitle = `签到成功,已连续签到 ${result.data.today} 天` + let body = '' + if (result.data.gift && Array.isArray(result.data.gift) && result.data.gift.length > 0) { + body = result.data.gift.reduce((prev, cur) => { + return (prev += `获得 ${cur.value} 个${cur.name} \n`) + }, '') + } + $util.msg(TASK_NAME, subtitle, body) + resolve() + } else { + $util.log(`签到失败,response: ${data}`) + $util.msg(TASK_NAME, `⚠️ 签到失败,${result.msg}`) + resolve() + } + }) + }) +} + +function signature(deviceId) { + let t = parseInt(new Date().getTime() / 1000) + let c = 0 + for (char of `${deviceId}&${t}`) { + c = (c * 131 + char.charCodeAt(0)) % 65536 + } + return `_t=${t}&_c=${c}` +} + +function init() { + isSurge = () => { + return undefined !== this.$httpClient + } + isQuanX = () => { + return undefined !== this.$task + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle = '', body = '') => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (msg) => { + console.log(`${msg}\n`) + } + get = (options, callback) => { + if (isQuanX()) { + if (typeof options == 'string') options = { url: options } + options['method'] = 'GET' + return $task.fetch(options).then( + (response) => { + response['status'] = response.statusCode + callback(null, response, response.body) + }, + (reason) => callback(reason.error, null, null) + ) + } + if (isSurge()) return $httpClient.get(options, callback) + } + post = (options, callback) => { + if (isQuanX()) { + if (typeof options == 'string') options = { url: options } + options['method'] = 'POST' + $task.fetch(options).then( + (response) => { + response['status'] = response.statusCode + callback(null, response, response.body) + }, + (reason) => callback(reason.error, null, null) + ) + } + if (isSurge()) $httpClient.post(options, callback) + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/emby/emby.js b/emby/emby.js new file mode 100644 index 000000000..b34b409cc --- /dev/null +++ b/emby/emby.js @@ -0,0 +1,20 @@ +const CHECK_URL = 'mb3admin.com/admin/service/registration/validateDevice' + +const url = $request.url +const isCheckUrl = (url) => url.includes(CHECK_URL) + +if (isCheckUrl(url) && $response.status != 200) { + const unlock = { + cacheExpirationDays: 999, + resultCode: 'GOOD', + message: 'Device Valid' + } + + const status = 200 + const headers = $response.headers + const body = JSON.stringify(unlock) + + $done({ status, headers, body }) +} else { + $done({}) +} diff --git a/emby/emby.sgmodule b/emby/emby.sgmodule new file mode 100644 index 000000000..44fefc2ce --- /dev/null +++ b/emby/emby.sgmodule @@ -0,0 +1,8 @@ +#!name=Emby Unlock +#!desc=Emby Unlock + +[Script] +emby.js = type=http-response,pattern=^https?:\/\/mb3admin.com\/admin\/service\/registration\/validateDevice,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/emby/emby.js + +[MITM] +hostname = %APPEND% mb3admin.com \ No newline at end of file diff --git a/neteasemusic/quanx/README.md b/everphoto/README.md similarity index 58% rename from neteasemusic/quanx/README.md rename to everphoto/README.md index 7a154ff8a..04165b041 100644 --- a/neteasemusic/quanx/README.md +++ b/everphoto/README.md @@ -1,42 +1,50 @@ -# 网易云音乐 +# 时光相册 -> 2020.1.11 QuanX 在`190`版本开始, 获取 Cookie 方式需要从`script-response-body`改为`script-request-header` +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 -## 配置 +## 配置 (Surge) ```properties [MITM] -music.163.com +api.everphoto.cn + +[Script] +http-request ^https:\/\/api.everphoto.cn\/users\/self\/checkin\/v2 script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/everphoto/everphoto.cookie.js +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/everphoto/everphoto.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +api.everphoto.cn [rewrite_local] -# 189及以前版本 -^https:\/\/music\.163\.com\/m\/?.? url script-response-body neteasemusic.cookie.js -# 190及以后版本 -^https:\/\/music\.163\.com\/m\/?.? url script-request-header neteasemusic.cookie.js +^https:\/\/api.everphoto.cn\/users\/self\/checkin\/v2 url script-request-header everphoto.cookie.js [task_local] -1 0 * * * neteasemusic.js +1 0 * * * everphoto.js ``` ## 说明 -1. 先把`music.163.com`加到`[MITM]` -2. 把`neteasemusic.cookie.js`和`neteasemusic.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) -3. 再把两条脚本分别放到`[rewrite_local]`和`[task_local]` -4. 浏览器访问并登录: https://music.163.com/m/login -5. 打开浏览器访问: https://music.163.com/m/ -6. `QuanX`提示: `Cookie [网易云音乐] 写入成功` -7. 最后就可以把`[rewrite_local]`的脚本注释掉了 +1. 先把`api.everphoto.cn`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`everphoto.cookie.js`和`everphoto.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP 然后手动签到 1 次, 系统提示: `获取Cookie: 成功` +4. 最后就可以把第 1 条脚本注释掉了 +5. 运行一次脚本, 如果提示重复签到, 那就算成功了! > 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. -> 第 2 条脚本是签到脚本, 每天`00:01:00`执行一次. +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. ## 常见问题 1. 无法写入 Cookie - - 检查 QuanX 系统通知权限放开了没 + - 检查 Surge 系统通知权限放开了没 - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) 2. 写入 Cookie 成功, 但签到不成功 diff --git a/everphoto/everphoto.cookie.js b/everphoto/everphoto.cookie.js new file mode 100644 index 000000000..87c5d2d90 --- /dev/null +++ b/everphoto/everphoto.cookie.js @@ -0,0 +1,69 @@ +const chavy = init() +const cookieName = '时光相册' +const KEY_signurl = 'chavy_sign_url_everphoto' +const KEY_signheader = 'chavy_sign_header_everphoto' + +if ($request && $request.method != 'OPTIONS') { + try { + chavy.log(`🔔 ${cookieName} 开始获取: Cookies`) + const VAL_signurl = $request.url + const VAL_signheader = JSON.stringify($request.headers) + if (VAL_signurl) { + chavy.setdata(VAL_signurl, KEY_signurl) + chavy.log(`❕ ${cookieName} VAL_signurl: ${VAL_signurl}`) + } + if (VAL_signheader) { + chavy.setdata(VAL_signheader, KEY_signheader) + chavy.log(`❕ ${cookieName} VAL_signheader: ${VAL_signheader}`) + } + chavy.msg(cookieName, `获取Cookie: 成功`, ``) + } catch (e) { + chavy.msg(cookieName, `获取Cookie: 失败`, e) + chavy.log(`❌ ${cookieName} 获取Cookie: 失败: ${e}`) + } +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} +chavy.done() diff --git a/everphoto/everphoto.js b/everphoto/everphoto.js new file mode 100644 index 000000000..f3f6481d3 --- /dev/null +++ b/everphoto/everphoto.js @@ -0,0 +1,98 @@ +const chavy = init() +const cookieName = '时光相册' +const KEY_signurl = 'chavy_sign_url_everphoto' +const KEY_signheader = 'chavy_sign_header_everphoto' + +const signinfo = {} +let VAL_signurl = chavy.getdata(KEY_signurl) +let VAL_signheader = chavy.getdata(KEY_signheader) + +;(exec = async () => { + chavy.log(`🔔 ${cookieName} 开始签到`) + await signapp() + showmsg() +})() +.catch((e) => chavy.log(`❌ ${cookieName} 签到失败: ${e}`)) +.finally(() => chavy.done()) + +function signapp() { + return new Promise((resolve, reject) => { + const url = { url: VAL_signurl, headers: JSON.parse(VAL_signheader) } + chavy.post(url, (error, response, data) => { + try { + signinfo.signapp = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `签到结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} sign - 签到失败: ${e}`) + chavy.log(`❌ ${cookieName} sign - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function showmsg() { + let subTitle, detail + if (signinfo.signapp.code == 0 && signinfo.signapp.data.checkin_result == true) { + const reward = signinfo.signapp.data.reward / 1024 / 1024 + const total_reward = signinfo.signapp.data.total_reward / 1024 / 1024 + const tomorrow_reward = signinfo.signapp.data.tomorrow_reward / 1024 / 1024 + subTitle = '签到结果: 成功' + detail = `总共获得: ${total_reward}MB (+${reward}MB), 明天获得: ${tomorrow_reward}MB` + } else if (signinfo.signapp.code == 0 && signinfo.signapp.data.checkin_result == false) { + const total_reward = signinfo.signapp.data.total_reward / 1024 / 1024 + const tomorrow_reward = signinfo.signapp.data.tomorrow_reward / 1024 / 1024 + subTitle = '签到结果: 成功 (重复签到)' + detail = `总共获得: ${total_reward}MB, 明天获得: ${tomorrow_reward}MB` + } else { + subTitle = '签到结果: 失败' + detail = `编码: ${signinfo.signapp.code}, 说明: 未知` + chavy.log(`❌ ${cookieName} showmsg - 签到失败: ${JSON.stringify(signinfo.signapp)}`) + } + chavy.msg(cookieName, subTitle, detail) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/videoqq/README.app.md b/fandeng/README.md similarity index 66% rename from videoqq/README.app.md rename to fandeng/README.md index c6ad56c25..854fb8eeb 100644 --- a/videoqq/README.app.md +++ b/fandeng/README.md @@ -1,49 +1,51 @@ -# 腾讯视频 (APP) +# 樊登读书 > 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 -> 需要 VIP 会员才能签到 (需要 VIP!需要 VIP!需要 VIP!) +> QuanX 需要: v1.0.6-build195 及以后版本 (TestFlight) -> 2020.1.11 QuanX 在`190`版本开始, 获取 Cookie 方式需要从`script-response-body`改为`script-request-header` - -> 2020.2.5 如果你从 APP 中获取的 Cookie 容易失效 [请点这里](https://github.com/chavyleung/scripts/blob/master/videoqq/README.md) +> 感谢 [@GideonSenku](https://github.com/GideonSenku) Commit ## 配置 (Surge) ```properties [MITM] -*.video.qq.com +api.dushu.io [Script] -http-request ^https:\/\/vip\.video\.qq\.com\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.cookie.js -cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.js +http-request ^https://api\.dushu\.io/CheckIn script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/fandeng/fandeng.cookie.js, requires-body=true + +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/fandeng/fandeng.js ``` ## 配置 (QuanX) ```properties [MITM] -*.video.qq.com +api.dushu.io [rewrite_local] -# 189及以前版本 -^https:\/\/vip\.video\.qq\.com\/?.? url script-response-body videoqq.cookie.js -# 190及以后版本 -^https:\/\/vip\.video\.qq\.com\/?.? url script-request-header videoqq.cookie.js + +# [商店版] QuanX v1.0.6-build194 及更早版本 +# 不支持 + +# [TestFlight] QuanX v1.0.6-build195 及以后版本 +^https://api\.dushu\.io/CheckIn url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/fandeng/fandeng.cookie.js [task_local] -1 0 * * * videoqq.js +1 0 * * * fandeng.js ``` ## 说明 -1. 先把`*.video.qq.com`加到`[MITM]` +1. 先把`api.dushu.io`加到`[MITM]` 2. 再配置重写规则: - Surge: 把两条远程脚本放到`[Script]` - - QuanX: 把`videoqq.cookie.js`和`videoqq.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) -3. 打开 APP, 访问下`个人中心` -4. 系统提示: `获取Cookie: 成功` (如果不提示获取成功, 尝试杀进程再进个人中心) -5. 最后就可以把第 1 条脚本注释掉了 + - QuanX: 把`fandeng.cookie.js`和`fandeng.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP 手动签到一次: 访问下右下角 `我的` > `签到` +4. 系统提示: `获取Cookie: 成功` +5. 把获取 Cookie 的脚本注释掉 +6. 运行一次脚本, 如果提示重复签到, 那就算成功了! > 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. @@ -98,3 +100,5 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr [@lhie1](https://github.com/lhie1) [@ConnersHua](https://github.com/ConnersHua) + +[@GideonSenku](https://github.com/GideonSenku) diff --git a/fandeng/fandeng.cookie.js b/fandeng/fandeng.cookie.js new file mode 100644 index 000000000..f9dc70934 --- /dev/null +++ b/fandeng/fandeng.cookie.js @@ -0,0 +1,64 @@ +const cookieName = '樊登读书' +const signurlKey = 'senku_signurl_pandeng' +const signheaderKey = 'senku_signheader_pandeng' +const signbodyKey = 'senku_signbody_pandeng' +const senku = init() + +const requrl = $request.url +if ($request && $request.method != 'OPTIONS') { + const signurlVal = requrl + const signheaderVal = JSON.stringify($request.headers) + const signbodyVal = $request.body + senku.log(`signurlVal:${signurlVal}`) + senku.log(`signheaderVal:${signheaderVal}`) + senku.log(`signbodyVal:${signbodyVal}`) + if (signurlVal) senku.setdata(signurlVal, signurlKey) + if (signheaderVal) senku.setdata(signheaderVal, signheaderKey) + if (signbodyVal) senku.setdata(signbodyVal, signbodyKey) + senku.msg(cookieName, `获取Cookie: 成功`, ``) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} +senku.done() diff --git a/fandeng/fandeng.js b/fandeng/fandeng.js new file mode 100644 index 000000000..7e071275a --- /dev/null +++ b/fandeng/fandeng.js @@ -0,0 +1,72 @@ +const cookieName = '樊登读书' +const signurlKey = 'senku_signurl_pandeng' +const signheaderKey = 'senku_signheader_pandeng' +const signbodyKey = 'senku_signbody_pandeng' +const senku = init() +const signurlVal = senku.getdata(signurlKey) +const signheaderVal = senku.getdata(signheaderKey) +const signBodyVal = senku.getdata(signbodyKey) + +sign() + +function sign() { + const url = { url: signurlVal, headers: JSON.parse(signheaderVal), body: signBodyVal } + senku.post(url, (error, response, data) => { + senku.log(`${cookieName}, data: ${data}`) + const res = JSON.parse(data) + let subTitle = `` + let detail = `` + if (res.status == 1) { + subTitle = `签到结果: 成功` + } else { + subTitle = `签到结果: 失败` + detail = `状态: ${res.message}` + } + senku.msg(cookieName, subTitle, detail) + senku.done() + }) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/feng/README.md b/feng/README.md index c10a3ef27..600eb7826 100644 --- a/feng/README.md +++ b/feng/README.md @@ -1,25 +1,13 @@ -# 威锋网 - -> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 - -> 注意了威锋网只能在一处登录, 如果你手机上登录了, 其他地方的登录会话会被踢掉 (重新登录需要重新获取 Cookie) - -> 2020.1.11 QuanX 在`190`版本开始, 获取 Cookie 方式需要从`script-response-body`改为`script-request-header` - -> 2020.2.6 威锋加了验证, 弃坑 - -> 2020.2.10 恢复签到: 增加参数签名 - -> 2020.2.11 威锋加了校验, 偶尔能签, 选择性弃坑吧! +# 威锋网 (APP) ## 配置 (Surge) ```properties [MITM] -*.feng.com +api.wfdata.club [Script] -http-request ^https:\/\/(www\.)?feng\.com\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.cookie.js +Rewrite: feng = type=http-request,pattern=^https?:\/\/api.wfdata.club\/v1\/auth\/signin,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.cookie.js,requires-body=true cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.js ``` @@ -27,84 +15,35 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr ```properties [MITM] -*.feng.com +api.wfdata.club [rewrite_local] -# 189及以前版本 -^https:\/\/(www\.)?feng\.com\/?.? url script-response-body feng.cookie.js -# 190及以后版本 -^https:\/\/(www\.)?feng\.com\/?.? url script-request-header feng.cookie.js +^https?:\/\/api.wfdata.club\/v1\/auth\/signin url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.cookie.js [task_local] -1 0 * * * feng.js +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.js ``` -## 说明 - -1. 先在浏览器登录 `(先登录! 先登录! 先登录!)` - - 如果你找不到登录的入口: 随便找个帖子做个“回帖”的动作, 会提示你登录的. - - 可以试试: https://www.feng.com/newthread -2. 先把`*.feng.com`加到`[MITM]` -3. 再配置重写规则: - - Surge: 把两条远程脚本放到`[Script]` - - QuanX: 把`feng.cookie.js`和`feng.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) -4. 打开浏览器访问: https://www.feng.com -5. 系统提示: `获取Cookie: 成功` - - 如果一直取不到 Cookie, 请尝试一切你想到的姿势, 如: - - 访问: https://www.feng.com/newthread - - 然后刷新下 -6. 最后就可以把第 1 条脚本注释掉了 - -> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. - -> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. - -## 常见问题 - -1. 无法写入 Cookie - - - 检查 Surge 系统通知权限放开了没 - - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) +## 配置 (Loon) -2. 写入 Cookie 成功, 但签到不成功 - - - 看看是不是在登录前就写入 Cookie 了 - - 如果是,请确保在登录成功后,再尝试写入 Cookie - -3. 为什么有时成功有时失败 - - - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) - - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): - - - `Surge`配置: - - ```properties - # 没有什么是一顿饭解决不了的: - cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 - # 如果有,那就两顿: - cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 - # 实在不行,三顿也能接受: - cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 +```properties +[MITM] +api.wfdata.club - # 再粗暴点,直接: - cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 - ``` +[rewrite_local] +http-request ^https?:\/\/api.wfdata.club\/v1\/auth\/signin script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.cookie.js, requires-body=true, tag=Rewrite: feng - - `QuanX`配置: +[task_local] +cron "1 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/feng/feng.js +``` - ```properties - [task_local] - 1 0 * * * xxx.js # 每天00:01执行一次 - 2 0 * * * xxx.js # 每天00:02执行一次 - 3 0 * * * xxx.js # 每天00:03执行一次 +## 说明 - */60 * * * * xxx.js # 每60分执行一次 - ``` +1. 配置重写 +2. 在 `威锋网` APP 下使用 账号密码 方式登录 +3. 提示 `获取会话: 成功` +4. 注释重写 ## 感谢 -[@NobyDa](https://github.com/NobyDa) - -[@lhie1](https://github.com/lhie1) - -[@ConnersHua](https://github.com/ConnersHua) +[@wangfei021325](https://github.com/wangfei021325) diff --git a/feng/feng.cookie.js b/feng/feng.cookie.js index c20456343..c00c697c8 100644 --- a/feng/feng.cookie.js +++ b/feng/feng.cookie.js @@ -1,61 +1,20 @@ -const cookieName = '威锋网' -const cookieKey = 'chavy_cookie_feng' -const chavy = init() -const cookieVal = $request.headers['Cookie'] -if (cookieVal.indexOf('userInfo') >= 0) { - if (cookieVal) { - if (chavy.setdata(cookieVal, cookieKey)) { - chavy.msg(`${cookieName}`, '获取Cookie: 成功', '') - chavy.log(`[${cookieName}] 获取Cookie: 成功, cookie: ${cookieVal}`) - } - } -} else { - let subTitle = '获取Cookie: 失败' - let detail = `请确保在已登录状态下获取Cookie` - chavy.msg(`${cookieName}`, subTitle, detail) - chavy.log(`[${cookieName}] ${subTitle}, cookie: ${cookieVal}`) -} -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) - } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) - } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } -} -chavy.done() +const $ = new Env('威锋网') +$.KEY_login = 'chavy_login_feng' + +!(async () => { + const session = {} + session.url = $request.url + session.body = $request.body + session.headers = $request.headers + if ($.setdata(JSON.stringify(session), $.KEY_login)) { + $.subt = `获取会话: 成功!` + } else { + $.subt = `获取会话: 失败!` + } + $.msg($.name, $.subt, $.desc) +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/feng/feng.js b/feng/feng.js index f1f587b01..732821d9b 100644 --- a/feng/feng.js +++ b/feng/feng.js @@ -7,157 +7,71 @@ }(), function () { function r() { for (var t = this._S, r = this._i, e = this._j, i = 0, n = 0; n < 4; n++) { r = (r + 1) % 256, e = (e + t[r]) % 256; var o = t[r]; t[r] = t[e], t[e] = o, i |= t[(t[r] + t[e]) % 256] << 24 - 8 * n } return this._i = r, this._j = e, i } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = o.RC4 = n.extend({ _doReset: function () { for (var t = this._key, r = t.words, e = t.sigBytes, i = this._S = [], n = 0; n < 256; n++)i[n] = n; for (var n = 0, o = 0; n < 256; n++) { var s = n % e, a = r[s >>> 2] >>> 24 - s % 4 * 8 & 255; o = (o + i[n] + a) % 256; var c = i[n]; i[n] = i[o], i[o] = c } this._i = this._j = 0 }, _doProcessBlock: function (t, e) { t[e] ^= r.call(this) }, keySize: 8, ivSize: 0 }); e.RC4 = n._createHelper(s); var a = o.RC4Drop = s.extend({ cfg: s.cfg.extend({ drop: 192 }), _doReset: function () { s._doReset.call(this); for (var t = this.cfg.drop; t > 0; t--)r.call(this) } }); e.RC4Drop = n._createHelper(a) }(), t.mode.CTRGladman = function () { function r(t) { if (255 === (t >> 24 & 255)) { var r = t >> 16 & 255, e = t >> 8 & 255, i = 255 & t; 255 === r ? (r = 0, 255 === e ? (e = 0, 255 === i ? i = 0 : ++i) : ++e) : ++r, t = 0, t += r << 16, t += e << 8, t += i } else t += 1 << 24; return t } function e(t) { return 0 === (t[0] = r(t[0])) && (t[1] = r(t[1])), t } var i = t.lib.BlockCipherMode.extend(), n = i.Encryptor = i.extend({ processBlock: function (t, r) { var i = this._cipher, n = i.blockSize, o = this._iv, s = this._counter; o && (s = this._counter = o.slice(0), this._iv = void 0), e(s); var a = s.slice(0); i.encryptBlock(a, 0); for (var c = 0; c < n; c++)t[r + c] ^= a[c] } }); return i.Decryptor = n, i }(), function () { function r() { for (var t = this._X, r = this._C, e = 0; e < 8; e++)a[e] = r[e]; r[0] = r[0] + 1295307597 + this._b | 0, r[1] = r[1] + 3545052371 + (r[0] >>> 0 < a[0] >>> 0 ? 1 : 0) | 0, r[2] = r[2] + 886263092 + (r[1] >>> 0 < a[1] >>> 0 ? 1 : 0) | 0, r[3] = r[3] + 1295307597 + (r[2] >>> 0 < a[2] >>> 0 ? 1 : 0) | 0, r[4] = r[4] + 3545052371 + (r[3] >>> 0 < a[3] >>> 0 ? 1 : 0) | 0, r[5] = r[5] + 886263092 + (r[4] >>> 0 < a[4] >>> 0 ? 1 : 0) | 0, r[6] = r[6] + 1295307597 + (r[5] >>> 0 < a[5] >>> 0 ? 1 : 0) | 0, r[7] = r[7] + 3545052371 + (r[6] >>> 0 < a[6] >>> 0 ? 1 : 0) | 0, this._b = r[7] >>> 0 < a[7] >>> 0 ? 1 : 0; for (var e = 0; e < 8; e++) { var i = t[e] + r[e], n = 65535 & i, o = i >>> 16, s = ((n * n >>> 17) + n * o >>> 15) + o * o, h = ((4294901760 & i) * i | 0) + ((65535 & i) * i | 0); c[e] = s ^ h } t[0] = c[0] + (c[7] << 16 | c[7] >>> 16) + (c[6] << 16 | c[6] >>> 16) | 0, t[1] = c[1] + (c[0] << 8 | c[0] >>> 24) + c[7] | 0, t[2] = c[2] + (c[1] << 16 | c[1] >>> 16) + (c[0] << 16 | c[0] >>> 16) | 0, t[3] = c[3] + (c[2] << 8 | c[2] >>> 24) + c[1] | 0, t[4] = c[4] + (c[3] << 16 | c[3] >>> 16) + (c[2] << 16 | c[2] >>> 16) | 0, t[5] = c[5] + (c[4] << 8 | c[4] >>> 24) + c[3] | 0, t[6] = c[6] + (c[5] << 16 | c[5] >>> 16) + (c[4] << 16 | c[4] >>> 16) | 0, t[7] = c[7] + (c[6] << 8 | c[6] >>> 24) + c[5] | 0 } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = [], a = [], c = [], h = o.Rabbit = n.extend({ _doReset: function () { for (var t = this._key.words, e = this.cfg.iv, i = 0; i < 4; i++)t[i] = 16711935 & (t[i] << 8 | t[i] >>> 24) | 4278255360 & (t[i] << 24 | t[i] >>> 8); var n = this._X = [t[0], t[3] << 16 | t[2] >>> 16, t[1], t[0] << 16 | t[3] >>> 16, t[2], t[1] << 16 | t[0] >>> 16, t[3], t[2] << 16 | t[1] >>> 16], o = this._C = [t[2] << 16 | t[2] >>> 16, 4294901760 & t[0] | 65535 & t[1], t[3] << 16 | t[3] >>> 16, 4294901760 & t[1] | 65535 & t[2], t[0] << 16 | t[0] >>> 16, 4294901760 & t[2] | 65535 & t[3], t[1] << 16 | t[1] >>> 16, 4294901760 & t[3] | 65535 & t[0]]; this._b = 0; for (var i = 0; i < 4; i++)r.call(this); for (var i = 0; i < 8; i++)o[i] ^= n[i + 4 & 7]; if (e) { var s = e.words, a = s[0], c = s[1], h = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8), l = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8), f = h >>> 16 | 4294901760 & l, u = l << 16 | 65535 & h; o[0] ^= h, o[1] ^= f, o[2] ^= l, o[3] ^= u, o[4] ^= h, o[5] ^= f, o[6] ^= l, o[7] ^= u; for (var i = 0; i < 4; i++)r.call(this) } }, _doProcessBlock: function (t, e) { var i = this._X; r.call(this), s[0] = i[0] ^ i[5] >>> 16 ^ i[3] << 16, s[1] = i[2] ^ i[7] >>> 16 ^ i[5] << 16, s[2] = i[4] ^ i[1] >>> 16 ^ i[7] << 16, s[3] = i[6] ^ i[3] >>> 16 ^ i[1] << 16; for (var n = 0; n < 4; n++)s[n] = 16711935 & (s[n] << 8 | s[n] >>> 24) | 4278255360 & (s[n] << 24 | s[n] >>> 8), t[e + n] ^= s[n] }, blockSize: 4, ivSize: 2 }); e.Rabbit = n._createHelper(h) }(), t.mode.CTR = function () { var r = t.lib.BlockCipherMode.extend(), e = r.Encryptor = r.extend({ processBlock: function (t, r) { var e = this._cipher, i = e.blockSize, n = this._iv, o = this._counter; n && (o = this._counter = n.slice(0), this._iv = void 0); var s = o.slice(0); e.encryptBlock(s, 0), o[i - 1] = o[i - 1] + 1 | 0; for (var a = 0; a < i; a++)t[r + a] ^= s[a] } }); return r.Decryptor = e, r }(), function () { function r() { for (var t = this._X, r = this._C, e = 0; e < 8; e++)a[e] = r[e]; r[0] = r[0] + 1295307597 + this._b | 0, r[1] = r[1] + 3545052371 + (r[0] >>> 0 < a[0] >>> 0 ? 1 : 0) | 0, r[2] = r[2] + 886263092 + (r[1] >>> 0 < a[1] >>> 0 ? 1 : 0) | 0, r[3] = r[3] + 1295307597 + (r[2] >>> 0 < a[2] >>> 0 ? 1 : 0) | 0, r[4] = r[4] + 3545052371 + (r[3] >>> 0 < a[3] >>> 0 ? 1 : 0) | 0, r[5] = r[5] + 886263092 + (r[4] >>> 0 < a[4] >>> 0 ? 1 : 0) | 0, r[6] = r[6] + 1295307597 + (r[5] >>> 0 < a[5] >>> 0 ? 1 : 0) | 0, r[7] = r[7] + 3545052371 + (r[6] >>> 0 < a[6] >>> 0 ? 1 : 0) | 0, this._b = r[7] >>> 0 < a[7] >>> 0 ? 1 : 0; for (var e = 0; e < 8; e++) { var i = t[e] + r[e], n = 65535 & i, o = i >>> 16, s = ((n * n >>> 17) + n * o >>> 15) + o * o, h = ((4294901760 & i) * i | 0) + ((65535 & i) * i | 0); c[e] = s ^ h } t[0] = c[0] + (c[7] << 16 | c[7] >>> 16) + (c[6] << 16 | c[6] >>> 16) | 0, t[1] = c[1] + (c[0] << 8 | c[0] >>> 24) + c[7] | 0, t[2] = c[2] + (c[1] << 16 | c[1] >>> 16) + (c[0] << 16 | c[0] >>> 16) | 0, t[3] = c[3] + (c[2] << 8 | c[2] >>> 24) + c[1] | 0, t[4] = c[4] + (c[3] << 16 | c[3] >>> 16) + (c[2] << 16 | c[2] >>> 16) | 0, t[5] = c[5] + (c[4] << 8 | c[4] >>> 24) + c[3] | 0, t[6] = c[6] + (c[5] << 16 | c[5] >>> 16) + (c[4] << 16 | c[4] >>> 16) | 0, t[7] = c[7] + (c[6] << 8 | c[6] >>> 24) + c[5] | 0 } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = [], a = [], c = [], h = o.RabbitLegacy = n.extend({ _doReset: function () { var t = this._key.words, e = this.cfg.iv, i = this._X = [t[0], t[3] << 16 | t[2] >>> 16, t[1], t[0] << 16 | t[3] >>> 16, t[2], t[1] << 16 | t[0] >>> 16, t[3], t[2] << 16 | t[1] >>> 16], n = this._C = [t[2] << 16 | t[2] >>> 16, 4294901760 & t[0] | 65535 & t[1], t[3] << 16 | t[3] >>> 16, 4294901760 & t[1] | 65535 & t[2], t[0] << 16 | t[0] >>> 16, 4294901760 & t[2] | 65535 & t[3], t[1] << 16 | t[1] >>> 16, 4294901760 & t[3] | 65535 & t[0]]; this._b = 0; for (var o = 0; o < 4; o++)r.call(this); for (var o = 0; o < 8; o++)n[o] ^= i[o + 4 & 7]; if (e) { var s = e.words, a = s[0], c = s[1], h = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8), l = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8), f = h >>> 16 | 4294901760 & l, u = l << 16 | 65535 & h; n[0] ^= h, n[1] ^= f, n[2] ^= l, n[3] ^= u, n[4] ^= h, n[5] ^= f, n[6] ^= l, n[7] ^= u; for (var o = 0; o < 4; o++)r.call(this) } }, _doProcessBlock: function (t, e) { var i = this._X; r.call(this), s[0] = i[0] ^ i[5] >>> 16 ^ i[3] << 16, s[1] = i[2] ^ i[7] >>> 16 ^ i[5] << 16, s[2] = i[4] ^ i[1] >>> 16 ^ i[7] << 16, s[3] = i[6] ^ i[3] >>> 16 ^ i[1] << 16; for (var n = 0; n < 4; n++)s[n] = 16711935 & (s[n] << 8 | s[n] >>> 24) | 4278255360 & (s[n] << 24 | s[n] >>> 8), t[e + n] ^= s[n] }, blockSize: 4, ivSize: 2 }); e.RabbitLegacy = n._createHelper(h) }(), t.pad.ZeroPadding = { pad: function (t, r) { var e = 4 * r; t.clamp(), t.sigBytes += e - (t.sigBytes % e || e) }, unpad: function (t) { for (var r = t.words, e = t.sigBytes - 1; !(r[e >>> 2] >>> 24 - e % 4 * 8 & 255);)e--; t.sigBytes = e + 1 } }, t }); -const cookieName = '威锋网' -const cookieKey = 'chavy_cookie_feng' -const chavy = init() -const cookieVal = chavy.getdata(cookieKey) +const $ = new Env('威锋网') +$.KEY_login = 'chavy_login_feng' -sign() +!(async () => { + $.CryptoJS = $.isNode() ? require('crypto-js') : CryptoJS + await login() + await sign() + showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) -function encrypt(str) { - const key = `abf82c19da4b098b` - const iv = CryptoJS.enc.Utf8.parse(key) - return CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(str), iv, { - iv: iv, - mode: CryptoJS.mode.CBC, - padding: CryptoJS.pad.Pkcs7 - }).toString() -} - -function sign() { - // abf82c19da4b098b - // url=/v1/attendance/userSignIn$time=1581313242043000000 - // PnzCEAiMjJaYWoBNqwXwssbnYHoJM81RvTrfrwyUsxUtRmMiiGKnyCVJrcqxb9+vKdljjPAZ3cf9lQUJdyNPdQ== - const timestamp = Date.parse(new Date()) - const signurl = `url=/v1/attendance/userSignIn$time=${timestamp}` - const url = { url: `https://beta-api.feng.com/v1/attendance/userSignIn?time=${timestamp}`, headers: {}, body: {} } - url.headers['Host'] = 'beta-api.feng.com' - url.headers['Origin'] = 'https://www.feng.com' - url.headers['Referer'] = 'https://www.feng.com/' - url.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8' - url.headers['Accept'] = 'application/json, text/plain, */*' - url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' - url.headers['X-Access-Token'] = getToken() - url.headers['X-Request-Id'] = encrypt(signurl) - chavy.post(url, (error, response, data) => { - chavy.log(`${cookieName}, signdata: ${data}`) - if (data) { - let result = JSON.parse(data) - let title = `${cookieName}` - // 签到成功 || 签到重复 - if (result.status && (result.status.code == 0 || result.status.code == 1021)) { - if (chavy.isQuanX()) getexp(result) - if (chavy.isSurge()) showSurgeMsg(result) - } - // 签到失败 - else { - let subTitle = `签到结果: 失败` - let detail = `说明: ${result.status.message}` - chavy.msg(title, subTitle, detail) - chavy.log(`${cookieName}, cookieKey: ${cookieVal}`) - chavy.log(`${cookieName}, token: ${getToken()}`) - } - } else { - chavy.msg(cookieName, `签到结果: 失败`, `说明: 威锋加了校验, 偶尔能签, 选择性弃坑吧!`) +function login() { + const loginOpts = $.getjson($.KEY_login) + const url = { + url: `https://api.wfdata.club/v1/auth/signin`, + body: loginOpts['body'], + headers: { + 'X-Request-Id': encrypt(`url=/v1/auth/signin$time=${new Date().getTime()}`), + 'X-Running-Env': loginOpts['headers']['X-Running-Env'] } + } + return $.http.post(url).then((resp) => { + $.login = JSON.parse(resp.body).data }) - chavy.done() } -function getexp(signResult) { - const timestamp = Date.parse(new Date()) - const signurl = `url=/v1/user/experience$time=${timestamp}` - const url = { url: `https://beta-api.feng.com/v1/user/experience?time=${timestamp}`, headers: {}, body: {} } - url.headers['Host'] = 'beta-api.feng.com' - url.headers['Origin'] = 'https://www.feng.com' - url.headers['Referer'] = 'https://www.feng.com/' - url.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8' - url.headers['Accept'] = 'application/json, text/plain, */*' - url.headers['Accept-Encoding'] = 'gzip, deflate, br' - url.headers['Accept-Language'] = 'zh-cn' - url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' - url.headers['X-Access-Token'] = getToken() - url.headers['X-Request-Id'] = encrypt(signurl) - chavy.get(url, (error, response, data) => { - chavy.log(`${cookieName}, getexpdata: ${data}`) - let result = JSON.parse(data) - let title = `${cookieName}` - let subTitle = '' - let detail = `累计: ${result.data.signInCount}次, 等级: ${result.data.level} (${result.data.levelTitle}), 经验: ${result.data.currentExperience}/${result.data.creditsLower}` - chavy.log(signResult.status.code + ', ' + signResult.status.code == 0) - // 签到成功 - if (signResult.status.code == 0) { - subTitle = `签到结果: 成功` - chavy.msg(title, subTitle, detail) - } - // 签到重复 - else if (signResult.status.code == 1021) { - subTitle = `签到结果: 成功 (重复签到)` - chavy.msg(title, subTitle, detail) +function sign() { + const loginOpts = $.getjson($.KEY_login) + const url = { + url: `https://api.wfdata.club/v1/attendance/userSignIn`, + body: '', + headers: { + 'Content-Type': `application/x-www-form-urlencoded`, + 'User-Agent': `fengapp/6.4 (com.feng.New.WPForumClient; build:21.03.14; iOS 14.4.1) Alamofire/4.9.1`, + 'X-Request-Id': encrypt(`url=/v1/attendance/userSignIn$time=${new Date().getTime()}`), + 'X-Running-Env': loginOpts['headers']['X-Running-Env'], + 'X-Access-Token': $.login.accessToken } - }) -} - -function showSurgeMsg(signResult) { - let title = `${cookieName}` - let detail = `` - // 签到成功 - if (signResult.status.code == 0) { - subTitle = `签到结果: 成功` - chavy.msg(title, subTitle, detail) - } - // 签到重复 - else if (signResult.status.code == 1021) { - subTitle = `签到结果: 成功 (重复签到)` - chavy.msg(title, subTitle, detail) } + return $.http + .post(url) + .then((resp) => { + $.sign = JSON.parse(resp.body) + }) + .catch((err) => console.log(err)) } -function getToken() { - const userInfo = decodeURIComponent(decodeURIComponent(cookieVal.match(/userInfo=(\{[^;]*)/)[1])) - return JSON.parse(userInfo).accessToken +function showmsg() { + const signCode = $.sign.status.code + const result = signCode === 0 ? '成功' : signCode === 1021 ? '重复' : '失败' + $.subt = `签到: ${result}` + $.desc = `说明: ${$.sign.status.message}` + $.msg($.name, $.subt, $.desc) } -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) - } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) - } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +function encrypt(str) { + const key = `aaf82c19ea3b090b` + const iv = $.CryptoJS.enc.Utf8.parse(key) + return $.CryptoJS.AES.encrypt($.CryptoJS.enc.Utf8.parse(str), iv, { + iv: iv, + mode: $.CryptoJS.mode.CBC, + padding: $.CryptoJS.pad.Pkcs7 + }).toString() } + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/flyertea/README.md b/flyertea/README.md index ea9ec672b..5c138b4ad 100644 --- a/flyertea/README.md +++ b/flyertea/README.md @@ -8,10 +8,10 @@ ```properties [MITM] -www.flyertea.com +www.flyert.com [Script] -http-request ^https:\/\/www\.flyertea\.com\/source\/plugin\/mobile\/mobile\.php\?module=getdata&.* script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/flyertea/flyertea.cookie.js +http-request ^https:\/\/www\.flyert\.com\/source\/plugin\/mobile\/mobile\.php\?module=getdata&.* script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/flyertea/flyertea.cookie.js cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/flyertea/flyertea.js ``` @@ -19,13 +19,13 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr ```properties [MITM] -www.flyertea.com +www.flyert.com [rewrite_local] # 189及以前版本 -^https:\/\/www\.flyertea\.com\/source\/plugin\/mobile\/mobile\.php\?module=getdata&.* url script-response-body flyertea.cookie.js +^https:\/\/www\.flyert\.com\/source\/plugin\/mobile\/mobile\.php\?module=getdata&.* url script-response-body flyertea.cookie.js # 190及以后版本 -^https:\/\/www\.flyertea\.com\/source\/plugin\/mobile\/mobile\.php\?module=getdata&.* url script-request-header flyertea.cookie.js +^https:\/\/www\.flyert\.com\/source\/plugin\/mobile\/mobile\.php\?module=getdata&.* url script-request-header flyertea.cookie.js [task_local] 1 0 * * * flyertea.js @@ -33,7 +33,7 @@ www.flyertea.com ## 说明 -1. 先把`www.flyertea.com`加到`[MITM]` +1. 先把`www.flyert.com`加到`[MITM]` 2. 再配置重写规则: - Surge: 把两条远程脚本放到`[Script]` - QuanX: 把`flyertea.cookie.js`和`flyertea.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) diff --git a/flyertea/flyertea.js b/flyertea/flyertea.js index ab5d575a3..4cddc0017 100644 --- a/flyertea/flyertea.js +++ b/flyertea/flyertea.js @@ -1,32 +1,32 @@ -const cookieName = '飞客茶馆' +const $ = new Env('飞客茶馆') + const cookieKey = 'chavy_cookie_flyertea' const tokenKey = 'chavy_token_flyertea' -const chavy = init() -let cookieVal = chavy.getdata(cookieKey) -let tokenVal = chavy.getdata(tokenKey) +const cookieVal = $.getdata(cookieKey) +const tokenVal = $.getdata(tokenKey) sign() function sign() { const token = JSON.parse(tokenVal) - let url = { url: `https://www.flyertea.com/plugin.php?id=k_misign:sign&operation=qiandao&from=insign&version=${token.version}&appcan=appcan&appkey=${token.appkey}&appversion=${token.appversion}&formhash=${token.formhash}&token=${token.token}`, headers: { Cookie: cookieVal } } + let url = { + url: `https://www.flyert.com/plugin.php?id=k_misign:sign&operation=qiandao&from=insign&version=${token.version}&appcan=appcan&appkey=${token.appkey}&appversion=${token.appversion}&formhash=${token.formhash}&token=${token.token}`, + headers: { Cookie: cookieVal } + } url.headers['Accept'] = `*/*` - url.headers['Accept-Language'] = `zh-Hans-CN;q=1, en-US;q=0.9` - url.headers['Host'] = `www.flyertea.com` - url.headers['User-Agent'] = `FKForum/7.14.0 (iPhone10,1; iOS 13.3; Scale/2.00)` - url.headers['Referer'] = `https://www.flyertea.com/home.php` + url.headers['Accept-Language'] = `zh-Hans-CN;q=1` + url.headers['Host'] = `www.flyert.com` + url.headers['User-Agent'] = `FKForum/7.28.3 (iPhone 12; iOS 14.5; Scale/3.00)` url.headers['Accept-Encoding'] = `gzip, deflate, br` url.headers['Connection'] = `keep-alive` - chavy.get(url, (error, response, data) => { - chavy.log(`${cookieName}, data: ${data}`) + $.get(url, (error, response, data) => { const result = JSON.parse(data) - const title = `${cookieName}` let subTitle = `` let detail = `` if (result.Variables && result.Variables.Message.messageval == 'success') { subTitle = `签到结果: 成功` detail = `说明: ${result.Variables.Message.messagestr}` - chavy.msg(title, subTitle, detail) + $.msg($.name, subTitle, detail) } else { if (result.Message.messageval == 'error' && result.Message.messagestr.indexOf('只能签到一次') >= 0) { subTitle = `签到结果: 成功 (重复签到)` @@ -34,52 +34,10 @@ function sign() { subTitle = `签到结果: 失败` } detail = `说明: ${result.Message.messagestr}` - chavy.msg(title, subTitle, detail) + $.msg($.name, subTitle, detail) } + $.done() }) - chavy.done() -} - -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) - } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) - } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } } +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/follow/follow.js b/follow/follow.js new file mode 100644 index 000000000..632e4da56 --- /dev/null +++ b/follow/follow.js @@ -0,0 +1,44 @@ +const $ = new Env('follow 每日签到') +$.desc = [] + +const csrfToken = $.getdata('follow_csrfToken') +const cookie = $.getdata('follow_cookie') + +!(async () => { + await sign() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +function sign() { + return new Promise((resolve) => { + const options = { + url: 'https://api.follow.is/wallets/transactions/claim_daily', + 'headers': { + 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.38(0x1800262c) NetType/4G Language/zh_CN', + 'content-type': 'application/json', + 'Accept': '*/*', + 'Connection': 'keep-alive', + 'cookie': cookie + }, + body: JSON.stringify({"csrfToken":csrfToken}) + } + $.post(options, async (err, resp, body) => { + try { + console.log(body) + const { code, message } = JSON.parse(body) + if (code !== 0) { + $.msg($.name, `签到失败: ${message}`) + } else { + $.msg($.name, `签到成功`) + } + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function Env(t,e){return new class{constructor(t,e){this.name=t,this.http=new class t{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,a)=>{s.call(this,t,(t,s,i)=>{t?a(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=new Date().getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e,a=this.getdata(t);if(a)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,a)=>e(a))})}runScript(t,e){return new Promise(s=>{let a=this.getdata("@chavy_boxjs_userCfgs.httpapi");a=a?a.replace(/\n/g,"").trim():a;let i=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");i=i?1*i:20,i=e&&e.timeout?e.timeout:i;let[r,h]=a.split("@"),o={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:i},headers:{"X-Key":r,Accept:"*/*"},timeout:i};this.post(o,(t,e,a)=>s(a))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");let t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e);if(!s&&!a)return{};try{return JSON.parse(this.fs.readFileSync(s?t:e))}catch(i){return{}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");let t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e),i=JSON.stringify(this.data);s?this.fs.writeFileSync(t,i):a?this.fs.writeFileSync(e,i):this.fs.writeFileSync(t,i)}}lodash_get(t,e,s){let a=e.replace(/\[(\d+)\]/g,".$1").split("."),i=t;for(let r of a)if(void 0===(i=Object(i)[r]))return s;return i}lodash_set(t,e,s){return Object(t)!==t||(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,a)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[a+1])>>0==+e[a+1]?[]:{},t)[e[e.length-1]]=s),t}getdata(t){let e=this.getval(t);if(/^@/.test(t)){let[,s,a]=/^@(.*?)\.(.*?)$/.exec(t),i=s?this.getval(s):"";if(i)try{let r=JSON.parse(i);e=r?this.lodash_get(r,a,""):e}catch(h){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){let[,a,i]=/^@(.*?)\.(.*?)$/.exec(e),r=this.getval(a);try{let h=JSON.parse(a?"null"===r?null:r||"{}":"{}");this.lodash_set(h,i,t),s=this.setval(JSON.stringify(h),a)}catch(o){let n={};this.lodash_set(n,i,t),s=this.setval(JSON.stringify(n),a)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=()=>{}){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),t?.params&&(t.url+="?"+this.queryStr(t.params)),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{let{statusCode:s,statusCode:a,headers:i,body:r,bodyBytes:h}=t;e(null,{status:s,statusCode:a,headers:i,body:r,bodyBytes:h},r,h)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){let s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(a){this.logErr(a)}}).then(t=>{let{statusCode:a,statusCode:i,headers:r,rawBody:h}=t,o=s.decode(h,this.encoding);e(null,{status:a,statusCode:i,headers:r,rawBody:h,body:o},o)},t=>{let{message:a,response:i}=t;e(a,i,i&&s.decode(i.rawBody,this.encoding))})}}post(t,e=()=>{}){let s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{let{statusCode:s,statusCode:a,headers:i,body:r,bodyBytes:h}=t;e(null,{status:s,statusCode:a,headers:i,body:r,bodyBytes:h},r,h)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let a=require("iconv-lite");this.initGotEnv(t);let{url:i,...r}=t;this.got[s](i,r).then(t=>{let{statusCode:s,statusCode:i,headers:r,rawBody:h}=t,o=a.decode(h,this.encoding);e(null,{status:s,statusCode:i,headers:r,rawBody:h,body:o},o)},t=>{let{message:s,response:i}=t;e(s,i,i&&a.decode(i.rawBody,this.encoding))})}}time(t,e=null){let s=e?new Date(e):new Date,a={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};for(let i in/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length))),a)RegExp("("+i+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[i]:("00"+a[i]).substr((""+a[i]).length)));return t}queryStr(t){let e="";for(let s in t){let a=t[s];null!=a&&""!==a&&("object"==typeof a&&(a=JSON.stringify(a)),e+=`${s}=${a}&`)}return e.substring(0,e.length-1)}msg(e=t,s="",a="",i){let r=t=>{switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:return{url:t.url||t.openUrl||t["open-url"]};case"Loon":{let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}case"Quantumult X":{let a=t["open-url"]||t.url||t.openUrl,i;return{"open-url":a,"media-url":t["media-url"]||t.mediaUrl,"update-pasteboard":t["update-pasteboard"]||t.updatePasteboard}}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,a,r(i));break;case"Quantumult X":$notify(e,s,a,r(i));case"Node.js":}if(!this.isMuteLog){let h=["","==============\uD83D\uDCE3系统通知\uD83D\uDCE3=============="];h.push(e),s&&h.push(s),a&&h.push(a),console.log(h.join("\n")),this.logs=this.logs.concat(h)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,t);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,t.stack)}}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){let e=new Date().getTime(),s=(e-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} \ No newline at end of file diff --git a/haidilao/README.md b/haidilao/README.md new file mode 100644 index 000000000..73430ba37 --- /dev/null +++ b/haidilao/README.md @@ -0,0 +1,104 @@ +# 海底捞 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> 感谢[@danchaw](https://github.com/danchaw) PR +## 配置 (Surge) + +```properties +[MITM] +activity-1.m.duiba.com.cn + +[Script] +http-request ^https:\/\/activity-1\.m\.duiba\.com\.cn\/signactivity\/doSign$ requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/haidilao/hdl.js +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/haidilao/hdl.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +activity-1.m.duiba.com.cn + +[rewrite_local] + +# [商店版] +^https:\/\/activity-1\.m\.duiba\.com\.cn\/signactivity\/doSign$ url script-request-body hdl.js + +# [TestFlight] +^https:\/\/activity-1\.m\.duiba\.com\.cn\/signactivity\/doSign$ url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/haidilao/hdl.js + +[task_local] + +# [商店版] +1 0 * * * hdl.js + +# [TestFlight] +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/haidilao/hdl.js +``` + +## 说明 + +1. 先把`activity-1.m.duiba.com.cn`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`hdl.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP[海底捞](https://apps.apple.com/cn/app/%E6%B5%B7%E5%BA%95%E6%8D%9E/id553115181) 然后手动签到 1 次, 系统提示: `获取Cookie: 成功` +4. 最后就可以把第 1 条脚本注释掉了 +5. 运行一次脚本, 如果提示重复签到, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@danchaw](https://github.com/danchaw) diff --git a/haidilao/hdl.js b/haidilao/hdl.js new file mode 100644 index 000000000..24363b8dd --- /dev/null +++ b/haidilao/hdl.js @@ -0,0 +1,106 @@ +const cookieName = '海底捞' +const signurlKey = 'signurl_hdl' +const signheaderKey = 'signheader_hdl' +const signbodyKey = 'signbody_hdl' +const hdl = init() + +let isGetCookie = typeof $request !== 'undefined' + +if (isGetCookie) { + getcookie() +} else { + sign() +} + +function getcookie() { + if ($request && $request.method == 'POST') { + const signurlVal = $request.url + const signheaderVal = JSON.stringify($request.headers) + const signbodyVal = $request.body + + if (signurlVal) hdl.setdata(signurlVal, signurlKey) + if (signheaderVal) hdl.setdata(signheaderVal, signheaderKey) + if (signbodyVal) hdl.setdata(signbodyVal, signbodyKey) + hdl.msg(cookieName, `获取Cookie: 成功, 请禁用该脚本`, ``) + } + hdl.done() +} + +function sign() { + const signurlVal = hdl.getdata(signurlKey) + const signheaderVal = hdl.getdata(signheaderKey) + const signbodyVal = hdl.getdata(signbodyKey) + const url = { url: signurlVal, headers: JSON.parse(signheaderVal), body: signbodyVal } + hdl.post(url, (error, response, data) => { + hdl.log(`${cookieName}, data: ${data}`) + const title = `${cookieName}` + let subTitle = '' + let detail = '' + const result = JSON.parse(data) + if (result.success == true && result.signInfoVO.todaySigned == true) { + subTitle = `签到结果: 成功` + detail = `签到奖励: ${result.customInfo.foodNum}火柴, 连签: ${result.signInfoVO.continueDay}天` + } else if (result.success == false && result.signInfoVO.todaySigned == true) { + subTitle = `签到结果: 成功 (重复签到)` + detail = `连签: ${result.signInfoVO.continueDay}天` + } else { + subTitle = `签到结果: 失败` + detail = `说明: ${result.message}, 请重新获取` + } + hdl.msg(title, subTitle, detail) + hdl.done() + }) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + put = (url, cb) => { + if (isSurge()) { + $httpClient.put(url, cb) + } + if (isQuanX()) { + url.method = 'PUT' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, put, done } +} \ No newline at end of file diff --git a/hellobike/README.md b/hellobike/README.md new file mode 100644 index 000000000..178636257 --- /dev/null +++ b/hellobike/README.md @@ -0,0 +1,102 @@ +# 哈啰出行 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +## 配置 (Surge) + +```properties +[MITM] +gameapi.hellobike.com + +[Script] +http-request ^https:\/\/gameapi\.hellobike\.com\/api script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/hellobike/hellobike.js, requires-body=true +cron "5 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/hellobike/hellobike.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +gameapi.hellobike.com + +[rewrite_local] +# [商店版] +^https:\/\/gameapi\.hellobike\.com\/api url script-request-body hellobike/hellobike.js + +# [TestFlight] +^https:\/\/gameapi\.hellobike\.com\/api url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/hellobike/hellobike.js + +[task_local] +# [商店版] +5 0 * * * hellobike/hellobike.js + +# [TestFlight] +5 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/hellobike/hellobike.js +``` + +## 说明 + +1. 先把`gameapi.hellobike.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把远程脚本放到`[Script]` + - QuanX: 把`hellobike.js`传到`On My iPhone - Quantumult X - Scripts - hellobike` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP 进入签到页面: `我的` > `有哈有车` +4. 系统提示: `首次写入 哈啰出行 Token 成功 🎉` +5. 把获取 Cookie 的脚本注释掉 +6. 运行一次脚本, 如果提示重复签到, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:05`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@GideonSenku](https://github.com/GideonSenku) diff --git a/hellobike/hellobike.js b/hellobike/hellobike.js new file mode 100644 index 000000000..0bede437b --- /dev/null +++ b/hellobike/hellobike.js @@ -0,0 +1,303 @@ +const HELLO_BIKE = init() +const TASK_NAME = '哈啰出行' +const TOKEN_KEY = 'hellobike' +const API_URL = 'https://gameapi.hellobike.com/api' +const UA = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148; app=easybike; version=5.35.0' + +if (typeof $request !== 'undefined') { + getToken() + HELLO_BIKE.done() +} else { + ;(async () => { + let token = HELLO_BIKE.getdata(TOKEN_KEY) + if (!token) { + HELLO_BIKE.msg(TASK_NAME, '请先获取 Token') + HELLO_BIKE.done() + return + } + + await checkin(token).then(data => { + if (data && data.isSuccess) { + HELLO_BIKE.msg(TASK_NAME, `签到成功,获取 ${data.energy}c 能量`) + } else if (data && !data.isSuccess) { + HELLO_BIKE.msg(TASK_NAME, `重复签到`) + } + }).catch(error => { + HELLO_BIKE.msg(TASK_NAME, error.reason) + if (error.isInvalidToken) { + token = null + } + }) + + await share(token).then(data => { + HELLO_BIKE.log(TASK_NAME, `分享成功, ${JSON.stringify(data)}`) + }).catch(error => { + HELLO_BIKE.msg(TASK_NAME, error.reason) + if (error.isInvalidToken) { + token = null + } + }) + + await getEnergyList(token).then( + data => { + HELLO_BIKE.log(TASK_NAME, `获取能量:${JSON.stringify(data)}`) + return mergePromise(data.map(energy => collectEnergy(token, energy.guid))) + }, + error => { + HELLO_BIKE.msg(TASK_NAME, error.reason) + if (error.isInvalidToken) { + token = null + } + }, + ).then( + data => { + if (Array.isArray(data) && data.length > 0) { + HELLO_BIKE.log(TASK_NAME, `收取能量: ${JSON.stringify(data)}`) + let collected = data.filter(energy => { + return energy != null + }).reduce((total, currentValue) => { + return total + currentValue.energy + }, 0) + HELLO_BIKE.msg(TASK_NAME, `收取能量成功,总共收取 ${collected}c 能量`) + } + HELLO_BIKE.done() + }, + error => { + HELLO_BIKE.msg(TASK_NAME, error.reason) + HELLO_BIKE.done() + }, + ) + })() +} + +function getToken() { + if ($request.body) { + let body = JSON.parse($request.body) + if (body && body.token) { + let token = HELLO_BIKE.getdata(TOKEN_KEY) + if (token != null) { + if (token !== body.token) { + if (!HELLO_BIKE.setdata(body.token, TOKEN_KEY)) { + HELLO_BIKE.msg(`更新 ${TASK_NAME} Token 失败‼️`) + } else { + HELLO_BIKE.msg(`更新 ${TASK_NAME} Token 成功 🎉`) + } + } + } else { + if (!HELLO_BIKE.setdata(body.token, TOKEN_KEY)) { + HELLO_BIKE.msg(`首次写入 ${TASK_NAME} Token 失败‼️`) + } else { + HELLO_BIKE.msg(`首次写入 ${TASK_NAME} Token 成功 🎉`) + } + } + } + } +} + +function checkin(token) { + if (!token) { + return Promise.resolve({}) + } + return new Promise((resolve, reject) => { + let action = 'happy.energy.dailyCheck.v2' + let options = { + url: API_URL, + headers: { 'User-Agent': UA }, + body: JSON.stringify({ + action, + token, + ticket: '', + }), + } + HELLO_BIKE.post(options, (error, response, data) => { + if (error) { + HELLO_BIKE.log(TASK_NAME, `签到失败,error:${error}`) + reject(new RequestFailed(action, error)) + return + } + let result = JSON.parse(data) + if (result && result.code === 0 && result.data) { + resolve(result.data) + } else { + HELLO_BIKE.log(TASK_NAME, `签到失败,response:${data}`) + reject(new RequestFailed(action, result.msg, result.code === 103)) + } + }) + }) +} + +function share(token) { + if (!token) { + return Promise.resolve({}) + } + return new Promise((resolve, reject) => { + let action = 'happy.energy.dailyShare' + let options = { + url: API_URL, + headers: { 'User-Agent': UA }, + body: JSON.stringify({ + token, + action, + ticket: '', + }), + } + HELLO_BIKE.post(options, (error, response, data) => { + if (error) { + HELLO_BIKE.log(TASK_NAME, `分享失败,error:${error}`) + reject(new RequestFailed(action, error)) + return + } + let result = JSON.parse(data) + if (result && result.code === 0) { + resolve(result) + } else { + HELLO_BIKE.log(TASK_NAME, `分享失败,response:${data}`) + reject(new RequestFailed(action, result.msg, result.code === 103)) + } + }) + }) +} + +function getEnergyList(token) { + if (!token) { + return Promise.resolve([]) + } + return new Promise((resolve, reject) => { + let action = 'happy.energy.getEnergyList' + let options = { + url: API_URL, + headers: { 'User-Agent': UA }, + body: JSON.stringify({ + token, + action, + ticket: '', + limit: 6, + }), + } + HELLO_BIKE.post(options, (error, response, data) => { + if (error) { + HELLO_BIKE.log(TASK_NAME, `获取能量失败,error:${error}`) + reject(new RequestFailed(action, error)) + return + } + let result = JSON.parse(data) + if (result && result.code === 0 && result.data) { + resolve(result.data) + } else { + HELLO_BIKE.log(TASK_NAME, `获取能量失败,response:${data}`) + reject(new RequestFailed(action, result.msg, result.code === 103)) + } + }) + }) +} + +function collectEnergy(token, energyGuid) { + if (!token) { + return Promise.resolve({}) + } + return new Promise((resolve, reject) => { + let action = 'happy.energy.collectEnergy' + let options = { + url: API_URL, + headers: { 'User-Agent': UA }, + body: JSON.stringify({ + token, + action, + ticket: '', + energyGuid, + }), + } + HELLO_BIKE.post(options, (error, response, data) => { + if (error) { + HELLO_BIKE.log(TASK_NAME, `收取能量失败,error:${error}`) + reject(new RequestFailed(action, error)) + return + } + let result = JSON.parse(data) + if (result && result.code === 0 && result.data) { + resolve(result.data) + } else { + HELLO_BIKE.log(TASK_NAME, `收取能量失败,response:${data}`) + reject(new RequestFailed(action, result.msg, result.code === 103)) + } + }) + }) +} + +function mergePromise(promises = []) { + let array = [] + let sequence = Promise.resolve([]) + promises.forEach(promise => { + sequence = sequence.then(() => promise).then(data => { + array.push(data) + return array + }) + }) + return sequence +} + +function init() { + isSurge = () => { + return undefined !== this.$httpClient + } + isQuanX = () => { + return undefined !== this.$task + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle = '', body = '') => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (title, msg) => { + console.log(`${title}:\n${msg}\n`) + } + get = (options, callback) => { + if (isQuanX()) { + if (typeof options == 'string') options = { url: options } + options['method'] = 'GET' + return $task.fetch(options).then( + response => { + response['status'] = response.statusCode + callback(null, response, response.body) + }, + reason => callback(reason.error, null, null), + ) + } + if (isSurge()) return $httpClient.get(options, callback) + } + post = (options, callback) => { + if (isQuanX()) { + if (typeof options == 'string') options = { url: options } + options['method'] = 'POST' + $task.fetch(options).then( + response => { + response['status'] = response.statusCode + callback(null, response, response.body) + }, + reason => callback(reason.error, null, null), + ) + } + if (isSurge()) $httpClient.post(options, callback) + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} + +function RequestFailed(action = '', reason = '', isInvalidToken = false) { + this.action = action + this.reason = reason + this.isInvalidToken = isInvalidToken +} + +RequestFailed.prototype = { + constructor: RequestFailed, +} diff --git a/hycan/README.md b/hycan/README.md new file mode 100644 index 000000000..e0fd94cc7 --- /dev/null +++ b/hycan/README.md @@ -0,0 +1,103 @@ +# HYCAN合创 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 +> 感谢 [@danchaw](https://github.com/danchaw) PR +## 配置 (Surge) + +```properties +[MITM] +wxprdapplet.gac-nio.com + +[Script] +http-request ^https:\/\/wxprdapplet\.gac-nio\.com\/community\/userSignIn\/simpleAuth\/front\/.*\/sign$ script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/hycan/hycan.cookie.js +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/hycan/hycan.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +wxprdapplet.gac-nio.com + +[rewrite_local] + +# [商店版] +^https:\/\/wxprdapplet\.gac-nio\.com\/community\/userSignIn\/simpleAuth\/front\/.*\/sign$ url script-request-header hycan.cookie.js + +# [TestFlight] +^https:\/\/wxprdapplet\.gac-nio\.com\/community\/userSignIn\/simpleAuth\/front\/.*\/sign$ url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/hycan/hycan.cookie.js + +[task_local] + +# [商店版] +1 0 * * * hycan.js + +# [TestFlight] +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/hycan/hycan.js +``` + +## 说明 + +1. 先把`wxprdapplet.gac-nio.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`hycan.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP[HYCAN合创](https://apps.apple.com/cn/app/hycan%E5%90%88%E5%88%9B-%E5%B9%BF%E6%B1%BD%E8%94%9A%E6%9D%A5/id1464838502) 然后手动签到 1 次, 系统提示: `获取Cookie: 成功` +4. 最后就可以把第 1 条脚本注释掉了 +5. 运行一次脚本, 如果提示重复签到, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@danchaw](https://github.com/danchaw) diff --git a/hycan/hycan.cookie.js b/hycan/hycan.cookie.js new file mode 100644 index 000000000..0bcae1e3a --- /dev/null +++ b/hycan/hycan.cookie.js @@ -0,0 +1,67 @@ +const cookieName = 'HYCAN合创' +const signurlKey = 'signurl_hycan' +const signheaderKey = 'signheader_hycan' +const hycan = init() + +if ($request && $request.method == 'POST') { + const signurlVal = $request.url + const signheaderVal = JSON.stringify($request.headers) + + if (signurlVal) hycan.setdata(signurlVal, signurlKey) + if (signheaderVal) hycan.setdata(signheaderVal, signheaderKey) + hycan.msg(cookieName, `获取Cookie: 成功`, ``) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + put = (url, cb) => { + if (isSurge()) { + $httpClient.put(url, cb) + } + if (isQuanX()) { + url.method = 'PUT' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, put, done } +} +hycan.done() \ No newline at end of file diff --git a/hycan/hycan.js b/hycan/hycan.js new file mode 100644 index 000000000..ca9aa2ba3 --- /dev/null +++ b/hycan/hycan.js @@ -0,0 +1,83 @@ +const cookieName = 'HYCAN合创' +const signurlKey = 'signurl_hycan' +const signheaderKey = 'signheader_hycan' +const hycan = init() +const signurlVal = hycan.getdata(signurlKey) +const signheaderVal = hycan.getdata(signheaderKey) + +sign() + +function sign() { + const url = { url: signurlVal, headers: JSON.parse(signheaderVal) } + hycan.post(url, (error, response, data) => { + hycan.log(`${cookieName}, data: ${data}`) + const title = `${cookieName}` + let subTitle = '' + let detail = '' + const result = JSON.parse(data) + if (result.data.addScore == true) { + subTitle = `签到结果: 成功` + detail = `签到积分: ${result.data.score}, 签到详情: ${result.data.msg}` + } else if (result.data.addScore == false) { + subTitle = `签到结果: 成功 (重复签到)` + } else { + subTitle = `签到结果: 失败` + detail = `说明: token失效, ${result.msg}` + } + hycan.msg(title, subTitle, detail) + hycan.done() + }) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + put = (url, cb) => { + if (isSurge()) { + $httpClient.put(url, cb) + } + if (isQuanX()) { + url.method = 'PUT' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, put, done } +} diff --git a/ithome/ithome.cookie.js b/ithome/ithome.cookie.js new file mode 100644 index 000000000..2387fc656 --- /dev/null +++ b/ithome/ithome.cookie.js @@ -0,0 +1,39 @@ +/** + * + * hostname = napi.ithome.com + * + * # Surge + * Rewrite: ithome = type=http-request,pattern=^https:\/\/napi\.ithome\.com\/api\/usersign\/getsigninfo?,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ithome/ithome.cookie.js,debug=true + * Tasks: ithome-签到 = type=cron,cronexp=10 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ithome/ithome.js,wake-system=true + * + * # QuanX + * ^https:\/\/napi\.ithome\.com\/api\/usersign\/getsigninfo? url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/ithome/ithome.cookie.js + * 10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/ithome/ithome.js, tag=ithome-签到 + * + * # Loon + * http-response ^https:\/\/napi\.ithome\.com\/api\/usersign\/getsigninfo? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ithome/ithome.cookie.js + * cron "10 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ithome/ithome.js + * + * # 获取方式:app进入签到页面获取 + * # 解密参考GitHub @Grergo @daimiaopeng + * + */ + + +const $ = new Env('IT之家') +$.userHash = 'senku_ithome_userHash' + +!(async () => { + const userHash = $request.url.match(/userHash=([^&]+)/)?.[1] + if (userHash&&$.setdata(userHash, $.userHash)) { + $.subt = `获取会话: 成功! (${$.userHash})` + } else { + $.subt = `获取会话: 失败! (${$.userHash})` + } + $.msg($.name, $.subt, $.desc) +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/ithome/ithome.js b/ithome/ithome.js new file mode 100644 index 000000000..9b582f587 --- /dev/null +++ b/ithome/ithome.js @@ -0,0 +1,174 @@ +// prettier-ignore +!function(t,e){"object"==typeof exports?module.exports=exports=e():"function"==typeof define&&define.amd?define([],e):t.CryptoJS=e()}(this,function(){var t,e,r,i,n,o,s,c,a,h,l=l||function(t,e){var r;if("undefined"!=typeof window&&window.crypto&&(r=window.crypto),!r&&"undefined"!=typeof window&&window.msCrypto&&(r=window.msCrypto),!r&&"undefined"!=typeof global&&global.crypto&&(r=global.crypto),!r&&"function"==typeof require)try{r=require("crypto")}catch(t){}var i=function(){if(r){if("function"==typeof r.getRandomValues)try{return r.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof r.randomBytes)try{return r.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")},n=Object.create||function(){function t(){}return function(e){var r;return t.prototype=e,r=new t,t.prototype=null,r}}(),o={},s=o.lib={},c=s.Base={extend:function(t){var e=n(this);return t&&e.mixIn(t),e.hasOwnProperty("init")&&this.init!==e.init||(e.init=function(){e.$super.init.apply(this,arguments)}),e.init.prototype=e,e.$super=this,e},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},a=s.WordArray=c.extend({init:function(t,e){t=this.words=t||[],this.sigBytes=null!=e?e:4*t.length},toString:function(t){return(t||l).stringify(this)},concat:function(t){var e=this.words,r=t.words,i=this.sigBytes,n=t.sigBytes;if(this.clamp(),i%4)for(var o=0;o<n;o++){var s=r[o>>>2]>>>24-o%4*8&255;e[i+o>>>2]|=s<<24-(i+o)%4*8}else for(o=0;o<n;o+=4)e[i+o>>>2]=r[o>>>2];return this.sigBytes+=n,this},clamp:function(){var e=this.words,r=this.sigBytes;e[r>>>2]&=4294967295<<32-r%4*8,e.length=t.ceil(r/4)},clone:function(){var t=c.clone.call(this);return t.words=this.words.slice(0),t},random:function(t){for(var e=[],r=0;r<t;r+=4)e.push(i());return new a.init(e,t)}}),h=o.enc={},l=h.Hex={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n<r;n++){var o=e[n>>>2]>>>24-n%4*8&255;i.push((o>>>4).toString(16)),i.push((15&o).toString(16))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i<e;i+=2)r[i>>>3]|=parseInt(t.substr(i,2),16)<<24-i%8*4;return new a.init(r,e/2)}},f=h.Latin1={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n<r;n++){var o=e[n>>>2]>>>24-n%4*8&255;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i<e;i++)r[i>>>2]|=(255&t.charCodeAt(i))<<24-i%4*8;return new a.init(r,e)}},u=h.Utf8={stringify:function(t){try{return decodeURIComponent(escape(f.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return f.parse(unescape(encodeURIComponent(t)))}},d=s.BufferedBlockAlgorithm=c.extend({reset:function(){this._data=new a.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=u.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(e){var r,i=this._data,n=i.words,o=i.sigBytes,s=this.blockSize,c=o/(4*s),h=(c=e?t.ceil(c):t.max((0|c)-this._minBufferSize,0))*s,l=t.min(4*h,o);if(h){for(var f=0;f<h;f+=s)this._doProcessBlock(n,f);r=n.splice(0,h),i.sigBytes-=l}return new a.init(r,l)},clone:function(){var t=c.clone.call(this);return t._data=this._data.clone(),t},_minBufferSize:0}),p=(s.Hasher=d.extend({cfg:c.extend(),init:function(t){this.cfg=this.cfg.extend(t),this.reset()},reset:function(){d.reset.call(this),this._doReset()},update:function(t){return this._append(t),this._process(),this},finalize:function(t){return t&&this._append(t),this._doFinalize()},blockSize:16,_createHelper:function(t){return function(e,r){return new t.init(r).finalize(e)}},_createHmacHelper:function(t){return function(e,r){return new p.HMAC.init(t,r).finalize(e)}}}),o.algo={});return o}(Math);return function(){var t=l,e=t.lib.WordArray;t.enc.Base64={stringify:function(t){var e=t.words,r=t.sigBytes,i=this._map;t.clamp();for(var n=[],o=0;o<r;o+=3)for(var s=(e[o>>>2]>>>24-o%4*8&255)<<16|(e[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|e[o+2>>>2]>>>24-(o+2)%4*8&255,c=0;c<4&&o+.75*c<r;c++)n.push(i.charAt(s>>>6*(3-c)&63));var a=i.charAt(64);if(a)for(;n.length%4;)n.push(a);return n.join("")},parse:function(t){var r=t.length,i=this._map,n=this._reverseMap;if(!n){n=this._reverseMap=[];for(var o=0;o<i.length;o++)n[i.charCodeAt(o)]=o}var s=i.charAt(64);if(s){var c=t.indexOf(s);-1!==c&&(r=c)}return function(t,r,i){for(var n=[],o=0,s=0;s<r;s++)if(s%4){var c=i[t.charCodeAt(s-1)]<<s%4*2,a=i[t.charCodeAt(s)]>>>6-s%4*2,h=c|a;n[o>>>2]|=h<<24-o%4*8,o++}return e.create(n,o)}(t,r,n)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}}(),function(t){var e=l,r=e.lib,i=r.WordArray,n=r.Hasher,o=e.algo,s=[];!function(){for(var e=0;e<64;e++)s[e]=4294967296*t.abs(t.sin(e+1))|0}();var c=o.MD5=n.extend({_doReset:function(){this._hash=new i.init([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(t,e){for(var r=0;r<16;r++){var i=e+r,n=t[i];t[i]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8)}var o=this._hash.words,c=t[e+0],l=t[e+1],d=t[e+2],p=t[e+3],_=t[e+4],v=t[e+5],y=t[e+6],g=t[e+7],B=t[e+8],w=t[e+9],k=t[e+10],S=t[e+11],m=t[e+12],x=t[e+13],b=t[e+14],H=t[e+15],z=o[0],A=o[1],C=o[2],D=o[3];z=a(z,A,C,D,c,7,s[0]),D=a(D,z,A,C,l,12,s[1]),C=a(C,D,z,A,d,17,s[2]),A=a(A,C,D,z,p,22,s[3]),z=a(z,A,C,D,_,7,s[4]),D=a(D,z,A,C,v,12,s[5]),C=a(C,D,z,A,y,17,s[6]),A=a(A,C,D,z,g,22,s[7]),z=a(z,A,C,D,B,7,s[8]),D=a(D,z,A,C,w,12,s[9]),C=a(C,D,z,A,k,17,s[10]),A=a(A,C,D,z,S,22,s[11]),z=a(z,A,C,D,m,7,s[12]),D=a(D,z,A,C,x,12,s[13]),C=a(C,D,z,A,b,17,s[14]),z=h(z,A=a(A,C,D,z,H,22,s[15]),C,D,l,5,s[16]),D=h(D,z,A,C,y,9,s[17]),C=h(C,D,z,A,S,14,s[18]),A=h(A,C,D,z,c,20,s[19]),z=h(z,A,C,D,v,5,s[20]),D=h(D,z,A,C,k,9,s[21]),C=h(C,D,z,A,H,14,s[22]),A=h(A,C,D,z,_,20,s[23]),z=h(z,A,C,D,w,5,s[24]),D=h(D,z,A,C,b,9,s[25]),C=h(C,D,z,A,p,14,s[26]),A=h(A,C,D,z,B,20,s[27]),z=h(z,A,C,D,x,5,s[28]),D=h(D,z,A,C,d,9,s[29]),C=h(C,D,z,A,g,14,s[30]),z=f(z,A=h(A,C,D,z,m,20,s[31]),C,D,v,4,s[32]),D=f(D,z,A,C,B,11,s[33]),C=f(C,D,z,A,S,16,s[34]),A=f(A,C,D,z,b,23,s[35]),z=f(z,A,C,D,l,4,s[36]),D=f(D,z,A,C,_,11,s[37]),C=f(C,D,z,A,g,16,s[38]),A=f(A,C,D,z,k,23,s[39]),z=f(z,A,C,D,x,4,s[40]),D=f(D,z,A,C,c,11,s[41]),C=f(C,D,z,A,p,16,s[42]),A=f(A,C,D,z,y,23,s[43]),z=f(z,A,C,D,w,4,s[44]),D=f(D,z,A,C,m,11,s[45]),C=f(C,D,z,A,H,16,s[46]),z=u(z,A=f(A,C,D,z,d,23,s[47]),C,D,c,6,s[48]),D=u(D,z,A,C,g,10,s[49]),C=u(C,D,z,A,b,15,s[50]),A=u(A,C,D,z,v,21,s[51]),z=u(z,A,C,D,m,6,s[52]),D=u(D,z,A,C,p,10,s[53]),C=u(C,D,z,A,k,15,s[54]),A=u(A,C,D,z,l,21,s[55]),z=u(z,A,C,D,B,6,s[56]),D=u(D,z,A,C,H,10,s[57]),C=u(C,D,z,A,y,15,s[58]),A=u(A,C,D,z,x,21,s[59]),z=u(z,A,C,D,_,6,s[60]),D=u(D,z,A,C,S,10,s[61]),C=u(C,D,z,A,d,15,s[62]),A=u(A,C,D,z,w,21,s[63]),o[0]=o[0]+z|0,o[1]=o[1]+A|0,o[2]=o[2]+C|0,o[3]=o[3]+D|0},_doFinalize:function(){var e=this._data,r=e.words,i=8*this._nDataBytes,n=8*e.sigBytes;r[n>>>5]|=128<<24-n%32;var o=t.floor(i/4294967296),s=i;r[15+(n+64>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),r[14+(n+64>>>9<<4)]=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),e.sigBytes=4*(r.length+1),this._process();for(var c=this._hash,a=c.words,h=0;h<4;h++){var l=a[h];a[h]=16711935&(l<<8|l>>>24)|4278255360&(l<<24|l>>>8)}return c},clone:function(){var t=n.clone.call(this);return t._hash=this._hash.clone(),t}});function a(t,e,r,i,n,o,s){var c=t+(e&r|~e&i)+n+s;return(c<<o|c>>>32-o)+e}function h(t,e,r,i,n,o,s){var c=t+(e&i|r&~i)+n+s;return(c<<o|c>>>32-o)+e}function f(t,e,r,i,n,o,s){var c=t+(e^r^i)+n+s;return(c<<o|c>>>32-o)+e}function u(t,e,r,i,n,o,s){var c=t+(r^(e|~i))+n+s;return(c<<o|c>>>32-o)+e}e.MD5=n._createHelper(c),e.HmacMD5=n._createHmacHelper(c)}(Math),e=(t=l).lib,r=e.WordArray,i=e.Hasher,n=t.algo,o=[],s=n.SHA1=i.extend({_doReset:function(){this._hash=new r.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],s=r[2],c=r[3],a=r[4],h=0;h<80;h++){if(h<16)o[h]=0|t[e+h];else{var l=o[h-3]^o[h-8]^o[h-14]^o[h-16];o[h]=l<<1|l>>>31}var f=(i<<5|i>>>27)+a+o[h];f+=h<20?1518500249+(n&s|~n&c):h<40?1859775393+(n^s^c):h<60?(n&s|n&c|s&c)-1894007588:(n^s^c)-899497514,a=c,c=s,s=n<<30|n>>>2,n=i,i=f}r[0]=r[0]+i|0,r[1]=r[1]+n|0,r[2]=r[2]+s|0,r[3]=r[3]+c|0,r[4]=r[4]+a|0},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[14+(i+64>>>9<<4)]=Math.floor(r/4294967296),e[15+(i+64>>>9<<4)]=r,t.sigBytes=4*e.length,this._process(),this._hash},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}}),t.SHA1=i._createHelper(s),t.HmacSHA1=i._createHmacHelper(s),function(t){var e=l,r=e.lib,i=r.WordArray,n=r.Hasher,o=e.algo,s=[],c=[];!function(){function e(e){for(var r=t.sqrt(e),i=2;i<=r;i++)if(!(e%i))return!1;return!0}function r(t){return 4294967296*(t-(0|t))|0}for(var i=2,n=0;n<64;)e(i)&&(n<8&&(s[n]=r(t.pow(i,.5))),c[n]=r(t.pow(i,1/3)),n++),i++}();var a=[],h=o.SHA256=n.extend({_doReset:function(){this._hash=new i.init(s.slice(0))},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],h=r[4],l=r[5],f=r[6],u=r[7],d=0;d<64;d++){if(d<16)a[d]=0|t[e+d];else{var p=a[d-15],_=(p<<25|p>>>7)^(p<<14|p>>>18)^p>>>3,v=a[d-2],y=(v<<15|v>>>17)^(v<<13|v>>>19)^v>>>10;a[d]=_+a[d-7]+y+a[d-16]}var g=i&n^i&o^n&o,B=(i<<30|i>>>2)^(i<<19|i>>>13)^(i<<10|i>>>22),w=u+((h<<26|h>>>6)^(h<<21|h>>>11)^(h<<7|h>>>25))+(h&l^~h&f)+c[d]+a[d];u=f,f=l,l=h,h=s+w|0,s=o,o=n,n=i,i=w+(B+g)|0}r[0]=r[0]+i|0,r[1]=r[1]+n|0,r[2]=r[2]+o|0,r[3]=r[3]+s|0,r[4]=r[4]+h|0,r[5]=r[5]+l|0,r[6]=r[6]+f|0,r[7]=r[7]+u|0},_doFinalize:function(){var e=this._data,r=e.words,i=8*this._nDataBytes,n=8*e.sigBytes;return r[n>>>5]|=128<<24-n%32,r[14+(n+64>>>9<<4)]=t.floor(i/4294967296),r[15+(n+64>>>9<<4)]=i,e.sigBytes=4*r.length,this._process(),this._hash},clone:function(){var t=n.clone.call(this);return t._hash=this._hash.clone(),t}});e.SHA256=n._createHelper(h),e.HmacSHA256=n._createHmacHelper(h)}(Math),function(){var t=l,e=t.lib.WordArray,r=t.enc;r.Utf16=r.Utf16BE={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n<r;n+=2){var o=e[n>>>2]>>>16-n%4*8&65535;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var r=t.length,i=[],n=0;n<r;n++)i[n>>>1]|=t.charCodeAt(n)<<16-n%2*16;return e.create(i,2*r)}};function i(t){return t<<8&4278255360|t>>>8&16711935}r.Utf16LE={stringify:function(t){for(var e=t.words,r=t.sigBytes,n=[],o=0;o<r;o+=2){var s=i(e[o>>>2]>>>16-o%4*8&65535);n.push(String.fromCharCode(s))}return n.join("")},parse:function(t){for(var r=t.length,n=[],o=0;o<r;o++)n[o>>>1]|=i(t.charCodeAt(o)<<16-o%2*16);return e.create(n,2*r)}}}(),function(){if("function"==typeof ArrayBuffer){var t=l.lib.WordArray,e=t.init;(t.init=function(t){if(t instanceof ArrayBuffer&&(t=new Uint8Array(t)),(t instanceof Int8Array||"undefined"!=typeof Uint8ClampedArray&&t instanceof Uint8ClampedArray||t instanceof Int16Array||t instanceof Uint16Array||t instanceof Int32Array||t instanceof Uint32Array||t instanceof Float32Array||t instanceof Float64Array)&&(t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength)),t instanceof Uint8Array){for(var r=t.byteLength,i=[],n=0;n<r;n++)i[n>>>2]|=t[n]<<24-n%4*8;e.call(this,i,r)}else e.apply(this,arguments)}).prototype=t}}(),function(t){var e=l,r=e.lib,i=r.WordArray,n=r.Hasher,o=e.algo,s=i.create([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13]),c=i.create([5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]),a=i.create([11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6]),h=i.create([8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]),f=i.create([0,1518500249,1859775393,2400959708,2840853838]),u=i.create([1352829926,1548603684,1836072691,2053994217,0]),d=o.RIPEMD160=n.extend({_doReset:function(){this._hash=i.create([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(t,e){for(var r=0;r<16;r++){var i=e+r,n=t[i];t[i]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8)}var o,l,d,w,k,S,m,x,b,H,z,A=this._hash.words,C=f.words,D=u.words,E=s.words,R=c.words,M=a.words,F=h.words;S=o=A[0],m=l=A[1],x=d=A[2],b=w=A[3],H=k=A[4];for(r=0;r<80;r+=1)z=o+t[e+E[r]]|0,z+=r<16?p(l,d,w)+C[0]:r<32?_(l,d,w)+C[1]:r<48?v(l,d,w)+C[2]:r<64?y(l,d,w)+C[3]:g(l,d,w)+C[4],z=(z=B(z|=0,M[r]))+k|0,o=k,k=w,w=B(d,10),d=l,l=z,z=S+t[e+R[r]]|0,z+=r<16?g(m,x,b)+D[0]:r<32?y(m,x,b)+D[1]:r<48?v(m,x,b)+D[2]:r<64?_(m,x,b)+D[3]:p(m,x,b)+D[4],z=(z=B(z|=0,F[r]))+H|0,S=H,H=b,b=B(x,10),x=m,m=z;z=A[1]+d+b|0,A[1]=A[2]+w+H|0,A[2]=A[3]+k+S|0,A[3]=A[4]+o+m|0,A[4]=A[0]+l+x|0,A[0]=z},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;e[i>>>5]|=128<<24-i%32,e[14+(i+64>>>9<<4)]=16711935&(r<<8|r>>>24)|4278255360&(r<<24|r>>>8),t.sigBytes=4*(e.length+1),this._process();for(var n=this._hash,o=n.words,s=0;s<5;s++){var c=o[s];o[s]=16711935&(c<<8|c>>>24)|4278255360&(c<<24|c>>>8)}return n},clone:function(){var t=n.clone.call(this);return t._hash=this._hash.clone(),t}});function p(t,e,r){return t^e^r}function _(t,e,r){return t&e|~t&r}function v(t,e,r){return(t|~e)^r}function y(t,e,r){return t&r|e&~r}function g(t,e,r){return t^(e|~r)}function B(t,e){return t<<e|t>>>32-e}e.RIPEMD160=n._createHelper(d),e.HmacRIPEMD160=n._createHmacHelper(d)}(Math),function(){var t=l,e=t.lib.Base,r=t.enc.Utf8;t.algo.HMAC=e.extend({init:function(t,e){t=this._hasher=new t.init,"string"==typeof e&&(e=r.parse(e));var i=t.blockSize,n=4*i;e.sigBytes>n&&(e=t.finalize(e)),e.clamp();for(var o=this._oKey=e.clone(),s=this._iKey=e.clone(),c=o.words,a=s.words,h=0;h<i;h++)c[h]^=1549556828,a[h]^=909522486;o.sigBytes=s.sigBytes=n,this.reset()},reset:function(){var t=this._hasher;t.reset(),t.update(this._iKey)},update:function(t){return this._hasher.update(t),this},finalize:function(t){var e=this._hasher,r=e.finalize(t);return e.reset(),e.finalize(this._oKey.clone().concat(r))}})}(),function(){var t=l,e=t.lib,r=e.Base,i=e.WordArray,n=t.algo,o=n.SHA1,s=n.HMAC,c=n.PBKDF2=r.extend({cfg:r.extend({keySize:4,hasher:o,iterations:1}),init:function(t){this.cfg=this.cfg.extend(t)},compute:function(t,e){for(var r=this.cfg,n=s.create(r.hasher,t),o=i.create(),c=i.create([1]),a=o.words,h=c.words,l=r.keySize,f=r.iterations;a.length<l;){var u=n.update(e).finalize(c);n.reset();for(var d=u.words,p=d.length,_=u,v=1;v<f;v++){_=n.finalize(_),n.reset();for(var y=_.words,g=0;g<p;g++)d[g]^=y[g]}o.concat(u),h[0]++}return o.sigBytes=4*l,o}});t.PBKDF2=function(t,e,r){return c.create(r).compute(t,e)}}(),function(){var t=l,e=t.lib,r=e.Base,i=e.WordArray,n=t.algo,o=n.MD5,s=n.EvpKDF=r.extend({cfg:r.extend({keySize:4,hasher:o,iterations:1}),init:function(t){this.cfg=this.cfg.extend(t)},compute:function(t,e){for(var r,n=this.cfg,o=n.hasher.create(),s=i.create(),c=s.words,a=n.keySize,h=n.iterations;c.length<a;){r&&o.update(r),r=o.update(t).finalize(e),o.reset();for(var l=1;l<h;l++)r=o.finalize(r),o.reset();s.concat(r)}return s.sigBytes=4*a,s}});t.EvpKDF=function(t,e,r){return s.create(r).compute(t,e)}}(),function(){var t=l,e=t.lib.WordArray,r=t.algo,i=r.SHA256,n=r.SHA224=i.extend({_doReset:function(){this._hash=new e.init([3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428])},_doFinalize:function(){var t=i._doFinalize.call(this);return t.sigBytes-=4,t}});t.SHA224=i._createHelper(n),t.HmacSHA224=i._createHmacHelper(n)}(),function(t){var e=l,r=e.lib,i=r.Base,n=r.WordArray,o=e.x64={};o.Word=i.extend({init:function(t,e){this.high=t,this.low=e}}),o.WordArray=i.extend({init:function(t,e){t=this.words=t||[],this.sigBytes=null!=e?e:8*t.length},toX32:function(){for(var t=this.words,e=t.length,r=[],i=0;i<e;i++){var o=t[i];r.push(o.high),r.push(o.low)}return n.create(r,this.sigBytes)},clone:function(){for(var t=i.clone.call(this),e=t.words=this.words.slice(0),r=e.length,n=0;n<r;n++)e[n]=e[n].clone();return t}})}(),function(t){var e=l,r=e.lib,i=r.WordArray,n=r.Hasher,o=e.x64.Word,s=e.algo,c=[],a=[],h=[];!function(){for(var t=1,e=0,r=0;r<24;r++){c[t+5*e]=(r+1)*(r+2)/2%64;var i=(2*t+3*e)%5;t=e%5,e=i}for(t=0;t<5;t++)for(e=0;e<5;e++)a[t+5*e]=e+(2*t+3*e)%5*5;for(var n=1,s=0;s<24;s++){for(var l=0,f=0,u=0;u<7;u++){if(1&n){var d=(1<<u)-1;d<32?f^=1<<d:l^=1<<d-32}128&n?n=n<<1^113:n<<=1}h[s]=o.create(l,f)}}();var f=[];!function(){for(var t=0;t<25;t++)f[t]=o.create()}();var u=s.SHA3=n.extend({cfg:n.cfg.extend({outputLength:512}),_doReset:function(){for(var t=this._state=[],e=0;e<25;e++)t[e]=new o.init;this.blockSize=(1600-2*this.cfg.outputLength)/32},_doProcessBlock:function(t,e){for(var r=this._state,i=this.blockSize/2,n=0;n<i;n++){var o=t[e+2*n],s=t[e+2*n+1];o=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),s=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),(A=r[n]).high^=s,A.low^=o}for(var l=0;l<24;l++){for(var u=0;u<5;u++){for(var d=0,p=0,_=0;_<5;_++){d^=(A=r[u+5*_]).high,p^=A.low}var v=f[u];v.high=d,v.low=p}for(u=0;u<5;u++){var y=f[(u+4)%5],g=f[(u+1)%5],B=g.high,w=g.low;for(d=y.high^(B<<1|w>>>31),p=y.low^(w<<1|B>>>31),_=0;_<5;_++){(A=r[u+5*_]).high^=d,A.low^=p}}for(var k=1;k<25;k++){var S=(A=r[k]).high,m=A.low,x=c[k];x<32?(d=S<<x|m>>>32-x,p=m<<x|S>>>32-x):(d=m<<x-32|S>>>64-x,p=S<<x-32|m>>>64-x);var b=f[a[k]];b.high=d,b.low=p}var H=f[0],z=r[0];H.high=z.high,H.low=z.low;for(u=0;u<5;u++)for(_=0;_<5;_++){var A=r[k=u+5*_],C=f[k],D=f[(u+1)%5+5*_],E=f[(u+2)%5+5*_];A.high=C.high^~D.high&E.high,A.low=C.low^~D.low&E.low}A=r[0];var R=h[l];A.high^=R.high,A.low^=R.low}},_doFinalize:function(){var e=this._data,r=e.words,n=(this._nDataBytes,8*e.sigBytes),o=32*this.blockSize;r[n>>>5]|=1<<24-n%32,r[(t.ceil((n+1)/o)*o>>>5)-1]|=128,e.sigBytes=4*r.length,this._process();for(var s=this._state,c=this.cfg.outputLength/8,a=c/8,h=[],l=0;l<a;l++){var f=s[l],u=f.high,d=f.low;u=16711935&(u<<8|u>>>24)|4278255360&(u<<24|u>>>8),d=16711935&(d<<8|d>>>24)|4278255360&(d<<24|d>>>8),h.push(d),h.push(u)}return new i.init(h,c)},clone:function(){for(var t=n.clone.call(this),e=t._state=this._state.slice(0),r=0;r<25;r++)e[r]=e[r].clone();return t}});e.SHA3=n._createHelper(u),e.HmacSHA3=n._createHmacHelper(u)}(Math),function(){var t=l,e=t.lib.Hasher,r=t.x64,i=r.Word,n=r.WordArray,o=t.algo;function s(){return i.create.apply(i,arguments)}var c=[s(1116352408,3609767458),s(1899447441,602891725),s(3049323471,3964484399),s(3921009573,2173295548),s(961987163,4081628472),s(1508970993,3053834265),s(2453635748,2937671579),s(2870763221,3664609560),s(3624381080,2734883394),s(310598401,1164996542),s(607225278,1323610764),s(1426881987,3590304994),s(1925078388,4068182383),s(2162078206,991336113),s(2614888103,633803317),s(3248222580,3479774868),s(3835390401,2666613458),s(4022224774,944711139),s(264347078,2341262773),s(604807628,2007800933),s(770255983,1495990901),s(1249150122,1856431235),s(1555081692,3175218132),s(1996064986,2198950837),s(2554220882,3999719339),s(2821834349,766784016),s(2952996808,2566594879),s(3210313671,3203337956),s(3336571891,1034457026),s(3584528711,2466948901),s(113926993,3758326383),s(338241895,168717936),s(666307205,1188179964),s(773529912,1546045734),s(1294757372,1522805485),s(1396182291,2643833823),s(1695183700,2343527390),s(1986661051,1014477480),s(2177026350,1206759142),s(2456956037,344077627),s(2730485921,1290863460),s(2820302411,3158454273),s(3259730800,3505952657),s(3345764771,106217008),s(3516065817,3606008344),s(3600352804,1432725776),s(4094571909,1467031594),s(275423344,851169720),s(430227734,3100823752),s(506948616,1363258195),s(659060556,3750685593),s(883997877,3785050280),s(958139571,3318307427),s(1322822218,3812723403),s(1537002063,2003034995),s(1747873779,3602036899),s(1955562222,1575990012),s(2024104815,1125592928),s(2227730452,2716904306),s(2361852424,442776044),s(2428436474,593698344),s(2756734187,3733110249),s(3204031479,2999351573),s(3329325298,3815920427),s(3391569614,3928383900),s(3515267271,566280711),s(3940187606,3454069534),s(4118630271,4000239992),s(116418474,1914138554),s(174292421,2731055270),s(289380356,3203993006),s(460393269,320620315),s(685471733,587496836),s(852142971,1086792851),s(1017036298,365543100),s(1126000580,2618297676),s(1288033470,3409855158),s(1501505948,4234509866),s(1607167915,987167468),s(1816402316,1246189591)],a=[];!function(){for(var t=0;t<80;t++)a[t]=s()}();var h=o.SHA512=e.extend({_doReset:function(){this._hash=new n.init([new i.init(1779033703,4089235720),new i.init(3144134277,2227873595),new i.init(1013904242,4271175723),new i.init(2773480762,1595750129),new i.init(1359893119,2917565137),new i.init(2600822924,725511199),new i.init(528734635,4215389547),new i.init(1541459225,327033209)])},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],h=r[4],l=r[5],f=r[6],u=r[7],d=i.high,p=i.low,_=n.high,v=n.low,y=o.high,g=o.low,B=s.high,w=s.low,k=h.high,S=h.low,m=l.high,x=l.low,b=f.high,H=f.low,z=u.high,A=u.low,C=d,D=p,E=_,R=v,M=y,F=g,P=B,W=w,O=k,I=S,U=m,K=x,X=b,L=H,j=z,N=A,T=0;T<80;T++){var q,Z,V=a[T];if(T<16)Z=V.high=0|t[e+2*T],q=V.low=0|t[e+2*T+1];else{var G=a[T-15],J=G.high,$=G.low,Q=(J>>>1|$<<31)^(J>>>8|$<<24)^J>>>7,Y=($>>>1|J<<31)^($>>>8|J<<24)^($>>>7|J<<25),tt=a[T-2],et=tt.high,rt=tt.low,it=(et>>>19|rt<<13)^(et<<3|rt>>>29)^et>>>6,nt=(rt>>>19|et<<13)^(rt<<3|et>>>29)^(rt>>>6|et<<26),ot=a[T-7],st=ot.high,ct=ot.low,at=a[T-16],ht=at.high,lt=at.low;Z=(Z=(Z=Q+st+((q=Y+ct)>>>0<Y>>>0?1:0))+it+((q+=nt)>>>0<nt>>>0?1:0))+ht+((q+=lt)>>>0<lt>>>0?1:0),V.high=Z,V.low=q}var ft,ut=O&U^~O&X,dt=I&K^~I&L,pt=C&E^C&M^E&M,_t=D&R^D&F^R&F,vt=(C>>>28|D<<4)^(C<<30|D>>>2)^(C<<25|D>>>7),yt=(D>>>28|C<<4)^(D<<30|C>>>2)^(D<<25|C>>>7),gt=(O>>>14|I<<18)^(O>>>18|I<<14)^(O<<23|I>>>9),Bt=(I>>>14|O<<18)^(I>>>18|O<<14)^(I<<23|O>>>9),wt=c[T],kt=wt.high,St=wt.low,mt=j+gt+((ft=N+Bt)>>>0<N>>>0?1:0),xt=yt+_t;j=X,N=L,X=U,L=K,U=O,K=I,O=P+(mt=(mt=(mt=mt+ut+((ft=ft+dt)>>>0<dt>>>0?1:0))+kt+((ft=ft+St)>>>0<St>>>0?1:0))+Z+((ft=ft+q)>>>0<q>>>0?1:0))+((I=W+ft|0)>>>0<W>>>0?1:0)|0,P=M,W=F,M=E,F=R,E=C,R=D,C=mt+(vt+pt+(xt>>>0<yt>>>0?1:0))+((D=ft+xt|0)>>>0<ft>>>0?1:0)|0}p=i.low=p+D,i.high=d+C+(p>>>0<D>>>0?1:0),v=n.low=v+R,n.high=_+E+(v>>>0<R>>>0?1:0),g=o.low=g+F,o.high=y+M+(g>>>0<F>>>0?1:0),w=s.low=w+W,s.high=B+P+(w>>>0<W>>>0?1:0),S=h.low=S+I,h.high=k+O+(S>>>0<I>>>0?1:0),x=l.low=x+K,l.high=m+U+(x>>>0<K>>>0?1:0),H=f.low=H+L,f.high=b+X+(H>>>0<L>>>0?1:0),A=u.low=A+N,u.high=z+j+(A>>>0<N>>>0?1:0)},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[30+(i+128>>>10<<5)]=Math.floor(r/4294967296),e[31+(i+128>>>10<<5)]=r,t.sigBytes=4*e.length,this._process(),this._hash.toX32()},clone:function(){var t=e.clone.call(this);return t._hash=this._hash.clone(),t},blockSize:32});t.SHA512=e._createHelper(h),t.HmacSHA512=e._createHmacHelper(h)}(),function(){var t=l,e=t.x64,r=e.Word,i=e.WordArray,n=t.algo,o=n.SHA512,s=n.SHA384=o.extend({_doReset:function(){this._hash=new i.init([new r.init(3418070365,3238371032),new r.init(1654270250,914150663),new r.init(2438529370,812702999),new r.init(355462360,4144912697),new r.init(1731405415,4290775857),new r.init(2394180231,1750603025),new r.init(3675008525,1694076839),new r.init(1203062813,3204075428)])},_doFinalize:function(){var t=o._doFinalize.call(this);return t.sigBytes-=16,t}});t.SHA384=o._createHelper(s),t.HmacSHA384=o._createHmacHelper(s)}(),l.lib.Cipher||function(t){var e=l,r=e.lib,i=r.Base,n=r.WordArray,o=r.BufferedBlockAlgorithm,s=e.enc,c=(s.Utf8,s.Base64),a=e.algo.EvpKDF,h=r.Cipher=o.extend({cfg:i.extend(),createEncryptor:function(t,e){return this.create(this._ENC_XFORM_MODE,t,e)},createDecryptor:function(t,e){return this.create(this._DEC_XFORM_MODE,t,e)},init:function(t,e,r){this.cfg=this.cfg.extend(r),this._xformMode=t,this._key=e,this.reset()},reset:function(){o.reset.call(this),this._doReset()},process:function(t){return this._append(t),this._process()},finalize:function(t){return t&&this._append(t),this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(){function t(t){return"string"==typeof t?B:y}return function(e){return{encrypt:function(r,i,n){return t(i).encrypt(e,r,i,n)},decrypt:function(r,i,n){return t(i).decrypt(e,r,i,n)}}}}()}),f=(r.StreamCipher=h.extend({_doFinalize:function(){return this._process(!0)},blockSize:1}),e.mode={}),u=r.BlockCipherMode=i.extend({createEncryptor:function(t,e){return this.Encryptor.create(t,e)},createDecryptor:function(t,e){return this.Decryptor.create(t,e)},init:function(t,e){this._cipher=t,this._iv=e}}),d=f.CBC=function(){var e=u.extend();function r(e,r,i){var n,o=this._iv;o?(n=o,this._iv=t):n=this._prevBlock;for(var s=0;s<i;s++)e[r+s]^=n[s]}return e.Encryptor=e.extend({processBlock:function(t,e){var i=this._cipher,n=i.blockSize;r.call(this,t,e,n),i.encryptBlock(t,e),this._prevBlock=t.slice(e,e+n)}}),e.Decryptor=e.extend({processBlock:function(t,e){var i=this._cipher,n=i.blockSize,o=t.slice(e,e+n);i.decryptBlock(t,e),r.call(this,t,e,n),this._prevBlock=o}}),e}(),p=(e.pad={}).Pkcs7={pad:function(t,e){for(var r=4*e,i=r-t.sigBytes%r,o=i<<24|i<<16|i<<8|i,s=[],c=0;c<i;c+=4)s.push(o);var a=n.create(s,i);t.concat(a)},unpad:function(t){var e=255&t.words[t.sigBytes-1>>>2];t.sigBytes-=e}},_=(r.BlockCipher=h.extend({cfg:h.cfg.extend({mode:d,padding:p}),reset:function(){var t;h.reset.call(this);var e=this.cfg,r=e.iv,i=e.mode;this._xformMode==this._ENC_XFORM_MODE?t=i.createEncryptor:(t=i.createDecryptor,this._minBufferSize=1),this._mode&&this._mode.__creator==t?this._mode.init(this,r&&r.words):(this._mode=t.call(i,this,r&&r.words),this._mode.__creator=t)},_doProcessBlock:function(t,e){this._mode.processBlock(t,e)},_doFinalize:function(){var t,e=this.cfg.padding;return this._xformMode==this._ENC_XFORM_MODE?(e.pad(this._data,this.blockSize),t=this._process(!0)):(t=this._process(!0),e.unpad(t)),t},blockSize:4}),r.CipherParams=i.extend({init:function(t){this.mixIn(t)},toString:function(t){return(t||this.formatter).stringify(this)}})),v=(e.format={}).OpenSSL={stringify:function(t){var e=t.ciphertext,r=t.salt;return(r?n.create([1398893684,1701076831]).concat(r).concat(e):e).toString(c)},parse:function(t){var e,r=c.parse(t),i=r.words;return 1398893684==i[0]&&1701076831==i[1]&&(e=n.create(i.slice(2,4)),i.splice(0,4),r.sigBytes-=16),_.create({ciphertext:r,salt:e})}},y=r.SerializableCipher=i.extend({cfg:i.extend({format:v}),encrypt:function(t,e,r,i){i=this.cfg.extend(i);var n=t.createEncryptor(r,i),o=n.finalize(e),s=n.cfg;return _.create({ciphertext:o,key:r,iv:s.iv,algorithm:t,mode:s.mode,padding:s.padding,blockSize:t.blockSize,formatter:i.format})},decrypt:function(t,e,r,i){return i=this.cfg.extend(i),e=this._parse(e,i.format),t.createDecryptor(r,i).finalize(e.ciphertext)},_parse:function(t,e){return"string"==typeof t?e.parse(t,this):t}}),g=(e.kdf={}).OpenSSL={execute:function(t,e,r,i){i||(i=n.random(8));var o=a.create({keySize:e+r}).compute(t,i),s=n.create(o.words.slice(e),4*r);return o.sigBytes=4*e,_.create({key:o,iv:s,salt:i})}},B=r.PasswordBasedCipher=y.extend({cfg:y.cfg.extend({kdf:g}),encrypt:function(t,e,r,i){var n=(i=this.cfg.extend(i)).kdf.execute(r,t.keySize,t.ivSize);i.iv=n.iv;var o=y.encrypt.call(this,t,e,n.key,i);return o.mixIn(n),o},decrypt:function(t,e,r,i){i=this.cfg.extend(i),e=this._parse(e,i.format);var n=i.kdf.execute(r,t.keySize,t.ivSize,e.salt);return i.iv=n.iv,y.decrypt.call(this,t,e,n.key,i)}})}(),l.mode.CFB=function(){var t=l.lib.BlockCipherMode.extend();function e(t,e,r,i){var n,o=this._iv;o?(n=o.slice(0),this._iv=void 0):n=this._prevBlock,i.encryptBlock(n,0);for(var s=0;s<r;s++)t[e+s]^=n[s]}return t.Encryptor=t.extend({processBlock:function(t,r){var i=this._cipher,n=i.blockSize;e.call(this,t,r,n,i),this._prevBlock=t.slice(r,r+n)}}),t.Decryptor=t.extend({processBlock:function(t,r){var i=this._cipher,n=i.blockSize,o=t.slice(r,r+n);e.call(this,t,r,n,i),this._prevBlock=o}}),t}(),l.mode.ECB=((c=l.lib.BlockCipherMode.extend()).Encryptor=c.extend({processBlock:function(t,e){this._cipher.encryptBlock(t,e)}}),c.Decryptor=c.extend({processBlock:function(t,e){this._cipher.decryptBlock(t,e)}}),c),l.pad.AnsiX923={pad:function(t,e){var r=t.sigBytes,i=4*e,n=i-r%i,o=r+n-1;t.clamp(),t.words[o>>>2]|=n<<24-o%4*8,t.sigBytes+=n},unpad:function(t){var e=255&t.words[t.sigBytes-1>>>2];t.sigBytes-=e}},l.pad.Iso10126={pad:function(t,e){var r=4*e,i=r-t.sigBytes%r;t.concat(l.lib.WordArray.random(i-1)).concat(l.lib.WordArray.create([i<<24],1))},unpad:function(t){var e=255&t.words[t.sigBytes-1>>>2];t.sigBytes-=e}},l.pad.Iso97971={pad:function(t,e){t.concat(l.lib.WordArray.create([2147483648],1)),l.pad.ZeroPadding.pad(t,e)},unpad:function(t){l.pad.ZeroPadding.unpad(t),t.sigBytes--}},l.mode.OFB=(a=l.lib.BlockCipherMode.extend(),h=a.Encryptor=a.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=this._iv,o=this._keystream;n&&(o=this._keystream=n.slice(0),this._iv=void 0),r.encryptBlock(o,0);for(var s=0;s<i;s++)t[e+s]^=o[s]}}),a.Decryptor=h,a),l.pad.NoPadding={pad:function(){},unpad:function(){}},function(t){var e=l,r=e.lib.CipherParams,i=e.enc.Hex;e.format.Hex={stringify:function(t){return t.ciphertext.toString(i)},parse:function(t){var e=i.parse(t);return r.create({ciphertext:e})}}}(),function(){var t=l,e=t.lib.BlockCipher,r=t.algo,i=[],n=[],o=[],s=[],c=[],a=[],h=[],f=[],u=[],d=[];!function(){for(var t=[],e=0;e<256;e++)t[e]=e<128?e<<1:e<<1^283;var r=0,l=0;for(e=0;e<256;e++){var p=l^l<<1^l<<2^l<<3^l<<4;p=p>>>8^255&p^99,i[r]=p,n[p]=r;var _=t[r],v=t[_],y=t[v],g=257*t[p]^16843008*p;o[r]=g<<24|g>>>8,s[r]=g<<16|g>>>16,c[r]=g<<8|g>>>24,a[r]=g;g=16843009*y^65537*v^257*_^16843008*r;h[p]=g<<24|g>>>8,f[p]=g<<16|g>>>16,u[p]=g<<8|g>>>24,d[p]=g,r?(r=_^t[t[t[y^_]]],l^=t[t[l]]):r=l=1}}();var p=[0,1,2,4,8,16,32,64,128,27,54],_=r.AES=e.extend({_doReset:function(){if(!this._nRounds||this._keyPriorReset!==this._key){for(var t=this._keyPriorReset=this._key,e=t.words,r=t.sigBytes/4,n=4*((this._nRounds=r+6)+1),o=this._keySchedule=[],s=0;s<n;s++)s<r?o[s]=e[s]:(l=o[s-1],s%r?r>6&&s%r==4&&(l=i[l>>>24]<<24|i[l>>>16&255]<<16|i[l>>>8&255]<<8|i[255&l]):(l=i[(l=l<<8|l>>>24)>>>24]<<24|i[l>>>16&255]<<16|i[l>>>8&255]<<8|i[255&l],l^=p[s/r|0]<<24),o[s]=o[s-r]^l);for(var c=this._invKeySchedule=[],a=0;a<n;a++){s=n-a;if(a%4)var l=o[s];else l=o[s-4];c[a]=a<4||s<=4?l:h[i[l>>>24]]^f[i[l>>>16&255]]^u[i[l>>>8&255]]^d[i[255&l]]}}},encryptBlock:function(t,e){this._doCryptBlock(t,e,this._keySchedule,o,s,c,a,i)},decryptBlock:function(t,e){var r=t[e+1];t[e+1]=t[e+3],t[e+3]=r,this._doCryptBlock(t,e,this._invKeySchedule,h,f,u,d,n);r=t[e+1];t[e+1]=t[e+3],t[e+3]=r},_doCryptBlock:function(t,e,r,i,n,o,s,c){for(var a=this._nRounds,h=t[e]^r[0],l=t[e+1]^r[1],f=t[e+2]^r[2],u=t[e+3]^r[3],d=4,p=1;p<a;p++){var _=i[h>>>24]^n[l>>>16&255]^o[f>>>8&255]^s[255&u]^r[d++],v=i[l>>>24]^n[f>>>16&255]^o[u>>>8&255]^s[255&h]^r[d++],y=i[f>>>24]^n[u>>>16&255]^o[h>>>8&255]^s[255&l]^r[d++],g=i[u>>>24]^n[h>>>16&255]^o[l>>>8&255]^s[255&f]^r[d++];h=_,l=v,f=y,u=g}_=(c[h>>>24]<<24|c[l>>>16&255]<<16|c[f>>>8&255]<<8|c[255&u])^r[d++],v=(c[l>>>24]<<24|c[f>>>16&255]<<16|c[u>>>8&255]<<8|c[255&h])^r[d++],y=(c[f>>>24]<<24|c[u>>>16&255]<<16|c[h>>>8&255]<<8|c[255&l])^r[d++],g=(c[u>>>24]<<24|c[h>>>16&255]<<16|c[l>>>8&255]<<8|c[255&f])^r[d++];t[e]=_,t[e+1]=v,t[e+2]=y,t[e+3]=g},keySize:8});t.AES=e._createHelper(_)}(),function(){var t=l,e=t.lib,r=e.WordArray,i=e.BlockCipher,n=t.algo,o=[57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,27,19,11,3,60,52,44,36,63,55,47,39,31,23,15,7,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,28,20,12,4],s=[14,17,11,24,1,5,3,28,15,6,21,10,23,19,12,4,26,8,16,7,27,20,13,2,41,52,31,37,47,55,30,40,51,45,33,48,44,49,39,56,34,53,46,42,50,36,29,32],c=[1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28],a=[{0:8421888,268435456:32768,536870912:8421378,805306368:2,1073741824:512,1342177280:8421890,1610612736:8389122,1879048192:8388608,2147483648:514,2415919104:8389120,2684354560:33280,2952790016:8421376,3221225472:32770,3489660928:8388610,3758096384:0,4026531840:33282,134217728:0,402653184:8421890,671088640:33282,939524096:32768,1207959552:8421888,1476395008:512,1744830464:8421378,2013265920:2,2281701376:8389120,2550136832:33280,2818572288:8421376,3087007744:8389122,3355443200:8388610,3623878656:32770,3892314112:514,4160749568:8388608,1:32768,268435457:2,536870913:8421888,805306369:8388608,1073741825:8421378,1342177281:33280,1610612737:512,1879048193:8389122,2147483649:8421890,2415919105:8421376,2684354561:8388610,2952790017:33282,3221225473:514,3489660929:8389120,3758096385:32770,4026531841:0,134217729:8421890,402653185:8421376,671088641:8388608,939524097:512,1207959553:32768,1476395009:8388610,1744830465:2,2013265921:33282,2281701377:32770,2550136833:8389122,2818572289:514,3087007745:8421888,3355443201:8389120,3623878657:0,3892314113:33280,4160749569:8421378},{0:1074282512,16777216:16384,33554432:524288,50331648:1074266128,67108864:1073741840,83886080:1074282496,100663296:1073758208,117440512:16,134217728:540672,150994944:1073758224,167772160:1073741824,184549376:540688,201326592:524304,218103808:0,234881024:16400,251658240:1074266112,8388608:1073758208,25165824:540688,41943040:16,58720256:1073758224,75497472:1074282512,92274688:1073741824,109051904:524288,125829120:1074266128,142606336:524304,159383552:0,176160768:16384,192937984:1074266112,209715200:1073741840,226492416:540672,243269632:1074282496,260046848:16400,268435456:0,285212672:1074266128,301989888:1073758224,318767104:1074282496,335544320:1074266112,352321536:16,369098752:540688,385875968:16384,402653184:16400,419430400:524288,436207616:524304,452984832:1073741840,469762048:540672,486539264:1073758208,503316480:1073741824,520093696:1074282512,276824064:540688,293601280:524288,310378496:1074266112,327155712:16384,343932928:1073758208,360710144:1074282512,377487360:16,394264576:1073741824,411041792:1074282496,427819008:1073741840,444596224:1073758224,461373440:524304,478150656:0,494927872:16400,511705088:1074266128,528482304:540672},{0:260,1048576:0,2097152:67109120,3145728:65796,4194304:65540,5242880:67108868,6291456:67174660,7340032:67174400,8388608:67108864,9437184:67174656,10485760:65792,11534336:67174404,12582912:67109124,13631488:65536,14680064:4,15728640:256,524288:67174656,1572864:67174404,2621440:0,3670016:67109120,4718592:67108868,5767168:65536,6815744:65540,7864320:260,8912896:4,9961472:256,11010048:67174400,12058624:65796,13107200:65792,14155776:67109124,15204352:67174660,16252928:67108864,16777216:67174656,17825792:65540,18874368:65536,19922944:67109120,20971520:256,22020096:67174660,23068672:67108868,24117248:0,25165824:67109124,26214400:67108864,27262976:4,28311552:65792,29360128:67174400,30408704:260,31457280:65796,32505856:67174404,17301504:67108864,18350080:260,19398656:67174656,20447232:0,21495808:65540,22544384:67109120,23592960:256,24641536:67174404,25690112:65536,26738688:67174660,27787264:65796,28835840:67108868,29884416:67109124,30932992:67174400,31981568:4,33030144:65792},{0:2151682048,65536:2147487808,131072:4198464,196608:2151677952,262144:0,327680:4198400,393216:2147483712,458752:4194368,524288:2147483648,589824:4194304,655360:64,720896:2147487744,786432:2151678016,851968:4160,917504:4096,983040:2151682112,32768:2147487808,98304:64,163840:2151678016,229376:2147487744,294912:4198400,360448:2151682112,425984:0,491520:2151677952,557056:4096,622592:2151682048,688128:4194304,753664:4160,819200:2147483648,884736:4194368,950272:4198464,1015808:2147483712,1048576:4194368,1114112:4198400,1179648:2147483712,1245184:0,1310720:4160,1376256:2151678016,1441792:2151682048,1507328:2147487808,1572864:2151682112,1638400:2147483648,1703936:2151677952,1769472:4198464,1835008:2147487744,1900544:4194304,1966080:64,2031616:4096,1081344:2151677952,1146880:2151682112,1212416:0,1277952:4198400,1343488:4194368,1409024:2147483648,1474560:2147487808,1540096:64,1605632:2147483712,1671168:4096,1736704:2147487744,1802240:2151678016,1867776:4160,1933312:2151682048,1998848:4194304,2064384:4198464},{0:128,4096:17039360,8192:262144,12288:536870912,16384:537133184,20480:16777344,24576:553648256,28672:262272,32768:16777216,36864:537133056,40960:536871040,45056:553910400,49152:553910272,53248:0,57344:17039488,61440:553648128,2048:17039488,6144:553648256,10240:128,14336:17039360,18432:262144,22528:537133184,26624:553910272,30720:536870912,34816:537133056,38912:0,43008:553910400,47104:16777344,51200:536871040,55296:553648128,59392:16777216,63488:262272,65536:262144,69632:128,73728:536870912,77824:553648256,81920:16777344,86016:553910272,90112:537133184,94208:16777216,98304:553910400,102400:553648128,106496:17039360,110592:537133056,114688:262272,118784:536871040,122880:0,126976:17039488,67584:553648256,71680:16777216,75776:17039360,79872:537133184,83968:536870912,88064:17039488,92160:128,96256:553910272,100352:262272,104448:553910400,108544:0,112640:553648128,116736:16777344,120832:262144,124928:537133056,129024:536871040},{0:268435464,256:8192,512:270532608,768:270540808,1024:268443648,1280:2097152,1536:2097160,1792:268435456,2048:0,2304:268443656,2560:2105344,2816:8,3072:270532616,3328:2105352,3584:8200,3840:270540800,128:270532608,384:270540808,640:8,896:2097152,1152:2105352,1408:268435464,1664:268443648,1920:8200,2176:2097160,2432:8192,2688:268443656,2944:270532616,3200:0,3456:270540800,3712:2105344,3968:268435456,4096:268443648,4352:270532616,4608:270540808,4864:8200,5120:2097152,5376:268435456,5632:268435464,5888:2105344,6144:2105352,6400:0,6656:8,6912:270532608,7168:8192,7424:268443656,7680:270540800,7936:2097160,4224:8,4480:2105344,4736:2097152,4992:268435464,5248:268443648,5504:8200,5760:270540808,6016:270532608,6272:270540800,6528:270532616,6784:8192,7040:2105352,7296:2097160,7552:0,7808:268435456,8064:268443656},{0:1048576,16:33555457,32:1024,48:1049601,64:34604033,80:0,96:1,112:34603009,128:33555456,144:1048577,160:33554433,176:34604032,192:34603008,208:1025,224:1049600,240:33554432,8:34603009,24:0,40:33555457,56:34604032,72:1048576,88:33554433,104:33554432,120:1025,136:1049601,152:33555456,168:34603008,184:1048577,200:1024,216:34604033,232:1,248:1049600,256:33554432,272:1048576,288:33555457,304:34603009,320:1048577,336:33555456,352:34604032,368:1049601,384:1025,400:34604033,416:1049600,432:1,448:0,464:34603008,480:33554433,496:1024,264:1049600,280:33555457,296:34603009,312:1,328:33554432,344:1048576,360:1025,376:34604032,392:33554433,408:34603008,424:0,440:34604033,456:1049601,472:1024,488:33555456,504:1048577},{0:134219808,1:131072,2:134217728,3:32,4:131104,5:134350880,6:134350848,7:2048,8:134348800,9:134219776,10:133120,11:134348832,12:2080,13:0,14:134217760,15:133152,2147483648:2048,2147483649:134350880,2147483650:134219808,2147483651:134217728,2147483652:134348800,2147483653:133120,2147483654:133152,2147483655:32,2147483656:134217760,2147483657:2080,2147483658:131104,2147483659:134350848,2147483660:0,2147483661:134348832,2147483662:134219776,2147483663:131072,16:133152,17:134350848,18:32,19:2048,20:134219776,21:134217760,22:134348832,23:131072,24:0,25:131104,26:134348800,27:134219808,28:134350880,29:133120,30:2080,31:134217728,2147483664:131072,2147483665:2048,2147483666:134348832,2147483667:133152,2147483668:32,2147483669:134348800,2147483670:134217728,2147483671:134219808,2147483672:134350880,2147483673:134217760,2147483674:134219776,2147483675:0,2147483676:133120,2147483677:2080,2147483678:131104,2147483679:134350848}],h=[4160749569,528482304,33030144,2064384,129024,8064,504,2147483679],f=n.DES=i.extend({_doReset:function(){for(var t=this._key.words,e=[],r=0;r<56;r++){var i=o[r]-1;e[r]=t[i>>>5]>>>31-i%32&1}for(var n=this._subKeys=[],a=0;a<16;a++){var h=n[a]=[],l=c[a];for(r=0;r<24;r++)h[r/6|0]|=e[(s[r]-1+l)%28]<<31-r%6,h[4+(r/6|0)]|=e[28+(s[r+24]-1+l)%28]<<31-r%6;h[0]=h[0]<<1|h[0]>>>31;for(r=1;r<7;r++)h[r]=h[r]>>>4*(r-1)+3;h[7]=h[7]<<5|h[7]>>>27}var f=this._invSubKeys=[];for(r=0;r<16;r++)f[r]=n[15-r]},encryptBlock:function(t,e){this._doCryptBlock(t,e,this._subKeys)},decryptBlock:function(t,e){this._doCryptBlock(t,e,this._invSubKeys)},_doCryptBlock:function(t,e,r){this._lBlock=t[e],this._rBlock=t[e+1],u.call(this,4,252645135),u.call(this,16,65535),d.call(this,2,858993459),d.call(this,8,16711935),u.call(this,1,1431655765);for(var i=0;i<16;i++){for(var n=r[i],o=this._lBlock,s=this._rBlock,c=0,l=0;l<8;l++)c|=a[l][((s^n[l])&h[l])>>>0];this._lBlock=s,this._rBlock=o^c}var f=this._lBlock;this._lBlock=this._rBlock,this._rBlock=f,u.call(this,1,1431655765),d.call(this,8,16711935),d.call(this,2,858993459),u.call(this,16,65535),u.call(this,4,252645135),t[e]=this._lBlock,t[e+1]=this._rBlock},keySize:2,ivSize:2,blockSize:2});function u(t,e){var r=(this._lBlock>>>t^this._rBlock)&e;this._rBlock^=r,this._lBlock^=r<<t}function d(t,e){var r=(this._rBlock>>>t^this._lBlock)&e;this._lBlock^=r,this._rBlock^=r<<t}t.DES=i._createHelper(f);var p=n.TripleDES=i.extend({_doReset:function(){var t=this._key.words;if(2!==t.length&&4!==t.length&&t.length<6)throw new Error("Invalid key length - 3DES requires the key length to be 64, 128, 192 or >192.");var e=t.slice(0,2),i=t.length<4?t.slice(0,2):t.slice(2,4),n=t.length<6?t.slice(0,2):t.slice(4,6);this._des1=f.createEncryptor(r.create(e)),this._des2=f.createEncryptor(r.create(i)),this._des3=f.createEncryptor(r.create(n))},encryptBlock:function(t,e){this._des1.encryptBlock(t,e),this._des2.decryptBlock(t,e),this._des3.encryptBlock(t,e)},decryptBlock:function(t,e){this._des3.decryptBlock(t,e),this._des2.encryptBlock(t,e),this._des1.decryptBlock(t,e)},keySize:6,ivSize:2,blockSize:2});t.TripleDES=i._createHelper(p)}(),function(){var t=l,e=t.lib.StreamCipher,r=t.algo,i=r.RC4=e.extend({_doReset:function(){for(var t=this._key,e=t.words,r=t.sigBytes,i=this._S=[],n=0;n<256;n++)i[n]=n;n=0;for(var o=0;n<256;n++){var s=n%r,c=e[s>>>2]>>>24-s%4*8&255;o=(o+i[n]+c)%256;var a=i[n];i[n]=i[o],i[o]=a}this._i=this._j=0},_doProcessBlock:function(t,e){t[e]^=n.call(this)},keySize:8,ivSize:0});function n(){for(var t=this._S,e=this._i,r=this._j,i=0,n=0;n<4;n++){r=(r+t[e=(e+1)%256])%256;var o=t[e];t[e]=t[r],t[r]=o,i|=t[(t[e]+t[r])%256]<<24-8*n}return this._i=e,this._j=r,i}t.RC4=e._createHelper(i);var o=r.RC4Drop=i.extend({cfg:i.cfg.extend({drop:192}),_doReset:function(){i._doReset.call(this);for(var t=this.cfg.drop;t>0;t--)n.call(this)}});t.RC4Drop=e._createHelper(o)}(),l.mode.CTRGladman=function(){var t=l.lib.BlockCipherMode.extend();function e(t){if(255==(t>>24&255)){var e=t>>16&255,r=t>>8&255,i=255&t;255===e?(e=0,255===r?(r=0,255===i?i=0:++i):++r):++e,t=0,t+=e<<16,t+=r<<8,t+=i}else t+=1<<24;return t}var r=t.Encryptor=t.extend({processBlock:function(t,r){var i=this._cipher,n=i.blockSize,o=this._iv,s=this._counter;o&&(s=this._counter=o.slice(0),this._iv=void 0),function(t){0===(t[0]=e(t[0]))&&(t[1]=e(t[1]))}(s);var c=s.slice(0);i.encryptBlock(c,0);for(var a=0;a<n;a++)t[r+a]^=c[a]}});return t.Decryptor=r,t}(),function(){var t=l,e=t.lib.StreamCipher,r=t.algo,i=[],n=[],o=[],s=r.Rabbit=e.extend({_doReset:function(){for(var t=this._key.words,e=this.cfg.iv,r=0;r<4;r++)t[r]=16711935&(t[r]<<8|t[r]>>>24)|4278255360&(t[r]<<24|t[r]>>>8);var i=this._X=[t[0],t[3]<<16|t[2]>>>16,t[1],t[0]<<16|t[3]>>>16,t[2],t[1]<<16|t[0]>>>16,t[3],t[2]<<16|t[1]>>>16],n=this._C=[t[2]<<16|t[2]>>>16,4294901760&t[0]|65535&t[1],t[3]<<16|t[3]>>>16,4294901760&t[1]|65535&t[2],t[0]<<16|t[0]>>>16,4294901760&t[2]|65535&t[3],t[1]<<16|t[1]>>>16,4294901760&t[3]|65535&t[0]];this._b=0;for(r=0;r<4;r++)c.call(this);for(r=0;r<8;r++)n[r]^=i[r+4&7];if(e){var o=e.words,s=o[0],a=o[1],h=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),l=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),f=h>>>16|4294901760&l,u=l<<16|65535&h;n[0]^=h,n[1]^=f,n[2]^=l,n[3]^=u,n[4]^=h,n[5]^=f,n[6]^=l,n[7]^=u;for(r=0;r<4;r++)c.call(this)}},_doProcessBlock:function(t,e){var r=this._X;c.call(this),i[0]=r[0]^r[5]>>>16^r[3]<<16,i[1]=r[2]^r[7]>>>16^r[5]<<16,i[2]=r[4]^r[1]>>>16^r[7]<<16,i[3]=r[6]^r[3]>>>16^r[1]<<16;for(var n=0;n<4;n++)i[n]=16711935&(i[n]<<8|i[n]>>>24)|4278255360&(i[n]<<24|i[n]>>>8),t[e+n]^=i[n]},blockSize:4,ivSize:2});function c(){for(var t=this._X,e=this._C,r=0;r<8;r++)n[r]=e[r];e[0]=e[0]+1295307597+this._b|0,e[1]=e[1]+3545052371+(e[0]>>>0<n[0]>>>0?1:0)|0,e[2]=e[2]+886263092+(e[1]>>>0<n[1]>>>0?1:0)|0,e[3]=e[3]+1295307597+(e[2]>>>0<n[2]>>>0?1:0)|0,e[4]=e[4]+3545052371+(e[3]>>>0<n[3]>>>0?1:0)|0,e[5]=e[5]+886263092+(e[4]>>>0<n[4]>>>0?1:0)|0,e[6]=e[6]+1295307597+(e[5]>>>0<n[5]>>>0?1:0)|0,e[7]=e[7]+3545052371+(e[6]>>>0<n[6]>>>0?1:0)|0,this._b=e[7]>>>0<n[7]>>>0?1:0;for(r=0;r<8;r++){var i=t[r]+e[r],s=65535&i,c=i>>>16,a=((s*s>>>17)+s*c>>>15)+c*c,h=((4294901760&i)*i|0)+((65535&i)*i|0);o[r]=a^h}t[0]=o[0]+(o[7]<<16|o[7]>>>16)+(o[6]<<16|o[6]>>>16)|0,t[1]=o[1]+(o[0]<<8|o[0]>>>24)+o[7]|0,t[2]=o[2]+(o[1]<<16|o[1]>>>16)+(o[0]<<16|o[0]>>>16)|0,t[3]=o[3]+(o[2]<<8|o[2]>>>24)+o[1]|0,t[4]=o[4]+(o[3]<<16|o[3]>>>16)+(o[2]<<16|o[2]>>>16)|0,t[5]=o[5]+(o[4]<<8|o[4]>>>24)+o[3]|0,t[6]=o[6]+(o[5]<<16|o[5]>>>16)+(o[4]<<16|o[4]>>>16)|0,t[7]=o[7]+(o[6]<<8|o[6]>>>24)+o[5]|0}t.Rabbit=e._createHelper(s)}(),l.mode.CTR=function(){var t=l.lib.BlockCipherMode.extend(),e=t.Encryptor=t.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=this._iv,o=this._counter;n&&(o=this._counter=n.slice(0),this._iv=void 0);var s=o.slice(0);r.encryptBlock(s,0),o[i-1]=o[i-1]+1|0;for(var c=0;c<i;c++)t[e+c]^=s[c]}});return t.Decryptor=e,t}(),function(){var t=l,e=t.lib.StreamCipher,r=t.algo,i=[],n=[],o=[],s=r.RabbitLegacy=e.extend({_doReset:function(){var t=this._key.words,e=this.cfg.iv,r=this._X=[t[0],t[3]<<16|t[2]>>>16,t[1],t[0]<<16|t[3]>>>16,t[2],t[1]<<16|t[0]>>>16,t[3],t[2]<<16|t[1]>>>16],i=this._C=[t[2]<<16|t[2]>>>16,4294901760&t[0]|65535&t[1],t[3]<<16|t[3]>>>16,4294901760&t[1]|65535&t[2],t[0]<<16|t[0]>>>16,4294901760&t[2]|65535&t[3],t[1]<<16|t[1]>>>16,4294901760&t[3]|65535&t[0]];this._b=0;for(var n=0;n<4;n++)c.call(this);for(n=0;n<8;n++)i[n]^=r[n+4&7];if(e){var o=e.words,s=o[0],a=o[1],h=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),l=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),f=h>>>16|4294901760&l,u=l<<16|65535&h;i[0]^=h,i[1]^=f,i[2]^=l,i[3]^=u,i[4]^=h,i[5]^=f,i[6]^=l,i[7]^=u;for(n=0;n<4;n++)c.call(this)}},_doProcessBlock:function(t,e){var r=this._X;c.call(this),i[0]=r[0]^r[5]>>>16^r[3]<<16,i[1]=r[2]^r[7]>>>16^r[5]<<16,i[2]=r[4]^r[1]>>>16^r[7]<<16,i[3]=r[6]^r[3]>>>16^r[1]<<16;for(var n=0;n<4;n++)i[n]=16711935&(i[n]<<8|i[n]>>>24)|4278255360&(i[n]<<24|i[n]>>>8),t[e+n]^=i[n]},blockSize:4,ivSize:2});function c(){for(var t=this._X,e=this._C,r=0;r<8;r++)n[r]=e[r];e[0]=e[0]+1295307597+this._b|0,e[1]=e[1]+3545052371+(e[0]>>>0<n[0]>>>0?1:0)|0,e[2]=e[2]+886263092+(e[1]>>>0<n[1]>>>0?1:0)|0,e[3]=e[3]+1295307597+(e[2]>>>0<n[2]>>>0?1:0)|0,e[4]=e[4]+3545052371+(e[3]>>>0<n[3]>>>0?1:0)|0,e[5]=e[5]+886263092+(e[4]>>>0<n[4]>>>0?1:0)|0,e[6]=e[6]+1295307597+(e[5]>>>0<n[5]>>>0?1:0)|0,e[7]=e[7]+3545052371+(e[6]>>>0<n[6]>>>0?1:0)|0,this._b=e[7]>>>0<n[7]>>>0?1:0;for(r=0;r<8;r++){var i=t[r]+e[r],s=65535&i,c=i>>>16,a=((s*s>>>17)+s*c>>>15)+c*c,h=((4294901760&i)*i|0)+((65535&i)*i|0);o[r]=a^h}t[0]=o[0]+(o[7]<<16|o[7]>>>16)+(o[6]<<16|o[6]>>>16)|0,t[1]=o[1]+(o[0]<<8|o[0]>>>24)+o[7]|0,t[2]=o[2]+(o[1]<<16|o[1]>>>16)+(o[0]<<16|o[0]>>>16)|0,t[3]=o[3]+(o[2]<<8|o[2]>>>24)+o[1]|0,t[4]=o[4]+(o[3]<<16|o[3]>>>16)+(o[2]<<16|o[2]>>>16)|0,t[5]=o[5]+(o[4]<<8|o[4]>>>24)+o[3]|0,t[6]=o[6]+(o[5]<<16|o[5]>>>16)+(o[4]<<16|o[4]>>>16)|0,t[7]=o[7]+(o[6]<<8|o[6]>>>24)+o[5]|0}t.RabbitLegacy=e._createHelper(s)}(),l.pad.ZeroPadding={pad:function(t,e){var r=4*e;t.clamp(),t.sigBytes+=r-(t.sigBytes%r||r)},unpad:function(t){var e=t.words,r=t.sigBytes-1;for(r=t.sigBytes-1;r>=0;r--)if(e[r>>>2]>>>24-r%4*8&255){t.sigBytes=r+1;break}}},l}); + +const $ = new Env("IT之家"); +$.userHash = "senku_ithome_userHash"; +const code = [ + 0, + 1, + 2, + 3, + 256, + 257, + 258, + 259, + 512, + 513, + 514, + 515, + 768, + 769, + 770, + 771, +]; +const now = new Date().getTime(); +$.arr = []; +$.result = ""; + +!(async () => { + $.CryptoJS = $.isNode() ? require("crypto-js") : CryptoJS; + // code.forEach(async (val) => { + // await sign(val); + // }); + await sign(); + await signinfo(); + await showmsg(); +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()); + +function sign() { + return new Promise((resolve) => { + const url = { + url: getUrl(), + headers: { + Host: "napi.ithome.com", + "User-Agent": + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 ithome/rmsdklevel2/day/7.63", + }, + }; + $.get(url, (err, resp, data) => { + try { + const res = JSON.parse(data); + if (res.ok === 0) { + $.result = res.msg; + } else if (res.ok === 1) { + $.result = res.title; + } else { + $.result = "未知签到结果,请查看日志"; + console.log(data); + } + } catch (e) { + $.logErr(e, resp); + } finally { + resolve(); + } + }); + }); +} + +function signinfo() { + return new Promise((resolve) => { + const userHash = $.getdata($.userHash); + const url = { + url: `https://napi.ithome.com/api/usersign/getsigninfo?userHash=${userHash}`, + headers: {}, + }; + url.headers["User-Agent"] = + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 ithome/rmsdklevel2/day/7.32"; + $.get(url, (err, resp, data) => { + try { + $.signinfo = JSON.parse(data); + } catch (e) { + $.logErr(e, resp); + } finally { + resolve(); + } + }); + }); +} + +function encrypt(str) { + const key = `HCa%Y|7#`; + const keyHex = $.CryptoJS.enc.Utf8.parse(key); + return $.CryptoJS.enc.Base64.parse( + $.CryptoJS.DES.encrypt(str, keyHex, { + mode: $.CryptoJS.mode.ECB, + padding: $.CryptoJS.pad.ZeroPadding, + }).toString() + ).toString($.CryptoJS.enc.Hex); +} + +function showmsg() { + return new Promise((resolve) => { + $.subt = `签到:${$.result}`; + $.desc = []; + if ($.signinfo) { + $.desc.push( + `连续:${$.signinfo.cdays}天,累计:${$.signinfo.mdays}天,金币:${$.signinfo.totalcoin}个` + ); + } + $.msg($.name, $.subt, $.desc.join("\n")); + resolve(); + }); +} + +function gekk(S) { + const Skey = + "hd7%b4f8p9)*fd4h5l6|)123/*-+!#$@%^*()_+?>?njidfds[]rfbcvnb3rz/ird|opqqyh487874515/%90hggigadfihklhkopjj`b3hsdfdsf84215456fi15451%q(#@Fzd795hn^Ccl$vK^L%#w$^yr%ETvX#0TaPSRm5)OeG)^fQnn6^%^UTtJI#3EZ@p6^Rf$^!O$(jnkOiBjn3#inhOQQ!aTX8R)9O%#o3zCVxo3tLyVorwYwA^$%^b9Yy$opSEAOOlFBsS^5d^HoF%tJ$dx%3)^q^c^$al%b4I)QHq^#^AlcK^KZFYf81#bL$n@$%j^H(%m^"; + const timeStemp = new Date(now).getTime(); + const today = new Date(now).getDate(); + const Value1 = Math.round(timeStemp / 50000) * today * 3; + if (S === 3) { + return ( + Skey[parseInt((Value1 % 10000) / 1000) * today] + + Skey[parseInt((Value1 % 1000) / 100) * today] + + Skey[parseInt((Value1 % 100) / 10) * today] + ); + } else if (S === 8) { + return ( + Skey[parseInt((Value1 % 100000000) / 10000000) * today] + + Skey[parseInt((Value1 % 10000000) / 1000000) * today] + + Skey[parseInt((Value1 % 1000000) / 100000) * today] + + Skey[parseInt((Value1 % 100000) / 10000) * today] + + Skey[parseInt((Value1 % 10000) / 1000) * today] + + Skey[parseInt((Value1 % 1000) / 100) * today] + + Skey[parseInt((Value1 % 100) / 10) * today] + + Skey[parseInt(Value1 % 10) * today] + ); + } +} + +function gnekk() { + const base = CryptoJS.TripleDES.encrypt( + CryptoJS.enc.Utf8.parse(gekk(3)), + CryptoJS.enc.Utf8.parse(gekk(8)), + { + mode: CryptoJS.mode.ECB, // 加密模式 + padding: CryptoJS.pad.ZeroPadding, + } + ).toString(); + const text = "k" + CryptoJS.enc.Base64.parse(base).toString(CryptoJS.enc.Hex); + return text; +} + +function geKsk() { + const base = CryptoJS.TripleDES.encrypt( + CryptoJS.enc.Utf8.parse($.time("yyyy-MM-dd HH:mm:ss", now)), + CryptoJS.enc.Utf8.parse(gekk(8)), + { + mode: CryptoJS.mode.ECB, // 加密模式 + padding: CryptoJS.pad.ZeroPadding, + } + ).toString(); + const text = CryptoJS.enc.Base64.parse(base).toString(CryptoJS.enc.Hex); + return text; +} + +function getUrl() { + const userHash = $.getdata($.userHash); + return `https://napi.ithome.com/api/usersign/sign?userHash=${userHash}&type=0×tamp=${now}&${gnekk()}=${geKsk()}`; +} + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/jd/JD_BaiTiao.js b/jd/JD_BaiTiao.js new file mode 100644 index 000000000..57de59199 --- /dev/null +++ b/jd/JD_BaiTiao.js @@ -0,0 +1,116 @@ +/* +[task_local] +# 京东金融领白条券 9点执行(周五券要9点开始领) +0 9 * * * JD_BaiTiao.js +*/ +const $ = new Env('天天领白条券'); +const Key = '';//单引号内自行填写您抓取的京东Cookie +const DualKey = '';//双账户 +//直接用NobyDa的jd cookie +const cookie ={CookieJD: [Key ? Key : $.getdata('CookieJD'),DualKey ? DualKey : $.getdata('CookieJD2')]}; +var CookieJD = '';//实际使用的cookie +const JR_API_HOST = 'https://jrmkt.jd.com/activity/newPageTake/takePrize'; +const Prize = { + //每周五领55-5券 每月两次 + PrizeFriday :{ Id : `Q96200731141823255924Qy`, Body : `activityId=Q96200731141823255924Qy&eid=${randomWord(false,90).toUpperCase()}&fp=${randomWord(false,32).toLowerCase()}`}, + //每日领随机白条券 + PrizeDaily : { Id : `Q229326314441137002k96C`, Body : `activityId=Q229326314441137002k96C&eid=${randomWord(false,90).toUpperCase()}&fp=${randomWord(false,32).toLowerCase()}`} +} + +!(async () => { + if (!cookie.CookieJD[0]) { + $.msg($.name, '【提示】请先获取cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/', {"open-url": "https://bean.m.jd.com/"}); + return; + } + for (let i = 0; i < cookie.CookieJD.length; i++) { + CookieJD = cookie.CookieJD[i]; + if (CookieJD) { + $.Prize = {}; + let date = new Date(); + await takePrize(Prize.PrizeDaily.Body, "PrizeDaily", "天天领"); + if ($.Prize["PrizeDaily"].respCode == "00001" ) + { + $.msg($.name, '【提示】请先获取cookie\n直接使用NobyDa的京东签到获取', 'https://bean.m.jd.com/', {"open-url": "https://bean.m.jd.com/"}); + continue; + } + if (date.getDay() == 5) { + await $.wait(800); //延迟执行,防止提示活动火爆 + await takePrize(Prize.PrizeFriday.Body,"PrizeFriday","周五领"); + } + await msgShow(); + } + } +})() + .catch((e) => { + $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') + }) + .finally(() => { + $.done(); + }) + + +function takePrize(body,PrizeName,Desc,timeout = 0) { + return new Promise((resolve) => { + setTimeout( ()=>{ + let url = { + url: JR_API_HOST, + body : body, + headers: { + 'Cookie' : CookieJD, + 'X-Requested-With' : `XMLHttpRequest`, + 'Accept' : `application/json, text/javascript, */*; q=0.01`, + 'Origin' : `https://jrmkt.jd.com`, + 'Accept-Encoding' : `gzip, deflate, br`, + 'Content-Type' : `application/x-www-form-urlencoded;charset=UTF-8`, + 'Host' : `jrmkt.jd.com`, + 'Connection' : `keep-alive`, + 'Referer' : `https://jrmkt.jd.com/ptp/wl/vouchers.html?activityId=${Prize[PrizeName].Id}`, + 'Accept-Language' : `zh-cn` + } + } + $.post(url, (err, resp, data) => { + try { + data = JSON.parse(data); + $.Prize[PrizeName] = data; + $.Prize[PrizeName].Desc = Desc; + } catch (e) { + $.logErr(e, resp); + } finally { + resolve() + } + }) + },timeout) + }) +} + +function randomWord(randomFlag, min, max){ + let str = "", + range = min, + arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; + // 随机产生 + if(randomFlag){ + range = Math.round(Math.random() * (max-min)) + min; + } + for(let i=0; i<range; i++){ + pos = Math.round(Math.random() * (arr.length-1)); + str += arr[pos]; + } + return str; +} + +function msgShow() { + $.message = ""; + for (var i in $.Prize) { + if (typeof($.message) == "undefined") $.message = `用户名【${$.Prize[i].nickName}】\n`; + if ($.Prize[i].respCode === "00000") { + $.message += `${$.Prize[i].Desc}:${$.Prize[i].prizeModels[0].prizeName + $.Prize[i].prizeModels[0].prizeAward}\n`; + } + else { + $.message += `${$.Prize[i].Desc}:${typeof($.Prize[i].failDesc) == "undefined" ? $.Prize[i].respDesc : $.Prize[i].failDesc}\n`; + } + } + $.msg($.name, '', `${$.message.substr(0,$.message.length - 1)}`); +} + + +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/jd/jd.618.adapt.js b/jd/jd.618.adapt.js new file mode 100644 index 000000000..fb9284b51 --- /dev/null +++ b/jd/jd.618.adapt.js @@ -0,0 +1,377 @@ +const $ = new Env('京东618') +$.VAL_url = $.getdata('chavy_url_jd816') +$.VAL_body = $.getdata('chavy_body_jd816') +$.VAL_headers = $.getdata('chavy_headers_jd816') +$.VAL_isSignShop = $.getdata('CFG_618_isSignShop') || 'true' +$.VAL_isJoinBrand = $.getdata('CFG_618_isJoinBrand') || 'false' +$.VAL_radommsMin = $.getdata('CFG_618_radomms_min') || '2000' +$.VAL_radommsMax = $.getdata('CFG_618_radomms_max') || '5000' + +!(async () => { + $.log('', `🔔 ${$.name}, 开始!`, '') + await getData() + await getActs() + await getShops() + await execActs() + showmsg() +})() + .catch((e) => { + $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') + }) + .finally(() => { + $.msg($.name, $.subt, $.desc), $.log('', `🔔 ${$.name}, 结束!`, ''), $.done() + }) + +function getData() { + return new Promise((resove) => { + $.post(taskurl('cakebaker_getHomeData'), (error, response, data) => { + try { + if (error) throw new Error(error) + const _info = JSON.parse(data).data.result.cakeBakerInfo + $.secretp = _info.secretp + if (!$.secretp) throw new Error('获取 secretp 失败!') + $.log(`❕ ${$.name}, 获取密钥!`) + $.log(` 密钥 = ${$.secretp.slice(0, 10)}...`) + $.log(` 等级 = ${_info.raiseInfo.scoreLevel}`) + $.log(` 分数 = ${_info.raiseInfo.totalScore} => ${_info.raiseInfo.nextLevelScore}`) + $.log(` 延时 = ${$.VAL_radommsMin} => ${$.VAL_radommsMax} 毫秒`, '') + } catch (e) { + $.log(`❗️ ${$.name}, 获取密钥!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +function getShops() { + return new Promise((resove) => { + $.post(taskurl('cakebaker_bigBrandHomeData'), (error, response, data) => { + try { + $.log(`❕ ${$.name}, 获取商店!`) + if (error) throw new Error(error) + $.shopActs = [] + JSON.parse(data).data.result.bigBrandList.forEach((_shopa) => { + const _shopact = { + _raw: _shopa, + id: _shopa.venderId, + name: _shopa.name + } + $.shopActs.push(_shopact) + }) + $.log(` 商店数量 = ${$.shopActs.length}`, '') + } catch (e) { + $.log(`❗️ ${$.name}, 获取商店!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +function getActs() { + return new Promise((resove) => { + $.post(taskurl('cakebaker_getTaskDetail'), (error, response, data) => { + try { + $.log(`❕ ${$.name}, 获取活动!`) + if (error) throw new Error(error) + $.acts = [] + JSON.parse(data).data.result.taskVos.forEach((_a) => { + const _act = { + _raw: _a, + id: _a.taskId, + name: _a.taskName, + times: _a.times, + maxTimes: _a.maxTimes, + waitDuration: _a.waitDuration === 0 ? 1 : _a.waitDuration, + isProd: _a.productInfoVos ? true : false, + isBrand: _a.shoppingActivityVos && _a.taskId === 42 ? true : false, + tasks: [] + } + const _vo = _a[Object.keys(_a).find((key) => (_a[key] && _a[key].itemId) || (_a[key] && _a[key][0] && _a[key][0].itemId))] + if (Array.isArray(_vo)) { + _vo.forEach((_task) => _act.tasks.push({ _raw: _task, id: _task.itemId, name: _task.title || _task.shopName || _task.taskName || '未知名称' })) + } else { + _act.tasks = Array(_act.maxTimes - _act.times).fill({ _raw: _vo, id: _vo.itemId, name: _act.name }) + } + $.acts.push(_act) + }) + if (!$.acts) throw new Error('获取活动失败!') + $.log(` 活动数量 = ${$.acts.length}`, '') + } catch (e) { + $.log(`❗️ ${$.name}, 获取活动!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +async function execActs() { + $.log(`❕ ${$.name}, 执行活动!`) + for (let _actIdx = 0; _actIdx < $.acts.length; _actIdx++) { + const _act = $.acts[_actIdx] + $.log(` ${_actIdx + 1}. ${_act.name} (${_act.times}/${_act.maxTimes})`) + if (_act.times === _act.maxTimes) { + $.log(` @跳过: 全部完成!`, '') + continue + } + // 跳过:邀请好友、加入战队 + if ([2, 12].includes(_act.id)) { + $.log(' 跳过!', '') + continue + } + // 甄选优品 + else if (_act.isProd) { + await getProdAct(_act) + for (let subactIdx = 0; subactIdx < _act.subacts.length; subactIdx++) { + const subact = _act.subacts[subactIdx] + $.log(` ${subactIdx + 1}. ${subact.name} (${subact.times}/${subact.maxTimes})`) + if (subact.times === subact.maxTimes) { + $.log(` @跳过: 全部完成!`, '') + continue + } + for (let subataskIdx = 0; subataskIdx < subact.tasks.length; subataskIdx++) { + const subatask = subact.tasks[subataskIdx] + $.log(` ${subataskIdx + 1}. ${subatask.name.slice(0, 15)}...`) + if (subatask._raw.status && subatask._raw.status === 2) { + $.log(` @跳过: 已经做过!`, '') + continue + } + await sendtask(subact, subatask, true) + $.log(` @认领任务: ${subatask.isClaimSuc ? '🟢' : '🔴'}`) + if (subatask.isskip) { + $.log(` @跳过: ${subatask.msg}`) + const randomms = genRadomms() + $.log(` @等待: 8 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(8000 + randomms)) + } else { + const randomms = genRadomms() + $.log(` @等待: ${subact.waitDuration} 秒 + ${randomms} 毫秒`) + await new Promise($.wait(subact.waitDuration * 1000 + randomms)) + await sendtask(subact, subatask) + $.log(` @完成任务: ${subatask.isExecSuc ? '🟢' : '🔴'}`) + $.log(` @等待: 5 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(5000 + randomms)) + } + } + } + } + // 开通会员 + else if (_act.isBrand) { + if ($.VAL_isJoinBrand === 'true' || $.VAL_isJoinBrand === true) { + for (let taskIdx = 0; taskIdx < _act.tasks.length; taskIdx++) { + const task = _act.tasks[taskIdx] + $.log(` ${taskIdx + 1}. ${task.name}`) + await joinBrand(task) + $.log(` @加入会员: ${task.isJoinSuc ? '🟢' : '🔴'}`) + const randomms = genRadomms() + $.log(` @等待: ${_act.waitDuration} 秒 + ${randomms} 毫秒`) + await new Promise($.wait(_act.waitDuration * 1000 + randomms)) + await brandAward(task) + $.log(` @完成任务: ${task.isAwardSuc ? '🟢' : '🔴'}`) + $.log(` @等待: 5 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(5000 + randomms)) + } + } else { + $.log(` @跳过: BoxJs 设置为 关闭 品牌会员!`, '') + } + } + // 普通任务 + else { + for (let taskIdx = 0; taskIdx < _act.tasks.length; taskIdx++) { + const task = _act.tasks[taskIdx] + $.log(` ${taskIdx + 1}. ${task.name}`) + if (task._raw.status && task._raw.status === 2) { + $.log(` @跳过: 已经做过!`, '') + continue + } + await sendtask(_act, task, true) + $.log(` @认领任务: ${task.isClaimSuc ? '🟢' : '🔴'}`) + if (task.isskip || task.ishot) { + $.log(` @跳过: ${task.msg}`) + const randomms = genRadomms() + $.log(` @等待: 8 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(8000 + randomms)) + } else { + const randomms = genRadomms() + $.log(` @等待: ${_act.waitDuration} 秒 + ${randomms} 毫秒`) + await new Promise($.wait(_act.waitDuration * 1000 + randomms)) + await sendtask(_act, task) + $.log(` @完成任务: ${task.isExecSuc ? '🟢' : '🔴'}`) + $.log(` @等待: 5 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(5000 + randomms)) + } + } + } + } + + // 商店签到 + $.log(` ${$.acts.length + 1}. 商店签到 (${$.shopActs.length})`) + if ($.VAL_isSignShop === 'true' || $.VAL_isSignShop === true) { + for (let _shopIdx = 0; _shopIdx < $.shopActs.length; _shopIdx++) { + const shop = $.shopActs[_shopIdx] + $.log(` ${_shopIdx + 1}. ${shop.name}`) + await signshop(shop) + shop.msg = /,/.test(shop.msg) ? shop.msg.split(',')[1] : shop.msg + $.log(` @签到: ${shop.isSuc ? '🟢 已领取!' : shop.code === 402 ? '⚪️ 无效活动!' : `🔴 ${shop.msg}`}`) + const randomms = genRadomms() + $.log(` @等待: 8 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(8000 + randomms)) + } + } else { + $.log(` @跳过: BoxJs 设置为 关闭 商店签到!`, '') + } +} + +// 商品类活动 +function getProdAct(act) { + return new Promise((resove) => { + const body = { taskIds: act.tasks.map((task) => task.id).toString() } + $.post(taskurl('cakebaker_getFeedDetail', JSON.stringify(body)), (error, response, data) => { + try { + const _result = JSON.parse(data).data.result + const _vo = _result[Object.keys(_result).find((key) => Array.isArray(_result[key] && _result[key][0] && _result[key][0].productInfoVos))] + act.subacts = [] + _vo.forEach((_suba) => { + const _subact = { + _raw: _suba, + id: _suba.taskId, + name: _suba.taskName, + times: _suba.times, + maxTimes: _suba.maxTimes, + waitDuration: _suba.waitDuration === 0 ? 1 : _suba.waitDuration, + isProd: _suba.productInfoVos ? true : false, + tasks: [] + } + _suba.productInfoVos.slice(0, 5).forEach((_prodvo) => { + const _taskname = _prodvo.skuName || _prodvo.title || _prodvo.shopName || _prodvo.taskName || '未知名称' + _subact.tasks.push({ + _raw: _prodvo, + id: _prodvo.itemId, + name: _taskname + }) + }) + act.subacts.push(_subact) + }) + } catch (e) { + $.log(`❗️ ${$.name}, 执行商品类活动!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +function sendtask(act, task, isClaim = false) { + return new Promise((resove) => { + const body = { + taskId: act.id, + itemId: task.id, + actionType: isClaim ? 1 : undefined, + safeStr: JSON.stringify({ secretp: $.secretp }) + } + $.post(taskurl('cakebaker_ckCollectScore', JSON.stringify(body)), (error, response, data) => { + try { + const _data = JSON.parse(data) + const _issuc = _data.data.bizCode === 0 || _data.data.bizCode === -5 || _data.data.bizCode === -15 + if (isClaim) task.isClaimSuc = _issuc + else task.isExecSuc = _issuc + task.isskip = _data.data.bizCode === -5 + task.ishot = _data.data.bizCode === -15 + task.msg = _data.data.bizMsg || '无' + } catch (e) { + if (isClaim) task.isClaimSuc = false + else task.isExecSuc = false + task.isskip = false + task.ishot = false + task.msg = error || e + } finally { + resove() + } + }) + }) +} + +function signshop(shop) { + return new Promise((resove) => { + const body = { channel: 2, venderId: shop.id } + $.post(taskurl('interact_center_sign_collectGift', JSON.stringify(body)), (error, response, data) => { + try { + const _data = JSON.parse(data) + shop.isSuc = _data.code === 407000005 || _data.code === 200 ? true : false + shop.code = _data.code + shop.msg = _data.msg + } catch (e) { + shop.isSuc = false + shop.msg = error || e + } finally { + resove() + } + }) + }) +} + +function joinBrand(task) { + return new Promise((resove) => { + const body = { + venderId: task._raw.copy1, + shopId: task._raw.copy1, + bindByVerifyCodeFlag: 1, + registerExtend: {}, + writeChildFlag: 0, + channel: 4032 + } + const joinurl = `https://api.m.jd.com/client.action?appid=jd_shop_member&functionId=bindWithVender&body=${encodeURIComponent(JSON.stringify(body))}&client=H5&clientVersion=8.5.6&uuid=88888` + const url = { url: joinurl, headers: JSON.parse($.VAL_headers) } + delete url.headers['Content-Length'] + $.get(url, (error, response, data) => { + try { + const _data = JSON.parse(data) + task.isJoinSuc = _data.busiCode === '0' + task.msg = _data.message || '无' + } catch (e) { + task.isJoinSuc = false + task.msg = error || e + } finally { + resove() + } + }) + }) +} +function brandAward(task) { + return new Promise((resove) => { + const body = { venderId: task._raw.copy1, itemId: task.id } + $.post(taskurl('cakebaker_taskBigBrandAward', JSON.stringify(body)), (error, response, data) => { + try { + const _data = JSON.parse(data) + const _issuc = _data.data.bizCode === 0 || _data.data.bizCode === -5 || _data.data.bizCode === -15 + task.isAwardSuc = _issuc + task.msg = _data.data.bizMsg || '无' + } catch (e) { + task.isAwardSuc = false + task.msg = error || e + } finally { + resove() + } + }) + }) +} + +function taskurl(fid, body = '{}') { + const url = { url: `https://api.m.jd.com/client.action` } + url.headers = JSON.parse($.VAL_headers) + url.body = `functionId=${fid}&body=${body}&client=wh5&clientVersion=1.0.0` + return url +} + +function genRadomms() { + const max = $.VAL_radommsMax * 1 + const min = $.VAL_radommsMin * 1 + return parseInt(Math.random() * (max - min + 1) + min, 10) +} + +function showmsg() {} + +// prettier-ignore +function Env(t){this.name=t,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.log=((...t)=>{this.logs=[...this.logs,...t],t?console.log(t.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((t=this.name,s="",i="")=>{this.isSurge()&&$notification.post(t,s,i),this.isQuanX()&&$notify(t,s,i);const e=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t&&e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n"))}),this.getdata=(t=>this.isSurge()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):void 0),this.setdata=((t,s)=>this.isSurge()?$persistentStore.write(t,s):this.isQuanX()?$prefs.setValueForKey(t,s):void 0),this.get=((t,s)=>this.send(t,"GET",s)),this.wait=((t,s=t)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(s-t+1)+t))),this.post=((t,s)=>this.send(t,"POST",s)),this.send=((t,s,i)=>{if(this.isSurge()){const e="POST"==s?$httpClient.post:$httpClient.get;e(t,(t,s,e)=>{s&&(s.body=e,s.statusCode=s.status),i(t,s,e)})}this.isQuanX()&&(t.method=s,$task.fetch(t).then(t=>{t.status=t.statusCode,i(null,t,t.body)},t=>i(t.error,t,t)))}),this.done=((t={})=>$done(t))} diff --git a/jd/jd.618.boom.js b/jd/jd.618.boom.js new file mode 100644 index 000000000..4e2b2915a --- /dev/null +++ b/jd/jd.618.boom.js @@ -0,0 +1,88 @@ +const $ = new Env('京东618炸弹') +$.VAL_url = $.getdata('chavy_url_jd816') +$.VAL_body = $.getdata('chavy_body_jd816') +$.VAL_headers = $.getdata('chavy_headers_jd816') +$.VAL_boomtimes = $.getdata('CFG_BOOM_times_JD618') || 1 +$.VAL_boominterval = $.getdata('CFG_BOOM_interval_JD618') || 100 + +!(async () => { + $.log('', `🔔 ${$.name}, 开始!`, '') + await boom() + await showmsg() +})() + .catch((e) => { + $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') + }) + .finally(() => { + $.log('', `🔔 ${$.name}, 结束!`, ''), $.done() + }) + +async function boom() { + $.boomacts = [] + $.boomdesc = [] + for (let boomIdx = 0; boomIdx < $.VAL_boomtimes; boomIdx++) { + const isLastBoom = boomIdx === $.VAL_boomtimes - 1 + $.boomdesc.push(`💣 [${moment('mm:ss')}] 发送第 ${boomIdx + 1} 个炸弹 ${isLastBoom ? '(最后一个)' : ''}`) + const boomAct = new Promise((resove) => { + $.post(taskurl('cakebaker_pk_getCakeBomb'), (error, response, data) => { + try { + if (error) throw new Error(error) + const _data = JSON.parse(data) + const _issuc = _data.code === 0 && _data.data && _data.data.bizCode === 0 + $.boom = { isSuc: _issuc, boomIdx, ..._data.data.result } + if (isLastBoom) $.boomdesc.push(`❕ [${moment('mm:ss')}] 第 ${boomIdx + 1} 炸: ${$.boom.tip}`) + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) + $.boomacts.push(boomAct) + if (isLastBoom) await boomAct + await new Promise($.wait($.VAL_boominterval * 1)) + $.boomdesc.push(`❕ [${moment('mm:ss')}] 等待: ${$.VAL_boominterval} 毫秒!`) + } +} + +function moment(fmt) { + const now = new Date() + const o = { + 'M+': now.getMonth() + 1, + 'd+': now.getDate(), + 'h+': now.getHours(), + 'm+': now.getMinutes(), + 's+': now.getSeconds(), + 'q+': Math.floor((now.getMonth() + 3) / 3), + S: now.getMilliseconds() + } + if (/(y+)/.test(fmt)) { + fmt = fmt.replace(RegExp.$1, (now.getFullYear() + '').substr(4 - RegExp.$1.length)) + } + for (var 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 +} + +function taskurl(fid, body = '{}') { + const url = { url: `https://api.m.jd.com/client.action` } + url.headers = JSON.parse($.VAL_headers) + url.body = `functionId=${fid}&body=${body}&client=wh5&clientVersion=1.0.0` + return url +} + +async function showmsg() { + await Promise.all($.boomacts) + $.subt = `我方: ${$.boom.groupLevel || '❓'}层, 对方: ${$.boom.opponentLevel || 0}层, 炸掉: ${$.boom.destroyLevel || 0}层` + $.desc = [$.boom.tip || '提示: 无!', '点击查看详情', ...$.boomdesc] + $.msg(`${$.name} (第 ${$.boom.boomIdx + 1} 炸)`, $.subt, $.desc.join('\n')) + // return new Promise((resove) => { + // resove() + // }) +} + +// prettier-ignore +function Env(t){this.name=t,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.log=((...t)=>{this.logs=[...this.logs,...t],t?console.log(t.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((t=this.name,s="",i="")=>{this.isSurge()&&$notification.post(t,s,i),this.isQuanX()&&$notify(t,s,i);const e=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t&&e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n"))}),this.getdata=(t=>this.isSurge()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):void 0),this.setdata=((t,s)=>this.isSurge()?$persistentStore.write(t,s):this.isQuanX()?$prefs.setValueForKey(t,s):void 0),this.get=((t,s)=>this.send(t,"GET",s)),this.wait=((t,s=t)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(s-t+1)+t))),this.post=((t,s)=>this.send(t,"POST",s)),this.send=((t,s,i)=>{if(this.isSurge()){const e="POST"==s?$httpClient.post:$httpClient.get;e(t,(t,s,e)=>{s&&(s.body=e,s.statusCode=s.status),i(t,s,e)})}this.isQuanX()&&(t.method=s,$task.fetch(t).then(t=>{t.status=t.statusCode,i(null,t,t.body)},t=>i(t.error,t,t)))}),this.done=((t={})=>$done(t))} diff --git a/jd/jd.618.cookie.js b/jd/jd.618.cookie.js new file mode 100644 index 000000000..227622a57 --- /dev/null +++ b/jd/jd.618.cookie.js @@ -0,0 +1,54 @@ +/** + * + * 进入 叠蛋糕 主页获取 Cookies + * + * Surge: + * Rewrite: JD618 = type=http-request,pattern=^https:\/\/api.m.jd.com\/client.action\?functionId=cakebaker_getHomeData,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.cookie.js,requires-body=true + * Tasks: JD618 = type=cron,cronexp="10,30,50 0,1 * * *",script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.js,wake-system=true,timeout=1200 + * Tasks: JD618.Boom = type=cron,cronexp="0 10,12,18,20,21 * * *",script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.boom.js,wake-system=true + * Tasks: JD618.Boom = type=cron,cronexp="30 21 * * *",script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.boom.js,wake-system=true + * + * QuanX: + * ^https:\/\/api.m.jd.com\/client.action\?functionId=cakebaker_getHomeData url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.cookie.js + * + * [task_local] + * # 远程 + * 10,30,50 0,1 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.adapt.js, tag=京东618 + * 0 10,12,18,20,21 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.boom.js, tag=京东618炸弹 + * 30 21 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.boom.js, tag=京东618炸弹 + * + * Loon: + * cron "10,30,50 0,1 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.adapt.js, timeout=600, tag=京东618 + * cron "0 10,12,18,20,21 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.boom.js, tag=京东618炸弹 + * cron "30 21 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.boom.js, tag=京东618炸弹 + * http-request ^https:\/\/api.m.jd.com\/client.action\?functionId=cakebaker_getHomeData script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.cookie.js,requires-body=true + * + * [MITM] + * hostname = api.m.jd.com + */ + +const $ = new Env('京东618') + +!(async () => { + $.log('', `🔔 ${$.name}, 获取会话: 开始!`, '') + const VAL_url = $request.url + const VAL_body = $request.body + const VAL_headers = JSON.stringify($request.headers) + if (VAL_url && VAL_body && VAL_headers) { + $.setdata($request.url, 'chavy_url_jd816') + $.setdata($request.body, 'chavy_body_jd816') + $.setdata(JSON.stringify($request.headers), 'chavy_headers_jd816') + $.subt = '获取会话: 成功!' + } +})() + .catch((e) => { + $.subt = '获取会话: 失败!' + $.desc = `原因: ${e}` + $.log(`❌ ${$.name}, 获取会话: 失败! 原因: ${e}!`) + }) + .finally(() => { + $.msg($.name, $.subt, $.desc), $.log('', `🔔 ${$.name}, 获取会话: 结束!`, ''), $.done() + }) + +// prettier-ignore +function Env(t){this.name=t,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.log=((...t)=>{this.logs=[...this.logs,...t],t?console.log(t.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((t=this.name,s="",i="")=>{this.isSurge()&&$notification.post(t,s,i),this.isQuanX()&&$notify(t,s,i);const e=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t&&e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n"))}),this.getdata=(t=>this.isSurge()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):void 0),this.setdata=((t,s)=>this.isSurge()?$persistentStore.write(t,s):this.isQuanX()?$prefs.setValueForKey(t,s):void 0),this.get=((t,s)=>this.send(t,"GET",s)),this.wait=((t,s=t)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(s-t+1)+t))),this.post=((t,s)=>this.send(t,"POST",s)),this.send=((t,s,i)=>{if(this.isSurge()){const e="POST"==s?$httpClient.post:$httpClient.get;e(t,(t,s,e)=>{s&&(s.body=e,s.statusCode=s.status),i(t,s,e)})}this.isQuanX()&&(t.method=s,$task.fetch(t).then(t=>{t.status=t.statusCode,i(null,t,t.body)},t=>i(t.error,t,t)))}),this.done=((t={})=>$done(t))} diff --git a/jd/jd.618.cookie.sgmodule b/jd/jd.618.cookie.sgmodule new file mode 100644 index 000000000..56aa5ac2f --- /dev/null +++ b/jd/jd.618.cookie.sgmodule @@ -0,0 +1,9 @@ +#!name=Chavy iOS JD618 Cookies Module +#!desc=获取京东 618 活动会话信息 +#!system=ios + +[Script] +Rewrite: JD618 = type=http-request,pattern=^https:\/\/api.m.jd.com\/client.action\?functionId=cakebaker_getHomeData,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.cookie.js,requires-body=true,debug=true + +[MITM] +hostname = %INSERT%, api.m.jd.com \ No newline at end of file diff --git a/jd/jd.618.js b/jd/jd.618.js new file mode 100644 index 000000000..fb9284b51 --- /dev/null +++ b/jd/jd.618.js @@ -0,0 +1,377 @@ +const $ = new Env('京东618') +$.VAL_url = $.getdata('chavy_url_jd816') +$.VAL_body = $.getdata('chavy_body_jd816') +$.VAL_headers = $.getdata('chavy_headers_jd816') +$.VAL_isSignShop = $.getdata('CFG_618_isSignShop') || 'true' +$.VAL_isJoinBrand = $.getdata('CFG_618_isJoinBrand') || 'false' +$.VAL_radommsMin = $.getdata('CFG_618_radomms_min') || '2000' +$.VAL_radommsMax = $.getdata('CFG_618_radomms_max') || '5000' + +!(async () => { + $.log('', `🔔 ${$.name}, 开始!`, '') + await getData() + await getActs() + await getShops() + await execActs() + showmsg() +})() + .catch((e) => { + $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') + }) + .finally(() => { + $.msg($.name, $.subt, $.desc), $.log('', `🔔 ${$.name}, 结束!`, ''), $.done() + }) + +function getData() { + return new Promise((resove) => { + $.post(taskurl('cakebaker_getHomeData'), (error, response, data) => { + try { + if (error) throw new Error(error) + const _info = JSON.parse(data).data.result.cakeBakerInfo + $.secretp = _info.secretp + if (!$.secretp) throw new Error('获取 secretp 失败!') + $.log(`❕ ${$.name}, 获取密钥!`) + $.log(` 密钥 = ${$.secretp.slice(0, 10)}...`) + $.log(` 等级 = ${_info.raiseInfo.scoreLevel}`) + $.log(` 分数 = ${_info.raiseInfo.totalScore} => ${_info.raiseInfo.nextLevelScore}`) + $.log(` 延时 = ${$.VAL_radommsMin} => ${$.VAL_radommsMax} 毫秒`, '') + } catch (e) { + $.log(`❗️ ${$.name}, 获取密钥!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +function getShops() { + return new Promise((resove) => { + $.post(taskurl('cakebaker_bigBrandHomeData'), (error, response, data) => { + try { + $.log(`❕ ${$.name}, 获取商店!`) + if (error) throw new Error(error) + $.shopActs = [] + JSON.parse(data).data.result.bigBrandList.forEach((_shopa) => { + const _shopact = { + _raw: _shopa, + id: _shopa.venderId, + name: _shopa.name + } + $.shopActs.push(_shopact) + }) + $.log(` 商店数量 = ${$.shopActs.length}`, '') + } catch (e) { + $.log(`❗️ ${$.name}, 获取商店!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +function getActs() { + return new Promise((resove) => { + $.post(taskurl('cakebaker_getTaskDetail'), (error, response, data) => { + try { + $.log(`❕ ${$.name}, 获取活动!`) + if (error) throw new Error(error) + $.acts = [] + JSON.parse(data).data.result.taskVos.forEach((_a) => { + const _act = { + _raw: _a, + id: _a.taskId, + name: _a.taskName, + times: _a.times, + maxTimes: _a.maxTimes, + waitDuration: _a.waitDuration === 0 ? 1 : _a.waitDuration, + isProd: _a.productInfoVos ? true : false, + isBrand: _a.shoppingActivityVos && _a.taskId === 42 ? true : false, + tasks: [] + } + const _vo = _a[Object.keys(_a).find((key) => (_a[key] && _a[key].itemId) || (_a[key] && _a[key][0] && _a[key][0].itemId))] + if (Array.isArray(_vo)) { + _vo.forEach((_task) => _act.tasks.push({ _raw: _task, id: _task.itemId, name: _task.title || _task.shopName || _task.taskName || '未知名称' })) + } else { + _act.tasks = Array(_act.maxTimes - _act.times).fill({ _raw: _vo, id: _vo.itemId, name: _act.name }) + } + $.acts.push(_act) + }) + if (!$.acts) throw new Error('获取活动失败!') + $.log(` 活动数量 = ${$.acts.length}`, '') + } catch (e) { + $.log(`❗️ ${$.name}, 获取活动!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +async function execActs() { + $.log(`❕ ${$.name}, 执行活动!`) + for (let _actIdx = 0; _actIdx < $.acts.length; _actIdx++) { + const _act = $.acts[_actIdx] + $.log(` ${_actIdx + 1}. ${_act.name} (${_act.times}/${_act.maxTimes})`) + if (_act.times === _act.maxTimes) { + $.log(` @跳过: 全部完成!`, '') + continue + } + // 跳过:邀请好友、加入战队 + if ([2, 12].includes(_act.id)) { + $.log(' 跳过!', '') + continue + } + // 甄选优品 + else if (_act.isProd) { + await getProdAct(_act) + for (let subactIdx = 0; subactIdx < _act.subacts.length; subactIdx++) { + const subact = _act.subacts[subactIdx] + $.log(` ${subactIdx + 1}. ${subact.name} (${subact.times}/${subact.maxTimes})`) + if (subact.times === subact.maxTimes) { + $.log(` @跳过: 全部完成!`, '') + continue + } + for (let subataskIdx = 0; subataskIdx < subact.tasks.length; subataskIdx++) { + const subatask = subact.tasks[subataskIdx] + $.log(` ${subataskIdx + 1}. ${subatask.name.slice(0, 15)}...`) + if (subatask._raw.status && subatask._raw.status === 2) { + $.log(` @跳过: 已经做过!`, '') + continue + } + await sendtask(subact, subatask, true) + $.log(` @认领任务: ${subatask.isClaimSuc ? '🟢' : '🔴'}`) + if (subatask.isskip) { + $.log(` @跳过: ${subatask.msg}`) + const randomms = genRadomms() + $.log(` @等待: 8 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(8000 + randomms)) + } else { + const randomms = genRadomms() + $.log(` @等待: ${subact.waitDuration} 秒 + ${randomms} 毫秒`) + await new Promise($.wait(subact.waitDuration * 1000 + randomms)) + await sendtask(subact, subatask) + $.log(` @完成任务: ${subatask.isExecSuc ? '🟢' : '🔴'}`) + $.log(` @等待: 5 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(5000 + randomms)) + } + } + } + } + // 开通会员 + else if (_act.isBrand) { + if ($.VAL_isJoinBrand === 'true' || $.VAL_isJoinBrand === true) { + for (let taskIdx = 0; taskIdx < _act.tasks.length; taskIdx++) { + const task = _act.tasks[taskIdx] + $.log(` ${taskIdx + 1}. ${task.name}`) + await joinBrand(task) + $.log(` @加入会员: ${task.isJoinSuc ? '🟢' : '🔴'}`) + const randomms = genRadomms() + $.log(` @等待: ${_act.waitDuration} 秒 + ${randomms} 毫秒`) + await new Promise($.wait(_act.waitDuration * 1000 + randomms)) + await brandAward(task) + $.log(` @完成任务: ${task.isAwardSuc ? '🟢' : '🔴'}`) + $.log(` @等待: 5 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(5000 + randomms)) + } + } else { + $.log(` @跳过: BoxJs 设置为 关闭 品牌会员!`, '') + } + } + // 普通任务 + else { + for (let taskIdx = 0; taskIdx < _act.tasks.length; taskIdx++) { + const task = _act.tasks[taskIdx] + $.log(` ${taskIdx + 1}. ${task.name}`) + if (task._raw.status && task._raw.status === 2) { + $.log(` @跳过: 已经做过!`, '') + continue + } + await sendtask(_act, task, true) + $.log(` @认领任务: ${task.isClaimSuc ? '🟢' : '🔴'}`) + if (task.isskip || task.ishot) { + $.log(` @跳过: ${task.msg}`) + const randomms = genRadomms() + $.log(` @等待: 8 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(8000 + randomms)) + } else { + const randomms = genRadomms() + $.log(` @等待: ${_act.waitDuration} 秒 + ${randomms} 毫秒`) + await new Promise($.wait(_act.waitDuration * 1000 + randomms)) + await sendtask(_act, task) + $.log(` @完成任务: ${task.isExecSuc ? '🟢' : '🔴'}`) + $.log(` @等待: 5 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(5000 + randomms)) + } + } + } + } + + // 商店签到 + $.log(` ${$.acts.length + 1}. 商店签到 (${$.shopActs.length})`) + if ($.VAL_isSignShop === 'true' || $.VAL_isSignShop === true) { + for (let _shopIdx = 0; _shopIdx < $.shopActs.length; _shopIdx++) { + const shop = $.shopActs[_shopIdx] + $.log(` ${_shopIdx + 1}. ${shop.name}`) + await signshop(shop) + shop.msg = /,/.test(shop.msg) ? shop.msg.split(',')[1] : shop.msg + $.log(` @签到: ${shop.isSuc ? '🟢 已领取!' : shop.code === 402 ? '⚪️ 无效活动!' : `🔴 ${shop.msg}`}`) + const randomms = genRadomms() + $.log(` @等待: 8 秒 + ${randomms} 毫秒`, '') + await new Promise($.wait(8000 + randomms)) + } + } else { + $.log(` @跳过: BoxJs 设置为 关闭 商店签到!`, '') + } +} + +// 商品类活动 +function getProdAct(act) { + return new Promise((resove) => { + const body = { taskIds: act.tasks.map((task) => task.id).toString() } + $.post(taskurl('cakebaker_getFeedDetail', JSON.stringify(body)), (error, response, data) => { + try { + const _result = JSON.parse(data).data.result + const _vo = _result[Object.keys(_result).find((key) => Array.isArray(_result[key] && _result[key][0] && _result[key][0].productInfoVos))] + act.subacts = [] + _vo.forEach((_suba) => { + const _subact = { + _raw: _suba, + id: _suba.taskId, + name: _suba.taskName, + times: _suba.times, + maxTimes: _suba.maxTimes, + waitDuration: _suba.waitDuration === 0 ? 1 : _suba.waitDuration, + isProd: _suba.productInfoVos ? true : false, + tasks: [] + } + _suba.productInfoVos.slice(0, 5).forEach((_prodvo) => { + const _taskname = _prodvo.skuName || _prodvo.title || _prodvo.shopName || _prodvo.taskName || '未知名称' + _subact.tasks.push({ + _raw: _prodvo, + id: _prodvo.itemId, + name: _taskname + }) + }) + act.subacts.push(_subact) + }) + } catch (e) { + $.log(`❗️ ${$.name}, 执行商品类活动!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +function sendtask(act, task, isClaim = false) { + return new Promise((resove) => { + const body = { + taskId: act.id, + itemId: task.id, + actionType: isClaim ? 1 : undefined, + safeStr: JSON.stringify({ secretp: $.secretp }) + } + $.post(taskurl('cakebaker_ckCollectScore', JSON.stringify(body)), (error, response, data) => { + try { + const _data = JSON.parse(data) + const _issuc = _data.data.bizCode === 0 || _data.data.bizCode === -5 || _data.data.bizCode === -15 + if (isClaim) task.isClaimSuc = _issuc + else task.isExecSuc = _issuc + task.isskip = _data.data.bizCode === -5 + task.ishot = _data.data.bizCode === -15 + task.msg = _data.data.bizMsg || '无' + } catch (e) { + if (isClaim) task.isClaimSuc = false + else task.isExecSuc = false + task.isskip = false + task.ishot = false + task.msg = error || e + } finally { + resove() + } + }) + }) +} + +function signshop(shop) { + return new Promise((resove) => { + const body = { channel: 2, venderId: shop.id } + $.post(taskurl('interact_center_sign_collectGift', JSON.stringify(body)), (error, response, data) => { + try { + const _data = JSON.parse(data) + shop.isSuc = _data.code === 407000005 || _data.code === 200 ? true : false + shop.code = _data.code + shop.msg = _data.msg + } catch (e) { + shop.isSuc = false + shop.msg = error || e + } finally { + resove() + } + }) + }) +} + +function joinBrand(task) { + return new Promise((resove) => { + const body = { + venderId: task._raw.copy1, + shopId: task._raw.copy1, + bindByVerifyCodeFlag: 1, + registerExtend: {}, + writeChildFlag: 0, + channel: 4032 + } + const joinurl = `https://api.m.jd.com/client.action?appid=jd_shop_member&functionId=bindWithVender&body=${encodeURIComponent(JSON.stringify(body))}&client=H5&clientVersion=8.5.6&uuid=88888` + const url = { url: joinurl, headers: JSON.parse($.VAL_headers) } + delete url.headers['Content-Length'] + $.get(url, (error, response, data) => { + try { + const _data = JSON.parse(data) + task.isJoinSuc = _data.busiCode === '0' + task.msg = _data.message || '无' + } catch (e) { + task.isJoinSuc = false + task.msg = error || e + } finally { + resove() + } + }) + }) +} +function brandAward(task) { + return new Promise((resove) => { + const body = { venderId: task._raw.copy1, itemId: task.id } + $.post(taskurl('cakebaker_taskBigBrandAward', JSON.stringify(body)), (error, response, data) => { + try { + const _data = JSON.parse(data) + const _issuc = _data.data.bizCode === 0 || _data.data.bizCode === -5 || _data.data.bizCode === -15 + task.isAwardSuc = _issuc + task.msg = _data.data.bizMsg || '无' + } catch (e) { + task.isAwardSuc = false + task.msg = error || e + } finally { + resove() + } + }) + }) +} + +function taskurl(fid, body = '{}') { + const url = { url: `https://api.m.jd.com/client.action` } + url.headers = JSON.parse($.VAL_headers) + url.body = `functionId=${fid}&body=${body}&client=wh5&clientVersion=1.0.0` + return url +} + +function genRadomms() { + const max = $.VAL_radommsMax * 1 + const min = $.VAL_radommsMin * 1 + return parseInt(Math.random() * (max - min + 1) + min, 10) +} + +function showmsg() {} + +// prettier-ignore +function Env(t){this.name=t,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.log=((...t)=>{this.logs=[...this.logs,...t],t?console.log(t.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((t=this.name,s="",i="")=>{this.isSurge()&&$notification.post(t,s,i),this.isQuanX()&&$notify(t,s,i);const e=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t&&e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n"))}),this.getdata=(t=>this.isSurge()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):void 0),this.setdata=((t,s)=>this.isSurge()?$persistentStore.write(t,s):this.isQuanX()?$prefs.setValueForKey(t,s):void 0),this.get=((t,s)=>this.send(t,"GET",s)),this.wait=((t,s=t)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(s-t+1)+t))),this.post=((t,s)=>this.send(t,"POST",s)),this.send=((t,s,i)=>{if(this.isSurge()){const e="POST"==s?$httpClient.post:$httpClient.get;e(t,(t,s,e)=>{s&&(s.body=e,s.statusCode=s.status),i(t,s,e)})}this.isQuanX()&&(t.method=s,$task.fetch(t).then(t=>{t.status=t.statusCode,i(null,t,t.body)},t=>i(t.error,t,t)))}),this.done=((t={})=>$done(t))} diff --git a/jd/jd.618.sgmodule b/jd/jd.618.sgmodule new file mode 100644 index 000000000..9c42a377c --- /dev/null +++ b/jd/jd.618.sgmodule @@ -0,0 +1,8 @@ +#!name=Chavy iOS JD618 Task Module +#!desc=执行京东 618 活动任务 +#!system=ios + +[Script] +Tasks: JD618 = type=cron,cronexp="10,30,50 0,1 * * *",script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.adapt.js,wake-system=true,timeout=1200 +Tasks: JD618.Boom = type=cron,cronexp="0 10,12,18,20,21 * * *",script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.boom.js,wake-system=true +Tasks: JD618.Boom = type=cron,cronexp="30 21 * * *",script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jd/jd.618.boom.js,wake-system=true \ No newline at end of file diff --git a/jddj/README.md b/jddj/README.md new file mode 100644 index 000000000..58a8a0588 --- /dev/null +++ b/jddj/README.md @@ -0,0 +1,104 @@ +# 京东到家 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 +> 感谢 [@barry](https://t.me/barrymchen) 编写 +> +> 感谢 [@GideonSenku](https://github.com/GideonSenku) 对代码优化 + +## 配置 (Surge) + +```properties +[MITM] +daojia.jd.com + +[Script] +http-request ^https:\/\/daojia.jd.com/client(.*?)functionId=signin(.*?)userSigninNew script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jddj/jddj.cookie.js + +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jddj/jddj.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +daojia.jd.com + +[rewrite_local] + +# [商店版] QuanX v1.0.6-build194 及更早版本 +# ^https:\/\/daojia.jd.com/client(.*?)functionId=signin(.*?)userSigninNew url script-request-header jddj.cookie.js + +# [TestFlight] QuanX v1.0.6-build195 及以后版本 +^https:\/\/daojia.jd.com/client(.*?)functionId=signin(.*?)userSigninNew url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/jddj/jddj.cookie.js + +[task_local] +1 0 * * * jddj.js +``` + +## 说明 + +1. 先把`daojia.jd.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`jddj.cookie.js`和`jddj.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 手机App打开,`我的`> `签到有惊喜`>`签到`手机浏览器打开`https://daojia.jd.com/html/index.html`,`我的`> `签到有惊喜` >`签到` +4. 系统提示: `获取Cookie: 成功` +5. 把获取 Cookie 的脚本注释掉 + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@barry](https://t.me/barrymchen) + +[@GideonSenku](https://github.com/GideonSenku) \ No newline at end of file diff --git a/jddj/jddj.cookie.js b/jddj/jddj.cookie.js new file mode 100644 index 000000000..24f3310d3 --- /dev/null +++ b/jddj/jddj.cookie.js @@ -0,0 +1,54 @@ +const cookieName = '京东到家' +const signheaderKey = 'chen_signheader_jddj' +const chen = init() + if (this.$request) { + const signheaderVal = JSON.stringify($request.headers) + if (signheaderVal) { + chen.setdata(signheaderVal, signheaderKey) + chen.msg(cookieName, `获取Cookie: 成功`, ``) + } + } +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} +chen.done() diff --git a/jddj/jddj.js b/jddj/jddj.js new file mode 100644 index 000000000..d0520bba5 --- /dev/null +++ b/jddj/jddj.js @@ -0,0 +1,74 @@ +const cookieName ='京东到家' +const signheaderKey = 'chen_signheader_jddj' +const chen = init() +const signheaderVal = chen.getdata(signheaderKey) +sign() +function sign() { + let url = {url: `https://daojia.jd.com/client?functionId=signin%2FuserSigninNew&body=%7B%7D`,headers: JSON.parse(signheaderVal)} + chen.get(url, (error, response, data) => { + chen.log(`${cookieName}, data: ${data}`) + let res = JSON.parse(data) + const title = `${cookieName}` + let subTitle = `` + let detail = `` + if (res.success&&res.result.points!='undefined') { + subTitle = `签到结果:成功` + detail = `获取鲜豆:${res.result.points}` + } else if(!res.success&&res.code==202){ + subTitle = `签到结果: 失败` + detail = `说明: ${res.msg}` + } + else if (!res.success&&res.code==-1){ + subTitle = `签到成功,请勿重复操作` + } + else{ + subTitle = `未知错误,截图日志` + } + chen.msg(title, subTitle, detail) + chen.done() + }) + } + + function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } + } diff --git a/rrtv/README.md b/mcdd/README.md similarity index 74% rename from rrtv/README.md rename to mcdd/README.md index 7ec12cb2f..b658b35bf 100644 --- a/rrtv/README.md +++ b/mcdd/README.md @@ -1,45 +1,38 @@ -# 人人视频 +# 叮咚买菜 > 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 -> 2020.1.11 QuanX 在`190`版本开始, 获取 Cookie 方式需要从`script-response-body`改为`script-request-header` - -> 2020.1.31 增加自动领取每日福利 (无需重新获取 Cookie, 直接更新脚本即可!) - ## 配置 (Surge) ```properties [MITM] -*.rr.tv +maicai.api.ddxq.mobi [Script] -http-request ^https:\/\/api\.rr\.tv\/user\/profile script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/rrtv/rrtv.cookie.js -cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/rrtv/rrtv.js +http-request ^https:\/\/maicai.api.ddxq.mobi\/point\/home script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mcdd/mcdd.cookie.js +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mcdd/mcdd.js ``` ## 配置 (QuanX) ```properties [MITM] -*.rr.tv +maicai.api.ddxq.mobi [rewrite_local] -# 189及以前版本 -^https:\/\/api\.rr\.tv\/user\/profile url script-response-body rrtv.cookie.js -# 190及以后版本 -^https:\/\/api\.rr\.tv\/user\/profile url script-request-header rrtv.cookie.js +^https:\/\/maicai.api.ddxq.mobi\/point\/home url script-request-header mcdd.cookie.js [task_local] -1 0 * * * rrtv.js +1 0 * * * mcdd.js ``` ## 说明 -1. 先把`*.rr.tv`加到`[MITM]` +1. 先把`maicai.api.ddxq.mobi`加到`[MITM]` 2. 再配置重写规则: - Surge: 把两条远程脚本放到`[Script]` - - QuanX: 把`rrtv.cookie.js`和`rrtv.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) -3. 打开 APP, 访问下`个人中心` + - QuanX: 把`mcdd.cookie.js`和`mcdd.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP, 访问下`我的`>`积分` 4. 系统提示: `获取Cookie: 成功` (如果不提示获取成功, 尝试杀进程再进个人中心) 5. 最后就可以把第 1 条脚本注释掉了 diff --git a/mcdd/mcdd.cookie.js b/mcdd/mcdd.cookie.js new file mode 100644 index 000000000..7104647f8 --- /dev/null +++ b/mcdd/mcdd.cookie.js @@ -0,0 +1,69 @@ +const chavy = init() +const cookieName = '叮咚买菜' +const KEY_homeurl = 'chavy_home_url_mcdd' +const KEY_homeheader = 'chavy_home_header_mcdd' + +if ($request && $request.method != 'OPTIONS') { + try { + chavy.log(`🔔 ${cookieName} 开始获取: Cookies`) + const VAL_homeurl = $request.url + const VAL_homeheader = JSON.stringify($request.headers) + if (VAL_homeurl) { + chavy.setdata(VAL_homeurl, KEY_homeurl) + chavy.log(`❕ ${cookieName} VAL_homeurl: ${VAL_homeurl}`) + } + if (VAL_homeheader) { + chavy.setdata(VAL_homeheader, KEY_homeheader) + chavy.log(`❕ ${cookieName} VAL_homeheader: ${VAL_homeheader}`) + } + chavy.msg(cookieName, `获取Cookie: 成功`, ``) + } catch (e) { + chavy.msg(cookieName, `获取Cookie: 失败`, e) + chavy.log(`❌ ${cookieName} 获取Cookie: 失败: ${e}`) + } +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} +chavy.done() diff --git a/mcdd/mcdd.js b/mcdd/mcdd.js new file mode 100644 index 000000000..8d88064fb --- /dev/null +++ b/mcdd/mcdd.js @@ -0,0 +1,234 @@ +const chavy = init() +const cookieName = '叮咚买菜' +const KEY_homeurl = 'chavy_home_url_mcdd' +const KEY_homeheader = 'chavy_home_header_mcdd' + +const signinfo = {} +let VAL_homeurl = chavy.getdata(KEY_homeurl) +let VAL_homeheader = chavy.getdata(KEY_homeheader) + +;(exec = async () => { + chavy.log(`🔔 ${cookieName} 开始签到`) + await signapp() + await getlottery() + if (signinfo.draw_num > 0) for (let i = 0; i < signinfo.draw_num; i++) await lotteryapp(i) + await browseapp() + await getinfo() + showmsg() +})() +.catch((e) => chavy.log(`❌ ${cookieName} 签到失败: ${e}`)) +.finally(() => chavy.done()) + +function getinfo() { + return new Promise((resolve, reject) => { + const url = { url: VAL_homeurl, headers: JSON.parse(VAL_homeheader) } + chavy.get(url, (error, response, data) => { + try { + signinfo.info = JSON.parse(data) + if (typeof signinfo.is_today_sign === 'undefined') signinfo.is_today_sign = signinfo.info.data.user_sign.is_today_sign + resolve() + } catch (e) { + chavy.msg(cookieName, `获取信息: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} getinfo - 获取信息失败: ${e}`) + chavy.log(`❌ ${cookieName} getinfo - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function signapp() { + return new Promise((resolve, reject) => { + const url = { url: `https://ddxq.mobi/api/v2/user/signin/`, headers: JSON.parse(VAL_homeheader) } + url.headers['Accept'] = '*/*' + url.headers['Origin'] = 'https://activity.m.ddxq.mobi' + url.headers['Accept-Encoding'] = 'gzip, deflate, br' + url.headers['Content-Type'] = 'application/x-www-form-urlencoded' + url.headers['Host'] = 'ddxq.mobi' + url.headers['Connection'] = 'keep-alive' + url.headers['Referer'] = 'https://activity.m.ddxq.mobi/' + url.headers['Content-Length'] = '129' + url.headers['Accept-Language'] = 'zh-cn' + url.body = VAL_homeurl.split('?')[1] + chavy.post(url, (error, response, data) => { + try { + signinfo.signapp = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `签到结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} signapp - 签到失败: ${e}`) + chavy.log(`❌ ${cookieName} signapp - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function getlottery() { + return new Promise((resolve, reject) => { + const getlotteryurl = `https://maicai.api.ddxq.mobi/lottery/index?${VAL_homeurl.split('?')[1]}&event_id=5dbacee44df3e3ed628ce721` + const url = { url: getlotteryurl, headers: JSON.parse(VAL_homeheader) } + url.headers['Origin'] = 'https://activity.m.ddxq.mobi' + url.headers['Connection'] = 'keep-alive' + url.headers['Accept'] = '*/*' + url.headers['Referer'] = 'https://activity.m.ddxq.mobi/' + url.headers['Host'] = 'maicai.api.ddxq.mobi' + url.headers['Accept-Encoding'] = 'gzip, deflate, br' + url.headers['Accept-Language'] = 'zh-cn' + chavy.get(url, (error, response, data) => { + try { + signinfo.lotteryinfo = JSON.parse(data) + if (typeof signinfo.draw_num === 'undefined') signinfo.draw_num = signinfo.lotteryinfo.data.draw_num + resolve() + } catch (e) { + chavy.msg(cookieName, `获取抽奖: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} getlottery - 获取抽奖失败: ${e}`) + chavy.log(`❌ ${cookieName} getlottery - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function lotteryapp(cnt) { + return new Promise((resolve, reject) => { + setTimeout(() => { + const lotteryappurl = `https://maicai.api.ddxq.mobi/lottery/draw?${VAL_homeurl.split('?')[1]}&event_id=5dbacee44df3e3ed628ce721` + const url = { url: lotteryappurl, headers: JSON.parse(VAL_homeheader) } + url.headers['Origin'] = 'https://activity.m.ddxq.mobi' + url.headers['Connection'] = 'keep-alive' + url.headers['Accept'] = '*/*' + url.headers['Referer'] = 'https://activity.m.ddxq.mobi/' + url.headers['Host'] = 'maicai.api.ddxq.mobi' + url.headers['Accept-Encoding'] = 'gzip, deflate, br' + url.headers['Accept-Language'] = 'zh-cn' + chavy.get(url, (error, response, data) => { + try { + if (!signinfo.lottery) signinfo.lottery = [] + signinfo.lottery.push(JSON.parse(data)) + resolve() + } catch (e) { + chavy.msg(cookieName, `获取抽奖: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} lotteryapp - 获取抽奖失败: ${e}`) + chavy.log(`❌ ${cookieName} lotteryapp - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }, cnt * 5000) + }) +} + +function browseapp() { + return new Promise((resolve, reject) => { + const browseappurl = `https://maicai.api.ddxq.mobi/point/completeTask` + const url = { url: browseappurl, headers: JSON.parse(VAL_homeheader) } + url.body = `${VAL_homeurl.split('?')[1]}&station_id=5500fe01916edfe0738b4e43&task_type=21` + url.headers['Accept'] = '*/*' + url.headers['Origin'] = 'https://maicai.m.ddxq.mobi' + url.headers['Accept-Encoding'] = 'gzip, deflate, br' + url.headers['Content-Type'] = 'application/x-www-form-urlencoded' + url.headers['Host'] = 'maicai.api.ddxq.mobi' + url.headers['Connection'] = 'keep-alive' + url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 xzone/9.7.5 station_id/5500fe01916edfe0738b4e43' + url.headers['Referer'] = 'https://maicai.m.ddxq.mobi/?v=1.30.0' + url.headers['Content-Length'] = '152' + url.headers['Accept-Language'] = 'zh-cn' + chavy.post(url, (error, response, data) => { + try { + signinfo.browseapp = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `浏览商品: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} browseapp - 浏览商品失败: ${e}`) + chavy.log(`❌ ${cookieName} browseapp - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function showmsg() { + let subTitle, detail + if (signinfo.signapp.code == 0) { + if (signinfo.is_today_sign === false) subTitle = '签到: 成功' + else subTitle = '签到: 重复' + detail = `积分: ${signinfo.info.data.point_num} (+${signinfo.signapp.data.point}), 价值: ${signinfo.info.data.point_money}` + } else { + subTitle = '签到: 失败' + detail = `编码: ${signinfo.signapp.code}, 说明: ${signinfo.signapp.message}` + chavy.log(`❌ ${cookieName} showmsg - 签到失败: ${JSON.stringify(signinfo.signapp)}`) + } + + if (signinfo.lotteryinfo.code == 0) { + if (signinfo.draw_num == 0) subTitle += '; 抽奖: 已转' + else subTitle += `; 抽奖: ${signinfo.draw_num}次` + } else { + subTitle = '抽奖: 失败' + detail = `编码: ${signinfo.lotteryinfo.code}, 说明: ${signinfo.lotteryinfo.message}` + chavy.log(`❌ ${cookieName} showmsg - 抽奖失败: ${JSON.stringify(signinfo.lotteryinfo)}`) + } + + if (signinfo.browseapp.code == 0) { + subTitle += '; 浏览任务: 成功' + } else if (signinfo.browseapp.code == -1) { + subTitle += '; 浏览任务: 重复' + } else { + subTitle = '浏览任务: 失败' + detail = `编码: ${signinfo.browseapp.code}, 说明: ${signinfo.browseapp.msg}` + chavy.log(`❌ ${cookieName} showmsg - 浏览任务失败: ${JSON.stringify(signinfo.browseapp)}`) + } + + if (signinfo.lottery) { + detail += '\n查看抽奖详情\n' + for (let i = 0; i < signinfo.lottery.length; i++) { + if (signinfo.lottery[i].code == 0) detail += `\n抽奖 (${i + 1}): ${signinfo.lottery[i].data.prize.title}` + else detail += `\n抽奖 (${i + 1}): ${signinfo.lottery[i].msg}` + } + } + + chavy.msg(cookieName, subTitle, detail) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/meituan/README.md b/meituan/README.md index 18cf2a319..bab5ffbe4 100644 --- a/meituan/README.md +++ b/meituan/README.md @@ -8,7 +8,7 @@ ```properties [MITM] -i.meituan.com +hostname = i.meituan.com [Script] http-request ^https:\/\/i.meituan.com\/evolve\/signin\/signpost\/ script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/meituan/meituan.cookie.js, requires-body=true @@ -39,10 +39,9 @@ i.meituan.com 2. 再配置重写规则: - Surge: 把两条远程脚本放到`[Script]` - QuanX: 把`meituan.cookie.js`和`meituan.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) -3. 打开 APP , 进入签到页面, 系统提示: `获取刷新链接: 成功` -4. 然后手动签到 1 次, 系统提示: `获取Cookie: 成功` -5. 把获取 Cookie 的脚本注释掉 -6. 运行一次脚本, 如果提示重复签到, 那就算成功了! +3. 打开 APP , 然后手动签到 1 次, 系统提示: `获取Cookie: 成功` (`首页` > `红包签到`) +4. 把获取 Cookie 的脚本注释掉 +5. 运行一次脚本, 如果提示重复签到, 那就算成功了! > 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. diff --git a/neteasemusic/README.md b/neteasemusic/README.md index 2a0ee3afc..197b5baec 100644 --- a/neteasemusic/README.md +++ b/neteasemusic/README.md @@ -1,24 +1,39 @@ # 网易云音乐 -## 配置 +> 2020.6.15 +> +> 1. 增加自动重试机制 (BoxJs 可调整次数及间隔) +> 2. 增加等级显示 (需按新方式获取会话) + +## 配置 (Surge & Loon) ```properties [MITM] music.163.com [Script] -http-request ^https?:\/\/music\.163\.com\/?.? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasemusic/neteasemusic.cookie.js +http-request ^https:\/\/music.163.com\/weapi\/user\/level script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasemusic/neteasemusic.cookie.js,requires-body=true cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasemusic/neteasemusic.js ``` +## 配置 (QuanX) + +```properties +[MITM] +music.163.com + +[rewrite_local] +^https:\/\/music.163.com\/weapi\/user\/level url script-request-body neteasemusic.cookie.js + +[task_local] +1 0 * * * neteasemusic.js +``` + ## 说明 -1. 先把`music.163.com`加到`[MITM]` -2. 再把两条远程脚本放到`[Script]` -3. 浏览器访问并登录: https://music.163.com/m/login -4. 登录成功后再用浏览器访问一下: https://music.163.com/ -5. `Surge`提示: `Cookie [网易云音乐] 写入成功` -6. 最后就可以把第 1 条脚本注释掉了 +1. 先登录: <https://music.163.com/m/login> +2. 再访问: <https://music.163.com/#/user/level> +3. 提示: `获取会话: 成功!` > 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. diff --git a/neteasemusic/neteasemusic.cookie.js b/neteasemusic/neteasemusic.cookie.js index 5c5791656..90a36c86f 100644 --- a/neteasemusic/neteasemusic.cookie.js +++ b/neteasemusic/neteasemusic.cookie.js @@ -1,15 +1,27 @@ -const cookieName = '网易云音乐' -const cookieKey = 'chavy_cookie_neteasemusic' -const cookieVal = $request.headers['Cookie'] +const $ = new Env('网易云音乐') -if (cookieVal) { - let cookie = $persistentStore.write(cookieVal, cookieKey) - if (cookie) { - let msg = `${cookieName}` - $notification.post(msg, 'Cookie写入成功', '详见日志') - console.log(msg) - console.log(cookieVal) +!(async () => { + $.log('', `🔔 ${$.name}, 获取会话: 开始!`, '') + const session = {} + session.url = $request.url + session.body = $request.body + session.headers = $request.headers + delete session.headers['Content-Length'] + $.log('', `url: ${session.url}`, `body: ${session.body}`, `headers: ${JSON.stringify(session.headers)}`) + if ($.setdata(JSON.stringify(session), 'chavy_cookie_neteasemusic')) { + $.subt = '获取会话: 成功!' + } else { + $.subt = '获取会话: 失败!' } -} +})() + .catch((e) => { + $.subt = '获取会话: 失败!' + $.desc = `原因: ${e}` + $.log(`❌ ${$.name}, 获取会话: 失败! 原因: ${e}!`) + }) + .finally(() => { + $.msg($.name, $.subt, $.desc), $.log('', `🔔 ${$.name}, 获取会话: 结束!`, ''), $.done() + }) -$done({}) +// prettier-ignore +function Env(s){this.name=s,this.data=null,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.isNode=(()=>"undefined"!=typeof module&&!!module.exports),this.log=((...s)=>{this.logs=[...this.logs,...s],s?console.log(s.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((s=this.name,t="",i="")=>{this.isSurge()&&$notification.post(s,t,i),this.isQuanX()&&$notify(s,t,i);const e=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];s&&e.push(s),t&&e.push(t),i&&e.push(i),console.log(e.join("\n"))}),this.getdata=(s=>{if(this.isSurge())return $persistentStore.read(s);if(this.isQuanX())return $prefs.valueForKey(s);if(this.isNode()){const t="box.dat";return this.fs=this.fs?this.fs:require("fs"),this.fs.existsSync(t)?(this.data=JSON.parse(this.fs.readFileSync(t)),this.data[s]):null}}),this.setdata=((s,t)=>{if(this.isSurge())return $persistentStore.write(s,t);if(this.isQuanX())return $prefs.setValueForKey(s,t);if(this.isNode()){const i="box.dat";return this.fs=this.fs?this.fs:require("fs"),!!this.fs.existsSync(i)&&(this.data=JSON.parse(this.fs.readFileSync(i)),this.data[t]=s,this.fs.writeFileSync(i,JSON.stringify(this.data)),!0)}}),this.wait=((s,t=s)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(t-s+1)+s))),this.get=((s,t)=>this.send(s,"GET",t)),this.post=((s,t)=>this.send(s,"POST",t)),this.send=((s,t,i)=>{if(this.isSurge()){const e="POST"==t?$httpClient.post:$httpClient.get;e(s,(s,t,e)=>{t&&(t.body=e,t.statusCode=t.status),i(s,t,e)})}this.isQuanX()&&(s.method=t,$task.fetch(s).then(s=>{s.status=s.statusCode,i(null,s,s.body)},s=>i(s.error,s,s))),this.isNode()&&(this.request=this.request?this.request:require("request"),s.method=t,s.gzip=!0,this.request(s,(s,t,e)=>{t&&(t.status=t.statusCode),i(null,t,e)}))}),this.done=((s={})=>this.isNode()?null:$done(s))} diff --git a/neteasemusic/neteasemusic.js b/neteasemusic/neteasemusic.js index 8abf83a0a..075aa1f81 100644 --- a/neteasemusic/neteasemusic.js +++ b/neteasemusic/neteasemusic.js @@ -1,77 +1,102 @@ -const cookieName = '网易云音乐' -const cookieKey = 'chavy_cookie_neteasemusic' -const cookieVal = $persistentStore.read(cookieKey) +const $ = new Env('网易云音乐') +$.VAL_session = $.getdata('chavy_cookie_neteasemusic') +$.CFG_retryCnt = ($.getdata('CFG_neteasemusic_retryCnt') || '10') * 1 +$.CFG_retryInterval = ($.getdata('CFG_neteasemusic_retryInterval') || '500') * 1 -const pc = `http://music.163.com/api/point/dailyTask?type=1` -const mobile = `http://music.163.com/api/point/dailyTask?type=0` - -function sign() { - let url = { - url: null, - headers: { - Cookie: cookieVal - } - } - - let signinfo = {} - - url.url = pc - $httpClient.post(url, (error, response, data) => { - let result = JSON.parse(data) - signinfo.pc = { - title: `网易云音乐(PC)`, - success: result.code == 200 || result.code == -2 ? true : false, - skiped: result.code == -2 ? true : false, - resultCode: result.code, - resultMsg: result.msg - } - console.log(`开始签到: ${signinfo.pc.title}, 编码: ${result.code}, 原因: ${result.msg}`) +!(async () => { + $.log('', `🔔 ${$.name}, 开始!`, '') + init() + await signweb() + await signapp() + await getInfo() + await showmsg() +})() + .catch((e) => { + $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') }) - - url.url = mobile - $httpClient.post(url, (error, response, data) => { - let result = JSON.parse(data) - signinfo.app = { - title: `网易云音乐(APP)`, - success: result.code == 200 || result.code == -2 ? true : false, - skiped: result.code == -2 ? true : false, - resultCode: result.code, - resultMsg: result.msg - } - console.log(`开始签到: ${signinfo.app.title}, 编码: ${result.code}, 原因: ${result.msg}`) + .finally(() => { + $.msg($.name, $.subt, $.desc), $.log('', `🔔 ${$.name}, 结束!`, ''), $.done() }) - check(signinfo) + +function init() { + $.isNewCookie = /https:\/\/music.163.com\/weapi\/user\/level/.test($.VAL_session) + $.Cookie = $.isNewCookie ? JSON.parse($.VAL_session).headers.Cookie : $.VAL_session } -function check(signinfo, checkms = 0) { - if (signinfo.pc && signinfo.app) { - log(signinfo) - $done({}) - } else { - if (checkms > 5000) { - $done({}) - } else { - setTimeout(() => check(signinfo, checkms + 100), 100) - } +async function signweb() { + for (let signIdx = 0; signIdx < $.CFG_retryCnt; signIdx++) { + await new Promise((resove) => { + const url = { url: `http://music.163.com/api/point/dailyTask?type=1`, headers: {} } + url.headers['Cookie'] = $.Cookie + url.headers['Host'] = 'music.163.com' + url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15' + $.get(url, (error, response, data) => { + try { + $.isWebSuc = JSON.parse(data).code === -2 + $.log(`[Web] 第 ${signIdx + 1} 次: ${data}`) + } catch (e) { + $.isWebSuc = false + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, '') + } finally { + resove() + } + }) + }) + await new Promise($.wait($.CFG_retryInterval)) + if ($.isWebSuc) break } } -function log(signinfo) { - let title = `${cookieName}` - let subTitle = `` - let detail = `今日共签: ${signinfo.signedCnt}, 本次成功: ${signinfo.successCnt}, 本次失败: ${signinfo.failedCnt}` - - if (signinfo.pc.success && signinfo.app.success) { - subTitle = `签到结果: 全部成功` - detail = `PC: ${signinfo.pc.success ? '成功' : '失败'}, APP: ${signinfo.app.success ? '成功' : '失败'}` - } else if (!signinfo.pc.success && !signinfo.app.success) { - subTitle = `签到结果: 全部失败` - detail = `PC: ${signinfo.pc.success ? '成功' : '失败'}, APP: ${signinfo.app.success ? '成功' : '失败'}, 详见日志!` - } else { - subTitle = `` - detail = `PC: ${signinfo.pc.success ? '成功' : '失败'}, APP: ${signinfo.app.success ? '成功' : '失败'}, 详见日志!` +async function signapp() { + for (let signIdx = 0; signIdx < $.CFG_retryCnt; signIdx++) { + await new Promise((resove) => { + const url = { url: `http://music.163.com/api/point/dailyTask?type=0`, headers: {} } + url.headers['Cookie'] = $.Cookie + url.headers['Host'] = 'music.163.com' + url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1' + $.get(url, (error, response, data) => { + try { + $.isAppSuc = JSON.parse(data).code === -2 + $.log(`[App] 第 ${signIdx + 1} 次: ${data}`) + } catch (e) { + $.isAppSuc = false + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, '') + } finally { + resove() + } + }) + }) + await new Promise($.wait($.CFG_retryInterval)) + if ($.isAppSuc) break } - $notification.post(title, subTitle, detail) } -sign() +function getInfo() { + if (!$.isNewCookie) return + return new Promise((resove) => { + $.post(JSON.parse($.VAL_session), (error, response, data) => { + try { + $.userInfo = JSON.parse(data) + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, '') + } finally { + resove() + } + }) + }) +} + +function showmsg() { + return new Promise((resove) => { + $.subt = $.isWebSuc ? 'PC: 成功' : 'PC: 失败' + $.subt += $.isAppSuc ? ', APP: 成功' : ', APP: 失败' + if ($.isNewCookie && $.userInfo) { + $.desc = `等级: ${$.userInfo.data.level}, 听歌: ${$.userInfo.data.nowPlayCount} => ${$.userInfo.data.nextPlayCount} 升级 (首)` + $.desc = $.userInfo.data.level === 10 ? `等级: ${$.userInfo.data.level}, 你的等级已爆表!` : $.desc + } + resove() + }) +} + +// prettier-ignore +function Env(s){this.name=s,this.data=null,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.isNode=(()=>"undefined"!=typeof module&&!!module.exports),this.log=((...s)=>{this.logs=[...this.logs,...s],s?console.log(s.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((s=this.name,t="",i="")=>{this.isSurge()&&$notification.post(s,t,i),this.isQuanX()&&$notify(s,t,i);const e=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];s&&e.push(s),t&&e.push(t),i&&e.push(i),console.log(e.join("\n"))}),this.getdata=(s=>{if(this.isSurge())return $persistentStore.read(s);if(this.isQuanX())return $prefs.valueForKey(s);if(this.isNode()){const t="box.dat";return this.fs=this.fs?this.fs:require("fs"),this.fs.existsSync(t)?(this.data=JSON.parse(this.fs.readFileSync(t)),this.data[s]):null}}),this.setdata=((s,t)=>{if(this.isSurge())return $persistentStore.write(s,t);if(this.isQuanX())return $prefs.setValueForKey(s,t);if(this.isNode()){const i="box.dat";return this.fs=this.fs?this.fs:require("fs"),!!this.fs.existsSync(i)&&(this.data=JSON.parse(this.fs.readFileSync(i)),this.data[t]=s,this.fs.writeFileSync(i,JSON.stringify(this.data)),!0)}}),this.wait=((s,t=s)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(t-s+1)+s))),this.get=((s,t)=>this.send(s,"GET",t)),this.post=((s,t)=>this.send(s,"POST",t)),this.send=((s,t,i)=>{if(this.isSurge()){const e="POST"==t?$httpClient.post:$httpClient.get;e(s,(s,t,e)=>{t&&(t.body=e,t.statusCode=t.status),i(s,t,e)})}this.isQuanX()&&(s.method=t,$task.fetch(s).then(s=>{s.status=s.statusCode,i(null,s,s.body)},s=>i(s.error,s,s))),this.isNode()&&(this.request=this.request?this.request:require("request"),s.method=t,s.gzip=!0,this.request(s,(s,t,e)=>{t&&(t.status=t.statusCode),i(null,t,e)}))}),this.done=((s={})=>this.isNode()?null:$done(s))} diff --git a/neteasemusic/quanx/neteasemusic.cookie.js b/neteasemusic/quanx/neteasemusic.cookie.js index 7ac1c21f5..a61299f59 100644 --- a/neteasemusic/quanx/neteasemusic.cookie.js +++ b/neteasemusic/quanx/neteasemusic.cookie.js @@ -1,15 +1,27 @@ -const cookieName = '网易云音乐' -const cookieKey = 'chavy_cookie_neteasemusic' -const cookieVal = $request.headers['Cookie'] +const $ = new Env('网易云音乐') -if (cookieVal) { - let cookie = $prefs.setValueForKey(cookieVal, cookieKey) - if (cookie) { - let msg = `${cookieName}` - $notify(msg, 'Cookie写入成功', '详见日志') - console.log(msg) - console.log(cookieVal) +!(async () => { + $.log('', `🔔 ${$.name}, 获取会话: 开始!`, '') + const session = {} + session.url = $request.url + session.body = $request.body + session.headers = $request.headers + delete session.headers['Content-Length'] + $.log('', `url: ${session.url}`, `body: ${session.body}`, `headers: ${JSON.stringify(session.headers)}`) + if ($.setdata(JSON.stringify(session), 'chavy_cookie_neteasemusic')) { + $.subt = '获取会话: 成功!' + } else { + $.subt = '获取会话: 失败!' } -} +})() + .catch((e) => { + $.subt = '获取会话: 失败!' + $.desc = `原因: ${e}` + $.log(`❌ ${$.name}, 获取会话: 失败! 原因: ${e}!`) + }) + .finally(() => { + $.msg($.name, $.subt, $.desc), $.log('', `🔔 ${$.name}, 获取会话: 结束!`, ''), $.done() + }) -$done({}) +// prettier-ignore +function Env(t){this.name=t,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.log=((...t)=>{this.logs=[...this.logs,...t],t?console.log(t.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((t=this.name,s="",i="")=>{this.isSurge()&&$notification.post(t,s,i),this.isQuanX()&&$notify(t,s,i);const e=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t&&e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n"))}),this.getdata=(t=>this.isSurge()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):void 0),this.setdata=((t,s)=>this.isSurge()?$persistentStore.write(t,s):this.isQuanX()?$prefs.setValueForKey(t,s):void 0),this.get=((t,s)=>this.send(t,"GET",s)),this.wait=((t,s=t)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(s-t+1)+t))),this.post=((t,s)=>this.send(t,"POST",s)),this.send=((t,s,i)=>{if(this.isSurge()){const e="POST"==s?$httpClient.post:$httpClient.get;e(t,(t,s,e)=>{s&&(s.body=e,s.statusCode=s.status),i(t,s,e)})}this.isQuanX()&&(t.method=s,$task.fetch(t).then(t=>{t.status=t.statusCode,i(null,t,t.body)},t=>i(t.error,t,t)))}),this.done=((t={})=>$done(t))} diff --git a/neteasemusic/quanx/neteasemusic.js b/neteasemusic/quanx/neteasemusic.js index d7b7f9807..857a6c449 100644 --- a/neteasemusic/quanx/neteasemusic.js +++ b/neteasemusic/quanx/neteasemusic.js @@ -1,79 +1,102 @@ -const cookieName = '网易云音乐' -const cookieKey = 'chavy_cookie_neteasemusic' -const cookieVal = $prefs.valueForKey(cookieKey) +const $ = new Env('网易云音乐') +$.VAL_session = $.getdata('chavy_cookie_neteasemusic') +$.CFG_retryCnt = ($.getdata('CFG_neteasemusic_retryCnt') || '10') * 1 +$.CFG_retryInterval = ($.getdata('CFG_neteasemusic_retryInterval') || '500') * 1 -const pc = `http://music.163.com/api/point/dailyTask?type=1` -const mobile = `http://music.163.com/api/point/dailyTask?type=0` - -function sign() { - let url = { - url: null, - headers: { - Cookie: cookieVal - } - } - - let signinfo = {} - - url.url = pc - $task.fetch(url).then((response) => { - let data = response.body - let result = JSON.parse(data) - signinfo.pc = { - title: `网易云音乐(PC)`, - success: result.code == 200 || result.code == -2 ? true : false, - skiped: result.code == -2 ? true : false, - resultCode: result.code, - resultMsg: result.msg - } - console.log(`开始签到: ${signinfo.pc.title}, 编码: ${result.code}, 原因: ${result.msg}`) +!(async () => { + $.log('', `🔔 ${$.name}, 开始!`, '') + init() + await signweb() + await signapp() + await getInfo() + await showmsg() +})() + .catch((e) => { + $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') }) - - url.url = mobile - $task.fetch(url).then((response) => { - let data = response.body - let result = JSON.parse(data) - signinfo.app = { - title: `网易云音乐(APP)`, - success: result.code == 200 || result.code == -2 ? true : false, - skiped: result.code == -2 ? true : false, - resultCode: result.code, - resultMsg: result.msg - } - console.log(`开始签到: ${signinfo.app.title}, 编码: ${result.code}, 原因: ${result.msg}`) + .finally(() => { + $.msg($.name, $.subt, $.desc), $.log('', `🔔 ${$.name}, 结束!`, ''), $.done() }) - check(signinfo) + +function init() { + $.isNewCookie = /https:\/\/music.163.com\/weapi\/user\/level/.test($.VAL_session) + $.Cookie = $.isNewCookie ? JSON.parse($.VAL_session).headers.Cookie : $.VAL_session } -function check(signinfo, checkms = 0) { - if (signinfo.pc && signinfo.app) { - log(signinfo) - $done({}) - } else { - if (checkms > 5000) { - $done({}) - } else { - setTimeout(() => check(signinfo, checkms + 100), 100) - } +async function signweb() { + for (let signIdx = 0; signIdx < $.CFG_retryCnt; signIdx++) { + await new Promise((resove) => { + const url = { url: `http://music.163.com/api/point/dailyTask?type=1`, headers: {} } + url.headers['Cookie'] = $.Cookie + url.headers['Host'] = 'music.163.com' + url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15' + $.get(url, (error, response, data) => { + try { + $.isWebSuc = JSON.parse(data).code === -2 + $.log(`[Web] 第 ${signIdx + 1} 次: ${data}`) + } catch (e) { + $.isWebSuc = false + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, '') + } finally { + resove() + } + }) + }) + await new Promise($.wait($.CFG_retryInterval)) + if ($.isWebSuc) break } } -function log(signinfo) { - let title = `${cookieName}` - let subTitle = `` - let detail = `今日共签: ${signinfo.signedCnt}, 本次成功: ${signinfo.successCnt}, 本次失败: ${signinfo.failedCnt}` - - if (signinfo.pc.success && signinfo.app.success) { - subTitle = `签到结果: 全部成功` - detail = `PC: ${signinfo.pc.success ? '成功' : '失败'}, APP: ${signinfo.app.success ? '成功' : '失败'}` - } else if (!signinfo.pc.success && !signinfo.app.success) { - subTitle = `签到结果: 全部失败` - detail = `PC: ${signinfo.pc.success ? '成功' : '失败'}, APP: ${signinfo.app.success ? '成功' : '失败'}, 详见日志!` - } else { - subTitle = `` - detail = `PC: ${signinfo.pc.success ? '成功' : '失败'}, APP: ${signinfo.app.success ? '成功' : '失败'}, 详见日志!` +async function signapp() { + for (let signIdx = 0; signIdx < $.CFG_retryCnt; signIdx++) { + await new Promise((resove) => { + const url = { url: `http://music.163.com/api/point/dailyTask?type=0`, headers: {} } + url.headers['Cookie'] = $.Cookie + url.headers['Host'] = 'music.163.com' + url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1' + $.get(url, (error, response, data) => { + try { + $.isAppSuc = JSON.parse(data).code === -2 + $.log(`[App] 第 ${signIdx + 1} 次: ${data}`) + } catch (e) { + $.isAppSuc = false + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, '') + } finally { + resove() + } + }) + }) + await new Promise($.wait($.CFG_retryInterval)) + if ($.isAppSuc) break } - $notify(title, subTitle, detail) } -sign() +function getInfo() { + if (!$.isNewCookie) return + return new Promise((resove) => { + $.post(JSON.parse($.VAL_session), (error, response, data) => { + try { + $.userInfo = JSON.parse(data) + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, '') + } finally { + resove() + } + }) + }) +} + +function showmsg() { + return new Promise((resove) => { + $.subt = $.isWebSuc ? 'PC: 成功' : 'PC: 失败' + $.subt += $.isAppSuc ? ', APP: 成功' : ', APP: 失败' + if ($.isNewCookie && $.userInfo) { + $.desc = `等级: ${$.userInfo.data.level}, 听歌: ${$.userInfo.data.nowPlayCount} => ${$.userInfo.data.nextPlayCount} 升级 (首)` + $.desc = $.userInfo.data.level === 10 ? `等级: ${$.userInfo.data.level}, 你的等级已爆表!` : $.desc + } + resove() + }) +} + +// prettier-ignore +function Env(t){this.name=t,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.log=((...t)=>{this.logs=[...this.logs,...t],t?console.log(t.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((t=this.name,s="",i="")=>{this.isSurge()&&$notification.post(t,s,i),this.isQuanX()&&$notify(t,s,i);const e=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t&&e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n"))}),this.getdata=(t=>this.isSurge()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):void 0),this.setdata=((t,s)=>this.isSurge()?$persistentStore.write(t,s):this.isQuanX()?$prefs.setValueForKey(t,s):void 0),this.get=((t,s)=>this.send(t,"GET",s)),this.wait=((t,s=t)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(s-t+1)+t))),this.post=((t,s)=>this.send(t,"POST",s)),this.send=((t,s,i)=>{if(this.isSurge()){const e="POST"==s?$httpClient.post:$httpClient.get;e(t,(t,s,e)=>{s&&(s.body=e,s.statusCode=s.status),i(t,s,e)})}this.isQuanX()&&(t.method=s,$task.fetch(t).then(t=>{t.status=t.statusCode,i(null,t,t.body)},t=>i(t.error,t,t)))}),this.done=((t={})=>$done(t))} diff --git a/neteasenews/README.md b/neteasenews/README.md index 980e75158..c97bb183c 100644 --- a/neteasenews/README.md +++ b/neteasenews/README.md @@ -13,7 +13,7 @@ *.m.163.com [Script] -http-request ^https:\/\/c\.m\.163\.com\/uc\/api\/sign\/v2\/commit script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.cookie.js,requires-body=true +http-request ^https:\/\/(.*?)c\.m\.163\.com\/uc\/api\/sign\/v3\/commit script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.cookie.js,requires-body=true cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.js ``` @@ -24,8 +24,7 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr *.m.163.com [rewrite_local] -# 195及以后版本 -^https:\/\/c\.m\.163\.com\/uc\/api\/sign\/v2\/commit url script-request-body neteasenews.cookie.js +^https:\/\/(.*?)c\.m\.163\.com\/uc\/api\/sign\/v3\/commit url script-request-body neteasenews.cookie.js [task_local] 1 0 * * * neteasenews.js diff --git a/neteasenews/README.old.md b/neteasenews/README.old.md deleted file mode 100644 index 028e21499..000000000 --- a/neteasenews/README.old.md +++ /dev/null @@ -1,127 +0,0 @@ -# 网易新闻 - -> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 - -> 由于 QuanX 不支持获取 `$request.body`, 所以 QuanX 用户需要自行抓包获取 body 参数 - -> Surge 可以由脚本自自动获取 Cookie 及 Body 参数 - -> QuanX 需要自己抓包签到请求中的 Body 参数, 详见: [抓包步骤](https://github.com/chavyleung/scripts/tree/master/neteasenews/抓包步骤) - -## 配置 (Surge) - -```properties -[MITM] -*.m.163.com - -[Script] -http-request ^https:\/\/c\.m\.163\.com\/uc\/api\/sign\/v2\/commit script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.cookie.js,requires-body=true -cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.js -``` - -## 配置 (QuanX) - -```properties -[MITM] -*.m.163.com - -[rewrite_local] -# 189及以前版本 -^https:\/\/user\.m\.163.com\/api\/v1\/commons\/fav\/topic\/allList url script-response-body neteasenews.cookie.js -# 190及以后版本 -^https:\/\/user\.m\.163.com\/api\/v1\/commons\/fav\/topic\/allList url script-request-header neteasenews.cookie.js - -[task_local] -1 0 * * * neteasenews.js -``` - -## 说明 (Surge) - -1. 先把`*.m.163.com`加到`[MITM]` -2. 把两条远程脚本放到`[Script]` -3. 打开 APP 然后手动签到 1 次: -4. 系统提示: `获取Cookie: 成功`, `获取Body: 成功` -5. 最后就可以把第 1 条脚本注释掉了 -6. 运行一次脚本, 如果提示重复签到, 那就算成功了! - -## 说明 (QuanX) - -> 由于 QuanX 目前不支持通过脚本获取\$request.body, 所以该参数需要自行抓包获取 - -1. 先把`*.m.163.com`加到`[MITM]` -2. 把两条脚本放到 QuanX 的 Scripts 目录 -3. 获取 Cookie: - - 打开 网易新闻, 系统提示: `获取Cookie: 成功` -4. 获取 body (抓包): - - - 打开 QuanX 的 `调试开关` (确保 `MITM` 已正确配置) - - 打开 网易新闻 手动签到 1 次 - - 进入 QuanX 的 `调试记录` (在`调试开关` 下面) - - 进入日期最新的抓包记录 - - 搜索关键字`commit`, 应该会搜索出 1 条记录: `https://c.m.163.com/uc/api/sign/v2/commit` - - 点进搜索出来的那条抓包记录: 请求体>文本查看 (把这里面的所有内容复制起来) - - 手动编辑 `neteasenews.cookie.js` 第 6 行: ` let bodyVal = `` ` - - 把刚才复制的文本放到过时去, 如: - - ```js - let bodyVal = `trashId=%7B%22id_ver%22%3A%22IOS_1.2.1%22...` - ``` - - 最后杀掉 `网易新闻` 重新打开获取一下 cookie - - 系统提示: `获取Cookie: 成功` - - 系统提示: `获取Body: 成功` - -5. 最后就可以把第 1 条脚本注释掉了 -6. 运行一次脚本, 如果提示重复签到, 那就算成功了! - -> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. - -> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. - -## 常见问题 - -1. 无法写入 Cookie - - - 检查 Surge 系统通知权限放开了没 - - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) - -2. 写入 Cookie 成功, 但签到不成功 - - - 看看是不是在登录前就写入 Cookie 了 - - 如果是,请确保在登录成功后,再尝试写入 Cookie - -3. 为什么有时成功有时失败 - - - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) - - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): - - - `Surge`配置: - - ```properties - # 没有什么是一顿饭解决不了的: - cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 - # 如果有,那就两顿: - cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 - # 实在不行,三顿也能接受: - cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 - - # 再粗暴点,直接: - cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 - ``` - - - `QuanX`配置: - - ```properties - [task_local] - 1 0 * * * xxx.js # 每天00:01执行一次 - 2 0 * * * xxx.js # 每天00:02执行一次 - 3 0 * * * xxx.js # 每天00:03执行一次 - - */60 * * * * xxx.js # 每60分执行一次 - ``` - -## 感谢 - -[@NobyDa](https://github.com/NobyDa) - -[@lhie1](https://github.com/lhie1) - -[@ConnersHua](https://github.com/ConnersHua) diff --git a/nfzm/nfzm.cookie.js b/nfzm/nfzm.cookie.js new file mode 100644 index 000000000..b3f0aec28 --- /dev/null +++ b/nfzm/nfzm.cookie.js @@ -0,0 +1,37 @@ +/** + * + * hostname = api.infzm.com + * + * # Surge + * Rewrite: nfzm = type=http-request,pattern=^http:\/\/api\.infzm\.com\/mobile\/pumpkin_task\/complete?,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/nfzm/nfzm.cookie.js,debug=true + * Tasks: nfzm-签到 = type=cron,cronexp=10 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/nfzm/nfzm.js,wake-system=true + * + * # QuanX + * ^http:\/\/api\.infzm\.com\/mobile\/pumpkin_task\/complete? url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/nfzm/nfzm.cookie.js + * 10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/nfzm/nfzm.js, tag=nfzm-签到 + * + * # Loon + * http-response ^http:\/\/api\.infzm\.com\/mobile\/pumpkin_task\/complete? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/nfzm/nfzm.cookie.js + * cron "10 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/nfzm/nfzm.js + * + * # 获取方式:点击签到获取 + */ + +const $ = new Env('南方周末') +$.url = 'senku_nfzm_url' + +!(async () => { + + url = $request.url + if (url&&$.setdata(url, $.url)) { + $.subt = `获取会话: 成功! (${$.url})` + } else { + $.subt = `获取会话: 失败! (${$.url})` + } + $.msg($.name, $.subt, $.desc) +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/nfzm/nfzm.js b/nfzm/nfzm.js new file mode 100644 index 000000000..ea33f406c --- /dev/null +++ b/nfzm/nfzm.js @@ -0,0 +1,67 @@ +const $ = new Env('南方周末') +$.url = 'senku_nfzm_url' +const urlVal = $.getdata($.url) +$.desc = [] + +!(async() => { + await sign(2) + await sign(2) + await sign(2) + await sign(6) + await sign(6) + await sign(1) + await showmsg() +})() +.catch((e) => $.logErr(e)) +.finally(() => $.done()) + +function sign(id) { + return new Promise((resolve) => { + const url = { + url: urlVal, + headers:{ + "User-Agent": "nfzm/7.1.4 (iPhone; iOS 14.0; Scale/3.00)", + "Host": "api.infzm.com", + "platform": "iOS" + }, + body : `task_id=${id}` + } + $.post(url, (err, resp, data) => { + try { + id == 1 ? $.sign = JSON.parse(data) : `` + id == 2 ? $.share = JSON.parse(data) : `` + id == 6 ? $.open = JSON.parse(data) : `` + + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function showmsg() { + return new Promise((resolve) => { + if ($.share) { + $.desc.push($.share.msg) + } + + if ($.open) { + $.desc.push($.open.msg) + } + + if ($.sign) { + $.subt = $.sign.msg + if ($.sign.data) { + console.log($.sign.data); + $.sign.data.pumpkin_point ? $.subt += `🎃:${$.sign.data.pumpkin_point}` : `` + } + } + $.msg($.name, $.subt, $.desc.join('\n')) + resolve() + }) +} + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/nio/README.md b/nio/README.md new file mode 100644 index 000000000..48efcfe26 --- /dev/null +++ b/nio/README.md @@ -0,0 +1,103 @@ +# 蔚来 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 +> 感谢[@danchaw](https://github.com/danchaw) PR +## 配置 (Surge) + +```properties +[MITM] +app.nio.com + +[Script] +http-request ^https:\/\/app\.nio\.com\/api\/1\/app\/daily_checkin script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/nio/nio.cookie.js +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/nio/nio.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +app.nio.com + +[rewrite_local] + +# [商店版] +^https:\/\/app\.nio\.com\/api\/1\/app\/daily_checkin url script-request-header nio.cookie.js + +# [TestFlight] +^https:\/\/app\.nio\.com\/api\/1\/app\/daily_checkin url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/nio/nio.cookie.js + +[task_local] + +# [商店版] +1 0 * * * nio.js + +# [TestFlight] +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/nio/nio.js +``` + +## 说明 + +1. 先把`app.nio.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`nio.cookie.js`和`nio.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP[蔚来](https://apps.apple.com/cn/app/%E8%94%9A%E6%9D%A5/id1116095987) 然后手动签到 1 次, 系统提示: `获取Cookie: 成功` +4. 最后就可以把第 1 条脚本注释掉了 +5. 运行一次脚本, 如果提示重复签到, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@danchaw](https://github.com/danchaw) diff --git a/nio/nio.cookie.js b/nio/nio.cookie.js new file mode 100644 index 000000000..7b82ddf65 --- /dev/null +++ b/nio/nio.cookie.js @@ -0,0 +1,67 @@ +const cookieName = '蔚来' +const signurlKey = 'signurl_nextevcar' +const signheaderKey = 'signheader_nextevcar' +const nextevcar = init() + +if ($request && $request.method == 'POST') { + const signurlVal = $request.url + const signheaderVal = JSON.stringify($request.headers) + + if (signurlVal) nextevcar.setdata(signurlVal, signurlKey) + if (signheaderVal) nextevcar.setdata(signheaderVal, signheaderKey) + nextevcar.msg(cookieName, `获取Cookie: 成功`, ``) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + put = (url, cb) => { + if (isSurge()) { + $httpClient.put(url, cb) + } + if (isQuanX()) { + url.method = 'PUT' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, put, done } +} +nextevcar.done() \ No newline at end of file diff --git a/nio/nio.js b/nio/nio.js new file mode 100644 index 000000000..7e49eebe8 --- /dev/null +++ b/nio/nio.js @@ -0,0 +1,83 @@ +const cookieName = '蔚来' +const signurlKey = 'signurl_nextevcar' +const signheaderKey = 'signheader_nextevcar' +const nextevcar = init() +const signurlVal = nextevcar.getdata(signurlKey) +const signheaderVal = nextevcar.getdata(signheaderKey) + +sign() + +function sign() { + const url = { url: signurlVal, headers: JSON.parse(signheaderVal) } + nextevcar.post(url, (error, response, data) => { + nextevcar.log(`${cookieName}, data: ${data}`) + const title = `${cookieName}` + let subTitle = '' + let detail = '' + const result = JSON.parse(data) + if (result.result_code == "success") { + subTitle = `签到结果: 成功` + detail = `签到积分: ${result.data.stats.credit_amount}, 连签: ${result.data.stats.continuous_checkin_days}天` + } else if (result.result_code == "credit_limit_reached") { + subTitle = `签到结果: 成功 (重复签到)` + } else { + subTitle = `签到结果: 失败` + detail = `说明: ${result.debug_msg}, 请重新获取` + } + nextevcar.msg(title, subTitle, detail) + nextevcar.done() + }) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + put = (url, cb) => { + if (isSurge()) { + $httpClient.put(url, cb) + } + if (isQuanX()) { + url.method = 'PUT' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, put, done } +} diff --git a/noteyoudao/noteyoudao.cookie.js b/noteyoudao/noteyoudao.cookie.js new file mode 100644 index 000000000..91b2cc5bf --- /dev/null +++ b/noteyoudao/noteyoudao.cookie.js @@ -0,0 +1,28 @@ +const $ = new Env('有道云笔记') + +!(async () => { + $.log('', `🔔 ${$.name}, 获取会话: 开始!`, '') + const VAL_url = $request.url + const VAL_body = $request.body + const VAL_headers = JSON.stringify($request.headers) + + $.log('', `❌ ${$.name}`, `url: ${$request.url}`, `body: ${$request.body}`, `headers: ${JSON.stringify($request.headers)}`, '') + + if (VAL_url && VAL_body && VAL_headers) { + $.setdata(VAL_url, 'chavy_signurl_noteyoudao') + $.setdata(VAL_body, 'chavy_signbody_noteyoudao') + $.setdata(VAL_headers, 'chavy_signheaders_noteyoudao') + $.subt = '获取会话: 成功 (签到)!' + } +})() + .catch((e) => { + $.subt = '获取会话: 失败!' + $.desc = `原因: ${e}` + $.log(`❌ ${$.name}, 获取会话: 失败! 原因: ${e}!`) + }) + .finally(() => { + $.msg($.name, $.subt, $.desc), $.log('', `🔔 ${$.name}, 获取会话: 结束!`, ''), $.done() + }) + +// prettier-ignore +function Env(t){this.name=t,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.log=((...t)=>{this.logs=[...this.logs,...t],t?console.log(t.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((t=this.name,s="",i="")=>{this.isSurge()&&$notification.post(t,s,i),this.isQuanX()&&$notify(t,s,i),this.log("==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="),t&&this.log(t),s&&this.log(s),i&&this.log(i)}),this.getdata=(t=>this.isSurge()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):void 0),this.setdata=((t,s)=>this.isSurge()?$persistentStore.write(t,s):this.isQuanX()?$prefs.setValueForKey(t,s):void 0),this.get=((t,s)=>this.send(t,"GET",s)),this.wait=((t,s=t)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(s-t+1)+t))),this.post=((t,s)=>this.send(t,"POST",s)),this.send=((t,s,i)=>{if(this.isSurge()){const e="POST"==s?$httpClient.post:$httpClient.get;e(t,(t,s,e)=>{s&&(s.body=e,s.statusCode=s.status),i(t,s,e)})}this.isQuanX()&&(t.method=s,$task.fetch(t).then(t=>{t.status=t.statusCode,i(null,t,t.body)},t=>i(t.error,t,t)))}),this.done=((t={})=>$done(t))} diff --git a/noteyoudao/noteyoudao.js b/noteyoudao/noteyoudao.js new file mode 100644 index 000000000..72c42481e --- /dev/null +++ b/noteyoudao/noteyoudao.js @@ -0,0 +1,82 @@ +const $ = new Env('有道云笔记') +$.VAL_login = $.getdata('chavy_login_noteyoudao') +$.VAL_sign_url = $.getdata('chavy_signurl_noteyoudao') +$.VAL_sign_body = $.getdata('chavy_signbody_noteyoudao') +$.VAL_sign_headers = $.getdata('chavy_signheaders_noteyoudao') + +!(async () => { + await loginapp() + await signinapp() + await logindaily() + await showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +function loginapp() { + return new Promise((resove) => { + const { url, body, headers } = JSON.parse($.VAL_login) + $.post({ url, body, headers: JSON.parse(headers) }, (error, response, data) => { + try { + if (error) throw new Error(error) + $.log(`❕ ${$.name}, 登录: ${JSON.stringify(response)}`) + } catch (e) { + $.log(`❗️ ${$.name}, 每日登录: 失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +function logindaily() { + return new Promise((resove) => { + const url = { url: 'https://note.youdao.com/yws/api/daupromotion?method=sync', headers: JSON.parse($.VAL_sign_headers) } + delete url.headers.Cookie + $.post(url, (error, response, data) => { + try { + if (error) throw new Error(error) + $.log(`❕ ${$.name}, 每日登录: ${data}`) + $.daily = JSON.parse(data) + } catch (e) { + $.log(`❗️ ${$.name}, 每日登录: 失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +function signinapp() { + return new Promise((resove) => { + const url = { url: $.VAL_sign_url, body: $.VAL_sign_body, headers: JSON.parse($.VAL_sign_headers) } + delete url.headers.Cookie + $.post(url, (error, response, data) => { + try { + if (error) throw new Error(error) + $.log(`❕ ${$.name}, 每日签到: ${data}`) + $.signin = JSON.parse(data) + } catch (e) { + $.log(`❗️ ${$.name}, 每日登录: 失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +function showmsg() { + return new Promise((resove) => { + const dailyFlag = $.daily.accept === true ? '成功' : '重复' + const signinFlag = $.signin.success === 1 ? '成功' : $.signin.success === 0 ? '重复' : '错误' + $.subt = `每日登录: ${dailyFlag}, 每日签到: ${signinFlag}` + const continuousDays = `连签: ${$.daily.rewardSpace / 1024 / 1024}天` + const rewardSpace = `本次获得: ${$.daily.rewardSpace / 1024 / 1024}MB` + const totalReward = `总共获得: ${$.daily.totalRewardSpace / 1024 / 1024}MB` + $.desc = `${continuousDays}, ${rewardSpace}, ${totalReward}` + resove() + }) +} + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..23156946d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,986 @@ +{ + "name": "chavy_scripts", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "chavy_scripts", + "version": "1.0.0", + "dependencies": { + "crypto-js": "^4.2.0", + "got": "^11.8.5", + "http-server": "^14.1.1", + "iconv-lite": "0.6.3", + "tough-cookie": "^4.1.3" + }, + "devDependencies": { + "prettier": "^3.2.5" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz", + "integrity": "sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", + "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", + "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", + "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==", + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", + "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "14.14.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz", + "integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==", + "license": "MIT" + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/clone-response/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz", + "integrity": "sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-server": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", + "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", + "dependencies": { + "basic-auth": "^2.0.1", + "chalk": "^4.1.2", + "corser": "^2.0.1", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", + "minimist": "^1.2.6", + "opener": "^1.5.1", + "portfinder": "^1.0.28", + "secure-compare": "3.0.1", + "union": "~0.5.0", + "url-join": "^4.0.1" + }, + "bin": { + "http-server": "bin/http-server" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.0-beta.5.2", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz", + "integrity": "sha512-xYz9goEyBnC8XwXDTuC/MZ6t+MrKVQZOk4s7+PaDkwIsQd8IwqvM+0M6bA/2lvG8GHXcPdf+MejTUeO2LCPCeQ==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "license": "MIT" + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/p-cancelable": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", + "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "license": "MIT", + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "license": "MIT" + }, + "node_modules/resolve-alpn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.0.0.tgz", + "integrity": "sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA==", + "license": "MIT" + }, + "node_modules/responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=", + "license": "MIT" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dependencies": { + "qs": "^6.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "license": "ISC" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..ee60f224d --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "chavy_scripts", + "version": "1.0.0", + "main": "Env.js", + "scripts": { + "dev": "http-server ." + }, + "dependencies": { + "crypto-js": "^4.2.0", + "got": "^11.8.5", + "http-server": "^14.1.1", + "iconv-lite": "0.6.3", + "tough-cookie": "^4.1.3" + }, + "devDependencies": { + "prettier": "^3.2.5" + } +} \ No newline at end of file diff --git a/pagoda/pagoda.cookie.js b/pagoda/pagoda.cookie.js new file mode 100644 index 000000000..5d28eb310 --- /dev/null +++ b/pagoda/pagoda.cookie.js @@ -0,0 +1,40 @@ +/** + * 百果园 - 小程序 + * + * > 进入小程序直接签到 + * + * hostname = wx-mini.pagoda.com.cn + * + * # Surge + * Rewrite: 百果园 = type=http-request,pattern=^https:\/\/wx-mini.pagoda.com.cn\/api\/v1\/wxmini\/signIn\/customer,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/pagoda/pagoda.cookie.js + * Tasks: 百果园 = type=cron,cronexp=10 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/pagoda/pagoda.js,wake-system=true + * + * # QuanX + * ^https:\/\/wx-mini.pagoda.com.cn\/api\/v1\/wxmini\/signIn\/customer url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/pagoda/pagoda.cookie.js + * 10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/pagoda/pagoda.js, tag=百果园 + * + * # Loon + * http-request ^https:\/\/wx-mini.pagoda.com.cn\/api\/v1\/wxmini\/signIn\/customer script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/pagoda/pagoda.cookie.js + * cron "10 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/pagoda/pagoda.js + * + */ + +const $ = new Env('百果园') +$.KEY_sign = 'chavy_sign_pagoda' + +!(async () => { + const session = {} + session.url = $request.url + session.headers = $request.headers + if ($.setdata(JSON.stringify(session), $.KEY_sign)) { + $.subt = `获取会话: 成功!` + } else { + $.subt = `获取会话: 失败!` + } + $.msg($.name, $.subt) +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/pagoda/pagoda.js b/pagoda/pagoda.js new file mode 100644 index 000000000..f02ae15ea --- /dev/null +++ b/pagoda/pagoda.js @@ -0,0 +1,37 @@ +const $ = new Env('百果园') +$.KEY_sign = 'chavy_sign_pagoda' + +!(async () => { + await signwx() + await showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +function signwx() { + return new Promise((resolve) => { + const opts = JSON.parse($.getdata($.KEY_sign)) + $.get(opts, (err, resp, data) => { + try { + $.wx = JSON.parse(data) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} +function showmsg() { + return new Promise((resolve) => { + $.subt = '签到: ' + if ($.wx.errorCode === 0) $.subt += '成功' + else if ($.wx.errorCode === 35702) $.subt += '重复' + else $.subt += '失败' + $.msg($.name, $.subt, $.desc) + resolve() + }) +} + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/qimao/README.md b/qimao/README.md new file mode 100644 index 000000000..f423df2eb --- /dev/null +++ b/qimao/README.md @@ -0,0 +1,104 @@ +# 七猫小说 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 +> 感谢[@danchaw](https://github.com/danchaw) PR +## 配置 (Surge) + +```properties +[MITM] +xiaoshuo.qm989.com + +[Script] +http-request ^https:\/\/xiaoshuo\.qm989\.com script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qimao/qmnovel.js +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qimao/qmnovel.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +xiaoshuo.qm989.com + +[rewrite_local] + +# [商店版] +^https:\/\/xiaoshuo\.qm989\.com url script-request-header qmnovel.js + +# [TestFlight] +^https:\/\/xiaoshuo\.qm989\.com url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/qimao/qmnovel.js + +[task_local] + +# [商店版] +1 0 * * * qmnovel.js + +# [TestFlight] +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/qimao/qmnovel.js +``` + +## 说明 + +1. 先把`xiaoshuo.qm989.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`qmnovel.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 暂时关闭QX或Surge中的广告屏蔽, 否则无法获取小视频奖励cookie和url +4. 打开 APP[七猫小说](https://apps.apple.com/cn/app/%E4%B8%83%E7%8C%AB%E5%B0%8F%E8%AF%B4-%E7%9C%8B%E5%B0%8F%E8%AF%B4%E7%94%B5%E5%AD%90%E4%B9%A6%E7%9A%84%E9%98%85%E8%AF%BB%E7%A5%9E%E5%99%A8/id1387717110) 然后到APP内福利界面手动日常签到(观看小视频领取奖励),新手领福利签到,视频签到以及幸运大转盘 1 次, 系统提示: `首次写入xxxUrl成功🎉,首次写入xxxCookie成功🎉` +5. 最后就可以把第 1 条脚本注释掉了 +6. 运行一次脚本, 如果提示重复签到, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@danchaw](https://github.com/danchaw) diff --git a/qimao/qmnovel.js b/qimao/qmnovel.js new file mode 100644 index 000000000..f13bc267f --- /dev/null +++ b/qimao/qmnovel.js @@ -0,0 +1,412 @@ +var cookieName = '七猫小说' +var qmnovel = init() +var DCURL = qmnovel.getdata("UrlDC") +var DCKEY = qmnovel.getdata("CookieDC") +var NCURL = qmnovel.getdata("UrlNC") +var NCKEY = qmnovel.getdata("CookieNC") +var LTURL = qmnovel.getdata("UrlLT") +var LTKEY = qmnovel.getdata("CookieLT") +var VCURL = qmnovel.getdata("UrlVC") + +const Totalresult = {} +const time = 0 + +let isGetCookie = typeof $request !== 'undefined' + +if (isGetCookie) { + GetCookie() + qmnovel.done() +} else { + all() + qmnovel.done() +} + +async function all() { + qmnovel.log(`🔔 ${cookieName}签到开始`) + await DailyCheckin(time); + await NoviceCheckin(time); + for (let i = 0; i < 5; i++) { + await LuckyTurn(time); + } + await VideoCoin(time) + Notify(); +} + +function GetCookie() { + const dailycheckin = '/api/v1/sign-in/do-sign-in'; + const novice = '/api/v1/task/get-novice-reward'; + const turn = '/api/v2/lucky-draw/do-extracting'; + const video = '/api/v1/sign-in/sign-in-video-coin'; + var url = $request.url; + if (url.indexOf(dailycheckin) != -1) { + if (url) { + var UrlKeyDC = "UrlDC"; + var UrlNameDC = "七猫小说日常签到"; + var UrlValueDC = url; + if (qmnovel.getdata(UrlKeyDC) != (undefined || null)) { + if (qmnovel.getdata(UrlKeyDC) != UrlValueDC) { + var urlDC = qmnovel.setdata(UrlValueDC, UrlKeyDC); + if (!urlDC) { + qmnovel.msg("更新" + UrlNameDC + "Url失败‼️", "", ""); + } else { + qmnovel.msg("更新" + UrlNameDC + "Url成功🎉", "", ""); + } + } else { + qmnovel.msg(UrlNameDC + "Url未变化❗️", "", ""); + } + } else { + var urlDC = qmnovel.setdata(UrlValueDC, UrlKeyDC); + if (!cookieDC) { + qmnovel.msg("首次写入" + UrlNameDC + "Url失败‼️", "", ""); + } else { + qmnovel.msg("首次写入" + UrlNameDC + "Url成功🎉", "", ""); + } + } + } else { + qmnovel.msg("写入" + UrlNameDC + "Url失败‼️", "", "配置错误, 无法读取URL, "); + } + if ($request.headers) { + var CookieKeyDC = "CookieDC"; + var CookieNameDC = "七猫小说日常签到及视频奖励"; + var CookieValueDC = JSON.stringify($request.headers); + if (qmnovel.getdata(CookieKeyDC) != (undefined || null)) { + if (qmnovel.getdata(CookieKeyDC) != CookieValueDC) { + var cookieDC = qmnovel.setdata(CookieValueDC, CookieKeyDC); + if (!cookieDC) { + qmnovel.msg("更新" + CookieNameDC + "Cookie失败‼️", "", ""); + } else { + qmnovel.msg("更新" + CookieNameDC + "Cookie成功🎉", "", ""); + } + } else { + qmnovel.msg(CookieNameDC + "Cookie未变化❗️", "", ""); + } + } else { + var cookieDC = qmnovel.setdata(CookieValueDC, CookieKeyDC); + if (!cookieDC) { + qmnovel.msg("首次写入" + CookieNameDC + "Cookie失败‼️", "", ""); + } else { + qmnovel.msg("首次写入" + CookieNameDC + "Cookie成功🎉", "", ""); + } + } + } else { + qmnovel.msg("写入" + CookieNameDC + "Cookie失败‼️", "", "配置错误, 无法读取请求头, "); + } + } else if (url.indexOf(novice) != -1) { + if (url) { + var UrlKeyNC = "UrlNC"; + var UrlNameNC = "七猫小说新人签到"; + var UrlValueNC = url; + if (qmnovel.getdata(UrlKeyNC) != (undefined || null)) { + if (qmnovel.getdata(UrlKeyNC) != UrlValueNC) { + var urlNC = qmnovel.setdata(UrlValueNC, UrlKeyNC); + if (!urlNC) { + qmnovel.msg("更新" + UrlNameNC + "Url失败‼️", "", ""); + } else { + qmnovel.msg("更新" + UrlNameNC + "Url成功🎉", "", ""); + } + } else { + qmnovel.msg(UrlNameNC + "Url未变化❗️", "", ""); + } + } else { + var urlNC = qmnovel.setdata(UrlValueNC, UrlKeyNC); + if (!urlNC) { + qmnovel.msg("首次写入" + UrlNameNC + "Url失败‼️", "", ""); + } else { + qmnovel.msg("首次写入" + UrlNameNC + "Url成功🎉", "", ""); + } + } + } else { + qmnovel.msg("写入" + UrlNameNC + "Url失败‼️", "", "配置错误, 无法读取URL, "); + } + if ($request.headers) { + var CookieKeyNC = "CookieNC"; + var CookieNameNC = "七猫小说新人签到"; + var CookieValueNC = JSON.stringify($request.headers); + if (qmnovel.getdata(CookieKeyNC) != (undefined || null)) { + if (qmnovel.getdata(CookieKeyNC) != CookieValueNC) { + var cookieNC = qmnovel.setdata(CookieValueNC, CookieKeyNC); + if (!cookieNC) { + qmnovel.msg("更新" + CookieNameNC + "Cookie失败‼️", "", ""); + } else { + qmnovel.msg("更新" + CookieNameNC + "Cookie成功🎉", "", ""); + } + } else { + qmnovel.msg(CookieNameNC + "Cookie未变化❗️", "", ""); + } + } else { + var cookieNC = qmnovel.setdata(CookieValueNC, CookieKeyNC); + if (!cookieNC) { + qmnovel.msg("首次写入" + CookieNameNC + "Cookie失败‼️", "", ""); + } else { + qmnovel.msg("首次写入" + CookieNameNC + "Cookie成功🎉", "", ""); + } + } + } else { + qmnovel.msg("写入" + CookieNameNC + "Cookie失败‼️", "", "配置错误, 无法读取请求头, "); + } + } else if (url.indexOf(turn) != -1) { + if (url) { + var UrlKeyLT = "UrlLT"; + var UrlNameLT = "七猫小说幸运大转盘"; + var UrlValueLT = url; + if (qmnovel.getdata(UrlKeyLT) != (undefined || null)) { + if (qmnovel.getdata(UrlKeyLT) != UrlValueLT) { + var urlLT = qmnovel.setdata(UrlValueLT, UrlKeyLT); + if (!urlLT) { + qmnovel.msg("更新" + UrlNameLT + "Url失败‼️", "", ""); + } else { + qmnovel.msg("更新" + UrlNameLT + "Url成功🎉", "", ""); + } + } else { + qmnovel.msg(UrlNameLT + "Url未变化❗️", "", ""); + } + } else { + var urlLT = qmnovel.setdata(UrlValueLT, UrlKeyLT); + if (!urlLT) { + qmnovel.msg("首次写入" + UrlNameLT + "Url失败‼️", "", ""); + } else { + qmnovel.msg("首次写入" + UrlNameLT + "Url成功🎉", "", ""); + } + } + } else { + qmnovel.msg("写入" + UrlNameLT + "Url失败‼️", "", "配置错误, 无法读取URL, "); + } + if ($request.headers) { + var CookieKeyLT = "CookieLT"; + var CookieNameLT = "七猫小说幸运大转盘"; + var CookieValueLT = JSON.stringify($request.headers); + if (qmnovel.getdata(CookieKeyLT) != (undefined || null)) { + if (qmnovel.getdata(CookieKeyLT) != CookieValueLT) { + var cookieLT = qmnovel.setdata(CookieValueLT, CookieKeyLT); + if (!cookieLT) { + qmnovel.msg("更新" + CookieNameLT + "Cookie失败‼️", "", ""); + } else { + qmnovel.msg("更新" + CookieNameLT + "Cookie成功🎉", "", ""); + } + } else { + qmnovel.msg(CookieNameLT + "Cookie未变化❗️", "", ""); + } + } else { + var cookieLT = qmnovel.setdata(CookieValueLT, CookieKeyLT); + if (!cookieLT) { + qmnovel.msg("首次写入" + CookieNameLT + "Cookie失败‼️", "", ""); + } else { + qmnovel.msg("首次写入" + CookieNameLT + "Cookie成功🎉", "", ""); + } + } + } else { + qmnovel.msg("写入" + CookieNameLT + "Cookie失败‼️", "", "配置错误, 无法读取请求头, "); + } + } else if (url.indexOf(video) != -1) { + if (url) { + var UrlKeyVC = "UrlVC"; + var UrlNameVC = "七猫小说视频奖励"; + var UrlValueVC = url; + if (qmnovel.getdata(UrlKeyVC) != (undefined || null)) { + if (qmnovel.getdata(UrlKeyVC) != UrlValueVC) { + var urlVC = qmnovel.setdata(UrlValueVC, UrlKeyVC); + if (!urlVC) { + qmnovel.msg("更新" + UrlNameVC + "Url失败‼️", "", ""); + } else { + qmnovel.msg("更新" + UrlNameVC + "Url成功🎉", "", ""); + } + } else { + qmnovel.msg(UrlNameVC + "Url未变化❗️", "", ""); + } + } else { + var urlVC = qmnovel.setdata(UrlValueVC, UrlKeyVC); + if (!urlVC) { + qmnovel.msg("首次写入" + UrlNameVC + "Url失败‼️", "", ""); + } else { + qmnovel.msg("首次写入" + UrlNameVC + "Url成功🎉", "", ""); + } + } + } else { + qmnovel.msg("写入" + UrlNameVC + "Url失败‼️", "", "配置错误, 无法读取URL, "); + } + } +} + +function DailyCheckin(t) { + return new Promise(resolve => { setTimeout(() => { + url = { url: DCURL, headers: JSON.parse(DCKEY) } + qmnovel.get(url, (error, response, data) => { + try { + Totalresult.dailycheckin = JSON.parse(data) + qmnovel.log(`${cookieName}日常签到, data: ${data}`) + resolve('done'); + } catch (e) { + qmnovel.log(`Error: ${error}`) + qmnovel.msg(cookieName, '日常签到结果: 失败‼️', '请查看错误日志‼️') + resolve('done') + } + })}, t) + }) +} + +function NoviceCheckin(t) { + return new Promise(resolve => { setTimeout(() => { + url = { url: NCURL, headers: JSON.parse(NCKEY) } + qmnovel.get(url, (error, response, data) => { + try { + Totalresult.novicecheckin = JSON.parse(data) + qmnovel.log(`${cookieName}新人签到, data: ${data}`) + resolve('done'); + } catch (e) { + qmnovel.log(`Error: ${error}`) + qmnovel.msg(cookieName, '新人签到结果: 失败‼️', '请查看错误日志‼️') + resolve('done') + } + })}, t) + }) + } + +function VideoCoin(t) { + return new Promise(resolve => { setTimeout(() => { + url = { url: VCURL, headers: JSON.parse(DCKEY) } + qmnovel.get(url, (error, response, data) => { + try { + Totalresult.videocoin = JSON.parse(data) + qmnovel.log(`${cookieName}视频奖励, data: ${data}`) + resolve('done'); + } catch (e) { + qmnovel.log(`Error: ${error}`) + qmnovel.msg(cookieName, '领取视频奖励: 失败‼️', '请查看错误日志‼️') + resolve('done'); + } + })}, t) + }) +} + +function LuckyTurn(t) { + return new Promise(resolve => { setTimeout(() => { + url = { url: LTURL, headers: JSON.parse(LTKEY) } + qmnovel.get(url, (error, response, data) => { + try { + Totalresult.luckyturnlist = Totalresult.luckyturnlist ? Totalresult.luckyturnlist : [] + Totalresult.luckyturnlist.push(JSON.parse(data)) + qmnovel.log(`${cookieName}幸运大转盘, data: ${data}`) + resolve('done'); + } catch (e) { + qmnovel.log(`Error: ${error}`) + qmnovel.msg(cookieName, '幸运大转盘: 失败‼️', '请查看错误日志‼️') + resolve('done') + } + })}, t) + }) +} + +function Notify() { + let subTitle = ''; + let detail = ''; + if (Totalresult.dailycheckin) { + if (Totalresult.dailycheckin.data) { + subTitle += '日常签到结果: 成功🎉\n' + detail += '日常签到奖励: '+ Totalresult.dailycheckin.data.coin +'金币\n' + } else if (Totalresult.dailycheckin.errors) { + if (Totalresult.dailycheckin.errors.code == 23010103) { + subTitle += '日常签到结果: 成功(重复签到)🎉\n' + } else { + subTitle += '日常签到结果: 失败‼️\n' + detail += '日常签到说明: ' + Totalresult.dailycheckin.errors.details + '\n' + } + } + } + if (Totalresult.videocoin) { + if (Totalresult.videocoin.data) { + subTitle += '领取视频奖励: 成功🎉\n' + detail += '视频奖励: '+ Totalresult.videocoin.data.coin +'金币\n' + } else if (Totalresult.videocoin.errors) { + if (Totalresult.videocoin.errors.code == 23010107) { + subTitle += '领取视频奖励: 成功(重复签到)🎉\n' + detail += '视频奖励说明: ' + Totalresult.videocoin.errors.details + '\n' + } else { + subTitle += '领取视频奖励: 失败‼️\n' + detail += '视频奖励说明: ' + Totalresult.videocoin.errors.details + '\n' + } + } + } + if (Totalresult.novicecheckin) { + if (Totalresult.novicecheckin.data) { + subTitle += '新人签到结果: 成功🎉\n' + detail += '签到奖励: '+ Totalresult.novicecheckin.data.reward_cash +'金币\n' + } else if (Totalresult.novicecheckin.errors) { + if (Totalresult.novicecheckin.errors.code == 13101002) { + subTitle += '新人签到结果: 成功(重复签到)🎉\n' + detail += '新人签到说明: ' + Totalresult.novicecheckin.errors.details + '\n' + } else { + subTitle += '新人签到结果: 失败‼️\n' + detail += '新人签到说明: ' + Totalresult.novicecheckin.errors.details + '\n' + } + } + } + if (Totalresult.luckyturnlist) { + subTitle += '幸运大转盘次数: 5次'; + for (let i = 0; i < 5; i++) { + n = i + 1 + if (Totalresult.luckyturnlist[i].data) { + detail += '第' + n + '次' + '幸运大转盘: 成功🎉 转盘奖励: ' + Totalresult.luckyturnlist[i].data.prize_title + '\n' + } else if (Totalresult.luckyturnlist[i].errors) { + if (Totalresult.luckyturnlist[i].errors.code == 13101002) { + detail += '幸运大转盘: 次数耗尽🚫 说明: ' + Totalresult.luckyturnlist[i].errors.details + '\n' + } else { + detail += '幸运大转盘: 失败‼️ 说明: ' + Totalresult.luckyturnlist[i].errors.details + '\n' + } + } + } + } + qmnovel.msg(cookieName, subTitle, detail) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + put = (url, cb) => { + if (isSurge()) { + $httpClient.put(url, cb) + } + if (isQuanX()) { + url.method = 'PUT' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, put, done } +} \ No newline at end of file diff --git a/qmkg/README.md b/qmkg/README.md new file mode 100644 index 000000000..61966b553 --- /dev/null +++ b/qmkg/README.md @@ -0,0 +1,104 @@ +# 全民K歌 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> QuanX 需要: v1.0.6-build195 及以后版本 (TestFlight) + +> 感谢 [@GideonSenku](https://github.com/GideonSenku) Commit + +## 配置 (Surge) + +```properties +[MITM] +node.kg.qq.com + +[Script] +http-request ^https://node\.kg\.qq\.com/webapp/proxy? script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qmkg/qmkg.cookie.js, requires-body=true + +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qmkg/qmkg.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +node.kg.qq.com + +[rewrite_local] + +# [商店版] QuanX v1.0.6-build194 及更早版本 +# 不支持 + +# [TestFlight] QuanX v1.0.6-build195 及以后版本 +^https://node\.kg\.qq\.com/webapp/proxy? url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/qmkg/qmkg.cookie.js + +[task_local] +1 0 * * * qmkg.js +``` + +## 说明 + +1. 先把`node.kg.qq.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`qmkg.cookie.js`和`qmkg.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP 手动签到一次: 访问下右下角 `我的` > `任务中心` > `签到` +4. 系统提示: `获取Cookie: 成功` +5. 把获取 Cookie 的脚本注释掉 +6. 运行一次脚本, 如果提示重复签到, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@GideonSenku](https://github.com/GideonSenku) diff --git a/qmkg/qmkg.cookie.js b/qmkg/qmkg.cookie.js new file mode 100644 index 000000000..c1a6fb900 --- /dev/null +++ b/qmkg/qmkg.cookie.js @@ -0,0 +1,67 @@ +const cookieName = '全民K歌' +const signurlKey = 'senku_signurl_qmkg' +const signheaderKey = 'senku_signheader_qmkg' +const signbodyKey = 'senku_signbody_qmkg' +const senku = init() + +const requrl = $request.url +if ($request && $request.method != 'OPTIONS') { + const signurlVal = requrl + const signheaderVal = JSON.stringify($request.headers) + const signbodyVal = $request.body + const cmd = JSON.parse($request.body).cmd + senku.log(`signurlVal:${signurlVal}`) + senku.log(`signheaderVal:${signheaderVal}`) + senku.log(`signbodyVal:${signbodyVal}`) + if (signurlVal) senku.setdata(signurlVal, signurlKey) + if (signheaderVal) senku.setdata(signheaderVal, signheaderKey) + if (signbodyVal && cmd=='task.revisionSignInGetAward') { + senku.setdata(signbodyVal, signbodyKey) + senku.msg(cookieName, `获取Cookie: 成功`, ``) + } +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} +senku.done() diff --git a/qmkg/qmkg.js b/qmkg/qmkg.js new file mode 100644 index 000000000..9ed1f27d7 --- /dev/null +++ b/qmkg/qmkg.js @@ -0,0 +1,76 @@ +const cookieName = '全民K歌' +const signurlKey = 'senku_signurl_qmkg' +const signheaderKey = 'senku_signheader_qmkg' +const signbodyKey = 'senku_signbody_qmkg' +const senku = init() +const signurlVal = senku.getdata(signurlKey) +const signheaderVal = senku.getdata(signheaderKey) +const signBodyVal = senku.getdata(signbodyKey) + +sign() + +function sign() { + const url = { url: signurlVal, headers: JSON.parse(signheaderVal), body: signBodyVal } + senku.post(url, (error, response, data) => { + const result = JSON.parse(data) + const total = result.data['task.revisionSignInGetAward'].total + const ret = result.data['task.revisionSignInGetAward'].ret + let subTitle = `` + let detail = `` + if (total != 0) { + const num = result.data['task.revisionSignInGetAward'].awards[0].num + subTitle = `签到结果: 成功` + detail = `获得鲜花: ${num}朵,已连续签到:${total}天` + } else if (ret == -11532) { + subTitle = `签到结果: 成功 (重复签到)` + } else { + subTitle = `签到结果: 失败` + } + senku.msg(cookieName, subTitle, detail) + senku.done() + }) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/qunar/README.md b/qunar/README.md index 8ee13072c..c3aea5263 100644 --- a/qunar/README.md +++ b/qunar/README.md @@ -9,7 +9,7 @@ user.qunar.com [Script] -http-request ^https:\/\/user.qunar.com\/webapi\/member\/signNewIndex.htm script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qunar/qunar.cookie.js +http-request ^https:\/\/user.qunar.com\/webapi\/member\/signIndexV2.htm script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qunar/qunar.cookie.js cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qunar/qunar.js ``` @@ -20,10 +20,7 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr user.qunar.com [rewrite_local] -# 189及以前版本 -^https:\/\/user.qunar.com\/webapi\/member\/signNewIndex.htm url script-response-body qunar.cookie.js -# 190及以后版本 -^https:\/\/user.qunar.com\/webapi\/member\/signNewIndex.htm url script-request-header qunar.cookie.js +^https:\/\/user.qunar.com\/webapi\/member\/signIndexV2.htm url script-request-header qunar.cookie.js [task_local] 1 0 * * * qunar.js diff --git a/rrtv/rrtv.js b/rrtv/rrtv.js deleted file mode 100644 index b6080240e..000000000 --- a/rrtv/rrtv.js +++ /dev/null @@ -1,179 +0,0 @@ -const cookieName = '人人视频' -const cookieKey = 'chavy_cookie_rrtv' -const chavy = init() -let cookieVal = chavy.getdata(cookieKey) -const signinfo = {} - -sign() - -function sign() { - signdaily() - signwelfare() - check() -} - -function signdaily() { - let url = { url: `https://api.rr.tv/rrtv-activity/sign/sign`, headers: { token: cookieVal } } - url.headers['clientType'] = `ios_rrsp_jzsp` - url.headers['Accept-Encoding'] = `gzip, deflate, br` - url.headers['Connection'] = `keep-alive` - url.headers['clientVersion'] = `4.3.5` - url.headers['Content-Type'] = `application/x-www-form-urlencoded; charset=UTF-8` - url.headers['Origin'] = `https://mobile.rr.tv` - url.headers['Referer'] = `https://mobile.rr.tv/` - url.headers['Accept'] = `application/json, text/plain, */*` - url.headers['Host'] = `api.rr.tv` - url.headers['Accept-Language'] = `zh-cn` - url.headers['Content-Length'] = `12` - url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 App/RRSPApp platform/iPhone AppVersion/4.3.5' - - chavy.post(url, (error, response, data) => { - chavy.log(`${cookieName}, signdaily.data: ${data}`) - signinfo.signdaily = JSON.parse(data) - }) -} - -function signwelfare() { - let url = { url: `https://api.rr.tv/dailyWelfare/getWelfare`, headers: { token: cookieVal } } - url.headers['clientType'] = `web` - url.headers['Accept-Encoding'] = `gzip, deflate, br` - url.headers['Connection'] = `keep-alive` - url.headers['clientVersion'] = `0.0.1` - url.headers['Content-Type'] = `application/x-www-form-urlencoded; charset=UTF-8` - url.headers['Origin'] = `https://mobile.rr.tv` - url.headers['Referer'] = `https://mobile.rr.tv/mission/` - url.headers['Accept'] = `application/json, text/plain, */*` - url.headers['Host'] = `api.rr.tv` - url.headers['Accept-Language'] = `zh-cn` - url.headers['Content-Length'] = `45` - url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 App/RRSPApp platform/iPhone AppVersion/4.3.5' - - chavy.post(url, (error, response, data) => { - chavy.log(`${cookieName}, signwelfare.data: ${data}`) - signinfo.signwelfare = JSON.parse(data) - }) -} - -function check(checkms = 0) { - if (signinfo.signdaily && signinfo.signwelfare) { - getinfo() - } else { - if (checkms > 5000) { - chavy.msg(`${cookieName}`, `签到失败: 超时退出`, ``) - chavy.done() - } else { - setTimeout(() => check(checkms + 100), 100) - } - } -} - -function getinfo() { - let url = { url: `https://api.rr.tv/user/profile`, headers: { token: cookieVal } } - url.headers['clientType'] = `ios_rrsp_jzsp` - url.headers['Accept-Encoding'] = `gzip, deflate, br` - url.headers['Connection'] = `keep-alive` - url.headers['clientVersion'] = `4.3.5` - url.headers['Content-Type'] = `application/x-www-form-urlencoded; charset=UTF-8` - url.headers['Origin'] = `https://mobile.rr.tv` - url.headers['Referer'] = `https://mobile.rr.tv/` - url.headers['Accept'] = `application/json, text/plain, */*` - url.headers['Host'] = `api.rr.tv` - url.headers['Accept-Language'] = `zh-cn` - url.headers['Content-Length'] = `0` - url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 App/RRSPApp platform/iPhone AppVersion/4.3.5' - - chavy.post(url, (error, response, data) => { - chavy.log(`${cookieName}, userinfo: ${data}`) - const result = JSON.parse(data) - const title = `${cookieName}` - let subTitle = `` - let detail = `` - if (signinfo.signdaily) { - subTitle = `每日签到: ` - if (signinfo.signdaily.code == '0000' || signinfo.signdaily.code == '8750') { - subTitle += signinfo.signdaily.code == '0000' ? '成功; ' : '' - subTitle += signinfo.signdaily.code == '8750' ? '重复; ' : '' - } else { - subTitle += '失败; ' - } - } - if (signinfo.signwelfare) { - subTitle += `每日福利: ` - if (signinfo.signwelfare.code == '0000' || signinfo.signwelfare.code == '8623') { - subTitle += signinfo.signwelfare.code == '0000' ? '成功; ' : '' - subTitle += signinfo.signwelfare.code == '8623' ? '重复; ' : '' - } else { - subTitle += '失败;' - } - } - if (result.code == '0000') { - const levelStr = result.data.user.levelStr ? ` (${result.data.user.levelStr})` : `` - detail = `等级: ${result.data.user.level}${levelStr}, 积分: ${result.data.user.score}` - } else { - detail = `编码: ${result.code}, 说明: ${result.msg}` - } - chavy.msg(title, subTitle, detail) - // if (signresult.code == '0000') { - // const levelStr = result.data.user.levelStr ? ` (${result.data.user.levelStr})` : `` - // subTitle = `签到结果: 成功` - // detail = `等级: ${result.data.user.level}${levelStr}, 说明: ${signresult.msg}` - // } else if (signresult.code == '8750') { - // const levelStr = result.data.user.levelStr ? ` (${result.data.user.levelStr})` : `` - // subTitle = `签到结果: 成功 (重复签到)` - // detail = `等级: ${result.data.user.level}${levelStr}, 说明: ${signresult.msg}` - // } else if (signresult.code == '8400') { - // subTitle = `签到失败: 失败` - // detail = `说明: ${signresult.msg}` - // } else { - // subTitle = `签到失败: 未知` - // detail = `编码: ${signresult.code}, 说明: ${signresult.msg}` - // } - - // chavy.msg(title, subTitle, detail) - }) - chavy.done() -} - -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) - } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) - } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } -} diff --git a/sfexpress/README.md b/sfexpress/README.md index 04b43ff57..2fdbfc19b 100644 --- a/sfexpress/README.md +++ b/sfexpress/README.md @@ -1,98 +1,47 @@ -# 顺丰速运 (弃坑) - -> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 - -> 2020.1.11 QuanX 在`190`版本开始, 获取 Cookie 方式需要从`script-response-body`改为`script-request-header` - -> 2020.1.22 据实测顺丰的 Cookie 只能存活 1 天不到,大家先弃坑 +# 顺丰速运 (APP) ## 配置 (Surge) ```properties [MITM] -*.weixinjia.net +hostname = ccsp-egmas.sf-express.com [Script] -http-request ^https:\/\/sf\-integral\-sign\-in\.weixinjia\.net\/app\/init script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.cookie.js -cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.js +Rewrite: 顺丰速运 = type=http-request, pattern=^https:\/\/ccsp-egmas.sf-express.com\/cx-app-member\/member\/app\/user\/universalSign,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.cookie.js,requires-body=true +cron "1 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.js ``` ## 配置 (QuanX) ```properties [MITM] -*.weixinjia.net +hostname = ccsp-egmas.sf-express.com [rewrite_local] -# 189及以前版本 -^https:\/\/sf\-integral\-sign\-in\.weixinjia\.net\/app\/init url script-response-body sfexpress.cookie.js -# 190及以后版本 -^https:\/\/sf\-integral\-sign\-in\.weixinjia\.net\/app\/init url script-request-header sfexpress.cookie.js +^https:\/\/ccsp-egmas.sf-express.com\/cx-app-member\/member\/app\/user\/universalSign url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.cookie.js [task_local] -1 0 * * * sfexpress.js +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.js ``` -## 说明 - -1. 先把`*.weixinjia.net`加到`[MITM]` -2. 再配置重写规则: - - Surge: 把两条远程脚本放到`[Script]` - - QuanX: 把`sfexpress.cookie.js`和`sfexpress.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) -3. 打开 APP, 访问下`我的顺丰` > `去签到` (访问下`去签到`的页面即可, 不用点`签到`) -4. 系统提示: `获取Cookie: 成功` (如果不提示获取成功, 尝试杀进程再进签到页面) -5. 最后就可以把第 1 条脚本注释掉了 - -> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. - -> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. - -## 常见问题 - -1. 无法写入 Cookie - - - 检查 Surge 系统通知权限放开了没 - - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) - -2. 写入 Cookie 成功, 但签到不成功 - - - 看看是不是在登录前就写入 Cookie 了 - - 如果是,请确保在登录成功后,再尝试写入 Cookie +## 配置 (Loon) -3. 为什么有时成功有时失败 - - - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) - - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): - - - `Surge`配置: - - ```properties - # 没有什么是一顿饭解决不了的: - cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 - # 如果有,那就两顿: - cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 - # 实在不行,三顿也能接受: - cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 - - # 再粗暴点,直接: - cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 - ``` +```properties +[MITM] +hostname = ccsp-egmas.sf-express.com - - `QuanX`配置: +[Script] +http-request ^https:\/\/ccsp-egmas.sf-express.com\/cx-app-member\/member\/app\/user\/universalSign script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.cookie.js, requires-body=true, tag=Rewrite: 顺丰速运 +cron "1 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.js +``` - ```properties - [task_local] - 1 0 * * * xxx.js # 每天00:01执行一次 - 2 0 * * * xxx.js # 每天00:02执行一次 - 3 0 * * * xxx.js # 每天00:03执行一次 +## 说明 - */60 * * * * xxx.js # 每60分执行一次 - ``` +1. 配置重写 +2. `APP` 我的顺丰 > 任务中心 > 去签到 +3. 提示 `获取会话: 成功` +4. 注释重写 ## 感谢 -[@NobyDa](https://github.com/NobyDa) - -[@lhie1](https://github.com/lhie1) - -[@ConnersHua](https://github.com/ConnersHua) +[@wangfei021325](https://github.com/wangfei021325) diff --git a/sfexpress/sfexpress.cookie.js b/sfexpress/sfexpress.cookie.js index 6188129a0..6541b3b00 100644 --- a/sfexpress/sfexpress.cookie.js +++ b/sfexpress/sfexpress.cookie.js @@ -1,55 +1,21 @@ -const cookieName = '顺丰速运' -const cookieKey = 'chavy_cookie_sfexpress' -const chavy = init() -const cookieVal = $request.headers['Cookie'] -if (cookieVal) { - if (chavy.setdata(cookieVal, cookieKey)) { - chavy.msg(`${cookieName}`, '获取Cookie: 成功', '') - chavy.log(`[${cookieName}] 获取Cookie: 成功, cookie: ${cookieVal}`) - } -} +const $ = new Env('顺丰速运') +$.KEY_login = 'chavy_login_sfexpress' -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) - } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) - } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } -} -chavy.done() +!(async () => { + const session = {} + session.url = $request.url + session.body = $request.body + session.headers = $request.headers + console.log(JSON.stringify(session)) + if ($.setdata(JSON.stringify(session), $.KEY_login)) { + $.subt = `获取会话: 成功!` + } else { + $.subt = `获取会话: 失败!` + } + $.msg($.name, $.subt, $.desc) +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/sfexpress/sfexpress.js b/sfexpress/sfexpress.js index 17a7b0cd0..6a54f8a35 100644 --- a/sfexpress/sfexpress.js +++ b/sfexpress/sfexpress.js @@ -1,87 +1,139 @@ -const cookieName = '顺丰速运' -const cookieKey = 'chavy_cookie_sfexpress' -const chavy = init() -let cookieVal = chavy.getdata(cookieKey) +const $ = new Env('顺丰速运') +$.KEY_login = 'chavy_login_sfexpress' -sign() +!(async () => { + await loginapp() + await $.wait('1000') + await loginweb() + await $.wait('1000') + await sign() + await $.wait('1000') + await signDailyTasks() + showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +function loginapp() { + const loginOpts = $.getjson($.KEY_login) + delete loginOpts.headers.Cookie + + return $.http + .post(loginOpts) + .then((resp) => { + $.login = JSON.parse(resp.body) + }) + .catch((err) => { + console.log(err) + }) +} + +function loginweb() { + const sign = encodeURIComponent($.login.obj.sign) + const loginOpts = { + url: `https://mcs-mimp-web.sf-express.com/mcs-mimp/share/app/shareRedirect?sign=${sign}&source=SFAPP&bizCode=647@RnlvejM1R3VTSVZ6d3BNaXJxRFpOUVVtQkp0ZnFpNDBKdytobm5TQWxMeHpVUXVrVzVGMHVmTU5BVFA1bXlwcw==` + } + return $.http.get(loginOpts) +} function sign() { - chavy.log(`${cookieName}, Cookie: ${cookieVal}`) - let url = { url: `https://sf-integral-sign-in.weixinjia.net/app/signin`, headers: { Cookie: cookieVal } } - url.headers['Origin'] = `https://sf-integral-sign-in.weixinjia.net` - url.headers['Connection'] = `keep-alive` - url.headers['Content-Type'] = `application/x-www-form-urlencoded` - url.headers['Accept'] = `application/json, text/plain, */*` - url.headers['Host'] = `sf-integral-sign-in.weixinjia.net` - url.headers['User-Agent'] = `Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 mediaCode=SFEXPRESSAPP-iOS-ML` - url.headers['ontent-Length'] = `15` - url.headers['Accept-Language'] = `zh-cn` - url.headers['Accept-Encoding'] = `gzip, deflate, br` - url.body = `date=${new Date().getFullYear()}-${new Date().getMonth() + 1}-${new Date().getDate()}` - chavy.log(`${cookieName}, body: ${url.body}`) - chavy.post(url, (error, response, data) => { - chavy.log(`${cookieName}, data: ${data}`) - const result = JSON.parse(data) - const title = `${cookieName}` - let subTitle = `` - let detail = `` - if (result.code == 0 && result.msg == 'success') { - subTitle = `签到结果: 成功` - } else if (result.code == -1) { - if (result.msg == 'ALREADY_CHECK') { - subTitle = `签到结果: 成功 (重复签到)` - } else { - subTitle = `签到结果: 失败` - } - } else { - subTitle = `签到结果: 未知` - detail = `说明: ${result.msg}` + const signOpts = { + url: `https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskSignPlusService~automaticSignFetchPackage`, + body: `{"comeFrom": "vioin", "channelFrom": "SFAPP"}`, + headers: { + 'Content-Type': 'application/json' } - chavy.msg(title, subTitle, detail) + } + return $.http.post(signOpts).then((resp) => { + $.sign = JSON.parse(resp.body) }) - chavy.done() } -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) - } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) +function queryDailyTask() { + return $.http + .post({ + url: `https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskStrategyService~queryPointTaskAndSignFromES`, + body: `{"channelType":"1"}`, + headers: { + 'Content-Type': 'application/json' + } + }) + .then((resp) => { + $.tasks = JSON.parse(resp.body).obj.taskTitleLevels + }) +} + +async function signDailyTasks() { + await queryDailyTask() + + for (let i = 0; i < $.tasks.length; i++) { + const task = $.tasks[i] + if (task.status === 1) { + await getPoint(task) + } else if (task.status === 2) { + await doTask(task) + await getPoint(task) + } else if (task.status === 3) { + task.result = '积分已领取!' + } else { + task.result = '未知' } } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) - } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) +} + +function doTask(task) { + return $.http.post({ + url: `https://mcs-mimp-web.sf-express.com/mcs-mimp/commonRoutePost/memberEs/taskRecord/finishTask`, + body: `{"taskCode":"${task.taskCode}"}`, + headers: {} + }) +} + + + + +function getPoint(task) { + return $.http + .post({ + url: 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskStrategyService~fetchIntegral', + body: `{"strategyId":${task.strategyId},"taskId":"${task.taskId}","taskCode":"${task.taskCode}","channelType":"1"}`, + headers: { + 'Content-Type': 'application/json' + } + }) + .then((resp) => { + const data = JSON.parse(resp.body) + task.result = data.success ? '成功' : data.errorMessage + }) +} + +function showmsg() { + const success = $.sign && $.sign.success + $.subt = `签到: ` + $.desc = [] + if (success) { + if ($.sign.obj.hasFinishSign){ + $.subt += `重复` + $.desc.push(`说明: 连续签到${$.sign.obj.countDay}天`) + } else { + $.subt += `成功` + $.desc.push(`说明: 连续签到${$.sign.obj.countDay}天`) } + } else { + const errmsg = $.sign.errorMessage + $.subt += `失败` + $.desc.push(`说明: ${errmsg}`) } - done = (value = {}) => { - $done(value) + + $.desc.push('', `每日任务: `) + for (let i = 0; i < $.tasks.length; i++) { + const name = $.tasks[i].title + const result = $.tasks[i].result + $.desc.push(`${name}: ${result}`) } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } + + $.msg($.name, $.subt, $.desc.join('\n')) } + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/smzdm/README.md b/smzdm/README.md index 4a756b614..c7ee550a7 100644 --- a/smzdm/README.md +++ b/smzdm/README.md @@ -1,14 +1,5 @@ # 什么值得买 -# 注意!注意!注意! - -目前不完美: - -1. ~~签到后系统提示“签到结果: 未知”~~ (Fixed) -2. 签到后手机 APP 上显示未签到(但实际上你用 pc 浏览器登录是会显示已经签到的) - -上述问题待跟进 - ## 配置 ```properties diff --git a/smzdm/quanx/README.md b/smzdm/quanx/README.md index b3bd9203c..581a5c1cd 100644 --- a/smzdm/quanx/README.md +++ b/smzdm/quanx/README.md @@ -1,16 +1,5 @@ # 什么值得买 -> 2020.1.11 QuanX 在`190`版本开始, 获取 Cookie 方式需要从`script-response-body`改为`script-request-header` - -# 注意!注意!注意! - -目前不完美: - -1. ~~签到后系统提示“签到结果: 未知”~~ (Fixed) -2. 签到后手机 APP 上显示未签到(但实际上你用 pc 浏览器登录是会显示已经签到的) - -上述问题待跟进 - ## 配置 ```properties diff --git a/smzdm/quanx/smzdm.js b/smzdm/quanx/smzdm.js index 84ce06547..21c3709d7 100644 --- a/smzdm/quanx/smzdm.js +++ b/smzdm/quanx/smzdm.js @@ -1,41 +1,100 @@ -const cookieName = '什么值得买' -const cookieKey = 'chavy_cookie_smzdm' -const cookieVal = $prefs.valueForKey(cookieKey) - -function sign() { - let url = { - url: `https://zhiyou.smzdm.com/user/checkin/jsonp_checkin`, - headers: { - Cookie: cookieVal - } - } - url.headers['Referer'] = 'http://www.smzdm.com/' - url.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36' - - $task.fetch(url).then((response) => { - let data = response.body - let result = JSON.parse(data) - let title = `${cookieName}` - // 签到成功 - if (result && result.data && result.error_code == 0) { - let subTitle = `签到结果: 成功` - let detail = `累计: ${result.data.checkin_num}次, 经验: ${result.data.exp}, 金币: ${result.data.gold}, 积分: ${result.data.point}` - $notify(title, subTitle, detail) +// prettier-ignore +!function (t, r) { "object" == typeof exports ? module.exports = exports = r() : "function" == typeof define && define.amd ? define([], r) : t.CryptoJS = r() }(this, function () { + var t = t || function (t, r) { var e = Object.create || function () { function t() { } return function (r) { var e; return t.prototype = r, e = new t, t.prototype = null, e } }(), i = {}, n = i.lib = {}, o = n.Base = function () { return { extend: function (t) { var r = e(this); return t && r.mixIn(t), r.hasOwnProperty("init") && this.init !== r.init || (r.init = function () { r.$super.init.apply(this, arguments) }), r.init.prototype = r, r.$super = this, r }, create: function () { var t = this.extend(); return t.init.apply(t, arguments), t }, init: function () { }, mixIn: function (t) { for (var r in t) t.hasOwnProperty(r) && (this[r] = t[r]); t.hasOwnProperty("toString") && (this.toString = t.toString) }, clone: function () { return this.init.prototype.extend(this) } } }(), s = n.WordArray = o.extend({ init: function (t, e) { t = this.words = t || [], e != r ? this.sigBytes = e : this.sigBytes = 4 * t.length }, toString: function (t) { return (t || c).stringify(this) }, concat: function (t) { var r = this.words, e = t.words, i = this.sigBytes, n = t.sigBytes; if (this.clamp(), i % 4) for (var o = 0; o < n; o++) { var s = e[o >>> 2] >>> 24 - o % 4 * 8 & 255; r[i + o >>> 2] |= s << 24 - (i + o) % 4 * 8 } else for (var o = 0; o < n; o += 4)r[i + o >>> 2] = e[o >>> 2]; return this.sigBytes += n, this }, clamp: function () { var r = this.words, e = this.sigBytes; r[e >>> 2] &= 4294967295 << 32 - e % 4 * 8, r.length = t.ceil(e / 4) }, clone: function () { var t = o.clone.call(this); return t.words = this.words.slice(0), t }, random: function (r) { for (var e, i = [], n = function (r) { var r = r, e = 987654321, i = 4294967295; return function () { e = 36969 * (65535 & e) + (e >> 16) & i, r = 18e3 * (65535 & r) + (r >> 16) & i; var n = (e << 16) + r & i; return n /= 4294967296, n += .5, n * (t.random() > .5 ? 1 : -1) } }, o = 0; o < r; o += 4) { var a = n(4294967296 * (e || t.random())); e = 987654071 * a(), i.push(4294967296 * a() | 0) } return new s.init(i, r) } }), a = i.enc = {}, c = a.Hex = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n++) { var o = r[n >>> 2] >>> 24 - n % 4 * 8 & 255; i.push((o >>> 4).toString(16)), i.push((15 & o).toString(16)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i += 2)e[i >>> 3] |= parseInt(t.substr(i, 2), 16) << 24 - i % 8 * 4; return new s.init(e, r / 2) } }, h = a.Latin1 = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n++) { var o = r[n >>> 2] >>> 24 - n % 4 * 8 & 255; i.push(String.fromCharCode(o)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i++)e[i >>> 2] |= (255 & t.charCodeAt(i)) << 24 - i % 4 * 8; return new s.init(e, r) } }, l = a.Utf8 = { stringify: function (t) { try { return decodeURIComponent(escape(h.stringify(t))) } catch (t) { throw new Error("Malformed UTF-8 data") } }, parse: function (t) { return h.parse(unescape(encodeURIComponent(t))) } }, f = n.BufferedBlockAlgorithm = o.extend({ reset: function () { this._data = new s.init, this._nDataBytes = 0 }, _append: function (t) { "string" == typeof t && (t = l.parse(t)), this._data.concat(t), this._nDataBytes += t.sigBytes }, _process: function (r) { var e = this._data, i = e.words, n = e.sigBytes, o = this.blockSize, a = 4 * o, c = n / a; c = r ? t.ceil(c) : t.max((0 | c) - this._minBufferSize, 0); var h = c * o, l = t.min(4 * h, n); if (h) { for (var f = 0; f < h; f += o)this._doProcessBlock(i, f); var u = i.splice(0, h); e.sigBytes -= l } return new s.init(u, l) }, clone: function () { var t = o.clone.call(this); return t._data = this._data.clone(), t }, _minBufferSize: 0 }), u = (n.Hasher = f.extend({ cfg: o.extend(), init: function (t) { this.cfg = this.cfg.extend(t), this.reset() }, reset: function () { f.reset.call(this), this._doReset() }, update: function (t) { return this._append(t), this._process(), this }, finalize: function (t) { t && this._append(t); var r = this._doFinalize(); return r }, blockSize: 16, _createHelper: function (t) { return function (r, e) { return new t.init(e).finalize(r) } }, _createHmacHelper: function (t) { return function (r, e) { return new u.HMAC.init(t, e).finalize(r) } } }), i.algo = {}); return i }(Math); return function () { function r(t, r, e) { for (var i = [], o = 0, s = 0; s < r; s++)if (s % 4) { var a = e[t.charCodeAt(s - 1)] << s % 4 * 2, c = e[t.charCodeAt(s)] >>> 6 - s % 4 * 2; i[o >>> 2] |= (a | c) << 24 - o % 4 * 8, o++ } return n.create(i, o) } var e = t, i = e.lib, n = i.WordArray, o = e.enc; o.Base64 = { stringify: function (t) { var r = t.words, e = t.sigBytes, i = this._map; t.clamp(); for (var n = [], o = 0; o < e; o += 3)for (var s = r[o >>> 2] >>> 24 - o % 4 * 8 & 255, a = r[o + 1 >>> 2] >>> 24 - (o + 1) % 4 * 8 & 255, c = r[o + 2 >>> 2] >>> 24 - (o + 2) % 4 * 8 & 255, h = s << 16 | a << 8 | c, l = 0; l < 4 && o + .75 * l < e; l++)n.push(i.charAt(h >>> 6 * (3 - l) & 63)); var f = i.charAt(64); if (f) for (; n.length % 4;)n.push(f); return n.join("") }, parse: function (t) { var e = t.length, i = this._map, n = this._reverseMap; if (!n) { n = this._reverseMap = []; for (var o = 0; o < i.length; o++)n[i.charCodeAt(o)] = o } var s = i.charAt(64); if (s) { var a = t.indexOf(s); a !== -1 && (e = a) } return r(t, e, n) }, _map: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" } }(), function (r) { function e(t, r, e, i, n, o, s) { var a = t + (r & e | ~r & i) + n + s; return (a << o | a >>> 32 - o) + r } function i(t, r, e, i, n, o, s) { var a = t + (r & i | e & ~i) + n + s; return (a << o | a >>> 32 - o) + r } function n(t, r, e, i, n, o, s) { var a = t + (r ^ e ^ i) + n + s; return (a << o | a >>> 32 - o) + r } function o(t, r, e, i, n, o, s) { var a = t + (e ^ (r | ~i)) + n + s; return (a << o | a >>> 32 - o) + r } var s = t, a = s.lib, c = a.WordArray, h = a.Hasher, l = s.algo, f = []; !function () { for (var t = 0; t < 64; t++)f[t] = 4294967296 * r.abs(r.sin(t + 1)) | 0 }(); var u = l.MD5 = h.extend({ _doReset: function () { this._hash = new c.init([1732584193, 4023233417, 2562383102, 271733878]) }, _doProcessBlock: function (t, r) { for (var s = 0; s < 16; s++) { var a = r + s, c = t[a]; t[a] = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8) } var h = this._hash.words, l = t[r + 0], u = t[r + 1], d = t[r + 2], v = t[r + 3], p = t[r + 4], _ = t[r + 5], y = t[r + 6], g = t[r + 7], B = t[r + 8], w = t[r + 9], k = t[r + 10], S = t[r + 11], m = t[r + 12], x = t[r + 13], b = t[r + 14], H = t[r + 15], z = h[0], A = h[1], C = h[2], D = h[3]; z = e(z, A, C, D, l, 7, f[0]), D = e(D, z, A, C, u, 12, f[1]), C = e(C, D, z, A, d, 17, f[2]), A = e(A, C, D, z, v, 22, f[3]), z = e(z, A, C, D, p, 7, f[4]), D = e(D, z, A, C, _, 12, f[5]), C = e(C, D, z, A, y, 17, f[6]), A = e(A, C, D, z, g, 22, f[7]), z = e(z, A, C, D, B, 7, f[8]), D = e(D, z, A, C, w, 12, f[9]), C = e(C, D, z, A, k, 17, f[10]), A = e(A, C, D, z, S, 22, f[11]), z = e(z, A, C, D, m, 7, f[12]), D = e(D, z, A, C, x, 12, f[13]), C = e(C, D, z, A, b, 17, f[14]), A = e(A, C, D, z, H, 22, f[15]), z = i(z, A, C, D, u, 5, f[16]), D = i(D, z, A, C, y, 9, f[17]), C = i(C, D, z, A, S, 14, f[18]), A = i(A, C, D, z, l, 20, f[19]), z = i(z, A, C, D, _, 5, f[20]), D = i(D, z, A, C, k, 9, f[21]), C = i(C, D, z, A, H, 14, f[22]), A = i(A, C, D, z, p, 20, f[23]), z = i(z, A, C, D, w, 5, f[24]), D = i(D, z, A, C, b, 9, f[25]), C = i(C, D, z, A, v, 14, f[26]), A = i(A, C, D, z, B, 20, f[27]), z = i(z, A, C, D, x, 5, f[28]), D = i(D, z, A, C, d, 9, f[29]), C = i(C, D, z, A, g, 14, f[30]), A = i(A, C, D, z, m, 20, f[31]), z = n(z, A, C, D, _, 4, f[32]), D = n(D, z, A, C, B, 11, f[33]), C = n(C, D, z, A, S, 16, f[34]), A = n(A, C, D, z, b, 23, f[35]), z = n(z, A, C, D, u, 4, f[36]), D = n(D, z, A, C, p, 11, f[37]), C = n(C, D, z, A, g, 16, f[38]), A = n(A, C, D, z, k, 23, f[39]), z = n(z, A, C, D, x, 4, f[40]), D = n(D, z, A, C, l, 11, f[41]), C = n(C, D, z, A, v, 16, f[42]), A = n(A, C, D, z, y, 23, f[43]), z = n(z, A, C, D, w, 4, f[44]), D = n(D, z, A, C, m, 11, f[45]), C = n(C, D, z, A, H, 16, f[46]), A = n(A, C, D, z, d, 23, f[47]), z = o(z, A, C, D, l, 6, f[48]), D = o(D, z, A, C, g, 10, f[49]), C = o(C, D, z, A, b, 15, f[50]), A = o(A, C, D, z, _, 21, f[51]), z = o(z, A, C, D, m, 6, f[52]), D = o(D, z, A, C, v, 10, f[53]), C = o(C, D, z, A, k, 15, f[54]), A = o(A, C, D, z, u, 21, f[55]), z = o(z, A, C, D, B, 6, f[56]), D = o(D, z, A, C, H, 10, f[57]), C = o(C, D, z, A, y, 15, f[58]), A = o(A, C, D, z, x, 21, f[59]), z = o(z, A, C, D, p, 6, f[60]), D = o(D, z, A, C, S, 10, f[61]), C = o(C, D, z, A, d, 15, f[62]), A = o(A, C, D, z, w, 21, f[63]), h[0] = h[0] + z | 0, h[1] = h[1] + A | 0, h[2] = h[2] + C | 0, h[3] = h[3] + D | 0 }, _doFinalize: function () { var t = this._data, e = t.words, i = 8 * this._nDataBytes, n = 8 * t.sigBytes; e[n >>> 5] |= 128 << 24 - n % 32; var o = r.floor(i / 4294967296), s = i; e[(n + 64 >>> 9 << 4) + 15] = 16711935 & (o << 8 | o >>> 24) | 4278255360 & (o << 24 | o >>> 8), e[(n + 64 >>> 9 << 4) + 14] = 16711935 & (s << 8 | s >>> 24) | 4278255360 & (s << 24 | s >>> 8), t.sigBytes = 4 * (e.length + 1), this._process(); for (var a = this._hash, c = a.words, h = 0; h < 4; h++) { var l = c[h]; c[h] = 16711935 & (l << 8 | l >>> 24) | 4278255360 & (l << 24 | l >>> 8) } return a }, clone: function () { var t = h.clone.call(this); return t._hash = this._hash.clone(), t } }); s.MD5 = h._createHelper(u), s.HmacMD5 = h._createHmacHelper(u) }(Math), function () { var r = t, e = r.lib, i = e.WordArray, n = e.Hasher, o = r.algo, s = [], a = o.SHA1 = n.extend({ _doReset: function () { this._hash = new i.init([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], a = e[3], c = e[4], h = 0; h < 80; h++) { if (h < 16) s[h] = 0 | t[r + h]; else { var l = s[h - 3] ^ s[h - 8] ^ s[h - 14] ^ s[h - 16]; s[h] = l << 1 | l >>> 31 } var f = (i << 5 | i >>> 27) + c + s[h]; f += h < 20 ? (n & o | ~n & a) + 1518500249 : h < 40 ? (n ^ o ^ a) + 1859775393 : h < 60 ? (n & o | n & a | o & a) - 1894007588 : (n ^ o ^ a) - 899497514, c = a, a = o, o = n << 30 | n >>> 2, n = i, i = f } e[0] = e[0] + i | 0, e[1] = e[1] + n | 0, e[2] = e[2] + o | 0, e[3] = e[3] + a | 0, e[4] = e[4] + c | 0 }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; return r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 64 >>> 9 << 4) + 14] = Math.floor(e / 4294967296), r[(i + 64 >>> 9 << 4) + 15] = e, t.sigBytes = 4 * r.length, this._process(), this._hash }, clone: function () { var t = n.clone.call(this); return t._hash = this._hash.clone(), t } }); r.SHA1 = n._createHelper(a), r.HmacSHA1 = n._createHmacHelper(a) }(), function (r) { var e = t, i = e.lib, n = i.WordArray, o = i.Hasher, s = e.algo, a = [], c = []; !function () { function t(t) { for (var e = r.sqrt(t), i = 2; i <= e; i++)if (!(t % i)) return !1; return !0 } function e(t) { return 4294967296 * (t - (0 | t)) | 0 } for (var i = 2, n = 0; n < 64;)t(i) && (n < 8 && (a[n] = e(r.pow(i, .5))), c[n] = e(r.pow(i, 1 / 3)), n++), i++ }(); var h = [], l = s.SHA256 = o.extend({ _doReset: function () { this._hash = new n.init(a.slice(0)) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], s = e[3], a = e[4], l = e[5], f = e[6], u = e[7], d = 0; d < 64; d++) { if (d < 16) h[d] = 0 | t[r + d]; else { var v = h[d - 15], p = (v << 25 | v >>> 7) ^ (v << 14 | v >>> 18) ^ v >>> 3, _ = h[d - 2], y = (_ << 15 | _ >>> 17) ^ (_ << 13 | _ >>> 19) ^ _ >>> 10; h[d] = p + h[d - 7] + y + h[d - 16] } var g = a & l ^ ~a & f, B = i & n ^ i & o ^ n & o, w = (i << 30 | i >>> 2) ^ (i << 19 | i >>> 13) ^ (i << 10 | i >>> 22), k = (a << 26 | a >>> 6) ^ (a << 21 | a >>> 11) ^ (a << 7 | a >>> 25), S = u + k + g + c[d] + h[d], m = w + B; u = f, f = l, l = a, a = s + S | 0, s = o, o = n, n = i, i = S + m | 0 } e[0] = e[0] + i | 0, e[1] = e[1] + n | 0, e[2] = e[2] + o | 0, e[3] = e[3] + s | 0, e[4] = e[4] + a | 0, e[5] = e[5] + l | 0, e[6] = e[6] + f | 0, e[7] = e[7] + u | 0 }, _doFinalize: function () { var t = this._data, e = t.words, i = 8 * this._nDataBytes, n = 8 * t.sigBytes; return e[n >>> 5] |= 128 << 24 - n % 32, e[(n + 64 >>> 9 << 4) + 14] = r.floor(i / 4294967296), e[(n + 64 >>> 9 << 4) + 15] = i, t.sigBytes = 4 * e.length, this._process(), this._hash }, clone: function () { var t = o.clone.call(this); return t._hash = this._hash.clone(), t } }); e.SHA256 = o._createHelper(l), e.HmacSHA256 = o._createHmacHelper(l) }(Math), function () { function r(t) { return t << 8 & 4278255360 | t >>> 8 & 16711935 } var e = t, i = e.lib, n = i.WordArray, o = e.enc; o.Utf16 = o.Utf16BE = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n += 2) { var o = r[n >>> 2] >>> 16 - n % 4 * 8 & 65535; i.push(String.fromCharCode(o)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i++)e[i >>> 1] |= t.charCodeAt(i) << 16 - i % 2 * 16; return n.create(e, 2 * r) } }; o.Utf16LE = { stringify: function (t) { for (var e = t.words, i = t.sigBytes, n = [], o = 0; o < i; o += 2) { var s = r(e[o >>> 2] >>> 16 - o % 4 * 8 & 65535); n.push(String.fromCharCode(s)) } return n.join("") }, parse: function (t) { for (var e = t.length, i = [], o = 0; o < e; o++)i[o >>> 1] |= r(t.charCodeAt(o) << 16 - o % 2 * 16); return n.create(i, 2 * e) } } }(), function () { if ("function" == typeof ArrayBuffer) { var r = t, e = r.lib, i = e.WordArray, n = i.init, o = i.init = function (t) { if (t instanceof ArrayBuffer && (t = new Uint8Array(t)), (t instanceof Int8Array || "undefined" != typeof Uint8ClampedArray && t instanceof Uint8ClampedArray || t instanceof Int16Array || t instanceof Uint16Array || t instanceof Int32Array || t instanceof Uint32Array || t instanceof Float32Array || t instanceof Float64Array) && (t = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), t instanceof Uint8Array) { for (var r = t.byteLength, e = [], i = 0; i < r; i++)e[i >>> 2] |= t[i] << 24 - i % 4 * 8; n.call(this, e, r) } else n.apply(this, arguments) }; o.prototype = i } }(), function (r) { function e(t, r, e) { return t ^ r ^ e } function i(t, r, e) { return t & r | ~t & e } function n(t, r, e) { return (t | ~r) ^ e } function o(t, r, e) { return t & e | r & ~e } function s(t, r, e) { return t ^ (r | ~e) } function a(t, r) { return t << r | t >>> 32 - r } var c = t, h = c.lib, l = h.WordArray, f = h.Hasher, u = c.algo, d = l.create([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]), v = l.create([5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]), p = l.create([11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6]), _ = l.create([8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]), y = l.create([0, 1518500249, 1859775393, 2400959708, 2840853838]), g = l.create([1352829926, 1548603684, 1836072691, 2053994217, 0]), B = u.RIPEMD160 = f.extend({ _doReset: function () { this._hash = l.create([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) }, _doProcessBlock: function (t, r) { for (var c = 0; c < 16; c++) { var h = r + c, l = t[h]; t[h] = 16711935 & (l << 8 | l >>> 24) | 4278255360 & (l << 24 | l >>> 8) } var f, u, B, w, k, S, m, x, b, H, z = this._hash.words, A = y.words, C = g.words, D = d.words, R = v.words, E = p.words, M = _.words; S = f = z[0], m = u = z[1], x = B = z[2], b = w = z[3], H = k = z[4]; for (var F, c = 0; c < 80; c += 1)F = f + t[r + D[c]] | 0, F += c < 16 ? e(u, B, w) + A[0] : c < 32 ? i(u, B, w) + A[1] : c < 48 ? n(u, B, w) + A[2] : c < 64 ? o(u, B, w) + A[3] : s(u, B, w) + A[4], F |= 0, F = a(F, E[c]), F = F + k | 0, f = k, k = w, w = a(B, 10), B = u, u = F, F = S + t[r + R[c]] | 0, F += c < 16 ? s(m, x, b) + C[0] : c < 32 ? o(m, x, b) + C[1] : c < 48 ? n(m, x, b) + C[2] : c < 64 ? i(m, x, b) + C[3] : e(m, x, b) + C[4], F |= 0, F = a(F, M[c]), F = F + H | 0, S = H, H = b, b = a(x, 10), x = m, m = F; F = z[1] + B + b | 0, z[1] = z[2] + w + H | 0, z[2] = z[3] + k + S | 0, z[3] = z[4] + f + m | 0, z[4] = z[0] + u + x | 0, z[0] = F }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 64 >>> 9 << 4) + 14] = 16711935 & (e << 8 | e >>> 24) | 4278255360 & (e << 24 | e >>> 8), t.sigBytes = 4 * (r.length + 1), this._process(); for (var n = this._hash, o = n.words, s = 0; s < 5; s++) { var a = o[s]; o[s] = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8) } return n }, clone: function () { var t = f.clone.call(this); return t._hash = this._hash.clone(), t } }); c.RIPEMD160 = f._createHelper(B), c.HmacRIPEMD160 = f._createHmacHelper(B) }(Math), function () { var r = t, e = r.lib, i = e.Base, n = r.enc, o = n.Utf8, s = r.algo; s.HMAC = i.extend({ init: function (t, r) { t = this._hasher = new t.init, "string" == typeof r && (r = o.parse(r)); var e = t.blockSize, i = 4 * e; r.sigBytes > i && (r = t.finalize(r)), r.clamp(); for (var n = this._oKey = r.clone(), s = this._iKey = r.clone(), a = n.words, c = s.words, h = 0; h < e; h++)a[h] ^= 1549556828, c[h] ^= 909522486; n.sigBytes = s.sigBytes = i, this.reset() }, reset: function () { var t = this._hasher; t.reset(), t.update(this._iKey) }, update: function (t) { return this._hasher.update(t), this }, finalize: function (t) { var r = this._hasher, e = r.finalize(t); r.reset(); var i = r.finalize(this._oKey.clone().concat(e)); return i } }) }(), function () { var r = t, e = r.lib, i = e.Base, n = e.WordArray, o = r.algo, s = o.SHA1, a = o.HMAC, c = o.PBKDF2 = i.extend({ cfg: i.extend({ keySize: 4, hasher: s, iterations: 1 }), init: function (t) { this.cfg = this.cfg.extend(t) }, compute: function (t, r) { for (var e = this.cfg, i = a.create(e.hasher, t), o = n.create(), s = n.create([1]), c = o.words, h = s.words, l = e.keySize, f = e.iterations; c.length < l;) { var u = i.update(r).finalize(s); i.reset(); for (var d = u.words, v = d.length, p = u, _ = 1; _ < f; _++) { p = i.finalize(p), i.reset(); for (var y = p.words, g = 0; g < v; g++)d[g] ^= y[g] } o.concat(u), h[0]++ } return o.sigBytes = 4 * l, o } }); r.PBKDF2 = function (t, r, e) { return c.create(e).compute(t, r) } }(), function () { var r = t, e = r.lib, i = e.Base, n = e.WordArray, o = r.algo, s = o.MD5, a = o.EvpKDF = i.extend({ cfg: i.extend({ keySize: 4, hasher: s, iterations: 1 }), init: function (t) { this.cfg = this.cfg.extend(t) }, compute: function (t, r) { for (var e = this.cfg, i = e.hasher.create(), o = n.create(), s = o.words, a = e.keySize, c = e.iterations; s.length < a;) { h && i.update(h); var h = i.update(t).finalize(r); i.reset(); for (var l = 1; l < c; l++)h = i.finalize(h), i.reset(); o.concat(h) } return o.sigBytes = 4 * a, o } }); r.EvpKDF = function (t, r, e) { return a.create(e).compute(t, r) } }(), function () { var r = t, e = r.lib, i = e.WordArray, n = r.algo, o = n.SHA256, s = n.SHA224 = o.extend({ _doReset: function () { this._hash = new i.init([3238371032, 914150663, 812702999, 4144912697, 4290775857, 1750603025, 1694076839, 3204075428]) }, _doFinalize: function () { var t = o._doFinalize.call(this); return t.sigBytes -= 4, t } }); r.SHA224 = o._createHelper(s), r.HmacSHA224 = o._createHmacHelper(s) }(), function (r) { var e = t, i = e.lib, n = i.Base, o = i.WordArray, s = e.x64 = {}; s.Word = n.extend({ init: function (t, r) { this.high = t, this.low = r } }), s.WordArray = n.extend({ init: function (t, e) { t = this.words = t || [], e != r ? this.sigBytes = e : this.sigBytes = 8 * t.length }, toX32: function () { for (var t = this.words, r = t.length, e = [], i = 0; i < r; i++) { var n = t[i]; e.push(n.high), e.push(n.low) } return o.create(e, this.sigBytes) }, clone: function () { for (var t = n.clone.call(this), r = t.words = this.words.slice(0), e = r.length, i = 0; i < e; i++)r[i] = r[i].clone(); return t } }) }(), function (r) { var e = t, i = e.lib, n = i.WordArray, o = i.Hasher, s = e.x64, a = s.Word, c = e.algo, h = [], l = [], f = []; !function () { for (var t = 1, r = 0, e = 0; e < 24; e++) { h[t + 5 * r] = (e + 1) * (e + 2) / 2 % 64; var i = r % 5, n = (2 * t + 3 * r) % 5; t = i, r = n } for (var t = 0; t < 5; t++)for (var r = 0; r < 5; r++)l[t + 5 * r] = r + (2 * t + 3 * r) % 5 * 5; for (var o = 1, s = 0; s < 24; s++) { for (var c = 0, u = 0, d = 0; d < 7; d++) { if (1 & o) { var v = (1 << d) - 1; v < 32 ? u ^= 1 << v : c ^= 1 << v - 32 } 128 & o ? o = o << 1 ^ 113 : o <<= 1 } f[s] = a.create(c, u) } }(); var u = []; !function () { for (var t = 0; t < 25; t++)u[t] = a.create() }(); var d = c.SHA3 = o.extend({ cfg: o.cfg.extend({ outputLength: 512 }), _doReset: function () { for (var t = this._state = [], r = 0; r < 25; r++)t[r] = new a.init; this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32 }, _doProcessBlock: function (t, r) { for (var e = this._state, i = this.blockSize / 2, n = 0; n < i; n++) { var o = t[r + 2 * n], s = t[r + 2 * n + 1]; o = 16711935 & (o << 8 | o >>> 24) | 4278255360 & (o << 24 | o >>> 8), s = 16711935 & (s << 8 | s >>> 24) | 4278255360 & (s << 24 | s >>> 8); var a = e[n]; a.high ^= s, a.low ^= o } for (var c = 0; c < 24; c++) { for (var d = 0; d < 5; d++) { for (var v = 0, p = 0, _ = 0; _ < 5; _++) { var a = e[d + 5 * _]; v ^= a.high, p ^= a.low } var y = u[d]; y.high = v, y.low = p } for (var d = 0; d < 5; d++)for (var g = u[(d + 4) % 5], B = u[(d + 1) % 5], w = B.high, k = B.low, v = g.high ^ (w << 1 | k >>> 31), p = g.low ^ (k << 1 | w >>> 31), _ = 0; _ < 5; _++) { var a = e[d + 5 * _]; a.high ^= v, a.low ^= p } for (var S = 1; S < 25; S++) { var a = e[S], m = a.high, x = a.low, b = h[S]; if (b < 32) var v = m << b | x >>> 32 - b, p = x << b | m >>> 32 - b; else var v = x << b - 32 | m >>> 64 - b, p = m << b - 32 | x >>> 64 - b; var H = u[l[S]]; H.high = v, H.low = p } var z = u[0], A = e[0]; z.high = A.high, z.low = A.low; for (var d = 0; d < 5; d++)for (var _ = 0; _ < 5; _++) { var S = d + 5 * _, a = e[S], C = u[S], D = u[(d + 1) % 5 + 5 * _], R = u[(d + 2) % 5 + 5 * _]; a.high = C.high ^ ~D.high & R.high, a.low = C.low ^ ~D.low & R.low } var a = e[0], E = f[c]; a.high ^= E.high, a.low ^= E.low } }, _doFinalize: function () { var t = this._data, e = t.words, i = (8 * this._nDataBytes, 8 * t.sigBytes), o = 32 * this.blockSize; e[i >>> 5] |= 1 << 24 - i % 32, e[(r.ceil((i + 1) / o) * o >>> 5) - 1] |= 128, t.sigBytes = 4 * e.length, this._process(); for (var s = this._state, a = this.cfg.outputLength / 8, c = a / 8, h = [], l = 0; l < c; l++) { var f = s[l], u = f.high, d = f.low; u = 16711935 & (u << 8 | u >>> 24) | 4278255360 & (u << 24 | u >>> 8), d = 16711935 & (d << 8 | d >>> 24) | 4278255360 & (d << 24 | d >>> 8), h.push(d), h.push(u) } return new n.init(h, a) }, clone: function () { for (var t = o.clone.call(this), r = t._state = this._state.slice(0), e = 0; e < 25; e++)r[e] = r[e].clone(); return t } }); e.SHA3 = o._createHelper(d), e.HmacSHA3 = o._createHmacHelper(d) }(Math), function () { function r() { return s.create.apply(s, arguments) } var e = t, i = e.lib, n = i.Hasher, o = e.x64, s = o.Word, a = o.WordArray, c = e.algo, h = [r(1116352408, 3609767458), r(1899447441, 602891725), r(3049323471, 3964484399), r(3921009573, 2173295548), r(961987163, 4081628472), r(1508970993, 3053834265), r(2453635748, 2937671579), r(2870763221, 3664609560), r(3624381080, 2734883394), r(310598401, 1164996542), r(607225278, 1323610764), r(1426881987, 3590304994), r(1925078388, 4068182383), r(2162078206, 991336113), r(2614888103, 633803317), r(3248222580, 3479774868), r(3835390401, 2666613458), r(4022224774, 944711139), r(264347078, 2341262773), r(604807628, 2007800933), r(770255983, 1495990901), r(1249150122, 1856431235), r(1555081692, 3175218132), r(1996064986, 2198950837), r(2554220882, 3999719339), r(2821834349, 766784016), r(2952996808, 2566594879), r(3210313671, 3203337956), r(3336571891, 1034457026), r(3584528711, 2466948901), r(113926993, 3758326383), r(338241895, 168717936), r(666307205, 1188179964), r(773529912, 1546045734), r(1294757372, 1522805485), r(1396182291, 2643833823), r(1695183700, 2343527390), r(1986661051, 1014477480), r(2177026350, 1206759142), r(2456956037, 344077627), r(2730485921, 1290863460), r(2820302411, 3158454273), r(3259730800, 3505952657), r(3345764771, 106217008), r(3516065817, 3606008344), r(3600352804, 1432725776), r(4094571909, 1467031594), r(275423344, 851169720), r(430227734, 3100823752), r(506948616, 1363258195), r(659060556, 3750685593), r(883997877, 3785050280), r(958139571, 3318307427), r(1322822218, 3812723403), r(1537002063, 2003034995), r(1747873779, 3602036899), r(1955562222, 1575990012), r(2024104815, 1125592928), r(2227730452, 2716904306), r(2361852424, 442776044), r(2428436474, 593698344), r(2756734187, 3733110249), r(3204031479, 2999351573), r(3329325298, 3815920427), r(3391569614, 3928383900), r(3515267271, 566280711), r(3940187606, 3454069534), r(4118630271, 4000239992), r(116418474, 1914138554), r(174292421, 2731055270), r(289380356, 3203993006), r(460393269, 320620315), r(685471733, 587496836), r(852142971, 1086792851), r(1017036298, 365543100), r(1126000580, 2618297676), r(1288033470, 3409855158), r(1501505948, 4234509866), r(1607167915, 987167468), r(1816402316, 1246189591)], l = []; !function () { for (var t = 0; t < 80; t++)l[t] = r() }(); var f = c.SHA512 = n.extend({ _doReset: function () { this._hash = new a.init([new s.init(1779033703, 4089235720), new s.init(3144134277, 2227873595), new s.init(1013904242, 4271175723), new s.init(2773480762, 1595750129), new s.init(1359893119, 2917565137), new s.init(2600822924, 725511199), new s.init(528734635, 4215389547), new s.init(1541459225, 327033209)]) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], s = e[3], a = e[4], c = e[5], f = e[6], u = e[7], d = i.high, v = i.low, p = n.high, _ = n.low, y = o.high, g = o.low, B = s.high, w = s.low, k = a.high, S = a.low, m = c.high, x = c.low, b = f.high, H = f.low, z = u.high, A = u.low, C = d, D = v, R = p, E = _, M = y, F = g, P = B, W = w, O = k, U = S, I = m, K = x, X = b, L = H, j = z, N = A, T = 0; T < 80; T++) { var Z = l[T]; if (T < 16) var q = Z.high = 0 | t[r + 2 * T], G = Z.low = 0 | t[r + 2 * T + 1]; else { var J = l[T - 15], $ = J.high, Q = J.low, V = ($ >>> 1 | Q << 31) ^ ($ >>> 8 | Q << 24) ^ $ >>> 7, Y = (Q >>> 1 | $ << 31) ^ (Q >>> 8 | $ << 24) ^ (Q >>> 7 | $ << 25), tt = l[T - 2], rt = tt.high, et = tt.low, it = (rt >>> 19 | et << 13) ^ (rt << 3 | et >>> 29) ^ rt >>> 6, nt = (et >>> 19 | rt << 13) ^ (et << 3 | rt >>> 29) ^ (et >>> 6 | rt << 26), ot = l[T - 7], st = ot.high, at = ot.low, ct = l[T - 16], ht = ct.high, lt = ct.low, G = Y + at, q = V + st + (G >>> 0 < Y >>> 0 ? 1 : 0), G = G + nt, q = q + it + (G >>> 0 < nt >>> 0 ? 1 : 0), G = G + lt, q = q + ht + (G >>> 0 < lt >>> 0 ? 1 : 0); Z.high = q, Z.low = G } var ft = O & I ^ ~O & X, ut = U & K ^ ~U & L, dt = C & R ^ C & M ^ R & M, vt = D & E ^ D & F ^ E & F, pt = (C >>> 28 | D << 4) ^ (C << 30 | D >>> 2) ^ (C << 25 | D >>> 7), _t = (D >>> 28 | C << 4) ^ (D << 30 | C >>> 2) ^ (D << 25 | C >>> 7), yt = (O >>> 14 | U << 18) ^ (O >>> 18 | U << 14) ^ (O << 23 | U >>> 9), gt = (U >>> 14 | O << 18) ^ (U >>> 18 | O << 14) ^ (U << 23 | O >>> 9), Bt = h[T], wt = Bt.high, kt = Bt.low, St = N + gt, mt = j + yt + (St >>> 0 < N >>> 0 ? 1 : 0), St = St + ut, mt = mt + ft + (St >>> 0 < ut >>> 0 ? 1 : 0), St = St + kt, mt = mt + wt + (St >>> 0 < kt >>> 0 ? 1 : 0), St = St + G, mt = mt + q + (St >>> 0 < G >>> 0 ? 1 : 0), xt = _t + vt, bt = pt + dt + (xt >>> 0 < _t >>> 0 ? 1 : 0); j = X, N = L, X = I, L = K, I = O, K = U, U = W + St | 0, O = P + mt + (U >>> 0 < W >>> 0 ? 1 : 0) | 0, P = M, W = F, M = R, F = E, R = C, E = D, D = St + xt | 0, C = mt + bt + (D >>> 0 < St >>> 0 ? 1 : 0) | 0 } v = i.low = v + D, i.high = d + C + (v >>> 0 < D >>> 0 ? 1 : 0), _ = n.low = _ + E, n.high = p + R + (_ >>> 0 < E >>> 0 ? 1 : 0), g = o.low = g + F, o.high = y + M + (g >>> 0 < F >>> 0 ? 1 : 0), w = s.low = w + W, s.high = B + P + (w >>> 0 < W >>> 0 ? 1 : 0), S = a.low = S + U, a.high = k + O + (S >>> 0 < U >>> 0 ? 1 : 0), x = c.low = x + K, c.high = m + I + (x >>> 0 < K >>> 0 ? 1 : 0), H = f.low = H + L, f.high = b + X + (H >>> 0 < L >>> 0 ? 1 : 0), A = u.low = A + N, u.high = z + j + (A >>> 0 < N >>> 0 ? 1 : 0) }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 128 >>> 10 << 5) + 30] = Math.floor(e / 4294967296), r[(i + 128 >>> 10 << 5) + 31] = e, t.sigBytes = 4 * r.length, this._process(); var n = this._hash.toX32(); return n }, clone: function () { var t = n.clone.call(this); return t._hash = this._hash.clone(), t }, blockSize: 32 }); e.SHA512 = n._createHelper(f), e.HmacSHA512 = n._createHmacHelper(f) }(), function () { var r = t, e = r.x64, i = e.Word, n = e.WordArray, o = r.algo, s = o.SHA512, a = o.SHA384 = s.extend({ _doReset: function () { this._hash = new n.init([new i.init(3418070365, 3238371032), new i.init(1654270250, 914150663), new i.init(2438529370, 812702999), new i.init(355462360, 4144912697), new i.init(1731405415, 4290775857), new i.init(2394180231, 1750603025), new i.init(3675008525, 1694076839), new i.init(1203062813, 3204075428)]) }, _doFinalize: function () { var t = s._doFinalize.call(this); return t.sigBytes -= 16, t } }); r.SHA384 = s._createHelper(a), r.HmacSHA384 = s._createHmacHelper(a) }(), t.lib.Cipher || function (r) { var e = t, i = e.lib, n = i.Base, o = i.WordArray, s = i.BufferedBlockAlgorithm, a = e.enc, c = (a.Utf8, a.Base64), h = e.algo, l = h.EvpKDF, f = i.Cipher = s.extend({ cfg: n.extend(), createEncryptor: function (t, r) { return this.create(this._ENC_XFORM_MODE, t, r) }, createDecryptor: function (t, r) { return this.create(this._DEC_XFORM_MODE, t, r) }, init: function (t, r, e) { this.cfg = this.cfg.extend(e), this._xformMode = t, this._key = r, this.reset() }, reset: function () { s.reset.call(this), this._doReset() }, process: function (t) { return this._append(t), this._process() }, finalize: function (t) { t && this._append(t); var r = this._doFinalize(); return r }, keySize: 4, ivSize: 4, _ENC_XFORM_MODE: 1, _DEC_XFORM_MODE: 2, _createHelper: function () { function t(t) { return "string" == typeof t ? m : w } return function (r) { return { encrypt: function (e, i, n) { return t(i).encrypt(r, e, i, n) }, decrypt: function (e, i, n) { return t(i).decrypt(r, e, i, n) } } } }() }), u = (i.StreamCipher = f.extend({ _doFinalize: function () { var t = this._process(!0); return t }, blockSize: 1 }), e.mode = {}), d = i.BlockCipherMode = n.extend({ createEncryptor: function (t, r) { return this.Encryptor.create(t, r) }, createDecryptor: function (t, r) { return this.Decryptor.create(t, r) }, init: function (t, r) { this._cipher = t, this._iv = r } }), v = u.CBC = function () { function t(t, e, i) { var n = this._iv; if (n) { var o = n; this._iv = r } else var o = this._prevBlock; for (var s = 0; s < i; s++)t[e + s] ^= o[s] } var e = d.extend(); return e.Encryptor = e.extend({ processBlock: function (r, e) { var i = this._cipher, n = i.blockSize; t.call(this, r, e, n), i.encryptBlock(r, e), this._prevBlock = r.slice(e, e + n) } }), e.Decryptor = e.extend({ processBlock: function (r, e) { var i = this._cipher, n = i.blockSize, o = r.slice(e, e + n); i.decryptBlock(r, e), t.call(this, r, e, n), this._prevBlock = o } }), e }(), p = e.pad = {}, _ = p.Pkcs7 = { pad: function (t, r) { for (var e = 4 * r, i = e - t.sigBytes % e, n = i << 24 | i << 16 | i << 8 | i, s = [], a = 0; a < i; a += 4)s.push(n); var c = o.create(s, i); t.concat(c) }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, y = (i.BlockCipher = f.extend({ cfg: f.cfg.extend({ mode: v, padding: _ }), reset: function () { f.reset.call(this); var t = this.cfg, r = t.iv, e = t.mode; if (this._xformMode == this._ENC_XFORM_MODE) var i = e.createEncryptor; else { var i = e.createDecryptor; this._minBufferSize = 1 } this._mode && this._mode.__creator == i ? this._mode.init(this, r && r.words) : (this._mode = i.call(e, this, r && r.words), this._mode.__creator = i) }, _doProcessBlock: function (t, r) { this._mode.processBlock(t, r) }, _doFinalize: function () { var t = this.cfg.padding; if (this._xformMode == this._ENC_XFORM_MODE) { t.pad(this._data, this.blockSize); var r = this._process(!0) } else { var r = this._process(!0); t.unpad(r) } return r }, blockSize: 4 }), i.CipherParams = n.extend({ init: function (t) { this.mixIn(t) }, toString: function (t) { return (t || this.formatter).stringify(this) } })), g = e.format = {}, B = g.OpenSSL = { stringify: function (t) { var r = t.ciphertext, e = t.salt; if (e) var i = o.create([1398893684, 1701076831]).concat(e).concat(r); else var i = r; return i.toString(c) }, parse: function (t) { var r = c.parse(t), e = r.words; if (1398893684 == e[0] && 1701076831 == e[1]) { var i = o.create(e.slice(2, 4)); e.splice(0, 4), r.sigBytes -= 16 } return y.create({ ciphertext: r, salt: i }) } }, w = i.SerializableCipher = n.extend({ cfg: n.extend({ format: B }), encrypt: function (t, r, e, i) { i = this.cfg.extend(i); var n = t.createEncryptor(e, i), o = n.finalize(r), s = n.cfg; return y.create({ ciphertext: o, key: e, iv: s.iv, algorithm: t, mode: s.mode, padding: s.padding, blockSize: t.blockSize, formatter: i.format }) }, decrypt: function (t, r, e, i) { i = this.cfg.extend(i), r = this._parse(r, i.format); var n = t.createDecryptor(e, i).finalize(r.ciphertext); return n }, _parse: function (t, r) { return "string" == typeof t ? r.parse(t, this) : t } }), k = e.kdf = {}, S = k.OpenSSL = { execute: function (t, r, e, i) { i || (i = o.random(8)); var n = l.create({ keySize: r + e }).compute(t, i), s = o.create(n.words.slice(r), 4 * e); return n.sigBytes = 4 * r, y.create({ key: n, iv: s, salt: i }) } }, m = i.PasswordBasedCipher = w.extend({ cfg: w.cfg.extend({ kdf: S }), encrypt: function (t, r, e, i) { i = this.cfg.extend(i); var n = i.kdf.execute(e, t.keySize, t.ivSize); i.iv = n.iv; var o = w.encrypt.call(this, t, r, n.key, i); return o.mixIn(n), o }, decrypt: function (t, r, e, i) { i = this.cfg.extend(i), r = this._parse(r, i.format); var n = i.kdf.execute(e, t.keySize, t.ivSize, r.salt); i.iv = n.iv; var o = w.decrypt.call(this, t, r, n.key, i); return o } }) }(), t.mode.CFB = function () { function r(t, r, e, i) { var n = this._iv; if (n) { var o = n.slice(0); this._iv = void 0 } else var o = this._prevBlock; i.encryptBlock(o, 0); for (var s = 0; s < e; s++)t[r + s] ^= o[s] } var e = t.lib.BlockCipherMode.extend(); return e.Encryptor = e.extend({ processBlock: function (t, e) { var i = this._cipher, n = i.blockSize; r.call(this, t, e, n, i), this._prevBlock = t.slice(e, e + n) } }), e.Decryptor = e.extend({ processBlock: function (t, e) { var i = this._cipher, n = i.blockSize, o = t.slice(e, e + n); r.call(this, t, e, n, i), this._prevBlock = o } }), e }(), t.mode.ECB = function () { var r = t.lib.BlockCipherMode.extend(); return r.Encryptor = r.extend({ processBlock: function (t, r) { this._cipher.encryptBlock(t, r) } }), r.Decryptor = r.extend({ processBlock: function (t, r) { this._cipher.decryptBlock(t, r) } }), r }(), t.pad.AnsiX923 = { pad: function (t, r) { var e = t.sigBytes, i = 4 * r, n = i - e % i, o = e + n - 1; t.clamp(), t.words[o >>> 2] |= n << 24 - o % 4 * 8, t.sigBytes += n }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, t.pad.Iso10126 = { pad: function (r, e) { var i = 4 * e, n = i - r.sigBytes % i; r.concat(t.lib.WordArray.random(n - 1)).concat(t.lib.WordArray.create([n << 24], 1)) }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, t.pad.Iso97971 = { pad: function (r, e) { r.concat(t.lib.WordArray.create([2147483648], 1)), t.pad.ZeroPadding.pad(r, e) }, unpad: function (r) { t.pad.ZeroPadding.unpad(r), r.sigBytes-- } }, t.mode.OFB = function () { var r = t.lib.BlockCipherMode.extend(), e = r.Encryptor = r.extend({ processBlock: function (t, r) { var e = this._cipher, i = e.blockSize, n = this._iv, o = this._keystream; n && (o = this._keystream = n.slice(0), this._iv = void 0), e.encryptBlock(o, 0); for (var s = 0; s < i; s++)t[r + s] ^= o[s] } }); return r.Decryptor = e, r }(), t.pad.NoPadding = { pad: function () { }, unpad: function () { } }, function (r) { var e = t, i = e.lib, n = i.CipherParams, o = e.enc, s = o.Hex, a = e.format; a.Hex = { stringify: function (t) { return t.ciphertext.toString(s) }, parse: function (t) { var r = s.parse(t); return n.create({ ciphertext: r }) } } }(), function () { var r = t, e = r.lib, i = e.BlockCipher, n = r.algo, o = [], s = [], a = [], c = [], h = [], l = [], f = [], u = [], d = [], v = []; !function () { for (var t = [], r = 0; r < 256; r++)r < 128 ? t[r] = r << 1 : t[r] = r << 1 ^ 283; for (var e = 0, i = 0, r = 0; r < 256; r++) { var n = i ^ i << 1 ^ i << 2 ^ i << 3 ^ i << 4; n = n >>> 8 ^ 255 & n ^ 99, o[e] = n, s[n] = e; var p = t[e], _ = t[p], y = t[_], g = 257 * t[n] ^ 16843008 * n; a[e] = g << 24 | g >>> 8, c[e] = g << 16 | g >>> 16, h[e] = g << 8 | g >>> 24, l[e] = g; var g = 16843009 * y ^ 65537 * _ ^ 257 * p ^ 16843008 * e; f[n] = g << 24 | g >>> 8, u[n] = g << 16 | g >>> 16, d[n] = g << 8 | g >>> 24, v[n] = g, e ? (e = p ^ t[t[t[y ^ p]]], i ^= t[t[i]]) : e = i = 1 } }(); var p = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54], _ = n.AES = i.extend({ _doReset: function () { if (!this._nRounds || this._keyPriorReset !== this._key) { for (var t = this._keyPriorReset = this._key, r = t.words, e = t.sigBytes / 4, i = this._nRounds = e + 6, n = 4 * (i + 1), s = this._keySchedule = [], a = 0; a < n; a++)if (a < e) s[a] = r[a]; else { var c = s[a - 1]; a % e ? e > 6 && a % e == 4 && (c = o[c >>> 24] << 24 | o[c >>> 16 & 255] << 16 | o[c >>> 8 & 255] << 8 | o[255 & c]) : (c = c << 8 | c >>> 24, c = o[c >>> 24] << 24 | o[c >>> 16 & 255] << 16 | o[c >>> 8 & 255] << 8 | o[255 & c], c ^= p[a / e | 0] << 24), s[a] = s[a - e] ^ c } for (var h = this._invKeySchedule = [], l = 0; l < n; l++) { var a = n - l; if (l % 4) var c = s[a]; else var c = s[a - 4]; l < 4 || a <= 4 ? h[l] = c : h[l] = f[o[c >>> 24]] ^ u[o[c >>> 16 & 255]] ^ d[o[c >>> 8 & 255]] ^ v[o[255 & c]] } } }, encryptBlock: function (t, r) { this._doCryptBlock(t, r, this._keySchedule, a, c, h, l, o) }, decryptBlock: function (t, r) { var e = t[r + 1]; t[r + 1] = t[r + 3], t[r + 3] = e, this._doCryptBlock(t, r, this._invKeySchedule, f, u, d, v, s); var e = t[r + 1]; t[r + 1] = t[r + 3], t[r + 3] = e }, _doCryptBlock: function (t, r, e, i, n, o, s, a) { for (var c = this._nRounds, h = t[r] ^ e[0], l = t[r + 1] ^ e[1], f = t[r + 2] ^ e[2], u = t[r + 3] ^ e[3], d = 4, v = 1; v < c; v++) { var p = i[h >>> 24] ^ n[l >>> 16 & 255] ^ o[f >>> 8 & 255] ^ s[255 & u] ^ e[d++], _ = i[l >>> 24] ^ n[f >>> 16 & 255] ^ o[u >>> 8 & 255] ^ s[255 & h] ^ e[d++], y = i[f >>> 24] ^ n[u >>> 16 & 255] ^ o[h >>> 8 & 255] ^ s[255 & l] ^ e[d++], g = i[u >>> 24] ^ n[h >>> 16 & 255] ^ o[l >>> 8 & 255] ^ s[255 & f] ^ e[d++]; h = p, l = _, f = y, u = g } var p = (a[h >>> 24] << 24 | a[l >>> 16 & 255] << 16 | a[f >>> 8 & 255] << 8 | a[255 & u]) ^ e[d++], _ = (a[l >>> 24] << 24 | a[f >>> 16 & 255] << 16 | a[u >>> 8 & 255] << 8 | a[255 & h]) ^ e[d++], y = (a[f >>> 24] << 24 | a[u >>> 16 & 255] << 16 | a[h >>> 8 & 255] << 8 | a[255 & l]) ^ e[d++], g = (a[u >>> 24] << 24 | a[h >>> 16 & 255] << 16 | a[l >>> 8 & 255] << 8 | a[255 & f]) ^ e[d++]; t[r] = p, t[r + 1] = _, t[r + 2] = y, t[r + 3] = g }, keySize: 8 }); r.AES = i._createHelper(_) }(), function () { + function r(t, r) { var e = (this._lBlock >>> t ^ this._rBlock) & r; this._rBlock ^= e, this._lBlock ^= e << t } function e(t, r) { + var e = (this._rBlock >>> t ^ this._lBlock) & r; this._lBlock ^= e, this._rBlock ^= e << t; + } var i = t, n = i.lib, o = n.WordArray, s = n.BlockCipher, a = i.algo, c = [57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4], h = [14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32], l = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28], f = [{ 0: 8421888, 268435456: 32768, 536870912: 8421378, 805306368: 2, 1073741824: 512, 1342177280: 8421890, 1610612736: 8389122, 1879048192: 8388608, 2147483648: 514, 2415919104: 8389120, 2684354560: 33280, 2952790016: 8421376, 3221225472: 32770, 3489660928: 8388610, 3758096384: 0, 4026531840: 33282, 134217728: 0, 402653184: 8421890, 671088640: 33282, 939524096: 32768, 1207959552: 8421888, 1476395008: 512, 1744830464: 8421378, 2013265920: 2, 2281701376: 8389120, 2550136832: 33280, 2818572288: 8421376, 3087007744: 8389122, 3355443200: 8388610, 3623878656: 32770, 3892314112: 514, 4160749568: 8388608, 1: 32768, 268435457: 2, 536870913: 8421888, 805306369: 8388608, 1073741825: 8421378, 1342177281: 33280, 1610612737: 512, 1879048193: 8389122, 2147483649: 8421890, 2415919105: 8421376, 2684354561: 8388610, 2952790017: 33282, 3221225473: 514, 3489660929: 8389120, 3758096385: 32770, 4026531841: 0, 134217729: 8421890, 402653185: 8421376, 671088641: 8388608, 939524097: 512, 1207959553: 32768, 1476395009: 8388610, 1744830465: 2, 2013265921: 33282, 2281701377: 32770, 2550136833: 8389122, 2818572289: 514, 3087007745: 8421888, 3355443201: 8389120, 3623878657: 0, 3892314113: 33280, 4160749569: 8421378 }, { 0: 1074282512, 16777216: 16384, 33554432: 524288, 50331648: 1074266128, 67108864: 1073741840, 83886080: 1074282496, 100663296: 1073758208, 117440512: 16, 134217728: 540672, 150994944: 1073758224, 167772160: 1073741824, 184549376: 540688, 201326592: 524304, 218103808: 0, 234881024: 16400, 251658240: 1074266112, 8388608: 1073758208, 25165824: 540688, 41943040: 16, 58720256: 1073758224, 75497472: 1074282512, 92274688: 1073741824, 109051904: 524288, 125829120: 1074266128, 142606336: 524304, 159383552: 0, 176160768: 16384, 192937984: 1074266112, 209715200: 1073741840, 226492416: 540672, 243269632: 1074282496, 260046848: 16400, 268435456: 0, 285212672: 1074266128, 301989888: 1073758224, 318767104: 1074282496, 335544320: 1074266112, 352321536: 16, 369098752: 540688, 385875968: 16384, 402653184: 16400, 419430400: 524288, 436207616: 524304, 452984832: 1073741840, 469762048: 540672, 486539264: 1073758208, 503316480: 1073741824, 520093696: 1074282512, 276824064: 540688, 293601280: 524288, 310378496: 1074266112, 327155712: 16384, 343932928: 1073758208, 360710144: 1074282512, 377487360: 16, 394264576: 1073741824, 411041792: 1074282496, 427819008: 1073741840, 444596224: 1073758224, 461373440: 524304, 478150656: 0, 494927872: 16400, 511705088: 1074266128, 528482304: 540672 }, { 0: 260, 1048576: 0, 2097152: 67109120, 3145728: 65796, 4194304: 65540, 5242880: 67108868, 6291456: 67174660, 7340032: 67174400, 8388608: 67108864, 9437184: 67174656, 10485760: 65792, 11534336: 67174404, 12582912: 67109124, 13631488: 65536, 14680064: 4, 15728640: 256, 524288: 67174656, 1572864: 67174404, 2621440: 0, 3670016: 67109120, 4718592: 67108868, 5767168: 65536, 6815744: 65540, 7864320: 260, 8912896: 4, 9961472: 256, 11010048: 67174400, 12058624: 65796, 13107200: 65792, 14155776: 67109124, 15204352: 67174660, 16252928: 67108864, 16777216: 67174656, 17825792: 65540, 18874368: 65536, 19922944: 67109120, 20971520: 256, 22020096: 67174660, 23068672: 67108868, 24117248: 0, 25165824: 67109124, 26214400: 67108864, 27262976: 4, 28311552: 65792, 29360128: 67174400, 30408704: 260, 31457280: 65796, 32505856: 67174404, 17301504: 67108864, 18350080: 260, 19398656: 67174656, 20447232: 0, 21495808: 65540, 22544384: 67109120, 23592960: 256, 24641536: 67174404, 25690112: 65536, 26738688: 67174660, 27787264: 65796, 28835840: 67108868, 29884416: 67109124, 30932992: 67174400, 31981568: 4, 33030144: 65792 }, { 0: 2151682048, 65536: 2147487808, 131072: 4198464, 196608: 2151677952, 262144: 0, 327680: 4198400, 393216: 2147483712, 458752: 4194368, 524288: 2147483648, 589824: 4194304, 655360: 64, 720896: 2147487744, 786432: 2151678016, 851968: 4160, 917504: 4096, 983040: 2151682112, 32768: 2147487808, 98304: 64, 163840: 2151678016, 229376: 2147487744, 294912: 4198400, 360448: 2151682112, 425984: 0, 491520: 2151677952, 557056: 4096, 622592: 2151682048, 688128: 4194304, 753664: 4160, 819200: 2147483648, 884736: 4194368, 950272: 4198464, 1015808: 2147483712, 1048576: 4194368, 1114112: 4198400, 1179648: 2147483712, 1245184: 0, 1310720: 4160, 1376256: 2151678016, 1441792: 2151682048, 1507328: 2147487808, 1572864: 2151682112, 1638400: 2147483648, 1703936: 2151677952, 1769472: 4198464, 1835008: 2147487744, 1900544: 4194304, 1966080: 64, 2031616: 4096, 1081344: 2151677952, 1146880: 2151682112, 1212416: 0, 1277952: 4198400, 1343488: 4194368, 1409024: 2147483648, 1474560: 2147487808, 1540096: 64, 1605632: 2147483712, 1671168: 4096, 1736704: 2147487744, 1802240: 2151678016, 1867776: 4160, 1933312: 2151682048, 1998848: 4194304, 2064384: 4198464 }, { 0: 128, 4096: 17039360, 8192: 262144, 12288: 536870912, 16384: 537133184, 20480: 16777344, 24576: 553648256, 28672: 262272, 32768: 16777216, 36864: 537133056, 40960: 536871040, 45056: 553910400, 49152: 553910272, 53248: 0, 57344: 17039488, 61440: 553648128, 2048: 17039488, 6144: 553648256, 10240: 128, 14336: 17039360, 18432: 262144, 22528: 537133184, 26624: 553910272, 30720: 536870912, 34816: 537133056, 38912: 0, 43008: 553910400, 47104: 16777344, 51200: 536871040, 55296: 553648128, 59392: 16777216, 63488: 262272, 65536: 262144, 69632: 128, 73728: 536870912, 77824: 553648256, 81920: 16777344, 86016: 553910272, 90112: 537133184, 94208: 16777216, 98304: 553910400, 102400: 553648128, 106496: 17039360, 110592: 537133056, 114688: 262272, 118784: 536871040, 122880: 0, 126976: 17039488, 67584: 553648256, 71680: 16777216, 75776: 17039360, 79872: 537133184, 83968: 536870912, 88064: 17039488, 92160: 128, 96256: 553910272, 100352: 262272, 104448: 553910400, 108544: 0, 112640: 553648128, 116736: 16777344, 120832: 262144, 124928: 537133056, 129024: 536871040 }, { 0: 268435464, 256: 8192, 512: 270532608, 768: 270540808, 1024: 268443648, 1280: 2097152, 1536: 2097160, 1792: 268435456, 2048: 0, 2304: 268443656, 2560: 2105344, 2816: 8, 3072: 270532616, 3328: 2105352, 3584: 8200, 3840: 270540800, 128: 270532608, 384: 270540808, 640: 8, 896: 2097152, 1152: 2105352, 1408: 268435464, 1664: 268443648, 1920: 8200, 2176: 2097160, 2432: 8192, 2688: 268443656, 2944: 270532616, 3200: 0, 3456: 270540800, 3712: 2105344, 3968: 268435456, 4096: 268443648, 4352: 270532616, 4608: 270540808, 4864: 8200, 5120: 2097152, 5376: 268435456, 5632: 268435464, 5888: 2105344, 6144: 2105352, 6400: 0, 6656: 8, 6912: 270532608, 7168: 8192, 7424: 268443656, 7680: 270540800, 7936: 2097160, 4224: 8, 4480: 2105344, 4736: 2097152, 4992: 268435464, 5248: 268443648, 5504: 8200, 5760: 270540808, 6016: 270532608, 6272: 270540800, 6528: 270532616, 6784: 8192, 7040: 2105352, 7296: 2097160, 7552: 0, 7808: 268435456, 8064: 268443656 }, { 0: 1048576, 16: 33555457, 32: 1024, 48: 1049601, 64: 34604033, 80: 0, 96: 1, 112: 34603009, 128: 33555456, 144: 1048577, 160: 33554433, 176: 34604032, 192: 34603008, 208: 1025, 224: 1049600, 240: 33554432, 8: 34603009, 24: 0, 40: 33555457, 56: 34604032, 72: 1048576, 88: 33554433, 104: 33554432, 120: 1025, 136: 1049601, 152: 33555456, 168: 34603008, 184: 1048577, 200: 1024, 216: 34604033, 232: 1, 248: 1049600, 256: 33554432, 272: 1048576, 288: 33555457, 304: 34603009, 320: 1048577, 336: 33555456, 352: 34604032, 368: 1049601, 384: 1025, 400: 34604033, 416: 1049600, 432: 1, 448: 0, 464: 34603008, 480: 33554433, 496: 1024, 264: 1049600, 280: 33555457, 296: 34603009, 312: 1, 328: 33554432, 344: 1048576, 360: 1025, 376: 34604032, 392: 33554433, 408: 34603008, 424: 0, 440: 34604033, 456: 1049601, 472: 1024, 488: 33555456, 504: 1048577 }, { 0: 134219808, 1: 131072, 2: 134217728, 3: 32, 4: 131104, 5: 134350880, 6: 134350848, 7: 2048, 8: 134348800, 9: 134219776, 10: 133120, 11: 134348832, 12: 2080, 13: 0, 14: 134217760, 15: 133152, 2147483648: 2048, 2147483649: 134350880, 2147483650: 134219808, 2147483651: 134217728, 2147483652: 134348800, 2147483653: 133120, 2147483654: 133152, 2147483655: 32, 2147483656: 134217760, 2147483657: 2080, 2147483658: 131104, 2147483659: 134350848, 2147483660: 0, 2147483661: 134348832, 2147483662: 134219776, 2147483663: 131072, 16: 133152, 17: 134350848, 18: 32, 19: 2048, 20: 134219776, 21: 134217760, 22: 134348832, 23: 131072, 24: 0, 25: 131104, 26: 134348800, 27: 134219808, 28: 134350880, 29: 133120, 30: 2080, 31: 134217728, 2147483664: 131072, 2147483665: 2048, 2147483666: 134348832, 2147483667: 133152, 2147483668: 32, 2147483669: 134348800, 2147483670: 134217728, 2147483671: 134219808, 2147483672: 134350880, 2147483673: 134217760, 2147483674: 134219776, 2147483675: 0, 2147483676: 133120, 2147483677: 2080, 2147483678: 131104, 2147483679: 134350848 }], u = [4160749569, 528482304, 33030144, 2064384, 129024, 8064, 504, 2147483679], d = a.DES = s.extend({ _doReset: function () { for (var t = this._key, r = t.words, e = [], i = 0; i < 56; i++) { var n = c[i] - 1; e[i] = r[n >>> 5] >>> 31 - n % 32 & 1 } for (var o = this._subKeys = [], s = 0; s < 16; s++) { for (var a = o[s] = [], f = l[s], i = 0; i < 24; i++)a[i / 6 | 0] |= e[(h[i] - 1 + f) % 28] << 31 - i % 6, a[4 + (i / 6 | 0)] |= e[28 + (h[i + 24] - 1 + f) % 28] << 31 - i % 6; a[0] = a[0] << 1 | a[0] >>> 31; for (var i = 1; i < 7; i++)a[i] = a[i] >>> 4 * (i - 1) + 3; a[7] = a[7] << 5 | a[7] >>> 27 } for (var u = this._invSubKeys = [], i = 0; i < 16; i++)u[i] = o[15 - i] }, encryptBlock: function (t, r) { this._doCryptBlock(t, r, this._subKeys) }, decryptBlock: function (t, r) { this._doCryptBlock(t, r, this._invSubKeys) }, _doCryptBlock: function (t, i, n) { this._lBlock = t[i], this._rBlock = t[i + 1], r.call(this, 4, 252645135), r.call(this, 16, 65535), e.call(this, 2, 858993459), e.call(this, 8, 16711935), r.call(this, 1, 1431655765); for (var o = 0; o < 16; o++) { for (var s = n[o], a = this._lBlock, c = this._rBlock, h = 0, l = 0; l < 8; l++)h |= f[l][((c ^ s[l]) & u[l]) >>> 0]; this._lBlock = c, this._rBlock = a ^ h } var d = this._lBlock; this._lBlock = this._rBlock, this._rBlock = d, r.call(this, 1, 1431655765), e.call(this, 8, 16711935), e.call(this, 2, 858993459), r.call(this, 16, 65535), r.call(this, 4, 252645135), t[i] = this._lBlock, t[i + 1] = this._rBlock }, keySize: 2, ivSize: 2, blockSize: 2 }); i.DES = s._createHelper(d); var v = a.TripleDES = s.extend({ _doReset: function () { var t = this._key, r = t.words; this._des1 = d.createEncryptor(o.create(r.slice(0, 2))), this._des2 = d.createEncryptor(o.create(r.slice(2, 4))), this._des3 = d.createEncryptor(o.create(r.slice(4, 6))) }, encryptBlock: function (t, r) { this._des1.encryptBlock(t, r), this._des2.decryptBlock(t, r), this._des3.encryptBlock(t, r) }, decryptBlock: function (t, r) { this._des3.decryptBlock(t, r), this._des2.encryptBlock(t, r), this._des1.decryptBlock(t, r) }, keySize: 6, ivSize: 2, blockSize: 2 }); i.TripleDES = s._createHelper(v) + }(), function () { function r() { for (var t = this._S, r = this._i, e = this._j, i = 0, n = 0; n < 4; n++) { r = (r + 1) % 256, e = (e + t[r]) % 256; var o = t[r]; t[r] = t[e], t[e] = o, i |= t[(t[r] + t[e]) % 256] << 24 - 8 * n } return this._i = r, this._j = e, i } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = o.RC4 = n.extend({ _doReset: function () { for (var t = this._key, r = t.words, e = t.sigBytes, i = this._S = [], n = 0; n < 256; n++)i[n] = n; for (var n = 0, o = 0; n < 256; n++) { var s = n % e, a = r[s >>> 2] >>> 24 - s % 4 * 8 & 255; o = (o + i[n] + a) % 256; var c = i[n]; i[n] = i[o], i[o] = c } this._i = this._j = 0 }, _doProcessBlock: function (t, e) { t[e] ^= r.call(this) }, keySize: 8, ivSize: 0 }); e.RC4 = n._createHelper(s); var a = o.RC4Drop = s.extend({ cfg: s.cfg.extend({ drop: 192 }), _doReset: function () { s._doReset.call(this); for (var t = this.cfg.drop; t > 0; t--)r.call(this) } }); e.RC4Drop = n._createHelper(a) }(), t.mode.CTRGladman = function () { function r(t) { if (255 === (t >> 24 & 255)) { var r = t >> 16 & 255, e = t >> 8 & 255, i = 255 & t; 255 === r ? (r = 0, 255 === e ? (e = 0, 255 === i ? i = 0 : ++i) : ++e) : ++r, t = 0, t += r << 16, t += e << 8, t += i } else t += 1 << 24; return t } function e(t) { return 0 === (t[0] = r(t[0])) && (t[1] = r(t[1])), t } var i = t.lib.BlockCipherMode.extend(), n = i.Encryptor = i.extend({ processBlock: function (t, r) { var i = this._cipher, n = i.blockSize, o = this._iv, s = this._counter; o && (s = this._counter = o.slice(0), this._iv = void 0), e(s); var a = s.slice(0); i.encryptBlock(a, 0); for (var c = 0; c < n; c++)t[r + c] ^= a[c] } }); return i.Decryptor = n, i }(), function () { function r() { for (var t = this._X, r = this._C, e = 0; e < 8; e++)a[e] = r[e]; r[0] = r[0] + 1295307597 + this._b | 0, r[1] = r[1] + 3545052371 + (r[0] >>> 0 < a[0] >>> 0 ? 1 : 0) | 0, r[2] = r[2] + 886263092 + (r[1] >>> 0 < a[1] >>> 0 ? 1 : 0) | 0, r[3] = r[3] + 1295307597 + (r[2] >>> 0 < a[2] >>> 0 ? 1 : 0) | 0, r[4] = r[4] + 3545052371 + (r[3] >>> 0 < a[3] >>> 0 ? 1 : 0) | 0, r[5] = r[5] + 886263092 + (r[4] >>> 0 < a[4] >>> 0 ? 1 : 0) | 0, r[6] = r[6] + 1295307597 + (r[5] >>> 0 < a[5] >>> 0 ? 1 : 0) | 0, r[7] = r[7] + 3545052371 + (r[6] >>> 0 < a[6] >>> 0 ? 1 : 0) | 0, this._b = r[7] >>> 0 < a[7] >>> 0 ? 1 : 0; for (var e = 0; e < 8; e++) { var i = t[e] + r[e], n = 65535 & i, o = i >>> 16, s = ((n * n >>> 17) + n * o >>> 15) + o * o, h = ((4294901760 & i) * i | 0) + ((65535 & i) * i | 0); c[e] = s ^ h } t[0] = c[0] + (c[7] << 16 | c[7] >>> 16) + (c[6] << 16 | c[6] >>> 16) | 0, t[1] = c[1] + (c[0] << 8 | c[0] >>> 24) + c[7] | 0, t[2] = c[2] + (c[1] << 16 | c[1] >>> 16) + (c[0] << 16 | c[0] >>> 16) | 0, t[3] = c[3] + (c[2] << 8 | c[2] >>> 24) + c[1] | 0, t[4] = c[4] + (c[3] << 16 | c[3] >>> 16) + (c[2] << 16 | c[2] >>> 16) | 0, t[5] = c[5] + (c[4] << 8 | c[4] >>> 24) + c[3] | 0, t[6] = c[6] + (c[5] << 16 | c[5] >>> 16) + (c[4] << 16 | c[4] >>> 16) | 0, t[7] = c[7] + (c[6] << 8 | c[6] >>> 24) + c[5] | 0 } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = [], a = [], c = [], h = o.Rabbit = n.extend({ _doReset: function () { for (var t = this._key.words, e = this.cfg.iv, i = 0; i < 4; i++)t[i] = 16711935 & (t[i] << 8 | t[i] >>> 24) | 4278255360 & (t[i] << 24 | t[i] >>> 8); var n = this._X = [t[0], t[3] << 16 | t[2] >>> 16, t[1], t[0] << 16 | t[3] >>> 16, t[2], t[1] << 16 | t[0] >>> 16, t[3], t[2] << 16 | t[1] >>> 16], o = this._C = [t[2] << 16 | t[2] >>> 16, 4294901760 & t[0] | 65535 & t[1], t[3] << 16 | t[3] >>> 16, 4294901760 & t[1] | 65535 & t[2], t[0] << 16 | t[0] >>> 16, 4294901760 & t[2] | 65535 & t[3], t[1] << 16 | t[1] >>> 16, 4294901760 & t[3] | 65535 & t[0]]; this._b = 0; for (var i = 0; i < 4; i++)r.call(this); for (var i = 0; i < 8; i++)o[i] ^= n[i + 4 & 7]; if (e) { var s = e.words, a = s[0], c = s[1], h = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8), l = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8), f = h >>> 16 | 4294901760 & l, u = l << 16 | 65535 & h; o[0] ^= h, o[1] ^= f, o[2] ^= l, o[3] ^= u, o[4] ^= h, o[5] ^= f, o[6] ^= l, o[7] ^= u; for (var i = 0; i < 4; i++)r.call(this) } }, _doProcessBlock: function (t, e) { var i = this._X; r.call(this), s[0] = i[0] ^ i[5] >>> 16 ^ i[3] << 16, s[1] = i[2] ^ i[7] >>> 16 ^ i[5] << 16, s[2] = i[4] ^ i[1] >>> 16 ^ i[7] << 16, s[3] = i[6] ^ i[3] >>> 16 ^ i[1] << 16; for (var n = 0; n < 4; n++)s[n] = 16711935 & (s[n] << 8 | s[n] >>> 24) | 4278255360 & (s[n] << 24 | s[n] >>> 8), t[e + n] ^= s[n] }, blockSize: 4, ivSize: 2 }); e.Rabbit = n._createHelper(h) }(), t.mode.CTR = function () { var r = t.lib.BlockCipherMode.extend(), e = r.Encryptor = r.extend({ processBlock: function (t, r) { var e = this._cipher, i = e.blockSize, n = this._iv, o = this._counter; n && (o = this._counter = n.slice(0), this._iv = void 0); var s = o.slice(0); e.encryptBlock(s, 0), o[i - 1] = o[i - 1] + 1 | 0; for (var a = 0; a < i; a++)t[r + a] ^= s[a] } }); return r.Decryptor = e, r }(), function () { function r() { for (var t = this._X, r = this._C, e = 0; e < 8; e++)a[e] = r[e]; r[0] = r[0] + 1295307597 + this._b | 0, r[1] = r[1] + 3545052371 + (r[0] >>> 0 < a[0] >>> 0 ? 1 : 0) | 0, r[2] = r[2] + 886263092 + (r[1] >>> 0 < a[1] >>> 0 ? 1 : 0) | 0, r[3] = r[3] + 1295307597 + (r[2] >>> 0 < a[2] >>> 0 ? 1 : 0) | 0, r[4] = r[4] + 3545052371 + (r[3] >>> 0 < a[3] >>> 0 ? 1 : 0) | 0, r[5] = r[5] + 886263092 + (r[4] >>> 0 < a[4] >>> 0 ? 1 : 0) | 0, r[6] = r[6] + 1295307597 + (r[5] >>> 0 < a[5] >>> 0 ? 1 : 0) | 0, r[7] = r[7] + 3545052371 + (r[6] >>> 0 < a[6] >>> 0 ? 1 : 0) | 0, this._b = r[7] >>> 0 < a[7] >>> 0 ? 1 : 0; for (var e = 0; e < 8; e++) { var i = t[e] + r[e], n = 65535 & i, o = i >>> 16, s = ((n * n >>> 17) + n * o >>> 15) + o * o, h = ((4294901760 & i) * i | 0) + ((65535 & i) * i | 0); c[e] = s ^ h } t[0] = c[0] + (c[7] << 16 | c[7] >>> 16) + (c[6] << 16 | c[6] >>> 16) | 0, t[1] = c[1] + (c[0] << 8 | c[0] >>> 24) + c[7] | 0, t[2] = c[2] + (c[1] << 16 | c[1] >>> 16) + (c[0] << 16 | c[0] >>> 16) | 0, t[3] = c[3] + (c[2] << 8 | c[2] >>> 24) + c[1] | 0, t[4] = c[4] + (c[3] << 16 | c[3] >>> 16) + (c[2] << 16 | c[2] >>> 16) | 0, t[5] = c[5] + (c[4] << 8 | c[4] >>> 24) + c[3] | 0, t[6] = c[6] + (c[5] << 16 | c[5] >>> 16) + (c[4] << 16 | c[4] >>> 16) | 0, t[7] = c[7] + (c[6] << 8 | c[6] >>> 24) + c[5] | 0 } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = [], a = [], c = [], h = o.RabbitLegacy = n.extend({ _doReset: function () { var t = this._key.words, e = this.cfg.iv, i = this._X = [t[0], t[3] << 16 | t[2] >>> 16, t[1], t[0] << 16 | t[3] >>> 16, t[2], t[1] << 16 | t[0] >>> 16, t[3], t[2] << 16 | t[1] >>> 16], n = this._C = [t[2] << 16 | t[2] >>> 16, 4294901760 & t[0] | 65535 & t[1], t[3] << 16 | t[3] >>> 16, 4294901760 & t[1] | 65535 & t[2], t[0] << 16 | t[0] >>> 16, 4294901760 & t[2] | 65535 & t[3], t[1] << 16 | t[1] >>> 16, 4294901760 & t[3] | 65535 & t[0]]; this._b = 0; for (var o = 0; o < 4; o++)r.call(this); for (var o = 0; o < 8; o++)n[o] ^= i[o + 4 & 7]; if (e) { var s = e.words, a = s[0], c = s[1], h = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8), l = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8), f = h >>> 16 | 4294901760 & l, u = l << 16 | 65535 & h; n[0] ^= h, n[1] ^= f, n[2] ^= l, n[3] ^= u, n[4] ^= h, n[5] ^= f, n[6] ^= l, n[7] ^= u; for (var o = 0; o < 4; o++)r.call(this) } }, _doProcessBlock: function (t, e) { var i = this._X; r.call(this), s[0] = i[0] ^ i[5] >>> 16 ^ i[3] << 16, s[1] = i[2] ^ i[7] >>> 16 ^ i[5] << 16, s[2] = i[4] ^ i[1] >>> 16 ^ i[7] << 16, s[3] = i[6] ^ i[3] >>> 16 ^ i[1] << 16; for (var n = 0; n < 4; n++)s[n] = 16711935 & (s[n] << 8 | s[n] >>> 24) | 4278255360 & (s[n] << 24 | s[n] >>> 8), t[e + n] ^= s[n] }, blockSize: 4, ivSize: 2 }); e.RabbitLegacy = n._createHelper(h) }(), t.pad.ZeroPadding = { pad: function (t, r) { var e = 4 * r; t.clamp(), t.sigBytes += e - (t.sigBytes % e || e) }, unpad: function (t) { for (var r = t.words, e = t.sigBytes - 1; !(r[e >>> 2] >>> 24 - e % 4 * 8 & 255);)e--; t.sigBytes = e + 1 } }, t +}); + +const $ = new Env('什么值得买') +$.VAL_cookies = $.getdata('chavy_cookie_smzdm') + +!(async () => { + $.CryptoJS = $.isNode() ? require('crypto-js') : CryptoJS + + await signweb() + await $.wait(4000) + await signapp() + await showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +function signweb() { + return new Promise((resove) => { + const url = { url: 'https://zhiyou.smzdm.com/user/checkin/jsonp_checkin', headers: {} } + url.headers['Cookie'] = $.VAL_cookies + url.headers['Referer'] = 'http://www.smzdm.com/' + url.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36' + $.get(url, (err, resp, data) => { + try { + $.web = JSON.parse(data) + } catch (e) { + $.logErr(e, resp) + } finally { + resove() + } + }) + }) +} + +function signapp() { + const body = getBody() + return new Promise((resove) => { + const url = { + url: 'https://user-api.smzdm.com/checkin', + body, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Cookie': $.VAL_cookies + } } - // 登录失效 - else if (result && result.data && result.error_code == 99) { - let subTitle = `签到结果: 失败` - let detail = `说明: 登录失效, 请重新获取Cookie` - $notify(title, subTitle, detail) + $.post(url, (err, resp, data) => { + try { + $.app = JSON.parse(data) + } catch (e) { + $.logErr(e, resp) + } finally { + resove() + } + }) + }) +} + +function getToken() { + const [, token] = $.VAL_cookies.match(/sess=(.*?);/) + return token +} + +function getAppSign(t) { + const sign = 'f=android&sk=1&time=' + t + '&token=' + getToken() + '&v=10.0&weixin=0&key=apr1$AwP!wRRT$gJ/q.X24poeBInlUJC' + return $.CryptoJS.MD5(sign).toString().toUpperCase() +} + +function getBody() { + const t = new Date().getTime() + const token = getToken() + const sign = getAppSign(t) + return 'touchstone_event=&v=10.0&sign=' + sign + '&weixin=0&time=' + t + '&sk=1&token=' + token + '&f=android&captcha=' +} + +function showmsg() { + return new Promise((resolve) => { + $.subt = '' + $.desc = [] + $.subt = $.web.error_code === 0 ? 'PC: 成功' : $.web.error_code === 99 ? 'PC: 未登录' : 'PC: 失败' + if ($.web.error_code === 0 && $.web.data) { + $.desc.push(`累计: ${$.web.data.checkin_num}次, 经验: ${$.web.data.exp}, 金币: ${$.web.data.gold}, 积分: ${$.web.data.point}`) } - // 签到失败 - else { - let subTitle = `签到结果: 失败` - let detail = `编码: ${result.error_code}, 说明: ${result.error_msg}` - $notify(title, subTitle, detail) + if ($.app) { + $.subt += $.app.error_code === '0' ? ', APP: 成功' : ', APP: 失败' + $.desc.push($.app.error_msg) } - console.log(`${cookieName}, data: ${data}`) + $.msg($.name, $.subt, $.desc.join('\n')) + resolve() }) } -sign() +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/smzdm/smzdm.js b/smzdm/smzdm.js index 3566f0e48..21c3709d7 100644 --- a/smzdm/smzdm.js +++ b/smzdm/smzdm.js @@ -1,42 +1,100 @@ -const cookieName = '什么值得买' -const cookieKey = 'chavy_cookie_smzdm' -const cookieVal = $persistentStore.read(cookieKey) - -function sign() { - let url = { - url: `https://zhiyou.smzdm.com/user/checkin/jsonp_checkin`, - headers: { - Cookie: cookieVal - } - } - url.headers['Referer'] = 'http://www.smzdm.com/' - url.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36' - - $httpClient.get(url, (error, response, data) => { - let result = JSON.parse(data) - let title = `${cookieName}` - // 签到成功 - if (result && result.data && result.error_code == 0) { - let subTitle = `签到结果: 成功` - let detail = `累计: ${result.data.checkin_num}次, 经验: ${result.data.exp}, 金币: ${result.data.gold}, 积分: ${result.data.point}` - $notification.post(title, subTitle, detail) +// prettier-ignore +!function (t, r) { "object" == typeof exports ? module.exports = exports = r() : "function" == typeof define && define.amd ? define([], r) : t.CryptoJS = r() }(this, function () { + var t = t || function (t, r) { var e = Object.create || function () { function t() { } return function (r) { var e; return t.prototype = r, e = new t, t.prototype = null, e } }(), i = {}, n = i.lib = {}, o = n.Base = function () { return { extend: function (t) { var r = e(this); return t && r.mixIn(t), r.hasOwnProperty("init") && this.init !== r.init || (r.init = function () { r.$super.init.apply(this, arguments) }), r.init.prototype = r, r.$super = this, r }, create: function () { var t = this.extend(); return t.init.apply(t, arguments), t }, init: function () { }, mixIn: function (t) { for (var r in t) t.hasOwnProperty(r) && (this[r] = t[r]); t.hasOwnProperty("toString") && (this.toString = t.toString) }, clone: function () { return this.init.prototype.extend(this) } } }(), s = n.WordArray = o.extend({ init: function (t, e) { t = this.words = t || [], e != r ? this.sigBytes = e : this.sigBytes = 4 * t.length }, toString: function (t) { return (t || c).stringify(this) }, concat: function (t) { var r = this.words, e = t.words, i = this.sigBytes, n = t.sigBytes; if (this.clamp(), i % 4) for (var o = 0; o < n; o++) { var s = e[o >>> 2] >>> 24 - o % 4 * 8 & 255; r[i + o >>> 2] |= s << 24 - (i + o) % 4 * 8 } else for (var o = 0; o < n; o += 4)r[i + o >>> 2] = e[o >>> 2]; return this.sigBytes += n, this }, clamp: function () { var r = this.words, e = this.sigBytes; r[e >>> 2] &= 4294967295 << 32 - e % 4 * 8, r.length = t.ceil(e / 4) }, clone: function () { var t = o.clone.call(this); return t.words = this.words.slice(0), t }, random: function (r) { for (var e, i = [], n = function (r) { var r = r, e = 987654321, i = 4294967295; return function () { e = 36969 * (65535 & e) + (e >> 16) & i, r = 18e3 * (65535 & r) + (r >> 16) & i; var n = (e << 16) + r & i; return n /= 4294967296, n += .5, n * (t.random() > .5 ? 1 : -1) } }, o = 0; o < r; o += 4) { var a = n(4294967296 * (e || t.random())); e = 987654071 * a(), i.push(4294967296 * a() | 0) } return new s.init(i, r) } }), a = i.enc = {}, c = a.Hex = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n++) { var o = r[n >>> 2] >>> 24 - n % 4 * 8 & 255; i.push((o >>> 4).toString(16)), i.push((15 & o).toString(16)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i += 2)e[i >>> 3] |= parseInt(t.substr(i, 2), 16) << 24 - i % 8 * 4; return new s.init(e, r / 2) } }, h = a.Latin1 = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n++) { var o = r[n >>> 2] >>> 24 - n % 4 * 8 & 255; i.push(String.fromCharCode(o)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i++)e[i >>> 2] |= (255 & t.charCodeAt(i)) << 24 - i % 4 * 8; return new s.init(e, r) } }, l = a.Utf8 = { stringify: function (t) { try { return decodeURIComponent(escape(h.stringify(t))) } catch (t) { throw new Error("Malformed UTF-8 data") } }, parse: function (t) { return h.parse(unescape(encodeURIComponent(t))) } }, f = n.BufferedBlockAlgorithm = o.extend({ reset: function () { this._data = new s.init, this._nDataBytes = 0 }, _append: function (t) { "string" == typeof t && (t = l.parse(t)), this._data.concat(t), this._nDataBytes += t.sigBytes }, _process: function (r) { var e = this._data, i = e.words, n = e.sigBytes, o = this.blockSize, a = 4 * o, c = n / a; c = r ? t.ceil(c) : t.max((0 | c) - this._minBufferSize, 0); var h = c * o, l = t.min(4 * h, n); if (h) { for (var f = 0; f < h; f += o)this._doProcessBlock(i, f); var u = i.splice(0, h); e.sigBytes -= l } return new s.init(u, l) }, clone: function () { var t = o.clone.call(this); return t._data = this._data.clone(), t }, _minBufferSize: 0 }), u = (n.Hasher = f.extend({ cfg: o.extend(), init: function (t) { this.cfg = this.cfg.extend(t), this.reset() }, reset: function () { f.reset.call(this), this._doReset() }, update: function (t) { return this._append(t), this._process(), this }, finalize: function (t) { t && this._append(t); var r = this._doFinalize(); return r }, blockSize: 16, _createHelper: function (t) { return function (r, e) { return new t.init(e).finalize(r) } }, _createHmacHelper: function (t) { return function (r, e) { return new u.HMAC.init(t, e).finalize(r) } } }), i.algo = {}); return i }(Math); return function () { function r(t, r, e) { for (var i = [], o = 0, s = 0; s < r; s++)if (s % 4) { var a = e[t.charCodeAt(s - 1)] << s % 4 * 2, c = e[t.charCodeAt(s)] >>> 6 - s % 4 * 2; i[o >>> 2] |= (a | c) << 24 - o % 4 * 8, o++ } return n.create(i, o) } var e = t, i = e.lib, n = i.WordArray, o = e.enc; o.Base64 = { stringify: function (t) { var r = t.words, e = t.sigBytes, i = this._map; t.clamp(); for (var n = [], o = 0; o < e; o += 3)for (var s = r[o >>> 2] >>> 24 - o % 4 * 8 & 255, a = r[o + 1 >>> 2] >>> 24 - (o + 1) % 4 * 8 & 255, c = r[o + 2 >>> 2] >>> 24 - (o + 2) % 4 * 8 & 255, h = s << 16 | a << 8 | c, l = 0; l < 4 && o + .75 * l < e; l++)n.push(i.charAt(h >>> 6 * (3 - l) & 63)); var f = i.charAt(64); if (f) for (; n.length % 4;)n.push(f); return n.join("") }, parse: function (t) { var e = t.length, i = this._map, n = this._reverseMap; if (!n) { n = this._reverseMap = []; for (var o = 0; o < i.length; o++)n[i.charCodeAt(o)] = o } var s = i.charAt(64); if (s) { var a = t.indexOf(s); a !== -1 && (e = a) } return r(t, e, n) }, _map: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" } }(), function (r) { function e(t, r, e, i, n, o, s) { var a = t + (r & e | ~r & i) + n + s; return (a << o | a >>> 32 - o) + r } function i(t, r, e, i, n, o, s) { var a = t + (r & i | e & ~i) + n + s; return (a << o | a >>> 32 - o) + r } function n(t, r, e, i, n, o, s) { var a = t + (r ^ e ^ i) + n + s; return (a << o | a >>> 32 - o) + r } function o(t, r, e, i, n, o, s) { var a = t + (e ^ (r | ~i)) + n + s; return (a << o | a >>> 32 - o) + r } var s = t, a = s.lib, c = a.WordArray, h = a.Hasher, l = s.algo, f = []; !function () { for (var t = 0; t < 64; t++)f[t] = 4294967296 * r.abs(r.sin(t + 1)) | 0 }(); var u = l.MD5 = h.extend({ _doReset: function () { this._hash = new c.init([1732584193, 4023233417, 2562383102, 271733878]) }, _doProcessBlock: function (t, r) { for (var s = 0; s < 16; s++) { var a = r + s, c = t[a]; t[a] = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8) } var h = this._hash.words, l = t[r + 0], u = t[r + 1], d = t[r + 2], v = t[r + 3], p = t[r + 4], _ = t[r + 5], y = t[r + 6], g = t[r + 7], B = t[r + 8], w = t[r + 9], k = t[r + 10], S = t[r + 11], m = t[r + 12], x = t[r + 13], b = t[r + 14], H = t[r + 15], z = h[0], A = h[1], C = h[2], D = h[3]; z = e(z, A, C, D, l, 7, f[0]), D = e(D, z, A, C, u, 12, f[1]), C = e(C, D, z, A, d, 17, f[2]), A = e(A, C, D, z, v, 22, f[3]), z = e(z, A, C, D, p, 7, f[4]), D = e(D, z, A, C, _, 12, f[5]), C = e(C, D, z, A, y, 17, f[6]), A = e(A, C, D, z, g, 22, f[7]), z = e(z, A, C, D, B, 7, f[8]), D = e(D, z, A, C, w, 12, f[9]), C = e(C, D, z, A, k, 17, f[10]), A = e(A, C, D, z, S, 22, f[11]), z = e(z, A, C, D, m, 7, f[12]), D = e(D, z, A, C, x, 12, f[13]), C = e(C, D, z, A, b, 17, f[14]), A = e(A, C, D, z, H, 22, f[15]), z = i(z, A, C, D, u, 5, f[16]), D = i(D, z, A, C, y, 9, f[17]), C = i(C, D, z, A, S, 14, f[18]), A = i(A, C, D, z, l, 20, f[19]), z = i(z, A, C, D, _, 5, f[20]), D = i(D, z, A, C, k, 9, f[21]), C = i(C, D, z, A, H, 14, f[22]), A = i(A, C, D, z, p, 20, f[23]), z = i(z, A, C, D, w, 5, f[24]), D = i(D, z, A, C, b, 9, f[25]), C = i(C, D, z, A, v, 14, f[26]), A = i(A, C, D, z, B, 20, f[27]), z = i(z, A, C, D, x, 5, f[28]), D = i(D, z, A, C, d, 9, f[29]), C = i(C, D, z, A, g, 14, f[30]), A = i(A, C, D, z, m, 20, f[31]), z = n(z, A, C, D, _, 4, f[32]), D = n(D, z, A, C, B, 11, f[33]), C = n(C, D, z, A, S, 16, f[34]), A = n(A, C, D, z, b, 23, f[35]), z = n(z, A, C, D, u, 4, f[36]), D = n(D, z, A, C, p, 11, f[37]), C = n(C, D, z, A, g, 16, f[38]), A = n(A, C, D, z, k, 23, f[39]), z = n(z, A, C, D, x, 4, f[40]), D = n(D, z, A, C, l, 11, f[41]), C = n(C, D, z, A, v, 16, f[42]), A = n(A, C, D, z, y, 23, f[43]), z = n(z, A, C, D, w, 4, f[44]), D = n(D, z, A, C, m, 11, f[45]), C = n(C, D, z, A, H, 16, f[46]), A = n(A, C, D, z, d, 23, f[47]), z = o(z, A, C, D, l, 6, f[48]), D = o(D, z, A, C, g, 10, f[49]), C = o(C, D, z, A, b, 15, f[50]), A = o(A, C, D, z, _, 21, f[51]), z = o(z, A, C, D, m, 6, f[52]), D = o(D, z, A, C, v, 10, f[53]), C = o(C, D, z, A, k, 15, f[54]), A = o(A, C, D, z, u, 21, f[55]), z = o(z, A, C, D, B, 6, f[56]), D = o(D, z, A, C, H, 10, f[57]), C = o(C, D, z, A, y, 15, f[58]), A = o(A, C, D, z, x, 21, f[59]), z = o(z, A, C, D, p, 6, f[60]), D = o(D, z, A, C, S, 10, f[61]), C = o(C, D, z, A, d, 15, f[62]), A = o(A, C, D, z, w, 21, f[63]), h[0] = h[0] + z | 0, h[1] = h[1] + A | 0, h[2] = h[2] + C | 0, h[3] = h[3] + D | 0 }, _doFinalize: function () { var t = this._data, e = t.words, i = 8 * this._nDataBytes, n = 8 * t.sigBytes; e[n >>> 5] |= 128 << 24 - n % 32; var o = r.floor(i / 4294967296), s = i; e[(n + 64 >>> 9 << 4) + 15] = 16711935 & (o << 8 | o >>> 24) | 4278255360 & (o << 24 | o >>> 8), e[(n + 64 >>> 9 << 4) + 14] = 16711935 & (s << 8 | s >>> 24) | 4278255360 & (s << 24 | s >>> 8), t.sigBytes = 4 * (e.length + 1), this._process(); for (var a = this._hash, c = a.words, h = 0; h < 4; h++) { var l = c[h]; c[h] = 16711935 & (l << 8 | l >>> 24) | 4278255360 & (l << 24 | l >>> 8) } return a }, clone: function () { var t = h.clone.call(this); return t._hash = this._hash.clone(), t } }); s.MD5 = h._createHelper(u), s.HmacMD5 = h._createHmacHelper(u) }(Math), function () { var r = t, e = r.lib, i = e.WordArray, n = e.Hasher, o = r.algo, s = [], a = o.SHA1 = n.extend({ _doReset: function () { this._hash = new i.init([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], a = e[3], c = e[4], h = 0; h < 80; h++) { if (h < 16) s[h] = 0 | t[r + h]; else { var l = s[h - 3] ^ s[h - 8] ^ s[h - 14] ^ s[h - 16]; s[h] = l << 1 | l >>> 31 } var f = (i << 5 | i >>> 27) + c + s[h]; f += h < 20 ? (n & o | ~n & a) + 1518500249 : h < 40 ? (n ^ o ^ a) + 1859775393 : h < 60 ? (n & o | n & a | o & a) - 1894007588 : (n ^ o ^ a) - 899497514, c = a, a = o, o = n << 30 | n >>> 2, n = i, i = f } e[0] = e[0] + i | 0, e[1] = e[1] + n | 0, e[2] = e[2] + o | 0, e[3] = e[3] + a | 0, e[4] = e[4] + c | 0 }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; return r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 64 >>> 9 << 4) + 14] = Math.floor(e / 4294967296), r[(i + 64 >>> 9 << 4) + 15] = e, t.sigBytes = 4 * r.length, this._process(), this._hash }, clone: function () { var t = n.clone.call(this); return t._hash = this._hash.clone(), t } }); r.SHA1 = n._createHelper(a), r.HmacSHA1 = n._createHmacHelper(a) }(), function (r) { var e = t, i = e.lib, n = i.WordArray, o = i.Hasher, s = e.algo, a = [], c = []; !function () { function t(t) { for (var e = r.sqrt(t), i = 2; i <= e; i++)if (!(t % i)) return !1; return !0 } function e(t) { return 4294967296 * (t - (0 | t)) | 0 } for (var i = 2, n = 0; n < 64;)t(i) && (n < 8 && (a[n] = e(r.pow(i, .5))), c[n] = e(r.pow(i, 1 / 3)), n++), i++ }(); var h = [], l = s.SHA256 = o.extend({ _doReset: function () { this._hash = new n.init(a.slice(0)) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], s = e[3], a = e[4], l = e[5], f = e[6], u = e[7], d = 0; d < 64; d++) { if (d < 16) h[d] = 0 | t[r + d]; else { var v = h[d - 15], p = (v << 25 | v >>> 7) ^ (v << 14 | v >>> 18) ^ v >>> 3, _ = h[d - 2], y = (_ << 15 | _ >>> 17) ^ (_ << 13 | _ >>> 19) ^ _ >>> 10; h[d] = p + h[d - 7] + y + h[d - 16] } var g = a & l ^ ~a & f, B = i & n ^ i & o ^ n & o, w = (i << 30 | i >>> 2) ^ (i << 19 | i >>> 13) ^ (i << 10 | i >>> 22), k = (a << 26 | a >>> 6) ^ (a << 21 | a >>> 11) ^ (a << 7 | a >>> 25), S = u + k + g + c[d] + h[d], m = w + B; u = f, f = l, l = a, a = s + S | 0, s = o, o = n, n = i, i = S + m | 0 } e[0] = e[0] + i | 0, e[1] = e[1] + n | 0, e[2] = e[2] + o | 0, e[3] = e[3] + s | 0, e[4] = e[4] + a | 0, e[5] = e[5] + l | 0, e[6] = e[6] + f | 0, e[7] = e[7] + u | 0 }, _doFinalize: function () { var t = this._data, e = t.words, i = 8 * this._nDataBytes, n = 8 * t.sigBytes; return e[n >>> 5] |= 128 << 24 - n % 32, e[(n + 64 >>> 9 << 4) + 14] = r.floor(i / 4294967296), e[(n + 64 >>> 9 << 4) + 15] = i, t.sigBytes = 4 * e.length, this._process(), this._hash }, clone: function () { var t = o.clone.call(this); return t._hash = this._hash.clone(), t } }); e.SHA256 = o._createHelper(l), e.HmacSHA256 = o._createHmacHelper(l) }(Math), function () { function r(t) { return t << 8 & 4278255360 | t >>> 8 & 16711935 } var e = t, i = e.lib, n = i.WordArray, o = e.enc; o.Utf16 = o.Utf16BE = { stringify: function (t) { for (var r = t.words, e = t.sigBytes, i = [], n = 0; n < e; n += 2) { var o = r[n >>> 2] >>> 16 - n % 4 * 8 & 65535; i.push(String.fromCharCode(o)) } return i.join("") }, parse: function (t) { for (var r = t.length, e = [], i = 0; i < r; i++)e[i >>> 1] |= t.charCodeAt(i) << 16 - i % 2 * 16; return n.create(e, 2 * r) } }; o.Utf16LE = { stringify: function (t) { for (var e = t.words, i = t.sigBytes, n = [], o = 0; o < i; o += 2) { var s = r(e[o >>> 2] >>> 16 - o % 4 * 8 & 65535); n.push(String.fromCharCode(s)) } return n.join("") }, parse: function (t) { for (var e = t.length, i = [], o = 0; o < e; o++)i[o >>> 1] |= r(t.charCodeAt(o) << 16 - o % 2 * 16); return n.create(i, 2 * e) } } }(), function () { if ("function" == typeof ArrayBuffer) { var r = t, e = r.lib, i = e.WordArray, n = i.init, o = i.init = function (t) { if (t instanceof ArrayBuffer && (t = new Uint8Array(t)), (t instanceof Int8Array || "undefined" != typeof Uint8ClampedArray && t instanceof Uint8ClampedArray || t instanceof Int16Array || t instanceof Uint16Array || t instanceof Int32Array || t instanceof Uint32Array || t instanceof Float32Array || t instanceof Float64Array) && (t = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), t instanceof Uint8Array) { for (var r = t.byteLength, e = [], i = 0; i < r; i++)e[i >>> 2] |= t[i] << 24 - i % 4 * 8; n.call(this, e, r) } else n.apply(this, arguments) }; o.prototype = i } }(), function (r) { function e(t, r, e) { return t ^ r ^ e } function i(t, r, e) { return t & r | ~t & e } function n(t, r, e) { return (t | ~r) ^ e } function o(t, r, e) { return t & e | r & ~e } function s(t, r, e) { return t ^ (r | ~e) } function a(t, r) { return t << r | t >>> 32 - r } var c = t, h = c.lib, l = h.WordArray, f = h.Hasher, u = c.algo, d = l.create([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]), v = l.create([5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]), p = l.create([11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6]), _ = l.create([8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]), y = l.create([0, 1518500249, 1859775393, 2400959708, 2840853838]), g = l.create([1352829926, 1548603684, 1836072691, 2053994217, 0]), B = u.RIPEMD160 = f.extend({ _doReset: function () { this._hash = l.create([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) }, _doProcessBlock: function (t, r) { for (var c = 0; c < 16; c++) { var h = r + c, l = t[h]; t[h] = 16711935 & (l << 8 | l >>> 24) | 4278255360 & (l << 24 | l >>> 8) } var f, u, B, w, k, S, m, x, b, H, z = this._hash.words, A = y.words, C = g.words, D = d.words, R = v.words, E = p.words, M = _.words; S = f = z[0], m = u = z[1], x = B = z[2], b = w = z[3], H = k = z[4]; for (var F, c = 0; c < 80; c += 1)F = f + t[r + D[c]] | 0, F += c < 16 ? e(u, B, w) + A[0] : c < 32 ? i(u, B, w) + A[1] : c < 48 ? n(u, B, w) + A[2] : c < 64 ? o(u, B, w) + A[3] : s(u, B, w) + A[4], F |= 0, F = a(F, E[c]), F = F + k | 0, f = k, k = w, w = a(B, 10), B = u, u = F, F = S + t[r + R[c]] | 0, F += c < 16 ? s(m, x, b) + C[0] : c < 32 ? o(m, x, b) + C[1] : c < 48 ? n(m, x, b) + C[2] : c < 64 ? i(m, x, b) + C[3] : e(m, x, b) + C[4], F |= 0, F = a(F, M[c]), F = F + H | 0, S = H, H = b, b = a(x, 10), x = m, m = F; F = z[1] + B + b | 0, z[1] = z[2] + w + H | 0, z[2] = z[3] + k + S | 0, z[3] = z[4] + f + m | 0, z[4] = z[0] + u + x | 0, z[0] = F }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 64 >>> 9 << 4) + 14] = 16711935 & (e << 8 | e >>> 24) | 4278255360 & (e << 24 | e >>> 8), t.sigBytes = 4 * (r.length + 1), this._process(); for (var n = this._hash, o = n.words, s = 0; s < 5; s++) { var a = o[s]; o[s] = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8) } return n }, clone: function () { var t = f.clone.call(this); return t._hash = this._hash.clone(), t } }); c.RIPEMD160 = f._createHelper(B), c.HmacRIPEMD160 = f._createHmacHelper(B) }(Math), function () { var r = t, e = r.lib, i = e.Base, n = r.enc, o = n.Utf8, s = r.algo; s.HMAC = i.extend({ init: function (t, r) { t = this._hasher = new t.init, "string" == typeof r && (r = o.parse(r)); var e = t.blockSize, i = 4 * e; r.sigBytes > i && (r = t.finalize(r)), r.clamp(); for (var n = this._oKey = r.clone(), s = this._iKey = r.clone(), a = n.words, c = s.words, h = 0; h < e; h++)a[h] ^= 1549556828, c[h] ^= 909522486; n.sigBytes = s.sigBytes = i, this.reset() }, reset: function () { var t = this._hasher; t.reset(), t.update(this._iKey) }, update: function (t) { return this._hasher.update(t), this }, finalize: function (t) { var r = this._hasher, e = r.finalize(t); r.reset(); var i = r.finalize(this._oKey.clone().concat(e)); return i } }) }(), function () { var r = t, e = r.lib, i = e.Base, n = e.WordArray, o = r.algo, s = o.SHA1, a = o.HMAC, c = o.PBKDF2 = i.extend({ cfg: i.extend({ keySize: 4, hasher: s, iterations: 1 }), init: function (t) { this.cfg = this.cfg.extend(t) }, compute: function (t, r) { for (var e = this.cfg, i = a.create(e.hasher, t), o = n.create(), s = n.create([1]), c = o.words, h = s.words, l = e.keySize, f = e.iterations; c.length < l;) { var u = i.update(r).finalize(s); i.reset(); for (var d = u.words, v = d.length, p = u, _ = 1; _ < f; _++) { p = i.finalize(p), i.reset(); for (var y = p.words, g = 0; g < v; g++)d[g] ^= y[g] } o.concat(u), h[0]++ } return o.sigBytes = 4 * l, o } }); r.PBKDF2 = function (t, r, e) { return c.create(e).compute(t, r) } }(), function () { var r = t, e = r.lib, i = e.Base, n = e.WordArray, o = r.algo, s = o.MD5, a = o.EvpKDF = i.extend({ cfg: i.extend({ keySize: 4, hasher: s, iterations: 1 }), init: function (t) { this.cfg = this.cfg.extend(t) }, compute: function (t, r) { for (var e = this.cfg, i = e.hasher.create(), o = n.create(), s = o.words, a = e.keySize, c = e.iterations; s.length < a;) { h && i.update(h); var h = i.update(t).finalize(r); i.reset(); for (var l = 1; l < c; l++)h = i.finalize(h), i.reset(); o.concat(h) } return o.sigBytes = 4 * a, o } }); r.EvpKDF = function (t, r, e) { return a.create(e).compute(t, r) } }(), function () { var r = t, e = r.lib, i = e.WordArray, n = r.algo, o = n.SHA256, s = n.SHA224 = o.extend({ _doReset: function () { this._hash = new i.init([3238371032, 914150663, 812702999, 4144912697, 4290775857, 1750603025, 1694076839, 3204075428]) }, _doFinalize: function () { var t = o._doFinalize.call(this); return t.sigBytes -= 4, t } }); r.SHA224 = o._createHelper(s), r.HmacSHA224 = o._createHmacHelper(s) }(), function (r) { var e = t, i = e.lib, n = i.Base, o = i.WordArray, s = e.x64 = {}; s.Word = n.extend({ init: function (t, r) { this.high = t, this.low = r } }), s.WordArray = n.extend({ init: function (t, e) { t = this.words = t || [], e != r ? this.sigBytes = e : this.sigBytes = 8 * t.length }, toX32: function () { for (var t = this.words, r = t.length, e = [], i = 0; i < r; i++) { var n = t[i]; e.push(n.high), e.push(n.low) } return o.create(e, this.sigBytes) }, clone: function () { for (var t = n.clone.call(this), r = t.words = this.words.slice(0), e = r.length, i = 0; i < e; i++)r[i] = r[i].clone(); return t } }) }(), function (r) { var e = t, i = e.lib, n = i.WordArray, o = i.Hasher, s = e.x64, a = s.Word, c = e.algo, h = [], l = [], f = []; !function () { for (var t = 1, r = 0, e = 0; e < 24; e++) { h[t + 5 * r] = (e + 1) * (e + 2) / 2 % 64; var i = r % 5, n = (2 * t + 3 * r) % 5; t = i, r = n } for (var t = 0; t < 5; t++)for (var r = 0; r < 5; r++)l[t + 5 * r] = r + (2 * t + 3 * r) % 5 * 5; for (var o = 1, s = 0; s < 24; s++) { for (var c = 0, u = 0, d = 0; d < 7; d++) { if (1 & o) { var v = (1 << d) - 1; v < 32 ? u ^= 1 << v : c ^= 1 << v - 32 } 128 & o ? o = o << 1 ^ 113 : o <<= 1 } f[s] = a.create(c, u) } }(); var u = []; !function () { for (var t = 0; t < 25; t++)u[t] = a.create() }(); var d = c.SHA3 = o.extend({ cfg: o.cfg.extend({ outputLength: 512 }), _doReset: function () { for (var t = this._state = [], r = 0; r < 25; r++)t[r] = new a.init; this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32 }, _doProcessBlock: function (t, r) { for (var e = this._state, i = this.blockSize / 2, n = 0; n < i; n++) { var o = t[r + 2 * n], s = t[r + 2 * n + 1]; o = 16711935 & (o << 8 | o >>> 24) | 4278255360 & (o << 24 | o >>> 8), s = 16711935 & (s << 8 | s >>> 24) | 4278255360 & (s << 24 | s >>> 8); var a = e[n]; a.high ^= s, a.low ^= o } for (var c = 0; c < 24; c++) { for (var d = 0; d < 5; d++) { for (var v = 0, p = 0, _ = 0; _ < 5; _++) { var a = e[d + 5 * _]; v ^= a.high, p ^= a.low } var y = u[d]; y.high = v, y.low = p } for (var d = 0; d < 5; d++)for (var g = u[(d + 4) % 5], B = u[(d + 1) % 5], w = B.high, k = B.low, v = g.high ^ (w << 1 | k >>> 31), p = g.low ^ (k << 1 | w >>> 31), _ = 0; _ < 5; _++) { var a = e[d + 5 * _]; a.high ^= v, a.low ^= p } for (var S = 1; S < 25; S++) { var a = e[S], m = a.high, x = a.low, b = h[S]; if (b < 32) var v = m << b | x >>> 32 - b, p = x << b | m >>> 32 - b; else var v = x << b - 32 | m >>> 64 - b, p = m << b - 32 | x >>> 64 - b; var H = u[l[S]]; H.high = v, H.low = p } var z = u[0], A = e[0]; z.high = A.high, z.low = A.low; for (var d = 0; d < 5; d++)for (var _ = 0; _ < 5; _++) { var S = d + 5 * _, a = e[S], C = u[S], D = u[(d + 1) % 5 + 5 * _], R = u[(d + 2) % 5 + 5 * _]; a.high = C.high ^ ~D.high & R.high, a.low = C.low ^ ~D.low & R.low } var a = e[0], E = f[c]; a.high ^= E.high, a.low ^= E.low } }, _doFinalize: function () { var t = this._data, e = t.words, i = (8 * this._nDataBytes, 8 * t.sigBytes), o = 32 * this.blockSize; e[i >>> 5] |= 1 << 24 - i % 32, e[(r.ceil((i + 1) / o) * o >>> 5) - 1] |= 128, t.sigBytes = 4 * e.length, this._process(); for (var s = this._state, a = this.cfg.outputLength / 8, c = a / 8, h = [], l = 0; l < c; l++) { var f = s[l], u = f.high, d = f.low; u = 16711935 & (u << 8 | u >>> 24) | 4278255360 & (u << 24 | u >>> 8), d = 16711935 & (d << 8 | d >>> 24) | 4278255360 & (d << 24 | d >>> 8), h.push(d), h.push(u) } return new n.init(h, a) }, clone: function () { for (var t = o.clone.call(this), r = t._state = this._state.slice(0), e = 0; e < 25; e++)r[e] = r[e].clone(); return t } }); e.SHA3 = o._createHelper(d), e.HmacSHA3 = o._createHmacHelper(d) }(Math), function () { function r() { return s.create.apply(s, arguments) } var e = t, i = e.lib, n = i.Hasher, o = e.x64, s = o.Word, a = o.WordArray, c = e.algo, h = [r(1116352408, 3609767458), r(1899447441, 602891725), r(3049323471, 3964484399), r(3921009573, 2173295548), r(961987163, 4081628472), r(1508970993, 3053834265), r(2453635748, 2937671579), r(2870763221, 3664609560), r(3624381080, 2734883394), r(310598401, 1164996542), r(607225278, 1323610764), r(1426881987, 3590304994), r(1925078388, 4068182383), r(2162078206, 991336113), r(2614888103, 633803317), r(3248222580, 3479774868), r(3835390401, 2666613458), r(4022224774, 944711139), r(264347078, 2341262773), r(604807628, 2007800933), r(770255983, 1495990901), r(1249150122, 1856431235), r(1555081692, 3175218132), r(1996064986, 2198950837), r(2554220882, 3999719339), r(2821834349, 766784016), r(2952996808, 2566594879), r(3210313671, 3203337956), r(3336571891, 1034457026), r(3584528711, 2466948901), r(113926993, 3758326383), r(338241895, 168717936), r(666307205, 1188179964), r(773529912, 1546045734), r(1294757372, 1522805485), r(1396182291, 2643833823), r(1695183700, 2343527390), r(1986661051, 1014477480), r(2177026350, 1206759142), r(2456956037, 344077627), r(2730485921, 1290863460), r(2820302411, 3158454273), r(3259730800, 3505952657), r(3345764771, 106217008), r(3516065817, 3606008344), r(3600352804, 1432725776), r(4094571909, 1467031594), r(275423344, 851169720), r(430227734, 3100823752), r(506948616, 1363258195), r(659060556, 3750685593), r(883997877, 3785050280), r(958139571, 3318307427), r(1322822218, 3812723403), r(1537002063, 2003034995), r(1747873779, 3602036899), r(1955562222, 1575990012), r(2024104815, 1125592928), r(2227730452, 2716904306), r(2361852424, 442776044), r(2428436474, 593698344), r(2756734187, 3733110249), r(3204031479, 2999351573), r(3329325298, 3815920427), r(3391569614, 3928383900), r(3515267271, 566280711), r(3940187606, 3454069534), r(4118630271, 4000239992), r(116418474, 1914138554), r(174292421, 2731055270), r(289380356, 3203993006), r(460393269, 320620315), r(685471733, 587496836), r(852142971, 1086792851), r(1017036298, 365543100), r(1126000580, 2618297676), r(1288033470, 3409855158), r(1501505948, 4234509866), r(1607167915, 987167468), r(1816402316, 1246189591)], l = []; !function () { for (var t = 0; t < 80; t++)l[t] = r() }(); var f = c.SHA512 = n.extend({ _doReset: function () { this._hash = new a.init([new s.init(1779033703, 4089235720), new s.init(3144134277, 2227873595), new s.init(1013904242, 4271175723), new s.init(2773480762, 1595750129), new s.init(1359893119, 2917565137), new s.init(2600822924, 725511199), new s.init(528734635, 4215389547), new s.init(1541459225, 327033209)]) }, _doProcessBlock: function (t, r) { for (var e = this._hash.words, i = e[0], n = e[1], o = e[2], s = e[3], a = e[4], c = e[5], f = e[6], u = e[7], d = i.high, v = i.low, p = n.high, _ = n.low, y = o.high, g = o.low, B = s.high, w = s.low, k = a.high, S = a.low, m = c.high, x = c.low, b = f.high, H = f.low, z = u.high, A = u.low, C = d, D = v, R = p, E = _, M = y, F = g, P = B, W = w, O = k, U = S, I = m, K = x, X = b, L = H, j = z, N = A, T = 0; T < 80; T++) { var Z = l[T]; if (T < 16) var q = Z.high = 0 | t[r + 2 * T], G = Z.low = 0 | t[r + 2 * T + 1]; else { var J = l[T - 15], $ = J.high, Q = J.low, V = ($ >>> 1 | Q << 31) ^ ($ >>> 8 | Q << 24) ^ $ >>> 7, Y = (Q >>> 1 | $ << 31) ^ (Q >>> 8 | $ << 24) ^ (Q >>> 7 | $ << 25), tt = l[T - 2], rt = tt.high, et = tt.low, it = (rt >>> 19 | et << 13) ^ (rt << 3 | et >>> 29) ^ rt >>> 6, nt = (et >>> 19 | rt << 13) ^ (et << 3 | rt >>> 29) ^ (et >>> 6 | rt << 26), ot = l[T - 7], st = ot.high, at = ot.low, ct = l[T - 16], ht = ct.high, lt = ct.low, G = Y + at, q = V + st + (G >>> 0 < Y >>> 0 ? 1 : 0), G = G + nt, q = q + it + (G >>> 0 < nt >>> 0 ? 1 : 0), G = G + lt, q = q + ht + (G >>> 0 < lt >>> 0 ? 1 : 0); Z.high = q, Z.low = G } var ft = O & I ^ ~O & X, ut = U & K ^ ~U & L, dt = C & R ^ C & M ^ R & M, vt = D & E ^ D & F ^ E & F, pt = (C >>> 28 | D << 4) ^ (C << 30 | D >>> 2) ^ (C << 25 | D >>> 7), _t = (D >>> 28 | C << 4) ^ (D << 30 | C >>> 2) ^ (D << 25 | C >>> 7), yt = (O >>> 14 | U << 18) ^ (O >>> 18 | U << 14) ^ (O << 23 | U >>> 9), gt = (U >>> 14 | O << 18) ^ (U >>> 18 | O << 14) ^ (U << 23 | O >>> 9), Bt = h[T], wt = Bt.high, kt = Bt.low, St = N + gt, mt = j + yt + (St >>> 0 < N >>> 0 ? 1 : 0), St = St + ut, mt = mt + ft + (St >>> 0 < ut >>> 0 ? 1 : 0), St = St + kt, mt = mt + wt + (St >>> 0 < kt >>> 0 ? 1 : 0), St = St + G, mt = mt + q + (St >>> 0 < G >>> 0 ? 1 : 0), xt = _t + vt, bt = pt + dt + (xt >>> 0 < _t >>> 0 ? 1 : 0); j = X, N = L, X = I, L = K, I = O, K = U, U = W + St | 0, O = P + mt + (U >>> 0 < W >>> 0 ? 1 : 0) | 0, P = M, W = F, M = R, F = E, R = C, E = D, D = St + xt | 0, C = mt + bt + (D >>> 0 < St >>> 0 ? 1 : 0) | 0 } v = i.low = v + D, i.high = d + C + (v >>> 0 < D >>> 0 ? 1 : 0), _ = n.low = _ + E, n.high = p + R + (_ >>> 0 < E >>> 0 ? 1 : 0), g = o.low = g + F, o.high = y + M + (g >>> 0 < F >>> 0 ? 1 : 0), w = s.low = w + W, s.high = B + P + (w >>> 0 < W >>> 0 ? 1 : 0), S = a.low = S + U, a.high = k + O + (S >>> 0 < U >>> 0 ? 1 : 0), x = c.low = x + K, c.high = m + I + (x >>> 0 < K >>> 0 ? 1 : 0), H = f.low = H + L, f.high = b + X + (H >>> 0 < L >>> 0 ? 1 : 0), A = u.low = A + N, u.high = z + j + (A >>> 0 < N >>> 0 ? 1 : 0) }, _doFinalize: function () { var t = this._data, r = t.words, e = 8 * this._nDataBytes, i = 8 * t.sigBytes; r[i >>> 5] |= 128 << 24 - i % 32, r[(i + 128 >>> 10 << 5) + 30] = Math.floor(e / 4294967296), r[(i + 128 >>> 10 << 5) + 31] = e, t.sigBytes = 4 * r.length, this._process(); var n = this._hash.toX32(); return n }, clone: function () { var t = n.clone.call(this); return t._hash = this._hash.clone(), t }, blockSize: 32 }); e.SHA512 = n._createHelper(f), e.HmacSHA512 = n._createHmacHelper(f) }(), function () { var r = t, e = r.x64, i = e.Word, n = e.WordArray, o = r.algo, s = o.SHA512, a = o.SHA384 = s.extend({ _doReset: function () { this._hash = new n.init([new i.init(3418070365, 3238371032), new i.init(1654270250, 914150663), new i.init(2438529370, 812702999), new i.init(355462360, 4144912697), new i.init(1731405415, 4290775857), new i.init(2394180231, 1750603025), new i.init(3675008525, 1694076839), new i.init(1203062813, 3204075428)]) }, _doFinalize: function () { var t = s._doFinalize.call(this); return t.sigBytes -= 16, t } }); r.SHA384 = s._createHelper(a), r.HmacSHA384 = s._createHmacHelper(a) }(), t.lib.Cipher || function (r) { var e = t, i = e.lib, n = i.Base, o = i.WordArray, s = i.BufferedBlockAlgorithm, a = e.enc, c = (a.Utf8, a.Base64), h = e.algo, l = h.EvpKDF, f = i.Cipher = s.extend({ cfg: n.extend(), createEncryptor: function (t, r) { return this.create(this._ENC_XFORM_MODE, t, r) }, createDecryptor: function (t, r) { return this.create(this._DEC_XFORM_MODE, t, r) }, init: function (t, r, e) { this.cfg = this.cfg.extend(e), this._xformMode = t, this._key = r, this.reset() }, reset: function () { s.reset.call(this), this._doReset() }, process: function (t) { return this._append(t), this._process() }, finalize: function (t) { t && this._append(t); var r = this._doFinalize(); return r }, keySize: 4, ivSize: 4, _ENC_XFORM_MODE: 1, _DEC_XFORM_MODE: 2, _createHelper: function () { function t(t) { return "string" == typeof t ? m : w } return function (r) { return { encrypt: function (e, i, n) { return t(i).encrypt(r, e, i, n) }, decrypt: function (e, i, n) { return t(i).decrypt(r, e, i, n) } } } }() }), u = (i.StreamCipher = f.extend({ _doFinalize: function () { var t = this._process(!0); return t }, blockSize: 1 }), e.mode = {}), d = i.BlockCipherMode = n.extend({ createEncryptor: function (t, r) { return this.Encryptor.create(t, r) }, createDecryptor: function (t, r) { return this.Decryptor.create(t, r) }, init: function (t, r) { this._cipher = t, this._iv = r } }), v = u.CBC = function () { function t(t, e, i) { var n = this._iv; if (n) { var o = n; this._iv = r } else var o = this._prevBlock; for (var s = 0; s < i; s++)t[e + s] ^= o[s] } var e = d.extend(); return e.Encryptor = e.extend({ processBlock: function (r, e) { var i = this._cipher, n = i.blockSize; t.call(this, r, e, n), i.encryptBlock(r, e), this._prevBlock = r.slice(e, e + n) } }), e.Decryptor = e.extend({ processBlock: function (r, e) { var i = this._cipher, n = i.blockSize, o = r.slice(e, e + n); i.decryptBlock(r, e), t.call(this, r, e, n), this._prevBlock = o } }), e }(), p = e.pad = {}, _ = p.Pkcs7 = { pad: function (t, r) { for (var e = 4 * r, i = e - t.sigBytes % e, n = i << 24 | i << 16 | i << 8 | i, s = [], a = 0; a < i; a += 4)s.push(n); var c = o.create(s, i); t.concat(c) }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, y = (i.BlockCipher = f.extend({ cfg: f.cfg.extend({ mode: v, padding: _ }), reset: function () { f.reset.call(this); var t = this.cfg, r = t.iv, e = t.mode; if (this._xformMode == this._ENC_XFORM_MODE) var i = e.createEncryptor; else { var i = e.createDecryptor; this._minBufferSize = 1 } this._mode && this._mode.__creator == i ? this._mode.init(this, r && r.words) : (this._mode = i.call(e, this, r && r.words), this._mode.__creator = i) }, _doProcessBlock: function (t, r) { this._mode.processBlock(t, r) }, _doFinalize: function () { var t = this.cfg.padding; if (this._xformMode == this._ENC_XFORM_MODE) { t.pad(this._data, this.blockSize); var r = this._process(!0) } else { var r = this._process(!0); t.unpad(r) } return r }, blockSize: 4 }), i.CipherParams = n.extend({ init: function (t) { this.mixIn(t) }, toString: function (t) { return (t || this.formatter).stringify(this) } })), g = e.format = {}, B = g.OpenSSL = { stringify: function (t) { var r = t.ciphertext, e = t.salt; if (e) var i = o.create([1398893684, 1701076831]).concat(e).concat(r); else var i = r; return i.toString(c) }, parse: function (t) { var r = c.parse(t), e = r.words; if (1398893684 == e[0] && 1701076831 == e[1]) { var i = o.create(e.slice(2, 4)); e.splice(0, 4), r.sigBytes -= 16 } return y.create({ ciphertext: r, salt: i }) } }, w = i.SerializableCipher = n.extend({ cfg: n.extend({ format: B }), encrypt: function (t, r, e, i) { i = this.cfg.extend(i); var n = t.createEncryptor(e, i), o = n.finalize(r), s = n.cfg; return y.create({ ciphertext: o, key: e, iv: s.iv, algorithm: t, mode: s.mode, padding: s.padding, blockSize: t.blockSize, formatter: i.format }) }, decrypt: function (t, r, e, i) { i = this.cfg.extend(i), r = this._parse(r, i.format); var n = t.createDecryptor(e, i).finalize(r.ciphertext); return n }, _parse: function (t, r) { return "string" == typeof t ? r.parse(t, this) : t } }), k = e.kdf = {}, S = k.OpenSSL = { execute: function (t, r, e, i) { i || (i = o.random(8)); var n = l.create({ keySize: r + e }).compute(t, i), s = o.create(n.words.slice(r), 4 * e); return n.sigBytes = 4 * r, y.create({ key: n, iv: s, salt: i }) } }, m = i.PasswordBasedCipher = w.extend({ cfg: w.cfg.extend({ kdf: S }), encrypt: function (t, r, e, i) { i = this.cfg.extend(i); var n = i.kdf.execute(e, t.keySize, t.ivSize); i.iv = n.iv; var o = w.encrypt.call(this, t, r, n.key, i); return o.mixIn(n), o }, decrypt: function (t, r, e, i) { i = this.cfg.extend(i), r = this._parse(r, i.format); var n = i.kdf.execute(e, t.keySize, t.ivSize, r.salt); i.iv = n.iv; var o = w.decrypt.call(this, t, r, n.key, i); return o } }) }(), t.mode.CFB = function () { function r(t, r, e, i) { var n = this._iv; if (n) { var o = n.slice(0); this._iv = void 0 } else var o = this._prevBlock; i.encryptBlock(o, 0); for (var s = 0; s < e; s++)t[r + s] ^= o[s] } var e = t.lib.BlockCipherMode.extend(); return e.Encryptor = e.extend({ processBlock: function (t, e) { var i = this._cipher, n = i.blockSize; r.call(this, t, e, n, i), this._prevBlock = t.slice(e, e + n) } }), e.Decryptor = e.extend({ processBlock: function (t, e) { var i = this._cipher, n = i.blockSize, o = t.slice(e, e + n); r.call(this, t, e, n, i), this._prevBlock = o } }), e }(), t.mode.ECB = function () { var r = t.lib.BlockCipherMode.extend(); return r.Encryptor = r.extend({ processBlock: function (t, r) { this._cipher.encryptBlock(t, r) } }), r.Decryptor = r.extend({ processBlock: function (t, r) { this._cipher.decryptBlock(t, r) } }), r }(), t.pad.AnsiX923 = { pad: function (t, r) { var e = t.sigBytes, i = 4 * r, n = i - e % i, o = e + n - 1; t.clamp(), t.words[o >>> 2] |= n << 24 - o % 4 * 8, t.sigBytes += n }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, t.pad.Iso10126 = { pad: function (r, e) { var i = 4 * e, n = i - r.sigBytes % i; r.concat(t.lib.WordArray.random(n - 1)).concat(t.lib.WordArray.create([n << 24], 1)) }, unpad: function (t) { var r = 255 & t.words[t.sigBytes - 1 >>> 2]; t.sigBytes -= r } }, t.pad.Iso97971 = { pad: function (r, e) { r.concat(t.lib.WordArray.create([2147483648], 1)), t.pad.ZeroPadding.pad(r, e) }, unpad: function (r) { t.pad.ZeroPadding.unpad(r), r.sigBytes-- } }, t.mode.OFB = function () { var r = t.lib.BlockCipherMode.extend(), e = r.Encryptor = r.extend({ processBlock: function (t, r) { var e = this._cipher, i = e.blockSize, n = this._iv, o = this._keystream; n && (o = this._keystream = n.slice(0), this._iv = void 0), e.encryptBlock(o, 0); for (var s = 0; s < i; s++)t[r + s] ^= o[s] } }); return r.Decryptor = e, r }(), t.pad.NoPadding = { pad: function () { }, unpad: function () { } }, function (r) { var e = t, i = e.lib, n = i.CipherParams, o = e.enc, s = o.Hex, a = e.format; a.Hex = { stringify: function (t) { return t.ciphertext.toString(s) }, parse: function (t) { var r = s.parse(t); return n.create({ ciphertext: r }) } } }(), function () { var r = t, e = r.lib, i = e.BlockCipher, n = r.algo, o = [], s = [], a = [], c = [], h = [], l = [], f = [], u = [], d = [], v = []; !function () { for (var t = [], r = 0; r < 256; r++)r < 128 ? t[r] = r << 1 : t[r] = r << 1 ^ 283; for (var e = 0, i = 0, r = 0; r < 256; r++) { var n = i ^ i << 1 ^ i << 2 ^ i << 3 ^ i << 4; n = n >>> 8 ^ 255 & n ^ 99, o[e] = n, s[n] = e; var p = t[e], _ = t[p], y = t[_], g = 257 * t[n] ^ 16843008 * n; a[e] = g << 24 | g >>> 8, c[e] = g << 16 | g >>> 16, h[e] = g << 8 | g >>> 24, l[e] = g; var g = 16843009 * y ^ 65537 * _ ^ 257 * p ^ 16843008 * e; f[n] = g << 24 | g >>> 8, u[n] = g << 16 | g >>> 16, d[n] = g << 8 | g >>> 24, v[n] = g, e ? (e = p ^ t[t[t[y ^ p]]], i ^= t[t[i]]) : e = i = 1 } }(); var p = [0, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54], _ = n.AES = i.extend({ _doReset: function () { if (!this._nRounds || this._keyPriorReset !== this._key) { for (var t = this._keyPriorReset = this._key, r = t.words, e = t.sigBytes / 4, i = this._nRounds = e + 6, n = 4 * (i + 1), s = this._keySchedule = [], a = 0; a < n; a++)if (a < e) s[a] = r[a]; else { var c = s[a - 1]; a % e ? e > 6 && a % e == 4 && (c = o[c >>> 24] << 24 | o[c >>> 16 & 255] << 16 | o[c >>> 8 & 255] << 8 | o[255 & c]) : (c = c << 8 | c >>> 24, c = o[c >>> 24] << 24 | o[c >>> 16 & 255] << 16 | o[c >>> 8 & 255] << 8 | o[255 & c], c ^= p[a / e | 0] << 24), s[a] = s[a - e] ^ c } for (var h = this._invKeySchedule = [], l = 0; l < n; l++) { var a = n - l; if (l % 4) var c = s[a]; else var c = s[a - 4]; l < 4 || a <= 4 ? h[l] = c : h[l] = f[o[c >>> 24]] ^ u[o[c >>> 16 & 255]] ^ d[o[c >>> 8 & 255]] ^ v[o[255 & c]] } } }, encryptBlock: function (t, r) { this._doCryptBlock(t, r, this._keySchedule, a, c, h, l, o) }, decryptBlock: function (t, r) { var e = t[r + 1]; t[r + 1] = t[r + 3], t[r + 3] = e, this._doCryptBlock(t, r, this._invKeySchedule, f, u, d, v, s); var e = t[r + 1]; t[r + 1] = t[r + 3], t[r + 3] = e }, _doCryptBlock: function (t, r, e, i, n, o, s, a) { for (var c = this._nRounds, h = t[r] ^ e[0], l = t[r + 1] ^ e[1], f = t[r + 2] ^ e[2], u = t[r + 3] ^ e[3], d = 4, v = 1; v < c; v++) { var p = i[h >>> 24] ^ n[l >>> 16 & 255] ^ o[f >>> 8 & 255] ^ s[255 & u] ^ e[d++], _ = i[l >>> 24] ^ n[f >>> 16 & 255] ^ o[u >>> 8 & 255] ^ s[255 & h] ^ e[d++], y = i[f >>> 24] ^ n[u >>> 16 & 255] ^ o[h >>> 8 & 255] ^ s[255 & l] ^ e[d++], g = i[u >>> 24] ^ n[h >>> 16 & 255] ^ o[l >>> 8 & 255] ^ s[255 & f] ^ e[d++]; h = p, l = _, f = y, u = g } var p = (a[h >>> 24] << 24 | a[l >>> 16 & 255] << 16 | a[f >>> 8 & 255] << 8 | a[255 & u]) ^ e[d++], _ = (a[l >>> 24] << 24 | a[f >>> 16 & 255] << 16 | a[u >>> 8 & 255] << 8 | a[255 & h]) ^ e[d++], y = (a[f >>> 24] << 24 | a[u >>> 16 & 255] << 16 | a[h >>> 8 & 255] << 8 | a[255 & l]) ^ e[d++], g = (a[u >>> 24] << 24 | a[h >>> 16 & 255] << 16 | a[l >>> 8 & 255] << 8 | a[255 & f]) ^ e[d++]; t[r] = p, t[r + 1] = _, t[r + 2] = y, t[r + 3] = g }, keySize: 8 }); r.AES = i._createHelper(_) }(), function () { + function r(t, r) { var e = (this._lBlock >>> t ^ this._rBlock) & r; this._rBlock ^= e, this._lBlock ^= e << t } function e(t, r) { + var e = (this._rBlock >>> t ^ this._lBlock) & r; this._lBlock ^= e, this._rBlock ^= e << t; + } var i = t, n = i.lib, o = n.WordArray, s = n.BlockCipher, a = i.algo, c = [57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4], h = [14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32], l = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28], f = [{ 0: 8421888, 268435456: 32768, 536870912: 8421378, 805306368: 2, 1073741824: 512, 1342177280: 8421890, 1610612736: 8389122, 1879048192: 8388608, 2147483648: 514, 2415919104: 8389120, 2684354560: 33280, 2952790016: 8421376, 3221225472: 32770, 3489660928: 8388610, 3758096384: 0, 4026531840: 33282, 134217728: 0, 402653184: 8421890, 671088640: 33282, 939524096: 32768, 1207959552: 8421888, 1476395008: 512, 1744830464: 8421378, 2013265920: 2, 2281701376: 8389120, 2550136832: 33280, 2818572288: 8421376, 3087007744: 8389122, 3355443200: 8388610, 3623878656: 32770, 3892314112: 514, 4160749568: 8388608, 1: 32768, 268435457: 2, 536870913: 8421888, 805306369: 8388608, 1073741825: 8421378, 1342177281: 33280, 1610612737: 512, 1879048193: 8389122, 2147483649: 8421890, 2415919105: 8421376, 2684354561: 8388610, 2952790017: 33282, 3221225473: 514, 3489660929: 8389120, 3758096385: 32770, 4026531841: 0, 134217729: 8421890, 402653185: 8421376, 671088641: 8388608, 939524097: 512, 1207959553: 32768, 1476395009: 8388610, 1744830465: 2, 2013265921: 33282, 2281701377: 32770, 2550136833: 8389122, 2818572289: 514, 3087007745: 8421888, 3355443201: 8389120, 3623878657: 0, 3892314113: 33280, 4160749569: 8421378 }, { 0: 1074282512, 16777216: 16384, 33554432: 524288, 50331648: 1074266128, 67108864: 1073741840, 83886080: 1074282496, 100663296: 1073758208, 117440512: 16, 134217728: 540672, 150994944: 1073758224, 167772160: 1073741824, 184549376: 540688, 201326592: 524304, 218103808: 0, 234881024: 16400, 251658240: 1074266112, 8388608: 1073758208, 25165824: 540688, 41943040: 16, 58720256: 1073758224, 75497472: 1074282512, 92274688: 1073741824, 109051904: 524288, 125829120: 1074266128, 142606336: 524304, 159383552: 0, 176160768: 16384, 192937984: 1074266112, 209715200: 1073741840, 226492416: 540672, 243269632: 1074282496, 260046848: 16400, 268435456: 0, 285212672: 1074266128, 301989888: 1073758224, 318767104: 1074282496, 335544320: 1074266112, 352321536: 16, 369098752: 540688, 385875968: 16384, 402653184: 16400, 419430400: 524288, 436207616: 524304, 452984832: 1073741840, 469762048: 540672, 486539264: 1073758208, 503316480: 1073741824, 520093696: 1074282512, 276824064: 540688, 293601280: 524288, 310378496: 1074266112, 327155712: 16384, 343932928: 1073758208, 360710144: 1074282512, 377487360: 16, 394264576: 1073741824, 411041792: 1074282496, 427819008: 1073741840, 444596224: 1073758224, 461373440: 524304, 478150656: 0, 494927872: 16400, 511705088: 1074266128, 528482304: 540672 }, { 0: 260, 1048576: 0, 2097152: 67109120, 3145728: 65796, 4194304: 65540, 5242880: 67108868, 6291456: 67174660, 7340032: 67174400, 8388608: 67108864, 9437184: 67174656, 10485760: 65792, 11534336: 67174404, 12582912: 67109124, 13631488: 65536, 14680064: 4, 15728640: 256, 524288: 67174656, 1572864: 67174404, 2621440: 0, 3670016: 67109120, 4718592: 67108868, 5767168: 65536, 6815744: 65540, 7864320: 260, 8912896: 4, 9961472: 256, 11010048: 67174400, 12058624: 65796, 13107200: 65792, 14155776: 67109124, 15204352: 67174660, 16252928: 67108864, 16777216: 67174656, 17825792: 65540, 18874368: 65536, 19922944: 67109120, 20971520: 256, 22020096: 67174660, 23068672: 67108868, 24117248: 0, 25165824: 67109124, 26214400: 67108864, 27262976: 4, 28311552: 65792, 29360128: 67174400, 30408704: 260, 31457280: 65796, 32505856: 67174404, 17301504: 67108864, 18350080: 260, 19398656: 67174656, 20447232: 0, 21495808: 65540, 22544384: 67109120, 23592960: 256, 24641536: 67174404, 25690112: 65536, 26738688: 67174660, 27787264: 65796, 28835840: 67108868, 29884416: 67109124, 30932992: 67174400, 31981568: 4, 33030144: 65792 }, { 0: 2151682048, 65536: 2147487808, 131072: 4198464, 196608: 2151677952, 262144: 0, 327680: 4198400, 393216: 2147483712, 458752: 4194368, 524288: 2147483648, 589824: 4194304, 655360: 64, 720896: 2147487744, 786432: 2151678016, 851968: 4160, 917504: 4096, 983040: 2151682112, 32768: 2147487808, 98304: 64, 163840: 2151678016, 229376: 2147487744, 294912: 4198400, 360448: 2151682112, 425984: 0, 491520: 2151677952, 557056: 4096, 622592: 2151682048, 688128: 4194304, 753664: 4160, 819200: 2147483648, 884736: 4194368, 950272: 4198464, 1015808: 2147483712, 1048576: 4194368, 1114112: 4198400, 1179648: 2147483712, 1245184: 0, 1310720: 4160, 1376256: 2151678016, 1441792: 2151682048, 1507328: 2147487808, 1572864: 2151682112, 1638400: 2147483648, 1703936: 2151677952, 1769472: 4198464, 1835008: 2147487744, 1900544: 4194304, 1966080: 64, 2031616: 4096, 1081344: 2151677952, 1146880: 2151682112, 1212416: 0, 1277952: 4198400, 1343488: 4194368, 1409024: 2147483648, 1474560: 2147487808, 1540096: 64, 1605632: 2147483712, 1671168: 4096, 1736704: 2147487744, 1802240: 2151678016, 1867776: 4160, 1933312: 2151682048, 1998848: 4194304, 2064384: 4198464 }, { 0: 128, 4096: 17039360, 8192: 262144, 12288: 536870912, 16384: 537133184, 20480: 16777344, 24576: 553648256, 28672: 262272, 32768: 16777216, 36864: 537133056, 40960: 536871040, 45056: 553910400, 49152: 553910272, 53248: 0, 57344: 17039488, 61440: 553648128, 2048: 17039488, 6144: 553648256, 10240: 128, 14336: 17039360, 18432: 262144, 22528: 537133184, 26624: 553910272, 30720: 536870912, 34816: 537133056, 38912: 0, 43008: 553910400, 47104: 16777344, 51200: 536871040, 55296: 553648128, 59392: 16777216, 63488: 262272, 65536: 262144, 69632: 128, 73728: 536870912, 77824: 553648256, 81920: 16777344, 86016: 553910272, 90112: 537133184, 94208: 16777216, 98304: 553910400, 102400: 553648128, 106496: 17039360, 110592: 537133056, 114688: 262272, 118784: 536871040, 122880: 0, 126976: 17039488, 67584: 553648256, 71680: 16777216, 75776: 17039360, 79872: 537133184, 83968: 536870912, 88064: 17039488, 92160: 128, 96256: 553910272, 100352: 262272, 104448: 553910400, 108544: 0, 112640: 553648128, 116736: 16777344, 120832: 262144, 124928: 537133056, 129024: 536871040 }, { 0: 268435464, 256: 8192, 512: 270532608, 768: 270540808, 1024: 268443648, 1280: 2097152, 1536: 2097160, 1792: 268435456, 2048: 0, 2304: 268443656, 2560: 2105344, 2816: 8, 3072: 270532616, 3328: 2105352, 3584: 8200, 3840: 270540800, 128: 270532608, 384: 270540808, 640: 8, 896: 2097152, 1152: 2105352, 1408: 268435464, 1664: 268443648, 1920: 8200, 2176: 2097160, 2432: 8192, 2688: 268443656, 2944: 270532616, 3200: 0, 3456: 270540800, 3712: 2105344, 3968: 268435456, 4096: 268443648, 4352: 270532616, 4608: 270540808, 4864: 8200, 5120: 2097152, 5376: 268435456, 5632: 268435464, 5888: 2105344, 6144: 2105352, 6400: 0, 6656: 8, 6912: 270532608, 7168: 8192, 7424: 268443656, 7680: 270540800, 7936: 2097160, 4224: 8, 4480: 2105344, 4736: 2097152, 4992: 268435464, 5248: 268443648, 5504: 8200, 5760: 270540808, 6016: 270532608, 6272: 270540800, 6528: 270532616, 6784: 8192, 7040: 2105352, 7296: 2097160, 7552: 0, 7808: 268435456, 8064: 268443656 }, { 0: 1048576, 16: 33555457, 32: 1024, 48: 1049601, 64: 34604033, 80: 0, 96: 1, 112: 34603009, 128: 33555456, 144: 1048577, 160: 33554433, 176: 34604032, 192: 34603008, 208: 1025, 224: 1049600, 240: 33554432, 8: 34603009, 24: 0, 40: 33555457, 56: 34604032, 72: 1048576, 88: 33554433, 104: 33554432, 120: 1025, 136: 1049601, 152: 33555456, 168: 34603008, 184: 1048577, 200: 1024, 216: 34604033, 232: 1, 248: 1049600, 256: 33554432, 272: 1048576, 288: 33555457, 304: 34603009, 320: 1048577, 336: 33555456, 352: 34604032, 368: 1049601, 384: 1025, 400: 34604033, 416: 1049600, 432: 1, 448: 0, 464: 34603008, 480: 33554433, 496: 1024, 264: 1049600, 280: 33555457, 296: 34603009, 312: 1, 328: 33554432, 344: 1048576, 360: 1025, 376: 34604032, 392: 33554433, 408: 34603008, 424: 0, 440: 34604033, 456: 1049601, 472: 1024, 488: 33555456, 504: 1048577 }, { 0: 134219808, 1: 131072, 2: 134217728, 3: 32, 4: 131104, 5: 134350880, 6: 134350848, 7: 2048, 8: 134348800, 9: 134219776, 10: 133120, 11: 134348832, 12: 2080, 13: 0, 14: 134217760, 15: 133152, 2147483648: 2048, 2147483649: 134350880, 2147483650: 134219808, 2147483651: 134217728, 2147483652: 134348800, 2147483653: 133120, 2147483654: 133152, 2147483655: 32, 2147483656: 134217760, 2147483657: 2080, 2147483658: 131104, 2147483659: 134350848, 2147483660: 0, 2147483661: 134348832, 2147483662: 134219776, 2147483663: 131072, 16: 133152, 17: 134350848, 18: 32, 19: 2048, 20: 134219776, 21: 134217760, 22: 134348832, 23: 131072, 24: 0, 25: 131104, 26: 134348800, 27: 134219808, 28: 134350880, 29: 133120, 30: 2080, 31: 134217728, 2147483664: 131072, 2147483665: 2048, 2147483666: 134348832, 2147483667: 133152, 2147483668: 32, 2147483669: 134348800, 2147483670: 134217728, 2147483671: 134219808, 2147483672: 134350880, 2147483673: 134217760, 2147483674: 134219776, 2147483675: 0, 2147483676: 133120, 2147483677: 2080, 2147483678: 131104, 2147483679: 134350848 }], u = [4160749569, 528482304, 33030144, 2064384, 129024, 8064, 504, 2147483679], d = a.DES = s.extend({ _doReset: function () { for (var t = this._key, r = t.words, e = [], i = 0; i < 56; i++) { var n = c[i] - 1; e[i] = r[n >>> 5] >>> 31 - n % 32 & 1 } for (var o = this._subKeys = [], s = 0; s < 16; s++) { for (var a = o[s] = [], f = l[s], i = 0; i < 24; i++)a[i / 6 | 0] |= e[(h[i] - 1 + f) % 28] << 31 - i % 6, a[4 + (i / 6 | 0)] |= e[28 + (h[i + 24] - 1 + f) % 28] << 31 - i % 6; a[0] = a[0] << 1 | a[0] >>> 31; for (var i = 1; i < 7; i++)a[i] = a[i] >>> 4 * (i - 1) + 3; a[7] = a[7] << 5 | a[7] >>> 27 } for (var u = this._invSubKeys = [], i = 0; i < 16; i++)u[i] = o[15 - i] }, encryptBlock: function (t, r) { this._doCryptBlock(t, r, this._subKeys) }, decryptBlock: function (t, r) { this._doCryptBlock(t, r, this._invSubKeys) }, _doCryptBlock: function (t, i, n) { this._lBlock = t[i], this._rBlock = t[i + 1], r.call(this, 4, 252645135), r.call(this, 16, 65535), e.call(this, 2, 858993459), e.call(this, 8, 16711935), r.call(this, 1, 1431655765); for (var o = 0; o < 16; o++) { for (var s = n[o], a = this._lBlock, c = this._rBlock, h = 0, l = 0; l < 8; l++)h |= f[l][((c ^ s[l]) & u[l]) >>> 0]; this._lBlock = c, this._rBlock = a ^ h } var d = this._lBlock; this._lBlock = this._rBlock, this._rBlock = d, r.call(this, 1, 1431655765), e.call(this, 8, 16711935), e.call(this, 2, 858993459), r.call(this, 16, 65535), r.call(this, 4, 252645135), t[i] = this._lBlock, t[i + 1] = this._rBlock }, keySize: 2, ivSize: 2, blockSize: 2 }); i.DES = s._createHelper(d); var v = a.TripleDES = s.extend({ _doReset: function () { var t = this._key, r = t.words; this._des1 = d.createEncryptor(o.create(r.slice(0, 2))), this._des2 = d.createEncryptor(o.create(r.slice(2, 4))), this._des3 = d.createEncryptor(o.create(r.slice(4, 6))) }, encryptBlock: function (t, r) { this._des1.encryptBlock(t, r), this._des2.decryptBlock(t, r), this._des3.encryptBlock(t, r) }, decryptBlock: function (t, r) { this._des3.decryptBlock(t, r), this._des2.encryptBlock(t, r), this._des1.decryptBlock(t, r) }, keySize: 6, ivSize: 2, blockSize: 2 }); i.TripleDES = s._createHelper(v) + }(), function () { function r() { for (var t = this._S, r = this._i, e = this._j, i = 0, n = 0; n < 4; n++) { r = (r + 1) % 256, e = (e + t[r]) % 256; var o = t[r]; t[r] = t[e], t[e] = o, i |= t[(t[r] + t[e]) % 256] << 24 - 8 * n } return this._i = r, this._j = e, i } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = o.RC4 = n.extend({ _doReset: function () { for (var t = this._key, r = t.words, e = t.sigBytes, i = this._S = [], n = 0; n < 256; n++)i[n] = n; for (var n = 0, o = 0; n < 256; n++) { var s = n % e, a = r[s >>> 2] >>> 24 - s % 4 * 8 & 255; o = (o + i[n] + a) % 256; var c = i[n]; i[n] = i[o], i[o] = c } this._i = this._j = 0 }, _doProcessBlock: function (t, e) { t[e] ^= r.call(this) }, keySize: 8, ivSize: 0 }); e.RC4 = n._createHelper(s); var a = o.RC4Drop = s.extend({ cfg: s.cfg.extend({ drop: 192 }), _doReset: function () { s._doReset.call(this); for (var t = this.cfg.drop; t > 0; t--)r.call(this) } }); e.RC4Drop = n._createHelper(a) }(), t.mode.CTRGladman = function () { function r(t) { if (255 === (t >> 24 & 255)) { var r = t >> 16 & 255, e = t >> 8 & 255, i = 255 & t; 255 === r ? (r = 0, 255 === e ? (e = 0, 255 === i ? i = 0 : ++i) : ++e) : ++r, t = 0, t += r << 16, t += e << 8, t += i } else t += 1 << 24; return t } function e(t) { return 0 === (t[0] = r(t[0])) && (t[1] = r(t[1])), t } var i = t.lib.BlockCipherMode.extend(), n = i.Encryptor = i.extend({ processBlock: function (t, r) { var i = this._cipher, n = i.blockSize, o = this._iv, s = this._counter; o && (s = this._counter = o.slice(0), this._iv = void 0), e(s); var a = s.slice(0); i.encryptBlock(a, 0); for (var c = 0; c < n; c++)t[r + c] ^= a[c] } }); return i.Decryptor = n, i }(), function () { function r() { for (var t = this._X, r = this._C, e = 0; e < 8; e++)a[e] = r[e]; r[0] = r[0] + 1295307597 + this._b | 0, r[1] = r[1] + 3545052371 + (r[0] >>> 0 < a[0] >>> 0 ? 1 : 0) | 0, r[2] = r[2] + 886263092 + (r[1] >>> 0 < a[1] >>> 0 ? 1 : 0) | 0, r[3] = r[3] + 1295307597 + (r[2] >>> 0 < a[2] >>> 0 ? 1 : 0) | 0, r[4] = r[4] + 3545052371 + (r[3] >>> 0 < a[3] >>> 0 ? 1 : 0) | 0, r[5] = r[5] + 886263092 + (r[4] >>> 0 < a[4] >>> 0 ? 1 : 0) | 0, r[6] = r[6] + 1295307597 + (r[5] >>> 0 < a[5] >>> 0 ? 1 : 0) | 0, r[7] = r[7] + 3545052371 + (r[6] >>> 0 < a[6] >>> 0 ? 1 : 0) | 0, this._b = r[7] >>> 0 < a[7] >>> 0 ? 1 : 0; for (var e = 0; e < 8; e++) { var i = t[e] + r[e], n = 65535 & i, o = i >>> 16, s = ((n * n >>> 17) + n * o >>> 15) + o * o, h = ((4294901760 & i) * i | 0) + ((65535 & i) * i | 0); c[e] = s ^ h } t[0] = c[0] + (c[7] << 16 | c[7] >>> 16) + (c[6] << 16 | c[6] >>> 16) | 0, t[1] = c[1] + (c[0] << 8 | c[0] >>> 24) + c[7] | 0, t[2] = c[2] + (c[1] << 16 | c[1] >>> 16) + (c[0] << 16 | c[0] >>> 16) | 0, t[3] = c[3] + (c[2] << 8 | c[2] >>> 24) + c[1] | 0, t[4] = c[4] + (c[3] << 16 | c[3] >>> 16) + (c[2] << 16 | c[2] >>> 16) | 0, t[5] = c[5] + (c[4] << 8 | c[4] >>> 24) + c[3] | 0, t[6] = c[6] + (c[5] << 16 | c[5] >>> 16) + (c[4] << 16 | c[4] >>> 16) | 0, t[7] = c[7] + (c[6] << 8 | c[6] >>> 24) + c[5] | 0 } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = [], a = [], c = [], h = o.Rabbit = n.extend({ _doReset: function () { for (var t = this._key.words, e = this.cfg.iv, i = 0; i < 4; i++)t[i] = 16711935 & (t[i] << 8 | t[i] >>> 24) | 4278255360 & (t[i] << 24 | t[i] >>> 8); var n = this._X = [t[0], t[3] << 16 | t[2] >>> 16, t[1], t[0] << 16 | t[3] >>> 16, t[2], t[1] << 16 | t[0] >>> 16, t[3], t[2] << 16 | t[1] >>> 16], o = this._C = [t[2] << 16 | t[2] >>> 16, 4294901760 & t[0] | 65535 & t[1], t[3] << 16 | t[3] >>> 16, 4294901760 & t[1] | 65535 & t[2], t[0] << 16 | t[0] >>> 16, 4294901760 & t[2] | 65535 & t[3], t[1] << 16 | t[1] >>> 16, 4294901760 & t[3] | 65535 & t[0]]; this._b = 0; for (var i = 0; i < 4; i++)r.call(this); for (var i = 0; i < 8; i++)o[i] ^= n[i + 4 & 7]; if (e) { var s = e.words, a = s[0], c = s[1], h = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8), l = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8), f = h >>> 16 | 4294901760 & l, u = l << 16 | 65535 & h; o[0] ^= h, o[1] ^= f, o[2] ^= l, o[3] ^= u, o[4] ^= h, o[5] ^= f, o[6] ^= l, o[7] ^= u; for (var i = 0; i < 4; i++)r.call(this) } }, _doProcessBlock: function (t, e) { var i = this._X; r.call(this), s[0] = i[0] ^ i[5] >>> 16 ^ i[3] << 16, s[1] = i[2] ^ i[7] >>> 16 ^ i[5] << 16, s[2] = i[4] ^ i[1] >>> 16 ^ i[7] << 16, s[3] = i[6] ^ i[3] >>> 16 ^ i[1] << 16; for (var n = 0; n < 4; n++)s[n] = 16711935 & (s[n] << 8 | s[n] >>> 24) | 4278255360 & (s[n] << 24 | s[n] >>> 8), t[e + n] ^= s[n] }, blockSize: 4, ivSize: 2 }); e.Rabbit = n._createHelper(h) }(), t.mode.CTR = function () { var r = t.lib.BlockCipherMode.extend(), e = r.Encryptor = r.extend({ processBlock: function (t, r) { var e = this._cipher, i = e.blockSize, n = this._iv, o = this._counter; n && (o = this._counter = n.slice(0), this._iv = void 0); var s = o.slice(0); e.encryptBlock(s, 0), o[i - 1] = o[i - 1] + 1 | 0; for (var a = 0; a < i; a++)t[r + a] ^= s[a] } }); return r.Decryptor = e, r }(), function () { function r() { for (var t = this._X, r = this._C, e = 0; e < 8; e++)a[e] = r[e]; r[0] = r[0] + 1295307597 + this._b | 0, r[1] = r[1] + 3545052371 + (r[0] >>> 0 < a[0] >>> 0 ? 1 : 0) | 0, r[2] = r[2] + 886263092 + (r[1] >>> 0 < a[1] >>> 0 ? 1 : 0) | 0, r[3] = r[3] + 1295307597 + (r[2] >>> 0 < a[2] >>> 0 ? 1 : 0) | 0, r[4] = r[4] + 3545052371 + (r[3] >>> 0 < a[3] >>> 0 ? 1 : 0) | 0, r[5] = r[5] + 886263092 + (r[4] >>> 0 < a[4] >>> 0 ? 1 : 0) | 0, r[6] = r[6] + 1295307597 + (r[5] >>> 0 < a[5] >>> 0 ? 1 : 0) | 0, r[7] = r[7] + 3545052371 + (r[6] >>> 0 < a[6] >>> 0 ? 1 : 0) | 0, this._b = r[7] >>> 0 < a[7] >>> 0 ? 1 : 0; for (var e = 0; e < 8; e++) { var i = t[e] + r[e], n = 65535 & i, o = i >>> 16, s = ((n * n >>> 17) + n * o >>> 15) + o * o, h = ((4294901760 & i) * i | 0) + ((65535 & i) * i | 0); c[e] = s ^ h } t[0] = c[0] + (c[7] << 16 | c[7] >>> 16) + (c[6] << 16 | c[6] >>> 16) | 0, t[1] = c[1] + (c[0] << 8 | c[0] >>> 24) + c[7] | 0, t[2] = c[2] + (c[1] << 16 | c[1] >>> 16) + (c[0] << 16 | c[0] >>> 16) | 0, t[3] = c[3] + (c[2] << 8 | c[2] >>> 24) + c[1] | 0, t[4] = c[4] + (c[3] << 16 | c[3] >>> 16) + (c[2] << 16 | c[2] >>> 16) | 0, t[5] = c[5] + (c[4] << 8 | c[4] >>> 24) + c[3] | 0, t[6] = c[6] + (c[5] << 16 | c[5] >>> 16) + (c[4] << 16 | c[4] >>> 16) | 0, t[7] = c[7] + (c[6] << 8 | c[6] >>> 24) + c[5] | 0 } var e = t, i = e.lib, n = i.StreamCipher, o = e.algo, s = [], a = [], c = [], h = o.RabbitLegacy = n.extend({ _doReset: function () { var t = this._key.words, e = this.cfg.iv, i = this._X = [t[0], t[3] << 16 | t[2] >>> 16, t[1], t[0] << 16 | t[3] >>> 16, t[2], t[1] << 16 | t[0] >>> 16, t[3], t[2] << 16 | t[1] >>> 16], n = this._C = [t[2] << 16 | t[2] >>> 16, 4294901760 & t[0] | 65535 & t[1], t[3] << 16 | t[3] >>> 16, 4294901760 & t[1] | 65535 & t[2], t[0] << 16 | t[0] >>> 16, 4294901760 & t[2] | 65535 & t[3], t[1] << 16 | t[1] >>> 16, 4294901760 & t[3] | 65535 & t[0]]; this._b = 0; for (var o = 0; o < 4; o++)r.call(this); for (var o = 0; o < 8; o++)n[o] ^= i[o + 4 & 7]; if (e) { var s = e.words, a = s[0], c = s[1], h = 16711935 & (a << 8 | a >>> 24) | 4278255360 & (a << 24 | a >>> 8), l = 16711935 & (c << 8 | c >>> 24) | 4278255360 & (c << 24 | c >>> 8), f = h >>> 16 | 4294901760 & l, u = l << 16 | 65535 & h; n[0] ^= h, n[1] ^= f, n[2] ^= l, n[3] ^= u, n[4] ^= h, n[5] ^= f, n[6] ^= l, n[7] ^= u; for (var o = 0; o < 4; o++)r.call(this) } }, _doProcessBlock: function (t, e) { var i = this._X; r.call(this), s[0] = i[0] ^ i[5] >>> 16 ^ i[3] << 16, s[1] = i[2] ^ i[7] >>> 16 ^ i[5] << 16, s[2] = i[4] ^ i[1] >>> 16 ^ i[7] << 16, s[3] = i[6] ^ i[3] >>> 16 ^ i[1] << 16; for (var n = 0; n < 4; n++)s[n] = 16711935 & (s[n] << 8 | s[n] >>> 24) | 4278255360 & (s[n] << 24 | s[n] >>> 8), t[e + n] ^= s[n] }, blockSize: 4, ivSize: 2 }); e.RabbitLegacy = n._createHelper(h) }(), t.pad.ZeroPadding = { pad: function (t, r) { var e = 4 * r; t.clamp(), t.sigBytes += e - (t.sigBytes % e || e) }, unpad: function (t) { for (var r = t.words, e = t.sigBytes - 1; !(r[e >>> 2] >>> 24 - e % 4 * 8 & 255);)e--; t.sigBytes = e + 1 } }, t +}); + +const $ = new Env('什么值得买') +$.VAL_cookies = $.getdata('chavy_cookie_smzdm') + +!(async () => { + $.CryptoJS = $.isNode() ? require('crypto-js') : CryptoJS + + await signweb() + await $.wait(4000) + await signapp() + await showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +function signweb() { + return new Promise((resove) => { + const url = { url: 'https://zhiyou.smzdm.com/user/checkin/jsonp_checkin', headers: {} } + url.headers['Cookie'] = $.VAL_cookies + url.headers['Referer'] = 'http://www.smzdm.com/' + url.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36' + $.get(url, (err, resp, data) => { + try { + $.web = JSON.parse(data) + } catch (e) { + $.logErr(e, resp) + } finally { + resove() + } + }) + }) +} + +function signapp() { + const body = getBody() + return new Promise((resove) => { + const url = { + url: 'https://user-api.smzdm.com/checkin', + body, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Cookie': $.VAL_cookies + } } - // 登录失效 - else if (result && result.data && result.error_code == 99) { - let subTitle = `签到结果: 失败` - let detail = `说明: 登录失效, 请重新获取Cookie` - $notification.post(title, subTitle, detail) + $.post(url, (err, resp, data) => { + try { + $.app = JSON.parse(data) + } catch (e) { + $.logErr(e, resp) + } finally { + resove() + } + }) + }) +} + +function getToken() { + const [, token] = $.VAL_cookies.match(/sess=(.*?);/) + return token +} + +function getAppSign(t) { + const sign = 'f=android&sk=1&time=' + t + '&token=' + getToken() + '&v=10.0&weixin=0&key=apr1$AwP!wRRT$gJ/q.X24poeBInlUJC' + return $.CryptoJS.MD5(sign).toString().toUpperCase() +} + +function getBody() { + const t = new Date().getTime() + const token = getToken() + const sign = getAppSign(t) + return 'touchstone_event=&v=10.0&sign=' + sign + '&weixin=0&time=' + t + '&sk=1&token=' + token + '&f=android&captcha=' +} + +function showmsg() { + return new Promise((resolve) => { + $.subt = '' + $.desc = [] + $.subt = $.web.error_code === 0 ? 'PC: 成功' : $.web.error_code === 99 ? 'PC: 未登录' : 'PC: 失败' + if ($.web.error_code === 0 && $.web.data) { + $.desc.push(`累计: ${$.web.data.checkin_num}次, 经验: ${$.web.data.exp}, 金币: ${$.web.data.gold}, 积分: ${$.web.data.point}`) } - // 签到失败 - else { - let subTitle = `签到结果: 失败` - let detail = `编码: ${result.error_code}, 说明: ${result.error_msg}` - $notification.post(title, subTitle, detail) + if ($.app) { + $.subt += $.app.error_code === '0' ? ', APP: 成功' : ', APP: 失败' + $.desc.push($.app.error_msg) } - console.log(`${cookieName}, data: ${data}`) + $.msg($.name, $.subt, $.desc.join('\n')) + resolve() }) - - $done({}) } -sign() +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/suning/README.md b/suning/README.md new file mode 100644 index 000000000..3599a6b14 --- /dev/null +++ b/suning/README.md @@ -0,0 +1,112 @@ +# 苏宁易购 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> 有一定动手及排查问题能力的同学先上车 + +> 2020.3.15 增加天天低价, 注意更新`mitm`和`rewrite`并进入天天低价获取两次 Cookie + +> 2020.3.16 修复部分机型的`天天红包`就算 Cookie 获取成功也会签到失败问题 + +> 2020.5.7 修复部分场景下报`d.obj.couponRuleName`问题 + +## 配置 (Surge) + +```properties +[MITM] +hostname = passport.suning.com, luckman.suning.com, sign.suning.com, gameapi.suning.com + +[Script] +# 注意有4条获取 Cookie 脚本 +http-request ^https:\/\/passport.suning.com\/ids\/login$ script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js, requires-body=true +http-request ^https:\/\/luckman.suning.com\/luck-web\/sign\/api\/clock_sign.do script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js +http-request ^https:\/\/sign.suning.com\/sign-web\/m\/promotion\/sign\/doSign.do script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js +http-request ^https:\/\/gameapi.suning.com\/sngame-web\/(api\/signin\/private\/customerSignOperation.do|gateway\/api\/queryPrize.do) script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +hostname = passport.suning.com, luckman.suning.com, sign.suning.com, gameapi.suning.com + +[rewrite_local] +# 注意有4条获取 Cookie 脚本 +^https:\/\/passport.suning.com\/ids\/login$ url script-request-body suning.cookie.js +^https:\/\/luckman.suning.com\/luck-web\/sign\/api\/clock_sign.do url script-request-header suning.cookie.js +^https:\/\/sign.suning.com\/sign-web\/m\/promotion\/sign\/doSign.do url script-request-header suning.cookie.js +^https:\/\/gameapi.suning.com\/sngame-web\/(api\/signin\/private\/customerSignOperation.do|gateway\/api\/queryPrize.do) url script-request-header suning.cookie.js + +[task_local] +1 0 * * * suning.js +``` + +## 说明 + +1. 先把`passport.suning.com, luckman.suning.com, sign.suning.com, gameapi.suning.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`suning.cookie.js`和`suning.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 获取 Cookie: + - 【必要】打开 APP, 系统提示: `获取Cookie: 成功 (登录链接)` + - 【可选】进入 `主页` > `签到有礼`, 系统提示: `获取Cookie: 成功 (每日签到)` + - 【可选】进入 `主页` > `领取红包`, 系统提示: `获取Cookie: 成功 (每日红包)` (如果找不到领取红包,尝试卸载苏宁重新安装) 兼容之前 @barrymchen 写的 snyg.js 如果之前有用这个脚本获取过 Cookie 那不用重新取 + - 【可选】进入 `主页` > `天天低价` > `点右上角宝箱`, 系统提示: `获取Cookie: 成功 (天天低价)`、`获取Cookie: 成功 (查询天天低价)` +4. 把获取 Cookie 的脚本注释或删掉 + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +@makexp diff --git a/suning/suning.cookie.js b/suning/suning.cookie.js new file mode 100644 index 000000000..55fcbe4fd --- /dev/null +++ b/suning/suning.cookie.js @@ -0,0 +1,103 @@ +const chavy = init() +const cookieName = '苏宁易购' +const KEY_loginurl = 'chavy_login_url_suning' +const KEY_loginbody = 'chavy_login_body_suning' +const KEY_loginheader = 'chavy_login_header_suning' +const KEY_signurl = 'chavy_sign_url_suning' +const KEY_signheader = 'chavy_sign_header_suning' +const KEY_signweburl = 'chavy_signweb_url_suning' +const KEY_signwebheader = 'chavy_signweb_header_suning' +const KEY_signgameurl = 'chavy_signgame_url_suning' +const KEY_signgameheader = 'chavy_signgame_header_suning' +const KEY_signgetgameurl = 'chavy_signgetgame_url_suning' +const KEY_signgetgameheader = 'chavy_signgetgame_header_suning' + +if ($request.url.match(/\/ids\/login/)) { + const VAL_loginurl = $request.url + const VAL_loginbody = $request.body + const VAL_loginheader = JSON.stringify($request.headers) + if (VAL_loginurl) chavy.setdata(VAL_loginurl, KEY_loginurl) + if (VAL_loginbody) chavy.setdata(VAL_loginbody, KEY_loginbody) + if (VAL_loginheader) chavy.setdata(VAL_loginheader, KEY_loginheader) + chavy.msg(`${cookieName}`, '获取Cookie: 成功 (登录链接)', '') + chavy.log(`❕ ${cookieName} 获取Cookie: 成功, VAL_loginurl: ${VAL_loginurl}`) + chavy.log(`❕ ${cookieName} 获取Cookie: 成功, VAL_loginbody: ${VAL_loginbody}`) + chavy.log(`❕ ${cookieName} 获取Cookie: 成功, VAL_loginheader: ${VAL_loginheader}`) +} else if ($request.url.match(/\/sign\/doSign.do/)) { + const VAL_signurl = $request.url + const VAL_signheader = JSON.stringify($request.headers) + if (VAL_signurl) chavy.setdata(VAL_signurl, KEY_signurl) + if (VAL_signheader) chavy.setdata(VAL_signheader, KEY_signheader) + chavy.msg(`${cookieName}`, '获取Cookie: 成功 (每日签到)', '') + chavy.log(`❕ ${cookieName} 获取Cookie: 成功, VAL_signurl: ${VAL_signurl}`) + chavy.log(`❕ ${cookieName} 获取Cookie: 成功, VAL_signheader: ${VAL_signheader}`) +} else if ($request.url.match(/\/api\/clock_sign.do/)) { + const VAL_signweburl = $request.url + const VAL_signwebheader = JSON.stringify($request.headers) + if (VAL_signweburl) chavy.setdata(VAL_signweburl, KEY_signweburl) + if (VAL_signwebheader) chavy.setdata(VAL_signwebheader, KEY_signwebheader) + chavy.msg(`${cookieName}`, '获取Cookie: 成功 (每日红包)', '') + chavy.log(`❕ ${cookieName} 获取Cookie: 成功, VAL_signweburl: ${VAL_signweburl}`) + chavy.log(`❕ ${cookieName} 获取Cookie: 成功, VAL_signwebheader: ${VAL_signwebheader}`) +} else if ($request.url.match(/customerSignOperation.do/)) { + const VAL_signgameurl = $request.url + const VAL_signgameheader = JSON.stringify($request.headers) + if (VAL_signgameurl) chavy.setdata(VAL_signgameurl, KEY_signgameurl) + if (VAL_signgameheader) chavy.setdata(VAL_signgameheader, KEY_signgameheader) + chavy.msg(`${cookieName}`, '获取Cookie: 成功 (天天低价)', '') + chavy.log(`❕ ${cookieName} 获取Cookie: 成功, VAL_signgameurl: ${VAL_signgameurl}`) + chavy.log(`❕ ${cookieName} 获取Cookie: 成功, VAL_signgameheader: ${VAL_signgameheader}`) +} else if ($request.url.match(/queryPrize.do/)) { + const VAL_signgetgameurl = $request.url + const VAL_signgetgameheader = JSON.stringify($request.headers) + if (VAL_signgetgameurl) chavy.setdata(VAL_signgetgameurl, KEY_signgetgameurl) + if (VAL_signgetgameheader) chavy.setdata(VAL_signgetgameheader, KEY_signgetgameheader) + chavy.msg(`${cookieName}`, '获取Cookie: 成功 (查询天天低价)', '') + chavy.log(`❕ ${cookieName} 获取Cookie: 成功, VAL_signgetgameurl: ${VAL_signgetgameurl}`) + chavy.log(`❕ ${cookieName} 获取Cookie: 成功, VAL_signgetgameheader: ${VAL_signgetgameheader}`) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} +chavy.done() diff --git a/suning/suning.js b/suning/suning.js new file mode 100644 index 000000000..bfe6ec350 --- /dev/null +++ b/suning/suning.js @@ -0,0 +1,324 @@ +const chavy = init() +const cookieName = '苏宁易购' +const KEY_loginurl = 'chavy_login_url_suning' +const KEY_loginbody = 'chavy_login_body_suning' +const KEY_loginheader = 'chavy_login_header_suning' +const KEY_signurl = 'chavy_sign_url_suning' +const KEY_signheader = 'chavy_sign_header_suning' +const KEY_signweburl = 'chavy_signweb_url_suning' +const KEY_signweburlBarry = 'snyg_userTokenKey' +const KEY_signwebheader = 'chavy_signweb_header_suning' +const KEY_signgameurl = 'chavy_signgame_url_suning' +const KEY_signgameheader = 'chavy_signgame_header_suning' +const KEY_signgetgameurl = 'chavy_signgetgame_url_suning' +const KEY_signgetgameheader = 'chavy_signgetgame_header_suning' +const KEY_runflag = 'chavy_runflag_suning' +const KEY_logflag = 'chavy_logflag_suning' + +const signinfo = {} +let VAL_loginurl = chavy.getdata(KEY_loginurl) +let VAL_loginbody = chavy.getdata(KEY_loginbody) +let VAL_loginheader = chavy.getdata(KEY_loginheader) +let VAL_signurl = chavy.getdata(KEY_signurl) +let VAL_signheader = chavy.getdata(KEY_signheader) +let VAL_signweburl = chavy.getdata(KEY_signweburl) +let VAL_signweburlBarry = chavy.getdata(KEY_signweburlBarry) +let VAL_signwebheader = chavy.getdata(KEY_signwebheader) +let VAL_signgameurl = chavy.getdata(KEY_signgameurl) +let VAL_signgameheader = chavy.getdata(KEY_signgameheader) +let VAL_signgetgameurl = chavy.getdata(KEY_signgetgameurl) +let VAL_signgetgameheader = chavy.getdata(KEY_signgetgameheader) +let VAL_runflag = chavy.getdata(KEY_runflag) +let VAl_logflag = chavy.getdata(KEY_logflag) === "true" ? true : false + +;(sign = async () => { + chavy.log(`🔔 ${cookieName} 开始`) + await loginapp() + //if (VAL_signurl) await signapp() + await getinfo() + if (VAL_signweburl || VAL_signweburlBarry) await signweb(), await getwebinfo() + if (VAL_signgameurl && VAL_signgetgameurl) await signgame(), await getgameinfo() + showmsg() + chavy.log(`🔔 ${cookieName} 结束`) +})() +.catch((e) => chavy.log(`❌ ${cookieName} 签到失败: ${e}`)) +.finally(() => chavy.done()) + +function loginapp() { + return new Promise((resolve, reject) => { + const url = { url: VAL_loginurl, body: VAL_loginbody, headers: JSON.parse(VAL_loginheader) } + // chavy.log(`❕ ${cookieName} loginapp - VAL_runflag: ${VAL_runflag}`) + // if (VAL_runflag) delete url.headers['Cookie'] + // else chavy.setdata('true', KEY_runflag) + chavy.post(url, (error, response, data) => { + resolve() + }) + }) +} +/* +function signapp() { + return new Promise((resolve, reject) => { + const url = { url: VAL_signurl, headers: JSON.parse(VAL_signheader) } + delete url.headers['Cookie'] + chavy.get(url, (error, response, data) => { + try { + chavy.log(`❕ ${cookieName} signapp - response: ${JSON.stringify(response)}`) + signinfo.signapp = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `签到结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} signapp - 签到失败: ${e}`) + chavy.log(`❌ ${cookieName} signapp - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +}*/ + +function signgame() { + return new Promise((resolve, reject) => { + const url = { url: VAL_signgameurl, headers: JSON.parse(VAL_signgameheader) } + delete url.headers['Cookie'] + chavy.get(url, (error, response, data) => { + try { + VAl_logflag ? chavy.log(`❕ ${cookieName} signgame - response: ${JSON.stringify(response)}`) : "" + signinfo.signgame = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `天天低价: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} signgame - 签到失败: ${e}`) + chavy.log(`❌ ${cookieName} signgame - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function signweb() { + return new Promise((resolve, reject) => { + let url = null + if (VAL_signweburl) { + url = { url: VAL_signweburl, headers: JSON.parse(VAL_signwebheader) } + delete url.headers['Cookie'] + url.headers['Host'] = 'luckman.suning.com' + url.headers['Referer'] = 'https: //luckman.suning.com/luck-web/sign/app/index_sign.htm?wx_navbar_transparent=true' + url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SNEBUY-APP 8.5.0 SNCLIENT-WAP' + } else if (VAL_signweburlBarry) { + url = { url: VAL_signweburlBarry, headers: {} } + url.headers['Cookie'] = chavy.getdata('snyg_userCookieKey') + url.headers['Accept'] = 'application/json' + url.headers['Accept-Encoding'] = 'gzip, deflate, br' + url.headers['Connection'] = 'keep-alive' + url.headers['Referer'] = 'https://luckman.suning.com/luck-web/sign/app/index_sign.htm?wx_navbar_transparent=true' + url.headers['Host'] = 'luckman.suning.com' + url.headers['User-Agent'] = chavy.getdata('snyg_userAgentKey') + url.headers['Accept-Language'] = 'en-us' + url.headers['X-Requested-With'] = 'XMLHttpRequest' + } + chavy.get(url, (error, response, data) => { + try { + VAl_logflag ? chavy.log(`❕ ${cookieName} signweb - response: ${JSON.stringify(response)}`) : "" + signinfo.signweb = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `每日红包: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} signweb - 每日红包失败: ${e}`) + chavy.log(`❌ ${cookieName} signweb - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function getwebinfo() { + return new Promise((resolve, reject) => { + const timestamp = Math.round(new Date().getTime()).toString() + const VAL_webinfourl = `https://luckman.suning.com/luck-web/sign/api/query/detail/record_sign.do?terminal=app&channel=sign&_=${timestamp}` + const url = { url: VAL_webinfourl, headers: JSON.parse(VAL_signheader) } + delete url.headers['Cookie'] + url.headers['Host'] = 'luckman.suning.com' + chavy.get(url, (error, response, data) => { + try { + VAl_logflag ? chavy.log(`❕ ${cookieName} getwebinfo - response: ${JSON.stringify(response)}`) : "" + signinfo.webinfo = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `领红包结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} getwebinfo - 领红包失败: ${e}`) + chavy.log(`❌ ${cookieName} getwebinfo - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function getgameinfo() { + return new Promise((resolve, reject) => { + const url = { url: VAL_signgetgameurl, headers: JSON.parse(VAL_signgetgameheader) } + delete url.headers['Cookie'] + chavy.get(url, (error, response, data) => { + try { + VAl_logflag ? chavy.log(`❕ ${cookieName} getgameinfo - response: ${JSON.stringify(response)}`) : "" + signinfo.gameinfo = JSON.parse(data.match(/\((.*)\)/)[1]) + resolve() + } catch (e) { + chavy.msg(cookieName, `查询天天低价: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} getgameinfo - 查询天天低价失败: ${e}`) + chavy.log(`❌ ${cookieName} getgameinfo - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function getinfo() { + return new Promise((resolve, reject) => { + const timestamp = Math.round(new Date().getTime()).toString() + const url = { url: `https://sign.suning.com/sign-web/m/promotion/sign/receiveSignDrip.do?_=${timestamp}`, headers: JSON.parse(VAL_signheader) } + delete url.headers['Cookie'] + chavy.get(url, (error, response, data) => { + try { + VAl_logflag ? chavy.log(`❕ ${cookieName} getinfo - info: ${JSON.stringify(response)}`) : "" + signinfo.info = JSON.parse(data) + resolve() + } catch (e) { + chavy.msg(cookieName, `获取签到信息: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} getinfo - 获取签到信息失败: ${e}`) + chavy.log(`❌ ${cookieName} getinfo - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function showmsg() { + let subTitle = '' + let detail = '' + let moreDetail = '' + if (signinfo.info && signinfo.info.code == '1') { + if (signinfo.info.data.todayFirstSignFlag == true) subTitle = '签到: 成功' + else subTitle = '签到: 重复' + //for (myinfo of signinfo.info.data) { + // detail += detail == '' ? '总共: ' : ', ' + // detail += myinfo.showLabel + //} + if (signinfo.info.data.prizeLists) { + detail += typeof(signinfo.info.data.remainingPoint) == "undefined" ? '' : `, 说明: 还有${signinfo.info.data.remainingPoint}云钻待领取` + const prizeLists = signinfo.info.data.prizeLists + const customerDays = signinfo.info.data.customerDays + const prize = prizeLists[customerDays - 1] + moreDetail += moreDetail == '' ? '' : '\n' + moreDetail += '\n💎 每日签到: ' + for (res of prize) moreDetail += `\n${res.prizeName}: ${res.prizeContent}` + } + } else { + subTitle = '签到: 失败' + chavy.log(`❌ ${cookieName} showmsg - 每日签到: ${JSON.stringify(signinfo.info)}`) + } + + subTitle += subTitle == '' ? '' : ', ' + if (signinfo.signweb) { + if (signinfo.signweb.respCode == '1') { + subTitle += '红包: 成功' + } else if (signinfo.signweb.respCode == '70512') { + subTitle += '红包: 重复' + } else { + subTitle += '红包: 失败' + chavy.log(`❌ ${cookieName} showmsg - 每日红包 - signweb: ${JSON.stringify(signinfo.signweb)}`) + } + } else { + subTitle += '红包: 失败' + chavy.log(`❌ ${cookieName} showmsg - 每日红包 - signweb: ${JSON.stringify(signinfo.signweb)}`) + } + + subTitle += subTitle == '' ? '' : ', ' + if (signinfo.signgame && signinfo.signgame.code == '1') { + if (signinfo.signgame.data.resultCode == 'SG0000') { + subTitle += '低价: 成功' + } else if (signinfo.signgame.data.resultCode == 'SG0103') { + subTitle += '低价: 重复' + } else { + subTitle += '低价: 失败' + chavy.log(`❌ ${cookieName} showmsg - 每日红包 - signgame: ${JSON.stringify(signinfo.signgame)}`) + } + } else { + subTitle += '低价: 失败' + chavy.log(`❌ ${cookieName} showmsg - 每日红包 - signgame: ${JSON.stringify(signinfo.signgame)}`) + } + + if (signinfo.webinfo && signinfo.webinfo.respData) { + const currentIndex = signinfo.webinfo.respData.currentIndex + const detailTreeMap = signinfo.webinfo.respData.detailTreeMap + const currentMap = detailTreeMap[currentIndex] + if (currentMap.signMark == true) { + moreDetail += moreDetail == '' ? '' : '\n' + moreDetail += '\n🧧 每日红包: ' + for (res of currentMap.resList) moreDetail += `\n${res.remark}: ${res.amount}` + } else { + chavy.log(`❌ ${cookieName} showmsg - 每日红包 - webinfo: ${JSON.stringify(signinfo.webinfo)}`) + } + } else { + chavy.log(`❌ ${cookieName} showmsg - 每日红包 - webinfo: ${JSON.stringify(signinfo.webinfo)}`) + } + + if (signinfo.signgame && signinfo.gameinfo && signinfo.gameinfo.code == 1) { + if (signinfo.gameinfo.data.resultCode == 0000) { + moreDetail += moreDetail == '' ? '' : '\n' + moreDetail += '\n💰 天天低价: ' + for (d of signinfo.gameinfo.data.result.datas) + if (d.obj) moreDetail += d.obj.couponStatus === "2" ? `\n${d.obj.couponRuleName} (${d.obj.remainValue}元)\n过期时间:${d.obj.endTime}` : '' + } else { + chavy.log(`❌ ${cookieName} showmsg - 天天低价 - gameinfo: ${JSON.stringify(signinfo.gameinfo)}`) + } + } else { + chavy.log(`❌ ${cookieName} showmsg - 天天低价 - gameinfo: ${JSON.stringify(signinfo.gameinfo)}`) + } + + if (moreDetail) detail += `\n查看签到详情\n${moreDetail}` + chavy.msg(cookieName, subTitle, detail) + chavy.log(detail) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/surge.cookies.sgmodule b/surge.cookies.sgmodule new file mode 100644 index 000000000..abdc5f3e7 --- /dev/null +++ b/surge.cookies.sgmodule @@ -0,0 +1,51 @@ +#!name=Chavy iOS Cookies Module +#!desc=iOS Cookies 模块配置 +#!system=ios + +[Script] +Rewrite: 10010 = type=http-request,pattern=^https:\/\/act.10010.com\/SigninApp(.*?)\/signin\/daySign,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js +Rewrite: 10010 = type=http-request,pattern=^https:\/\/act.10010.com\/SigninApp\/signin\/querySigninActivity.htm,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js +Rewrite: 10010 = type=http-request,pattern=^https:\/\/m.client.10010.com\/dailylottery\/static\/(textdl\/userLogin|active\/findActivityInfo),script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.cookie.js +Rewrite: AcFun = type=http-request,pattern=^https:\/\/api\-new\.app\.acfun\.cn\/rest\/app\/user\/personalInfo,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/acfun/acfun.cookie.js +Rewrite: ApkTw = type=http-request,pattern=^https://apk.tw\/member.php(.*?)action=login,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/apktw/apktw.cookie.js,requires-body=true +Rewrite: BiliBili = type=http-request,pattern=^https:\/\/(www|live)\.bilibili\.com\/?.?,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.cookie.js +Rewrite: CSDN = type=http-request,pattern=^https:\/\/gw.csdn.net\/mini-app\/v2\/lucky_draw\/login\/sign_in\?,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.cookie.js +Rewrite: CSDN = type=http-request,pattern=^https:\/\/passport.csdn.net\/v2\/api\/app\/login\/checkAndRefreshToken,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/csdn/csdn.cookie.js +Rewrite: V2EX = type=http-request,pattern=^https:\/\/www\.v2ex\.com\/mission\/daily,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/v2ex/v2ex.cookie.js +Rewrite: WPS = type=http-request,pattern=^https:\/\/zt.wps.cn\/2018\/docer_check_in\/api\/act_list,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wps/wps.cookie.js +Rewrite: 懂球帝 = type=http-request,pattern=^https:\/\/api\.dongqiudi\.com\/v2\/user\/is_login,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/dongqiudi/dongqiudi.cookie.js +Rewrite: 电信营业厅 = type=http-request,pattern=^https:\/\/wapside.189.cn:9001\/api\/home\/sign,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.cookie.js,requires-body=true +Rewrite: 飞客茶馆 = type=http-request,pattern=^https:\/\/www\.flyertea\.com\/source\/plugin\/mobile\/mobile\.php\?module=getdata&.*,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/flyertea/flyertea.cookie.js +Rewrite: 网易云音乐 = type=http-request,pattern=^https:\/\/music.163.com\/weapi\/user\/level,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasemusic/quanx/neteasemusic.cookie.js,requires-body=true +Rewrite: 百度签到 = type=http-request,pattern=^https?:\/\/tieba\.baidu\.com\/?.?,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/tieba/tieba.cookie.js +Rewrite: 叮咚买菜 = type=http-request,pattern=^https:\/\/maicai.api.ddxq.mobi\/point\/home,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mcdd/mcdd.cookie.js +Rewrite: 樊登读书 = type=http-request,pattern=^https://api\.dushu\.io/CheckIn,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/fandeng/fandeng.cookie.js,requires-body=true +Rewrite: 合创 = type=http-request,pattern=^https:\/\/wxprdapplet\.gac-nio\.com\/community\/userSignIn\/simpleAuth\/front\/v3\.1\.3\.5\/signV2$,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/hycan/hycan.cookie.js +Rewrite: 京东到家 = type=http-request,pattern=^https:\/\/daojia.jd.com/client(.*?)functionId=signin(.*?)userSigninNew,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/jddj/jddj.cookie.js +Rewrite: 加油广东 = type=http-request,pattern=^https:\/\/m.gdoil.cn\/webapi\/usersign\/addusersign,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/gdoil/gdoil.cookie.js +Rewrite: 猫咪音乐网 = type=http-request,pattern=https:\/\/www.maomicd.com\/plugin.php\?id=k_misign:sign&operation=qiandao,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/maomicd/maomicd.cookie.js +Rewrite: 米游社 = type=http-request,pattern=^https:\/\/api-takumi.mihoyo.com\/apihub\/api\/getGameList,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mihoyo/mihoyo.cookie.js +Rewrite: 美团 = type=http-request,pattern=^https:\/\/i.meituan.com\/evolve\/signin\/signpost\/,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/meituan/meituan.cookie.js,requires-body=true +Rewrite: 美团外卖 = type=http-request,pattern=^https:\/\/promotion.waimai.meituan.com\/playcenter\/signIn\/doaction url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/wmmeituan/wmmeituan.cookie.js +Rewrite: 美团外卖 = type=http-request,pattern=^https:\/\/promotion.waimai.meituan.com\/playcenter\/signIn\/entry,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wmmeituan/wmmeituan.cookie.js +Rewrite: 芒果TV = type=http-request,pattern=^https:\/\/credits.bz.mgtv.com\/user\/creditsTake,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mgtv/mgtv.cookie.js +Rewrite: 全民K歌 = type=http-request,pattern=^https://node\.kg\.qq\.com/webapp/proxy?,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qmkg/qmkg.cookie.js,requires-body=true +Rewrite: 去哪儿 = type=http-request,pattern=^https:\/\/user.qunar.com\/webapi\/member\/signIndexV2.htm,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qunar/qunar.cookie.js +Rewrite: 什么值得买 = type=http-request,pattern=^https:\/\/www\.smzdm\.com\/?.?,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/smzdm/smzdm.cookie.js +Rewrite: 时光相册 = type=http-request,pattern=^https:\/\/api.everphoto.cn\/users\/self\/checkin\/v2,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/everphoto/everphoto.cookie.js +Rewrite: 苏宁易购 = type=http-request,pattern=^https:\/\/gameapi.suning.com\/sngame-web\/(api\/signin\/private\/customerSignOperation.do|gateway\/api\/queryPrize.do),script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js +Rewrite: 苏宁易购 = type=http-request,pattern=^https:\/\/luckman.suning.com\/luck-web\/sign\/api\/clock_sign.do,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js +Rewrite: 苏宁易购 = type=http-request,pattern=^https:\/\/passport.suning.com\/ids\/login$,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js,requires-body=true +Rewrite: 苏宁易购 = type=http-request,pattern=^https:\/\/sign.suning.com\/sign-web\/m\/promotion\/sign\/doSign.do,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.cookie.js +Rewrite: 顺丰速运 = type=http-request,pattern=^https:\/\/mcs-mimp-web.sf-express.com\/mcs-mimp\/share\/(.*?)Redirect,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.cookie.js +Rewrite: 顺丰速运 = type=http-request,pattern=^https:\/\/sf-integral-sign-in.weixinjia.net\/app\/index,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.cookie.js +Rewrite: 腾讯视频 = type=http-request,pattern=^https:\/\/access.video.qq.com\/user\/auth_refresh,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.cookie.js +Rewrite: 网易新闻 = type=http-request,pattern=^https:\/\/(.*?)c\.m\.163\.com\/uc\/api\/sign\/v3\/commit,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.cookie.js,requires-body=true +Rewrite: 网易考拉 = type=http-request,pattern=^https:\/\/m-bean\.kaola\.com/m/point/sign\.html,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wykl/wykl.cookie.js,requires-body=true +Rewrite: 蔚来 = type=http-request,pattern=^https:\/\/app\.nio\.com\/api\/1\/app\/daily_checkin,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/nio/nio.cookie.js +Rewrite: 喜马拉雅 = type=http-request,pattern=^https?:\/\/.*\/mobile\-user\/(v1\/)?homePage\/.*,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ximalaya/ximalaya.cookie.js +Rewrite: 智行火车 = type=http-request,pattern=^https:\/\/m\.suanya\.cn/restapi/soa2/\d+/attendanceDay,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zxhc/zxhc.cookie.js,requires-body=true +Rewrite: citybox = type=http-request,pattern=^https:\/\/api\.icitybox\.cn\/index.php\/api\/user\/get_user_info,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/citybox/citybox.cookie.js,debug=true + +[MITM] +hostname = %INSERT%, apiwz.midukanshu.com, api.1sapp.com, frodo.douban.com, luckman.suning.com, passport.suning.com, sign.suning.com, gameapi.suning.com, m.suanya.cn, 110.43.90.61, zt.wps.cn, m-bean.kaola.com, daojia.jd.com, app.nio.com, wxprdapplet.gac-nio.com, node.kg.qq.com, api.dushu.io, pm.m.fenqile.com, maicai.api.ddxq.mobi, group.baicizhan.com, api.everphoto.cn, i.meituan.com, promotion.waimai.meituan.com, wx.10086.cn, www.maomicd.com, m.client.10010.com, act.10010.com, api-takumi.mihoyo.com, m.gdoil.cn, credits.bz.mgtv.com, *.csdn.net, wapside.189.cn, *.acfun.cn, apk.tw, *.bilibili.com, api.dongqiudi.com, *.feng.com, www.flyertea.com, music.163.com, *.m.163.com, user.qunar.com, *.rr.tv, sf-integral-sign-in.weixinjia.net, mcs-mimp-web.sf-express.com, *.smzdm.com, tieba.baidu.com, *.v2ex.com, *.video.qq.com, 113.96.156.178, *.ximalaya.com, *.you.163.com, *.rrys2020.com, ios.zmzapi.com \ No newline at end of file diff --git a/surge.tasks.sgmodule b/surge.tasks.sgmodule new file mode 100644 index 000000000..08a647d45 --- /dev/null +++ b/surge.tasks.sgmodule @@ -0,0 +1,36 @@ +#!name=Chavy iOS Tasks Module +#!desc=iOS Tasks 模块配置 +#!system=ios + +[Script] +Tasks: 去哪儿 = type=cron,cronexp=4 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/qunar/qunar.js +Tasks: 网易新闻 = type=cron,cronexp=4 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasenews/neteasenews.js +Tasks: 腾讯视频 = type=cron,cronexp=3 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.js +Tasks: 10010 = type=cron,cronexp=0 9 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/10010/10010.js,wake-system=true +Tasks: AcFun = type=cron,cronexp=3 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/acfun/acfun.js,wake-system=true +Tasks: ApkTw = type=cron,cronexp=0 8 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/apktw/apktw.js,wake-system=true +Tasks: BiliBili = type=cron,cronexp=2 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/bilibili/bilibili.js,wake-system=true, timeout = 60 +Tasks: V2EX = type=cron,cronexp=2 9 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/v2ex/v2ex.js,wake-system=true +Tasks: WPS = type=cron,cronexp=0 9 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wps/wps.js,wake-system=true +Tasks: 叮咚买菜 = type=cron,cronexp=7 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mcdd/mcdd.js,wake-system=true +Tasks: 加油广东 = type=cron,cronexp=1 7 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/gdoil/gdoil.js,wake-system=true +Tasks: 什么值得买 = type=cron,cronexp=2 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/smzdm/smzdm.js,wake-system=true +Tasks: 喜马拉雅 = type=cron,cronexp=4 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ximalaya/ximalaya.js,wake-system=true +Tasks: 百度贴吧 = type=cron,cronexp=1 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/tieba/tieba.js,wake-system=true +Tasks: 懂球帝 = type=cron,cronexp=4 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/dongqiudi/dongqiudi.js,wake-system=true +Tasks: 飞客茶馆 = type=cron,cronexp=4 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/flyertea/flyertea.js,wake-system=true +Tasks: 米游社 = type=cron,cronexp=2 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mihoyo/mihoyo.js,wake-system=true +Tasks: 美团 = type=cron,cronexp=7 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/meituan/meituan.js,wake-system=true +Tasks: 芒果TV = type=cron,cronexp=2 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/mgtv/mgtv.js,wake-system=true +Tasks: 时光相册 = type=cron,cronexp=7 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/everphoto/everphoto.js,wake-system=true +Tasks: 苏宁易购 = type=cron,cronexp=7 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/suning/suning.js,wake-system=true +Tasks: 顺丰速运 = type=cron,cronexp=6 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/sfexpress/sfexpress.js,wake-system=true +Tasks: 网易云音乐 = type=cron,cronexp=1 7 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/neteasemusic/neteasemusic.js,wake-system=true +Tasks: citybox-签到 = type=cron,cronexp=10 10 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/citybox/citybox.js,wake-system=true +Tasks: 智行火车 = type=cron,cronexp=10 8 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zxhc/zxhc.js,wake-system=true +# Tasks: 美团外卖 = type=cron,cronexp=8 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wmmeituan/wmmeituan.js + +Rewrite: 头脑吃鸡 = type=http-response,pattern=^https://tncj.hortorgames.com/chicken/fight/(answer|findQuiz),script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/tncj/tncj.min.js,requires-body=true,max-size=0 + +[MITM] +hostname = %INSERT% tncj.hortorgames.com \ No newline at end of file diff --git a/testflight/README.md b/testflight/README.md new file mode 100644 index 000000000..7e3bfdec3 --- /dev/null +++ b/testflight/README.md @@ -0,0 +1,29 @@ +# TestFlight +自动加入 TF (公测) + +## Surge + +### 说明: + +本脚本包含两个模块 +1. [testflight.har.sgmodule](https://raw.githubusercontent.com/chavyleung/scripts/master/testflight/rewrite/testflight.har.sgmodule) + 1. 用于获取 TestFlight 账号信息, 获取完即可关掉 + 2. 与 `TestFlight账户管理` 冲突, 使用前请先临时关闭 + +2. [testflight.sgmodule](https://raw.githubusercontent.com/chavyleung/scripts/master/testflight/rewrite/testflight.sgmodule) + 1. 定时任务, 每 `1秒` 运行一次尝试加入 `TF` + +### 使用: +1. 安装远程 [testflight.har.sgmodule](https://raw.githubusercontent.com/chavyleung/scripts/master/testflight/rewrite/testflight.har.sgmodule) 模块 +2. 打开 `TestFlight`, 脚本提示 `获取 TestFlight 账户成功` +3. 安装 [BoxJs订阅](http://boxjs.com/#/sub/add/https%3A%2F%2Fraw.githubusercontent.com%2Fchavyleung%2Fscripts%2Fmaster%2Fbox%2Fchavy.boxjs.json +) (如果之前已安装, 请直接更新订阅) +4. 打开 [BoxJs](http://boxjs.com/#/app/testflight), 并填写 `应用编号` (如: McBV96Wi,uEXBDwt2) + 1. 请使用`英文逗号`分隔`应用编号` +5. 关闭 [testflight.har.sgmodule](https://raw.githubusercontent.com/chavyleung/scripts/master/testflight/rewrite/testflight.har.sgmodule) 模块 +6. 安装 [testflight.sgmodule](https://raw.githubusercontent.com/chavyleung/scripts/master/testflight/rewrite/testflight.sgmodule) 模块 + +## 感谢 +[@githubdulong](https://github.com/githubdulong) + +[@DecoAri](https://github.com/DecoAri) \ No newline at end of file diff --git a/testflight/rewrite/testflight.har.sgmodule b/testflight/rewrite/testflight.har.sgmodule new file mode 100644 index 000000000..cfb067978 --- /dev/null +++ b/testflight/rewrite/testflight.har.sgmodule @@ -0,0 +1,8 @@ +#!name=@boxapp/script-testflight +#!desc=Get TestFlight Har + +[Script] +TestFlight HAR = type=http-request,pattern=^https:\/\/testflight\.apple\.com\/v3\/accounts/.*\/apps$,requires-body=0,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/testflight/testflight.har.js + +[MITM] +hostname = testflight.apple.com diff --git a/testflight/rewrite/testflight.sgmodule b/testflight/rewrite/testflight.sgmodule new file mode 100644 index 000000000..bedef060b --- /dev/null +++ b/testflight/rewrite/testflight.sgmodule @@ -0,0 +1,5 @@ +#!name=@boxapp/script-testflight +#!desc=Auto Join TestFlight + +[Script] +TestFlight = type=cron,cronexp=*/1 * * * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/testflight/testflight.js,wake-system=0,timeout=180 diff --git a/testflight/testflight.har.js b/testflight/testflight.har.js new file mode 100644 index 000000000..35a0ac3a0 --- /dev/null +++ b/testflight/testflight.har.js @@ -0,0 +1,13 @@ +const $ = new Env('TestFlight') + +!(async () => { + const KEY = 'boxapp_testflight_har' + const har = { url: $request.url, headers: $request.headers } + $.setjson(har, KEY) + $.msg($.name, '获取 TestFlight 账户成功') +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}isStash(){return"undefined"!=typeof $environment&&$environment["stash-version"]}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,n]=i.split("@"),a={url:`http://${n}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),n=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(n);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){if(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:i,statusCode:r,headers:o,rawBody:n}=t,a=s.decode(n,this.encoding);e(null,{status:i,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:i,response:r}=t;e(i,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let i=require("iconv-lite");this.initGotEnv(t);const{url:r,...o}=t;this.got[s](r,o).then(t=>{const{statusCode:s,statusCode:r,headers:o,rawBody:n}=t,a=i.decode(n,this.encoding);e(null,{status:s,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:s,response:r}=t;e(s,r,r&&i.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}queryStr(t){let e="";for(const s in t){let i=t[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),e+=`${s}=${i}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,i=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":i}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),this.isSurge()||this.isQuanX()||this.isLoon()?$done(t):this.isNode()&&process.exit(1)}}(t,e)} diff --git a/testflight/testflight.js b/testflight/testflight.js new file mode 100644 index 000000000..381299b03 --- /dev/null +++ b/testflight/testflight.js @@ -0,0 +1,132 @@ +const $ = new Env('TestFlight') +$.isDisableModule = false + +!(async () => { + const KEY_har = 'boxapp_testflight_har' + const KEY_app = 'boxapp_testflight_app' + const har = $.getjson(KEY_har) + const appIds = $.getdata(KEY_app) + + if (!appIds) { + $.isDisableModule = true + $.msg($.name, '请先指定需要加入测试的应用, 并重新打开模块') + return + } + + if (!har) { + $.msg($.name, '请先使用脚本获取 TestFlight 账号信息') + return + } + + const ids = appIds.split(',') + for (let i = 0; i < ids.length; i++) { + const id = ids[i].trim() + const result = await join(id, har) + const success = result[0] + const message = result[1] + const data = result[2] + + if (success) { + $.msg($.name, `[${data.data.name} (${id})]: ${message}`) + + const newIds = ids.filter((i) => i !== id).join(',') + $.setdata(newIds, KEY_app) + continue + } + + if (!success && !data) { + $.msg($.name, message) + continue + } + } +})() + .catch((e) => $.logErr(e)) + .finally(() => { + if ( + $.isDisableModule && + $.isSurge() && + !$.isLoon() && + !$.isShadowrocket() && + !$.isStash() + ) { + $.done( + $httpAPI('POST', '/v1/modules', { + '@boxapp/script-testflight': 'false' + }) + ) + } else { + $.done() + } + }) + +function join(id, har) { + const key = har.url.replace(/(.*accounts\/)(.*)(\/apps)/, '$2') + return $.http + .get({ + url: `https://testflight.apple.com/v3/accounts/${key}/ru/${id}`, + headers: getHeaders(har) + }) + .then(async (resp) => { + const result = JSON.parse(resp.body) + + // {"data":null,"messages":[{"message":"This beta isn't accepting any new testers right now.","messageType":"ERROR","code":1110}]} + if (result.data === null) { + const message = + (result.messages && + result.messages[0] && + result.messages[0].message) || + '名额已满' + console.log(`[${id}]: ${message}`) + return [false, message, result] + } + + // {"data":{"status":"FULL","message":"This beta is full.", + if (result.data && result.data.status === 'FULL') { + const message = result.data.message || '名额已满' + console.log(`[${id}]: ${message}`) + return [false, message, result] + } + + return await accept(id, har) + }) + .catch((error) => { + console.log('-------------') + console.log(error) + if (error.status === 404) { + return [false, '不存在应用', null] + } + return [false, '未知错误', null] + }) +} + +function accept(id, har) { + const key = har.url.replace(/(.*accounts\/)(.*)(\/apps)/, '$2') + return $.http + .post({ + url: `https://testflight.apple.com/v3/accounts/${key}/ru/${id}/accept`, + headers: getHeaders(har) + }) + .then((resp) => { + const result = JSON.parse(resp.body) + return [true, '加入成功', result] + }) + .catch(() => { + return [false, '加入失败', null] + }) +} + +function getHeaders(har) { + const userAgent = har.headers['user-agent'] + const xRequestId = har.headers['x-request-id'] + const xSessionDigest = har.headers['x-session-digest'] + const xSessionId = har.headers['x-session-id'] + return { + 'user-agent': userAgent, + 'x-request-id': xRequestId, + 'x-session-digest': xSessionDigest, + 'x-session-id': xSessionId + } +} + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}isStash(){return"undefined"!=typeof $environment&&$environment["stash-version"]}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,n]=i.split("@"),a={url:`http://${n}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),n=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(n);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){if(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:i,statusCode:r,headers:o,rawBody:n}=t,a=s.decode(n,this.encoding);e(null,{status:i,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:i,response:r}=t;e(i,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t&&t.error||"UndefinedError"));else if(this.isNode()){let i=require("iconv-lite");this.initGotEnv(t);const{url:r,...o}=t;this.got[s](r,o).then(t=>{const{statusCode:s,statusCode:r,headers:o,rawBody:n}=t,a=i.decode(n,this.encoding);e(null,{status:s,statusCode:r,headers:o,rawBody:n,body:a},a)},t=>{const{message:s,response:r}=t;e(s,r,r&&i.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}queryStr(t){let e="";for(const s in t){let i=t[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),e+=`${s}=${i}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,i=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":i}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),this.isSurge()||this.isQuanX()||this.isLoon()?$done(t):this.isNode()&&process.exit(1)}}(t,e)} diff --git a/tieba/tieba.cookie.js b/tieba/tieba.cookie.js index fbe454c63..44b13cd59 100644 --- a/tieba/tieba.cookie.js +++ b/tieba/tieba.cookie.js @@ -1,7 +1,7 @@ const cookieName = '百度贴吧' const cookieKey = 'chavy_cookie_tieba' const chavy = init() -const cookieVal = $request.headers['Cookie'] +const cookieVal = $request.headers['Cookie'] || $request.headers['cookie'] if (cookieVal.indexOf('BDUSS') > 0) { let cookie = chavy.setdata(cookieVal, cookieKey) diff --git a/tieba/tieba.js b/tieba/tieba.js index 761efb28e..c907a5aa3 100644 --- a/tieba/tieba.js +++ b/tieba/tieba.js @@ -1,188 +1,240 @@ -const cookieName = '百度贴吧' -const cookieKey = 'chavy_cookie_tieba' -const chavy = init() -const cookieVal = chavy.getdata(cookieKey) +const $ = new Env('百度签到') +$.VAL_cookies = $.getdata('chavy_cookie_tieba') || $.getdata('CookieTB') -sign() +$.CFG_isOrderBars = $.getdata('CFG_tieba_isOrderBars') || 'false' // 1: 经验排序, 2: 连签排序 +$.CFG_maxShowBars = $.getdata('CFG_tieba_maxShowBars') * 1 || 15 //每次通知数量 +$.CFG_maxSignBars = $.getdata('CFG_tieba_maxSignBars') * 1 || 5 // 每次并发执行多少个任务 +$.CFG_signWaitTime = $.getdata('CFG_tieba_signWaitTime') * 1 || 2000 // 每次并发间隔时间 (毫秒) -function sign() { - signTieba() - // signWenku() - signZhidao() +!(async () => { + await tieba() + await zhidao() + await showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// 贴吧 +function tieba() { + return new Promise((resove) => { + const url = { url: 'https://tieba.baidu.com/mo/q/newmoindex', headers: { Cookie: $.VAL_cookies } } + $.get(url, async (err, resp, data) => { + try { + const _data = JSON.parse(data) + // 处理异常 + if (_data.no !== 0) { + throw new Error(`获取清单失败! 原因: ${_data.error}`) + } + // 组装数据 + $.bars = [] + $.tieba = { tbs: _data.data.tbs } + _data.data.like_forum.forEach((bar) => $.bars.push(barWrapper(bar))) + $.bars = $.bars.sort((a, b) => b.exp - a.exp) + // 开始签到 + await signbars($.bars) + // await getbars($.bars) + } catch (e) { + $.logErr(e, resp) + } finally { + resove() + } + }) + }) } -function signTieba() { - let url = { url: `https://tieba.baidu.com/mo/q/newmoindex`, headers: { Cookie: cookieVal } } - chavy.post(url, (error, response, data) => { - let result = JSON.parse(data) - let tbs = result.data.tbs - let forums = result.data.like_forum - let signinfo = { - forumCnt: forums.length, - signedCnt: 0, - successCnt: 0, - failedCnt: 0, - skipedCnt: 0 +async function signbars(bars) { + let signbarActs = [] + // 处理`已签`数据 + bars.filter((bar) => bar.isSign).forEach((bar) => (bar.iscurSign = false)) + // 处理`未签`数据 + let _curbarIdx = 1 + let _signbarCnt = 0 + bars.filter((bar) => !bar.isSign).forEach((bar) => _signbarCnt++) + for (let bar of bars.filter((bar) => !bar.isSign)) { + const signbarAct = (resove) => { + const url = { url: 'https://tieba.baidu.com/sign/add', headers: { Cookie: $.VAL_cookies } } + url.body = `ie=utf-8&kw=${encodeURIComponent(bar.name)}&tbs=${$.tieba.tbs}` + url.headers['Host'] = 'tieba.baidu.com' + url.headers['User-Agent'] = + 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Mobile/15E148 Safari/604.1' + $.post(url, (err, resp, data) => { + try { + const _data = JSON.parse(data) + bar.iscurSign = true + bar.issignSuc = _data.no === 0 || _data.no === 1101 + bar.signNo = _data.no + bar.signMsg = _data.no === 1102 ? '签得太快!' : _data.error + bar.signMsg = _data.no === 2150040 ? '需要验证码!' : _data.error + } catch (e) { + bar.iscurSign = true + bar.issignSuc = false + bar.signNo = null + bar.signMsg = err !== null ? error : e + $.logErr(e, resp) + } finally { + $.log(`❕ 贴吧:【${bar.name}】签到完成!`) + resove() + } + }) + } + signbarActs.push(new Promise(signbarAct)) + if (signbarActs.length === $.CFG_maxSignBars || _signbarCnt === _curbarIdx) { + $.log('', `⏳ 正在发起 ${signbarActs.length} 个签到任务!`) + await Promise.all(signbarActs) + await $.wait($.CFG_signWaitTime) + signbarActs = [] } + _curbarIdx++ + } +} - for (const bar of forums) { - // 已签 - if (bar.is_sign == 1) { - signinfo.signedCnt += 1 - signinfo.skipedCnt += 1 - chavy.log(`[${cookieName}] \"${bar.forum_name}\"签到结果: 跳过, 原因: 重复签到`) - } - // 未签 - else { - signBar(bar, tbs, (error, response, data) => { - let signresult = JSON.parse(data) - if (signresult.no == 0 || signresult.no == 1011) { - signinfo.signedCnt += 1 - signinfo.successCnt += 1 - chavy.log(`[${cookieName}] \"${bar.forum_name}\"签到结果: 成功`) - } else { - signinfo.failedCnt += 1 - chavy.log(`[${cookieName}] \"${bar.forum_name}\"签到结果: 失败, 编码: ${signresult.no}, 原因: ${signresult.error}`) - } - }) +function getbars(bars) { + const getBarActs = [] + for (let bar of bars) { + const getBarAct = (resove) => { + const url = { + url: `http://tieba.baidu.com/sign/loadmonth?kw=${encodeURIComponent(bar.name)}&ie=utf-8`, + headers: { Cookie: $.VAL_cookies } } + url.headers['Host'] = 'tieba.baidu.com' + url.headers['User-Agent'] = + 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Mobile/15E148 Safari/604.1' + $.get(url, (err, resp, data) => { + try { + const _signinfo = JSON.parse(data).data.sign_user_info + bar.signRank = _signinfo.rank + bar.contsignCnt = _signinfo.sign_keep + bar.totalsignCnt = _signinfo.sign_total + } catch (e) { + bar.contsignCnt = '❓' + $.logErr(e, resp) + } finally { + resove() + } + }) } - check(forums, signinfo) - }) + getBarActs.push(new Promise(getBarAct)) + } + return Promise.all(getBarActs) } -function signBar(bar, tbs, cb) { - let url = { - url: `https://tieba.baidu.com/sign/add`, - headers: { Cookie: cookieVal }, - body: `ie=utf-8&kw=${bar.forum_name.split('&').join('%26')}&tbs=${tbs}` - } - chavy.post(url, cb) +async function zhidao() { + await loginZhidao() + await signZhidao() } -function signWenku() { - let url = { url: `https://wenku.baidu.com/task/submit/signin`, headers: { Cookie: cookieVal } } - url.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8' - chavy.get(url, (error, response, data) => { - const signresult = JSON.parse(data) - const title = '百度文库' - let subTitle = '' - let detail = '' - if (signresult.errno == '0') { - subTitle = '签到结果: 成功' - chavy.msg(title, subTitle, detail) - chavy.log(`[${title}] ${subTitle}`) - } else { - subTitle = '签到结果: 未知' - detail = '详见日志' - chavy.msg(title, subTitle, detail) - chavy.log(`[${title}] 签到结果: 未知, ${data}`) - } +function loginZhidao() { + return new Promise((resove) => { + const url = { url: 'https://zhidao.baidu.com/', headers: { Cookie: $.VAL_cookies } } + url.headers['Host'] = 'zhidao.baidu.com' + url.headers['User-Agent'] = + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15' + $.zhidao = {} + $.post(url, (err, resp, data) => { + try { + $.zhidao.stoken = data.match(/"stoken"[^"]*"([^"]*)"/)[1] + if (!$.zhidao.stoken) { + throw new Error(`获取 stoken 失败! stoken: ${$.zhidao.stoken}`) + } + $.zhidao.isloginSuc = true + $.zhidao.loginMsg = '登录成功' + } catch (e) { + $.zhidao.isloginSuc = false + $.zhidao.loginMsg = '登录失败' + $.logErr(e, resp) + } finally { + resove() + } + }) }) } function signZhidao() { - let url = { - url: `https://zhidao.baidu.com/`, - headers: { Cookie: cookieVal } + // 登录失败, 直接跳出 + if (!$.zhidao.isloginSuc) { + return null } - chavy.get(url, (error, response, data) => { + return new Promise((resove) => { + const url = { url: 'https://zhidao.baidu.com/submit/user', headers: { Cookie: $.VAL_cookies } } + url.headers['Host'] = 'zhidao.baidu.com' + url.headers['User-Agent'] = + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15' const timestamp = Date.parse(new Date()) const utdata = `61,61,7,0,0,0,12,61,5,2,12,4,24,5,4,1,4,${timestamp}` - const stoken = data.match(/"stoken"[^"]*"([^"]*)"/)[1] - const signurl = { url: `https://zhidao.baidu.com/submit/user`, headers: { Cookie: cookieVal }, body: {} } - signurl.body = `cm=100509&utdata=${utdata}&stoken=${stoken}` - chavy.post(signurl, (signerror, signresp, signdata) => { - const signresult = JSON.parse(signdata) - const title = '百度知道' - let subTitle = '' - let detail = '' - if (signresult.errorNo == 0) { - subTitle = '签到结果: 成功' - detail = `活跃: ${signresult.data.signInDataNum}天, 说明: ${signresult.errorMsg}` - chavy.msg(title, subTitle, detail) - chavy.log(`[${title}] ${subTitle}, ${signdata}`) - } else if (signresult.errorNo == 2) { - subTitle = `签到结果: 成功 (重复签到)` - detail = `活跃: ${signresult.data.signInDataNum}天, 说明: ${signresult.errorMsg}` - chavy.msg(title, subTitle, detail) - chavy.log(`[${title}] ${subTitle}, ${signdata}`) - } else { - subTitle = '签到结果: 失败' - detail = `说明: ${signresult.errorMsg}` - chavy.msg(title, subTitle, detail) - chavy.log(`[${title}] ${subTitle}`) + url.body = `cm=100509&utdata=${utdata}&stoken=${$.zhidao.stoken}` + $.post(url, (err, resp, data) => { + try { + const _data = JSON.parse(data) + $.zhidao.isSignSuc = true + $.zhidao.signNo = _data.errorNo + $.zhidao.signMsg = _data.errorMsg + } catch (e) { + $.zhidao.isSignSuc = false + $.zhidao.signNo = null + $.zhidao.signMsg = e + $.logErr(e, resp) + } finally { + resove() } }) }) } -function check(forums, signinfo, checkms = 0) { - let title = `${cookieName}` - let subTitle = `` - let detail = `今日共签: ${signinfo.signedCnt}/${signinfo.forumCnt}, 本次成功: ${signinfo.successCnt}, 本次失败: ${signinfo.failedCnt}` - if (signinfo.forumCnt == signinfo.signedCnt + signinfo.failedCnt) { - // 成功数+跳过数=总数 = 全部签到成功 - if (signinfo.successCnt + signinfo.skipedCnt == signinfo.forumCnt) { - subTitle = `签到结果: 全部成功` - } else { - subTitle = `签到结果: 部分成功` - } - chavy.log(`${title}, ${subTitle}, ${detail}`) - chavy.msg(title, subTitle, detail) - chavy.done() - } else { - if (checkms > 9000) { - subTitle = `签到结果: 超时退出 (请重试)` - chavy.log(`${title}, ${subTitle}, ${detail}`) - chavy.msg(title, subTitle, detail) - chavy.done() - } else { - setTimeout(() => check(forums, signinfo, checkms + 50), 50) - } - } +function barWrapper(bar) { + return { id: bar.forum_id, name: bar.forum_name, exp: bar.user_exp, level: bar.user_level, isSign: bar.is_sign === 1 } } -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) - } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) - } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) - } - } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +function showmsg() { + return new Promise((resolve) => { + // 数据: 签到数量 + const allbarCnt = $.bars.length + let allsignCnt = 0 + let cursignCnt = 0 + let curfailCnt = 0 + $.bars.filter((bar) => bar.isSign).forEach((bar) => (allsignCnt += 1)) + $.bars.filter((bar) => bar.iscurSign && bar.issignSuc).forEach((bar) => (cursignCnt += 1)) + $.bars.filter((bar) => bar.iscurSign && !bar.issignSuc).forEach((bar) => (curfailCnt += 1)) + $.bars = [true, 'true'].includes($.CFG_isOrderBars) ? $.bars.sort((a, b) => b.contsignCnt - a.contsignCnt) : $.bars + allsignCnt += cursignCnt + // 通知: 副标题 + let tiebasubt = '贴吧: ' + if (allbarCnt == allsignCnt) tiebasubt += '成功' + else if (allbarCnt == curfailCnt) tiebasubt += '失败' + else tiebasubt += '部分' + let zhidaosubt = '知道: ' + if ($.zhidao.isSignSuc && $.zhidao.signNo === 0) zhidaosubt += '成功' + else if ($.zhidao.isSignSuc && $.zhidao.signNo === 2) zhidaosubt += '重复' + else zhidaosubt += '失败' + // 通知: 详情 + let _curPage = 1 + const _totalPage = Math.ceil(allbarCnt / $.CFG_maxShowBars) + + $.desc = [] + $.bars.forEach((bar, index) => { + const barno = index + 1 + // const signbar = `${bar.isSign || bar.issignSuc ? '🟢' : '🔴'} [${barno}]【${bar.name}】排名: ${bar.signRank}` + const signbar = `${bar.isSign || bar.issignSuc ? '🟢' : '🔴'} [${barno}]【${bar.name}】` + const signlevel = `等级: ${bar.level}` + const signexp = `经验: ${bar.exp}` + const signcnt = `连签: ${bar.contsignCnt}/${bar.totalsignCnt}天` + const signmsg = `${bar.isSign || bar.issignSuc ? '' : `失败原因: ${bar.signMsg}\n`}` + $.desc.push(`${signbar}`) + // $.desc.push(`${signlevel}, ${signexp}, ${signcnt}`) + $.desc.push(`${signlevel}, ${signexp}`) + $.desc.push(`${signmsg}`) + if (barno % $.CFG_maxShowBars === 0 || barno === allbarCnt) { + const _descinfo = [] + _descinfo.push(`共签: ${allsignCnt}/${allbarCnt}, 本次成功: ${cursignCnt}, 本次失败: ${curfailCnt}`) + _descinfo.push(`点击查看详情, 第 ${_curPage++}/${_totalPage} 页`) + $.subt = `${tiebasubt}, ${zhidaosubt}` + $.desc = [..._descinfo, '', ...$.desc].join('\n') + $.msg($.name, $.subt, $.desc) + $.desc = [] + } + }) + resolve() + }) } + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/tongcheng-trip/tongcheng-trip.js b/tongcheng-trip/tongcheng-trip.js new file mode 100644 index 000000000..bcd9cf772 --- /dev/null +++ b/tongcheng-trip/tongcheng-trip.js @@ -0,0 +1,205 @@ +/** + * + * hostname = app.17u.cn + * + * # Surge + * http-request ^https:\/\/app\.17u\.cn\/welfarecenter\/index\/signIndex script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/tongcheng-trip/tongcheng-trip.js, tag=同程旅行 + * cron "5 12 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/tongcheng-trip/tongcheng-trip.js, timeout=300, tag=同程旅行-签到 + * + * # QuanX + * ^https:\/\/app\.17u\.cn\/welfarecenter\/index\/signIndex url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/tongcheng-trip/tongcheng-trip.js + * 5 12 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/tongcheng-trip/tongcheng-trip.js, tag=同程旅行-签到 + * + * # Loon + * http-request ^https:\/\/app\.17u\.cn\/welfarecenter\/index\/signIndex script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/tongcheng-trip/tongcheng-trip.js, tag=同程旅行 + * cron "5 12 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/tongcheng-trip/tongcheng-trip.js, timeout=300, tag=同程旅行-签到 + * + * # 获取方式: 打开同程旅行 APP → 领福利,命中 signIndex 请求后自动保存请求头(含 phone、apptoken、device) + */ + + +const $ = new Env('同程旅行') +const BASE_URL = 'https://app.17u.cn/welfarecenter' +const KEY_SIGNHEADER = 'tongcheng_trip_signheader' + +function getTodayDate() { + return $.time('yyyy-MM-dd') +} + +function postApi(path, body, headers) { + return new Promise((resolve) => { + const opts = { + url: path.startsWith('http') ? path : BASE_URL + path, + headers: { ...headers, 'content-type': 'application/json' }, + body: typeof body === 'object' ? JSON.stringify(body || {}) : body || '{}' + } + $.post(opts, (err, resp, data) => { + try { + resolve(data ? JSON.parse(data) : null) + } catch (e) { + $.logErr(e, data) + resolve(null) + } + }) + }) +} + +function signIndex() { + return new Promise((resolve) => { + const signheaderVal = $.getdata(KEY_SIGNHEADER) + if (!signheaderVal) { + $.log('未获取到 Cookie,请先通过 MiTM 获取:在 APP 打开「领福利」→ 点击签到') + $.msg($.name, '', '请先配置抓包脚本,在 APP 领福利页点击签到以获取 Cookie') + resolve(null) + return + } + $.headers = JSON.parse(signheaderVal) + $.phone = $.headers.phone || $.headers.Phone || '当前账号' + postApi('/index/signIndex', {}, $.headers).then((data) => resolve(data)) + }) +} + +function doSignIn() { + return new Promise((resolve) => { + const todayDate = getTodayDate() + postApi('/index/sign', { type: 1, day: todayDate }, $.headers).then((data) => resolve(data)) + }) +} + +function getTaskList() { + return new Promise((resolve) => { + postApi('/task/taskList?version=11.0.7', {}, $.headers).then((data) => resolve(data)) + }) +} + +function taskStart(taskCode) { + return new Promise((resolve) => { + postApi('/task/start', { taskCode }, $.headers).then((data) => resolve(data)) + }) +} + +function taskFinish(taskId) { + return new Promise((resolve) => { + postApi('/task/finish', { id: taskId }, $.headers).then((data) => resolve(data)) + }) +} + +function taskReceive(taskId) { + return new Promise((resolve) => { + postApi('/task/receive', { id: taskId }, $.headers).then((data) => resolve(data)) + }) +} + +async function runSignIn() { + $.accountResult = '' + $.signSuccess = false + $.tokenInvalid = false + + const signIndexRes = await signIndex() + if (!signIndexRes) return + if (signIndexRes.code !== 2200) { + $.log(`用户【${$.phone}】 - token 失效了,请重新在 APP 领福利页点击签到以更新`) + $.tokenInvalid = true + $.accountResult = `📱 账号:${$.phone}\n❌ token 失效,请重新抓包获取\n\n` + $.msg('✈️ 同程旅行签到结果\n⚠️ Token 失效', '', $.accountResult) + return + } + + const todaySign = signIndexRes.data?.todaySign + const mileage = signIndexRes.data?.mileageBalance?.mileage ?? 0 + $.log(`用户【${$.phone}】 - 今日${todaySign ? '已' : '未'}签到,当前剩余里程 ${mileage}!`) + + if (todaySign) { + $.log(`用户【${$.phone}】 - 今日已签到,开始获取任务列表`) + $.signSuccess = true + } else { + $.log(`用户【${$.phone}】 - 今日未签到,开始执行签到`) + const signRes = await doSignIn() + if (signRes && signRes.code === 2200) { + $.log(`用户【${$.phone}】 - 签到成功!`) + $.signSuccess = true + } else { + $.log(`用户【${$.phone}】 - 签到失败!${signRes?.message || '未知错误'}`) + } + } + + const taskListRes = await getTaskList() + if (taskListRes && taskListRes.code === 2200 && Array.isArray(taskListRes.data)) { + const tasks = taskListRes.data.filter((t) => t.state === 1 && t.browserTime !== 0) + for (const task of tasks) { + const { taskCode, title, browserTime } = task + $.log(`用户【${$.phone}】 - 开始做任务【${title}】,需要浏览 ${browserTime} 秒`) + const startRes = await taskStart(taskCode) + if (startRes && startRes.code === 2200 && startRes.data) { + const taskId = startRes.data + await $.wait(browserTime * 1000) + let finishOk = false + for (let attempt = 0; attempt < 3; attempt++) { + const finishRes = await taskFinish(taskId) + if (finishRes && finishRes.code === 2200) { + $.log(`用户【${$.phone}】 - 完成任务【${taskId}】成功!开始领取奖励`) + finishOk = true + break + } + if (attempt < 2) { + $.log(`用户【${$.phone}】 - 完成任务【${taskId}】失败,第 ${attempt + 1} 次重试...`) + await $.wait(2000 * (attempt + 1)) + } + } + if (finishOk) { + await taskReceive(taskId) + $.log(`用户【${$.phone}】 - 领取签到奖励成功!开始下一个任务`) + } + } + } + } + + const mileageRes = await postApi('/index/signIndex', {}, $.headers) + if (mileageRes && mileageRes.code === 2200 && mileageRes.data) { + const d = mileageRes.data + const cycleSignNum = d.cycleSighNum + const mileage2 = d.mileageBalance?.mileage ?? 0 + const todayMileage = d.mileageBalance?.todayMileage ?? 0 + $.log(`用户【${$.phone}】 - 本月签到 ${cycleSignNum} 天,今日共获取 ${todayMileage} 里程,当前剩余里程 ${mileage2}`) + const statusIcon = $.signSuccess ? '✨️' : '❗️' + const resultText = $.signSuccess + ? `${statusIcon} 签到成功,本月签到【${cycleSignNum}】天` + : `${statusIcon} 签到暂不可用,请前往 APP 手动签到!\n🈷️ 本月签到【${cycleSignNum}】天` + $.accountResult = `📱 账号:${$.phone}\n${resultText}\n🎁 当前里程: 【${mileage2}】(+${todayMileage})\n\n` + } else { + $.accountResult = `📱 账号:${$.phone}\n` + if ($.signSuccess) $.accountResult += '✅ 签到成功(但获取里程信息失败)\n\n' + else $.accountResult += '❌ 签到失败且获取里程信息失败\n\n' + } + + let title = '✈️ 同程旅行签到结果\n' + if ($.tokenInvalid) title += ' ⚠️ Token 失效' + $.msg(title, '', $.accountResult.trim()) +} + +// 入口:MiTM 时保存 Cookie,否则执行签到 +const isMitmRequest = + typeof $request !== 'undefined' && + $request && + typeof $request.url === 'string' && + /\/welfarecenter\/index\/signIndex/.test($request.url) && + $request.headers +if (isMitmRequest) { + if ($request.method !== 'OPTIONS') { + $.setdata(JSON.stringify($request.headers), KEY_SIGNHEADER) + $.msg($.name, '获取同程旅行账户成功', '请运行签到脚本') + $.done() + } else { + $.log('获取同程旅行账户失败') + $.done() + } +} else { + !(async () => { + await runSignIn() + })() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) +} + + +function Env(e,t){class s{constructor(e){this.env=e}send(e,t="GET"){e="string"==typeof e?{url:e}:e;let s=this.get;"POST"===t&&(s=this.post);const i=new Promise(((t,i)=>{s.call(this,e,((e,s,o)=>{e?i(e):t(s)}))}));return e.timeout?((e,t=1e3)=>Promise.race([e,new Promise(((e,s)=>{setTimeout((()=>{s(new Error("请求超时"))}),t)}))]))(i,e.timeout):i}get(e){return this.send.call(this.env,e)}post(e){return this.send.call(this.env,e,"POST")}}return new class{constructor(e,t){this.logLevels={debug:0,info:1,warn:2,error:3},this.logLevelPrefixs={debug:"[DEBUG] ",info:"[INFO] ",warn:"[WARN] ",error:"[ERROR] "},this.logLevel="info",this.name=e,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,t),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(e,t=null){try{return JSON.parse(e)}catch{return t}}toStr(e,t=null,...s){try{return JSON.stringify(e,...s)}catch{return t}}getjson(e,t){let s=t;if(this.getdata(e))try{s=JSON.parse(this.getdata(e))}catch{}return s}setjson(e,t){try{return this.setdata(JSON.stringify(e),t)}catch{return!1}}getScript(e){return new Promise((t=>{this.get({url:e},((e,s,i)=>t(i)))}))}runScript(e,t){return new Promise((s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let o=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");o=o?1*o:20,o=t&&t.timeout?t.timeout:o;const[r,a]=i.split("@"),n={url:`http://${a}/v1/scripting/evaluate`,body:{script_text:e,mock_type:"cron",timeout:o},headers:{"X-Key":r,Accept:"*/*"},policy:"DIRECT",timeout:o};this.post(n,((e,t,i)=>s(i)))})).catch((e=>this.logErr(e)))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const e=this.path.resolve(this.dataFile),t=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(e),i=!s&&this.fs.existsSync(t);if(!s&&!i)return{};{const i=s?e:t;try{return JSON.parse(this.fs.readFileSync(i))}catch(e){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const e=this.path.resolve(this.dataFile),t=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(e),i=!s&&this.fs.existsSync(t),o=JSON.stringify(this.data);s?this.fs.writeFileSync(e,o):i?this.fs.writeFileSync(t,o):this.fs.writeFileSync(e,o)}}lodash_get(e,t,s){const i=t.replace(/\[(\d+)\]/g,".$1").split(".");let o=e;for(const e of i)if(o=Object(o)[e],void 0===o)return s;return o}lodash_set(e,t,s){return Object(e)!==e||(Array.isArray(t)||(t=t.toString().match(/[^.[\]]+/g)||[]),t.slice(0,-1).reduce(((e,s,i)=>Object(e[s])===e[s]?e[s]:e[s]=Math.abs(t[i+1])>>0==+t[i+1]?[]:{}),e)[t[t.length-1]]=s),e}getdata(e){let t=this.getval(e);if(/^@/.test(e)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(e),o=s?this.getval(s):"";if(o)try{const e=JSON.parse(o);t=e?this.lodash_get(e,i,""):t}catch(e){t=""}}return t}setdata(e,t){let s=!1;if(/^@/.test(t)){const[,i,o]=/^@(.*?)\.(.*?)$/.exec(t),r=this.getval(i),a=i?"null"===r?null:r||"{}":"{}";try{const t=JSON.parse(a);this.lodash_set(t,o,e),s=this.setval(JSON.stringify(t),i)}catch(t){const r={};this.lodash_set(r,o,e),s=this.setval(JSON.stringify(r),i)}}else s=this.setval(e,t);return s}getval(e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(e);case"Quantumult X":return $prefs.valueForKey(e);case"Node.js":return this.data=this.loaddata(),this.data[e];default:return this.data&&this.data[e]||null}}setval(e,t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(e,t);case"Quantumult X":return $prefs.setValueForKey(e,t);case"Node.js":return this.data=this.loaddata(),this.data[t]=e,this.writedata(),!0;default:return this.data&&this.data[t]||null}}initGotEnv(e){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,e&&(e.headers=e.headers?e.headers:{},e&&(e.headers=e.headers?e.headers:{},void 0===e.headers.cookie&&void 0===e.headers.Cookie&&void 0===e.cookieJar&&(e.cookieJar=this.ckjar)))}get(e,t=(()=>{})){switch(e.headers&&(delete e.headers["Content-Type"],delete e.headers["Content-Length"],delete e.headers["content-type"],delete e.headers["content-length"]),e.params&&(e.url+="?"+this.queryStr(e.params)),void 0===e.followRedirect||e.followRedirect||((this.isSurge()||this.isLoon())&&(e["auto-redirect"]=!1),this.isQuanX()&&(e.opts?e.opts.redirection=!1:e.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(e.headers=e.headers||{},Object.assign(e.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(e,((e,s,i)=>{!e&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),t(e,s,i)}));break;case"Quantumult X":this.isNeedRewrite&&(e.opts=e.opts||{},Object.assign(e.opts,{hints:!1})),$task.fetch(e).then((e=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=e;t(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)}),(e=>t(e&&e.error||"UndefinedError")));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(e),this.got(e).on("redirect",((e,t)=>{try{if(e.headers["set-cookie"]){const s=e.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),t.cookieJar=this.ckjar}}catch(e){this.logErr(e)}})).then((e=>{const{statusCode:i,statusCode:o,headers:r,rawBody:a}=e,n=s.decode(a,this.encoding);t(null,{status:i,statusCode:o,headers:r,rawBody:a,body:n},n)}),(e=>{const{message:i,response:o}=e;t(i,o,o&&s.decode(o.rawBody,this.encoding))}));break}}post(e,t=(()=>{})){const s=e.method?e.method.toLocaleLowerCase():"post";switch(e.body&&e.headers&&!e.headers["Content-Type"]&&!e.headers["content-type"]&&(e.headers["content-type"]="application/x-www-form-urlencoded"),e.headers&&(delete e.headers["Content-Length"],delete e.headers["content-length"]),void 0===e.followRedirect||e.followRedirect||((this.isSurge()||this.isLoon())&&(e["auto-redirect"]=!1),this.isQuanX()&&(e.opts?e.opts.redirection=!1:e.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(e.headers=e.headers||{},Object.assign(e.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](e,((e,s,i)=>{!e&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),t(e,s,i)}));break;case"Quantumult X":e.method=s,this.isNeedRewrite&&(e.opts=e.opts||{},Object.assign(e.opts,{hints:!1})),$task.fetch(e).then((e=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=e;t(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)}),(e=>t(e&&e.error||"UndefinedError")));break;case"Node.js":let i=require("iconv-lite");this.initGotEnv(e);const{url:o,...r}=e;this.got[s](o,r).then((e=>{const{statusCode:s,statusCode:o,headers:r,rawBody:a}=e,n=i.decode(a,this.encoding);t(null,{status:s,statusCode:o,headers:r,rawBody:a,body:n},n)}),(e=>{const{message:s,response:o}=e;t(s,o,o&&i.decode(o.rawBody,this.encoding))}));break}}time(e,t=null){const s=t?new Date(t):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(e)&&(e=e.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let t in i)new RegExp("("+t+")").test(e)&&(e=e.replace(RegExp.$1,1==RegExp.$1.length?i[t]:("00"+i[t]).substr((""+i[t]).length)));return e}queryStr(e){let t="";for(const s in e){let i=e[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),t+=`${s}=${i}&`)}return t=t.substring(0,t.length-1),t}msg(t=e,s="",i="",o={}){const r=e=>{const{$open:t,$copy:s,$media:i,$mediaMime:o}=e;switch(typeof e){case void 0:return e;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:e};case"Loon":case"Shadowrocket":return e;case"Quantumult X":return{"open-url":e};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{const r={};let a=e.openUrl||e.url||e["open-url"]||t;a&&Object.assign(r,{action:"open-url",url:a});let n=e["update-pasteboard"]||e.updatePasteboard||s;n&&Object.assign(r,{action:"clipboard",text:n});let h=e.mediaUrl||e["media-url"]||i;if(h){let e,t;if(h.startsWith("http"));else if(h.startsWith("data:")){const[s]=h.split(";"),[,i]=h.split(",");e=i,t=s.replace("data:","")}else{e=h,t=(e=>{const t={JVBERi0:"application/pdf",R0lGODdh:"image/gif",R0lGODlh:"image/gif",iVBORw0KGgo:"image/png","/9j/":"image/jpg"};for(var s in t)if(0===e.indexOf(s))return t[s];return null})(h)}Object.assign(r,{"media-url":h,"media-base64":e,"media-base64-mime":o??t})}return Object.assign(r,{"auto-dismiss":e["auto-dismiss"],sound:e.sound}),r}case"Loon":{const s={};let o=e.openUrl||e.url||e["open-url"]||t;o&&Object.assign(s,{openUrl:o});let r=e.mediaUrl||e["media-url"]||i;return r&&Object.assign(s,{mediaUrl:r}),console.log(JSON.stringify(s)),s}case"Quantumult X":{const o={};let r=e["open-url"]||e.url||e.openUrl||t;r&&Object.assign(o,{"open-url":r});let a=e.mediaUrl||e["media-url"]||i;a&&Object.assign(o,{"media-url":a});let n=e["update-pasteboard"]||e.updatePasteboard||s;return n&&Object.assign(o,{"update-pasteboard":n}),console.log(JSON.stringify(o)),o}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(t,s,i,r(o));break;case"Quantumult X":$notify(t,s,i,r(o));break;case"Node.js":break}if(!this.isMuteLog){let e=["","==============📣系统通知📣=============="];e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n")),this.logs=this.logs.concat(e)}}debug(...e){this.logLevels[this.logLevel]<=this.logLevels.debug&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.debug}${e.map((e=>e??String(e))).join(this.logSeparator)}`))}info(...e){this.logLevels[this.logLevel]<=this.logLevels.info&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.info}${e.map((e=>e??String(e))).join(this.logSeparator)}`))}warn(...e){this.logLevels[this.logLevel]<=this.logLevels.warn&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.warn}${e.map((e=>e??String(e))).join(this.logSeparator)}`))}error(...e){this.logLevels[this.logLevel]<=this.logLevels.error&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.error}${e.map((e=>e??String(e))).join(this.logSeparator)}`))}log(...e){e.length>0&&(this.logs=[...this.logs,...e]),console.log(e.map((e=>e??String(e))).join(this.logSeparator))}logErr(e,t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,t,e);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,t,void 0!==e.message?e.message:e,e.stack);break}}wait(e){return new Promise((t=>setTimeout(t,e)))}done(e={}){const t=((new Date).getTime()-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${t} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(e);break;case"Node.js":process.exit(1)}}}(e,t)} \ No newline at end of file diff --git a/v2ex/quanx/v2ex.cookie.js b/v2ex/quanx/v2ex.cookie.js index 5119d086c..057214fa9 100644 --- a/v2ex/quanx/v2ex.cookie.js +++ b/v2ex/quanx/v2ex.cookie.js @@ -1,6 +1,6 @@ const cookieName = 'V2EX' const cookieKey = 'chavy_cookie_v2ex' -const cookieVal = $request.headers['Cookie'] +const cookieVal = $request.headers['Cookie'] || $request.headers['cookie'] if (cookieVal) { let cookie = $prefs.setValueForKey(cookieVal, cookieKey) diff --git a/v2ex/quanx/v2ex.js b/v2ex/quanx/v2ex.js index 3f35cb666..7494795e6 100644 --- a/v2ex/quanx/v2ex.js +++ b/v2ex/quanx/v2ex.js @@ -18,6 +18,7 @@ function sign() { let detail = `今天已经签过了` console.log(`${title}, ${subTitle}, ${detail}`) $notify(title, subTitle, detail) + $done() } else { signMission(data.match(/<input[^>]*\/mission\/daily\/redeem\?once=(\d+)[^>]*>/)[1]) } @@ -45,6 +46,7 @@ function signMission(code) { console.log(`签到失败: ${cookieName}, data: ${data}`) $notify(title, subTitle, detail) } + $done() }) } diff --git a/v2ex/v2ex.cookie.js b/v2ex/v2ex.cookie.js index 39c1bb7fd..2b7ce6ac8 100644 --- a/v2ex/v2ex.cookie.js +++ b/v2ex/v2ex.cookie.js @@ -1,6 +1,6 @@ const cookieName = 'V2EX' const cookieKey = 'chavy_cookie_v2ex' -const cookieVal = $request.headers['Cookie'] +const cookieVal = $request.headers['Cookie'] || $request.headers['cookie'] if (cookieVal) { let cookie = $persistentStore.write(cookieVal, cookieKey) diff --git a/videoqq/README.md b/videoqq/README.md index db0eab570..9e707c969 100644 --- a/videoqq/README.md +++ b/videoqq/README.md @@ -1,4 +1,4 @@ -# 腾讯视频 (网页) +# 腾讯视频 > 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 @@ -6,15 +6,20 @@ > 2020.2.17 增加移动端网页版签到 (请仔细阅读移动端网页版的操作说明) (MITM 新增一条、获取 Cookie 脚本新增一条、两脚本需要更新) +> 2020.3.2 \[Beta\] 增加移动端抽奖脚本 (部分用户移动端签到时会提示: 无匹配的签到活动, 那就是移动端签不上了) + +> 2020.3.6 移动端每个用户仅可签两周,签到活动结果后,移动端签到不再弹通知 + +> 2020.3.16 移动端签到活动已结束 + ## 配置 (Surge) ```properties [MITM] -*.video.qq.com, v.qq.com +*.video.qq.com [Script] http-request ^https:\/\/access.video.qq.com\/user\/auth_refresh script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.cookie.js -http-request ^https?:\/\/v.qq.com\/x\/bu\/mobile_checkin script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.cookie.js cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/videoqq/videoqq.js ``` @@ -22,11 +27,10 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr ```properties [MITM] -*.video.qq.com, v.qq.com +*.video.qq.com [rewrite_local] ^https:\/\/access.video.qq.com\/user\/auth_refresh url script-request-header videoqq.cookie.js -^https?:\/\/v.qq.com\/x\/bu\/mobile_checkin url script-request-header videoqq.cookie.js [task_local] 1 0 * * * videoqq.js diff --git a/videoqq/videoqq.js b/videoqq/videoqq.js index 79c3ef1fa..d32efd6f9 100644 --- a/videoqq/videoqq.js +++ b/videoqq/videoqq.js @@ -1,163 +1,108 @@ -const cookieName = '腾讯视频' -const cookieKey = 'chavy_cookie_videoqq' -const authUrlKey = 'chavy_auth_url_videoqq' -const authHeaderKey = 'chavy_auth_header_videoqq' -const msignurlKey = 'chavy_msign_url_videoqq' -const msignheaderKey = 'chavy_msign_header_videoqq' const chavy = init() -let cookieVal = chavy.getdata(cookieKey) -const authUrlVal = chavy.getdata(authUrlKey) -const authHeaderVal = chavy.getdata(authHeaderKey) -const msignurlVal = chavy.getdata(msignurlKey) -const msignheaderVal = chavy.getdata(msignheaderKey) +const cookieName = '腾讯视频' +const KEY_signcookie = 'chavy_cookie_videoqq' +const KEY_loginurl = 'chavy_auth_url_videoqq' +const KEY_loginheader = 'chavy_auth_header_videoqq' +const KEY_mh5signurl = 'chavy_msign_url_videoqq' +const KEY_mh5signheader = 'chavy_msign_header_videoqq' + const signinfo = {} +let VAL_signcookie = chavy.getdata(KEY_signcookie) +let VAL_loginurl = chavy.getdata(KEY_loginurl) +let VAL_loginheader = chavy.getdata(KEY_loginheader) +let VAL_mh5signurl = chavy.getdata(KEY_mh5signurl) +let VAL_mh5signheader = chavy.getdata(KEY_mh5signheader) -sign() +;(sign = async () => { + chavy.log(`🔔 ${cookieName}`) + await login() + await signapp() + await getexp() + showmsg() +})() +.catch((e) => chavy.log(`❌ ${cookieName} 签到失败: ${e}`)) +.finally(() => chavy.done()) -function sign() { - if (authUrlVal && authHeaderVal) { - const url = { url: authUrlVal, headers: JSON.parse(authHeaderVal) } +function login() { + return new Promise((resolve, reject) => { + const url = { url: VAL_loginurl, headers: JSON.parse(VAL_loginheader) } chavy.get(url, (error, response, data) => { - // chavy.log(`${cookieName}, auth_refresh - data: ${data}`) - // chavy.log(`${cookieName}, auth_refresh - old-cookie: ${cookieVal}`) - // chavy.log(`${cookieName}, auth_refresh - set-cookie: ${response.headers['Set-Cookie']}`) - const result = JSON.parse(data.match(/\(([^\)]*)\)/)[1]) - let respcookie = response.headers['Set-Cookie'] - // chavy.log(`${cookieName}, auth_refresh - Expires: ${respcookie.indexOf('Expires=') >= 0 ? respcookie.match(/Expires=(.*?)GMT/)[1] : '无'}`) - respcookie = respcookie.replace(/Expires=(.*?)GMT,? ?/g, '') - respcookie = respcookie.replace(/Path=(.*?); ?/g, '') - respcookie = respcookie.replace(/Domain=(.*?); ?/g, '') - respcookie = respcookie.replace(/;$/g, '') - if (result.errcode == 0) { - let setcookies = [] - for (setcookie of respcookie.split(';')) { - const setcookieKey = setcookie.split('=')[0] - const setcookieVal = setcookie.split('=')[1] - if (setcookieKey && cookieVal.indexOf(setcookieKey) >= 0) { - cookieVal = cookieVal.replace(new RegExp(`${setcookieKey}=[^;]*`), `${setcookieKey}=${setcookieVal}`) - } else { - cookieVal += `; ${setcookieKey}=${setcookieVal}` - } - setcookies.push({ key: setcookieKey, val: setcookieVal }) - // chavy.log(`${cookieName}, auth_refresh - set-cookie: ${setcookieKey} = ${setcookieVal}`) - } - for (resultcookie in result) { - if (cookieVal.indexOf(resultcookie) >= 0) { - cookieVal = cookieVal.replace(new RegExp(`${resultcookie}=[^;]*`, 'g'), `${resultcookie}=${result[resultcookie]}`) - setcookies.push({ key: resultcookie, val: result[resultcookie] }) - // chavy.log(`${cookieName}, auth_refresh - ret-cookie: ${resultcookie} = ${result[resultcookie]}`) - } - } - // chavy.log(`${cookieName}, auth_refresh - new-cookie: ${cookieVal}`) - // chavy.log(`${cookieName}, auth_refresh - setcookies: ${JSON.stringify(setcookies)}`) - chavy.setdata(cookieVal, cookieKey) - signapp() - signmobile(setcookies) - chavy.done() + try { + resolve() + } catch (e) { + chavy.msg(cookieName, `签到结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} login - 登录失败: ${e}`) + chavy.log(`❌ ${cookieName} login - response: ${JSON.stringify(response)}`) + resolve() } }) - } else { - signapp() - } + }) } -function refreshSetCookie() {} - function signapp() { - const timestamp = Math.round(new Date().getTime() / 1000).toString() - let url = { url: `https://vip.video.qq.com/fcgi-bin/comm_cgi?name=hierarchical_task_system&cmd=2&_=${timestamp}`, headers: { Cookie: cookieVal } } - url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' - chavy.get(url, (error, response, data) => { - chavy.log(`${cookieName}, data: ${data}`) - let result = JSON.parse(data.match(/QZOutputJson=\(([^\)]*)\)/)[1]) - const title = `${cookieName}` - let subTitle = '' - let detail = '' - if (result.ret == 0) { - getexp(result) - } else if (result.ret == -10006) { - subTitle = '签到结果: 失败' - detail = `原因: 未登录, 说明: ${result.msg}` - chavy.msg(title, subTitle, detail) - } else if (result.ret == -10019) { - subTitle = '签到结果: 失败' - detail = `原因: 非VIP会员, 说明: ${result.msg}` - chavy.msg(title, subTitle, detail) - } else { - subTitle = '签到结果: 未知' - detail = `编码: ${result.ret}, 说明: ${result.msg}` - chavy.msg(title, subTitle, detail) - } + return new Promise((resolve, reject) => { + const timestamp = Math.round(new Date().getTime() / 1000).toString() + const VAL_signurl = `https://vip.video.qq.com/fcgi-bin/comm_cgi?name=hierarchical_task_checkin&cmd=2&_=${timestamp}` + let url = { url: VAL_signurl, headers: {} } + url.headers['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' + chavy.get(url, (error, response, data) => { + try { + signinfo.signapp = JSON.parse(data.match(/\((.*)\);/)[1]) + resolve() + } catch (e) { + chavy.msg(cookieName, `签到结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} signapp - 签到失败: ${e}`) + chavy.log(`❌ ${cookieName} signapp - response: ${JSON.stringify(response)}`) + resolve() + } + }) }) - // chavy.done() } -function signmobile(cookies) { - if (msignheaderVal) { - let msignheaderObj = JSON.parse(msignheaderVal) - let msignCookies = msignheaderObj.Cookie - // chavy.log(`${cookieName} updatemobile old-cookie: ${msignCookies}`) - for (c of cookies) { - if (msignCookies.indexOf(c.key) >= 0) { - msignCookies = msignCookies.replace(new RegExp(`${c.key}=[^;]*`, 'g'), `${c.key}=${c.val}`) - } - } - // chavy.log(`${cookieName} updatemobile new-cookie: ${msignCookies}`) - msignheaderObj.Cookie = msignCookies - - const url = { url: msignurlVal, headers: msignheaderObj } +function getexp() { + return new Promise((resolve, reject) => { + const timestamp = Math.round(new Date().getTime() / 1000).toString() + const VAL_getexpurl = `https://vip.video.qq.com/fcgi-bin/comm_cgi?name=spp_vscore_user_mashup&type=1&_=${timestamp}` + let url = { url: VAL_getexpurl, headers: {} } + url.headers['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' chavy.get(url, (error, response, data) => { - const dmatch = data.match(/window\.__STATE__=(.*?)<\/script>/) - let result = {} - result.msg = '未知' - result.ret = -9999 - if (dmatch) { - try { - result = JSON.parse(dmatch[1]).payloads.execCheck - } catch (e) { - chavy.log(`${cookieName} catch - error: ${e}`) - } + try { + signinfo.expinfo = JSON.parse(data.match(/\((.*)\);/)[1]) + resolve() + } catch (e) { + chavy.msg(cookieName, `签到结果: 失败`, `说明: ${e}`) + chavy.log(`❌ ${cookieName} getexp - 签到失败: ${e}`) + chavy.log(`❌ ${cookieName} getexp - response: ${JSON.stringify(response)}`) + resolve() } - const title = `${cookieName} (移动端)` - let subtitle = `` - let detail = `` - if (result.ret == -9999) { - // chavy.log(`${cookieName} updatemobile data: ${data}`) - subtitle = `签到结果: 失败` - detail = `说明: 未知` - } else { - if (result.ret == 0) { - subtitle = `签到结果: 成功` - if (result.data && result.data.show_text_1) detail = `说明: ${result.data.show_text_1}` - else detail = `说明: ${result.msg}` - } else if (result.ret == -2021) { - subtitle = `签到结果: 成功(重复签到)` - } - } - chavy.msg(title, subtitle, detail) }) - } + }) } -function getexp(signresult) { - const timestamp = Math.round(new Date().getTime() / 1000).toString() - let url = { url: `https://vip.video.qq.com/fcgi-bin/comm_cgi?name=spp_PropertyNum&cmd=1&growth_value=1&otype=json&_=${timestamp}`, headers: { Cookie: cookieVal } } - url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' - chavy.get(url, (error, response, data) => { - chavy.log(`${cookieName}, data: ${data}`) - let result = JSON.parse(data.match(/QZOutputJson=\(([^\)]*)\)/)[1]) - const title = `${cookieName}` - let subTitle = '' - let detail = '' - if (signresult.checkin_score) { +function showmsg() { + if (signinfo.signapp) { + let subTitle, detail + if (signinfo.signapp.ret == 0) { subTitle = '签到结果: 成功' - detail = `V力值: ${result.GrowthValue.num} (+${signresult.checkin_score}), 观影券: ${result.MovieTicket.num}, 赠片资格: ${result.GiveMovie.num}` + if (signinfo.expinfo) { + subTitle += ! +Number(signinfo.signapp.checkin_score) ? ' (重复签到)' : '' + detail = `V力值: ${signinfo.expinfo.lscore_info.score} (+${signinfo.signapp.checkin_score}), 积分: ${signinfo.expinfo.cscore_info.vip_score_total}` + } + } else if (signinfo.signapp.ret == -10006) { + subTitle = '签到结果: 失败' + detail = `原因: 未登录, 说明: ${signinfo.signapp.msg}` + } else if (signinfo.signapp.ret == -10019) { + subTitle = '签到结果: 失败' + detail = `原因: 非会员, 说明: ${signinfo.signapp.msg}` } else { - subTitle = '签到结果: 成功 (重复签到)' - detail = `V力值: ${result.GrowthValue.num}, 观影券: ${result.MovieTicket.num}, 赠片资格: ${result.GiveMovie.num}` + subTitle = '签到结果: 未知' + detail = `编码: ${signinfo.signapp.ret}, 说明: ${signinfo.signapp.msg}` } - chavy.msg(title, subTitle, detail) - }) + chavy.msg(cookieName, subTitle, detail) + chavy.log(subTitle) + chavy.log(detail) + } } function init() { diff --git a/wanda/wanda.cookie.js b/wanda/wanda.cookie.js new file mode 100644 index 000000000..3ac7bf7e1 --- /dev/null +++ b/wanda/wanda.cookie.js @@ -0,0 +1,38 @@ +/** + * + * hostname = user-api-prd-mx.wandafilm.com + * + * # Surge + * Rewrite: wanda = type=http-request,pattern=^https:\/\/user-api-prd-mx\.wandafilm\.com,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wanda/wanda.cookie.js,debug=true + * Tasks: wanda-签到 = type=cron,cronexp=10 0 * * *,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wanda/wanda.js,wake-system=true + * + * # QuanX + * ^https:\/\/user-api-prd-mx\.wandafilm\.com url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/wanda/wanda.cookie.js + * 10 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/wanda/wanda.js, tag=wanda-签到 + * + * # Loon + * http-request ^https:\/\/user-api-prd-mx\.wandafilm\.com script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wanda/wanda.cookie.js, tag=万达电影 + * cron "10 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wanda/wanda.js + * + * # 获取方式:进入签到页面获取,网页端:https://act-m.wandacinemas.com/2005/17621a8caacc4d190dadd/ + */ + +const $ = new Env('万达影城') +$._mi_ = 'senku_wanda_mi_' + +!(async () => { + const session = {} + session.url = $request.url + session.headers = JSON.parse($request.headers['MX-API'])['_mi_'] + if (session.headers&&$.setdata(session.headers, $._mi_)) { + $.subt = `获取会话: 成功! (${$._mi_})` + } else { + $.subt = `获取会话: 失败! (${$._mi_})` + } + $.msg($.name, $.subt, $.desc) +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/wanda/wanda.js b/wanda/wanda.js new file mode 100644 index 000000000..66f44c108 --- /dev/null +++ b/wanda/wanda.js @@ -0,0 +1,243 @@ +const $ = new Env('万达电影') +$._mi_ = 'senku_wanda_mi_' +$.desc = [] +$.signCode = '134146532' +$.questionCode = '15884027' +const date = tTime(new Date().getTime()) + +function getKey(){ + const ts = new Date().getTime() + const key = 'Wanda1_3B3AA12B0145E1982F282BEDD8A3305B89A9811280C0B8CC3A6A60D81022E4903'+ts + return {'key':key,'ts':ts} +} +const mx_api = { + "ver":"v1.0.0", + "sCode":"Wanda", + "_mi_":`${$.getdata($._mi_)}`, + "width":1280, + "json":true, + "cCode":"1_3", + "check":'', + "ts":0, + "heigth":720, + "appId":"3" +} + +!(async () => { + await sign() + await signRecord() + // await question_() + // await question() + // await answer() + // await drawprize_ans() + // await drawprize_ans() + if ($.signRecord.data.remainMedal >= 50 ) { + await lottery() + } + await showmsg() + })() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + + + +function sign() { + return new Promise((resolve) => { + const signVal = getKey()['key'] + '/activityWholeSign/wholeSignUp.apiactivityCode='+$.signCode+'&signDate='+date + mx_api['ts'] = getKey()['ts'] + mx_api['check'] = hex_md5(signVal) + const url = { + url:'https://activity-api-mx.wandafilm.com/activityWholeSign/wholeSignUp.api', + headers:{ + 'MX-API':JSON.stringify(mx_api), + }, + body : 'activityCode='+$.signCode+'&signDate=' + date + } + $.post(url, (err, resp, data) => { + try { + $.sign = JSON.parse(data) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function signRecord() { + return new Promise((resolve) => { + const signRecordVal = getKey()['key']+'/activityWholeSign/getSignRecord.apiactivityCode='+$.signCode + mx_api['ts'] = getKey()['ts'] + mx_api['check'] = hex_md5(signRecordVal) + const url = { + url:'https://activity-api-mx.wandafilm.com/activityWholeSign/getSignRecord.api', + headers:{ + 'MX-API':JSON.stringify(mx_api), + }, + body : 'activityCode='+$.signCode + } + $.post(url, (err, resp, data) => { + try { + $.signRecord = JSON.parse(data) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function lottery() { + return new Promise((resolve) => { + const signVal = getKey()['key'] + '/activityWholeSign/prize/lottery.apiactivityCode='+$.signCode+'&vcode=&requestId=' + mx_api['ts'] = getKey()['ts'] + mx_api['check'] = hex_md5(signVal) + const url = { + url:'https://activity-api-mx.wandafilm.com/activityWholeSign/prize/lottery.api', + headers:{ + 'MX-API':JSON.stringify(mx_api), + }, + body : 'activityCode='+$.signCode+'&vcode=&requestId=' + } + $.post(url, (err, resp, data) => { + try { + $.lottery = JSON.parse(data) + console.log(data) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function question_() { + return new Promise((resolve) => { + const questionVal = getKey()['key']+'/question/qustion/strength.apiactivityCode='+$.questionCode + mx_api['ts'] = getKey()['ts'] + mx_api['check'] = hex_md5(questionVal) + const url = { + url:'https://activity-api-mx.wandafilm.com/question/qustion/strength.api', + headers:{ + 'MX-API':JSON.stringify(mx_api), + }, + body : 'activityCode='+$.questionCode + } + $.post(url, (err, resp, data) => { + try { + $.log(`尝试性报名答题`) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +// 获取题目答案 +function question() { + return new Promise((resolve) => { + const questionVal = getKey()['key']+'/question/question_list.apiactivityCode='+$.questionCode + mx_api['ts'] = getKey()['ts'] + mx_api['check'] = hex_md5(questionVal) + const url = { + url:'https://activity-api-mx.wandafilm.com/question/question_list.api', + headers:{ + 'MX-API':JSON.stringify(mx_api), + }, + body : 'activityCode='+$.questionCode + } + $.post(url, (err, resp, data) => { + try { + const res = JSON.parse(data) + $.answer = res.data.questionList[0].movie.nameCN + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +// 答题 +function answer() { + return new Promise((resolve) => { + const answerVal = getKey()['key'] + '/question/qustion/answer.apiactivityCode='+$.questionCode+'&answer=%7b%221%22%3a%22'+escape(`${$.answer}`).toLowerCase()+'%22%7d' + mx_api['ts'] = getKey()['ts'] + mx_api['check'] = hex_md5(answerVal) + const url = { + url:'https://activity-api-mx.wandafilm.com/question/qustion/answer.api', + headers:{ + 'MX-API':JSON.stringify(mx_api), + }, + body : 'activityCode='+$.questionCode+'&answer=%7B%221%22%3A%22'+encodeURI(`${$.answer}`) + '%22%7D' + } + $.post(url, (err, resp, data) => { + try { + $.answer = JSON.parse(data) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +// 答题后抽奖 +function drawprize_ans() { + return new Promise((resolve) => { + const drawprizeVal = getKey()['key']+'/question/prize/lottery.apiactivityCode='+$.questionCode + mx_api['ts'] = getKey()['ts'] + mx_api['check'] = hex_md5(drawprizeVal) + const url = { + url:'https://activity-api-mx.wandafilm.com/question/prize/lottery.api', + headers:{ + 'MX-API':JSON.stringify(mx_api), + }, + body : 'activityCode='+$.questionCode + } + $.post(url, (err, resp, data) => { + try { + const res = JSON.parse(data) + $.desc.push(`答题抽奖:${res.data.prize.prizeName}`) + } catch (e) { + $.logErr(e, resp) + } finally { + resolve() + } + }) + }) +} + +function showmsg() { + return new Promise((resolve) => { + $.subt = `签到:${$.sign.code == 1 ? `成功` : $.sign.msg}` + + if ($.signRecord.code == 1) { + const totalMedal = $.signRecord.data.totalMedal + const remainMedal = $.signRecord.data.remainMedal + $.desc.push(`总计获得${totalMedal}能量,剩余可用${remainMedal}能量`) + } + //$.subt += ` 答题详情:${$.answer.code == 1 ? `答案:${$.answer.data.answer},获得:${$.answer.data.remainChance}次抽奖`:$.answer.msg}` + $.lottery ? $.desc.push(`签到抽奖:${$.lottery.data.prize.prizeName}`) : `` + $.msg($.name, $.subt, $.desc.join('\n')) + resolve() + }) +} + +function tTime(timestamp) { + const date = new Date(timestamp) + const Y = date.getFullYear() + '-' + const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-' + const D = (date.getDate() + 1 < 10 ? '0' + date.getDate() : date.getDate()) + return Y + M + D +} +function hex_md5(r){return rstr2hex(rstr_md5(str2rstr_utf8(r)))}function b64_md5(r){return rstr2b64(rstr_md5(str2rstr_utf8(r)))}function any_md5(r,t){return rstr2any(rstr_md5(str2rstr_utf8(r)),t)}function hex_hmac_md5(r,t){return rstr2hex(rstr_hmac_md5(str2rstr_utf8(r),str2rstr_utf8(t)))}function b64_hmac_md5(r,t){return rstr2b64(rstr_hmac_md5(str2rstr_utf8(r),str2rstr_utf8(t)))}function any_hmac_md5(r,t,d){return rstr2any(rstr_hmac_md5(str2rstr_utf8(r),str2rstr_utf8(t)),d)}function md5_vm_test(){return"900150983cd24fb0d6963f7d28e17f72"==hex_md5("abc").toLowerCase()}function rstr_md5(r){return binl2rstr(binl_md5(rstr2binl(r),8*r.length))}function rstr_hmac_md5(r,t){var d=rstr2binl(r);d.length>16&&(d=binl_md5(d,8*r.length));for(var n=Array(16),_=Array(16),m=0;m<16;m++)n[m]=909522486^d[m],_[m]=1549556828^d[m];var f=binl_md5(n.concat(rstr2binl(t)),512+8*t.length);return binl2rstr(binl_md5(_.concat(f),640))}function rstr2hex(r){for(var t,d=hexcase?"0123456789ABCDEF":"0123456789abcdef",n="",_=0;_<r.length;_++)t=r.charCodeAt(_),n+=d.charAt(t>>>4&15)+d.charAt(15&t);return n}function rstr2b64(r){for(var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",d="",n=r.length,_=0;_<n;_+=3)for(var m=r.charCodeAt(_)<<16|(_+1<n?r.charCodeAt(_+1)<<8:0)|(_+2<n?r.charCodeAt(_+2):0),f=0;f<4;f++)8*_+6*f>8*r.length?d+=b64pad:d+=t.charAt(m>>>6*(3-f)&63);return d}function rstr2any(r,t){var d,n,_,m,f,h=t.length,e=Array(Math.ceil(r.length/2));for(d=0;d<e.length;d++)e[d]=r.charCodeAt(2*d)<<8|r.charCodeAt(2*d+1);var a=Math.ceil(8*r.length/(Math.log(t.length)/Math.log(2))),i=Array(a);for(n=0;n<a;n++){for(f=Array(),m=0,d=0;d<e.length;d++)m=(m<<16)+e[d],_=Math.floor(m/h),m-=_*h,(f.length>0||_>0)&&(f[f.length]=_);i[n]=m,e=f}var o="";for(d=i.length-1;d>=0;d--)o+=t.charAt(i[d]);return o}function str2rstr_utf8(r){for(var t,d,n="",_=-1;++_<r.length;)t=r.charCodeAt(_),d=_+1<r.length?r.charCodeAt(_+1):0,55296<=t&&t<=56319&&56320<=d&&d<=57343&&(t=65536+((1023&t)<<10)+(1023&d),_++),t<=127?n+=String.fromCharCode(t):t<=2047?n+=String.fromCharCode(192|t>>>6&31,128|63&t):t<=65535?n+=String.fromCharCode(224|t>>>12&15,128|t>>>6&63,128|63&t):t<=2097151&&(n+=String.fromCharCode(240|t>>>18&7,128|t>>>12&63,128|t>>>6&63,128|63&t));return n}function str2rstr_utf16le(r){for(var t="",d=0;d<r.length;d++)t+=String.fromCharCode(255&r.charCodeAt(d),r.charCodeAt(d)>>>8&255);return t}function str2rstr_utf16be(r){for(var t="",d=0;d<r.length;d++)t+=String.fromCharCode(r.charCodeAt(d)>>>8&255,255&r.charCodeAt(d));return t}function rstr2binl(r){for(var t=Array(r.length>>2),d=0;d<t.length;d++)t[d]=0;for(d=0;d<8*r.length;d+=8)t[d>>5]|=(255&r.charCodeAt(d/8))<<d%32;return t}function binl2rstr(r){for(var t="",d=0;d<32*r.length;d+=8)t+=String.fromCharCode(r[d>>5]>>>d%32&255);return t}function binl_md5(r,t){r[t>>5]|=128<<t%32,r[14+(t+64>>>9<<4)]=t;for(var d=1732584193,n=-271733879,_=-1732584194,m=271733878,f=0;f<r.length;f+=16){var h=d,e=n,a=_,i=m;d=md5_ff(d,n,_,m,r[f+0],7,-680876936),m=md5_ff(m,d,n,_,r[f+1],12,-389564586),_=md5_ff(_,m,d,n,r[f+2],17,606105819),n=md5_ff(n,_,m,d,r[f+3],22,-1044525330),d=md5_ff(d,n,_,m,r[f+4],7,-176418897),m=md5_ff(m,d,n,_,r[f+5],12,1200080426),_=md5_ff(_,m,d,n,r[f+6],17,-1473231341),n=md5_ff(n,_,m,d,r[f+7],22,-45705983),d=md5_ff(d,n,_,m,r[f+8],7,1770035416),m=md5_ff(m,d,n,_,r[f+9],12,-1958414417),_=md5_ff(_,m,d,n,r[f+10],17,-42063),n=md5_ff(n,_,m,d,r[f+11],22,-1990404162),d=md5_ff(d,n,_,m,r[f+12],7,1804603682),m=md5_ff(m,d,n,_,r[f+13],12,-40341101),_=md5_ff(_,m,d,n,r[f+14],17,-1502002290),n=md5_ff(n,_,m,d,r[f+15],22,1236535329),d=md5_gg(d,n,_,m,r[f+1],5,-165796510),m=md5_gg(m,d,n,_,r[f+6],9,-1069501632),_=md5_gg(_,m,d,n,r[f+11],14,643717713),n=md5_gg(n,_,m,d,r[f+0],20,-373897302),d=md5_gg(d,n,_,m,r[f+5],5,-701558691),m=md5_gg(m,d,n,_,r[f+10],9,38016083),_=md5_gg(_,m,d,n,r[f+15],14,-660478335),n=md5_gg(n,_,m,d,r[f+4],20,-405537848),d=md5_gg(d,n,_,m,r[f+9],5,568446438),m=md5_gg(m,d,n,_,r[f+14],9,-1019803690),_=md5_gg(_,m,d,n,r[f+3],14,-187363961),n=md5_gg(n,_,m,d,r[f+8],20,1163531501),d=md5_gg(d,n,_,m,r[f+13],5,-1444681467),m=md5_gg(m,d,n,_,r[f+2],9,-51403784),_=md5_gg(_,m,d,n,r[f+7],14,1735328473),n=md5_gg(n,_,m,d,r[f+12],20,-1926607734),d=md5_hh(d,n,_,m,r[f+5],4,-378558),m=md5_hh(m,d,n,_,r[f+8],11,-2022574463),_=md5_hh(_,m,d,n,r[f+11],16,1839030562),n=md5_hh(n,_,m,d,r[f+14],23,-35309556),d=md5_hh(d,n,_,m,r[f+1],4,-1530992060),m=md5_hh(m,d,n,_,r[f+4],11,1272893353),_=md5_hh(_,m,d,n,r[f+7],16,-155497632),n=md5_hh(n,_,m,d,r[f+10],23,-1094730640),d=md5_hh(d,n,_,m,r[f+13],4,681279174),m=md5_hh(m,d,n,_,r[f+0],11,-358537222),_=md5_hh(_,m,d,n,r[f+3],16,-722521979),n=md5_hh(n,_,m,d,r[f+6],23,76029189),d=md5_hh(d,n,_,m,r[f+9],4,-640364487),m=md5_hh(m,d,n,_,r[f+12],11,-421815835),_=md5_hh(_,m,d,n,r[f+15],16,530742520),n=md5_hh(n,_,m,d,r[f+2],23,-995338651),d=md5_ii(d,n,_,m,r[f+0],6,-198630844),m=md5_ii(m,d,n,_,r[f+7],10,1126891415),_=md5_ii(_,m,d,n,r[f+14],15,-1416354905),n=md5_ii(n,_,m,d,r[f+5],21,-57434055),d=md5_ii(d,n,_,m,r[f+12],6,1700485571),m=md5_ii(m,d,n,_,r[f+3],10,-1894986606),_=md5_ii(_,m,d,n,r[f+10],15,-1051523),n=md5_ii(n,_,m,d,r[f+1],21,-2054922799),d=md5_ii(d,n,_,m,r[f+8],6,1873313359),m=md5_ii(m,d,n,_,r[f+15],10,-30611744),_=md5_ii(_,m,d,n,r[f+6],15,-1560198380),n=md5_ii(n,_,m,d,r[f+13],21,1309151649),d=md5_ii(d,n,_,m,r[f+4],6,-145523070),m=md5_ii(m,d,n,_,r[f+11],10,-1120210379),_=md5_ii(_,m,d,n,r[f+2],15,718787259),n=md5_ii(n,_,m,d,r[f+9],21,-343485551),d=safe_add(d,h),n=safe_add(n,e),_=safe_add(_,a),m=safe_add(m,i)}return Array(d,n,_,m)}function md5_cmn(r,t,d,n,_,m){return safe_add(bit_rol(safe_add(safe_add(t,r),safe_add(n,m)),_),d)}function md5_ff(r,t,d,n,_,m,f){return md5_cmn(t&d|~t&n,r,t,_,m,f)}function md5_gg(r,t,d,n,_,m,f){return md5_cmn(t&n|d&~n,r,t,_,m,f)}function md5_hh(r,t,d,n,_,m,f){return md5_cmn(t^d^n,r,t,_,m,f)}function md5_ii(r,t,d,n,_,m,f){return md5_cmn(d^(t|~n),r,t,_,m,f)}function safe_add(r,t){var d=(65535&r)+(65535&t),n=(r>>16)+(t>>16)+(d>>16);return n<<16|65535&d}function bit_rol(r,t){return r<<t|r>>>32-t}var hexcase=0,b64pad=""; +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/wps/README.md b/wps/README.md new file mode 100644 index 000000000..e42d6665f --- /dev/null +++ b/wps/README.md @@ -0,0 +1,101 @@ +# WPS + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> 2020.3.15 增加小程序签到 + +> 2020.6.10 1.小程序打卡可以自动答题; 2.自动做满邀请 10 个用户任务 (次日打卡送 10 天会员). 感谢 @Wenmoux 提供的邀请人列表 +> 注意 1: 获取 Cookie 的正则有变动, 但不用重取 Cookie +> 注意 2: 把签到时间调整为 06:00 - 13:00 之间 + +> 2020.6.11 不需要单独从小程序获取 Cookie, 添加自动报名脚本 + +## 配置 (Surge) + +```properties +[MITM] +hostname = zt.wps.cn + +[Script] +http-request ^https:\/\/zt.wps.cn\/2018\/docer_check_in\/api\/act_list script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wps/wps.cookie.js +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wps/wps.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +hostname = 110.43.90.61, zt.wps.cn + +[rewrite_local] +^https:\/\/zt.wps.cn\/2018\/docer_check_in\/api\/act_list url script-request-header wps.cookie.js + +[task_local] +1 0 * * * wps.js +``` + +## 说明 + +1. 配置`[MITM]` + - Surge: zt.wps.cn + - QuanX: 110.43.90.61, zt.wps.cn +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`wps.cookie.js`和`wps.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP , 进入签到页面, 系统提示: `获取会话: 成功 (签到)` (不用手动签到) +4. 最后就可以把两条获取 Cookie 的脚本注释掉了 +5. 运行一次脚本, 如果提示重复签到, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) diff --git a/wps/wps.cookie.js b/wps/wps.cookie.js new file mode 100644 index 000000000..b8aa12576 --- /dev/null +++ b/wps/wps.cookie.js @@ -0,0 +1,22 @@ +const $ = new Env('WPS') + +!(async () => { + $.log('', `🔔 ${$.name}, 获取会话: 开始!`, '') + const VAL_url = $request.url + const VAL_headers = JSON.stringify($request.headers) + $.log('', `❕ ${$.name}`, `url: ${$request.url}`, `headers: ${JSON.stringify($request.headers)}`, '') + $.setdata(VAL_url, 'chavy_signhomeurl_wps') + $.setdata(VAL_headers, 'chavy_signhomeheader_wps') + $.subt = '获取会话: 成功!' +})() + .catch((e) => { + $.subt = '获取会话: 失败!' + $.desc = `原因: ${e}` + $.log(`❌ ${$.name}, 获取会话: 失败! 原因: ${e}!`) + }) + .finally(() => { + $.msg($.name, $.subt, $.desc), $.log('', `🔔 ${$.name}, 获取会话: 结束!`, ''), $.done() + }) + +// prettier-ignore +function Env(s){this.name=s,this.data=null,this.logs=[],this.isSurge=(()=>"undefined"!=typeof $httpClient),this.isQuanX=(()=>"undefined"!=typeof $task),this.isNode=(()=>"undefined"!=typeof module&&!!module.exports),this.log=((...s)=>{this.logs=[...this.logs,...s],s?console.log(s.join("\n")):console.log(this.logs.join("\n"))}),this.msg=((s=this.name,t="",i="")=>{this.isSurge()&&$notification.post(s,t,i),this.isQuanX()&&$notify(s,t,i);const e=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];s&&e.push(s),t&&e.push(t),i&&e.push(i),console.log(e.join("\n"))}),this.getdata=(s=>{if(this.isSurge())return $persistentStore.read(s);if(this.isQuanX())return $prefs.valueForKey(s);if(this.isNode()){const t="box.dat";return this.fs=this.fs?this.fs:require("fs"),this.fs.existsSync(t)?(this.data=JSON.parse(this.fs.readFileSync(t)),this.data[s]):null}}),this.setdata=((s,t)=>{if(this.isSurge())return $persistentStore.write(s,t);if(this.isQuanX())return $prefs.setValueForKey(s,t);if(this.isNode()){const i="box.dat";return this.fs=this.fs?this.fs:require("fs"),!!this.fs.existsSync(i)&&(this.data=JSON.parse(this.fs.readFileSync(i)),this.data[t]=s,this.fs.writeFileSync(i,JSON.stringify(this.data)),!0)}}),this.wait=((s,t=s)=>i=>setTimeout(()=>i(),Math.floor(Math.random()*(t-s+1)+s))),this.get=((s,t)=>this.send(s,"GET",t)),this.post=((s,t)=>this.send(s,"POST",t)),this.send=((s,t,i)=>{if(this.isSurge()){const e="POST"==t?$httpClient.post:$httpClient.get;e(s,(s,t,e)=>{t&&(t.body=e,t.statusCode=t.status),i(s,t,e)})}this.isQuanX()&&(s.method=t,$task.fetch(s).then(s=>{s.status=s.statusCode,i(null,s,s.body)},s=>i(s.error,s,s))),this.isNode()&&(this.request=this.request?this.request:require("request"),s.method=t,s.gzip=!0,this.request(s,(s,t,e)=>{t&&(t.status=t.statusCode),i(null,t,e)}))}),this.done=((s={})=>this.isNode()?null:$done(s))} diff --git a/wps/wps.js b/wps/wps.js new file mode 100644 index 000000000..c63ab4469 --- /dev/null +++ b/wps/wps.js @@ -0,0 +1,358 @@ +const $ = new Env('WPS') +$.VAL_signhomeurl = $.getdata('chavy_signhomeurl_wps') +$.VAL_signhomeheader = $.getdata('chavy_signhomeheader_wps') +$.CFG_inviteWaitTime = $.getdata('CFG_wps_inviteTime') * 1 || 2000 // 每次并发间隔时间 (毫秒) + +!(async () => { + await loginapp() + await signapp() + await getquestion() + await answerwx() + // await signwx() + // await signupwx() + await getUserInfo() + await invite() + await getSigninfo() + await getSignreward() + await showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// 登录 App +function loginapp() { + return new Promise((resove) => + $.get({ url: $.VAL_signhomeurl, headers: JSON.parse($.VAL_signhomeheader) }, (error, response, data) => { + try { + if (error) throw new Error(error) + $.homeinfo = JSON.parse(data) + if ($.homeinfo.result === 'ok') { + const headers = JSON.parse($.VAL_signhomeheader) + const [, sid] = /wps_sid=(.*?)(;|,|$)/.exec(headers.Cookie) + $.sid = sid + } + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + ) +} + +// 签到 App +function signapp() { + return new Promise((resove) => { + const url = { url: 'https://zt.wps.cn/2018/docer_check_in/api/checkin_today', headers: JSON.parse($.VAL_signhomeheader) } + url.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01' + url.headers['Accept-Encoding'] = 'gzip, deflate, br' + url.headers['Origin'] = 'https://zt.wps.cn' + url.headers['Connection'] = 'keep-alive' + url.headers['Host'] = 'zt.wps.cn' + url.headers['Referer'] = 'https://zt.wps.cn/static/2019/docer_check_in_ios/dist/?position=member_ios' + url.headers['Accept-Language'] = 'zh-cn' + url.headers['X-Requested-With'] = 'XMLHttpRequest' + $.post(url, (error, response, data) => { + try { + if (error) throw new Error(error) + $.signapp = JSON.parse(data) + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +// 获取并回答问题 +async function answerwx() { + const answers = [ + 'WPS会员全文检索', + '100G', + 'WPS会员数据恢复', + 'WPS会员PDF转doc', + 'WPS会员PDF转图片', + 'WPS图片转PDF插件', + '金山PDF转WORD', + 'WPS会员拍照转文字', + '使用WPS会员修复', + 'WPS全文检索功能', + '有,且无限次', + '文档修复' + ] + // 尝试最多 10 次回答问题 + for (let idx = 0; idx < 10; idx++) { + $.log(`问题: ${$.question.title}`) + if ($.question.multi_select === 0) { + const optionIdx = $.question.options.findIndex((option) => answers.includes(option)) + if (optionIdx === -1) { + $.log(`选项: ${$.question.options.join(', ')}`) + $.log('跳过! 原因: 找不到答案.', '') + await getquestion() + } else { + $.log(`选项: ${$.question.options.join(', ')}`) + $.log(`答案: ${optionIdx + 1}.${$.question.options[optionIdx]}`, '') + await answerquestion(optionIdx + 1) + if ($.answer.right) { + $.answer.optionIdx = optionIdx + $.log('回答正确!') + break + } else { + $.log(`回答错误! 详情: ${$.answer._raw.msg}`) + await getquestion() + continue + } + } + } else { + $.log(`选项: ${$.question.options.join(', ')}`) + $.log('跳过! 原因: 不做多选.', '') + await getquestion() + } + } +} + +// 获取问题 +function getquestion() { + return new Promise((resove) => { + const url = { url: 'https://zt.wps.cn/2018/clock_in/api/get_question?award=wps', headers: { sid: $.sid } } + $.get(url, (error, response, data) => { + try { + if (error) throw new Error(error) + $.question = JSON.parse(data).data + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +// 回答问题 +function answerquestion(optIdx) { + return new Promise((resove) => { + const body = `answer=${optIdx}` + const url = { url: 'https://zt.wps.cn/2018/clock_in/api/answer?member=wps', body, headers: { sid: $.sid } } + $.post(url, (error, response, data) => { + try { + if (error) throw new Error(error) + const _data = JSON.parse(data) + $.answer = { _raw: _data, right: _data.result === 'ok' } + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +function signwx() { + return new Promise((resove) => { + const url = { url: 'https://zt.wps.cn/2018/clock_in/api/clock_in?award=wps', headers: { sid: $.sid } } + $.get(url, (error, response, data) => { + try { + if (error) throw new Error(error) + const _data = JSON.parse(data) + $.signwx = { + _raw: _data, + isSuc: _data.result === 'ok' || (_data.result === 'error' && '已打卡' === _data.msg), + isRepeat: _data.result === 'error' && _data.msg === '已打卡', + isSignupNeed: _data.result === 'error' && _data.msg === '前一天未报名', + msg: _data.msg + } + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +function signupwx() { + if (!$.signwx.isSignupNeed) return null + return new Promise((resove) => { + const url = { url: 'http://zt.wps.cn/2018/clock_in/api/sign_up', headers: { sid: $.sid } } + $.get(url, (error, response, data) => { + try { + if (error) throw new Error(error) + const _data = JSON.parse(data) + $.signupwx = { + _raw: _data, + isSuc: _data.result === 'ok', + msg: _data.msg + } + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +// 获取签到详情 +function getSigninfo() { + return new Promise((resove) => { + const url = { url: 'https://zt.wps.cn/2018/docer_check_in/api/checkin_record', headers: JSON.parse($.VAL_signhomeheader) } + url.headers['Accept-Encoding'] = 'gzip, deflate, br' + url.headers['Connection'] = 'keep-alive' + url.headers['Referer'] = 'https://zt.wps.cn/static/2019/docer_check_in_ios/dist/?position=member_ios' + url.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01' + url.headers['Host'] = 'zt.wps.cn' + url.headers['Accept-Language'] = 'zh-cn' + url.headers['X-Requested-With'] = 'XMLHttpRequest' + $.get(url, (error, response, data) => { + try { + if (error) throw new Error(error) + $.signinfo = JSON.parse(data) + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +// 获取签到奖励 +function getSignreward() { + return new Promise((resove) => { + const url = { url: 'https://zt.wps.cn/2018/docer_check_in/api/reward_record', headers: JSON.parse($.VAL_signhomeheader) } + url.headers['Accept-Encoding'] = 'gzip, deflate, br' + url.headers['Connection'] = 'keep-alive' + url.headers['Referer'] = 'https://zt.wps.cn/static/2019/docer_check_in_ios/dist/?position=member_ios' + url.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01' + url.headers['Host'] = 'zt.wps.cn' + url.headers['Accept-Language'] = 'zh-cn' + url.headers['X-Requested-With'] = 'XMLHttpRequest' + $.get(url, (error, response, data) => { + try { + if (error) throw new Error(error) + $.signreward = JSON.parse(data) + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +// 获取用户信息 +function getUserInfo() { + return new Promise((resove) => { + const url = { url: 'https://vip.wps.cn/userinfo', headers: { sid: $.sid } } + $.get(url, (error, response, data) => { + try { + if (error) throw new Error(error) + $.userinfo = JSON.parse(data) + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) +} + +async function invite() { + const sids = [ + 'V02S2UBSfNlvEprMOn70qP3jHPDqiZU00a7ef4a800341c7c3b', + 'V02StVuaNcoKrZ3BuvJQ1FcFS_xnG2k00af250d4002664c02f', + 'V02SWIvKWYijG6Rggo4m0xvDKj1m7ew00a8e26d3002508b828', + 'V02Sr3nJ9IicoHWfeyQLiXgvrRpje6E00a240b890023270f97', + 'V02SBsNOf4sJZNFo4jOHdgHg7-2Tn1s00a338776000b669579', + 'V02SfEpW1yy4wUUh_eEnEHpiJJuoDnE00ae12710000179aa7f', + 'V02S2oI49T-Jp0_zJKZ5U38dIUSIl8Q00aa679530026780e96', + 'V02ShotJqqiWyubCX0VWTlcbgcHqtSQ00a45564e002678124c', + 'V02SFiqdXRGnH5oAV2FmDDulZyGDL3M00a61660c0026781be1', + 'V02S7tldy5ltYcikCzJ8PJQDSy_ElEs00a327c3c0026782526', + 'V02SPoOluAnWda0dTBYTXpdetS97tyI00a16135e002684bb5c', + 'V02Sb8gxW2inr6IDYrdHK_ywJnayd6s00ab7472b0026849b17', + 'V02SwV15KQ_8n6brU98_2kLnnFUDUOw00adf3fda0026934a7f', + 'V02SC1mOHS0RiUBxeoA8NTliH2h2NGc00a803c35002693584d' + ] + $.invites = [] + $.log('', `开始邀请(间隔 ${$.CFG_inviteWaitTime} 毫秒): `) + for (let sidIdx = 0; sidIdx < sids.length; sidIdx++) { + await new Promise((resove) => { + const body = `invite_userid=${$.userinfo.data.userid}` + const url = { url: 'http://zt.wps.cn/2018/clock_in/api/invite', body, headers: { sid: sids[sidIdx] } } + $.post(url, (error, response, data) => { + try { + if (error) throw new Error(error) + const _data = JSON.parse(data) + const _invite = { _raw: _data, inviteIdx: sidIdx, isSuc: _data.result === 'ok' } + $.invites.push(_invite) + $.log(` 邀请第 ${_invite.inviteIdx + 1} 个用户: ${_invite.isSuc ? '成功!' : '失败!'}`) + } catch (e) { + $.log(`❗️ ${$.name}, 执行失败!`, ` error = ${error || e}`, `response = ${JSON.stringify(response)}`, `data = ${data}`, '') + } finally { + resove() + } + }) + }) + await $.wait($.CFG_inviteWaitTime) + } +} + +function showmsg() { + return new Promise((resove) => { + $.subt = '' + $.desc = [] + if (/ok/.test($.signapp.result)) { + $.subt = '签到: 成功' + } else if (/error/.test($.signapp.result) && /recheckin/.test($.signapp.msg)) { + $.subt = '签到: 重复' + } else { + $.subt = '签到: 失败' + } + if ($.signinfo && $.homeinfo.data[0]) { + const current = $.homeinfo.data[0] + $.desc.push(`连签: ${$.signinfo.data.max_days}天, 本期: ${current.end_date} (第${current.id}期)`) + $.desc.push('查看签到详情', '') + } + if ($.signwx) { + $.subt += ', ' + if ($.signwx.isSuc && !$.signwx.isRepeat) $.subt += `打卡: 成功` + else if ($.signwx.isSuc && $.signwx.isRepeat) $.subt += `打卡: 重复` + else if (!$.signwx.isSuc && $.signwx.isSignupNeed && $.signupwx.isSuc) $.subt += `打卡: 报名成功` + else if (!$.signwx.isSuc && $.signwx.isSignupNeed && !$.signupwx.isSuc) $.subt += `打卡: 报名失败` + else $.subt += `打卡: 失败` + $.desc.push(`打卡: ${$.signwx.msg}`) + if ($.signwx.isSignupNeed) { + $.desc.push(`报名: ${$.signupwx.isSuc ? '成功' : `失败! 原因: ${$.signupwx.msg}`}`) + } + $.desc.push(`问题: ${$.question.title}`) + $.desc.push(`答案: ${$.answer.optionIdx + 1}.${$.question.options[$.answer.optionIdx]}`) + } + if ($.invites) { + const invitedCnt = $.invites.filter((invite) => invite.isSuc).length + const inviteCnt = $.invites.length + $.subt += ', 邀请: ' + $.subt += `${invitedCnt}/${inviteCnt}` + } + if ($.signreward && $.signreward.data) { + const maxdays = $.signinfo.data.max_days + let curDays = 0 + $.signreward.data.forEach((r) => { + const rstatus = r.status == 'unreceived' ? '[未领]' : '[已领]' + const limit_days = parseInt(r.limit_days) + const daysstatus = maxdays >= limit_days ? '✅' : '❕' + if (curDays < limit_days) { + curDays = limit_days + $.desc.push('', `${daysstatus} 连签${limit_days}天: `) + } + $.desc.push(` ${rstatus} ${r.reward_name}`) + }) + } + $.msg($.name, $.subt, $.desc.join('\n')) + resove() + }) +} + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`🔔${this.name}, 开始!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============📣系统通知📣=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`❗️${this.name}, 错误!`,t.stack):this.log("",`❗️${this.name}, 错误!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`🔔${this.name}, 结束! 🕛 ${s} 秒`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/wykl/README.md b/wykl/README.md new file mode 100644 index 000000000..d7dc04e7b --- /dev/null +++ b/wykl/README.md @@ -0,0 +1,104 @@ +# 网易考拉(弃坑) + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> QuanX 需要: v1.0.6-build195 及以后版本 (TestFlight) + +> 感谢 [@GideonSenku](https://github.com/GideonSenku) Commit + +## 配置 (Surge) + +```properties +[MITM] +m-bean.kaola.com + +[Script] +http-request ^https:\/\/m-bean\.kaola\.com/m/point/sign\.html script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wykl/wykl.cookie.js, requires-body=true + +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/wykl/wykl.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +m-bean.kaola.com + +[rewrite_local] + +# [商店版] QuanX v1.0.6-build194 及更早版本 +# ^https:\/\/m-bean\.kaola\.com/m/point/sign\.html url script-request-body wykl.cookie.js + +# [TestFlight] QuanX v1.0.6-build195 及以后版本 +^https:\/\/m-bean\.kaola\.com/m/point/sign\.html url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/wykl/wykl.cookie.js + +[task_local] +1 0 * * * wykl.js +``` + +## 说明 + +1. 先把`m-bean.kaola.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`wykl.cookie.js`和`wykl.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP 手动签到一次: 访问下右下角 `我的考拉` > `领考拉豆` > `签到` +4. 系统提示: `获取Cookie: 成功` +5. 把获取 Cookie 的脚本注释掉 +6. 运行一次脚本, 如果提示重复签到, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@GideonSenku](https://github.com/GideonSenku) diff --git a/wykl/wykl.cookie.js b/wykl/wykl.cookie.js new file mode 100644 index 000000000..7537a7afd --- /dev/null +++ b/wykl/wykl.cookie.js @@ -0,0 +1,61 @@ +const cookieName = '网易考拉' +const signurlKey = 'senku_signurl_wykl' +const signheaderKey = 'senku_signheader_wykl' +const signbodyKey = 'senku_signbody_wykl' +const senku = init() + +const requrl = $request.url +if ($request && $request.method != 'OPTIONS') { + const signurlVal = requrl + const signheaderVal = JSON.stringify($request.headers) + const signbodyVal = $request.body + if (signurlVal) senku.setdata(signurlVal, signurlKey) + if (signheaderVal) senku.setdata(signheaderVal, signheaderKey) + if (signbodyVal) senku.setdata(signbodyVal, signbodyKey) + senku.msg(cookieName, `获取Cookie: 成功`, ``) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} +senku.done() diff --git a/wykl/wykl.js b/wykl/wykl.js new file mode 100644 index 000000000..1926424f6 --- /dev/null +++ b/wykl/wykl.js @@ -0,0 +1,75 @@ +const cookieName = '网易考拉' +const signurlKey = 'senku_signurl_wykl' +const signheaderKey = 'senku_signheader_wykl' +const signbodyKey = 'senku_signbody_wykl' +const senku = init() +const signurlVal = senku.getdata(signurlKey) +const signheaderVal = senku.getdata(signheaderKey) +const signBodyVal = senku.getdata(signbodyKey) + +sign() + +function sign() { + const url = { url: signurlVal, headers: JSON.parse(signheaderVal), body: signBodyVal } + senku.post(url, (error, response, data) => { + senku.log(`${cookieName}, data: ${data}`) + const res = JSON.parse(data) + let subTitle = `` + let detail = `` + if (res.retCode == 200) { + subTitle = `签到结果: 成功` + detail = `获得:${res.data.popupWindowInfo.frontRewardName},签到天数:${res.data.signCount}` + } else if (res.retCode==401 || res.retCode==403 || res.code==401) { + subTitle = `签到结果: 成功 (重复签到)` + } else { + subTitle = `签到结果: 失败` + detail = `编码: ${res.code}, 说明: ${res.msg}` + } + senku.msg(cookieName, subTitle, detail) + senku.done() + }) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, resp, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } +} diff --git a/ximalaya/README.md b/ximalaya/README.md index 71603d8fe..414d3a994 100644 --- a/ximalaya/README.md +++ b/ximalaya/README.md @@ -6,14 +6,18 @@ > 2020.1.11 QuanX 在`190`版本开始, 获取 Cookie 方式需要从`script-response-body`改为`script-request-header` +> 2020.3.9 增加自动执行每日`浏览发现页`任务 (更新脚本即可, 无需重新获取 cookike) + +> 2020.3.12 移除`浏览发现页`, 原因: 需要观看视频 3 分钟 + ## 配置 (Surge) ```properties [MITM] -mobwsa.ximalaya.com +113.96.156.178, *.ximalaya.com [Script] -http-request ^https?:\/\/.*\/mobile\-user\/homePage\/.* script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ximalaya/ximalaya.cookie.js +http-request ^https?:\/\/.*\/mobile\-user\/(v1\/)?homePage\/.* script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ximalaya/ximalaya.cookie.js cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/ximalaya/ximalaya.js ``` @@ -21,13 +25,10 @@ cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scr ```properties [MITM] -mobwsa.ximalaya.com +113.96.156.178, *.ximalaya.com [rewrite_local] -# 189及以前版本 -^https?:\/\/.*\/mobile\-user\/homePage\/.* url script-response-body ximalaya.cookie.js -# 190及以后版本 -^https?:\/\/.*\/mobile\-user\/homePage\/.* url script-request-header ximalaya.cookie.js +^https?:\/\/.*\/mobile\-user\/(v1\/)?homePage\/.* url script-request-header ximalaya.cookie.js [task_local] 1 0 * * * ximalaya.js @@ -35,7 +36,7 @@ mobwsa.ximalaya.com ## 说明 -1. 先把`mobwsa.ximalaya.com`加到`[MITM]` +1. 先把`113.96.156.178, *.ximalaya.com`加到`[MITM]` 2. 再配置重写规则: - Surge: 把两条远程脚本放到`[Script]` - QuanX: 把`ximalaya.cookie.js`和`ximalaya.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) diff --git a/ximalaya/ximalaya.js b/ximalaya/ximalaya.js index 4ad625ddc..fea0e111d 100644 --- a/ximalaya/ximalaya.js +++ b/ximalaya/ximalaya.js @@ -1,131 +1,154 @@ -const cookieName = '喜马拉雅' -const cookieKey = 'chavy_cookie_ximalaya' -const chavy = init() -const cookieVal = chavy.getdata(cookieKey) +const $ = new Env('喜马拉雅') -sign() +$.KEY_signcookie = 'chavy_cookie_ximalaya' +$.signinfo = {} -function sign() { - getinfo((signinfo) => { - if (signinfo.isTickedToday == false) { - let url = { url: `https://m.ximalaya.com/starwar/lottery/check-in/check/action`, headers: { Cookie: cookieVal } } - url.headers['Accept'] = `application/json, text/plain, */*` - url.headers['Accept-Encoding'] = `gzip, deflate, br` - url.headers['Accept-Language'] = `zh-cn` - url.headers['Connection'] = `keep-alive` - url.headers['Host'] = `m.ximalaya.com` - url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 iting/6.6.45 kdtunion_iting/1.0 iting(main)/6.6.45/ios_1' - chavy.post(url, (error, response, data) => { - const title = `${cookieName}` - let subTitle = `` - let detail = `` - if (data == 'true') { - getacc((accinfo) => { - subTitle = `签到结果: 成功` - detail = `共签: ${signinfo.totalCheckedCounts + 1}天, 积分: ${accinfo.data.score}(+${signinfo.awardAmount})` - chavy.msg(title, subTitle, detail) - chavy.log(`${cookieName}, sign: ${data}`) - }) - } else { - subTitle = `签到结果: 失败` - detail = `说明: ${data}` - chavy.msg(title, subTitle, detail) - chavy.log(`${cookieName}, sign: ${data}`) - } - }) - chavy.done() +let VAL_signcookie = $.getdata($.KEY_signcookie) +let time = new Date().getTime() + +;(exec = async () => { + await getinfo() + if ($.signinfo.info.isTickedToday == 0) await signapp() + // await browseapp() + await getacc() + showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +function signapp() { + return new Promise((resolve, reject) => { + const url = { + url: `https://hybrid.ximalaya.com/web-activity/signIn/action?aid=8&ts=${time}&_sonic=0&impl=com.gemd.iting&_sonic=0`, + headers: { Cookie: VAL_signcookie } } + url.headers['Accept'] = 'application/json, text/plain, */*' + url.headers['Accept-Encoding'] = 'gzip, deflate, br' + url.headers['Accept-Language'] = 'zh-cn' + url.headers['Connection'] = 'keep-alive' + url.headers['Host'] = 'hybrid.ximalaya.com' + url.headers['User-Agent'] = + 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 iting/6.6.45 kdtunion_iting/1.0 iting(main)/6.6.45/ios_1' + $.post(url, (error, response, data) => { + try { + $.signinfo.sign = JSON.parse(response.body) + resolve() + } catch (e) { + $.msg($.name, `签到结果: 失败`, `说明: ${e}`) + $.log(`❌ ${$.name} signapp - 签到失败: ${e}`) + $.log(`❌ ${$.name} signapp - response: ${JSON.stringify(response)}`) + resolve() + } + }) }) } -function getinfo(cb) { - let url = { url: `https://m.ximalaya.com/starwar/lottery/check-in/record`, headers: { Cookie: cookieVal } } - url.headers['Accept'] = `application/json, text/plain, */*` - url.headers['Accept-Encoding'] = `gzip, deflate, br` - url.headers['Accept-Language'] = `zh-cn` - url.headers['Connection'] = `keep-alive` - url.headers['Content-Type'] = `application/json;charset=utf-8` - url.headers['Host'] = `m.ximalaya.com` - url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 iting/6.6.45 kdtunion_iting/1.0 iting(main)/6.6.45/ios_1' - chavy.get(url, (error, response, data) => { - chavy.log(`${cookieName}, signinfo: ${data}`) - if (data) { - const signinfo = JSON.parse(data) - if (signinfo.isTickedToday == true) { - getacc((accinfo) => { - const title = `${cookieName}` - let subTitle = `签到结果: 成功 (重复签到)` - let detail = `共签: ${signinfo.totalCheckedCounts}天, 积分: ${accinfo.data.score}(+${signinfo.awardAmount})` - chavy.msg(title, subTitle, detail) - chavy.log(`${cookieName}, data: ${data}`) - }) - } else { - cb(signinfo) +function browseapp() { + return new Promise((resolve, reject) => { + const timestamp = Math.round(new Date().getTime() / 1000).toString() + const browseappurl = `https://mobile.ximalaya.com/daily-label-mobile/v1/task/checkIn/ts-${timestamp}?coinSwitch=true` + const url = { url: browseappurl, headers: { Cookie: VAL_signcookie } } + url.headers['Accept'] = '*/*' + url.headers['Accept-Encoding'] = 'gzip, deflate' + url.headers['Accept-Language'] = 'zh-Hans-CN;q=1, en-US;q=0.9' + url.headers['Connection'] = 'close' + url.headers['Host'] = 'mobile.ximalaya.com' + url.headers['User-Agent'] = + 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 iting/6.6.45 kdtunion_iting/1.0 iting(main)/6.6.45/ios_1' + $.get(url, (error, response, data) => { + try { + $.log(`❕ ${$.name} browseapp - response: ${JSON.stringify(response)}`) + $.signinfo.browseapp = JSON.parse(data) + resolve() + } catch (e) { + $.msg($.name, `每日浏览: 失败`, `说明: ${e}`) + $.log(`❌ ${$.name} browseapp - 每日浏览: ${e}`) + $.log(`❌ ${$.name} browseapp - response: ${JSON.stringify(response)}`) + resolve() } - } else { - const title = `${cookieName}` - let subTitle = `签到结果: 失败` - let detail = `说明: 请选登录` - chavy.msg(title, subTitle, detail) - } + }) }) } -function getacc(cb) { - let url = { url: `https://m.ximalaya.com/starwar/task/listen/account`, headers: { Cookie: cookieVal } } - url.headers['Accept'] = `application/json, text/plain, */*` - url.headers['Accept-Encoding'] = `gzip, deflate, br` - url.headers['Accept-Language'] = `zh-cn` - url.headers['Connection'] = `keep-alive` - url.headers['Content-Type'] = `application/json;charset=utf-8` - url.headers['Host'] = `m.ximalaya.com` - url.headers['User-Agent'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 iting/6.6.45 kdtunion_iting/1.0 iting(main)/6.6.45/ios_1' - chavy.get(url, (error, response, data) => { - cb(JSON.parse(data)) - chavy.log(`${cookieName}, acc: ${data}`) +function getinfo() { + return new Promise((resolve, reject) => { + const url = { url: `https://m.ximalaya.com/starwar/lottery/check-in/record`, headers: { Cookie: VAL_signcookie } } + url.headers['Accept'] = `application/json, text/plain, */*` + url.headers['Accept-Encoding'] = `gzip, deflate, br` + url.headers['Accept-Language'] = `zh-cn` + url.headers['Connection'] = `keep-alive` + url.headers['Content-Type'] = `application/json;charset=utf-8` + url.headers['Host'] = `m.ximalaya.com` + url.headers['User-Agent'] = + 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 iting/6.6.45 kdtunion_iting/1.0 iting(main)/6.6.45/ios_1' + $.get(url, (error, response, data) => { + try { + $.signinfo.info = JSON.parse(data) + resolve() + } catch (e) { + $.msg($.name, `获取签到信息: 失败`, `说明: ${e}`) + $.log(`❌ ${$.name} getinfo - 获取签到信息失败: ${e}`) + $.log(`❌ ${$.name} getinfo - response: ${JSON.stringify(response)}`) + resolve() + } + }) }) } -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) - } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) +function getacc() { + return new Promise((resolve, reject) => { + const url = { url: `https://m.ximalaya.com/starwar/task/listen/account`, headers: { Cookie: VAL_signcookie } } + url.headers['Accept'] = `application/json, text/plain, */*` + url.headers['Accept-Encoding'] = `gzip, deflate, br` + url.headers['Accept-Language'] = `zh-cn` + url.headers['Connection'] = `keep-alive` + url.headers['Content-Type'] = `application/json;charset=utf-8` + url.headers['Host'] = `m.ximalaya.com` + url.headers['User-Agent'] = + 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 iting/6.6.45 kdtunion_iting/1.0 iting(main)/6.6.45/ios_1' + $.get(url, (error, response, data) => { + try { + $.signinfo.acc = JSON.parse(data) + resolve() + } catch (e) { + $.msg($.name, `获取账号信息: 失败`, `说明: ${e}`) + $.log(`❌ ${$.name} getacc - 获取账号信息失败: ${e}`) + $.log(`❌ ${$.name} getacc - response: ${JSON.stringify(response)}`) + resolve() + } + }) + }) +} + +function showmsg() { + let subTitle = '' + let detail = '' + if ($.signinfo.info.isTickedToday == false) { + if ($.signinfo.sign.data.status == 0) { + subTitle = '签到: 成功' + detail = `当前连签: ${$.signinfo.info.continuousDays + 1}天, 积分: ${$.signinfo.acc.data.score}(+${$.signinfo.info.awardAmount})` + } else if ($.signinfo.sign.data.msg != undefined) { + subTitle = '签到: 失败' + detail = `说明: ${$.signinfo.sign.data.msg}` + } else { + subTitle = '签到: 失败' + detail = `说明: Cookie失效` } + } else { + subTitle = `签到: 重复` + detail = `当前连签: ${$.signinfo.info.continuousDays}天, 积分: ${$.signinfo.acc.data.score}(+${$.signinfo.info.awardAmount})` } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) - } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + + if ($.signinfo.browseapp) { + if ($.signinfo.browseapp.ret == 0 && $.signinfo.browseapp.data && $.signinfo.browseapp.data.awards) { + if ($.signinfo.browseapp.data.awards) subTitle += `, 每日浏览: 成功 (${$.signinfo.browseapp.data.awards})` + else subTitle += ', 每日浏览: 重复' + } else { + subTitle += ', 每日浏览: 失败' } } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } + $.msg($.name, subTitle, detail) } + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/xunlei/xunlei.js b/xunlei/xunlei.js new file mode 100644 index 000000000..8c6c38b7c --- /dev/null +++ b/xunlei/xunlei.js @@ -0,0 +1,31 @@ +const $ = new Env('迅雷') + +!(async () => { + if ($request.method !== 'GET') { + console.log(`[迅雷] 跳出重写, 原因: method == ${$request.method}`); + $.done({}) + return + } + + if ($response.body == null) { + console.log(`[迅雷] 跳出重写, 原因: $response.body == null`); + $.done({}) + return + } + + const body = JSON.parse($response.body) + body.files.forEach((f) => { + f.audit = { + "message": "正常资源", + "status": "STATUS_OK", + "title": "" + } + }) + + $.done({body: JSON.stringify(body)}) +})() + .catch((e) => $.logErr(e)) + + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}isShadowrocket(){return"undefined"!=typeof $rocket}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:i,...r}=t;this.got[s](i,r).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} diff --git a/xunlei/xunlei.sgmodule b/xunlei/xunlei.sgmodule new file mode 100644 index 000000000..4a606e914 --- /dev/null +++ b/xunlei/xunlei.sgmodule @@ -0,0 +1,12 @@ +#!name=迅雷 +#!desc=http://boxjs.com +#!author=ChavyLeung +#!homepage=https://docs.boxjs.app/ +#!icon=https://raw.githubusercontent.com/chavyleung/scripts/master/box/icons/BoxJs.png +#!category=BoxJs + +[MITM] +hostname = %INSERT% api-pan.xunlei.com + +[Script] +迅雷 = type=http-response,pattern=^https:\/\/api-pan.xunlei.com\/drive\/v1\/files,requires-body=1,max-size=0,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/xunlei/xunlei.js diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..2cf0f3de8 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,599 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@sindresorhus/is@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz" + integrity sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ== + +"@szmarczak/http-timer@^4.0.5": + version "4.0.5" + resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz" + integrity sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ== + dependencies: + defer-to-connect "^2.0.0" + +"@types/cacheable-request@^6.0.1": + version "6.0.1" + resolved "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz" + integrity sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "*" + "@types/node" "*" + "@types/responselike" "*" + +"@types/http-cache-semantics@*": + version "4.0.0" + resolved "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz" + integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== + +"@types/keyv@*": + version "3.1.1" + resolved "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz" + integrity sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw== + dependencies: + "@types/node" "*" + +"@types/node@*": + version "14.14.20" + resolved "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz" + integrity sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A== + +"@types/responselike@*", "@types/responselike@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +async@^2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + +basic-auth@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" + integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== + dependencies: + safe-buffer "5.1.2" + +cacheable-lookup@^5.0.3: + version "5.0.4" + resolved "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz" + integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== + +cacheable-request@^7.0.2: + version "7.0.2" + resolved "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz" + integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^6.0.1" + responselike "^2.0.0" + +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bound@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +corser@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz" + integrity sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c= + +crypto-js@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +defer-to-connect@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz" + integrity sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg== + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +follow-redirects@^1.0.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" + integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +got@^11.8.5: + version "11.8.5" + resolved "https://registry.npmjs.org/got/-/got-11.8.5.tgz" + integrity sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ== + dependencies: + "@sindresorhus/is" "^4.0.0" + "@szmarczak/http-timer" "^4.0.5" + "@types/cacheable-request" "^6.0.1" + "@types/responselike" "^1.0.0" + cacheable-lookup "^5.0.3" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + http2-wrapper "^1.0.0-beta.5.2" + lowercase-keys "^2.0.0" + p-cancelable "^2.0.0" + responselike "^2.0.0" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +html-encoding-sniffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" + integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== + dependencies: + whatwg-encoding "^2.0.0" + +http-cache-semantics@^4.0.0: + version "4.1.1" + resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +http-server@^14.1.1: + version "14.1.1" + resolved "https://registry.yarnpkg.com/http-server/-/http-server-14.1.1.tgz#d60fbb37d7c2fdff0f0fbff0d0ee6670bd285e2e" + integrity sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A== + dependencies: + basic-auth "^2.0.1" + chalk "^4.1.2" + corser "^2.0.1" + he "^1.2.0" + html-encoding-sniffer "^3.0.0" + http-proxy "^1.18.1" + mime "^1.6.0" + minimist "^1.2.6" + opener "^1.5.1" + portfinder "^1.0.28" + secure-compare "3.0.1" + union "~0.5.0" + url-join "^4.0.1" + +http2-wrapper@^1.0.0-beta.5.2: + version "1.0.0-beta.5.2" + resolved "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz" + integrity sha512-xYz9goEyBnC8XwXDTuC/MZ6t+MrKVQZOk4s7+PaDkwIsQd8IwqvM+0M6bA/2lvG8GHXcPdf+MejTUeO2LCPCeQ== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.0.0" + +iconv-lite@0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +keyv@^4.0.0: + version "4.0.3" + resolved "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz" + integrity sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA== + dependencies: + json-buffer "3.0.1" + +lodash@^4.17.14: + version "4.18.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" + integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +mime@^1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-response@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mkdirp@^0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== + +object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + +once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +opener@^1.5.1: + version "1.5.2" + resolved "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz" + integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== + +p-cancelable@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz" + integrity sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg== + +portfinder@^1.0.28: + version "1.0.32" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" + integrity sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg== + dependencies: + async "^2.6.4" + debug "^3.2.7" + mkdirp "^0.5.6" + +prettier@^3.2.5: + version "3.2.5" + resolved "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz" + integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== + +psl@^1.1.33: + version "1.8.0" + resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@^6.4.0: + version "6.14.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.2.tgz#b5634cf9d9ad9898e31fba3504e866e8efb6798c" + integrity sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q== + dependencies: + side-channel "^1.1.0" + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +resolve-alpn@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.0.0.tgz" + integrity sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA== + +responselike@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz" + integrity sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw== + dependencies: + lowercase-keys "^2.0.0" + +safe-buffer@5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +secure-compare@3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz" + integrity sha1-8aAymzCLIh+uN7mXTz1XjQypmeM= + +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +tough-cookie@^4.1.3: + version "4.1.3" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz" + integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + +union@~0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/union/-/union-0.5.0.tgz" + integrity sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA== + dependencies: + qs "^6.4.0" + +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +whatwg-encoding@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" + integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== + dependencies: + iconv-lite "0.6.3" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= diff --git a/zaker/README.md b/zaker/README.md new file mode 100644 index 000000000..94e9e803b --- /dev/null +++ b/zaker/README.md @@ -0,0 +1,104 @@ +# ZAKER新闻 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> 感谢[@danchaw](https://github.com/danchaw) PR +## 配置 (Surge) + +```properties +[MITM] +iphone.myzaker.com + +[Script] +http-request ^https:\/\/iphone\.myzaker\.com\/zaker\/sign_in\/\/api\/sign_in\.php script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zaker/zaker.js +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zaker/zaker.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +iphone.myzaker.com + +[rewrite_local] + +# [商店版] +^https:\/\/iphone\.myzaker\.com\/zaker\/sign_in\/\/api\/sign_in\.php url script-request-header zaker.js + +# [TestFlight] +^https:\/\/iphone\.myzaker\.com\/zaker\/sign_in\/\/api\/sign_in\.php url script-request-header https://raw.githubusercontent.com/chavyleung/scripts/master/zaker/zaker.js + +[task_local] + +# [商店版] +1 0 * * * zaker.js + +# [TestFlight] +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/zaker/zaker.js +``` + +## 说明 + +1. 先把`iphone.myzaker.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`zaker.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP[ZAKER](https://apps.apple.com/cn/app/zaker-%E6%97%B6%E4%BA%8B%E5%A4%B4%E6%9D%A1%E6%96%B0%E9%97%BB/id462149227) 然后手动签到 1 次, 系统提示: `首次写入ZAKER新闻Url成功🎉`和`首次写入ZAKER新闻Cookie成功🎉` +4. 最后就可以把第 1 条脚本注释掉了 +5. 运行一次脚本, 如果提示说明:签到失败, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@danchaw](https://github.com/danchaw) diff --git a/zaker/zaker.js b/zaker/zaker.js new file mode 100644 index 000000000..c8c2a5b83 --- /dev/null +++ b/zaker/zaker.js @@ -0,0 +1,140 @@ +var appName = 'ZAKER新闻' +var zaker = init() +var URL = zaker.getdata("UrlZK") +var KEY = zaker.getdata("CookieZK") + +let isGetCookie = typeof $request !== 'undefined' + +if (isGetCookie) { + getcookie() +} else { + sign() +} + +function getcookie() { + var url = $request.url; + if (url) { + var UrlKeyZK = "UrlZK"; + var UrlValueZK = url; + if (zaker.getdata(UrlKeyZK) != (undefined || null)) { + if (zaker.getdata(UrlKeyZK) != UrlValueZK) { + var url = zaker.setdata(UrlValueZK, UrlKeyZK); + if (!url) { + zaker.msg("更新" + appName + "Url失败‼️", "", ""); + } else { + zaker.msg("更新" + appName + "Url成功🎉", "", ""); + } + } else { + zaker.msg(appName + "Url未变化❗️", "", ""); + } + } else { + var url = zaker.setdata(UrlValueZK, UrlKeyZK); + if (!url) { + zaker.msg("首次写入" + appName + "Url失败‼️", "", ""); + } else { + zaker.msg("首次写入" + appName + "Url成功🎉", "", ""); + } + } + } else { + zaker.msg("写入" + appName + "Url失败‼️", "", "配置错误, 无法读取URL, "); + } + if ($request.headers) { + var CookieKeyZK = "CookieZK"; + var CookieValueZK = JSON.stringify($request.headers); + if (zaker.getdata(CookieKeyZK) != (undefined || null)) { + if (zaker.getdata(CookieKeyZK) != CookieValueZK) { + var cookie = zaker.setdata(CookieValueZK, CookieKeyZK); + if (!cookie) { + zaker.msg("更新" + appName + "Cookie失败‼️", "", ""); + } else { + zaker.msg("更新" + appName + "Cookie成功🎉", "", ""); + } + } else { + zaker.msg(appName + "Cookie未变化❗️", "", ""); + } + } else { + var cookie = zaker.setdata(CookieValueZK, CookieKeyZK); + if (!cookie) { + zaker.msg("首次写入" + appName + "Cookie失败‼️", "", ""); + } else { + zaker.msg("首次写入" + appName + "Cookie成功🎉", "", ""); + } + } + } else { + zaker.msg("写入" + appName + "Cookie失败‼️", "", "配置错误, 无法读取请求头, "); + } + zaker.done() +} + +function sign() { + const url = { url: URL, headers: JSON.parse(KEY) } + zaker.get(url, (error, response, data) => { + zaker.log(`${appName}, data: ${data}`) + const title = `${appName}` + let subTitle = '' + let detail = '' + const result = JSON.parse(data) + if (result.stat == 1) { + subTitle = `签到结果: 成功` + detail = `签到奖励: ${result.data.tips}, 总签到天数: ${result.data.total_day_count}天` + } else { + subTitle = `签到结果: 未知` + detail = `说明: ${result.msg}` + } + zaker.msg(title, subTitle, detail) + zaker.done() + }) +} + +function init() { + isSurge = () => { + return undefined === this.$httpClient ? false : true + } + isQuanX = () => { + return undefined === this.$task ? false : true + } + getdata = (key) => { + if (isSurge()) return $persistentStore.read(key) + if (isQuanX()) return $prefs.valueForKey(key) + } + setdata = (key, val) => { + if (isSurge()) return $persistentStore.write(key, val) + if (isQuanX()) return $prefs.setValueForKey(key, val) + } + msg = (title, subtitle, body) => { + if (isSurge()) $notification.post(title, subtitle, body) + if (isQuanX()) $notify(title, subtitle, body) + } + log = (message) => console.log(message) + get = (url, cb) => { + if (isSurge()) { + $httpClient.get(url, cb) + } + if (isQuanX()) { + url.method = 'GET' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + post = (url, cb) => { + if (isSurge()) { + $httpClient.post(url, cb) + } + if (isQuanX()) { + url.method = 'POST' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + put = (url, cb) => { + if (isSurge()) { + $httpClient.put(url, cb) + } + if (isQuanX()) { + url.method = 'PUT' + $task.fetch(url).then((resp) => cb(null, {}, resp.body)) + } + } + done = (value = {}) => { + $done(value) + } + return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, put, done } +} \ No newline at end of file diff --git a/zimuzu/zimuzu.js b/zimuzu/zimuzu.js deleted file mode 100644 index 932039907..000000000 --- a/zimuzu/zimuzu.js +++ /dev/null @@ -1,168 +0,0 @@ -const cookieName = '字幕组' -const cookieKey = 'chavy_cookie_zimuzu' -const cookieAppKey = 'chavy_cookie_zimuzu_app' -const authUrlAppKey = 'chavy_auth_url_zimuzu_app' -const chavy = init() -const cookieVal = chavy.getdata(cookieKey) -let cookieAppVal = chavy.getdata(cookieAppKey) -const authUrlAppVal = chavy.getdata(authUrlAppKey) -const signinfo = {} - -sign() - -function sign() { - signweb() - signapp() - check() -} - -function signweb() { - let url = { url: `http://www.rrys2019.com/user/login/getCurUserTopInfo`, headers: { Cookie: cookieVal } } - url.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15' - - chavy.get(url, (error, response, data) => { - chavy.log(`${cookieName}, signweb - data: ${data}`) - signinfo.web = JSON.parse(data) - }) -} - -function loginapp(cb) { - if (authUrlAppVal) { - const url = { url: authUrlAppVal, headers: {} } - url.headers['Accept'] = `*/*` - url.headers['Accept-Encoding'] = `gzip;q=1.0, compress;q=0.5` - url.headers['Accept-Language'] = `zh-Hans-CN;q=1.0, en-US;q=0.9` - url.headers['Connection'] = `close` - url.headers['Host'] = `ios.zmzapi.com` - url.headers['Referer'] = `http://h5.rrhuodong.com/mobile/mission/pages/task.html` - url.headers['User-Agent'] = `YYets_swift/2.5.7 (com.yyets.ZiMuZu; build:29; iOS 13.3.1) Alamofire/4.9.1` - chavy.get(url, (error, response, data) => { - const result = JSON.parse(data) - if (result.status == 1) refreshapp(result, cb) - else signinfo.app = result - }) - } else { - cb() - } -} - -function refreshapp(logininfo, cb) { - const url = { url: `http://h5.rrhuodong.com/index.php?g=api/mission&m=index&a=login&uid=${logininfo.data.uid}&token=${logininfo.data.token}`, headers: {} } - url.headers['Accept'] = `application/json, text/plain, */*` - url.headers['Accept-Encoding'] = `gzip, deflate` - url.headers['Accept-Language'] = `zh-cn` - url.headers['Connection'] = `close` - url.headers['Host'] = `h5.rrhuodong.com` - url.headers['Referer'] = `http://h5.rrhuodong.com/mobile/mission/pages/task.html` - url.headers['User-Agent'] = `Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148` - chavy.get(url, (error, response, data) => { - const respcookie = response.headers['Set-Cookie'] - if (respcookie && respcookie.indexOf('PHPSESSID=') >= 0) { - cookieAppVal = response.headers['Set-Cookie'].match(/PHPSESSID=([^;]*)/)[0] - if (cookieAppVal) chavy.setdata(cookieAppVal, cookieAppKey) - } - cb() - }) -} - -function signapp() { - loginapp(() => { - let url = { url: `http://h5.rrhuodong.com/index.php?g=api/mission&m=clock&a=store&id=2`, headers: { Cookie: cookieAppVal } } - url.headers['Accept'] = `application/json, text/plain, */*` - url.headers['Accept-Encoding'] = `gzip, deflate` - url.headers['Accept-Language'] = `zh-cn` - url.headers['Connection'] = `close` - url.headers['Host'] = `h5.rrhuodong.com` - url.headers['Referer'] = `http://h5.rrhuodong.com/mobile/mission/pages/task.html` - url.headers['User-Agent'] = `Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148` - - chavy.get(url, (error, response, data) => { - chavy.log(`${cookieName}, signapp - data: ${data}`) - signinfo.app = JSON.parse(data) - }) - }) -} - -function getinfo() { - const title = `${cookieName}` - let subTitle = `网页: ` - let detail = '' - - // web - if (signinfo.web.status == 1) { - if (signinfo.web.data.new_login) subTitle += '成功' - else subTitle += '成功 (重复)' - detail = `人人钻: ${signinfo.web.data.userinfo.point}, 登录天数: ${signinfo.web.data.usercount.cont_login}` - } else if (signinfo.web.status == 4001) { - subTitle += '未登录' - } else { - subTitle += '失败' - } - - // app - subTitle += `; APP: ` - if (signinfo.app.status == 1) subTitle += '成功' - else if (signinfo.app.status == 4005) subTitle += '成功 (重复)' - else if (signinfo.app.status == 1021) subTitle += '未登录' - else subTitle += '失败' - - chavy.msg(title, subTitle, detail) - chavy.done() -} - -function check(checkms = 0) { - if (signinfo.web && signinfo.app) { - getinfo() - } else { - if (checkms > 5000) { - chavy.msg(`${cookieName}`, `签到失败: 超时退出`, ``) - chavy.done() - } else { - setTimeout(() => check(checkms + 100), 100) - } - } -} - -function init() { - isSurge = () => { - return undefined === this.$httpClient ? false : true - } - isQuanX = () => { - return undefined === this.$task ? false : true - } - getdata = (key) => { - if (isSurge()) return $persistentStore.read(key) - if (isQuanX()) return $prefs.valueForKey(key) - } - setdata = (key, val) => { - if (isSurge()) return $persistentStore.write(key, val) - if (isQuanX()) return $prefs.setValueForKey(key, val) - } - msg = (title, subtitle, body) => { - if (isSurge()) $notification.post(title, subtitle, body) - if (isQuanX()) $notify(title, subtitle, body) - } - log = (message) => console.log(message) - get = (url, cb) => { - if (isSurge()) { - $httpClient.get(url, cb) - } - if (isQuanX()) { - url.method = 'GET' - $task.fetch(url).then((resp) => cb(null, resp, resp.body)) - } - } - post = (url, cb) => { - if (isSurge()) { - $httpClient.post(url, cb) - } - if (isQuanX()) { - url.method = 'POST' - $task.fetch(url).then((resp) => cb(null, resp, resp.body)) - } - } - done = (value = {}) => { - $done(value) - } - return { isSurge, isQuanX, msg, log, getdata, setdata, get, post, done } -} diff --git a/zsfc/README.md b/zsfc/README.md new file mode 100644 index 000000000..cf91f7a4b --- /dev/null +++ b/zsfc/README.md @@ -0,0 +1,68 @@ +# 掌上飞车 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> 感谢[@danchaw](https://github.com/danchaw) PR、[@chiupam](https://github.com/chiupam) 修改签到脚本,感谢[@chiupam](https://github.com/chiupam) PR购物脚本、寻宝脚本 + +> 代码已适配最新版掌上飞车APP,旧版本APP无法继续签到,请及时更新 + +## 配置 (Surge) +```properties +[MITM] +hostname = %APPEDN% comm.ams.game.qq.com, bang.qq.com + +[Script] +掌上飞车Cookie = type=http-request, pattern=^https?://(comm\.ams\.game\.qq\.com/ams/ame/amesvr*|bang\.qq\.com/app/speed/mall/main2\?*), requires-body=true, max-size=-1, script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js, script-update-interval=0, timeout=5 +掌飞寻宝Cookie = type=http-request, pattern=^https?://bang\.qq\.com/app/speed/treasure/index\?*, requires-body=true, max-size=-1, script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js, script-update-interval=0, timeout=60 +掌上飞车 =type=cron, cronexp="0 10 0,21 * * *", wake-system=1, script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js, script-update-interval=0, timeout=60 +掌飞寻宝 =type=cron, cronexp="0 */11 17 * * *", wake-system=1, script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js, script-update-interval=0, timeout=60 +``` + +## 配置 (Loon) +```properties +[Mitm] +hostname = comm.ams.game.qq.com, bang.qq.com + +[Script] +http-request ^https?://(comm\.ams\.game\.qq\.com/ams/ame/amesvr*|bang\.qq\.com/app/speed/mall/main2\?*) script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js, requires-body=true, timeout=10, tag=掌上飞车Cookie +http-request ^https?://bang\.qq\.com/app/speed/treasure/index\?* script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js, requires-body=true, timeout=60, tag=掌飞寻宝Cookie + +cron "0 10 0,21 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js, tag=掌上飞车 +cron "0 */11 17 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js, tag=掌飞寻宝 +``` + +## 配置 (QuanX) +```properties +[MITM] +hostname = comm.ams.game.qq.com, bang.qq.com + +[rewrite_local] +^https?://(comm\.ams\.game\.qq\.com/ams/ame/amesvr*|bang\.qq\.com/app/speed/mall/main2\?*) url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js +^https?://bang\.qq\.com/app/speed/treasure/index\?* url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js + +[task_local] +0 10 0,21 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js, tag=掌上飞车, enabled=true +0 */11 17 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js, tag=掌飞寻宝, enabled=true +``` + +## 说明 + +1. 先把`comm.ams.game.qq.com, bang.qq.com`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把三条远程脚本放到`[Script]` + - Loon: 把三条远程脚本放到`[Script]` + - QuanX: 把远程重写脚本放到`[rewrite_local]`,再把远程定时任务放到`[task_local]` +3. 打开[掌上飞车APP](https://apps.apple.com/cn/app/%E6%8E%8C%E4%B8%8A%E9%A3%9E%E8%BD%A6/id1116903233),点击咨询栏的签到(每日福利),系统提示`✅ 获取签到数据成功!`即可 +4. 打开[掌上飞车APP](https://apps.apple.com/cn/app/%E6%8E%8C%E4%B8%8A%E9%A3%9E%E8%BD%A6/id1116903233),点击下方游戏栏,然后点击掌飞商城,系统提示`✅ 获取商城数据成功!`即可 +5. 打开[掌上飞车APP](https://apps.apple.com/cn/app/%E6%8E%8C%E4%B8%8A%E9%A3%9E%E8%BD%A6/id1116903233),点击下方游戏栏,然后点击每日寻宝,系统提示`✅ 获取寻宝数据成功!`即可 +6. 如果使用了[掌飞购物](https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.shop.js)脚本的,请继续订阅[chiupam boxjs仓库](https://raw.githubusercontent.com/chiupam/surge/main/boxjs/chiupam.boxjs.json)并在应用中设置掌飞商城所需购买的游戏道具名称 + +## 反馈bug +如果出现bug,请提交issue到[chiupam仓库](https://github.com/chiupam/surge/issues/new) + +## 感谢 +[@NobyDa](https://github.com/NobyDa) +[@lhie1](https://github.com/lhie1) +[@ConnersHua](https://github.com/ConnersHua) +[@danchaw](https://github.com/danchaw) +[@chiupam](https://github.com/chiupam) diff --git a/zsfc/zsfc.js b/zsfc/zsfc.js new file mode 100644 index 000000000..781000f11 --- /dev/null +++ b/zsfc/zsfc.js @@ -0,0 +1,976 @@ +/** + * + * 特别提醒: 仍然处于测试阶段, 更新频率可能比较高 + * + * 使用方法:打开掌上飞车APP, 点击咨询栏的签到(每日福利)即可,无需点击签到,然后点击下方游戏栏,最后点击掌飞商城即可获取所需商城数据。 + * 注意事项:1、每月需手动打开一次掌上飞车APP并进入签到页面,以重新抓包更新礼包数据,为此需要每日运行两次脚本;2、如果账号信息没有发生根本性变化的话,抓取 Cookie 等信息的脚本就不会被执行;3、如需购买掌飞商店中的指定商品,请订阅boxjs链接,并在掌上飞车应用中填写在售商品的完整名称 + * + * boxjs订阅地址:https://raw.githubusercontent.com/chiupam/surge/main/boxjs/chiupam.boxjs.json + * + * + * hostname: comm.ams.game.qq.com, bang.qq.com + * + * type: http-request + * regex: ^https?://(comm\.ams\.game\.qq\.com/ams/ame/amesvr*|bang\.qq\.com/app/speed/mall/main2\?*) + * script-path: https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js + * requests-body: 1 + * + * type: cron + * cron: 0 10 0,21 * * * + * script-path: https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js + * + * =============== Surge =============== + * 掌上飞车Cookie = type=http-request, pattern=^https?://(comm\.ams\.game\.qq\.com/ams/ame/amesvr*|bang\.qq\.com/app/speed/mall/main2\?*), requires-body=true, max-size=-1, script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js, script-update-interval=0, timeout=5 + * 掌上飞车 =type=cron, cronexp="0 10 0,21 * * *", wake-system=1, script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js, script-update-interval=0, timeout=60 + * + * =============== Loon =============== + * http-request ^https?://(comm\.ams\.game\.qq\.com/ams/ame/amesvr*|bang\.qq\.com/app/speed/mall/main2\?*) script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js, requires-body=true, timeout=60, tag=掌上飞车Cookie + * cron "0 10 0,21 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js, tag=掌上飞车 + * + * =============== Quan X =============== + * ^https?://(comm\.ams\.game\.qq\.com/ams/ame/amesvr*|bang\.qq\.com/app/speed/mall/main2\?*) url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js + * 0 10 0,21 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.js, tag=掌上飞车, enabled=true + * +*/ + +/** + * 创建一个名为 $ 的环境变量实例,用于处理掌上飞车相关操作 + */ +const $ = new Env() + +/** + * 检查是否为请求阶段 + */ +const isRequest = typeof $request !== 'undefined'; + +/** + * 主函数,用于执行签到操作或设置请求数据 + */ +(async () => { + if (isRequest) { + + if ($request.url.includes(`amesvr`)) { + /** + * ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 以下获取签到数据 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ + */ + + // 提取请求数据 + const cookie = $request.headers.cookie || $request.headers.Cookie; // QX、Loon都是用的Cookie + const body = $request.body; + + // 提取请求体中的 iActivityId 和 iFlowId 作为检验使用 + $.iActivityId = matchParam(body, 'iActivityId'); + $.iFlowId = matchParam(body, 'iFlowId'); + + // 初始化 cookieToWrite 词典,填充待写入内存的键值对 + const cookieToWrite = { + 'zsfc_accessToken': matchParam(cookie, 'accessToken'), + 'zsfc_openid': matchParam(cookie, 'openId') + }; + + // 将请求数据写入内存 + Object.entries(cookieToWrite).forEach(([key, value]) => $.write(value, key)); + + // 发起请求检验 iActivityId 和 iFlowId 是否为需要的值 + if (await getTotalSignInDays() === -1) return; + + // 解码 tokenParams 端内容 + const decodeTokenParams = decodeURIComponent(matchParam(cookie, 'tokenParams')); + + // 初始化 dataToWrite 词典,填充待写入内存的键值对 + const dataToWrite = { + 'zsfc_roleId': matchParam(decodeTokenParams, 'roleId'), + 'zsfc_uin': matchParam(decodeTokenParams, 'uin'), + 'zsfc_areaId': matchParam(decodeTokenParams, 'areaId'), + 'zsfc_iActivityId': ($.iActivityId).toString(), + 'zsfc_iFlowId': ($.iFlowId).toString(), + } + + // 如果所有键值都与内存中的值相同,则立即终止程序 + if (Object.keys(dataToWrite).every(key => dataToWrite[key] === $.read(key))) return; + + // 将请求数据写入内存,并输出到日志中 + Object.entries(dataToWrite).forEach(([key, value]) => $.write(value, key)); + $.log(dataToWrite) + + // 显示获取结果通知 + $.notice(`🏎️ 掌上飞车`, `✅ 获取签到数据成功!`, `流水ID:${$.iFlowId},活动ID:${$.iActivityId}`); + + // 检查并设置青龙相关变量 + if ($.read(`ql_url`) && $.read(`ql_client_id`) && $.read(`ql_client_secret`) && $.toObj($.read(`zsfc_upload_id`))) { + const qlUrlCache = $.read(`ql_url`); + $.qlUrl = qlUrlCache.charAt(qlUrlCache.length - 1) === '/' ? qlUrlCache.slice(0, -1) : qlUrlCache; + $.qlId = $.read(`ql_client_id`); + $.qlSecret = $.read(`ql_client_secret`); + $.qlToken = await qlToken(); + + const qlEnvsName = `ZSFC_iFlowdId`; + const qlEnvsValue = `${$.iFlowId}/${$.iActivityId}`; + const qlEnvsRemarks = `掌飞签到`; + + // 获取青龙面板令牌,若成功则执行后续操作 + if ($.qlToken) { + const qlEnvsNewBody = await qlEnvsSearch(qlEnvsName, qlEnvsValue, qlEnvsRemarks); + if (!qlEnvsNewBody) return $.log(`⭕ ${qlEnvsName}变量值没有发生变化`); // 环境变量的值没有发生变化,不需要进行操作 + + // 检查并处理环境变量的返回值类型 + if (Array.isArray(qlEnvsNewBody)) { + // 暂时无法完成新增操作,后续再修改 + $.log(`⭕ 手动添加名为 ${qlEnvsName} 变量`); + } else { + await qlEnvsEdit(qlEnvsNewBody); + } + } else { + $.log("❌ 无法获取 token,请检查青龙相关配置"); + } + } + } else { + /** + * ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 以下获取商城数据 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ + */ + + // 提取请求的URL并去除引号 + const url = $.toStr($request.url).replace(/^"|"$/g, ''); + const cookie = $request.headers.cookie || $request.headers.Cookie; // QX、Loon都是用的Cookie + + // 对比 token 是否发生变化 + if ($.read(`zsfc_token`) === matchParam(url, "token")) return; + + // 初始化 dataToWrite 词典,填充待写入内存的键值对 + const dataToWrite = { + 'zsfc_iActivityId': $.read(`zsfc_iActivityId`), // 掌飞商城无法抓取,只能读取签到页面的脚本获取情况 + "zsfc_accessToken": matchParam(url, "accessToken"), + "zsfc_openid": matchParam(cookie, "openid"), + "zsfc_token": matchParam(url, "token"), + "zsfc_roleId": matchParam(url, "roleId"), + "zsfc_userId": matchParam(url, "userId"), + "zsfc_areaId": matchParam(url, "areaId"), + 'zsfc_uin': matchParam(url, "uin"), + }; + + // 将请求数据写入内存 + Object.entries(dataToWrite).forEach(([key, value]) => $.write(value, key)); + + // 输出到日志只输出特定的键值对 + // const { zsfc_iActivityId, zsfc_iFlowId, zsfc_accessToken, zsfc_openid } = dataToWrite; + // $.log({ zsfc_iActivityId, zsfc_iFlowId, zsfc_accessToken, zsfc_openid }); + $.log(dataToWrite) + + // 发送通知 + $.notice(`🏎️ 掌飞购物`, `✅ 获取商城数据成功!`, `请不要再次打开掌上飞车APP, 否则商城 Cookie 将失效!`); + + } + + } else { + /** + * ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 以下进行签到阶段 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ + */ + + // 获取会员状态 + $.isVip = await checkIsVip(); + if ($.isVip) $.log(`💎 尊贵的会员用户`); + + // todo 定义流水ID词典, 不清楚是否是周周更新或者月月更新 + idItems = { + dailyReward: { + 0: {iFlowId: "1028286", IdName: "周日签到"}, // 周日签到 + 1: {iFlowId: "1028292", IdName: "周一签到"}, // 周一签到 + 2: {iFlowId: "1028291", IdName: "周二签到"}, // 周二签到 + 3: {iFlowId: "1028290", IdName: "周三签到"}, // 周三签到 + 4: {iFlowId: "1028289", IdName: "周四签到"}, // 周四签到 + 5: {iFlowId: "1028288", IdName: "周五签到"}, // 周五签到 + 6: {iFlowId: "1028287", IdName: "周六签到"} // 周六签到 + }, + makeUpReward: {iFlowId: "1028285", IdName: "补签"}, // 周补签 + accumulative: { + 5: {iFlowId: "1028380", IdName: "月签5天"}, // 月签5 + 10: {iFlowId: "1028379", IdName: "月签10天"}, // 月签10 + 15: {iFlowId: "1028378", IdName: "月签15天"}, // 月签15 + 20: {iFlowId: "1028377", IdName: "月签20天"}, // 月签20 + 25: {iFlowId: "1028376", IdName: "月签25天"} // 月签25 + }, + dailyTask: { + 1: {iFlowId: "1028557", IdName: "查看动态"}, // 任务1 + 2: {iFlowId: "1028556", IdName: "浏览背包"}, // 任务2, 只有浏览背包可以完成 + 3: {iFlowId: "1028555", IdName: "游戏活跃"} // 任务3 + }, + weeklyTask: { + 1: {iFlowId: "1028554", IdName: "进行游戏"}, // 任务4 + 2: {iFlowId: "1028553", IdName: "花费点券"} // 任务5 + } + }; + + // 每日签到 + var { iFlowId, IdName } = idItems.dailyReward[new Date().getDay()]; + await claimGift(iFlowId, IdName); + + // 获取本月累签天数并判断是否有累签奖励 + const totalSignInDay = await getTotalSignInDays(); + if (idItems.accumulative[totalSignInDay]) { + var { iFlowId, IdName } = idItems.accumulative[totalSignInDay]; + await claimGift(iFlowId, IdName); + } + + // 浏览背包 + await openBackpack(); + + // 领取每日任务奖励 + for (var key in idItems.dailyTask) { + var { iFlowId, IdName } = idItems.dailyTask[key]; + await claimGift(iFlowId, IdName); + } + + // 判断为周末时领取每周对局任务奖励 + if (new Date().getDay() === 6 || new Date().getDay() === 7) { + for (var key in idItems.weeklyTask) { + var { iFlowId, IdName } = idItems.weeklyTask[key]; + await claimGift(iFlowId, IdName); + } + } + + // 显示签到结果通知 + if ($.checkInMsg && $.toObj($.read(`zsfc_treasure_log`) || `true`)) $.notice(`🏎️ 掌上飞车`, $.subtitle, $.checkInMsg, ``); + + /** + * ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 以下进行购物阶段 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ + */ + + // 读取到设置不进行购物 + if (!$.toObj($.read(`zsfc_shop`))) return $.log(`⭕ 设置为不执行购物`); + + // 读取到没有获取过商城数据 + if (!$.read(`zsfc_token`)) return $.notice(`🏎️ 掌飞购物`, `❌ 请先获取商城数据`, `打开掌上飞车,点击游戏并进入掌上商城`); + + // 获取当前点券和消费券 + const packBefore = await getPackInfo(`before`); + + // Cookie 已过期,程序终止 + if (!packBefore) return $.log(`❌ Cookie 已过期,请重新获取`), $.notice(`🏎️ 掌飞购物`, `❌ Cookie 已过期`, `打开掌上飞车,点击游戏并进入掌上商城`); + + // 获取当前余额 + const beforeLog = `✅ 当前共有${packBefore.money}点券,${packBefore.coupons}消费券`; + $.log(beforeLog); + if (new Date().getHours() < 16) return $.log(`🕒 每天16点后再执行购物操作`); + $.subtitle = beforeLog; + + // 判断当天是否为本月月尾2天以内 + $.lastDayOfMonth = checkLastDayOfMonth(2); + + // 读取要购买的商品名称并生成商品列表 + const shopName = $.read(`zsfc_bang_shopname`) || autoGetGameItem(); + const shopIdArray = await searchShop(shopName); + + // 无法在掌上商城中搜索到相关商品时终止程序 + if (!Object.keys(shopIdArray).length) return $.notice(`🏎️ 掌飞购物`, `❌ ${shopName} 未在商店中售卖`, `请在掌上商城中认真核对商品名称`); + + // 获取购物包 + const [shopArray, totalCount, unit] = getShopItems(shopIdArray, packBefore); + + // 开始购物循环 + if (shopArray.length) { + // 重置购买成功道具数量和失败道具数量为0 + let successBuyCounts = 0; + let failedBuyCounts = 0; + + const estimatedBydCounts = totalCount === 999 ? "1个" : totalCount; + const caption = totalCount === 999 ? "永久" : unit; + + $.log(`✅ 预计可购买${estimatedBydCounts}${caption}${shopName}`); + + // 开始执行购物函数 + for (let buyInfo of shopArray) { + let { count, id, idx } = buyInfo; + successBuyCounts += await purchaseItem(shopName, count, id, idx); + } + + if (successBuyCounts > 0) { + // 购买永久道具后为避免重复购买自动禁用购买脚本并重置道具名称 + if (totalCount === 999) $.write(`false`, `zsfc_shop`), $.write(``, `zsfc_bang_shopname`); + + $.shopMsg = `🎉 成功购买${estimatedBydCounts}${caption}${shopName}`; + failedBuyCounts = estimatedBydCounts - successBuyCounts; + if (failedBuyCounts > 0) { + $.shopMsg += `(未成功购买${failedBuyCounts}${caption})`; + } + } else { + $.shopMsg = `❌ 全部购买失败,共计${estimatedBydCounts}${caption}${shopName}`; + } + $.log($.shopMsg) + + // 获取剩余余额 + const packAfter = await getPackInfo(`after`); + const afterLog = `✅ 现在剩余${packAfter.money}点券,${packAfter.coupons}消费券`; + $.log(afterLog); + $.subtitle = afterLog; + + } else { + $.log(`⭕ ${$.lastDayOfMonth ? '余额' : '消费券'}不足以购买${shopName}`); + } + + // 显示购物结果通知 + if ($.shopMsg && $.toObj($.read(`zsfc_treasure_log`) || `true`)) $.notice(`🏎️ 掌飞购物`, $.subtitle, $.shopMsg, ``); + + } +})() + .catch((e) => $.notice(`🏎️ 掌上飞车`, '❌ 未知错误无法执行', e, '')) + .finally(() => $.done()); + + +/** + * 判断今天的日期和本月剩余天数是否小于N天。 + * + * @param {number} N - 传入数字,代表本月最后N天 + * @returns {boolean} - 返回匹布尔值 + */ +function checkLastDayOfMonth(N) { + // 初始化一个表示当前日期和时间的 today 对象 + let today = new Date(); + + // 获取当前月份的最后一天的日期 + let day = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate(); + + return (day - today.getDate()) < N; // 月底最后3天的计算方式是小于N而不能有等于 +} + +/** + * 从输入字符串中提取指定关键字的值。 + * + * @param {string} input - 输入字符串,要从中提取关键字的值。 + * @param {string} key - 要提取的关键字。 + * @returns {string} - 返回匹配到的关键字值,如果没有匹配到则返回空字符串。 + */ +function matchParam(input, key) { + const separator = input.includes("&") ? "&" : ";"; + const pattern = new RegExp(`${key}=([^${separator}]+)`); + const match = input.match(pattern); + return match ? match[1] : ''; +} + +/** + * @description 掌飞购物相关函数,获取当前月份对应的游戏道具。 + * @returns {string} 返回当前月份对应的游戏道具名称。 + */ +function autoGetGameItem() { + // 定义游戏道具的列表,包括普通改装道具和进阶改装道具 + const gameItems = [ + "进气系统+1", "点火装置+1", "引擎装置+1", // 普通改装道具, 燃料系统已经改29了, 不要买了 + // "进气系统+1", "燃料系统+1", "点火装置+1", "引擎装置+1", // 普通改装道具 + // "普通粒子推进", "普通阿尔法离合" // 进阶改装道具,我不需要,注释掉了 + ]; + + // 计算当前月份对应的游戏道具的索引 + const index = new Date().getMonth() % gameItems.length; + + // 返回当前月份对应的游戏道具名称 + return gameItems[index]; +} + +/** + * @description 掌飞购物相关函数,获取商店物品信息。 + * @param {object} shopInfo - 商店信息对象 + * @param {object} overage - 用户余额对象 + * @returns {[array, number, str]} - 返回购买的物品数组、总数和单位信息的数组 + */ +function getShopItems(shopInfo, overage) { + // 创建一个包含道具信息和空白数据列表的初始对象 + const info = {"Id": shopInfo.iId, "data": []}; + + // 根据用户会员状态获取道具折扣,判断道具类型并获取相应的购买数值 + const iMemeberRebate = $.isVip ? parseInt(shopInfo.iMemeberRebate) / 100 : 1; + const shopType = shopInfo.szItems[0].ItemNum !== ""; // 表示购买的道具是按数量购买 + const values = shopType ? shopInfo.szItems[0].ItemNum : shopInfo.szItems[0].ItemAvailPeriod; + + // 将物品数值转换成数组 + const numArray = values.split(',').filter(item => item !== '').map((item) => { + if (item === "-1") return 999; + return shopType ? parseInt(item) : parseInt(item) / 24; + }); + + // 根据价格排序道具数据 + const sortedData = shopInfo.szPrices.map((price, index) => ({ + price: parseInt(price.SuperMoneyPrice) * iMemeberRebate, + count: numArray[index], idx: index + })).sort((a, b) => b.count - a.count); + + // 将排序后的数据存入 info 对象 + sortedData.forEach(({ price, count, idx }) => { + info.data.push({ count, price, idx }); + }); + + // 初始化购买总数、物品数组和投入金额 + let totalCount = 0; + let purchasedItemsList = []; + let remMoney = $.lastDayOfMonth ? overage.money + overage.coupons : overage.coupons;y = overage.coupons; + + // 定义商品数据、最便宜商品序列(最便宜商品序列一定是列表最后一个) + const itemData = info.data; + const cheapestItemIndex = itemData.length - 1; + + for (let m = 0; m < itemData.length; m++) { + // 每次循环开始前把元素添加次数重置为0 + let pushCounts = 0; + + // 判断是否购买永久道具且传入的金额足够购买永久道具 + if (itemData[m].count === 999 && remMoney > itemData[m].price) { + purchasedItemsList.push({"count": 999, "id": info.Id, "idx": itemData[m].idx}); + totalCount = itemData[m].count; + info.unit = "永久"; + break; + } + + // 计算最大可购买的物品数量并更新总数和剩余金钱 + const maxPurchasableItems = Math.floor(remMoney / itemData[m].price); // 这是一个计算出的整数,表示根据当前余额和道具价格,最多可以购买的道具数量。 + thisTimeCost = maxPurchasableItems * itemData[m].price; // 这是一个累加的变量,用于跟踪本轮循环购买道具的总花费。 + totalCount += maxPurchasableItems * itemData[m].count; // 这是一个累加的变量,用于跟踪购买的总道具数量。 + remMoney -= maxPurchasableItems * itemData[m].price; // 这是当前可用的余额。在每次购买道具后,余额会根据购买的道具数量和价格进行更新,以反映购买后的余额。 + + // 将购买的物品加入数组 + for (let n = 0; n < maxPurchasableItems; n++) { + purchasedItemsList.push({ + "count": itemData[m].count, + "id": info.Id, + "idx": itemData[m].idx, + }); + pushCounts += 1; + } + + // 在购买数量道具情况下,非月尾判断是否可以购买最后一个物品 + if (remMoney < itemData[cheapestItemIndex].price && !$.lastDayOfMonth && shopType) { + const meetsThreshold = remMoney > itemData[cheapestItemIndex].price / Number(`1000000`); + const canAffordLastItem = remMoney + overage.money >= itemData[cheapestItemIndex].price; + + // 如果满足阈值条件,且消费券加点券的和大于最便宜一个道具的价格 + if (meetsThreshold && canAffordLastItem) { + purchasedItemsList.push({ + "count": itemData[cheapestItemIndex].count, + "id": info.Id, + "idx": itemData[cheapestItemIndex].idx, + }); + thisTimeCost += itemData[cheapestItemIndex].price; + totalCount += itemData[cheapestItemIndex].count; + pushCounts += 1; + } + + // 本轮花费大于0且本轮消费等于倒数第二阶梯的消费价格时,清空本轮添加的购买包 + if (thisTimeCost && thisTimeCost === itemData[cheapestItemIndex - 1].price) { + // 计算需要保留的元素数量、新的元素序列 + const itemsToKeep = purchasedItemsList.length - pushCounts; + const newIndex = cheapestItemIndex - 1; + + // 使用 slice 创建一个新数组,仅保留需要的元素,并添加新元素到数组末尾 + purchasedItemsList = purchasedItemsList.slice(0, itemsToKeep); + purchasedItemsList.push({ + "count": itemData[newIndex].count, + "id": info.Id, + "idx": itemData[newIndex].idx, + }); + } + + break; + } + } + + return [purchasedItemsList, totalCount, shopType ? "个" : "天"]; +} + +/** + * @description 掌飞签到相关函数,获取累签天数的情况 + * @returns {Promise<string>} 返回累签天数 + */ +async function getTotalSignInDays() { + // 初始化总签到天数 + let totalSignInDays; + + // 构建请求体 + const options = { + url: `https://comm.ams.game.qq.com/ams/ame/amesvr?${$.queryStr({ + "sServiceType": "speed", // params部分必须加上 sServiceType=speed 参数 + "iActivityId": isRequest ? $.iActivityId : $.read(`zsfc_iActivityId`) + })}`, + headers: { + "cookie": $.cookieStr({ + "access_token": $.read(`zsfc_accessToken`), + "acctype": "qc", + "appid": "1105330667", + "openid": $.read(`zsfc_openid`) + }), + }, + body: $.queryStr({ + "iActivityId": isRequest ? $.iActivityId : $.read(`zsfc_iActivityId`), + "iFlowId": isRequest ? $.iFlowId : $.read(`zsfc_iFlowId`), + "g_tk": "1842395457", + "witchDay": "1", // 不知道为什么需要传一个 witchDay 参数, 键值 1 也不清楚是什么意思 + }) + }; + + // 返回一个 Promise 对象,用于异步操作 + return new Promise(resolve => { + // 发送 POST 请求,获取累签天数 + $.post(options, (err, resp, data) => { + if (data) { + try { + // todo 目前暂定为 sOutValue5 因为猜测 sOutValue4 是本周签到天数, 可能还需要分析 sOutValue2 漏签的情况, 以及 sOutValue7 是否可补签 + totalSignInDays = $.toObj(data).modRet.sOutValue5; + + if (!isRequest) { + $.subtitle = `📅 累计签到 ${totalSignInDays} 天`; + $.log($.subtitle); + } + } catch {} + } else { + $.log(`❌ 获取累签天数时发生错误`); + $.log($.toStr(err)); + } + resolve(!isNaN(totalSignInDays) ? Number(totalSignInDays) : -1); + }); + }); +} + +/** + * @description 掌飞签到相关函数,领取礼物函数 + * @param {string} giftId 礼物 ID + * @param {string} giftName 礼物名称 + */ +async function claimGift(giftId, giftName) { + // 构建请求体 + const options = { + url: `https://comm.ams.game.qq.com/ams/ame/amesvr?${$.queryStr({ + "sServiceType": "speed", // params部分必须加上 sServiceType=speed 参数 + "iActivityId": $.read(`zsfc_iActivityId`) + })}`, + headers: { + "Cookie": $.cookieStr({ + "access_token": $.read(`zsfc_accessToken`), + "acctype": "qc", + "appid": "1105330667", + "openid": $.read(`zsfc_openid`) + }) + }, + body: $.queryStr({ + "iActivityId": $.read(`zsfc_iActivityId`), + "iFlowId": giftId, + "g_tk": "1842395457" + }) + }; + + // 返回一个 Promise 对象,用于异步操作 + return new Promise(resolve => { + // 发送 POST 请求,获取领取结果 + $.post(options, (err, resp, data) => { + if (data) { + let body = $.toObj(data.replace(/\r|\n/ig, ``)); + if (body.msg.includes(`已经`)) { + $.log(`✅ ${giftName}: 已经领取`); + // $.checkInMsg += `, ${giftName}`; + } else if (body.msg.includes(`不满足`)) { + $.log(`⭕ ${giftName}: ${body.flowRet.sMsg}`); + } else { + const sPackageName = body.modRet.sPackageName.replace(/[,,]/g, ", "); + $.log(`✅ ${giftName}: ${sPackageName}`); + if ($.checkInMsg) { + $.checkInMsg += `,${sPackageName}`; + } else { + $.checkInMsg = `领取结果: 获得${sPackageName}` + } + } + } else { + $.log(`❌ ${giftName}: 发生错误`); + $.log($.toStr(err)); + } + resolve(); + }); + }); +} + +/** + * @description 掌飞签到相关函数,浏览背包 + * @returns {Promise<object>} 返回空的 Promise 对象。 + */ +async function openBackpack() { + // 构建请求体 + const options = { + url: `https://mwegame.qq.com/yoyo/dnf/phpgameproxypass`, + body: $.queryStr({ + uin: $.read(`zsfc_uin`), + areaId: $.read(`zsfc_areaId`), + userId: $.read(`zsfc_userId`), + token: $.read(`zsfc_token`), + service: `dnf_getspeedknapsack`, + cGameId: `1003` // 必须传入这个参数才可以完成任务 + }) + }; + + // 返回一个 Promise 对象,用于异步操作 + return new Promise(resolve => { + // 发送 POST 请求 + $.post(options, (error, response, data) => { + // 只需要发送请求即可, 不进行任何处理 + resolve(); + }); + }); +} + +/** + * @description 掌飞购物相关函数,判断用户是否为会员用户。 + * @returns {Promise<object>} 包含会员状态的 Promise 对象。 + */ +async function checkIsVip() { + // 初始化会员情况默认为非会员 + let result = false; + + // 构建所请求的 URL 地址 + const url = `https://bang.qq.com/app/speed/treasure/index?${$.queryStr({ + 'roleId': $.read(`zsfc_roleId`), + 'uin': $.read(`zsfc_uin`), + 'areaId': $.read(`zsfc_areaId`), + })}`; + + // 返回一个 Promise 对象,用于异步操作 + return new Promise(resolve => { + // 发送 GET 请求,获取寻宝页面数据 + $.get(url, (error, response, data) => { + try { + if (data) { + // 提取userInfo和mapInfo的数据 + const userInfoData = eval(data.match(/window\.userInfo\s*=\s*eval\('([^']+)'\);/)?.[1]); + result = userInfoData.vip_flag !== 0; + } + } finally { + // 解析 Promise,将结果对象传递给 resolve 函数 + resolve(result); + } + }); + }); +} + +/** + * @description 掌飞购物相关函数,根据商品名称搜索商品信息 + * @param {string} shopName - 要搜索的商品名称 + * @returns {Promise<Object>} 包含商品信息的 Promise 对象 + */ +async function searchShop(shopName) { + // 初始化目标商品对象 + let targetShopObject = {}; + + // 构建请求体 + const options = { + url: `https://bang.qq.com/app/speed/mall/search?${$.queryStr({ + 'uin': $.read(`zsfc_uin`), + 'userId': $.read(`zsfc_userId`), + 'token': $.read(`zsfc_token`), + 'start': '0', + 'paytype': '1', // 按点券筛选 + 'order': '2', // 按点券筛选 + 'text': encodeURIComponent(shopName) + })}`, + headers: { Referer: `https://bang.qq.com/app/speed/mall/main2` }, + }; + + // 返回一个 Promise 对象,用于异步操作 + return new Promise(resolve => { + // 发送 POST 请求,获取商品信息 + $.post(options, (err, resp, data) => { + if (data) { + const body = $.toObj(data); + targetShopObject = body.data.find(item => item.szName === shopName); + } + // 解析 Promise,将结果对象传递给 resolve 函数 + resolve(targetShopObject); + }); + }); +} + +/** + * @description 掌飞购物相关函数,获取点券和消费券信息 + * @param {string} argument - 余额状态,可选值为 "before" 或 "after" + * @returns {Promise<object|false>} - 包含点券和消费券数量的对象,或者在获取失败时返回 false + */ +async function getPackInfo(argument) { + // 创建一个空对象,用于存储点券和消费券信息 + let result = {}; + + // 根据参数值设置状态文本 + const statu = (argument === "before") ? "当前" : "剩余"; + + // 构建请求体 + const options = { + url: `https://bang.qq.com/app/speed/mall/main2?${$.queryStr({ + 'areaId': $.read(`zsfc_areaId`), + 'accessToken': $.read(`zsfc_accessToken`), + 'token': $.read(`zsfc_token`), + 'uin': $.read(`zsfc_uin`), + 'userId': $.read(`zsfc_userId`), + })}` + }; + + // 输出日志,表示开始获取点券和消费券 + if (statu === "before") $.log(`🧑‍💻 开始获取${statu}点券和消费券`); + + // 返回一个 Promise 对象,用于异步操作 + return new Promise(resolve => { + // 发送 GET 请求,获取点券和消费券信息 + $.get(options, (err, resp, data) => { + if (data) { + // 将响应数据转换为字符串 + const body = data.toString(); + + // 使用正则表达式匹配点券和消费券数量 + money = body.match(/<b id="super_money">(\d+)<\/b>/)[1]; + coupons = body.match(/<b id="coupons">(\d+)<\/b>/)[1]; + + // 将点券和消费券数量存储在结果对象中 + result.money = Number(money); + result.coupons = Number(coupons); + } else { + // 如果获取失败,将结果对象设置为 false + result = false; + } + + // 解析 Promise,将结果对象传递给 resolve 函数 + resolve(result); + }); + }); +} + +/** + * @description 掌飞购物相关函数,购买道具 + * @param {string} name - 道具名称 + * @param {number} count - 购买数量 + * @param {string} id - 道具的唯一标识符 + * @param {string} idx - 道具的价格索引 + * @returns {Promise<number>} - 返回成功购买的道具数量 + */ +async function purchaseItem(name, count, id, idx) { + // 构建请求体 + const options = { + url: `https://bang.qq.com/app/speed/mall/getPurchase`, + headers: { + "Referer": `https://bang.qq.com/app/speed/mall/detail2` + }, + body: $.queryStr({ + 'areaId': $.read(`zsfc_areaId`), + 'token': $.read(`zsfc_token`), + 'userId': $.read(`zsfc_userId`), + 'uin': $.read(`zsfc_uin`), + 'pay_type': "1", + 'commodity_id': id, + 'price_idx': idx + }) + }; + + // 返回一个 Promise 对象,用于异步操作 + return new Promise(resolve => { + // 发送 POST 请求,购买道具 + $.post(options, (err, resp, data) => { + if (data) { + // 将响应数据转换为对象 + const body = $.toObj(data); + + // 提取响应中的消息 + const msg = body.msg; + + // 检查响应结果,如果购买失败,输出错误消息 + if (body.res == -1) { + $.log(`❌ ${msg}`); + } else { + // 如果购买成功,将成功购买的道具数量设置为购买数量 + totalCount = count; + } + } else { + // 如果发生错误,输出错误消息和错误信息 + $.log(`❌ 购买${name}时发生错误`); + $.log($.toStr(err)); + } + + // 解析 Promise,将成功购买的道具数量传递给 resolve 函数 + resolve(totalCount ? totalCount : 0); + }); + }); +} + +/** + * @description 获取青龙面板令牌 + * @returns {Promise<string|boolean>} 返回一个包含青龙面板令牌或布尔值的 Promise。 + */ +async function qlToken() { + // 初始化访问令牌 + let accessToken; + + // 构建请求体 + const options = { + url: `${$.qlUrl}/open/auth/token?client_id=${$.qlId}&client_secret=${$.qlSecret}` + }; + // 返回一个 Promise 对象,用于异步操作 + return new Promise(resolve => { + // 发送 GET 请求,获取token令牌 + $.get(options, (err, resp, data) => { + if (data) { + const responseBody = $.toObj(data); + if (responseBody.code === 200) { + // 获取成功 + accessToken = responseBody.data.token; + } else { + accessToken = false; + } + } + resolve(accessToken); + }); + }); +} + +/** + * @description 搜索环境变量并生成新的请求体部分参数 + * @param {string} envsName - 新环境变量的名称 + * @param {string} envsValue - 新环境变量的具体值 + * @param {string} envsRemarks - 新环境变量的备注名 + * @returns {Promise<object|Array|boolean>} 返回一个请求体对象或列表或布尔值的 Promise。 + */ +async function qlEnvsSearch(envsName, envsValue, envsRemarks) { + // 初始化请求体的变量名 + let requestPayload; + + // 构建请求体 + const options = { + url: `${$.qlUrl}/open/envs?searchValue=${envsName}`, + headers: { "Authorization": `Bearer ${$.qlToken}` } + }; + + // 返回一个 Promise 对象,用于异步操作 + return new Promise(resolve => { + // 发送 GET 请求,搜索指定变量 + $.get(options, (err, resp, data) => { + if (data) { + const responseBody = $.toObj(data).data; + if (responseBody.length === 1) { + // 找到匹配的环境变量,生成单个请求体对象 + const matchingEnv = responseBody[0]; + if (matchingEnv.value === envsValue) { + requestPayload = false; + } else { + requestPayload = { + 'id': matchingEnv.id, + 'name': envsName, + 'value': envsValue, + 'remarks': envsRemarks + }; + } + } else { + // 未找到匹配的环境变量,生成包含一个对象的数组 + requestPayload = [{ + 'name': envsName, + 'value': envsValue, + 'remarks': envsRemarks + }]; + } + } + resolve(requestPayload); + }); + }); +} + +/** + * @description 编辑青龙面板的环境变量 + * @param {object} data - 请求参数 + */ +async function qlEnvsEdit(data) { + // 构建请求体 + const options = { + url: `${$.qlUrl}/open/envs`, + headers: { "Authorization": `Bearer ${$.qlToken}` }, + body: data + }; + + // 返回一个 Promise 对象,用于异步操作 + return new Promise(resolve => { + // 判断请求方法(post还是put) + const requestMethod = Array.isArray(data) ? $.post : $.put; + requestMethod(options, (err, resp, responseData) => { + if (responseData) { + let body = $.toObj(responseData); + // 根据返回的状态码处理结果 + if (body.code !== 200) { + $.log(`❌ 上传青龙面板失败`); + } + } + resolve(); // 完成Promise + }); + }); +} + +/** + * @description 创建一个名为 Env 的构造函数,用于处理环境相关操作。 + * @param {string} name - 环境名称 + */ +function Env(name) { + // 判断当前环境是否为 Loon + const isLoon = typeof $loon !== "undefined"; + // 判断当前环境是否为 Surge + const isSurge = typeof $httpClient !== "undefined" && !isLoon; + // 判断当前环境是否为 QuantumultX + const isQX = typeof $task !== "undefined"; + + // 定义 read 方法,用于读取数据 + const read = (key) => { + if (isLoon || isSurge) return $persistentStore.read(key); + if (isQX) return $prefs.valueForKey(key); + }; + + // 定义 write 方法,用于写入数据 + const write = (key, value) => { + if (isLoon || isSurge) return $persistentStore.write(key, value); + if (isQX) return $prefs.setValueForKey(key, value); + }; + + // 定义 notice 方法,用于发送通知 + const notice = (title, subtitle, message, url) => { + if (isLoon) $notification.post(title, subtitle, message, url); + if (isSurge) $notification.post(title, subtitle, message, { url }); + if (isQX) $notify(title, subtitle, message, { "open-url": url }); + }; + + // 定义 get 方法,用于发送 GET 请求 + const get = (url, callback) => { + if (isLoon || isSurge) $httpClient.get(url, callback); + if (isQX) {url.method = `GET`; $task.fetch(url).then((resp) => callback(null, {}, resp.body))}; + }; + + // 定义 post 方法,用于发送 POST 请求 + const post = (url, callback) => { + if (isLoon || isSurge) $httpClient.post(url, callback); + if (isQX) {url.method = `POST`; $task.fetch(url).then((resp) => callback(null, {}, resp.body))}; + }; + + // 定义 put 方法,用于发送 PUT 请求 + const put = (url, callback) => { + if (isLoon || isSurge) $httpClient.put(url, callback) + if (isQX) {url.method = 'PUT'; $task.fetch(url).then((resp) => callback(null, {}, resp.body))}; + }; + + // 定义 toObj 方法,用于将字符串转为对象 + const toObj = (str) => JSON.parse(str); + + // 定义 toStr 方法,用于将对象转为字符串 + const toStr = (obj) => JSON.stringify(obj); + + // 定义 queryStr 方法,用于将对象转为可以请求的字符串 + const queryStr = (obj, str) => { + return Object.keys(obj) + .map(key => `${key}=${obj[key]}`) + .join('&'); + }; + + const cookieStr = (obj) => { + return Object.keys(obj) + .map(key => `${key}=${obj[key]}`) + .join('; '); + } + + // 定义 log 方法,用于输出日志 + const log = (message) => console.log(message); + + // 定义 done 方法,用于结束任务 + const done = (value = {}) => $done(value); + + // 返回包含所有方法的对象 + return { name, read, write, notice, get, post, put, toObj, toStr, queryStr, cookieStr, log, done }; +} diff --git a/zsfc/zsfc.treasure.js b/zsfc/zsfc.treasure.js new file mode 100644 index 000000000..5294acccb --- /dev/null +++ b/zsfc/zsfc.treasure.js @@ -0,0 +1,531 @@ +/** + * + * 使用方法:打开掌上飞车APP, 点击下方游戏栏,然后点击每日寻宝即可获取所需数据。 + * 注意事项:目前只能每天打开掌飞并进入寻宝页面进行寻宝,非常麻烦,准备弃坑~ + * + * hostname: bang.qq.com + * + * type: http-request + * regex: ^https?://bang\.qq\.com/app/speed/treasure/index\?* + * script-path: https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js + * requests-body: 1 + * + * type: cron + * cron: 0 0 11-16/1 * * * + * script-path: https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js + * + * =============== Surge =============== + * 掌飞寻宝Cookie = type=http-request, pattern=^https?://bang\.qq\.com/app/speed/treasure/index\?*, requires-body=true, max-size=-1, script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js, script-update-interval=0, timeout=60 + * 掌飞寻宝 =type=cron, cronexp="0 0 11-16/1 * * *", wake-system=1, script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js, script-update-interval=0, timeout=30 + * + * =============== Loon =============== + * http-request ^https?://bang\.qq\.com/app/speed/treasure/index\?* script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js, requires-body=true, timeout=60, tag=掌飞寻宝Cookie + * cron "0 0 11-16/1 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js, tag=掌飞寻宝 + * + * =============== Quan X =============== + * ^https?://bang\.qq\.com/app/speed/treasure/index\?* url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js + * 0 0 11-16/1 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/zsfc/zsfc.treasure.js, tag=掌飞寻宝, enabled=true + * + */ + +/** + * 创建一个名为 $ 的环境变量实例,用于处理掌飞寻宝相关操作 + */ +const $ = new Env(`🏎️ 掌飞寻宝`) + +/** + * 检查是否为请求阶段 + */ +const isreq = typeof $request !== 'undefined'; + +/** + * 主函数,用于执行寻宝操作或设置请求数据 + */ +(async () => { + if (isreq) { + // 处理请求时的逻辑 + + // 提取请求的URL和其他数据 + const url = $request.url; + const cookie = $request.headers.cookie || $request.headers.Cookie; // QX、Loon都是用的Cookie + + // 对比 token 是否发生变化 + // if ($.read(`zsfc_token`) === matchStr(url, "token")) return; + + // 初始化 dataToWrite 词典,填充待写入内存的键值对 + const dataToWrite = { + 'zsfc_iActivityId': $.read(`zsfc_iActivityId`), // 掌飞寻宝无法抓取,只能读取签到页面的脚本获取情况 + "zsfc_accessToken": matchStr(url, "accessToken"), + "zsfc_openid": matchStr(cookie, "openid"), + "zsfc_token": matchStr(url, "token"), + "zsfc_roleId": matchStr(url, "roleId"), + "zsfc_userId": matchStr(url, "userId"), + "zsfc_areaId": matchStr(url, "areaId"), + 'zsfc_uin': matchStr(url, "uin"), + // 'zsfc_day': (new Date().getDate()).toString() + }; + + // 将请求数据写入内存 + Object.entries(dataToWrite).forEach(([key, value]) => $.write(value, key)); + + // 写入日志并发送通知 + if ($.toObj($.read(`zsfc_treasure_log`) || `true`)) { + $.log(dataToWrite); + $.notice($.name, `✅ 获取寻宝数据成功!`, `此脚本需每天打开掌上飞车APP并进入一次寻宝页面`, ``); + } + + // 检查并设置青龙相关变量 + if ($.read(`ql_url`) && $.read(`ql_client_id`) && $.read(`ql_client_secret`) && $.toObj($.read(`zsfc_upload_config`))) { + const qlUrlCache = $.read(`ql_url`); + $.qlUrl = qlUrlCache.charAt(qlUrlCache.length - 1) === '/' ? qlUrlCache.slice(0, -1) : qlUrlCache; + $.qlId = $.read(`ql_client_id`); + $.qlSecret = $.read(`ql_client_secret`); + $.qlToken = await qlToken(); + + const qlEnvsName = `ZSFC_CONFIG`; + const qlEnvsValue = $.toStr(dataToWrite); + const qlEnvsRemarks = `掌飞商城`; + + // 获取青龙面板令牌,若成功则执行后续操作 + if ($.qlToken) { + const qlEnvsNewBody = await qlEnvsSearch(qlEnvsName, qlEnvsValue, qlEnvsRemarks); + if (!qlEnvsNewBody) return; // 环境变量的值没有发生变化,不需要进行操作 + + // 检查并处理环境变量的返回值类型 + if (Array.isArray(qlEnvsNewBody)) { + // 暂时无法完成新增操作,后续再修改 + $.log(`⭕ 手动添加名为 ${qlEnvsName} 变量`); + } else { + await qlEnvsEdit(qlEnvsNewBody); + } + } else { + $.log("❌ 无法获取 token,请检查青龙相关配置"); + } + } + + } else { + // 处理非请求时的逻辑 + + /** + * 2023.12.15 发现iOS端重开掌飞不会使token过期,因此无需检测 + */ + // 检查用户今天是否打开过寻宝页面 + // const date = (new Date().getDate()).toString(); + // if (date != $.read(`zsfc_day`)) return $.log(`❌ 今天未进过寻宝页面`); + + // 获取地图数据 + $.mapData = await fetchMapData(); + if (!Object.keys($.mapData).length) return $.log(`❌ 无法获取地图信息`); + if (!$.mapData.remainingTimes) return $.log(`⭕ 当天的寻宝次数已用完`); + + // 尊贵的紫钻用户 + if ($.mapData.isVip) $.log(`💎 尊贵的紫钻用户`); + + // 输出最高解锁星级信息和今日大吉地图 + $.log(`✅ 最高解锁星级:${'⭐️'.repeat($.mapData.starId * 1)}`); + $.log(`✅ 今日大吉地图:${$.mapData.mapName}`); + + // 等待当前分钟数除以5的秒数时间 + // await wait((new Date().getMinutes()) / 5); + + // 开始查询目前的寻宝状态 + treasureData = await performTreasureAction(`start`); + // if (!treasureData.timeLeft) return $.log(`❌ 无法获取寻宝状态`); + + if (treasureData.ending) { + // 寻宝完成,先结束寻宝再领取奖励 + $.log(`🧑‍💻 结束在${$.mapData.mapName}中寻宝`); + treasureData = await performTreasureAction(`end`); + + // 循环领取两个寻宝奖励 + for (let iFlowId of $.mapData.iFlowId) { + $.log(`✅ 恭喜你获得:${await claimTreasureReward(iFlowId)}`); + } + + // 今天还能寻宝,继续寻宝 + if (treasureData.todaycanTimes) { + $.log(`💨 还剩余${treasureData.todaycanTimes}次寻宝机会,继续寻宝`); + await performTreasureAction(`start`); + } + } else if (!treasureData.todaycanTimes) { + $.log(`⭕ 当天的寻宝次数已用完`); + } else if (treasureData.timeLeft > 597) { + $.log(`✅ 开始寻宝,将在${treasureData.timeLeft}秒后结束`); + } else { + $.log(`⭕ 正在寻宝中,将在${treasureData.timeLeft}秒后结束`); + } + + // 这个脚本不发送通知,静默运行 + // $.notice($.name, ``, ``, ``); + } +})() + .catch((e) => $.notice($.name, '❌ 未知错误无法寻宝', e, '')) + .finally(() => $.done()); + +/** + * 从输入字符串中提取指定关键字的值。 + * + * @param {string} input - 输入字符串,要从中提取关键字的值。 + * @param {string} key - 要提取的关键字。 + * @returns {string} - 返回匹配到的关键字值,如果没有匹配到则返回空字符串。 + */ +function matchStr(input, key) { + const separator = input.includes("&") ? "&" : ";"; + const pattern = new RegExp(`${key}=([^${separator}]+)`); + const match = input.match(pattern); + return match ? match[1] : ''; +} + +/** + * @description 等待一段时候。 + * @param {number} s - 等待时长。 + * @returns {Promise} Promise + */ + async function wait(s) { + $.log(`💤 程序休眠 ${s}s 后继续...`); + return new Promise((resolve) => { + setTimeout(resolve, s * 1000); + }); +} + +/** + * @description 异步获取地图数据操作。 + * @returns {Promise<object>} 包含地图数据的 Promise 对象。 + */ +async function fetchMapData() { + const params = { + 'roleId': $.read(`zsfc_roleId`), + 'uin': $.read(`zsfc_uin`), + 'areaId': $.read(`zsfc_areaId`), + }; + const url = `https://bang.qq.com/app/speed/treasure/index?${$.queryStr(params)}`; + $.log(`🧑‍💻 正在获取地图数据`); + let mapData = {}; + + return new Promise(resolve => { + $.get(url, (error, response, data) => { + if (data) { + // 提取userInfo和mapInfo的数据 + const [userInfoData, mapInfoData, todaycanTimes, todayTimes] = [ + data.match(/window\.userInfo\s*=\s*eval\('([^']+)'\);/)?.[1], + data.match(/window\.mapInfo\s*=\s*eval\('([^']+)'\);/)?.[1], + data.match(/"todaycanTimes":(\d+)/)?.[1], + data.match(/"todayTimes":(\d+)/)?.[1] + ].map(match => match && eval(`(${match})`)); + + // 判断今日可寻宝次数是否用完 + if ((todaycanTimes - todayTimes)) { // 次数没有用完 + // 固定 iFlowId 列表 + const iFlowIdArray = { + "1": ["856152", "856155"], // 1星 + "2": ["856156", "856157"], // 2星,100次 + "3": ["856158", "856159"], // 3星,300次 + "4": ["856160", "856161"], // 4星,500次 + "5": ["856162", "856163"], // 5星,紫钻地图 + "6": ["856164", "856165"] // 6星,皇族地图 + }; + + // 获取地图最高解锁星级 + const highestUnlockedStarId = Math.max( + ...Object.keys(userInfoData.starInfo) // 转化为数组 + .filter(starId => userInfoData.starInfo[starId] === 1) + ); + + // 获取大吉地图信息 + const luckyMap = mapInfoData[highestUnlockedStarId] + .find(map => map.isdaji === 1); + + mapData = { + remainingTimes: true, + starId: highestUnlockedStarId, + mapId: luckyMap.id, + isVip: userInfoData.vip_flag, + mapName: luckyMap.name, + iFlowId: iFlowIdArray[highestUnlockedStarId] + }; + } else { // 次数已经用完 + mapData = { + remainingTimes: false + }; + } + } else { + $.log(`❌ 获取地图数据时发生错误`); + $.log($.toStr(error)); + } + + resolve(mapData); + }); + }); +} + +/** + * @description 异步执行寻宝操作。 + * @param {string} action - 操作动作,可以是 "start" 或 "end"。 + * @returns {Promise<object>} - 包含操作结果的相关信息的 Promise 对象。 + */ +async function performTreasureAction(action) { + let isEnding = 0; + let timeRemaining = 0; + let remainingTimes = 1; + let digTreasureData = {}; + + const options = { + url:`https://bang.qq.com/app/speed/treasure/ajax/${action}DigTreasure`, + headers: { + "Referer": "https://bang.qq.com/app/speed/treasure/index", + "Cookie": `access_token=${$.read(`zsfc_accessToken`)}; acctype=qc; appid=1105330667; openid=${$.read(`zsfc_openid`)}` + }, + body: $.queryStr({ + "mapId": $.mapData.mapId, + "starId": $.mapData.starId, + // 普通寻宝1 600s -- 快捷寻宝2 10s + "type": $.mapData.isVip ? 2 : 1, + "areaId": $.read(`zsfc_areaId`), + "roleId": $.read(`zsfc_roleId`), + "userId": $.read(`zsfc_userId`), + "uin": $.read(`zsfc_roleId`), + "token": $.read(`zsfc_token`) + }) + }; + + // 发送 POST 异步请求并返回一个 Promise 对象 + return new Promise(resolve => { + $.post(options, (error, response, data) => { + if (data) { + const body = $.toObj(data); + if (action === "start") { + if (body.msg.includes(`用完`)) { + remainingTimes = 0; + } else { + const targetTimestamp = new Date(body.data.time).getTime(); + const tenMinutesLaterTimestamp = targetTimestamp + 10 * 60 * 1000; + if (Date.now() > tenMinutesLaterTimestamp) { + isEnding = 1; + } else { + timeRemaining = parseInt((tenMinutesLaterTimestamp - Date.now()) / 1000); + } + } + } else { + remainingTimes = body.data.todaycanTimes - body.data.todayTimes + } + + digTreasureData = { + ending: isEnding, + timeLeft: timeRemaining, + todaycanTimes: remainingTimes + }; + } else { + $.log(`❌ 寻宝时发生错误`); + $.log($.toStr(error)); + } + + resolve(digTreasureData); + }); + }); +} + +/** + * @description 异步执行领取寻宝奖励操作。 + * @param {number} flowId - 寻宝流水ID,用于标识领取的奖励。 + * @returns {Promise<string>} - 包含领取的奖励包名的 Promise 对象。 + */ +async function claimTreasureReward(flowId) { + let sPackageName; + + const options = { + url: `https://act.game.qq.com/ams/ame/amesvr?ameVersion=0.3&iActivityId=468228`, + headers: { + "Cookie": `access_token=${$.read(`zsfc_accessToken`)}; acctype=qc; appid=1105330667; openid=${$.read(`zsfc_openid`)}` + }, + body: $.queryStr({ + 'appid': '1105330667', + 'sArea': $.read(`zsfc_areaId`), + 'sRoleId': $.read(`zsfc_roleId`), + 'accessToken': $.read(`zsfc_accessToken`), + 'iActivityId': "468228", + 'iFlowId': flowId, + 'g_tk': '1842395457', + 'sServiceType': 'bb' + }) + } + + return new Promise(resolve => { + $.post(options, (error, response, data) => { + if (data) { + sPackageName = $.toObj(data).modRet.sPackageName; + } else { + $.log(`❌ 领取寻宝奖励时发生错误`); + $.log($.toStr(error)); + } + resolve(sPackageName); + }); + }); +} + +/** + * @description 获取青龙面板令牌 + * @returns {Promise<string|boolean>} 返回一个包含青龙面板令牌或布尔值的 Promise。 + */ +async function qlToken() { + let accessToken; // 更具体的变量名,表示访问令牌 + const options = { + url: `${$.qlUrl}/open/auth/token?client_id=${$.qlId}&client_secret=${$.qlSecret}` + }; + return new Promise(resolve => { + $.get(options, (err, resp, data) => { + if (data) { + const responseBody = $.toObj(data); + if (responseBody.code === 200) { + accessToken = responseBody.data.token; + } else { + accessToken = false; + } + } + resolve(accessToken); + }); + }); +} + +/** + * @description 搜索环境变量并生成新的请求体部分参数 + * @param {string} envsName - 新环境变量的名称 + * @param {string} envsValue - 新环境变量的具体值 + * @param {string} envsRemarks - 新环境变量的备注名 + * @returns {Promise<object|Array|boolean>} 返回一个请求体对象或列表或布尔值的 Promise。 + */ +async function qlEnvsSearch(envsName, envsValue, envsRemarks) { + let requestPayload; // 代表请求体的变量名更具体 + const options = { + url: `${$.qlUrl}/open/envs?searchValue=${envsName}`, + headers: { "Authorization": `Bearer ${$.qlToken}` } + }; + return new Promise(resolve => { + $.get(options, (err, resp, data) => { + if (data) { + const responseBody = $.toObj(data).data; + if (responseBody.length === 1) { + // 找到匹配的环境变量,生成单个请求体对象 + const matchingEnv = responseBody[0]; + if (matchingEnv.value === envsValue) { + requestPayload = false; + } else { + requestPayload = { + 'id': matchingEnv.id, + 'name': envsName, + 'value': envsValue, + 'remarks': envsRemarks + }; + } + } else { + // 未找到匹配的环境变量,生成包含一个对象的数组 + requestPayload = [{ + 'name': envsName, + 'value': envsValue, + 'remarks': envsRemarks + }]; + } + } + resolve(requestPayload); + }); + }); +} + +/** + * @description 编辑青龙面板的环境变量 + * @param {object} data - 请求参数 + */ +async function qlEnvsEdit(data) { + const options = { + url: `${$.qlUrl}/open/envs`, + headers: { "Authorization": `Bearer ${$.qlToken}` }, + body: data + }; + $.log(options.body) + return new Promise(resolve => { + // 判断请求方法(post还是put) + const requestMethod = Array.isArray(data) ? $.post : $.put; + requestMethod(options, (err, resp, responseData) => { + if (responseData) { + let body = $.toObj(responseData); + // 根据返回的状态码处理结果 + if (body.code !== 200) { + $.log(`❌ 上传青龙面板失败`); + $.log(body) + } + } + resolve(); // 完成Promise + }); + }); +} + +/** + * @description 创建一个名为 Env 的构造函数,用于处理环境相关操作。 + * @param {string} name - 环境名称 + */ +function Env(name) { + // 判断当前环境是否为 Loon + const isLoon = typeof $loon !== "undefined"; + // 判断当前环境是否为 Surge + const isSurge = typeof $httpClient !== "undefined" && !isLoon; + // 判断当前环境是否为 QuantumultX + const isQX = typeof $task !== "undefined"; + + // 定义 read 方法,用于读取数据 + const read = (key) => { + if (isLoon || isSurge) return $persistentStore.read(key); + if (isQX) return $prefs.valueForKey(key); + }; + + // 定义 write 方法,用于写入数据 + const write = (key, value) => { + if (isLoon || isSurge) return $persistentStore.write(key, value); + if (isQX) return $prefs.setValueForKey(key, value); + }; + + // 定义 notice 方法,用于发送通知 + const notice = (title, subtitle, message, url) => { + if (isLoon) $notification.post(title, subtitle, message, url); + if (isSurge) $notification.post(title, subtitle, message, { url }); + if (isQX) $notify(title, subtitle, message, { "open-url": url }); + }; + + // 定义 get 方法,用于发送 GET 请求 + const get = (url, callback) => { + if (isLoon || isSurge) $httpClient.get(url, callback); + if (isQX) {url.method = `GET`; $task.fetch(url).then((resp) => callback(null, {}, resp.body))}; + }; + + // 定义 post 方法,用于发送 POST 请求 + const post = (url, callback) => { + if (isLoon || isSurge) $httpClient.post(url, callback); + if (isQX) {url.method = `POST`; $task.fetch(url).then((resp) => callback(null, {}, resp.body))}; + }; + + // 定义 put 方法,用于发送 PUT 请求 + const put = (url, callback) => { + if (isLoon || isSurge) $httpClient.put(url, callback) + if (isQX) {url.method = 'PUT'; $task.fetch(url).then((resp) => callback(null, {}, resp.body))}; + }; + + // 定义 toObj 方法,用于将字符串转为对象 + const toObj = (str) => JSON.parse(str); + + // 定义 toStr 方法,用于将对象转为字符串 + const toStr = (obj) => JSON.stringify(obj); + + // 定义 queryStr 方法,用于将对象转为可以请求的字符串 + const queryStr = (obj) => { + return Object.keys(obj) + .map(key => `${key}=${obj[key]}`) + .join('&'); + }; + + // 定义 log 方法,用于输出日志 + const log = (message) => console.log(message); + + // 定义 done 方法,用于结束任务 + const done = (value = {}) => $done(value); + + // 返回包含所有方法的对象 + return { name, read, write, notice, get, post, put, toObj, toStr, queryStr, log, done }; +} diff --git a/zxhc/README.md b/zxhc/README.md new file mode 100644 index 000000000..ea5c3b712 --- /dev/null +++ b/zxhc/README.md @@ -0,0 +1,105 @@ +# 智行火车票 + +> 代码已同时兼容 Surge & QuanX, 使用同一份签到脚本即可 + +> QuanX 需要: v1.0.6-build195 及以后版本 (TestFlight) + +> 感谢 [@GideonSenku](https://github.com/GideonSenku) Commit + +## 配置 (Surge) + +```properties +[MITM] +m.suanya.cn + +[Script] +http-request ^https:\/\/m\.suanya\.cn/restapi/soa2/\d+/attendanceDay script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zxhc/zxhc.cookie.js, requires-body=true + +cron "10 0 0 * * *" script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/zxhc/zxhc.js +``` + +## 配置 (QuanX) + +```properties +[MITM] +m.suanya.cn + +[rewrite_local] +#&QuanX +^https:\/\/m\.suanya\.cn/restapi/soa2/\d+/attendanceDay url script-request-body chavyleung/zxhc/zxhc.cookie.js +# QuanTF +^https:\/\/m\.suanya\.cn/restapi/soa2/\d+/attendanceDay url script-request-body https://raw.githubusercontent.com/chavyleung/scripts/master/zxhc/zxhc.cookie.js + +[task_local] +1 0 * * * zxhc.js + +[task_remote] +1 0 * * * https://raw.githubusercontent.com/chavyleung/scripts/master/zxhc/zxhc.js +``` + +## 说明 + +1. 先把`m.suanya.cn`加到`[MITM]` +2. 再配置重写规则: + - Surge: 把两条远程脚本放到`[Script]` + - QuanX: 把`zxhc.cookie.js`和`zxhc.js`传到`On My iPhone - Quantumult X - Scripts` (传到 iCloud 相同目录也可, 注意要打开 quanx 的 iCloud 开关) +3. 打开 APP 手动签到一次: 访问下右下角 `个人中心` > `签到` +4. 系统提示: `获取Cookie: 成功` +5. 把获取 Cookie 的脚本注释掉 +6. 运行一次脚本, 如果提示重复签到, 那就算成功了! + +> 第 1 条脚本是用来获取 cookie 的, 用浏览器访问一次获取 cookie 成功后就可以删掉或注释掉了, 但请确保在`登录成功`后再获取 cookie. + +> 第 2 条脚本是签到脚本, 每天`00:00:10`执行一次. + +## 常见问题 + +1. 无法写入 Cookie + + - 检查 Surge 系统通知权限放开了没 + - 如果你用的是 Safari, 请尝试在浏览地址栏`手动输入网址`(不要用复制粘贴) + +2. 写入 Cookie 成功, 但签到不成功 + + - 看看是不是在登录前就写入 Cookie 了 + - 如果是,请确保在登录成功后,再尝试写入 Cookie + +3. 为什么有时成功有时失败 + + - 很正常,网络问题,哪怕你是手工签到也可能失败(凌晨签到容易拥堵就容易失败) + - 暂时不考虑代码级的重试机制,但咱有配置级的(暴力美学): + + - `Surge`配置: + + ```properties + # 没有什么是一顿饭解决不了的: + cron "10 0 0 * * *" script-path=xxx.js # 每天00:00:10执行一次 + # 如果有,那就两顿: + cron "20 0 0 * * *" script-path=xxx.js # 每天00:00:20执行一次 + # 实在不行,三顿也能接受: + cron "30 0 0 * * *" script-path=xxx.js # 每天00:00:30执行一次 + + # 再粗暴点,直接: + cron "* */60 * * * *" script-path=xxx.js # 每60分执行一次 + ``` + + - `QuanX`配置: + + ```properties + [task_local] + 1 0 * * * xxx.js # 每天00:01执行一次 + 2 0 * * * xxx.js # 每天00:02执行一次 + 3 0 * * * xxx.js # 每天00:03执行一次 + + */60 * * * * xxx.js # 每60分执行一次 + ``` + +## 感谢 + +[@NobyDa](https://github.com/NobyDa) + +[@lhie1](https://github.com/lhie1) + +[@ConnersHua](https://github.com/ConnersHua) + +[@GideonSenku](https://github.com/GideonSenku) diff --git a/zxhc/zxhc.cookie.js b/zxhc/zxhc.cookie.js new file mode 100644 index 000000000..185df9be7 --- /dev/null +++ b/zxhc/zxhc.cookie.js @@ -0,0 +1,19 @@ +const $ = new Env('智行火车') +const signurlKey = 'senku_signurl_zxhc' +const signheaderKey = 'senku_signheader_zxhc' +const signbodyKey = 'senku_signbody_zxhc' + +!(async () => { + if ($request && $request.method != 'OPTIONS') { + const signheaderVal = JSON.stringify($request.headers) + const signbodyVal = $request.body || '' + if (signheaderVal) $.setdata(signheaderVal, signheaderKey) + if (signbodyVal) $.setdata(signbodyVal, signbodyKey) + $.msg($.name, '获取Cookie: 成功', '') + } +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +// prettier-ignore +function Env(e,t){class s{constructor(e){this.env=e}send(e,t="GET"){e="string"==typeof e?{url:e}:e;let s=this.get;"POST"===t&&(s=this.post);const i=new Promise(((t,i)=>{s.call(this,e,((e,s,o)=>{e?i(e):t(s)}))}));return e.timeout?((e,t=1e3)=>Promise.race([e,new Promise(((e,s)=>{setTimeout((()=>{s(new Error("请求超时"))}),t)}))]))(i,e.timeout):i}get(e){return this.send.call(this.env,e)}post(e){return this.send.call(this.env,e,"POST")}}return new class{constructor(e,t){this.logLevels={debug:0,info:1,warn:2,error:3},this.logLevelPrefixs={debug:"[DEBUG] ",info:"[INFO] ",warn:"[WARN] ",error:"[ERROR] "},this.logLevel="info",this.name=e,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,t),this.log("",`🔔${this.name}, 开始!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(e,t=null){try{return JSON.parse(e)}catch{return t}}toStr(e,t=null,...s){try{return JSON.stringify(e,...s)}catch{return t}}getjson(e,t){let s=t;if(this.getdata(e))try{s=JSON.parse(this.getdata(e))}catch{}return s}setjson(e,t){try{return this.setdata(JSON.stringify(e),t)}catch{return!1}}getScript(e){return new Promise((t=>{this.get({url:e},((e,s,i)=>t(i)))}))}runScript(e,t){return new Promise((s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let o=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");o=o?1*o:20,o=t&&t.timeout?t.timeout:o;const[r,a]=i.split("@"),n={url:`http://${a}/v1/scripting/evaluate`,body:{script_text:e,mock_type:"cron",timeout:o},headers:{"X-Key":r,Accept:"*/*"},policy:"DIRECT",timeout:o};this.post(n,((e,t,i)=>s(i)))})).catch((e=>this.logErr(e)))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const e=this.path.resolve(this.dataFile),t=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(e),i=!s&&this.fs.existsSync(t);if(!s&&!i)return{};{const i=s?e:t;try{return JSON.parse(this.fs.readFileSync(i))}catch(e){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const e=this.path.resolve(this.dataFile),t=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(e),i=!s&&this.fs.existsSync(t),o=JSON.stringify(this.data);s?this.fs.writeFileSync(e,o):i?this.fs.writeFileSync(t,o):this.fs.writeFileSync(e,o)}}lodash_get(e,t,s){const i=t.replace(/\[(\d+)\]/g,".$1").split(".");let o=e;for(const e of i)if(o=Object(o)[e],void 0===o)return s;return o}lodash_set(e,t,s){return Object(e)!==e||(Array.isArray(t)||(t=t.toString().match(/[^.[\]]+/g)||[]),t.slice(0,-1).reduce(((e,s,i)=>Object(e[s])===e[s]?e[s]:e[s]=Math.abs(t[i+1])>>0==+t[i+1]?[]:{}),e)[t[t.length-1]]=s),e}getdata(e){let t=this.getval(e);if(/^@/.test(e)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(e),o=s?this.getval(s):"";if(o)try{const e=JSON.parse(o);t=e?this.lodash_get(e,i,""):t}catch(e){t=""}}return t}setdata(e,t){let s=!1;if(/^@/.test(t)){const[,i,o]=/^@(.*?)\.(.*?)$/.exec(t),r=this.getval(i),a=i?"null"===r?null:r||"{}":"{}";try{const t=JSON.parse(a);this.lodash_set(t,o,e),s=this.setval(JSON.stringify(t),i)}catch(t){const r={};this.lodash_set(r,o,e),s=this.setval(JSON.stringify(r),i)}}else s=this.setval(e,t);return s}getval(e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(e);case"Quantumult X":return $prefs.valueForKey(e);case"Node.js":return this.data=this.loaddata(),this.data[e];default:return this.data&&this.data[e]||null}}setval(e,t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(e,t);case"Quantumult X":return $prefs.setValueForKey(e,t);case"Node.js":return this.data=this.loaddata(),this.data[t]=e,this.writedata(),!0;default:return this.data&&this.data[t]||null}}initGotEnv(e){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,e&&(e.headers=e.headers?e.headers:{},e&&(e.headers=e.headers?e.headers:{},void 0===e.headers.cookie&&void 0===e.headers.Cookie&&void 0===e.cookieJar&&(e.cookieJar=this.ckjar)))}get(e,t=(()=>{})){switch(e.headers&&(delete e.headers["Content-Type"],delete e.headers["Content-Length"],delete e.headers["content-type"],delete e.headers["content-length"]),e.params&&(e.url+="?"+this.queryStr(e.params)),void 0===e.followRedirect||e.followRedirect||((this.isSurge()||this.isLoon())&&(e["auto-redirect"]=!1),this.isQuanX()&&(e.opts?e.opts.redirection=!1:e.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(e.headers=e.headers||{},Object.assign(e.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(e,((e,s,i)=>{!e&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),t(e,s,i)}));break;case"Quantumult X":this.isNeedRewrite&&(e.opts=e.opts||{},Object.assign(e.opts,{hints:!1})),$task.fetch(e).then((e=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=e;t(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)}),(e=>t(e&&e.error||"UndefinedError")));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(e),this.got(e).on("redirect",((e,t)=>{try{if(e.headers["set-cookie"]){const s=e.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),t.cookieJar=this.ckjar}}catch(e){this.logErr(e)}})).then((e=>{const{statusCode:i,statusCode:o,headers:r,rawBody:a}=e,n=s.decode(a,this.encoding);t(null,{status:i,statusCode:o,headers:r,rawBody:a,body:n},n)}),(e=>{const{message:i,response:o}=e;t(i,o,o&&s.decode(o.rawBody,this.encoding))}));break}}post(e,t=(()=>{})){const s=e.method?e.method.toLocaleLowerCase():"post";switch(e.body&&e.headers&&!e.headers["Content-Type"]&&!e.headers["content-type"]&&(e.headers["content-type"]="application/x-www-form-urlencoded"),e.headers&&(delete e.headers["Content-Length"],delete e.headers["content-length"]),void 0===e.followRedirect||e.followRedirect||((this.isSurge()||this.isLoon())&&(e["auto-redirect"]=!1),this.isQuanX()&&(e.opts?e.opts.redirection=!1:e.opts={redirection:!1})),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(e.headers=e.headers||{},Object.assign(e.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](e,((e,s,i)=>{!e&&s&&(s.body=i,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),t(e,s,i)}));break;case"Quantumult X":e.method=s,this.isNeedRewrite&&(e.opts=e.opts||{},Object.assign(e.opts,{hints:!1})),$task.fetch(e).then((e=>{const{statusCode:s,statusCode:i,headers:o,body:r,bodyBytes:a}=e;t(null,{status:s,statusCode:i,headers:o,body:r,bodyBytes:a},r,a)}),(e=>t(e&&e.error||"UndefinedError")));break;case"Node.js":let i=require("iconv-lite");this.initGotEnv(e);const{url:o,...r}=e;this.got[s](o,r).then((e=>{const{statusCode:s,statusCode:o,headers:r,rawBody:a}=e,n=i.decode(a,this.encoding);t(null,{status:s,statusCode:o,headers:r,rawBody:a,body:n},n)}),(e=>{const{message:s,response:o}=e;t(s,o,o&&i.decode(o.rawBody,this.encoding))}));break}}time(e,t=null){const s=t?new Date(t):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(e)&&(e=e.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let t in i)new RegExp("("+t+")").test(e)&&(e=e.replace(RegExp.$1,1==RegExp.$1.length?i[t]:("00"+i[t]).substr((""+i[t]).length)));return e}queryStr(e){let t="";for(const s in e){let i=e[s];null!=i&&""!==i&&("object"==typeof i&&(i=JSON.stringify(i)),t+=`${s}=${i}&`)}return t=t.substring(0,t.length-1),t}msg(t=e,s="",i="",o={}){const r=e=>{const{$open:t,$copy:s,$media:i,$mediaMime:o}=e;switch(typeof e){case void 0:return e;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:e};case"Loon":case"Shadowrocket":return e;case"Quantumult X":return{"open-url":e};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{const r={};let a=e.openUrl||e.url||e["open-url"]||t;a&&Object.assign(r,{action:"open-url",url:a});let n=e["update-pasteboard"]||e.updatePasteboard||s;n&&Object.assign(r,{action:"clipboard",text:n});let h=e.mediaUrl||e["media-url"]||i;if(h){let e,t;if(h.startsWith("http"));else if(h.startsWith("data:")){const[s]=h.split(";"),[,i]=h.split(",");e=i,t=s.replace("data:","")}else{e=h,t=(e=>{const t={JVBERi0:"application/pdf",R0lGODdh:"image/gif",R0lGODlh:"image/gif",iVBORw0KGgo:"image/png","/9j/":"image/jpg"};for(var s in t)if(0===e.indexOf(s))return t[s];return null})(h)}Object.assign(r,{"media-url":h,"media-base64":e,"media-base64-mime":o??t})}return Object.assign(r,{"auto-dismiss":e["auto-dismiss"],sound:e.sound}),r}case"Loon":{const s={};let o=e.openUrl||e.url||e["open-url"]||t;o&&Object.assign(s,{openUrl:o});let r=e.mediaUrl||e["media-url"]||i;return r&&Object.assign(s,{mediaUrl:r}),console.log(JSON.stringify(s)),s}case"Quantumult X":{const o={};let r=e["open-url"]||e.url||e.openUrl||t;r&&Object.assign(o,{"open-url":r});let a=e.mediaUrl||e["media-url"]||i;a&&Object.assign(o,{"media-url":a});let n=e["update-pasteboard"]||e.updatePasteboard||s;return n&&Object.assign(o,{"update-pasteboard":n}),console.log(JSON.stringify(o)),o}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(t,s,i,r(o));break;case"Quantumult X":$notify(t,s,i,r(o));break;case"Node.js":break}if(!this.isMuteLog){let e=["","==============📣系统通知📣=============="];e.push(t),s&&e.push(s),i&&e.push(i),console.log(e.join("\n")),this.logs=this.logs.concat(e)}}debug(...e){this.logLevels[this.logLevel]<=this.logLevels.debug&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.debug}${e.map((e=>e??String(e))).join(this.logSeparator)}`))}info(...e){this.logLevels[this.logLevel]<=this.logLevels.info&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.info}${e.map((e=>e??String(e))).join(this.logSeparator)}`))}warn(...e){this.logLevels[this.logLevel]<=this.logLevels.warn&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.warn}${e.map((e=>e??String(e))).join(this.logSeparator)}`))}error(...e){this.logLevels[this.logLevel]<=this.logLevels.error&&(e.length>0&&(this.logs=[...this.logs,...e]),console.log(`${this.logLevelPrefixs.error}${e.map((e=>e??String(e))).join(this.logSeparator)}`))}log(...e){e.length>0&&(this.logs=[...this.logs,...e]),console.log(e.map((e=>e??String(e))).join(this.logSeparator))}logErr(e,t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,t,e);break;case"Node.js":this.log("",`❗️${this.name}, 错误!`,t,void 0!==e.message?e.message:e,e.stack);break}}wait(e){return new Promise((t=>setTimeout(t,e)))}done(e={}){const t=((new Date).getTime()-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${t} 秒`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(e);break;case"Node.js":process.exit(1)}}}(e,t)} diff --git a/zxhc/zxhc.js b/zxhc/zxhc.js new file mode 100644 index 000000000..d8a8b9f6b --- /dev/null +++ b/zxhc/zxhc.js @@ -0,0 +1,91 @@ +const $ = new Env('智行火车') +const signheaderKey = 'senku_signheader_zxhc' +const signbodyKey = 'senku_signbody_zxhc' +// 若智行更换 soa2 版本号,请将 18903 改为新版本号 +const signURL = 'https://m.suanya.cn/restapi/soa2/18903/attendanceDay' +const creditURL = 'https://m.suanya.cn/restapi/soa2/17679/get2020ZtripIntergrationDailyAttendanceInfo' + +!(async () => { + await sign() + await getCreditInfo() + showmsg() +})() + .catch((e) => $.logErr(e)) + .finally(() => $.done()) + +function sign() { + return new Promise((resolve) => { + const signheaderVal = $.getdata(signheaderKey) + const signBodyVal = $.getdata(signbodyKey) + if (!signheaderVal || !signBodyVal) { + return resolve(null) + } + const opts = { + url: signURL, + headers: JSON.parse(signheaderVal), + body: signBodyVal, + } + $.post(opts, (err, resp, data) => { + try { + $.log(`${$.name}, sign data: ${data}`) + const res = JSON.parse(data) + $.sign = res + resolve() + } catch (e) { + $.logErr(e, data) + reject(e) + } finally { + resolve() + } + }) + }) +} + +function getCreditInfo() { + return new Promise((resolve) => { + const creditHeaderVal = $.getdata(signheaderKey) + const creditBodyVal = $.getdata(signbodyKey) || '' + if (!creditHeaderVal || !creditBodyVal) { + return resolve({ credit: null, coupon: null }) + } + const opts = { + url: creditURL, + headers: $.toObj(creditHeaderVal, {}), + body: creditBodyVal, + } + $.post(opts, (err, resp, data) => { + try { + if (err || !data) return resolve({ credit: null, coupon: null }) + $.log(`${$.name}, credit data: ${data}`) + const res = JSON.parse(data) + $.credit = res + resolve() + } catch (e) { + $.logErr(e, data) + } finally { + resolve() + } + }) + }) +} + +function showmsg() { + let subTitle = '' + let detail = '' + if (!$.sign) { + subTitle = '签到: 失败' + detail = '请先获取 Cookie' + } else { + subTitle = `签到: ${$.sign.resultMessage}` + if ($.credit && ($.credit.credit != null || $.credit.coupon != null)) { + const parts = [] + if ($.credit.credit != null) parts.push(`积分: ${$.credit.credit}`) + if ($.credit.coupon != null) parts.push(`优惠券: ${$.credit.coupon}`) + detail = parts.join(' ') + } + } + $.msg($.name, subTitle, detail) +} + +// prettier-ignore +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)} \ No newline at end of file