diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 00000000..513f4228
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,7 @@
+
diff --git a/.github/workflows/checkin.yml b/.github/workflows/checkin.yml
index 898686d6..7c6ffea1 100644
--- a/.github/workflows/checkin.yml
+++ b/.github/workflows/checkin.yml
@@ -2,7 +2,7 @@ name: CheckIn
on:
schedule:
- - cron: "30 22 * * *" # 北京时间上午06:30
+ - cron: "40 22 * * *" # 北京时间上午06:40
workflow_dispatch:
jobs:
CheckIn:
@@ -13,9 +13,15 @@ jobs:
- name: Run Project
env:
COOKIE: ${{ secrets.COOKIE }}
+ COOKIE_2: ${{ secrets.COOKIE_2 }}
+ COOKIE_3: ${{ secrets.COOKIE_3 }}
+ COOKIE_4: ${{ secrets.COOKIE_4 }}
+ COOKIE_5: ${{ secrets.COOKIE_5 }}
EMAIL_USER: ${{ secrets.EMAIL_USER }}
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 c9d87123..0d5ddb11 100644
--- a/.github/workflows/seaGold.yml
+++ b/.github/workflows/seaGold.yml
@@ -13,9 +13,15 @@ jobs:
- name: Run Project
env:
COOKIE: ${{ secrets.COOKIE }}
+ COOKIE_2: ${{ secrets.COOKIE_2 }}
+ COOKIE_3: ${{ secrets.COOKIE_3 }}
+ COOKIE_4: ${{ secrets.COOKIE_4 }}
+ COOKIE_5: ${{ secrets.COOKIE_5 }}
EMAIL_USER: ${{ secrets.EMAIL_USER }}
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/.gitignore b/.gitignore
index 7df6d182..d8c2951c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
.DS_Store
node_modules
+dist
# local env files
.env.local
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 00000000..824ac82b
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,8 @@
+{
+ "tabWidth": 2,
+ "semi": true,
+ "singleQuote": false,
+ "printWidth": 100,
+ "trailingComma": "none",
+ "bracketSpacing": false
+}
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..a07b7eba
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,41 @@
+# 参与贡献
+
+## 分支介绍
+
+- `package` 掘金API发布npm包,供给自动化工作流使用。
+- `workflows` 自动化工作流开发分支。
+- `main` 是 workflows 分支的稳定版。
+
+**处理自动化相关逻辑:**
+base: `workflows` <- compare `your branch`
+
+**处理JueJinAPI相关逻辑:**
+base: `package` <- compare `your branch`
+
+## workflows 分支
+
+### 安装
+
+- `yarn` 安装依赖
+
+### 环境变量
+
+- `/scripts/utils/env.js` 替换本地测试所需的环境变量
+
+```javascript
+module.exports = {
+ COOKIE: "测试掘金Cookie",
+ // ...
+};
+```
+
+### 本地运行
+
+- `yarn checkin` 运行掘金签到脚本
+- `yarn seagold` 运行海底掘金游戏脚本
+
+## package 分支
+
+- `yarn` 安装依赖
+- `yarn dev` 启动开发模式
+- `node tests/your-test.js` 测试一个模块
diff --git a/README.md b/README.md
index f6a9b010..b02aea8d 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,23 @@
-
-
-
JuejinHelper-稀土掘金助手
签到、抽奖、沾喜气、海底掘金游戏、自动化工作流。
## 使用
自动化执行任务: 掘金每日签到, 沾喜气, 免费抽奖, 海底掘金游戏, 最后将结果报告邮件通知订阅人。\
+=======
+签到、抽奖、沾喜气、消除Bug、海底掘金游戏、自动化工作流。
+
+## 使用
+
+自动化执行任务: 掘金每日签到, 沾喜气, 免费抽奖, 消除Bug, 海底掘金游戏, 最后将结果报告邮件通知订阅人。\
+>>>>>>> Stashed changes
自动化运行时间: 北京时间上午06:30
1. [Fork 仓库](https://github.com/iDerekLi/juejin-helper)
2. 仓库 -> Settings -> Secrets -> New repository secret, 添加Secrets变量如下:
+<<<<<<< Updated upstream
| Name | Value |
| --- | --- |
| COOKIE | 掘金网站Cookie, 打开浏览器,登录 [掘金](https://juejin.cn/), 打开控制台DevTools -> Network,复制 cookie, **掘金Cookie有效期约1个月需定期更新.** |
@@ -25,12 +26,29 @@
| EMAIL_TO | 订阅人邮箱地址(收件人). 如需多人订阅使用 `, ` 分割, 例如: `a@163.com, b@qq.com` |
3. 仓库 -> Actions, 检查Workflows并启用。
+=======
+ | Name | Value | Required |
+ | --- | --- | --- |
+ | COOKIE | 掘金网站Cookie | 是 |
+ | COOKIE_2 | 多用户, 当需要同时运行多个掘金用户时所需, 支持最多 **5** 名用户(即COOKIE + COOKIE_2 - COOKIE_5) | 否 |
+ | EMAIL_USER | 发件人邮箱地址(需要开启 SMTP) | 否 |
+ | EMAIL_PASS | 发件人邮箱密码(SMTP密码) | 否 |
+ | EMAIL_TO | 订阅人邮箱地址(收件人). 如需多人订阅使用 `, ` 分割, 例如: `a@163.com, b@qq.com` | 否 |
+ | DINGDING_WEBHOOK | 钉钉机器人WEBHOOK | 否 |
+ | PUSHPLUS_TOKEN | [Pushplus](http://www.pushplus.plus/) 官网申请,支持微信消息推送 | 否 |
+
+4. 仓库 -> Actions, 检查Workflows并启用。
+>>>>>>> Stashed changes
## 预览
| 掘金每日签到 | 海底掘金游戏 |
|:-----------:| :-------------:|
+<<<<<<< Updated upstream
| ![掘金每日签到](https://user-images.githubusercontent.com/24502299/150481822-b488d30c-93b6-4d73-9e28-56c04a9413fb.png) | ![海底掘金游戏](https://user-images.githubusercontent.com/24502299/150625136-5649d2fe-b204-40aa-b8b5-7f54a44e018d.png) |
+=======
+| ![掘金每日签到](https://user-images.githubusercontent.com/24502299/156475511-342cfcd8-3b66-4b9c-8614-215e0b4e08a1.jpg) | ![海底掘金游戏](https://user-images.githubusercontent.com/24502299/156475550-c8cc459a-3b27-4ca6-a07b-902b65bea7a9.jpg) |
+>>>>>>> Stashed changes
## 问题
@@ -51,10 +69,14 @@ DevTools截图:
[![海底掘金挑战赛](https://user-images.githubusercontent.com/24502299/151397151-0d69998a-2310-4a32-945f-c8e0035ed65d.png)](https://juejin.cn/game/haidijuejin/)
+<<<<<<< Updated upstream
## 赞赏
### ☕️微信赞赏!鼓励升级!
-
+=======
+## 贡献
+
+这个项目的存在要感谢所有做出贡献的人。 请先阅读 [[Contribute](CONTRIBUTING.md)]。
+您可以将任何想法作为 [拉取请求](https://github.com/iDerekLi/juejin-helper/pulls) 或 [GitHub问题](https://github.com/iDerekLi/juejin-helper/issues) 提交。
+
-## 许可
-[MIT](./LICENSE)
diff --git a/package.json b/package.json
index 3f6ba950..5158a417 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "juejin-helper",
- "version": "1.0.0",
- "description": "稀土掘金助手:签到、抽奖、沾喜气、海底淘金、自动化工作流。",
+ "version": "1.5.1",
+ "description": "稀土掘金助手:签到、抽奖、沾喜气、消除Bug、海底掘金游戏、自动化工作流。",
"author": "Derek Li",
"license": "MIT",
"scripts": {
@@ -11,8 +11,10 @@
},
"dependencies": {
"fast-astar": "^1.0.6",
+ "juejin-helper": "^1.7.2",
"jsonwebtoken": "^8.5.1",
"node-fetch": "^2.6.1",
+ "juejin-helper": "^1.5.1",
"nodemailer": "^6.7.0"
},
"repository": {
diff --git a/scripts/api/api.js b/scripts/api/api.js
deleted file mode 100644
index 8b9e6241..00000000
--- a/scripts/api/api.js
+++ /dev/null
@@ -1,57 +0,0 @@
-const fetch = require("node-fetch");
-
-class Api {
- baseURL = "";
- headers = {
- "content-type": "application/json; charset=utf-8",
- "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36",
- "accept-encoding": "gzip, deflate, br",
- "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
- "sec-ch-ua": `"Chromium";v="88", "Google Chrome";v="88", ";Not A Brand";v="99"`,
- "sec-ch-ua-mobile": "?0",
- accept: "*/*",
- credentials: "include"
- };
-
- requestInterceptor = config => config;
- responseInterceptor = res => res;
-
- async request(config) {
- config = this.requestInterceptor({
- baseURL: config.baseURL || this.baseURL,
- url: config.url,
- method: (config.method || "get").toLocaleUpperCase(),
- headers: {
- ...this.headers,
- ...config.headers
- },
- data: config.data
- });
-
- const response = await fetch(config.baseURL + config.url, {
- method: config.method,
- headers: config.headers,
- body: config.method !== "GET" ? JSON.stringify(config.data) : undefined
- });
-
- return this.responseInterceptor(await response.json());
- }
-
- async get(url, config) {
- return this.request({
- ...config,
- url,
- method: "get"
- });
- }
-
- async post(url, config) {
- return this.request({
- ...config,
- url,
- method: "post"
- });
- }
-}
-
-module.exports = Api;
diff --git a/scripts/api/juejin-api.js b/scripts/api/juejin-api.js
deleted file mode 100644
index a1e3bd60..00000000
--- a/scripts/api/juejin-api.js
+++ /dev/null
@@ -1,67 +0,0 @@
-const Api = require("./api");
-const env = require("../utils/env");
-
-class JuejinApi extends Api {
- constructor() {
- super();
- this.baseURL = "https://api.juejin.cn";
- this.headers.referer = "https://juejin.cn/";
- this.headers.cookie = env.COOKIE;
- }
-
- responseInterceptor = res => {
- if (res.err_no) {
- throw new Error(res.err_msg);
- }
- return res.data;
- }
-
- async getToken() {
- return this.get("/get/token", {
- baseURL: "https://juejin.cn"
- });
- }
-
- async getUserInfo() {
- return this.get("/user_api/v1/user/get");
- }
-
- async getLotteryConfig() {
- return this.get("/growth_api/v1/lottery_config/get");
- }
-
- async getCurrentPoint() {
- return this.get("/growth_api/v1/get_cur_point");
- }
-
- async drawLottery() {
- return this.post("/growth_api/v1/lottery/draw");
- }
-
- async checkIn() {
- return this.post("/growth_api/v1/check_in");
- }
-
- async getLotteriesLuckyUsers() {
- return this.post("/growth_api/v1/lottery_history/global_big", {
- data: {
- page_no: 1,
- page_size: 5
- }
- });
- }
-
- async dipLucky(lottery_history_id) {
- return this.post("/growth_api/v1/lottery_lucky/dip_lucky", {
- data: {
- lottery_history_id
- }
- });
- }
-
- async getMyLucky() {
- return this.post("/growth_api/v1/lottery_lucky/my_lucky");
- }
-}
-
-module.exports = new JuejinApi;
diff --git a/scripts/api/juejin-game-api.js b/scripts/api/juejin-game-api.js
deleted file mode 100644
index 7c2d5389..00000000
--- a/scripts/api/juejin-game-api.js
+++ /dev/null
@@ -1,105 +0,0 @@
-const Api = require("./api");
-const jwt = require("jsonwebtoken");
-
-class JuejinGameApi extends Api {
- user = null;
-
- constructor() {
- super();
- this.baseURL = "https://juejin-game.bytedance.com/game";
- this.headers.referer = "https://juejin.cn/";
- }
-
- setUser(user) {
- this.user = user;
- }
-
- setToken(token) {
- this.headers.Authorization = `Bearer ${token}`;
- }
-
- requestInterceptor = config => {
- if (this.user) {
- config.url += (config.url.indexOf("?") === -1 ? "?" : "&") + `uid=${this.user.user_id}&time=${Date.now()}`;
- }
- return config;
- };
-
- responseInterceptor = res => {
- if (res.code !== 0) {
- throw new Error(res.message);
- }
- return res.data;
- }
-
- async gameLogin() {
- return this.post("/sea-gold/user/login", {
- data: {
- name: this.user.user_name
- }
- });
- }
-
- async gameInfo() {
- return this.get("/sea-gold/home/info");
- }
-
- async gameStart() {
- return this.post("/sea-gold/game/start", {
- data: {
- roleId: 3
- }
- });
- }
-
- async gameOver() {
- // const result = {
- // activity: "",
- // deep: 3,
- // gameDiamond: 34, // 当局获取
- // originMapData: [],
- // passLine: [{ x: 0, y: 0 }, { x: 0, y: 1 }],
- // picoDiamond: 0,
- // realDiamond: 34, // 真实获取
- // todayDiamond: 34, // 今日获取
- // todayLimitDiamond: 1500 // 今日最大获取
- // };
- return this.post("/sea-gold/game/over", {
- data: {
- isButton: 1
- }
- });
- }
-
- async gameCommand(gameId, command = []) {
- // const result = {
- // appendMapData: [],
- // blockData: { moveUp: 14, moveDown: 14, moveLeft: 2, moveRight: 5, jump: 3, loop: 3 },
- // curPos: { x: 0, y: 2 },
- // gameDiamond: 34
- // }
- const privateKey = "-----BEGIN EC PARAMETERS-----\nBggqhkjOPQMBBw==\n-----END EC PARAMETERS-----\n-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIDB7KMVQd+eeKt7AwDMMUaT7DE3Sl0Mto3LEojnEkRiAoAoGCCqGSM49\nAwEHoUQDQgAEEkViJDU8lYJUenS6IxPlvFJtUCDNF0c/F/cX07KCweC4Q/nOKsoU\nnYJsb4O8lMqNXaI1j16OmXk9CkcQQXbzfg==\n-----END EC PRIVATE KEY-----\n";
- const token = jwt.sign({
- gameId: gameId,
- time: new Date().getTime()
- }, privateKey, {
- algorithm: "ES256",
- expiresIn: 2592e3,
- header: {
- alg: "ES256",
- typ: "JWT"
- }
- });
- return this.post("/sea-gold/game/command", {
- headers: {
- "x-tt-gameid": token
- },
- data: {
- command
- // command: ["R", { times: 2, command: ["R"] }, "2"]
- }
- });
- }
-}
-
-module.exports = new JuejinGameApi;
diff --git a/scripts/checkin.js b/scripts/checkin.js
index 32065fad..c751947a 100644
--- a/scripts/checkin.js
+++ b/scripts/checkin.js
@@ -1,143 +1,194 @@
-const api = require("./api/juejin-api");
-const console = require("./utils/logger");
+const JuejinHelper = require("juejin-helper");
const utils = require("./utils/utils");
const email = require("./utils/email");
+const env = require("./utils/env");
+
+class CheckIn {
+ username = "";
+ todayStatus = 0; // 未签到
+ incrPoint = 0;
+ sumPoint = 0; // 当前矿石数
+ contCount = 0; // 连续签到天数
+ sumCount = 0; // 累计签到天数
+ dipStatus = 0;
+ dipValue = 0; // 沾喜气
+ luckyValue = 0;
+ lottery = []; // 奖池
+ pointCost = 0; // 一次抽奖消耗
+ freeCount = 0; // 免费抽奖次数
+ drawLotteryHistory = {};
+ lotteryCount = 0;
+ luckyValueProbability = 0;
+
+ calledSdkSetting = false;
+ calledTrackGrowthEvent = false;
+ calledTrackOnloadEvent = false;
+
+ async run() {
+ const juejin = new JuejinHelper();
+ try {
+ await juejin.login(env.COOKIE);
+ console.log(env.COOKIE);
+ } catch (e) {
+ console.error(e);
+
+
+ throw new Error("登录失败, 请尝试更新Cookies!");
+ }
-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();
- 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;
- }
+ this.username = juejin.getUser().user_name;
+
+ const growth = juejin.growth();
+
+ const todayStatus = await growth.getTodayStatus();
+ if (!todayStatus) {
+ const checkInResult = await growth.checkIn();
+
+ this.incrPoint = checkInResult.incr_point;
+ this.sumPoint = checkInResult.sum_point;
+ this.todayStatus = 1; // 本次签到
+ } else {
+ this.todayStatus = 2; // 已签到
+ }
+
+ const counts = await growth.getCounts();
+ this.contCount = counts.cont_count;
+ this.sumCount = counts.sum_count;
- try {
- const luckyusersResult = await api.getLotteriesLuckyUsers();
+ const luckyusersResult = await growth.getLotteriesLuckyUsers();
if (luckyusersResult.count > 0) {
const no1LuckyUser = luckyusersResult.lotteries[0];
- const dipLuckyResult = await api.dipLucky(no1LuckyUser.history_id);
+ const dipLuckyResult = await growth.dipLucky(no1LuckyUser.history_id);
if (dipLuckyResult.has_dip) {
- console.log(`今天你已经沾过喜气,明天再来吧!`);
+ this.dipStatus = 2;
} else {
- console.log(`沾喜气 +${dipLuckyResult.dip_value} 幸运值`);
+ this.dipStatus = 1;
+ this.dipValue = 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;
-
- const getProbabilityOfWinning = sumPoint => {
- const pointCost = state.pointCost;
- const luckyValueCost = 10;
- const totalDrawsNumber = sumPoint / pointCost;
- let supplyPoint = 0;
- for(let i = 0, length = Math.floor(totalDrawsNumber * 0.65); i < length; i++) {
- supplyPoint += Math.ceil(Math.random() * 100)
+
+ const luckyResult = await growth.getMyLucky();
+ this.luckyValue = luckyResult.total_value;
+
+ const lotteryConfig = await growth.getLotteryConfig();
+ this.lottery = lotteryConfig.lottery;
+ this.pointCost = lotteryConfig.point_cost;
+ this.freeCount = lotteryConfig.free_count;
+ this.lotteryCount = 0;
+
+ let freeCount = this.freeCount;
+ while (freeCount > 0) {
+ const result = await growth.drawLottery();
+ this.drawLotteryHistory[result.lottery_id] = (this.drawLotteryHistory[result.lottery_id] || 0) + 1;
+ this.luckyValue = result.total_lucky_value
+ freeCount--;
+ this.lotteryCount++;
+ await utils.wait(utils.randomRangeNumber(300, 1000));
}
- const luckyValue = (sumPoint + supplyPoint) / pointCost * luckyValueCost + state.luckyValue;
- return luckyValue / 6000;
- }
- console.log(`预测梭哈矿石累计幸运值比率: ${(getProbabilityOfWinning(state.sumPoint) * 100).toFixed(2) + "%"}`);
-
- 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;
+
+ this.sumPoint = await growth.getCurrentPoint();
+
+ const getProbabilityOfWinning = sumPoint => {
+ const pointCost = this.pointCost;
+ const luckyValueCost = 10;
+ const totalDrawsNumber = sumPoint / pointCost;
+ let supplyPoint = 0;
+ for(let i = 0, length = Math.floor(totalDrawsNumber * 0.65); i < length; i++) {
+ supplyPoint += Math.ceil(Math.random() * 100)
}
+ const luckyValue = (sumPoint + supplyPoint) / pointCost * luckyValueCost + this.luckyValue;
+ return luckyValue / 6000;
}
- 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);
- }
- console.logGroupEnd("奖品实况");
+ this.luckyValueProbability = getProbabilityOfWinning(this.sumPoint);
- console.log(`当前余额:${state.sumPoint} 矿石`);
+ // 调用埋点
+ const sdk = juejin.sdk();
- const recordInfo = [];
- recordInfo.push("=====[战绩详情]=====");
- if (state.counter > 0) {
- const prizeList = [];
- for (const key in state.prize) {
- prizeList.push(`${key}: ${state.prize[key]}`);
+ try {
+ await sdk.slardarSDKSetting();
+ this.calledSdkSetting = true;
+ } catch {
+ this.calledSdkSetting = false;
}
- recordInfo.push(...prizeList);
- recordInfo.push("-------------------");
- recordInfo.push(`共计: ${state.counter}`);
- } else {
- recordInfo.push("暂无奖品");
+
+ try {
+ const result = await sdk.mockTrackGrowthEvent();
+ if (result && result.e === 0) {
+ this.calledTrackGrowthEvent = true;
+ } else {
+ throw result;
+ }
+ } catch {
+ this.calledTrackGrowthEvent = false;
+ }
+
+ try {
+ const result = await sdk.mockTrackOnloadEvent();
+ if (result && result.e === 0) {
+ this.calledTrackOnloadEvent = true;
+ } else {
+ throw result;
+ }
+ } catch {
+ this.calledTrackOnloadEvent = false;
+ }
+
+ console.log("------事件埋点追踪-------");
+ console.log(`SDK状态: ${this.calledSdkSetting ? "加载成功" : "加载失败"}`);
+ console.log(`成长API事件埋点: ${this.calledTrackGrowthEvent ? "调用成功" : "调用失败"}`);
+ console.log(`OnLoad事件埋点: ${this.calledTrackOnloadEvent ? "调用成功" : "调用失败"}`);
+ console.log("-------------------------");
+
+ await juejin.logout();
}
- recordInfo.push("+++++++++++++++++++");
- recordInfo.push(`幸运值: ${state.luckyValue}/6000`);
- recordInfo.push("===================");
- console.log(recordInfo.join("\n "));
+
+ toString() {
+ const drawLotteryHistory = Object.entries(this.drawLotteryHistory).map(([lottery_id, count]) => {
+ const lotteryItem = this.lottery.find(item => item.lottery_id === lottery_id);
+ if (lotteryItem) {
+ return `${lotteryItem.lottery_name}: ${count}`;
+ }
+ return `${lottery_id}: ${count}`
+ }).join("\n");
+
+ return `
+掘友: ${this.username}
+${this.todayStatus === 1 ? `签到成功 +${this.incrPoint} 矿石` :
+ this.todayStatus === 2 ? "今日已完成签到" : "签到失败"}
+${this.dipStatus === 1 ? `沾喜气 +${this.dipValue} 幸运值` :
+ this.dipStatus === 2 ? "今日已经沾过喜气" : "沾喜气失败"}
+连续签到天数 ${this.contCount}
+累计签到天数 ${this.sumCount}
+当前矿石数 ${this.sumPoint}
+当前幸运值 ${this.luckyValue}/6000
+预测All In矿石累计幸运值比率 ${(this.luckyValueProbability * 100).toFixed(2) + "%"}
+抽奖总次数 ${this.lotteryCount}
+免费抽奖次数 ${this.freeCount}
+${this.lotteryCount > 0 ? "==============\n" + drawLotteryHistory + "\n==============" : ""}
+ `.trim();
+ }
+}
+
+async function run(args) {
+ const checkin = new CheckIn();
+ await utils.wait(utils.randomRangeNumber(1000, 5000)); // 初始等待1-5s
+ await checkin.run(); // 执行
+ const content = checkin.toString();
+
+ console.log(content); // 打印结果
email({
subject: "掘金每日签到",
- text: console.toString()
+ text: content
});
}
run(process.argv.splice(2)).catch(error => {
email({
subject: "掘金每日签到",
- html: `Error${error.message}
`
+ 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 845522eb..bbfb696a 100644
--- a/scripts/seaGold.js
+++ b/scripts/seaGold.js
@@ -1,49 +1,59 @@
-const api = require("./api/juejin-api");
-const juejinGameApi = require("./api/juejin-game-api");
+const JuejinHelper = require("juejin-helper");
const utils = require("./utils/utils");
const { Grid, Astar } = require("fast-astar");
-const console = require("./utils/logger");
const email = require("./utils/email");
+const env = require("./utils/env");
+
+class SeaGold {
+ gameApi = null;
+
+ nodeRules = [
+ { code: 0, hasBounty: false, isWall: false, name: "空地" },
+ { code: 2, hasBounty: true, isWall: false, name: "矿石", isBest: true },
+ { code: 3, hasBounty: false, isWall: false, name: "星星" },
+ { code: 4, hasBounty: false, isWall: true, name: "贝壳" },
+ { code: 5, hasBounty: false, isWall: true, name: "水母" },
+ { code: 6, hasBounty: false, isWall: true, name: "石头" },
+ { code: 10, hasBounty: true, isWall: false, name: "上指令" },
+ { code: 11, hasBounty: true, isWall: false, name: "下指令" },
+ { code: 12, hasBounty: true, isWall: false, name: "左指令" },
+ { code: 13, hasBounty: true, isWall: false, name: "右指令" },
+ { code: 14, hasBounty: true, isWall: false, name: "跳跃指令" },
+ { code: 15, hasBounty: true, isWall: false, name: "循环指令" }
+ ];
+
+ debug = false;
+ userInfo = {
+ uid: "",
+ name: "",
+ todayDiamond: 0, // 今日获取矿石数
+ todayLimitDiamond: 1500, // 今日限制获取矿石数
+ maxTodayDiamond: 0 // 今日最大矿石数
+ };
+
+ gameInfo = {
+ gameId: "",
+ mapData: [],
+ curPos: { x: 0, y: 0 },
+ blockData: {
+ moveUp: 0,
+ moveDown: 0,
+ moveLeft: 0,
+ moveRight: 0,
+ jump: 0,
+ loop: 0
+ },
+ gameDiamond: 0
+ };
+
+ history = [];
+
+ get isGaming() {
+ return this.gameInfo && this.gameInfo.gameId !== "";
+ }
-async function run(args) {
- console.clear();
-
- class SeaGold {
- static async init() {
- const user = await api.getUserInfo();
- const token = await api.getToken();
- juejinGameApi.setUser(user);
- juejinGameApi.setToken(token);
- const seaGold = new this();
- await seaGold.init();
- return seaGold;
- }
-
- nodeRules = [
- { code: 0, hasBounty: false, isWall: false, name: "空地" },
- { code: 2, hasBounty: true, isWall: false, name: "矿石", isBest: true },
- { code: 3, hasBounty: false, isWall: false, name: "星星" },
- { code: 4, hasBounty: false, isWall: true, name: "贝壳" },
- { code: 5, hasBounty: false, isWall: true, name: "水母" },
- { code: 6, hasBounty: false, isWall: true, name: "石头" },
- { code: 10, hasBounty: true, isWall: false, name: "上指令" },
- { code: 11, hasBounty: true, isWall: false, name: "下指令" },
- { code: 12, hasBounty: true, isWall: false, name: "左指令" },
- { code: 13, hasBounty: true, isWall: false, name: "右指令" },
- { code: 14, hasBounty: true, isWall: false, name: "跳跃指令" },
- { code: 15, hasBounty: true, isWall: false, name: "循环指令" }
- ];
-
- debug = false;
- userInfo = {
- uid: "",
- name: "",
- todayDiamond: 0, // 今日获取矿石数
- todayLimitDiamond: 1500, // 今日限制获取矿石数
- maxTodayDiamond: 0 // 今日最大矿石数
- };
-
- gameInfo = {
+ resetGame() {
+ this.gameInfo = {
gameId: "",
mapData: [],
curPos: { x: 0, y: 0 },
@@ -57,344 +67,356 @@ async function run(args) {
},
gameDiamond: 0
};
+ }
- get isGaming() {
- return this.gameInfo && this.gameInfo.gameId !== "";
+ restoreGame(gameInfo) {
+ this.gameInfo = {
+ gameId: gameInfo.gameId,
+ mapData: this.makeMap(gameInfo.mapData, 6),
+ curPos: gameInfo.curPos,
+ blockData: gameInfo.blockData,
+ gameDiamond: gameInfo.gameDiamond
}
+ }
- async init() {
- const loginInfo = await juejinGameApi.gameLogin();
- if (!loginInfo.isAuth) {
- throw Error("玩家未授权, 请前往掘金授权!");
- }
- console.log(`玩家: ${loginInfo.name}`);
- const info = await juejinGameApi.gameInfo();
- this.userInfo = {
- uid: info.userInfo.uid,
- name: info.userInfo.name,
- todayDiamond: info.userInfo.todayDiamond,
- todayLimitDiamond: info.userInfo.todayLimitDiamond,
- maxTodayDiamond: info.userInfo.maxTodayDiamond
- };
- if (info.gameStatus === 1) {
- this.restoreGame(info.gameInfo);
- } else {
- this.resetGame();
- }
- }
+ async gameStart() {
+ if (this.isGaming) return;
+ const roleId = Math.ceil(Math.random() * 3);
+ const gameInfo = await this.gameApi.gameStart({ roleId });
+
+ this.gameInfo = {
+ roleId,
+ gameId: gameInfo.gameId,
+ mapData: this.makeMap(gameInfo.mapData, 6),
+ curPos: gameInfo.curPos,
+ blockData: gameInfo.blockData,
+ gameDiamond: 0
+ };
+ }
- resetGame() {
- this.gameInfo = {
- gameId: "",
- mapData: [],
- curPos: { x: 0, y: 0 },
- blockData: {
- moveUp: 0,
- moveDown: 0,
- moveLeft: 0,
- moveRight: 0,
- jump: 0,
- loop: 0
- },
- gameDiamond: 0
- };
- }
+ async gameOver() {
+ if (!this.isGaming) return;
+ const gameOverInfo = await this.gameApi.gameOver();
+ this.userInfo.todayDiamond = gameOverInfo.todayDiamond;
+ this.userInfo.todayLimitDiamond = gameOverInfo.todayLimitDiamond;
- restoreGame(gameInfo) {
- this.gameInfo = {
- gameId: gameInfo.gameId,
- mapData: this.makeMap(gameInfo.mapData, 6),
- curPos: gameInfo.curPos,
- blockData: gameInfo.blockData,
- gameDiamond: gameInfo.gameDiamond
- }
- }
+ this.history.push({
+ gameId: this.gameInfo.gameId,
+ gameDiamond: gameOverInfo.gameDiamond,
+ realDiamond: gameOverInfo.realDiamond,
+ todayDiamond: gameOverInfo.todayDiamond,
+ todayLimitDiamond: gameOverInfo.todayLimitDiamond
+ });
- async gameStart() {
- if (this.isGaming) return;
- const gameInfo = await juejinGameApi.gameStart();
-
- this.gameInfo = {
- gameId: gameInfo.gameId,
- mapData: this.makeMap(gameInfo.mapData, 6),
- curPos: gameInfo.curPos,
- blockData: gameInfo.blockData,
- gameDiamond: 0
- };
-
- console.log("╔══════游戏开始══════╗");
- console.log(`gameId: ${this.gameInfo.gameId}`);
- console.log(`curPos(${this.gameInfo.curPos.x},${this.gameInfo.curPos.y}): ${this.gameInfo.gameDiamond} 矿石`);
- }
+ this.resetGame();
- async gameOver() {
- if (!this.isGaming) return;
- const gameOverInfo = await juejinGameApi.gameOver();
- this.userInfo.todayDiamond = gameOverInfo.todayDiamond;
- this.userInfo.todayLimitDiamond = gameOverInfo.todayLimitDiamond;
- // console.log("|==================|");
- const gameDiamond = this.gameInfo.gameDiamond;
- console.log(`游戏清算: ${gameDiamond} 矿石`);
- console.log("╚══════游戏结束══════╝");
- this.resetGame();
- return gameDiamond;
- }
+ return gameOverInfo;
+ }
- async executeGameCommand() {
- const bmmap = this.getBMMap();
- const curNode = this.getNode(this.gameInfo.curPos);
- const bestNode = this.getBestNode(bmmap);
- const path = this.getRoutePath(bmmap, curNode, bestNode);
- const commands = this.getCommands(path);
- if (commands.length <= 0) {
- console.log("当局游戏资源耗尽");
- return false;
- }
- const gameCommandInfo = await juejinGameApi.gameCommand(this.gameInfo.gameId, commands);
- this.gameInfo.curPos = gameCommandInfo.curPos;
- this.gameInfo.blockData = gameCommandInfo.blockData;
- this.gameInfo.gameDiamond = gameCommandInfo.gameDiamond;
- console.log(`curPos(${this.gameInfo.curPos.x},${this.gameInfo.curPos.y}): ${this.gameInfo.gameDiamond} 矿石`);
- return true;
+ async executeGameCommand() {
+ const bmmap = this.getBMMap();
+ const curNode = this.getNode(this.gameInfo.curPos);
+ const bestNode = this.getBestNode(bmmap);
+ const path = this.getRoutePath(bmmap, curNode, bestNode);
+ const commands = this.getCommands(path);
+ if (commands.length <= 0) {
+ return false;
}
+ const gameCommandInfo = await this.gameApi.gameCommand(this.gameInfo.gameId, commands);
+ this.gameInfo.curPos = gameCommandInfo.curPos;
+ this.gameInfo.blockData = gameCommandInfo.blockData;
+ this.gameInfo.gameDiamond = gameCommandInfo.gameDiamond;
- getCommand(start, end) {
- const [sx, sy] = start;
- const [ex, ey] = end;
+ return true;
+ }
- if (sx === ex && sy !== ey) {
- return sy > ey ? "U" : "D";
- }
+ getCommand(start, end) {
+ const [sx, sy] = start;
+ const [ex, ey] = end;
- if (sy === ey && sx !== ex) {
- return sx > ex ? "L" : "R";
- }
+ if (sx === ex && sy !== ey) {
+ return sy > ey ? "U" : "D";
+ }
- return null;
+ if (sy === ey && sx !== ex) {
+ return sx > ex ? "L" : "R";
}
- getCommands(path) {
- const commands = [];
- for(let i=0; i${i+1}`);
- }
- commands.push(cmd);
+ return null;
+ }
+
+ getCommands(path) {
+ const commands = [];
+ for(let i=0; i${i+1}`);
}
- return commands;
+ commands.push(cmd);
}
+ return commands;
+ }
- getNodePosition(map, node) {
- for (let y = 0; y < map.length; y++) {
- const list = map[y];
- for (let x = 0; x < list.length; x++) {
- const cNode = list[x];
- if (cNode === node) {
- return { x, y };
- }
+ getNodePosition(map, node) {
+ for (let y = 0; y < map.length; y++) {
+ const list = map[y];
+ for (let x = 0; x < list.length; x++) {
+ const cNode = list[x];
+ if (cNode === node) {
+ return { x, y };
}
}
- return { x: 0, y: 0 };
}
+ return { x: 0, y: 0 };
+ }
- getRoutePath(map, startNode, endNode) {
- const maze = this.generateMapMaze(map);
- const startPos = this.getNodePosition(map, startNode);
- const endPos = this.getNodePosition(map, endNode);
+ getRoutePath(map, startNode, endNode) {
+ const maze = this.generateMapMaze(map);
+ const startPos = this.getNodePosition(map, startNode);
+ const endPos = this.getNodePosition(map, endNode);
- if (this.debug) {
- console.log("地图", this.getMaze(map));
- console.log("开始位置", startPos);
- console.log("结束位置", endPos);
- }
+ if (this.debug) {
+ console.log("地图", this.getMaze(map));
+ console.log("开始位置", startPos);
+ console.log("结束位置", endPos);
+ }
- const astar = new Astar(maze);
- const path = astar.search(
- [startPos.x, startPos.y],
- [endPos.x, endPos.y],
- {
- rightAngle: true,
- optimalResult: true
- }
- );
+ const astar = new Astar(maze);
+ const path = astar.search(
+ [startPos.x, startPos.y],
+ [endPos.x, endPos.y],
+ {
+ rightAngle: true,
+ optimalResult: true
+ }
+ );
- return path;
- }
+ return path;
+ }
- makeMap(mapData, grid = 6) {
- const map = [];
- for (let i = 0, y = 0; i < mapData.length; i+=grid, y++) {
- const row = [];
- map.push(row);
- for (let x = 0; x < grid; x++) {
- const cell = mapData[i + x];
- row.push(this.createMapNode(x, y, cell));
- }
+ makeMap(mapData, grid = 6) {
+ const map = [];
+ for (let i = 0, y = 0; i < mapData.length; i+=grid, y++) {
+ const row = [];
+ map.push(row);
+ for (let x = 0; x < grid; x++) {
+ const cell = mapData[i + x];
+ row.push(this.createMapNode(x, y, cell));
}
- return map;
}
+ return map;
+ }
- createMapNode(x, y, secret) {
- const rule = this.getNodeRule(secret);
- return {
- code: rule.code,
- bounty: rule.hasBounty ? this.getBounty(secret, rule.code) : 0,
- x,
- y,
- isWall: rule.isWall,
- isBest: !!rule.isBest
- }
+ createMapNode(x, y, secret) {
+ const rule = this.getNodeRule(secret);
+ return {
+ code: rule.code,
+ bounty: rule.hasBounty ? this.getBounty(secret, rule.code) : 0,
+ x,
+ y,
+ isWall: rule.isWall,
+ isBest: !!rule.isBest
}
+ }
- // 获取范围地图
- getBMMap() {
- const { mapData, blockData, curPos } = this.gameInfo;
- const minX = Math.max(curPos.x - blockData.moveLeft, 0);
- const maxX = Math.min(curPos.x + blockData.moveRight, mapData[0].length - 1);
- const minY = Math.max(curPos.y - blockData.moveUp, 0);
- const maxY = Math.min(curPos.y + blockData.moveDown, mapData.length - 1);
-
- const map = [];
- for (let y = minY; y <= maxY; y++) {
- const row = []; map.push(row);
- for (let x = minX; x <= maxX; x++) {
- row.push(mapData[y][x]);
- }
+ // 获取范围地图
+ getBMMap() {
+ const { mapData, blockData, curPos } = this.gameInfo;
+ const minX = Math.max(curPos.x - blockData.moveLeft, 0);
+ const maxX = Math.min(curPos.x + blockData.moveRight, mapData[0].length - 1);
+ const minY = Math.max(curPos.y - blockData.moveUp, 0);
+ const maxY = Math.min(curPos.y + blockData.moveDown, mapData.length - 1);
+
+ const map = [];
+ for (let y = minY; y <= maxY; y++) {
+ const row = []; map.push(row);
+ for (let x = minX; x <= maxX; x++) {
+ row.push(mapData[y][x]);
}
-
- return map;
}
- getNode(pos) {
- return this.gameInfo.mapData[pos.y][pos.x];
- }
+ return map;
+ }
- getBestNode(map) {
- let bestNode = null;
- map.forEach(row => {
- row.forEach(node => {
- if (node.isBest && bestNode === null) {
- bestNode = node;
- } else if (node.isBest && node.bounty > bestNode.bounty) {
- bestNode = node;
- }
- });
- });
- return bestNode;
- }
+ getNode(pos) {
+ return this.gameInfo.mapData[pos.y][pos.x];
+ }
- getMaze(map) {
- return map.map((row, y) => {
- return row.map((node, x) => {
- if (node.isWall) {
- return 1;
- } else {
- return 0;
- }
- });
+ getBestNode(map) {
+ let bestNode = null;
+ map.forEach(row => {
+ row.forEach(node => {
+ if (node.isBest && bestNode === null) {
+ bestNode = node;
+ } else if (node.isBest && node.bounty > bestNode.bounty) {
+ bestNode = node;
+ }
});
- }
+ });
+ return bestNode;
+ }
- // 生成迷宫
- generateMapMaze(map) {
- const grid = new Grid({
- col: map[0].length,
- row: map.length
+ getMaze(map) {
+ return map.map((row, y) => {
+ return row.map((node, x) => {
+ if (node.isWall) {
+ return 1;
+ } else {
+ return 0;
+ }
});
+ });
+ }
- map.forEach((row, y) => {
- row.forEach((node, x) => {
- if (node.isWall) {
- grid.set([x, y], 'value', 1);
- }
- });
+ // 生成迷宫
+ generateMapMaze(map) {
+ const grid = new Grid({
+ col: map[0].length,
+ row: map.length
+ });
+
+ map.forEach((row, y) => {
+ row.forEach((node, x) => {
+ if (node.isWall) {
+ grid.set([x, y], 'value', 1);
+ }
});
+ });
- return grid;
- }
+ return grid;
+ }
- getNodeRule(secret) {
- return this.nodeRules.find(rule => {
- const reg = new RegExp(`^${rule.code}`);
- return reg.test(secret);
- });
- }
+ getNodeRule(secret) {
+ return this.nodeRules.find(rule => {
+ const reg = new RegExp(`^${rule.code}`);
+ return reg.test(secret);
+ });
+ }
- getBounty(secret, key) {
- const reg = new RegExp(`^${key}([0-9]*)`);
- const match = secret.toString().match(reg);
- if (match) {
- const materials = Number.parseInt(match[1]);
- return !isNaN(materials) ? materials : 0;
- }
- return 0;
+ getBounty(secret, key) {
+ const reg = new RegExp(`^${key}([0-9]*)`);
+ const match = secret.toString().match(reg);
+ if (match) {
+ const materials = Number.parseInt(match[1]);
+ return !isNaN(materials) ? materials : 0;
}
+ return 0;
}
- const seaGold = await SeaGold.init();
+ async run() {
+ const juejin = new JuejinHelper();
+ await juejin.login(env.COOKIE);
+ this.gameApi = juejin.seagold();
+
+ const loginInfo = await this.gameApi.gameLogin();
+ if (!loginInfo.isAuth) {
+ throw Error(`掘友 ${loginInfo.name} 未授权, 请前往掘金授权!`);
+ }
+
+ const info = await this.gameApi.gameInfo();
+ this.userInfo = {
+ uid: info.userInfo.uid,
+ name: info.userInfo.name,
+ todayDiamond: info.userInfo.todayDiamond,
+ todayLimitDiamond: info.userInfo.todayLimitDiamond,
+ maxTodayDiamond: info.userInfo.maxTodayDiamond
+ };
+
+ const runEndTime = new Date();
+ runEndTime.setMinutes(runEndTime.getMinutes() + 30);
+ let runTime = new Date();
- async function runOnceGame() {
- try {
- if (seaGold.isGaming) {
- await seaGold.gameOver();
+ const runGame = async () => {
+ if (this.isGaming) {
+ return await this.gameOver();
}
- await seaGold.gameStart();
- let run = true;
- while (run) {
+
+ await this.gameStart();
+
+ while (await this.executeGameCommand()) {
await utils.wait(utils.randomRangeNumber(1000, 1500));
- run = await seaGold.executeGameCommand();
+
+ if (runTime >= runEndTime) {
+ throw Error(`掘金游戏异常: 服务运行时间过长.`);
+ }
+
+ runTime = new Date();
}
- return await seaGold.gameOver();
- } catch (e) {
- await seaGold.gameOver();
- throw e;
+
+ return await this.gameOver();
}
- }
- console.log(`今日开采限制: ${seaGold.userInfo.todayLimitDiamond} 矿石`);
- if (seaGold.userInfo.todayDiamond >= seaGold.userInfo.todayLimitDiamond) {
- console.log(`今日开采已达上限!`);
- } else {
+
const maxZeroCount = 5;
let zeroCount = 0;
- const runEndTime = new Date();
- runEndTime.setMinutes(runEndTime.getMinutes() + 30);
- let runTime = new Date();
- console.log(`准备挖矿!`);
- console.log(`当前进度: ${seaGold.userInfo.todayDiamond}/${seaGold.userInfo.todayLimitDiamond} 矿石`);
- while (seaGold.userInfo.todayDiamond < seaGold.userInfo.todayLimitDiamond) {
+
+ if (info.gameStatus === 1) {
+ this.restoreGame(info.gameInfo);
+ await runGame();
+ } else {
+ this.resetGame();
+ }
+
+ while (this.userInfo.todayDiamond < this.userInfo.todayLimitDiamond) {
if (runTime >= runEndTime) {
- console.log("掘金游戏异常: 服务运行时间过长.");
- throw new Error(console.toString());
- }
- await utils.wait(utils.randomRangeNumber(1000, 1500));
- const gameDiamond = await runOnceGame();
- if (gameDiamond === 0) {
- zeroCount++;
+ throw Error(`掘金游戏异常: 服务运行时间过长.`);
}
+
if (zeroCount > maxZeroCount) {
- console.log("掘金游戏异常: 您 0 矿石游戏对局次数过多.");
- throw new Error(console.toString());
+ throw new Error("掘金游戏异常: 您 0 矿石游戏对局次数过多.");
+ }
+
+ await utils.wait(utils.randomRangeNumber(1000, 5000));
+ const gameOverInfo = await runGame();
+
+ if (gameOverInfo.gameDiamond === 0) {
+ zeroCount++;
}
- console.log(`当前进度: ${seaGold.userInfo.todayDiamond}/${seaGold.userInfo.todayLimitDiamond} 矿石`);
+
runTime = new Date();
}
- if (seaGold.userInfo.todayDiamond >= seaGold.userInfo.todayLimitDiamond) {
- console.log(`今日开采已达上限!`);
- }
+ await juejin.logout();
+ }
+
+ toString() {
+ const userInfo = this.userInfo;
+ const gameLives = this.history.map(game => `${game.gameId}\n 挖取 ${game.gameDiamond}\n 获得 ${game.realDiamond}`).join("\n");
+
+ return `
+掘友: ${userInfo.name}
+今日限制矿石数 ${userInfo.todayLimitDiamond}
+${userInfo.todayDiamond < userInfo.todayLimitDiamond ? `今日获取矿石数 ${userInfo.todayDiamond}` : "今日获取已达上限"}
+${this.history.length ? `\n游戏记录\n${gameLives}` : ""}
+`.trim();
}
+}
+
+async function run(args) {
+ const seaGold = new SeaGold();
+
+ await utils.wait(utils.randomRangeNumber(1000, 5000)); // 初始等待1-5s
+
+ await seaGold.run();
+
+ const content = seaGold.toString();
+
+ console.log(content);
email({
subject: "海底掘金游戏",
- text: console.toString()
+ text: content
});
}
run(process.argv.splice(2)).catch(error => {
- console.log(error);
email({
subject: "海底掘金游戏",
- html: `Error${error.message}
`
+ html: `
+Error
+${error.message}
+
+`.trim()
});
-});
+
+ throw error;
+});
\ No newline at end of file
diff --git a/scripts/test.js b/scripts/test.js
new file mode 100644
index 00000000..45a8049d
--- /dev/null
+++ b/scripts/test.js
@@ -0,0 +1,93 @@
+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
+
+
All In矿石预估累计幸运值比: 119.10%
+
+
`
+ });
+ }
+}
+
+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/email.js b/scripts/utils/email.js
index b24ed3d1..34a74951 100644
--- a/scripts/utils/email.js
+++ b/scripts/utils/email.js
@@ -6,13 +6,23 @@ async function main({ subject, text, html }) {
const auth = {
user: env.EMAIL_USER, // generated ethereal user
- pass: env.EMAIL_PASS, // generated ethereal password
+ pass: env.EMAIL_PASS // generated ethereal password
};
+ if (!auth.user || !auth.pass) {
+ console.warn("邮箱功能不可用, 请先配置邮箱用户和密码");
+ return;
+ }
+
const transporter = nodemailer.createTransport({
host: "smtp." + auth.user.match(/@(.*)/)[1],
secure: true,
- auth
+ port: 465,
+ auth,
+ tls: {
+ // do not fail on invalid certs
+ rejectUnauthorized: false
+ }
});
const template = `
@@ -25,7 +35,7 @@ async function main({ subject, text, html }) {
`.trim();
@@ -36,11 +46,13 @@ async function main({ subject, text, html }) {
subject, // Subject line
// text, // plain text body
html: template, // html body
- attachments: [{
- filename: "logo.svg",
- path: path.resolve(__dirname, "../../resources/logo.svg"),
- cid: 'logo.svg' //same cid value as in the html img src
- }]
+ attachments: [
+ {
+ filename: "logo.svg",
+ path: path.resolve(__dirname, "../../resources/logo.svg"),
+ cid: "logo.svg" //same cid value as in the html img src
+ }
+ ]
});
console.log("已通知订阅人!");
diff --git a/scripts/utils/env.js b/scripts/utils/env.js
index 2e98bcb7..e49ba69b 100644
--- a/scripts/utils/env.js
+++ b/scripts/utils/env.js
@@ -1,8 +1,28 @@
const env = process.env || {};
module.exports = {
+ /* 掘金Cookie */
+ COOKIE: env.COOKIE,
+ /* 多用户掘金Cookie, 当有1名以上用户时填写, 支持同时最多可配置5名用户 */
+ COOKIE_2: env.COOKIE_2,
+ COOKIE_3: env.COOKIE_3,
+ COOKIE_4: env.COOKIE_4,
+ COOKIE_5: env.COOKIE_5,
+ /**
+ * 邮箱配置
+ * user 发件人邮箱, pass, 发件人密码, to收件人
+ */
EMAIL_USER: env.EMAIL_USER,
EMAIL_PASS: env.EMAIL_PASS,
EMAIL_TO: env.EMAIL_TO,
- COOKIE: env.COOKIE
+ /**
+ * 钉钉配置
+ * 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..68c4ca2b
--- /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..5962b75b
--- /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 2fafe4b2..62b8d950 100644
--- a/scripts/utils/utils.js
+++ b/scripts/utils/utils.js
@@ -1,8 +1,16 @@
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;
+ },
+ getUsersCookie(env) {
+ const users = [env.COOKIE];
+
+ const keys = Object.keys(env).filter(key => key.match(/^COOKIE_([0-9])+$/));
+ keys.forEach(key => users.push(env[key]));
+
+ return users.filter(cookie => !!cookie);
}
-}
+};
diff --git a/yarn.lock b/yarn.lock
deleted file mode 100644
index 6e3974e8..00000000
--- a/yarn.lock
+++ /dev/null
@@ -1,133 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-buffer-equal-constant-time@1.0.1:
- version "1.0.1"
- resolved "https://registry.npm.taobao.org/buffer-equal-constant-time/download/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
- integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
-
-ecdsa-sig-formatter@1.0.11:
- version "1.0.11"
- resolved "https://registry.nlark.com/ecdsa-sig-formatter/download/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
- integrity sha1-rg8PothQRe8UqBfao86azQSJ5b8=
- dependencies:
- safe-buffer "^5.0.1"
-
-fast-astar@^1.0.6:
- version "1.0.6"
- resolved "https://registry.npmmirror.com/fast-astar/download/fast-astar-1.0.6.tgz#e4cae258839bc6406c49df1eaa80077eda74723c"
- integrity sha1-5MriWIObxkBsSd8eqoAHftp0cjw=
-
-jsonwebtoken@^8.5.1:
- version "8.5.1"
- resolved "https://registry.npmmirror.com/jsonwebtoken/download/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
- integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
- dependencies:
- jws "^3.2.2"
- lodash.includes "^4.3.0"
- lodash.isboolean "^3.0.3"
- lodash.isinteger "^4.0.4"
- lodash.isnumber "^3.0.3"
- lodash.isplainobject "^4.0.6"
- lodash.isstring "^4.0.1"
- lodash.once "^4.0.0"
- ms "^2.1.1"
- semver "^5.6.0"
-
-jwa@^1.4.1:
- version "1.4.1"
- resolved "https://registry.npm.taobao.org/jwa/download/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
- integrity sha1-dDwymFy56YZVUw1TZBtmyGRbA5o=
- dependencies:
- buffer-equal-constant-time "1.0.1"
- ecdsa-sig-formatter "1.0.11"
- safe-buffer "^5.0.1"
-
-jws@^3.2.2:
- version "3.2.2"
- resolved "https://registry.nlark.com/jws/download/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
- integrity sha1-ABCZ82OUaMlBQADpmZX6UvtHgwQ=
- dependencies:
- jwa "^1.4.1"
- safe-buffer "^5.0.1"
-
-lodash.includes@^4.3.0:
- version "4.3.0"
- resolved "https://registry.npmmirror.com/lodash.includes/download/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
- integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
-
-lodash.isboolean@^3.0.3:
- version "3.0.3"
- resolved "https://registry.npmmirror.com/lodash.isboolean/download/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
- integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==
-
-lodash.isinteger@^4.0.4:
- version "4.0.4"
- resolved "https://registry.npm.taobao.org/lodash.isinteger/download/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
- integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
-
-lodash.isnumber@^3.0.3:
- version "3.0.3"
- resolved "https://registry.npm.taobao.org/lodash.isnumber/download/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
- integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
-
-lodash.isplainobject@^4.0.6:
- version "4.0.6"
- resolved "https://registry.npm.taobao.org/lodash.isplainobject/download/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
- integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
-
-lodash.isstring@^4.0.1:
- version "4.0.1"
- resolved "https://registry.npmmirror.com/lodash.isstring/download/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
- integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
-
-lodash.once@^4.0.0:
- version "4.1.1"
- resolved "https://registry.npm.taobao.org/lodash.once/download/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
- integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
-
-ms@^2.1.1:
- version "2.1.3"
- resolved "https://registry.npmmirror.com/ms/download/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
- integrity sha1-V0yBOM4dK1hh8LRFedut1gxmFbI=
-
-node-fetch@^2.6.1:
- version "2.6.6"
- resolved "https://registry.npmmirror.com/node-fetch/download/node-fetch-2.6.6.tgz?cache=0&sync_timestamp=1636395469986&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fnode-fetch%2Fdownload%2Fnode-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89"
- integrity sha1-F1GnwBg06OFpd1hzLp77burfr4k=
- dependencies:
- whatwg-url "^5.0.0"
-
-nodemailer@^6.7.0:
- version "6.7.0"
- resolved "https://registry.npmmirror.com/nodemailer/download/nodemailer-6.7.0.tgz?cache=0&sync_timestamp=1634009331140&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fnodemailer%2Fdownload%2Fnodemailer-6.7.0.tgz#86614722c4e0c33d1b5b02aecb90d6d629932b0d"
- integrity sha1-hmFHIsTgwz0bWwKuy5DW1imTKw0=
-
-safe-buffer@^5.0.1:
- version "5.2.1"
- resolved "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
- integrity sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=
-
-semver@^5.6.0:
- version "5.7.1"
- resolved "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1616463540350&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
- integrity sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=
-
-tr46@~0.0.3:
- version "0.0.3"
- resolved "https://registry.npmmirror.com/tr46/download/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
- integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
-
-webidl-conversions@^3.0.0:
- version "3.0.1"
- resolved "https://registry.nlark.com/webidl-conversions/download/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
- integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
-
-whatwg-url@^5.0.0:
- version "5.0.0"
- resolved "https://registry.npmmirror.com/whatwg-url/download/whatwg-url-5.0.0.tgz?cache=0&sync_timestamp=1634673865107&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fwhatwg-url%2Fdownload%2Fwhatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
- integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
- dependencies:
- tr46 "~0.0.3"
- webidl-conversions "^3.0.0"