diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..6dabcdd8 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,5 @@ +## 处理自动化相关逻辑 +base: `workflows` <- compare `your branch` + +## 处理JueJinAPI相关逻辑 +base: `package` <- compare `your branch` diff --git a/.github/workflows/checkin.yml b/.github/workflows/checkin.yml index d5ba0ac4..bd7bfc40 100644 --- a/.github/workflows/checkin.yml +++ b/.github/workflows/checkin.yml @@ -17,6 +17,7 @@ jobs: EMAIL_PASS: ${{ secrets.EMAIL_PASS }} EMAIL_TO: ${{ secrets.EMAIL_TO }} DINGDING_WEBHOOK: ${{ secrets.DINGDING_WEBHOOK }} + PUSHPLUS_TOKEN: ${{ secrets.PUSHPLUS_TOKEN }} run: | yarn yarn checkin diff --git a/.github/workflows/seaGold.yml b/.github/workflows/seaGold.yml index 6a6ac87c..bdceead1 100644 --- a/.github/workflows/seaGold.yml +++ b/.github/workflows/seaGold.yml @@ -17,6 +17,7 @@ jobs: EMAIL_PASS: ${{ secrets.EMAIL_PASS }} EMAIL_TO: ${{ secrets.EMAIL_TO }} DINGDING_WEBHOOK: ${{ secrets.DINGDING_WEBHOOK }} + PUSHPLUS_TOKEN: ${{ secrets.PUSHPLUS_TOKEN }} run: | yarn yarn seaGold diff --git a/README.md b/README.md index 0f6826c0..fad00035 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,14 @@ 2. 仓库 -> Settings -> Secrets -> New repository secret, 添加Secrets变量如下: - | Name | Value | - | --- | --- | - | COOKIE | 掘金网站Cookie, 打开浏览器,登录 [掘金](https://juejin.cn/), 打开控制台DevTools -> Network,复制 cookie, **掘金Cookie有效期约1个月需定期更新.** | - | DINGDING_WEBHOOK | 钉钉机器人WEBHOOK | - | EMAIL_USER | 发件人邮箱地址(需要开启 SMTP) | - | EMAIL_PASS | 发件人邮箱密码(SMTP密码) | - | EMAIL_TO | 订阅人邮箱地址(收件人). 如需多人订阅使用 `, ` 分割, 例如: `a@163.com, b@qq.com` | + | Name | Value | 是否必填 | + | --- | --- | --- | + | COOKIE | 掘金网站Cookie, 打开浏览器,登录 [掘金](https://juejin.cn/), 打开控制台DevTools -> Network,复制 cookie, **掘金Cookie有效期约1个月需定期更新.** | ✅ | + | DINGDING_WEBHOOK | 钉钉机器人WEBHOOK | ❌ | + | EMAIL_USER | 发件人邮箱地址(需要开启 SMTP) | ❌ | + | EMAIL_PASS | 发件人邮箱密码(SMTP密码) | ❌ | + | EMAIL_TO | 订阅人邮箱地址(收件人). 如需多人订阅使用 `, ` 分割, 例如: `a@163.com, b@qq.com` | ❌ | + | PUSHPLUS_TOKEN | [Pushplus](http://www.pushplus.plus/) 官网免费申请,支持微信公众号、第三方webhook、企业微信、邮箱。 | ❌ | 3. 仓库 -> Actions, 检查Workflows并启用。 diff --git a/scripts/checkin.js b/scripts/checkin.js index 4be0d5fa..69341d77 100644 --- a/scripts/checkin.js +++ b/scripts/checkin.js @@ -1,6 +1,6 @@ const JuejinHelper = require("juejin-helper"); const utils = require("./utils/utils"); -const email = require("./utils/email"); +const pushMessage = require("./utils/pushMessage"); const env = require("./utils/env"); class CheckIn { @@ -199,18 +199,17 @@ async function run(args) { console.log(content); // 打印结果 - email({ + pushMessage({ subject: "掘金每日签到", text: content - }); - utils.dingding(content); + }) } run(process.argv.splice(2)).catch(error => { - email({ + pushMessage({ subject: "掘金每日签到", html: `Error
${error.message}
` - }); + }) throw error; }); diff --git a/scripts/juejin-console-script.js b/scripts/juejin-console-script.js deleted file mode 100644 index 886b7059..00000000 --- a/scripts/juejin-console-script.js +++ /dev/null @@ -1,214 +0,0 @@ -!(({ api, console, utils }) => { - const state = { - simulateSpeed: 100, // ms/进行一次抽奖 - sumPoint: 0, - pointCost: 0, - supplyPoint: 0, - freeCount: 0, - luckyValue: 0, - lottery: [], - counter: 0, - prize: {} - }; - - !(async () => { - await utils.wait(100); - console.clear(); - - try { - const checkInResult = await api.checkIn(); - console.log(checkInResult); - const incrPoint = checkInResult.incr_point; - console.log(`签到成功 +${incrPoint} 矿石`); - - const sumPoint = checkInResult.sum_point; - state.sumPoint = sumPoint; - } catch (e) { - console.log(e.message); - - const sumPoint = await api.getCurrentPoint(); - state.sumPoint = sumPoint; - } - - try { - const luckyusersResult = await api.getLotteriesLuckyUsers(); - if (luckyusersResult.count > 0) { - const no1LuckyUser = luckyusersResult.lotteries[0]; - const dipLuckyResult = await api.dipLucky(no1LuckyUser.history_id); - if (dipLuckyResult.has_dip) { - console.log(`今天你已经沾过喜气,明天再来吧!`); - } else { - console.log(`沾喜气 +${dipLuckyResult.dip_value} 幸运值`); - } - } - } catch {} - - console.log(`当前余额:${state.sumPoint} 矿石`); - - const luckyResult = await api.getMyLucky(); - state.luckyValue = luckyResult.total_value; - console.log(`当前幸运值:${state.luckyValue}/6000`); - - const lotteryConfig = await api.getLotteryConfig(); - state.lottery = lotteryConfig.lottery; - state.pointCost = lotteryConfig.point_cost; - state.freeCount = lotteryConfig.free_count; - state.sumPoint += state.freeCount * state.pointCost; - console.log(`免费抽奖次数: ${state.freeCount}`); - - const getProbabilityOfWinning = sumPoint => { - const pointCost = 200; - const luckyValueCost = 10; - const totalDrawsNumber = sumPoint / pointCost; - const perhapsSupplyNumber = Math.floor(totalDrawsNumber * (2 / 3)); - let supplyPoint = 0; - for(let i = 0; i < perhapsSupplyNumber; i++) { - supplyPoint += Math.ceil(Math.random() * 100) - } - const luckyValue = (sumPoint + supplyPoint) / pointCost * luckyValueCost + state.luckyValue; - return luckyValue / 6000; - } - - console.log(`预测您必中奖幸运概率: ${(getProbabilityOfWinning(state.sumPoint) * 100).toFixed(2) + "%"}`); - - console.log(`准备梭哈!`); - - console.logGroupStart("奖品实况"); - - const getSupplyPoint = draw => { - const maybe = [ - ["lottery_id", "6981716980386496552"], - ["lottery_name", "随机矿石"], - ["lottery_type", 1] - ]; - if (maybe.findIndex(([prop, value]) => draw[prop] === value) !== -1) { - const supplyPoint = Number.parseInt(draw.lottery_name); - if (!isNaN(supplyPoint)) { - return supplyPoint; - } - } - return 0; - }; - - const lottery = async () => { - const result = await api.drawLottery(); - state.sumPoint -= state.pointCost; - state.sumPoint += getSupplyPoint(result); - state.luckyValue += result.draw_lucky_value; - state.counter++; - state.prize[result.lottery_name] = (state.prize[result.lottery_name] || 0) + 1; - console.log(`[第${state.counter}抽]:${result.lottery_name}`); - }; - - while (state.freeCount > 0) { - await lottery(); - state.freeCount--; - await utils.wait(state.simulateSpeed); - } - - // while (state.sumPoint >= state.pointCost) { - // await lottery(); - // await utils.wait(state.simulateSpeed); - // } - - console.logGroupEnd("奖品实况"); - - console.log(`弹药不足,当前余额:${state.sumPoint} 矿石`); - console.log(`养精蓄锐来日再战!`); - - const recordInfo = []; - recordInfo.push("=====[战绩详情]====="); - if (state.counter > 0) { - const prizeList = []; - for (const key in state.prize) { - prizeList.push(`${key}: ${state.prize[key]}`); - } - recordInfo.push(...prizeList); - recordInfo.push("-------------------"); - recordInfo.push(`共计: ${state.counter}`); - } else { - recordInfo.push("暂无奖品"); - } - recordInfo.push("+++++++++++++++++++"); - recordInfo.push(`幸运值: ${state.luckyValue}/6000`); - recordInfo.push("==================="); - console.log(recordInfo.join("\n")); - })(); -})( - (() => { - const cs = (() => { - const result = []; - return { - done: () => (typeof completion === "function" && completion(result), (result.length = 0)), - log: msg => (result.push(msg), console.log(msg)), - clear: () => ((result.length = 0), console.clear()), - logGroupStart: name => console.group(name), - logGroupEnd: name => console.groupEnd(name) - }; - })(); - - const api = (() => { - return { - async fetch({ path, method, data }) { - return fetch(`https://api.juejin.cn/growth_api/v1${path}`, { - headers: { - cookie: document.cookie - }, - method: method, - body: JSON.stringify(data), - credentials: "include" - }) - .then(res => res.json()) - .then(res => { - if (res.err_no) { - throw new Error(res.err_msg); - } - return res.data; - }); - }, - async get(path) { - return this.fetch({ path, method: "GET" }); - }, - async post(path, data) { - return this.fetch({ path, method: "POST", data }); - }, - async getLotteryConfig() { - return this.get("/lottery_config/get"); - }, - async getCurrentPoint() { - return this.get("/get_cur_point"); - }, - async drawLottery() { - return this.post("/lottery/draw"); - }, - async checkIn() { - return this.post("/check_in"); - }, - async getLotteriesLuckyUsers() { - return this.post("/lottery_history/global_big", { - page_no: 1, - page_size: 5 - }); - }, - async dipLucky(lottery_history_id) { - return this.post("/lottery_lucky/dip_lucky", { - lottery_history_id - }); - }, - async getMyLucky() { - return this.post("/lottery_lucky/my_lucky"); - } - }; - })(); - - const utils = (() => { - return { - async wait(time = 0) { - return new Promise(resolve => setTimeout(resolve, time)); - } - }; - })(); - - return { console: cs, api, utils }; - })() -); diff --git a/scripts/lottery.js b/scripts/lottery.js deleted file mode 100644 index 73b5b25d..00000000 --- a/scripts/lottery.js +++ /dev/null @@ -1,137 +0,0 @@ -const api = require("./utils/juejin-api"); -const console = require("./utils/logger"); -const utils = require("./utils/utils"); -const email = require("./utils/email"); - -async function run(args) { - const state = { - simulateSpeed: 100, // ms/进行一次抽奖 - sumPoint: 0, - pointCost: 0, - supplyPoint: 0, - freeCount: 0, - luckyValue: 0, - lottery: [], - counter: 0, - prize: {} - }; - - await utils.wait(100); - console.clear(); - - try { - const checkInResult = await api.checkIn(); - console.log(checkInResult); - const incrPoint = checkInResult.incr_point; - console.log(`签到成功 +${incrPoint} 矿石`); - - const sumPoint = checkInResult.sum_point; - state.sumPoint = sumPoint; - } catch (e) { - console.log(e.message); - - const sumPoint = await api.getCurrentPoint(); - state.sumPoint = sumPoint; - } - - try { - const luckyusersResult = await api.getLotteriesLuckyUsers(); - if (luckyusersResult.count > 0) { - const no1LuckyUser = luckyusersResult.lotteries[0]; - const dipLuckyResult = await api.dipLucky(no1LuckyUser.history_id); - if (dipLuckyResult.has_dip) { - console.log(`今天你已经沾过喜气,明天再来吧!`); - } else { - console.log(`沾喜气 +${dipLuckyResult.dip_value} 幸运值`); - } - } - } catch {} - - console.log(`当前余额:${state.sumPoint} 矿石`); - - const luckyResult = await api.getMyLucky(); - state.luckyValue = luckyResult.total_value; - console.log(`当前幸运值:${state.luckyValue}/6000`); - - const lotteryConfig = await api.getLotteryConfig(); - state.lottery = lotteryConfig.lottery; - state.pointCost = lotteryConfig.point_cost; - state.freeCount = lotteryConfig.free_count; - state.sumPoint += state.freeCount * state.pointCost; - console.log(`免费抽奖次数: ${state.freeCount}`); - - console.log(`准备梭哈!`); - - console.logGroupStart("奖品实况"); - - const getSupplyPoint = draw => { - const maybe = [ - ["lottery_id", "6981716980386496552"], - ["lottery_name", "随机矿石"], - ["lottery_type", 1] - ]; - if (maybe.findIndex(([prop, value]) => draw[prop] === value) !== -1) { - const supplyPoint = Number.parseInt(draw.lottery_name); - if (!isNaN(supplyPoint)) { - return supplyPoint; - } - } - return 0; - }; - - const lottery = async () => { - const result = await api.drawLottery(); - state.sumPoint -= state.pointCost; - state.sumPoint += getSupplyPoint(result); - state.luckyValue += result.draw_lucky_value; - state.counter++; - state.prize[result.lottery_name] = (state.prize[result.lottery_name] || 0) + 1; - console.log(`[第${state.counter}抽]:${result.lottery_name}`); - }; - - while (state.freeCount > 0) { - await lottery(); - state.freeCount--; - await utils.wait(state.simulateSpeed); - } - - while (state.sumPoint >= state.pointCost) { - await lottery(); - await utils.wait(state.simulateSpeed); - } - - console.logGroupEnd("奖品实况"); - - console.log(`弹药不足,当前余额:${state.sumPoint} 矿石`); - console.log(`养精蓄锐来日再战!`); - - const recordInfo = []; - recordInfo.push("=====[战绩详情]====="); - if (state.counter > 0) { - const prizeList = []; - for (const key in state.prize) { - prizeList.push(`${key}: ${state.prize[key]}`); - } - recordInfo.push(...prizeList); - recordInfo.push("-------------------"); - recordInfo.push(`共计: ${state.counter}`); - } else { - recordInfo.push("暂无奖品"); - } - recordInfo.push("+++++++++++++++++++"); - recordInfo.push(`幸运值: ${state.luckyValue}/6000`); - recordInfo.push("==================="); - console.log(recordInfo.join("\n")); - - email({ - subject: "掘金每日签到", - text: console.toString() - }); -} - -run(process.argv.splice(2)).catch(error => { - email({ - subject: "掘金每日签到", - html: `Error
${error.message}
` - }); -}); diff --git a/scripts/seaGold.js b/scripts/seaGold.js index a5807d19..66bde13c 100644 --- a/scripts/seaGold.js +++ b/scripts/seaGold.js @@ -1,7 +1,7 @@ const JuejinHelper = require("juejin-helper"); const utils = require("./utils/utils"); const { Grid, Astar } = require("fast-astar"); -const email = require("./utils/email"); +const pushMessage = require("./utils/pushMessage"); const env = require("./utils/env"); class SeaGold { @@ -118,6 +118,9 @@ class SeaGold { const curNode = this.getNode(this.gameInfo.curPos); const bestNode = this.getBestNode(bmmap); const path = this.getRoutePath(bmmap, curNode, bestNode); + if (!Array.isArray(path)) { + throw new Error(`路径 ${JSON.stringify(path)} 无法在地图 ${JSON.stringify(this.getMaze(bmmap))} 行进.`); + } const commands = this.getCommands(path); if (commands.length <= 0) { return false; @@ -401,22 +404,20 @@ async function run(args) { const content = seaGold.toString(); console.log(content); - - email({ + pushMessage({ subject: "海底掘金游戏", text: content - }); - utils.dingding(content); + }) } -run(process.argv.splice(2)).catch(error => { - email({ +run(process.argv.splice(2)).catch((error) => { + pushMessage({ subject: "海底掘金游戏", html: ` -Error -
${error.message}
-
如果版本过低请前往升级: juejin-helper
-`.trim() + Error +
${error.message}
+
如果版本过低请前往升级: juejin-helper
+ `.trim() }); throw error; diff --git a/scripts/test.js b/scripts/test.js deleted file mode 100644 index 45a8049d..00000000 --- a/scripts/test.js +++ /dev/null @@ -1,93 +0,0 @@ -const JuejinHelper = require('juejin-helper'); -const email = require("./utils/email"); -const env = require("./utils/env"); - -const CheckInState = { - no: -1, - success: 1, - error: 0 -} - -class CheckIn { - state = { - simulateSpeed: 100, // ms/进行一次抽奖 - sumPoint: 0, - pointCost: 0, - supplyPoint: 0, - freeCount: 0, - luckyValue: 0, - lottery: [], - counter: 0, - prize: {}, - checkInState: CheckInState.no - }; - - juejin = new JuejinHelper(); - - static async run() { - email({ - subject: "掘金每日签到", - html: ` -
- -
签到成功 +700 矿石
-
沾喜气 +10 幸运值
-
矿石 98559
-
-
幸运值
-
-
-
-
1385/6000
-
-
All In矿石预估累计幸运值比: 119.10%
-
-
免费抽奖 1 次
-
我的奖品
- -
-
` - }); - } -} - -CheckIn.run(); - -// async function run() { -// const checkin = new CheckIn(); -// const juejin = new JuejinHelper(); -// await juejin.login(mockCookie); -// console.log(checkin.hello, juejin.getUser()); -// } -// -// run(); diff --git a/scripts/utils/dingding.js b/scripts/utils/dingding.js new file mode 100644 index 00000000..2bfe864f --- /dev/null +++ b/scripts/utils/dingding.js @@ -0,0 +1,20 @@ +const fetch = require("node-fetch"); + +const env = require("./env"); +async function dingding({ subject, text, html }) { + return fetch(env.DINGDING_WEBHOOK, { + headers: { + "Content-Type": "application/json", + Charset: "UTF-8" + }, + method: "POST", + body: JSON.stringify({ + msgtype: "text", + text: { + content: `${subject}\n${text || html}` + } + }) + }).then((res) => console.log(JSON.stringify(res))); +} + +module.exports = dingding; diff --git a/scripts/utils/env.js b/scripts/utils/env.js index 8cd33079..41b08f9b 100644 --- a/scripts/utils/env.js +++ b/scripts/utils/env.js @@ -1,9 +1,23 @@ const env = process.env || {}; module.exports = { + /* 掘金Cookie */ + COOKIE: env.COOKIE, + /** + * 邮箱配置 + * user 发件人邮箱, pass, 发件人密码, to收件人 + */ EMAIL_USER: env.EMAIL_USER, EMAIL_PASS: env.EMAIL_PASS, EMAIL_TO: env.EMAIL_TO, - COOKIE: env.COOKIE, - DINGDING_WEBHOOK:env.DINGDING_WEBHOOK + /** + * 钉钉配置 + * https://open.dingtalk.com/document/robots/custom-robot-access + */ + DINGDING_WEBHOOK: env.DINGDING_WEBHOOK, + /** + * PushPlus配置 + * http://www.pushplus.plus/doc/guide/openApi.html + */ + PUSHPLUS_TOKEN: env.PUSHPLUS_TOKEN }; diff --git a/scripts/utils/logger.js b/scripts/utils/logger.js deleted file mode 100644 index 331e4be8..00000000 --- a/scripts/utils/logger.js +++ /dev/null @@ -1,84 +0,0 @@ -class LogNode { - constructor(data, parent = null, leaf = true) { - this.data = data; - this.parent = parent; - this.level = parent ? parent.level + 1 : 0; - this.leaf = leaf; - - if (!leaf) { - this.children = []; - } - } - - toString() { - const level = this.level - 1; - const isGroup = !this.leaf; - return `${' '.repeat(level * 3)}${isGroup ? '▼' : level > 0 ? '-' : ' '} ${this.data}\n`; - } -} - -class Logger { - result = this.createNode(null, null, false); - current = this.result; - - createNode(data, parent, leaf) { - return new LogNode(data, parent, leaf); - } - - clear() { - this.result = this.createNode(null, null, false); - this.current = this.result; - console.clear(); - } - - log(msg) { - const node = this.createNode(msg, this.current, true); - this.current.children.push(node); - console.log(msg); - } - - logGroupStart(name) { - const current = this.createNode(name, this.current, false); - this.result.children.push(current); - this.current = current; - console.group(name); - } - - logGroupEnd(name) { - const current = this.current.parent; - this.current = current; - console.groupEnd(name); - } - - toString() { - const each = children => { - if (!Array.isArray(children)) return ""; - let content = ""; - children.forEach(child => { - content += child.toString(); - if (!child.leaf) { - content += each(child.children); - } - }); - return content; - } - return each(this.result.children); - } -} - -const logger = new Logger(); - -module.exports = logger; -// logger.log(2) -// logger.logGroupStart("group 1") -// logger.log(3) -// logger.log(4) -// logger.log(5) -// logger.logGroupStart("group 2") -// logger.log(6) -// logger.log(7) -// logger.log(8) -// logger.logGroupEnd("group 2") -// logger.logGroupEnd("group 1") -// logger.log(9) -// logger.toString(); diff --git a/scripts/utils/pushMessage.js b/scripts/utils/pushMessage.js new file mode 100644 index 00000000..889f9154 --- /dev/null +++ b/scripts/utils/pushMessage.js @@ -0,0 +1,12 @@ +const env = require("./env"); +const email = require("./email"); +const pushplus = require("./pushplus"); +const dingding = require("./dingding"); + +async function pushMessage({ subject, text, html }) { + env.EMAIL_USER && await email({ subject, text, html }); + env.DINGDING_WEBHOOK && await dingding({ subject, text, html }); + env.PUSHPLUS_TOKEN && await pushplus({ subject, text, html }); +} + +module.exports = pushMessage; diff --git a/scripts/utils/pushplus.js b/scripts/utils/pushplus.js new file mode 100644 index 00000000..0e84927d --- /dev/null +++ b/scripts/utils/pushplus.js @@ -0,0 +1,41 @@ +const fetch = require("node-fetch"); +const env = require("./env"); +const userConfig = { + url: "http://www.pushplus.plus/send", + token: env.PUSHPLUS_TOKEN +}; + +async function main({ subject, text, html }) { + if (!userConfig.token) { + console.warn("未配置PushPlus之Token, 请先配置PushPlus"); + return; + } + return await postMessage({ + token: userConfig.token, + title: subject, + content: text ?? html, + topic: "", + template: "html", + channel: "wechat", + webhook: "", + callbackUrl: "", + timestamp: "" + }) + .then((res) => res.json()) + .then((json) => { + console.log(`PushPlus推送结果: `+json.msg) + return json + }); +} + +async function postMessage(message) { + return await fetch(userConfig.url, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(message) + }).catch((err) => console.log(err)); +} + +module.exports = main; diff --git a/scripts/utils/utils.js b/scripts/utils/utils.js index 19d4d159..f42d3df1 100644 --- a/scripts/utils/utils.js +++ b/scripts/utils/utils.js @@ -1,28 +1,8 @@ -const env = require("./env"); -const fetch = require('node-fetch') module.exports = { async wait(time = 0) { - return new Promise(resolve => setTimeout(resolve, time)); + return new Promise((resolve) => setTimeout(resolve, time)); }, randomRangeNumber(start = 500, end = 1000) { return (Math.random() * (end - start) + start) >> 0; - }, - dingding(msg) { - DINGDING_WEBHOOK = env.DINGDING_WEBHOOK - if (typeof DINGDING_WEBHOOK != "undefined" && DINGDING_WEBHOOK != null && DINGDING_WEBHOOK != "" && DINGDING_WEBHOOK != undefined) { - data = { - "msgtype": "text", - "text": { - "content": msg - } - } - fetch(DINGDING_WEBHOOK, { - headers: { - "Content-Type": "application/json", "Charset": "UTF-8" - }, - method: "POST", - body: JSON.stringify(data) - }).then(res => console.log(JSON.stringify(res))) - } } -} +};