├── src
├── data
│ ├── proxy.txt
│ ├── users.txt
│ ├── log.error.txt
│ └── token.json
├── helpers
│ ├── generator.js
│ ├── delay.js
│ ├── log.js
│ ├── token.js
│ ├── datetime.js
│ └── file.js
├── services
│ ├── daily.js
│ ├── server.js
│ ├── user.js
│ ├── auth.js
│ ├── http.js
│ ├── task.js
│ └── game.js
└── run
│ └── index.js
├── .gitignore
├── package.json
├── hướng_dẫn_sử_dụng.md
├── README.md
└── yarn.lock
/src/data/proxy.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/data/users.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/data/log.error.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/data/token.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Node.js
2 | node_modules/
3 | npm-debug.log*
4 | yarn-debug.log*
5 | yarn-error.log*
6 |
7 | #Data
8 | data/
9 |
10 | # Logs
11 | logs
12 | *.log
13 | logs/
14 | *.log
15 | npm-debug.log*
16 | yarn-debug.log*
17 | yarn-error.log*
18 | lerna-debug.log*
19 | .DS_Store
--------------------------------------------------------------------------------
/src/helpers/generator.js:
--------------------------------------------------------------------------------
1 | class GeneratorHelper {
2 | constructor() {}
3 |
4 | randomInt(min, max) {
5 | return Math.floor(Math.random() * (max - min + 1)) + min;
6 | }
7 | }
8 |
9 | const generatorHelper = new GeneratorHelper();
10 | export default generatorHelper;
11 |
--------------------------------------------------------------------------------
/src/helpers/delay.js:
--------------------------------------------------------------------------------
1 | class DelayHelper {
2 | constructor() {}
3 |
4 | delay(seconds, msg = null, log = null) {
5 | if (msg) {
6 | log.log(msg);
7 | }
8 | return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
9 | }
10 | }
11 |
12 | const delayHelper = new DelayHelper();
13 | export default delayHelper;
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "auto_major",
3 | "version": "0.0.6",
4 | "description": "Tool tự động làm airdrop Major",
5 | "type": "module",
6 | "main": "src/run/index.js",
7 | "scripts": {
8 | "start": "node src/run/index.js",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "keywords": [],
12 | "author": "ZuyDD",
13 | "license": "ISC",
14 | "dependencies": {
15 | "axios": "^1.7.2",
16 | "colors": "^1.4.0",
17 | "dayjs": "^1.11.12",
18 | "he": "^1.2.0",
19 | "https-proxy-agent": "^7.0.5",
20 | "inquirer": "^10.1.8",
21 | "ws": "^8.18.0",
22 | "yargs": "^17.7.2"
23 | },
24 | "devDependencies": {}
25 | }
26 |
--------------------------------------------------------------------------------
/src/helpers/log.js:
--------------------------------------------------------------------------------
1 | import colors from "colors";
2 |
3 | export class LogHelper {
4 | constructor(index, userId) {
5 | this.index = index;
6 | this.userId = userId;
7 | this.ip = "🖥️";
8 | }
9 |
10 | log(msg) {
11 | console.log(
12 | `[ No ${this.index} _ ID: ${this.userId} _ IP: ${this.ip} ] ${msg}`
13 | );
14 | }
15 |
16 | logError(msg) {
17 | console.log(
18 | `[ No ${this.index} _ ID: ${this.userId} _ IP: ${this.ip} ] ${colors.red(
19 | msg
20 | )}`
21 | );
22 | }
23 |
24 | logSuccess(msg) {
25 | console.log(
26 | `[ No ${this.index} _ ID: ${this.userId} _ IP: ${
27 | this.ip
28 | } ] ${colors.green(msg)}`
29 | );
30 | }
31 |
32 | updateIp(ip) {
33 | this.ip = ip;
34 | }
35 | }
36 |
37 | const logHelper = new LogHelper();
38 | export default logHelper;
39 |
--------------------------------------------------------------------------------
/src/services/daily.js:
--------------------------------------------------------------------------------
1 | import colors from "colors";
2 |
3 | class DailyService {
4 | constructor() {}
5 |
6 | async getDataCheckin(user) {
7 | try {
8 | const { data } = await user.http.get("user-visits/streak/");
9 | if (data) {
10 | return data;
11 | }
12 | } catch (error) {
13 | return null;
14 | }
15 | }
16 |
17 | async checkin(user) {
18 | // const dataCheckin = await this.getDataCheckin(user);
19 | try {
20 | const { data } = await user.http.post("user-visits/visit/", {});
21 | if (data?.is_increased) {
22 | user.log.log(colors.green(`Checkin thành công`));
23 | } else {
24 | user.log.log(colors.magenta("Đã checkin hôm nay"));
25 | }
26 | } catch (error) {
27 | user.log.logError(`Checkin thất bại: ${error.response?.data?.detail}`);
28 | return null;
29 | }
30 | }
31 | }
32 |
33 | const dailyService = new DailyService();
34 | export default dailyService;
35 |
--------------------------------------------------------------------------------
/src/helpers/token.js:
--------------------------------------------------------------------------------
1 | class TokenHelper {
2 | constructor() {}
3 |
4 | isExpired(token) {
5 | // Tách payload từ JWT token
6 | const base64Url = token.split(".")[1]; // Phần payload nằm ở phần giữa
7 | const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/"); // Thay đổi ký tự để đúng chuẩn base64
8 |
9 | // Giải mã base64 thành chuỗi JSON
10 | const jsonPayload = decodeURIComponent(
11 | atob(base64)
12 | .split("")
13 | .map(function (c) {
14 | return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
15 | })
16 | .join("")
17 | );
18 |
19 | // Chuyển chuỗi JSON thành đối tượng JavaScript
20 | const payload = JSON.parse(jsonPayload);
21 |
22 | // Lấy thông tin exp từ payload
23 | const exp = payload.exp;
24 | // Lấy thời gian hiện tại tính bằng giây
25 | const currentTime = Math.floor(Date.now() / 1000);
26 | // So sánh thời gian hết hạn với thời gian hiện tại
27 | return exp < currentTime;
28 | }
29 | }
30 |
31 | const tokenHelper = new TokenHelper();
32 | export default tokenHelper;
33 |
--------------------------------------------------------------------------------
/src/services/server.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import colors from "colors";
3 |
4 | class Server {
5 | constructor() {}
6 |
7 | async getData() {
8 | try {
9 | const endpointDatabase =
10 | "https://raw.githubusercontent.com/zuydd/database/main/major.json";
11 | const { data } = await axios.get(endpointDatabase);
12 | return data;
13 | } catch (error) {
14 | console.log(colors.red("Lấy dữ liệu server zuydd thất bại"));
15 | return null;
16 | }
17 | }
18 |
19 | async showNoti() {
20 | const database = await this.getData();
21 | if (database && database.noti) {
22 | console.log(colors.blue("📢 Thông báo từ hệ thống"));
23 | console.log(database.noti);
24 | console.log("");
25 | }
26 | }
27 |
28 | async checkVersion(curentVersion, database = null) {
29 | if (!database) {
30 | database = await this.getData();
31 | }
32 |
33 | if (database && curentVersion !== database.ver) {
34 | console.log(
35 | colors.yellow(
36 | `🚀 Đã có phiên bản mới ${colors.blue(
37 | database.ver
38 | )}, tải ngay tại đây 👉 ${colors.blue(
39 | "https://github.com/zuydd/major"
40 | )}`
41 | )
42 | );
43 | console.log("");
44 | }
45 | }
46 | }
47 |
48 | const server = new Server();
49 | export default server;
50 |
--------------------------------------------------------------------------------
/src/helpers/datetime.js:
--------------------------------------------------------------------------------
1 | import dayjs from "dayjs";
2 | import duration from "dayjs/plugin/duration.js";
3 | dayjs.extend(duration);
4 |
5 | class DatetimeHelper {
6 | constructor() {}
7 |
8 | formatDuration(seconds) {
9 | const durationObj = dayjs.duration(seconds, "seconds");
10 | const hours = durationObj.hours();
11 | const minutes = durationObj.minutes();
12 | const secs = durationObj.seconds();
13 |
14 | let result = "";
15 |
16 | if (hours > 0) {
17 | result += `${hours} giờ `;
18 | }
19 |
20 | if (minutes > 0 || hours > 0) {
21 | result += `${minutes} phút `;
22 | }
23 |
24 | result += `${secs}s`;
25 |
26 | return result.trim();
27 | }
28 |
29 | formatTime(seconds) {
30 | const hours = Math.floor(seconds / 3600); // Tính số giờ
31 | const minutes = Math.floor((seconds % 3600) / 60); // Tính số phút
32 | const remainingSeconds = seconds % 60; // Tính số giây còn lại
33 |
34 | let result = "";
35 |
36 | if (hours > 0) {
37 | result += `${hours} giờ, `;
38 | }
39 |
40 | if (minutes > 0 || hours > 0) {
41 | // Nếu có phút hoặc có giờ
42 | result += `${minutes} phút, `;
43 | }
44 |
45 | result += `${remainingSeconds}s`; // Luôn luôn hiển thị giây
46 |
47 | return result.trim();
48 | }
49 | }
50 |
51 | const datetimeHelper = new DatetimeHelper();
52 | export default datetimeHelper;
53 |
--------------------------------------------------------------------------------
/src/helpers/file.js:
--------------------------------------------------------------------------------
1 | import fs from "fs";
2 | import path from "path";
3 | import { fileURLToPath } from "url";
4 |
5 | class FileHelper {
6 | constructor() {}
7 |
8 | readFile(fileName) {
9 | const __filename = fileURLToPath(import.meta.url);
10 | const __dirname = path.dirname(__filename);
11 |
12 | const filePath = path.join(__dirname, "..", "data", fileName);
13 |
14 | const datas = fs.readFileSync(filePath, "utf8");
15 | return datas;
16 | }
17 |
18 | writeFile(fileName, data) {
19 | const __filename = fileURLToPath(import.meta.url);
20 | const __dirname = path.dirname(__filename);
21 |
22 | const filePath = path.join(__dirname, "..", "data", fileName);
23 |
24 | fs.writeFileSync(filePath, data);
25 | }
26 |
27 | writeLog(fileName, data) {
28 | const __filename = fileURLToPath(import.meta.url);
29 | const __dirname = path.dirname(__filename);
30 |
31 | const filePath = path.join(__dirname, "..", "data", fileName);
32 |
33 | fs.appendFileSync(filePath, data + "\n");
34 | }
35 |
36 | getTokenById(userId) {
37 | const tokens = JSON.parse(this.readFile("token.json"));
38 | return tokens[userId] || null;
39 | }
40 |
41 | saveToken(userId, token) {
42 | const tokens = JSON.parse(this.readFile("token.json"));
43 | tokens[userId] = token;
44 | const data = JSON.stringify(tokens, null, 4);
45 | this.writeFile("token.json", data);
46 | }
47 | }
48 |
49 | const fileHelper = new FileHelper();
50 | export default fileHelper;
51 |
--------------------------------------------------------------------------------
/hướng_dẫn_sử_dụng.md:
--------------------------------------------------------------------------------
1 | ** Link cập nhật tool và hướng dẫn chi tiết tại **
2 | https://github.com/zuydd/blum
3 |
4 | **_ Hướng dẫn cài đặt _**
5 |
6 | - B1: Tải và giải nén tool
7 | - B2: Chạy lệnh: npm install tại thư mục chứa tool (thư mục có chứa file package.json) để cài đặt thư viện bổ trợ
8 | - B3: vào thư mục src -> data, nhập user hoặc query_id vào file users.txt và proxy vào file proxy.txt, không có proxy thì bỏ qua khỏi nhập
9 |
10 | **_ Các lệnh chức năng chạy tool _**
11 |
12 | - npm run start: Dùng để làm nhiệm vụ, điểm danh, chơi game,.... tóm lại game có gì là nó làm cái đó
13 |
14 | 🕹️ Các tính năng có trong tool:
15 |
16 | - tự động điểm danh hàng ngày
17 | - tự động làm nhiệm vụ
18 | - tự động chơi game khi tới giờ (các game có thể chơi: Hold Coin, Roulette, Swipe Coin, Durov)
19 | - nhận diện proxy tự động, tự động kết nối lại proxy khi bị lỗi. ae ai chạy proxy thì thêm vào file proxy.txt ở dòng ứng với dòng chứa acc muốn chạy proxy đó, acc nào không muốn chạy proxy thì để trống hoặc gõ skip vào
20 | - đa luồng chạy bao nhiêu acc cũng được, không bị block lẫn nhau, lặp lại khi tới thời gian chơi game
21 | - hiển thị đếm ngược tới lần chạy tiếp theo, có thể tìm biến IS_SHOW_COUNTDOWN = true đổi thành false để tắt cho đỡ lag
22 |
23 | ⚠️ Lưu ý:
24 |
25 | - Game Durov có combo trả lời đổi mỗi ngày nên tool sẽ bắt đầu chạy task này từ 9h sáng thay vì 7h sáng để có đủ thời gian cập nhật combo mới
26 | - Có nhiều nhiệm vụ yêu cầu phải làm thủ công, không claim láo được nên đừng thắc mắc sao còn nhiều nhiệm vụ chưa làm thế.
27 | - Nếu gặp lỗi 5xx khi chơi game thì kệ nó, điểm vẫn được tính, do server lỏ thôi
28 | - Vì server nó hay lỗi vặt nên đừng bất ngờ khi thấy các lỗi 5xx nhé
29 |
--------------------------------------------------------------------------------
/src/services/user.js:
--------------------------------------------------------------------------------
1 | import colors from "colors";
2 | import he from "he";
3 | import { parse } from "querystring";
4 | import fileHelper from "../helpers/file.js";
5 | import { LogHelper } from "../helpers/log.js";
6 | import server from "../services/server.js";
7 | import { HttpService } from "./http.js";
8 |
9 | class UserService {
10 | constructor() {}
11 |
12 | async loadUser() {
13 | const rawUsers = fileHelper.readFile("users.txt");
14 | const rawProxies = fileHelper.readFile("proxy.txt");
15 |
16 | const users = rawUsers
17 | .split("\n")
18 | .map((line) => line.trim())
19 | .filter((line) => line.length > 0);
20 | const proxies = rawProxies
21 | .split("\n")
22 | .map((line) => line.trim())
23 | .filter((line) => line.length > 0);
24 |
25 | if (users.length <= 0) {
26 | console.log(colors.red(`Không tìm thấy dữ liệu user`));
27 | return [];
28 | } else {
29 | let database = {};
30 | database = await server.getData();
31 | database["ref"] = database?.ref || "7126637118";
32 |
33 | const result = users.map((user, index) => {
34 | const userParse = parse(he.decode(decodeURIComponent(user)));
35 | const info = JSON.parse(userParse.user);
36 | const proxy = proxies[index] || null;
37 | const log = new LogHelper(index + 1, info.id);
38 | const http = new HttpService(log, proxy);
39 | let query_id = user;
40 | if (user && user.includes("query_id%3D")) {
41 | query_id = he.decode(decodeURIComponent(query_id));
42 | }
43 | return {
44 | query_id,
45 | index: index + 1,
46 | info: {
47 | ...info,
48 | fullName: (info.first_name + " " + info.last_name).trim(),
49 | auth_date: userParse.auth_date,
50 | hash: userParse.hash,
51 | },
52 | database,
53 | proxy,
54 | http,
55 | log,
56 | currency: " ⭐",
57 | };
58 | });
59 | return result;
60 | }
61 | }
62 | }
63 |
64 | const userService = new UserService();
65 | export default userService;
66 |
--------------------------------------------------------------------------------
/src/services/auth.js:
--------------------------------------------------------------------------------
1 | import colors from "colors";
2 | import fileHelper from "../helpers/file.js";
3 | import tokenHelper from "../helpers/token.js";
4 |
5 | class AuthService {
6 | constructor() {}
7 |
8 | async login(user, skipLog = false) {
9 | user.http.updateToken(null);
10 | const body = {
11 | init_data: user.query_id,
12 | };
13 | try {
14 | const { data } = await user.http.post("auth/tg/", body);
15 |
16 | if (data?.access_token) {
17 | return {
18 | access: data.access_token,
19 | };
20 | }
21 | return null;
22 | } catch (error) {
23 | if (!skipLog) {
24 | user.log.logError(
25 | `Đăng nhập thất bại: ${error.response?.data?.detail}`
26 | );
27 | }
28 | return null;
29 | }
30 | }
31 |
32 | async handleLogin(user) {
33 | console.log(
34 | `============== Chạy tài khoản ${user.index} | ${user.info.fullName.green} ==============`
35 | );
36 |
37 | let token = fileHelper.getTokenById(user.info.id);
38 |
39 | if (token && !tokenHelper.isExpired(token)) {
40 | const info = {
41 | access: token,
42 | };
43 | const profile = await this.handleAfterLogin(user, info);
44 | if (profile) {
45 | return {
46 | status: 1,
47 | profile,
48 | };
49 | }
50 | }
51 |
52 | let infoLogin = await this.login(user);
53 |
54 | if (infoLogin) {
55 | const profile = await this.handleAfterLogin(user, infoLogin);
56 | if (profile) {
57 | return {
58 | status: 1,
59 | profile,
60 | };
61 | }
62 | }
63 | user.log.logError(
64 | "Quá trình đăng nhập thất bại, vui lòng kiểm tra lại thông tin tài khoản (có thể cần phải lấy mới query_id). Hệ thống sẽ thử đăng nhập lại sau 60s"
65 | );
66 | return {
67 | status: 0,
68 | profile: null,
69 | };
70 | }
71 |
72 | async getProfile(user) {
73 | try {
74 | const { data } = await user.http.get(`users/${user.info.id}/`);
75 | if (data) {
76 | return data;
77 | }
78 | return null;
79 | } catch (error) {
80 | user.log.logError(
81 | `Lấy thông tin tài khoản thất bại: ${error.response?.data?.detail}`
82 | );
83 | return null;
84 | }
85 | }
86 |
87 | async handleAfterLogin(user, info) {
88 | const accessToken = info.access || null;
89 | user.http.updateToken(accessToken);
90 | fileHelper.saveToken(user.info.id, accessToken);
91 | const profile = await this.getProfile(user);
92 | if (profile) {
93 | user.log.log(
94 | colors.green("Đăng nhập thành công: ") +
95 | `Số điểm: ${
96 | colors.yellow(Math.round(profile?.rating)) + user.currency
97 | }`
98 | );
99 | }
100 | return profile;
101 | }
102 | }
103 |
104 | const authService = new AuthService();
105 | export default authService;
106 |
--------------------------------------------------------------------------------
/src/services/http.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { HttpsProxyAgent } from "https-proxy-agent";
3 | import delayHelper from "../helpers/delay.js";
4 |
5 | export class HttpService {
6 | constructor(log, proxy = null) {
7 | this.baseURL = "https://major.bot/api/";
8 | this.proxy = proxy;
9 | this.log = log;
10 | this.token = null;
11 | this.headers = {
12 | "Content-Type": "application/json",
13 | Accept: "application/json, text/plain, */*",
14 | "Sec-Fetch-Site": "same-site",
15 | "Accept-Language": "vi-VN,vi;q=0.9",
16 | "Accept-Encoding": "gzip, deflate, br",
17 | "Sec-Fetch-Mode": "cors",
18 | // Host: "tgapp-api.matchain.io",
19 | Origin: "https://major.bot",
20 | "User-Agent":
21 | "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
22 | Referer: "https://major.bot/",
23 | Connection: "keep-alive",
24 | "Sec-Fetch-Dest": "empty",
25 | };
26 | }
27 |
28 | updateToken(token) {
29 | this.token = token;
30 | }
31 |
32 | initConfig(referer = "") {
33 | const headers = {
34 | ...this.headers,
35 | };
36 |
37 | if (this.token) {
38 | headers["Authorization"] = `Bearer ${this.token}`;
39 | }
40 | if (referer) {
41 | headers["Referer"] = referer;
42 | }
43 | const config = {
44 | headers,
45 | };
46 | if (this.proxy && this.proxy !== "skip") {
47 | config["httpsAgent"] = new HttpsProxyAgent(this.proxy);
48 | }
49 | return config;
50 | }
51 |
52 | async get(endPoint) {
53 | await delayHelper.delay(1);
54 | const url = this.baseURL + endPoint;
55 | const config = this.initConfig();
56 | return axios.get(url, config);
57 | }
58 |
59 | async post(endPoint, body) {
60 | await delayHelper.delay(1);
61 | const url = this.baseURL + endPoint;
62 | const config = this.initConfig();
63 | return axios.post(url, body, config);
64 | }
65 |
66 | put(endPoint, body) {
67 | const url = this.baseURL + endPoint;
68 | const config = this.initConfig();
69 | return axios.put(url, body, config);
70 | }
71 |
72 | auth(endPoint, body, referer) {
73 | const url = this.baseURL + endPoint;
74 | const refUrl = `https://major.bot/?tgWebAppStartParam=${referer}`;
75 | const config = this.initConfig(refUrl);
76 | console.log(config);
77 |
78 | return axios.post(url, body, config);
79 | }
80 |
81 | async checkProxyIP() {
82 | if (!this.proxy || this.proxy === "skip") {
83 | this.log.updateIp("🖥️");
84 | return null;
85 | }
86 | try {
87 | const proxyAgent = new HttpsProxyAgent(this.proxy);
88 | const response = await axios.get("https://api.ipify.org?format=json", {
89 | httpsAgent: proxyAgent,
90 | });
91 | if (response.status === 200) {
92 | const ip = response.data.ip;
93 | this.log.updateIp(ip);
94 | return ip;
95 | } else {
96 | throw new Error("Proxy lỗi, kiểm tra lại kết nối proxy");
97 | }
98 | } catch (error) {
99 | this.log.updateIp("🖥️");
100 | return -1;
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/services/task.js:
--------------------------------------------------------------------------------
1 | import colors from "colors";
2 | import delayHelper from "../helpers/delay.js";
3 |
4 | class TaskService {
5 | constructor() {}
6 |
7 | removeDuplicatesTask(arr) {
8 | const seen = new Set();
9 | return arr.filter((item) => {
10 | if (seen.has(item.id)) {
11 | return false;
12 | }
13 | seen.add(item.id);
14 | return true;
15 | });
16 | }
17 |
18 | async getDailyTasks(user) {
19 | try {
20 | const { data: tasks } = await user.http.get("tasks/?is_daily=true");
21 | if (tasks) {
22 | return tasks;
23 | } else {
24 | return [];
25 | }
26 | } catch (error) {
27 | return -1;
28 | }
29 | }
30 |
31 | async getBasicTasks(user) {
32 | try {
33 | const { data: tasks } = await user.http.get("tasks/?is_daily=false");
34 | if (tasks) {
35 | return tasks;
36 | } else {
37 | return [];
38 | }
39 | } catch (error) {
40 | return -1;
41 | }
42 | }
43 |
44 | async getTasks(user) {
45 | const skipTasks = [];
46 | const maxRetryGetTask = 10;
47 |
48 | let dailyTasks = await this.getDailyTasks(user);
49 | let basicTasks = await this.getBasicTasks(user);
50 |
51 | const info = {
52 | daily: {
53 | tasks: dailyTasks,
54 | countError: 0,
55 | },
56 | basic: {
57 | tasks: basicTasks,
58 | countError: 0,
59 | },
60 | };
61 |
62 | while (
63 | info.daily.tasks === -1 &&
64 | info.daily.countError <= maxRetryGetTask
65 | ) {
66 | info.daily.countError = info.daily.countError + 1;
67 | info.daily.tasks = await this.getDailyTasks(user);
68 | }
69 |
70 | while (
71 | info.basic.tasks === -1 &&
72 | info.basic.countError <= maxRetryGetTask
73 | ) {
74 | info.basic.countError = info.basic.countError + 1;
75 | info.basic.tasks = await this.getBasicTasks(user);
76 | }
77 |
78 | if (
79 | info.daily.countError > maxRetryGetTask ||
80 | info.basic.countError > maxRetryGetTask
81 | ) {
82 | user.log.logError(`Lấy danh sách nhiệm vụ thất bại`);
83 | return [];
84 | }
85 |
86 | let tasks = [...info.daily.tasks, ...info.basic.tasks];
87 | tasks = tasks.filter(
88 | (task) => !task.is_completed && !skipTasks.includes(task.id)
89 | );
90 | return tasks;
91 | }
92 |
93 | async claimTask(user, task) {
94 | let body = { task_id: task.id };
95 | const taskAnswer = user.database?.tasks?.find((t) => task.id === t.id);
96 | if (taskAnswer) {
97 | body = { ...body, ...taskAnswer.answer };
98 | }
99 | try {
100 | await delayHelper.delay(1);
101 | const { data } = await user.http.post("tasks/", body);
102 | if (data?.is_completed) {
103 | user.log.log(
104 | `Làm nhiệm vụ ${colors.blue(
105 | task?.title
106 | )} thành công, phần thưởng: ${colors.yellow(
107 | task?.award + user.currency
108 | )}`
109 | );
110 | return true;
111 | } else {
112 | if (user?.database?.skipErrorTasks.includes(task.id)) return;
113 | user.log.logError(
114 | `Làm thưởng nhiệm vụ ${colors.blue(task?.title)} - ${colors.gray(
115 | `[${task.id}]`
116 | )} thất bại do không thể hoàn thành tự động`
117 | );
118 | return false;
119 | }
120 | } catch (error) {
121 | if (error.response?.status === 520) {
122 | return;
123 | }
124 |
125 | user.log.logError(
126 | `Làm nhiệm vụ ${colors.blue(task?.title)} - ${colors.gray(
127 | `[${task.id}]`
128 | )} thất bại: ${error.response?.status} - ${
129 | error.response?.data?.detail
130 | }`
131 | );
132 | return -1;
133 | }
134 | }
135 |
136 | async handleTask(user) {
137 | const tasks = await this.getTasks(user);
138 | let errorTasks = [];
139 |
140 | if (!tasks.length) {
141 | user.log.log(colors.magenta("Đã làm hết nhiệm vụ"));
142 | return;
143 | }
144 |
145 | if (tasks.length) {
146 | user.log.log(`Còn ${colors.blue(tasks.length)} nhiệm vụ chưa hoàn thành`);
147 | }
148 |
149 | for (const task of tasks) {
150 | const status = await this.claimTask(user, task);
151 | if (status === -1) {
152 | errorTasks.push(task);
153 | }
154 | }
155 |
156 | const maxRetry = 10;
157 | let countRetry = 0;
158 | while (errorTasks.length && countRetry <= maxRetry) {
159 | user.log.log(colors.magenta("Làm lại các nhiệm vụ bị lỗi"));
160 | const tempError = [];
161 | for (const task of errorTasks) {
162 | const status = await this.claimTask(user, task);
163 | if (status === -1) {
164 | tempError.push(task);
165 | }
166 | }
167 | countRetry++;
168 | errorTasks = tempError;
169 | }
170 |
171 | user.log.log(colors.magenta("Đã làm xong các nhiệm vụ"));
172 | }
173 | }
174 |
175 | const taskService = new TaskService();
176 | export default taskService;
177 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Tool Auto Major NodeJS by ZuyDD
4 |
5 | **Tool phát triển và chia sẻ miễn phí bởi ZuyDD**
6 |
7 |
8 |
9 |
10 | > [!WARNING]
11 | > Mọi hành vi buôn bán tool dưới bất cứ hình thức nào đều không được cho phép!
12 |
13 | ## 🛠️ Hướng dẫn cài đặt
14 |
15 | > Yêu cầu đã cài đặt NodeJS
16 |
17 | - Bước 1: Tải về phiên bản mới nhất của tool [tại đây ⬇️](https://github.com/zuydd/major/archive/refs/heads/main.zip)
18 | - Bước 2: Giải nén tool
19 | - Bước 3: Tại thư mục tool vừa giải nén (thư mục có chứa file package.json), chạy lệnh `npm install` để cài đặt các thư viện bổ trợ
20 |
21 | ## 💾 Cách thêm dữ liệu tài khoản
22 |
23 | > Tool hỗ trợ cả `user` và `query_id` (khuyến khích dùng query_id)
24 |
25 | > Tất cả dữ liệu mà bạn cần nhập đều nằm ở các file trong thư mục 📁 `src / data`
26 |
27 | - [users.txt](src/data/users.txt) : chứa danh sách `user` hoặc `query_id` của các tài khoản, mỗi dòng ứng với một tài khoản
28 | - [proxy.txt](src/data/proxy.txt) : chứa danh sách proxy, proxy ở mỗi dòng sẽ ứng với tài khoản ở dòng đó trong file users.txt phía trên, để trống nếu không dùng proxy.
29 | - [token.json](src/data/token.json) : chứa danh sách token được tạo ra từ `user` hoặc `query_id`. Token sẽ được tự động sinh ra khi bạn chạy tool. (Không cần quan tâm đến file này)
30 |
31 | > Định dạng proxy: http://user:pass@ip:port
32 |
33 | ## >\_ Các lệnh và chức năng tương ứng
34 |
35 | | Lệnh | Chức năng |
36 | | --------------- | ----------------------------------------------------------------------------------- |
37 | | `npm run start` | Dùng để làm nhiệm vụ, điểm danh, chơi game,.... tóm lại game có gì là nó làm cái đó |
38 |
39 | ## 🕹️ Các tính năng có trong tool
40 |
41 | - tự động điểm danh hàng ngày
42 | - tự động làm nhiệm vụ
43 | - tự động chơi game khi tới giờ (các game có thể chơi: Hold Coin, Roulette, Swipe Coin, Durov)
44 | - nhận diện proxy tự động, tự động kết nối lại proxy khi bị lỗi. ae ai chạy proxy thì thêm vào file proxy.txt ở dòng ứng với dòng chứa acc muốn chạy proxy đó, acc nào không muốn chạy proxy thì để trống hoặc gõ skip vào
45 | - đa luồng chạy bao nhiêu acc cũng được, không bị block lẫn nhau, lặp lại khi tới thời gian chơi game
46 | - hiển thị đếm ngược tới lần chạy tiếp theo, có thể tìm biến `IS_SHOW_COUNTDOWN = true` đổi thành `false` để tắt cho đỡ lag
47 |
48 | > [!WARNING]
49 | >
50 | > - Game Durov có combo trả lời đổi mỗi ngày nên tool sẽ bắt đầu chạy task này từ 9h sáng thay vì 7h sáng để có đủ thời gian cập nhật combo mới
51 | > - Có nhiều nhiệm vụ yêu cầu phải làm thủ công, không claim láo được nên đừng thắc mắc sao còn nhiều nhiệm vụ chưa làm thế.
52 | > - Nếu gặp lỗi 5xx khi chơi game thì kệ nó, điểm vẫn được tính, do server lỏ thôi
53 | > - Vì server nó hay lỗi vặt nên đừng bất ngờ khi thấy các lỗi 5xx nhé
54 |
55 | ## ♾ Cài đặt đa luồng
56 |
57 | - Mặc định tool sẽ chạy đa luồng ứng với số tài khoản bạn nhập vào, không cần cài đặt thêm gì cả.
58 | - Mặc định ở vòng lặp đầu tiên mỗi tài khoản (luồng) sẽ chạy cách nhau 30s để tránh spam request, có thể tìm biến `DELAY_ACC = 30` trong file [index.js](src/run/index.js) để điều chỉnh cho phù hợp
59 |
60 | ## ❌ Chế độ thử lại khi lỗi
61 |
62 | - Đỗi với lỗi kết nối proxy, hệ thống sẽ cố thử lại sau mỗi 30s, bạn có thể cài đặt giới hạn số lần thử lại bằng cách tìm biến `MAX_RETRY_PROXY = 20` trong file [index.js](src/run/index.js) để điều chỉnh cho phù hợp (mặc định là 20). Khi quá số lần thử kết nối lại hệ thống sẽ dừng auto tài khoản đó và nghi nhận lỗi vào file [log.error.txt](src/data/log.error.txt)
63 | - Đỗi với lỗi đăng nhập thất bại, hệ thống sẽ cố thử lại sau mỗi 60s, bạn có thể cài đặt giới hạn số lần thử lại bằng cách tìm biến `MAX_RETRY_LOGIN = 20` trong file [index.js](src/run/index.js) để điều chỉnh cho phù hợp (mặc định là 20). Khi quá số lần thử đăng nhập lại hệ thống sẽ dừng auto tài khoản đó và nghi nhận lỗi vào file [log.error.txt](src/data/log.error.txt)
64 |
65 | ## 🔄 Lịch sử cập nhật
66 |
67 | > Khi cập nhật phiên bản mới chỉ cần copy thư mục 📁 [data](src/data) của bản cũ ghi đè lại ở bản mới là có thể chạy được mà không cần lấy lại data
68 |
69 | > Phiên bản mới nhất: `v0.0.6`
70 |
71 |
72 | v0.0.6 - 📅 30/09/2024
73 |
74 | - Thêm thử đăng nhập lại khi lỗi
75 | - Thêm delay 1s cho mỗi request, bạn sẽ thấy tool chạy chậm hơn nhưng nó đảm bảo tool ổn định hơn
76 |
77 |
78 | v0.0.5 - 📅 29/09/2024
79 |
80 | - Fix lỗi đăng nhập
81 |
82 |
83 | v0.0.4 - 📅 14/09/2024
84 |
85 | - Thêm làm task xem video youtube nhập code
86 | - Thêm thông báo từ hệ thống và kiểm tra version
87 |
88 |
89 | v0.0.3 - 📅 13/09/2024
90 |
91 | - Sửa lỗi spam request server github
92 |
93 |
94 | v0.0.2 - 📅 12/09/2024
95 |
96 | - Thêm tự động lấy dữ liệu từ server mỗi 20-40 phút mà không cần chạy lại tool
97 |
98 |
99 | v0.0.1 - 📅 12/09/2024
100 |
101 | - Chia sẽ tool đến cộng đồng
102 |
103 |
104 | ## 🎁 Donate
105 |
106 | Chúng tôi rất vui được chia sẻ các mã script và tài nguyên mã nguồn miễn phí đến cộng đồng làm airdrop. Nếu bạn thấy các công cụ và tài liệu của chúng tôi hữu ích và muốn ủng hộ chúng tôi tiếp tục phát triển và duy trì các dự án này, bạn có thể đóng góp hỗ trợ qua hình thức donate.
107 |
108 | Mỗi đóng góp của bạn sẽ giúp chúng tôi duy trì chất lượng dịch vụ và tiếp tục cung cấp những tài nguyên giá trị cho cộng đồng làm airdrop. Chúng tôi chân thành cảm ơn sự hỗ trợ và ủng hộ của bạn!
109 |
110 | Mãi iu 😘😘😘
111 |
112 |
113 |

114 |

115 |
116 |
--------------------------------------------------------------------------------
/src/run/index.js:
--------------------------------------------------------------------------------
1 | import colors from "colors";
2 | import dayjs from "dayjs";
3 | import datetimeHelper from "../helpers/datetime.js";
4 | import delayHelper from "../helpers/delay.js";
5 | import fileHelper from "../helpers/file.js";
6 | import generatorHelper from "../helpers/generator.js";
7 | import authService from "../services/auth.js";
8 | import dailyService from "../services/daily.js";
9 | import gameService from "../services/game.js";
10 | import server from "../services/server.js";
11 | import taskService from "../services/task.js";
12 | import userService from "../services/user.js";
13 |
14 | const VERSION = "v0.0.6";
15 | // Điều chỉnh khoảng cách thời gian chạy vòng lặp đầu tiên giữa các luồng tránh bị spam request (tính bằng giây)
16 | const DELAY_ACC = 30;
17 | // Đặt số lần thử kết nối lại tối đa khi proxy lỗi, nếu thử lại quá số lần cài đặt sẽ dừng chạy tài khoản đó và ghi lỗi vào file log
18 | const MAX_RETRY_PROXY = 20;
19 | // Đặt số lần thử đăng nhập tối đa khi đăng nhập lỗi, nếu thử lại quá số lần cài đặt sẽ dừng chạy tài khoản đó và ghi lỗi vào file log
20 | const MAX_RETRY_LOGIN = 20;
21 | // Cài đặt đếm ngược đến lần chạy tiếp theo
22 | const IS_SHOW_COUNTDOWN = true;
23 | const countdownList = [];
24 |
25 | let database = {};
26 | setInterval(async () => {
27 | const data = await server.getData();
28 | if (data) {
29 | database = data;
30 | server.checkVersion(VERSION, data);
31 | }
32 | }, generatorHelper.randomInt(20, 40) * 60 * 1000);
33 |
34 | const run = async (user, index) => {
35 | let countRetryProxy = 0;
36 | let countRetryLogin = 0;
37 | await delayHelper.delay((user.index - 1) * DELAY_ACC);
38 | while (true) {
39 | // Lấy lại dữ liệu từ server zuydd
40 | if (database?.ref) {
41 | user.database = database;
42 | }
43 |
44 | countdownList[index].running = true;
45 | // Kiểm tra kết nối proxy
46 | let isProxyConnected = false;
47 | while (!isProxyConnected) {
48 | const ip = await user.http.checkProxyIP();
49 | if (ip === -1) {
50 | user.log.logError(
51 | "Proxy lỗi, kiểm tra lại kết nối proxy, sẽ thử kết nối lại sau 30s"
52 | );
53 | countRetryProxy++;
54 | if (countRetryProxy >= MAX_RETRY_PROXY) {
55 | break;
56 | } else {
57 | await delayHelper.delay(30);
58 | }
59 | } else {
60 | countRetryProxy = 0;
61 | isProxyConnected = true;
62 | }
63 | }
64 | try {
65 | if (countRetryProxy >= MAX_RETRY_PROXY) {
66 | const dataLog = `[No ${user.index} _ ID: ${
67 | user.info.id
68 | } _ Time: ${dayjs().format(
69 | "YYYY-MM-DDTHH:mm:ssZ[Z]"
70 | )}] Lỗi kết nối proxy - ${user.proxy}`;
71 | fileHelper.writeLog("log.error.txt", dataLog);
72 | break;
73 | }
74 |
75 | if (countRetryLogin >= MAX_RETRY_LOGIN) {
76 | const dataLog = `[No ${user.index} _ ID: ${
77 | user.info.id
78 | } _ Time: ${dayjs().format(
79 | "YYYY-MM-DDTHH:mm:ssZ[Z]"
80 | )}] Lỗi đăng nhập thất bại quá ${MAX_RETRY_LOGIN} lần`;
81 | fileHelper.writeLog("log.error.txt", dataLog);
82 | break;
83 | }
84 | } catch (error) {
85 | user.log.logError("Ghi lỗi thất bại");
86 | }
87 |
88 | // Đăng nhập tài khoản
89 | const login = await authService.handleLogin(user);
90 | if (!login.status) {
91 | countRetryLogin++;
92 | await delayHelper.delay(60);
93 | continue;
94 | } else {
95 | countRetryLogin = 0;
96 | }
97 |
98 | await dailyService.checkin(user);
99 | await taskService.handleTask(user);
100 | const awaitTime = await gameService.handleGame(user);
101 | user.log.log(
102 | colors.magenta(
103 | `Đã hoàn thành hết công việc, chạy lại sau: ${colors.blue(
104 | `${awaitTime + 1} phút`
105 | )}`
106 | )
107 | );
108 | countdownList[index].time = (awaitTime + 1) * 60;
109 | countdownList[index].created = dayjs().unix();
110 | countdownList[index].running = false;
111 | await delayHelper.delay((awaitTime + 1) * 60);
112 | }
113 | };
114 |
115 | console.log(
116 | colors.yellow.bold(
117 | `============= Tool phát triển và chia sẻ miễn phí bởi ZuyDD =============`
118 | )
119 | );
120 | console.log(
121 | "Mọi hành vi buôn bán tool dưới bất cứ hình thức nào đều không được cho phép!"
122 | );
123 | console.log(
124 | `Telegram: ${colors.green(
125 | "https://t.me/zuydd"
126 | )} ___ Facebook: ${colors.blue("https://www.facebook.com/zuy.dd")}`
127 | );
128 | console.log(
129 | `🚀 Cập nhật các tool mới nhất tại: 👉 ${colors.gray(
130 | "https://github.com/zuydd"
131 | )} 👈`
132 | );
133 | console.log("");
134 | console.log("");
135 |
136 | server.checkVersion(VERSION);
137 | server.showNoti();
138 | console.log("");
139 | const users = await userService.loadUser();
140 |
141 | for (const [index, user] of users.entries()) {
142 | countdownList.push({
143 | running: true,
144 | time: 480 * 60,
145 | created: dayjs().unix(),
146 | });
147 | run(user, index);
148 | }
149 |
150 | if (IS_SHOW_COUNTDOWN && users.length) {
151 | let isLog = false;
152 | setInterval(() => {
153 | const isPauseAll = !countdownList.some((item) => item.running === true);
154 |
155 | if (isPauseAll) {
156 | if (!isLog) {
157 | console.log(
158 | "========================================================================================="
159 | );
160 | isLog = true;
161 | }
162 | const minTimeCountdown = countdownList.reduce((minItem, currentItem) => {
163 | // bù trừ chênh lệch
164 | const currentOffset = dayjs().unix() - currentItem.created;
165 | const minOffset = dayjs().unix() - minItem.created;
166 | return currentItem.time - currentOffset < minItem.time - minOffset
167 | ? currentItem
168 | : minItem;
169 | }, countdownList[0]);
170 | const offset = dayjs().unix() - minTimeCountdown.created;
171 | const countdown = minTimeCountdown.time - offset;
172 | process.stdout.write("\x1b[K");
173 | process.stdout.write(
174 | colors.white(
175 | `[${dayjs().format(
176 | "DD-MM-YYYY HH:mm:ss"
177 | )}] Đã chạy hết các luồng, cần chờ: ${colors.blue(
178 | datetimeHelper.formatTime(countdown)
179 | )} \r`
180 | )
181 | );
182 | } else {
183 | isLog = false;
184 | }
185 | }, 1000);
186 |
187 | process.on("SIGINT", () => {
188 | console.log("");
189 | process.stdout.write("\x1b[K"); // Xóa dòng hiện tại từ con trỏ đến cuối dòng
190 | process.exit(); // Thoát khỏi quá trình
191 | });
192 | }
193 |
194 | setInterval(() => {}, 1000); // Để script không kết thúc ngay
195 |
--------------------------------------------------------------------------------
/src/services/game.js:
--------------------------------------------------------------------------------
1 | import colors from "colors";
2 | import dayjs from "dayjs";
3 | import utc from "dayjs/plugin/utc.js";
4 | import delayHelper from "../helpers/delay.js";
5 | import generatorHelper from "../helpers/generator.js";
6 | dayjs.extend(utc);
7 |
8 | class GameService {
9 | constructor() {}
10 |
11 | async startGameHoldCoin(user) {
12 | try {
13 | const { data } = await user.http.get("bonuses/coins/");
14 | if (data?.success) {
15 | user.log.log(
16 | `Bắt đầu chơi game Hold Coin, nhận thưởng sau: ${colors.blue(
17 | "60 giây"
18 | )}`
19 | );
20 | return -1;
21 | } else {
22 | return 10;
23 | }
24 | } catch (error) {
25 | if (error.response?.status === 400 && error.response?.data?.detail) {
26 | const until =
27 | Math.floor(error.response?.data?.detail.blocked_until) * 1000;
28 |
29 | const diffTime = dayjs(until).diff(dayjs(), "minutes");
30 | user.log.log(
31 | `Đã hết lượt chơi game Hold Coin, chờ lượt mới sau: ${colors.blue(
32 | diffTime + ` phút`
33 | )}`
34 | );
35 | return diffTime;
36 | } else {
37 | user.log.logError(
38 | `Chơi game Hold Coin thất bại: ${error.response?.status} - ${error.response?.data?.detail}`
39 | );
40 | return error.response?.status === 520 ? -1 : 10;
41 | }
42 | }
43 | }
44 |
45 | async claimGameHoldCoin(user) {
46 | const coins = generatorHelper.randomInt(850, 900);
47 | const body = { coins };
48 | try {
49 | const { data } = await user.http.post("bonuses/coins/", body);
50 | if (data.success) {
51 | user.log.log(
52 | `Chơi game Hold Coin thành công, phần thưởng: ${colors.yellow(
53 | coins + user.currency
54 | )}, chờ lượt mới sau ${colors.blue(`480 phút`)}`
55 | );
56 | return true;
57 | } else {
58 | throw new Error(`Chơi game Roulette thất bại`);
59 | }
60 | } catch (error) {
61 | if (error.response?.status === 400 && error.response?.data?.detail) {
62 | const until =
63 | Math.floor(error.response?.data?.detail.blocked_until) * 1000;
64 |
65 | const diffTime = dayjs(until).diff(dayjs(), "minutes");
66 | user.log.log(
67 | `Đã hết lượt chơi game Hold Coin, chờ lượt mới sau: ${colors.blue(
68 | diffTime + ` phút`
69 | )}`
70 | );
71 | return diffTime;
72 | } else {
73 | user.log.logError(
74 | `Nhận thưởng chơi game Roulette thất bại: ${error.response?.status} - ${error.response?.data?.detail}`
75 | );
76 | return false;
77 | }
78 | }
79 | }
80 |
81 | async startGameRoulette(user) {
82 | try {
83 | const { data } = await user.http.get("roulette/");
84 | if (data?.success) {
85 | user.log.log(
86 | `Bắt đầu chơi game Roulette, nhận thưởng sau: ${colors.blue(
87 | "5 giây"
88 | )}`
89 | );
90 | return -1;
91 | } else {
92 | return 10;
93 | }
94 | } catch (error) {
95 | if (error.response?.status === 400 && error.response?.data?.detail) {
96 | const until =
97 | Math.floor(error.response?.data?.detail.blocked_until) * 1000;
98 |
99 | const diffTime = dayjs(until).diff(dayjs(), "minutes");
100 | user.log.log(
101 | `Đã hết lượt chơi game Roulette, chờ lượt mới sau: ${colors.blue(
102 | diffTime + ` phút`
103 | )}`
104 | );
105 | return diffTime;
106 | } else {
107 | user.log.logError(
108 | `Chơi game Roulette thất bại: ${error.response?.status} - ${error.response?.data?.detail}`
109 | );
110 | return error.response?.status === 520 ? -1 : 10;
111 | }
112 | }
113 | }
114 |
115 | async claimGameRoulette(user) {
116 | try {
117 | const { data } = await user.http.post("roulette/", {});
118 | if (data?.rating_award) {
119 | user.log.log(
120 | `Chơi game Roulette thành công, phần thưởng: ${colors.yellow(
121 | data.rating_award + user.currency
122 | )}, chờ lượt mới sau ${colors.blue(`480 phút`)}`
123 | );
124 | return true;
125 | } else {
126 | throw new Error(`Chơi game Roulette thất bại`);
127 | }
128 | } catch (error) {
129 | if (error.response?.status === 400 && error.response?.data?.detail) {
130 | const until =
131 | Math.floor(error.response?.data?.detail.blocked_until) * 1000;
132 |
133 | const diffTime = dayjs(until).diff(dayjs(), "minutes");
134 | user.log.log(
135 | `Đã hết lượt chơi game Roulette, chờ lượt mới sau: ${colors.blue(
136 | diffTime + ` phút`
137 | )}`
138 | );
139 | return diffTime;
140 | } else {
141 | user.log.logError(
142 | `Nhận thưởng chơi game Roulette thất bại: ${error.response?.status} - ${error.response?.data?.detail}`
143 | );
144 | return false;
145 | }
146 | }
147 | }
148 |
149 | async startGameSwipeCoin(user) {
150 | try {
151 | const { data } = await user.http.get("swipe_coin/");
152 | if (data?.success) {
153 | user.log.log(
154 | `Bắt đầu chơi game Swipe Coin, nhận thưởng sau: ${colors.blue(
155 | "60 giây"
156 | )}`
157 | );
158 | return -1;
159 | } else {
160 | return 10;
161 | }
162 | } catch (error) {
163 | if (error.response?.status === 400 && error.response?.data?.detail) {
164 | const until =
165 | Math.floor(error.response?.data?.detail.blocked_until) * 1000;
166 |
167 | const diffTime = dayjs(until).diff(dayjs(), "minutes");
168 | user.log.log(
169 | `Đã hết lượt chơi game Swipe Coin, chờ lượt mới sau: ${colors.blue(
170 | diffTime + ` phút`
171 | )}`
172 | );
173 | return diffTime;
174 | } else {
175 | user.log.logError(
176 | `Chơi game Swipe Coin thất bại: ${error.response?.status} - ${error.response?.data?.detail}`
177 | );
178 | return error.response?.status === 520 ? -1 : 10;
179 | }
180 | }
181 | }
182 |
183 | async claimGameSwipeCoin(user) {
184 | const coins = generatorHelper.randomInt(2850, 2950);
185 | const body = { coins };
186 | try {
187 | const { data } = await user.http.post("swipe_coin/", body);
188 | if (data?.success) {
189 | user.log.log(
190 | `Chơi game Swipe Coin thành công, phần thưởng: ${colors.yellow(
191 | coins + user.currency
192 | )}, chờ lượt mới sau ${colors.blue(`480 phút`)}`
193 | );
194 | return true;
195 | } else {
196 | throw new Error(`Chơi game Swipe Coin thất bại`);
197 | }
198 | } catch (error) {
199 | if (error.response?.status === 400 && error.response?.data?.detail) {
200 | const until =
201 | Math.floor(error.response?.data?.detail.blocked_until) * 1000;
202 |
203 | const diffTime = dayjs(until).diff(dayjs(), "minutes");
204 | user.log.log(
205 | `Đã hết lượt chơi game Swipe Coin, chờ lượt mới sau: ${colors.blue(
206 | diffTime + ` phút`
207 | )}`
208 | );
209 | return diffTime;
210 | } else {
211 | user.log.logError(
212 | `Nhận thưởng chơi game Swipe Coin thất bại: ${error.response?.status} - ${error.response?.data?.detail}`
213 | );
214 | return false;
215 | }
216 | }
217 | }
218 |
219 | async startGameDurov(user) {
220 | try {
221 | const { data } = await user.http.get("durov/");
222 | if (data?.success) {
223 | user.log.log(
224 | `Bắt đầu chơi game Durov, nhận thưởng sau: ${colors.blue("5 giây")}`
225 | );
226 | return -1;
227 | } else {
228 | return 10;
229 | }
230 | } catch (error) {
231 | if (error.response?.status === 400 && error.response?.data?.detail) {
232 | const until =
233 | Math.floor(error.response?.data?.detail.blocked_until) * 1000;
234 |
235 | const diffTime = dayjs(until).add(2, "hour").diff(dayjs(), "minutes");
236 | user.log.log(
237 | `Đã hết lượt chơi game Durov, chờ lượt mới sau: ${colors.blue(
238 | diffTime + ` phút`
239 | )}`
240 | );
241 | return diffTime;
242 | } else {
243 | user.log.logError(
244 | `Chơi game Durov thất bại: ${error.response?.status} - ${error.response?.data?.detail}`
245 | );
246 | return error.response?.status === 520 ? -1 : 10;
247 | }
248 | }
249 | }
250 |
251 | async claimGameDurov(user) {
252 | const answer = user?.database?.durov.answer;
253 | const body = {
254 | choice_1: answer[0],
255 | choice_2: answer[1],
256 | choice_3: answer[2],
257 | choice_4: answer[3],
258 | };
259 |
260 | try {
261 | const { data } = await user.http.post("durov/", body);
262 | if (data?.correct) {
263 | const tomorrowMidnightUtc = dayjs
264 | .utc()
265 | .add(1, "day")
266 | .startOf("day")
267 | .add(2, "hour");
268 | const nowUtc = dayjs.utc();
269 | const minutesDifference = tomorrowMidnightUtc.diff(nowUtc, "minute");
270 | user.log.log(
271 | `Chơi game Durov thành công, phần thưởng: ${colors.yellow(
272 | "5000" + user.currency
273 | )}, chờ lượt mới sau ${colors.blue(`${minutesDifference} phút`)}`
274 | );
275 | return {
276 | status: true,
277 | diff: minutesDifference,
278 | };
279 | } else {
280 | throw new Error(`Chơi game Durov thất bại`);
281 | }
282 | } catch (error) {
283 | if (error.response?.status === 400 && error.response?.data?.detail) {
284 | const until =
285 | Math.floor(error.response?.data?.detail.blocked_until) * 1000;
286 |
287 | const diffTime = dayjs(until).add(2, "hour").diff(dayjs(), "minutes");
288 | user.log.log(
289 | `Đã hết lượt chơi game Durov, chờ lượt mới sau: ${colors.blue(
290 | diffTime + ` phút`
291 | )}`
292 | );
293 | return diffTime;
294 | } else {
295 | user.log.logError(
296 | `Nhận thưởng chơi game Durov thất bại: ${error.response?.status} - ${error.response?.data?.detail}`
297 | );
298 | return false;
299 | }
300 | }
301 | }
302 |
303 | async handleGame(user) {
304 | let countdown = 480;
305 |
306 | // Hold Coin
307 | const infoGameHoldCoin = await this.startGameHoldCoin(user);
308 | if (infoGameHoldCoin === -1) {
309 | await delayHelper.delay(65);
310 | const status = await this.claimGameHoldCoin(user);
311 | if (status) {
312 | if (countdown > 480) {
313 | countdown = 480;
314 | }
315 | } else {
316 | countdown = 10;
317 | }
318 | } else if (infoGameHoldCoin < countdown) {
319 | countdown = infoGameHoldCoin;
320 | }
321 |
322 | // Roulette
323 | const infoGameRoulette = await this.startGameRoulette(user);
324 | if (infoGameRoulette === -1) {
325 | await delayHelper.delay(5);
326 | const status = await this.claimGameRoulette(user);
327 | if (status) {
328 | if (countdown > 480) {
329 | countdown = 480;
330 | }
331 | } else {
332 | countdown = 10;
333 | }
334 | } else if (infoGameRoulette < countdown) {
335 | countdown = infoGameRoulette;
336 | }
337 |
338 | // Swipe Coin
339 | const infoGameSwipeCoin = await this.startGameSwipeCoin(user);
340 | if (infoGameSwipeCoin === -1) {
341 | await delayHelper.delay(65);
342 | const status = await this.claimGameSwipeCoin(user);
343 | if (status) {
344 | if (countdown > 480) {
345 | countdown = 480;
346 | }
347 | } else {
348 | countdown = 10;
349 | }
350 | } else if (infoGameSwipeCoin < countdown) {
351 | countdown = infoGameSwipeCoin;
352 | }
353 |
354 | // Durov
355 | const nowUtc = dayjs.utc();
356 | const dayUtc = nowUtc.format("DD-MM-YYYY");
357 |
358 | if (dayUtc === user?.database?.durov?.day) {
359 | const infoGameDurov = await this.startGameDurov(user);
360 | if (infoGameDurov === -1) {
361 | await delayHelper.delay(5);
362 | const infoClaim = await this.claimGameDurov(user);
363 | if (infoClaim?.status) {
364 | if (countdown > infoClaim.diff) {
365 | countdown = infoClaim.diff;
366 | }
367 | } else {
368 | countdown = 10;
369 | }
370 | } else if (infoGameDurov < countdown) {
371 | countdown = infoGameDurov;
372 | }
373 | } else if (20 < countdown) {
374 | user.log.log(
375 | colors.yellow(
376 | "Chưa có combo Durov, liên hệ chủ tool @zuydd để yêu cầu update"
377 | )
378 | );
379 | countdown = 20;
380 | }
381 | return countdown;
382 | }
383 | }
384 |
385 | const gameService = new GameService();
386 | export default gameService;
387 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@inquirer/checkbox@^2.5.0":
6 | version "2.5.0"
7 | resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-2.5.0.tgz#41c5c9dd332c0a8fa159be23982ce080d0b199d4"
8 | integrity sha512-sMgdETOfi2dUHT8r7TT1BTKOwNvdDGFDXYWtQ2J69SvlYNntk9I/gJe7r5yvMwwsuKnYbuRs3pNhx4tgNck5aA==
9 | dependencies:
10 | "@inquirer/core" "^9.1.0"
11 | "@inquirer/figures" "^1.0.5"
12 | "@inquirer/type" "^1.5.3"
13 | ansi-escapes "^4.3.2"
14 | yoctocolors-cjs "^2.1.2"
15 |
16 | "@inquirer/confirm@^3.2.0":
17 | version "3.2.0"
18 | resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-3.2.0.tgz#6af1284670ea7c7d95e3f1253684cfbd7228ad6a"
19 | integrity sha512-oOIwPs0Dvq5220Z8lGL/6LHRTEr9TgLHmiI99Rj1PJ1p1czTys+olrgBqZk4E2qC0YTzeHprxSQmoHioVdJ7Lw==
20 | dependencies:
21 | "@inquirer/core" "^9.1.0"
22 | "@inquirer/type" "^1.5.3"
23 |
24 | "@inquirer/core@^9.1.0":
25 | version "9.1.0"
26 | resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-9.1.0.tgz#158b82dc44564a1abd0ce14723d50c3efa0634a2"
27 | integrity sha512-RZVfH//2ytTjmaBIzeKT1zefcQZzuruwkpTwwbe/i2jTl4o9M+iML5ChULzz6iw1Ok8iUBBsRCjY2IEbD8Ft4w==
28 | dependencies:
29 | "@inquirer/figures" "^1.0.5"
30 | "@inquirer/type" "^1.5.3"
31 | "@types/mute-stream" "^0.0.4"
32 | "@types/node" "^22.5.2"
33 | "@types/wrap-ansi" "^3.0.0"
34 | ansi-escapes "^4.3.2"
35 | cli-spinners "^2.9.2"
36 | cli-width "^4.1.0"
37 | mute-stream "^1.0.0"
38 | signal-exit "^4.1.0"
39 | strip-ansi "^6.0.1"
40 | wrap-ansi "^6.2.0"
41 | yoctocolors-cjs "^2.1.2"
42 |
43 | "@inquirer/editor@^2.2.0":
44 | version "2.2.0"
45 | resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-2.2.0.tgz#a41eb7b151bd9a6bc3c0b69219d02d82547bc387"
46 | integrity sha512-9KHOpJ+dIL5SZli8lJ6xdaYLPPzB8xB9GZItg39MBybzhxA16vxmszmQFrRwbOA918WA2rvu8xhDEg/p6LXKbw==
47 | dependencies:
48 | "@inquirer/core" "^9.1.0"
49 | "@inquirer/type" "^1.5.3"
50 | external-editor "^3.1.0"
51 |
52 | "@inquirer/expand@^2.3.0":
53 | version "2.3.0"
54 | resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-2.3.0.tgz#afc44aee303315a85563e9d0275e658f0ee0e701"
55 | integrity sha512-qnJsUcOGCSG1e5DTOErmv2BPQqrtT6uzqn1vI/aYGiPKq+FgslGZmtdnXbhuI7IlT7OByDoEEqdnhUnVR2hhLw==
56 | dependencies:
57 | "@inquirer/core" "^9.1.0"
58 | "@inquirer/type" "^1.5.3"
59 | yoctocolors-cjs "^2.1.2"
60 |
61 | "@inquirer/figures@^1.0.5":
62 | version "1.0.5"
63 | resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.5.tgz#57f9a996d64d3e3345d2a3ca04d36912e94f8790"
64 | integrity sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==
65 |
66 | "@inquirer/input@^2.3.0":
67 | version "2.3.0"
68 | resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-2.3.0.tgz#9b99022f53780fecc842908f3f319b52a5a16865"
69 | integrity sha512-XfnpCStx2xgh1LIRqPXrTNEEByqQWoxsWYzNRSEUxJ5c6EQlhMogJ3vHKu8aXuTacebtaZzMAHwEL0kAflKOBw==
70 | dependencies:
71 | "@inquirer/core" "^9.1.0"
72 | "@inquirer/type" "^1.5.3"
73 |
74 | "@inquirer/number@^1.1.0":
75 | version "1.1.0"
76 | resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-1.1.0.tgz#4dac004021ea67c89552a261564f103a494cac96"
77 | integrity sha512-ilUnia/GZUtfSZy3YEErXLJ2Sljo/mf9fiKc08n18DdwdmDbOzRcTv65H1jjDvlsAuvdFXf4Sa/aL7iw/NanVA==
78 | dependencies:
79 | "@inquirer/core" "^9.1.0"
80 | "@inquirer/type" "^1.5.3"
81 |
82 | "@inquirer/password@^2.2.0":
83 | version "2.2.0"
84 | resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-2.2.0.tgz#0b6f26336c259c8a9e5f5a3f2e1a761564f764ba"
85 | integrity sha512-5otqIpgsPYIshqhgtEwSspBQE40etouR8VIxzpJkv9i0dVHIpyhiivbkH9/dGiMLdyamT54YRdGJLfl8TFnLHg==
86 | dependencies:
87 | "@inquirer/core" "^9.1.0"
88 | "@inquirer/type" "^1.5.3"
89 | ansi-escapes "^4.3.2"
90 |
91 | "@inquirer/prompts@^5.5.0":
92 | version "5.5.0"
93 | resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-5.5.0.tgz#5805aa15a13180017829aa31d071fd37a43b735d"
94 | integrity sha512-BHDeL0catgHdcHbSFFUddNzvx/imzJMft+tWDPwTm3hfu8/tApk1HrooNngB2Mb4qY+KaRWF+iZqoVUPeslEog==
95 | dependencies:
96 | "@inquirer/checkbox" "^2.5.0"
97 | "@inquirer/confirm" "^3.2.0"
98 | "@inquirer/editor" "^2.2.0"
99 | "@inquirer/expand" "^2.3.0"
100 | "@inquirer/input" "^2.3.0"
101 | "@inquirer/number" "^1.1.0"
102 | "@inquirer/password" "^2.2.0"
103 | "@inquirer/rawlist" "^2.3.0"
104 | "@inquirer/search" "^1.1.0"
105 | "@inquirer/select" "^2.5.0"
106 |
107 | "@inquirer/rawlist@^2.3.0":
108 | version "2.3.0"
109 | resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-2.3.0.tgz#6b2c0da39c1cd855af5608b2d627681cdac7277d"
110 | integrity sha512-zzfNuINhFF7OLAtGHfhwOW2TlYJyli7lOUoJUXw/uyklcwalV6WRXBXtFIicN8rTRK1XTiPWB4UY+YuW8dsnLQ==
111 | dependencies:
112 | "@inquirer/core" "^9.1.0"
113 | "@inquirer/type" "^1.5.3"
114 | yoctocolors-cjs "^2.1.2"
115 |
116 | "@inquirer/search@^1.1.0":
117 | version "1.1.0"
118 | resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-1.1.0.tgz#665928cac2326b9501ddafbb8606ce4823b3106b"
119 | integrity sha512-h+/5LSj51dx7hp5xOn4QFnUaKeARwUCLs6mIhtkJ0JYPBLmEYjdHSYh7I6GrLg9LwpJ3xeX0FZgAG1q0QdCpVQ==
120 | dependencies:
121 | "@inquirer/core" "^9.1.0"
122 | "@inquirer/figures" "^1.0.5"
123 | "@inquirer/type" "^1.5.3"
124 | yoctocolors-cjs "^2.1.2"
125 |
126 | "@inquirer/select@^2.5.0":
127 | version "2.5.0"
128 | resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-2.5.0.tgz#345c6908ecfaeef3d84ddd2f9feb2f487c558efb"
129 | integrity sha512-YmDobTItPP3WcEI86GvPo+T2sRHkxxOq/kXmsBjHS5BVXUgvgZ5AfJjkvQvZr03T81NnI3KrrRuMzeuYUQRFOA==
130 | dependencies:
131 | "@inquirer/core" "^9.1.0"
132 | "@inquirer/figures" "^1.0.5"
133 | "@inquirer/type" "^1.5.3"
134 | ansi-escapes "^4.3.2"
135 | yoctocolors-cjs "^2.1.2"
136 |
137 | "@inquirer/type@^1.5.3":
138 | version "1.5.3"
139 | resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.5.3.tgz#220ae9f3d5ae17dd3b2ce5ffd6b48c4a30c73181"
140 | integrity sha512-xUQ14WQGR/HK5ei+2CvgcwoH9fQ4PgPGmVFSN0pc1+fVyDL3MREhyAY7nxEErSu6CkllBM3D7e3e+kOvtu+eIg==
141 | dependencies:
142 | mute-stream "^1.0.0"
143 |
144 | "@types/mute-stream@^0.0.4":
145 | version "0.0.4"
146 | resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478"
147 | integrity sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==
148 | dependencies:
149 | "@types/node" "*"
150 |
151 | "@types/node@*", "@types/node@^22.5.2":
152 | version "22.5.4"
153 | resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.4.tgz#83f7d1f65bc2ed223bdbf57c7884f1d5a4fa84e8"
154 | integrity sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==
155 | dependencies:
156 | undici-types "~6.19.2"
157 |
158 | "@types/wrap-ansi@^3.0.0":
159 | version "3.0.0"
160 | resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd"
161 | integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==
162 |
163 | agent-base@^7.0.2:
164 | version "7.1.1"
165 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317"
166 | integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==
167 | dependencies:
168 | debug "^4.3.4"
169 |
170 | ansi-escapes@^4.3.2:
171 | version "4.3.2"
172 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
173 | integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
174 | dependencies:
175 | type-fest "^0.21.3"
176 |
177 | ansi-regex@^5.0.1:
178 | version "5.0.1"
179 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
180 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
181 |
182 | ansi-styles@^4.0.0:
183 | version "4.3.0"
184 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
185 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
186 | dependencies:
187 | color-convert "^2.0.1"
188 |
189 | asynckit@^0.4.0:
190 | version "0.4.0"
191 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
192 | integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
193 |
194 | axios@^1.7.2:
195 | version "1.7.7"
196 | resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f"
197 | integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==
198 | dependencies:
199 | follow-redirects "^1.15.6"
200 | form-data "^4.0.0"
201 | proxy-from-env "^1.1.0"
202 |
203 | chardet@^0.7.0:
204 | version "0.7.0"
205 | resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
206 | integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
207 |
208 | cli-spinners@^2.9.2:
209 | version "2.9.2"
210 | resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41"
211 | integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==
212 |
213 | cli-width@^4.1.0:
214 | version "4.1.0"
215 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5"
216 | integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==
217 |
218 | cliui@^8.0.1:
219 | version "8.0.1"
220 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
221 | integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
222 | dependencies:
223 | string-width "^4.2.0"
224 | strip-ansi "^6.0.1"
225 | wrap-ansi "^7.0.0"
226 |
227 | color-convert@^2.0.1:
228 | version "2.0.1"
229 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
230 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
231 | dependencies:
232 | color-name "~1.1.4"
233 |
234 | color-name@~1.1.4:
235 | version "1.1.4"
236 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
237 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
238 |
239 | colors@^1.4.0:
240 | version "1.4.0"
241 | resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
242 | integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
243 |
244 | combined-stream@^1.0.8:
245 | version "1.0.8"
246 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
247 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
248 | dependencies:
249 | delayed-stream "~1.0.0"
250 |
251 | dayjs@^1.11.12:
252 | version "1.11.13"
253 | resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
254 | integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
255 |
256 | debug@4, debug@^4.3.4:
257 | version "4.3.7"
258 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
259 | integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
260 | dependencies:
261 | ms "^2.1.3"
262 |
263 | delayed-stream@~1.0.0:
264 | version "1.0.0"
265 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
266 | integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
267 |
268 | emoji-regex@^8.0.0:
269 | version "8.0.0"
270 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
271 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
272 |
273 | escalade@^3.1.1:
274 | version "3.2.0"
275 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
276 | integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
277 |
278 | external-editor@^3.1.0:
279 | version "3.1.0"
280 | resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
281 | integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
282 | dependencies:
283 | chardet "^0.7.0"
284 | iconv-lite "^0.4.24"
285 | tmp "^0.0.33"
286 |
287 | follow-redirects@^1.15.6:
288 | version "1.15.9"
289 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
290 | integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
291 |
292 | form-data@^4.0.0:
293 | version "4.0.0"
294 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
295 | integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
296 | dependencies:
297 | asynckit "^0.4.0"
298 | combined-stream "^1.0.8"
299 | mime-types "^2.1.12"
300 |
301 | get-caller-file@^2.0.5:
302 | version "2.0.5"
303 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
304 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
305 |
306 | he@^1.2.0:
307 | version "1.2.0"
308 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
309 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
310 |
311 | https-proxy-agent@^7.0.5:
312 | version "7.0.5"
313 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2"
314 | integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==
315 | dependencies:
316 | agent-base "^7.0.2"
317 | debug "4"
318 |
319 | iconv-lite@^0.4.24:
320 | version "0.4.24"
321 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
322 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
323 | dependencies:
324 | safer-buffer ">= 2.1.2 < 3"
325 |
326 | inquirer@^10.1.8:
327 | version "10.2.2"
328 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-10.2.2.tgz#36b866443a9fb2747151766c01ef9c8ba2d585eb"
329 | integrity sha512-tyao/4Vo36XnUItZ7DnUXX4f1jVao2mSrleV/5IPtW/XAEA26hRVsbc68nuTEKWcr5vMP/1mVoT2O7u8H4v1Vg==
330 | dependencies:
331 | "@inquirer/core" "^9.1.0"
332 | "@inquirer/prompts" "^5.5.0"
333 | "@inquirer/type" "^1.5.3"
334 | "@types/mute-stream" "^0.0.4"
335 | ansi-escapes "^4.3.2"
336 | mute-stream "^1.0.0"
337 | run-async "^3.0.0"
338 | rxjs "^7.8.1"
339 |
340 | is-fullwidth-code-point@^3.0.0:
341 | version "3.0.0"
342 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
343 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
344 |
345 | mime-db@1.52.0:
346 | version "1.52.0"
347 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
348 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
349 |
350 | mime-types@^2.1.12:
351 | version "2.1.35"
352 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
353 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
354 | dependencies:
355 | mime-db "1.52.0"
356 |
357 | ms@^2.1.3:
358 | version "2.1.3"
359 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
360 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
361 |
362 | mute-stream@^1.0.0:
363 | version "1.0.0"
364 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e"
365 | integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==
366 |
367 | os-tmpdir@~1.0.2:
368 | version "1.0.2"
369 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
370 | integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
371 |
372 | proxy-from-env@^1.1.0:
373 | version "1.1.0"
374 | resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
375 | integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
376 |
377 | require-directory@^2.1.1:
378 | version "2.1.1"
379 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
380 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
381 |
382 | run-async@^3.0.0:
383 | version "3.0.0"
384 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-3.0.0.tgz#42a432f6d76c689522058984384df28be379daad"
385 | integrity sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==
386 |
387 | rxjs@^7.8.1:
388 | version "7.8.1"
389 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543"
390 | integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==
391 | dependencies:
392 | tslib "^2.1.0"
393 |
394 | "safer-buffer@>= 2.1.2 < 3":
395 | version "2.1.2"
396 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
397 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
398 |
399 | signal-exit@^4.1.0:
400 | version "4.1.0"
401 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
402 | integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
403 |
404 | string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
405 | version "4.2.3"
406 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
407 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
408 | dependencies:
409 | emoji-regex "^8.0.0"
410 | is-fullwidth-code-point "^3.0.0"
411 | strip-ansi "^6.0.1"
412 |
413 | strip-ansi@^6.0.0, strip-ansi@^6.0.1:
414 | version "6.0.1"
415 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
416 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
417 | dependencies:
418 | ansi-regex "^5.0.1"
419 |
420 | tmp@^0.0.33:
421 | version "0.0.33"
422 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
423 | integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
424 | dependencies:
425 | os-tmpdir "~1.0.2"
426 |
427 | tslib@^2.1.0:
428 | version "2.7.0"
429 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01"
430 | integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==
431 |
432 | type-fest@^0.21.3:
433 | version "0.21.3"
434 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
435 | integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
436 |
437 | undici-types@~6.19.2:
438 | version "6.19.8"
439 | resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
440 | integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
441 |
442 | wrap-ansi@^6.2.0:
443 | version "6.2.0"
444 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
445 | integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
446 | dependencies:
447 | ansi-styles "^4.0.0"
448 | string-width "^4.1.0"
449 | strip-ansi "^6.0.0"
450 |
451 | wrap-ansi@^7.0.0:
452 | version "7.0.0"
453 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
454 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
455 | dependencies:
456 | ansi-styles "^4.0.0"
457 | string-width "^4.1.0"
458 | strip-ansi "^6.0.0"
459 |
460 | ws@^8.18.0:
461 | version "8.18.0"
462 | resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
463 | integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
464 |
465 | y18n@^5.0.5:
466 | version "5.0.8"
467 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
468 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
469 |
470 | yargs-parser@^21.1.1:
471 | version "21.1.1"
472 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
473 | integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
474 |
475 | yargs@^17.7.2:
476 | version "17.7.2"
477 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
478 | integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
479 | dependencies:
480 | cliui "^8.0.1"
481 | escalade "^3.1.1"
482 | get-caller-file "^2.0.5"
483 | require-directory "^2.1.1"
484 | string-width "^4.2.3"
485 | y18n "^5.0.5"
486 | yargs-parser "^21.1.1"
487 |
488 | yoctocolors-cjs@^2.1.2:
489 | version "2.1.2"
490 | resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242"
491 | integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==
492 |
--------------------------------------------------------------------------------