From 149c1e556bdcf0517299da6cf8ddb24dd4a0dd86 Mon Sep 17 00:00:00 2001 From: Hex Date: Tue, 28 Feb 2023 20:27:10 +0800 Subject: [PATCH] update --- README.md | 3 +- env.js | 391 ++++++++++++++++++++++++++++++++++++++++ smzdm_lottery.js | 457 ++++------------------------------------------- smzdm_task.js | 404 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 829 insertions(+), 426 deletions(-) create mode 100644 env.js create mode 100644 smzdm_task.js diff --git a/README.md b/README.md index 5d34d7e..ddf560f 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,14 @@ * 每日签到 * 每日抽奖 +* 每日任务(Beta),只完成文章浏览和分享任务 ## 使用方法 ### 青龙拉库 ```bash -ql repo https://github.com/hex-ci/smzdm_script.git "" "" "" "" "py js" +ql repo https://github.com/hex-ci/smzdm_script.git "" "" "env.js" "" "py js" ``` 建议更改定时为随机时间 diff --git a/env.js b/env.js new file mode 100644 index 0000000..1c6febe --- /dev/null +++ b/env.js @@ -0,0 +1,391 @@ +module.exports = function Env(t, e) { + "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); + + 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("@"), + n = { + url: `http://${h}/v1/scripting/evaluate`, + body: { + script_text: t, + mock_type: "cron", + timeout: r + }, + headers: { + "X-Key": o, + Accept: "*/*" + } + }; + 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), + 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, 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_lottery.js b/smzdm_lottery.js index 7ac0e08..ed49771 100644 --- a/smzdm_lottery.js +++ b/smzdm_lottery.js @@ -5,8 +5,10 @@ cron: 10 8 * * * */ +const Env = require('./env'); +const notify = require('./sendNotify'); + const $ = new Env('什么值得买抽奖'); -const notify = $.isNode() ? require('./sendNotify') : ''; let cookiesArr = []; @@ -21,42 +23,6 @@ if (process.env.SMZDM_COOKIE) { } } -!(async () => { - if (!cookiesArr[0]) { - $.log('\n请先设置 SMZDM_COOKIE 环境变量'); - return; - } - - let notifyContent = ''; - - for (let i = 0; i < cookiesArr.length; i++) { - if (cookiesArr[i]) { - if (i > 0) { - $.log('\n延时 5 秒执行\n'); - await $.wait(5000) - } - - const cookie = cookiesArr[i]; - const sep = `\n******开始账号${i + 1}******\n`; - - const msg = await lottery(cookie); - - notifyContent += sep + msg + "\n"; - - $.log(sep + msg + "\n"); - } - } - - await notify.sendNotify($.name, notifyContent); -})() - .catch((e) => { - $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') - }) - .finally(() => { - $.done(); - }); - - // 每日抽奖 async function lottery(cookie) { let activeId = ''; @@ -116,394 +82,35 @@ async function lottery(cookie) { } } +!(async () => { + if (!cookiesArr[0]) { + $.log('\n请先设置 SMZDM_COOKIE 环境变量'); + return; + } -function Env(t, e) { - "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); - 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") + let notifyContent = ''; + + for (let i = 0; i < cookiesArr.length; i++) { + if (cookiesArr[i]) { + if (i > 0) { + $.log('\n延时 5 秒执行\n'); + await $.wait(5000) + } + + const cookie = cookiesArr[i]; + const sep = `\n******开始账号${i + 1}******\n`; + + const msg = await lottery(cookie); + + notifyContent += sep + msg + "\n"; + + $.log(sep + msg + "\n"); } } - 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("@"), - n = { - url: `http://${h}/v1/scripting/evaluate`, - body: { - script_text: t, - mock_type: "cron", - timeout: r - }, - headers: { - "X-Key": o, - Accept: "*/*" - } - }; - 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), - 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, 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) -} + + await notify.sendNotify($.name, notifyContent); +})().catch((e) => { + $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') +}).finally(() => { + $.done(); +}); diff --git a/smzdm_task.js b/smzdm_task.js new file mode 100644 index 0000000..6eb1fc6 --- /dev/null +++ b/smzdm_task.js @@ -0,0 +1,404 @@ +/* +什么值得买任务脚本 +项目地址: https://github.com/hex-ci/smzdm_script + +cron: 20 8 * * * +*/ + +const crypto = require('crypto') + +const Env = require('./env'); +const notify = require('./sendNotify'); + +const $ = new Env('什么值得买任务'); + +let cookiesArr = []; + +// 判断环境变量里面是否有 cookie +if (process.env.SMZDM_COOKIE) { + if (process.env.SMZDM_COOKIE.indexOf('&') > -1) { + cookiesArr = process.env.SMZDM_COOKIE.split('&'); + } else if (process.env.SMZDM_COOKIE.indexOf('\n') > -1) { + cookiesArr = process.env.SMZDM_COOKIE.split('\n'); + } else { + cookiesArr = [process.env.SMZDM_COOKIE]; + } +} + +const SIGN_KEY = "apr1$AwP!wRRT$gJ/q.X24poeBInlUJC"; +const DEFAULT_USER_AGENT = "smzdm_android_V10.2.0 rv:860 (Redmi Note 3;Android10;zh)smzdmapp"; + +function randomStr(len = 18) { + let char = "0123456789"; + let str = ""; + for (let i = 0; i < len; i++) { + str += char.charAt(Math.floor(Math.random() * char.length)); + } + return str; +} + +function parseJSON(str) { + try { + return JSON.parse(str); + } + catch (e) { + return {}; + } +} + +function getToken(cookie) { + const match = cookie.match(/sess=(.*?);/); + + return match ? match[1] : ''; +} + +function getHeaders(cookie) { + return { + 'User-Agent': process.env.SMZDM_USER_AGENT || DEFAULT_USER_AGENT, + 'Accept-Language': 'zh-Hans-CN;q=1', + 'Accept-Encoding': 'gzip', + 'Connection': 'Keep-Alive', + 'request_key': randomStr(18), + Cookie: cookie.replace('iphone', 'android').replace('iPhone', 'Android').replace('apk_partner_name=appstore', 'apk_partner_name=android') + }; +} + +// 添加公共参数并签名数据 +function signFormData(data) { + const newData = { + weixin: '1', + f: 'android', + v: '10.2.0', + sk: '1', + time: `${Math.round(new Date().getTime() / 1000)}000`, + ...data + }; + + const keys = Object.keys(newData).sort(); + const signData = keys.map(key => `${key}=${newData[key]}`).join('&'); + const sign = crypto.createHash('md5').update(`${signData}&key=${SIGN_KEY}`).digest('hex').toUpperCase(); + + return { + ...newData, + sign + }; +} + +// 获取任务列表 +async function getTaskList(cookie) { + try { + const response = await $.http.post({ + url: 'https://user-api.smzdm.com/task/list_new', + headers: getHeaders(cookie), + form: signFormData({ + get_total: '1', + limit: '100', + offset: '0', + point_type: '0', + token: getToken(cookie) + }) + }); + + const data = parseJSON(response.body); + + if (data.error_code == '0') { + return data.data.rows[0].cell_data.activity_task.accumulate_list.task_list + } + else { + return []; + } + } + catch (e) { + return []; + } +} + +// 执行浏览任务 +async function doViewTask(task, cookie) { + try { + $.log(`开始任务: ${task.task_name}`); + + $.log('延迟 11 秒模拟阅读文章'); + await $.wait(11000); + + let response = await $.http.post({ + url: 'https://user-api.smzdm.com/task/event_view_article', + headers: getHeaders(cookie), + form: signFormData({ + article_id: task.article_id, + channel_id: task.channel_id, + token: getToken(cookie) + }) + }); + + let data = parseJSON(response.body); + + if (data.error_code != '0') { + $.log('完成阅读失败!'); + + return { + isSuccess: false + }; + } + + $.log('延迟 3 秒领取奖励'); + await $.wait(3000) + + const rewardResult = await receiveReward(task.task_id, cookie); + + return rewardResult; + } + catch (e) { + $.log('任务异常!'); + + return { + isSuccess: false + }; + } +} + +async function receiveReward(taskId, cookie) { + try { + const response = await $.http.post({ + url: 'https://user-api.smzdm.com/task/activity_task_receive', + headers: getHeaders(cookie), + form: signFormData({ + task_id: taskId, + token: getToken(cookie) + }) + }); + + const data = parseJSON(response.body); + + if (data.error_code == '0') { + $.log(data.data.reward_msg); + + return { + isSuccess: true, + msg: data.data.reward_msg + }; + } + else { + $.log(`领取任务奖励失败!${response.body}`) + return { + isSuccess: false, + msg: '领取任务奖励失败!' + }; + } + } + catch (e) { + $.log('领取任务奖励请求失败!'); + return { + isSuccess: false, + msg: '领取任务奖励请求失败!' + }; + } +} + +async function getArticleList(cookie) { + const response = await $.http.get({ + url: 'https://post.smzdm.com/json_more/?tab_id=tuijian&filterUrl=tuijian', + headers: { + Accept: "*/*", + "Accept-Encoding": "gzip", + "Accept-Language": "zh-cn", + Connection: "keep-alive", + Referer: "https://post.smzdm.com/", + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148/smzdm 10.4.25 rv:93.4 (iPhone13,4; iOS 14.5; zh_CN)/iphone_smzdmapp/10.4.25/wkwebview/jsbv_1.0.0", + Cookie: cookie + } + }); + + const data = parseJSON(response.body); + + if (data.error_code == '0') { + // 目前只取前两个做任务 + return data.data.slice(0, 2); + } + else { + $.log(`获取文章列表失败: ${data}`); + return []; + } +} + +async function shareCallback(article, cookie) { + try { + const response = await $.http.post({ + url: 'https://user-api.smzdm.com/share/callback', + headers: getHeaders(cookie), + form: signFormData({ + article_id: article.article_hash_id, + channel_id: article.channel_id, + touchstone_event: '{}', + token: getToken(cookie) + }) + }); + + const data = parseJSON(response.body); + + if (data.error_code == '0') { + $.log('分享回调完成。'); + return { + isSuccess: true, + msg: '' + }; + } + else { + $.log(`分享回调失败!${response.body}`) + return { + isSuccess: false, + msg: '分享回调失败!' + }; + } + } + catch (e) { + $.log('分享回调请求失败!'); + return { + isSuccess: false, + msg: '分享回调请求失败!' + }; + } +} + +async function shareArticleDone(article, cookie) { + try { + const response = await $.http.post({ + url: 'https://user-api.smzdm.com/share/article_reward', + headers: getHeaders(cookie), + form: signFormData({ + article_id: article.article_hash_id, + channel_id: article.channel_id, + token: getToken(cookie) + }) + }); + + const data = parseJSON(response.body); + + if (data.error_code == '0') { + $.log('完成分享成功。'); + return { + isSuccess: true, + msg: '' + }; + } + else { + $.log('完成分享失败!'); + return { + isSuccess: false, + msg: '完成分享失败!' + }; + } + } + catch (e) { + $.log('完成分享请求失败!'); + return { + isSuccess: false, + msg: '完成分享请求失败!' + }; + } +} + +// 执行分享任务 +async function doShareTask(task, cookie) { + $.log(`开始任务: ${task.task_name}`); + + try { + const articles = await getArticleList(cookie); + + for (let i = 0; i < articles.length; i++) { + $.log(`开始分享第 ${i + 1} 篇文章...`); + + const article = articles[i]; + + await shareCallback(article, cookie); + + $.log('等候 3 秒'); + $.wait(3000); + + await shareArticleDone(article, cookie); + + $.log('等候 5 秒'); + $.wait(5000); + } + + $.log('延迟 3 秒领取奖励'); + await $.wait(3000) + + const rewardResult = await receiveReward(task.task_id, cookie); + + return rewardResult; + } + catch (e) { + return { + isSuccess: false + }; + } +} + +async function run(cookie) { + const tasks = await getTaskList(cookie); + + let count = 0; + + for (let i = 0; i < tasks.length; i++) { + const task = tasks[i]; + + if (task.task_status == '2' && task.task_event_type == 'interactive.view.article') { + const result = await doViewTask(task, cookie); + + if (result.isSuccess) { + count++; + } + + $.log('等候 5 秒'); + $.wait(5000); + } + else if (task.task_status == '2' && task.task_event_type == 'interactive.share') { + const result = await doShareTask(task, cookie); + + if (result.isSuccess) { + count++; + } + + $.log('等候 5 秒'); + $.wait(5000); + } + } + + return `成功完成任务数: ${count}`; +} + +!(async () => { + if (!cookiesArr[0]) { + $.log('\n请先设置 SMZDM_COOKIE 环境变量'); + return; + } + + let notifyContent = ''; + + for (let i = 0; i < cookiesArr.length; i++) { + if (cookiesArr[i]) { + if (i > 0) { + $.log('\n延迟 5 秒执行\n'); + await $.wait(5000) + } + + const cookie = cookiesArr[i]; + const sep = `\n******开始账号${i + 1}******\n`; + + $.log(sep); + + const msg = await run(cookie); + + $.log(msg); + + notifyContent += sep + msg + "\n"; + } + } + + await notify.sendNotify($.name, notifyContent); +})().catch((e) => { + $.log('', `❌ ${$.name}, 失败! 原因: ${e}!`, '') +}).finally(() => { + $.done(); +});