├── src ├── data │ ├── key.txt │ ├── proxy.txt │ ├── users.txt │ ├── log.error.txt │ ├── device.txt │ ├── token.json │ └── phone.json ├── helpers │ ├── game2.wasm │ ├── delay.js │ ├── log.js │ ├── token.js │ ├── datetime.js │ ├── generator.js │ ├── file.js │ └── payload-blum.js ├── services │ ├── server.js │ ├── device.js │ ├── invite.js │ ├── daily.js │ ├── fake.js │ ├── farming.js │ ├── user.js │ ├── tribe.js │ ├── key.js │ ├── http.js │ ├── auth.js │ ├── game.js │ └── task.js ├── lang │ ├── zh.json │ ├── en.json │ ├── vi.json │ ├── id.json │ └── ru.json └── run │ └── index.js ├── package.json ├── README.md └── yarn.lock /src/data/key.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/data/proxy.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/data/users.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/data/log.error.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/data/device.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/data/token.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /src/helpers/game2.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/candyburst/blum/HEAD/src/helpers/game2.wasm -------------------------------------------------------------------------------- /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_blum", 3 | "version": "0.2.9", 4 | "description": "Tool tự động làm airdrop Blum", 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 | "crypto": "^1.0.1", 18 | "dayjs": "^1.11.12", 19 | "fingerprintjs2": "^2.1.4", 20 | "he": "^1.2.0", 21 | "https-proxy-agent": "^7.0.5", 22 | "inquirer": "^10.1.8", 23 | "ws": "^8.18.0", 24 | "yargs": "^17.7.2" 25 | }, 26 | "devDependencies": {} 27 | } 28 | -------------------------------------------------------------------------------- /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/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(lang) { 8 | try { 9 | const endpointDatabase = 10 | "https://raw.githubusercontent.com/candyburst/database/refs/heads/main/blum.json"; 11 | const { data } = await axios.get(endpointDatabase); 12 | return data; 13 | } catch (error) { 14 | console.log(colors.red(lang?.server?.get_json_github_error)); 15 | return null; 16 | } 17 | } 18 | 19 | async showNoti(lang) { 20 | const database = await this.getData(); 21 | if (database && database.noti) { 22 | console.log(colors.blue("📢 " + lang?.server?.noti)); 23 | console.log(database.noti); 24 | console.log(""); 25 | } 26 | } 27 | 28 | async checkVersion(curentVersion, lang, database = null) { 29 | if (!database) { 30 | database = await this.getData(lang); 31 | } 32 | 33 | if (database && curentVersion !== database.ver) { 34 | console.log( 35 | colors.yellow( 36 | `🚀 ${lang?.server?.noti_new_version} ${colors.blue(database.ver)}, ${ 37 | lang?.server?.download_now 38 | } 👉 ${colors.blue("https://github.com/zuydd/blum")}` 39 | ) 40 | ); 41 | console.log(""); 42 | } 43 | } 44 | } 45 | 46 | const server = new Server(); 47 | export default server; 48 | -------------------------------------------------------------------------------- /src/services/device.js: -------------------------------------------------------------------------------- 1 | class DeviceService { 2 | constructor() {} 3 | 4 | initDataDevice(device) { 5 | const arrDevice = device.split("|"); 6 | const deviceName = arrDevice[1]; 7 | const resolution = arrDevice[2]; 8 | const version = arrDevice[3]; 9 | const versionDot = version.replaceAll("_", "."); 10 | const canvas_code = arrDevice[4]; 11 | const audio = arrDevice[5]; 12 | 13 | const deviceInfoWithoutFingerprint = { 14 | screen_resolution: resolution, 15 | available_screen_resolution: resolution, 16 | system_version: `iOS ${versionDot}`, 17 | brand_model: "mobile Apple iPhone ", 18 | system_lang: "vi-VN", 19 | timezone: "GMT+07:00", 20 | timezoneOffset: -420, 21 | user_agent: `Mozilla/5.0 (iPhone; CPU iPhone OS ${version} like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148`, 22 | list_plugin: 23 | "PDF Viewer,Chrome PDF Viewer,Chromium PDF Viewer,Microsoft Edge PDF Viewer,WebKit built-in PDF", 24 | canvas_code, 25 | webgl_vendor: "Apple Inc.", 26 | webgl_renderer: "Apple GPU", 27 | audio, 28 | platform: "iPhone", 29 | web_timezone: "Asia/Saigon", 30 | device_name: "WebKit V605.1.15 (iOS)", 31 | device_id: "", 32 | related_device_ids: "", 33 | }; 34 | 35 | return { 36 | userAgent: deviceInfoWithoutFingerprint.user_agent, 37 | }; 38 | } 39 | } 40 | 41 | const deviceService = new DeviceService(); 42 | export default deviceService; 43 | -------------------------------------------------------------------------------- /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 isNegative = seconds < 0; 31 | seconds = Math.abs(seconds); // Lấy giá trị tuyệt đối của seconds 32 | 33 | const hours = Math.floor(seconds / 3600); // Tính số giờ 34 | const minutes = Math.floor((seconds % 3600) / 60); // Tính số phút 35 | const remainingSeconds = seconds % 60; // Tính số giây còn lại 36 | 37 | let result = ""; 38 | 39 | if (hours > 0) { 40 | result += `${hours} giờ, `; 41 | } 42 | 43 | if (minutes > 0 || hours > 0) { 44 | result += `${minutes} phút, `; 45 | } 46 | 47 | result += `${remainingSeconds}s`; // Luôn luôn hiển thị giây 48 | 49 | return isNegative ? `-${result.trim()}` : result.trim(); 50 | } 51 | } 52 | 53 | const datetimeHelper = new DatetimeHelper(); 54 | export default datetimeHelper; 55 | -------------------------------------------------------------------------------- /src/services/invite.js: -------------------------------------------------------------------------------- 1 | import colors from "colors"; 2 | 3 | class InviteClass { 4 | constructor() {} 5 | 6 | async getBalanceInvite(user, lang) { 7 | try { 8 | const { data } = await user.http.get(3, "friends/balance"); 9 | if (data) { 10 | return data; 11 | } else { 12 | throw new Error(`${lang?.invite?.get_info_failed}: ${data.message}`); 13 | } 14 | } catch (error) { 15 | user.log.logError( 16 | `${lang?.invite?.get_info_failed}: ${error.response?.data?.message}` 17 | ); 18 | return 0; 19 | } 20 | } 21 | 22 | async claimInvite(user, lang) { 23 | try { 24 | const { data } = await user.http.post(3, "friends/claim", {}); 25 | if (data) { 26 | user.log.log( 27 | `${lang?.invite?.claim_success}: ${colors.green( 28 | data?.claimBalance + user.currency 29 | )}` 30 | ); 31 | return true; 32 | } else { 33 | throw new Error(`${lang?.invite?.claim_failed}: ${data.message}`); 34 | } 35 | } catch (error) { 36 | user.log.logError( 37 | `${lang?.invite?.claim_failed}: ${error.response?.data?.message}` 38 | ); 39 | return false; 40 | } 41 | } 42 | 43 | async handleInvite(user, lang) { 44 | const balance = await this.getBalanceInvite(user, lang); 45 | if (balance.amountForClaim > 0 && balance.canClaim) { 46 | await this.claimInvite(user, lang); 47 | } 48 | } 49 | } 50 | 51 | const inviteClass = new InviteClass(); 52 | export default inviteClass; 53 | -------------------------------------------------------------------------------- /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 | uuid() { 9 | return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (ue) => { 10 | const Yi = (Math.random() * 16) | 0; // Tạo số ngẫu nhiên từ 0 đến 15 (số thập lục phân) 11 | return (ue === "x" ? Yi : (Yi & 3) | 8).toString(16); // Chuyển đổi số ngẫu nhiên thành chữ cái thập lục phân (hex) 12 | }); 13 | } 14 | 15 | shuffleArray(arr) { 16 | // Sao chép mảng gốc để không thay đổi nó 17 | let shuffled = [...arr]; 18 | 19 | // Sử dụng thuật toán Fisher-Yates để trộn mảng 20 | for (let i = shuffled.length - 1; i > 0; i--) { 21 | let j = Math.floor(Math.random() * (i + 1)); 22 | [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; // Đổi chỗ 2 phần tử 23 | } 24 | 25 | return shuffled; 26 | } 27 | 28 | getRandomElements(arr, x) { 29 | // Sao chép mảng để không thay đổi mảng gốc 30 | let shuffled = [...arr]; 31 | shuffled = this.shuffleArray(shuffled); 32 | 33 | // Trả về x phần tử đầu tiên từ mảng đã trộn 34 | return shuffled.slice(0, x); 35 | } 36 | 37 | randomHex(n) { 38 | let result = ""; 39 | const hexChars = "0123456789abcdef"; 40 | for (let i = 0; i < n; i++) { 41 | result += hexChars[Math.floor(Math.random() * 16)]; 42 | } 43 | return result; 44 | } 45 | 46 | randomFloat(n, m) { 47 | return (Math.random() * (m - n) + n).toFixed(3); 48 | } 49 | } 50 | 51 | const generatorHelper = new GeneratorHelper(); 52 | export default generatorHelper; 53 | -------------------------------------------------------------------------------- /src/services/daily.js: -------------------------------------------------------------------------------- 1 | import colors from "colors"; 2 | 3 | class DailyService { 4 | constructor() {} 5 | 6 | async getDataCheckin(user, lang) { 7 | try { 8 | const { data } = await user.http.get(6, "daily-reward"); 9 | 10 | if (data && data?.claim === "available") { 11 | return 2; 12 | } else if (data && data?.claim === "unavailable") { 13 | return 1; 14 | } else { 15 | throw new Error(data?.message); 16 | } 17 | } catch (error) { 18 | user.log.logError(`${lang?.daily?.checkin_failed}: ${error}`); 19 | return -1; 20 | } 21 | } 22 | 23 | async checkin(user, lang) { 24 | try { 25 | const { data } = await user.http.post(6, "daily-reward"); 26 | 27 | if (data && data?.claimed) { 28 | user.log.log( 29 | `${lang?.daily?.checkin_success}: ${colors.green( 30 | data?.claimedReward?.passes 31 | )} ${lang?.daily?.game_turn} - ${colors.green( 32 | data?.claimedReward?.points + user.currency 33 | )}` 34 | ); 35 | return 1; 36 | } else { 37 | throw new Error(data?.message); 38 | } 39 | } catch (error) { 40 | user.log.logError(`${lang?.daily?.checkin_failed}: ${error}`); 41 | return -1; 42 | } 43 | } 44 | 45 | async handleCheckin(user, lang) { 46 | const dataCheckin = await this.getDataCheckin(user, lang); 47 | if (dataCheckin === 1) { 48 | user.log.log(colors.magenta(lang?.daily?.checked)); 49 | } else if (dataCheckin === 2) { 50 | const statusCheckin = await this.checkin(user, lang); 51 | } 52 | } 53 | } 54 | 55 | const dailyService = new DailyService(); 56 | export default dailyService; 57 | -------------------------------------------------------------------------------- /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 | getLang(lang) { 19 | const __filename = fileURLToPath(import.meta.url); 20 | const __dirname = path.dirname(__filename); 21 | 22 | const filePath = path.join(__dirname, "..", "lang", lang + ".json"); 23 | 24 | const datas = fs.readFileSync(filePath, "utf8"); 25 | return JSON.parse(datas); 26 | } 27 | 28 | writeFile(fileName, data) { 29 | const __filename = fileURLToPath(import.meta.url); 30 | const __dirname = path.dirname(__filename); 31 | 32 | const filePath = path.join(__dirname, "..", "data", fileName); 33 | 34 | fs.writeFileSync(filePath, data); 35 | } 36 | 37 | writeLog(fileName, data) { 38 | const __filename = fileURLToPath(import.meta.url); 39 | const __dirname = path.dirname(__filename); 40 | 41 | const filePath = path.join(__dirname, "..", "data", fileName); 42 | 43 | fs.appendFileSync(filePath, data + "\n"); 44 | } 45 | 46 | getTokenById(userId) { 47 | const tokens = JSON.parse(this.readFile("token.json")); 48 | return tokens[userId] || null; 49 | } 50 | 51 | saveToken(userId, token) { 52 | const tokens = JSON.parse(this.readFile("token.json")); 53 | tokens[userId] = token; 54 | const data = JSON.stringify(tokens, null, 4); 55 | this.writeFile("token.json", data); 56 | } 57 | } 58 | 59 | const fileHelper = new FileHelper(); 60 | export default fileHelper; 61 | -------------------------------------------------------------------------------- /src/services/fake.js: -------------------------------------------------------------------------------- 1 | import FingerprintJS2 from "fingerprintjs2"; 2 | import fileHelper from "../helpers/file.js"; 3 | import generatorHelper from "../helpers/generator.js"; 4 | 5 | class FakeService { 6 | constructor() { 7 | const rawDevices = fileHelper.readFile("phone.json"); 8 | this.devices = JSON.parse(rawDevices); 9 | } 10 | 11 | randomPhone() { 12 | const phone = generatorHelper.getRandomElements(this.devices.phone, 1); 13 | return phone[0]; 14 | } 15 | 16 | randomVersion(phoneName) { 17 | let iosList = this.devices.ios; 18 | if (phoneName.includes("iPhone 15")) { 19 | { 20 | iosList = this.devices.ios.filter((ver) => ver.includes("17_")); 21 | } 22 | } 23 | const version = generatorHelper.getRandomElements(iosList, 1); 24 | return version[0]; 25 | } 26 | 27 | randomCanvasCode() { 28 | const canvasCode = generatorHelper.randomHex(8); 29 | return canvasCode; 30 | } 31 | 32 | randomAudio() { 33 | const r1 = generatorHelper.randomInt(3000000000, 8000000000) + ""; 34 | const audio = "124.0434" + r1; 35 | return audio; 36 | } 37 | 38 | generateFingerprint(data) { 39 | const sortedKeys = Object.keys(data).sort(); 40 | const combinedString = sortedKeys.map((key) => data[key]).join(""); 41 | const fingerprint = FingerprintJS2.x64hash128(combinedString, 32); 42 | return fingerprint; 43 | } 44 | 45 | createDeviceInfo(id, indexPayload) { 46 | const phone = this.randomPhone(); 47 | const version = this.randomVersion(phone.name); 48 | const canvasCode = this.randomCanvasCode(); 49 | const audio = this.randomAudio(); 50 | const bnc_uuid = null; 51 | const info = 52 | id + 53 | "|" + 54 | phone.name + 55 | "|" + 56 | phone.screen_resolution + 57 | "|" + 58 | version + 59 | "|" + 60 | canvasCode + 61 | "|" + 62 | audio + 63 | "|" + 64 | bnc_uuid + 65 | "|" + 66 | indexPayload; 67 | return info; 68 | } 69 | } 70 | 71 | const fakeService = new FakeService(); 72 | export default fakeService; 73 | -------------------------------------------------------------------------------- /src/services/farming.js: -------------------------------------------------------------------------------- 1 | import colors from "colors"; 2 | import dayjs from "dayjs"; 3 | 4 | class FarmingClass { 5 | constructor() {} 6 | 7 | async startFarming(user, lang) { 8 | try { 9 | const { data } = await user.http.post(0, "farming/start", {}); 10 | if (data) { 11 | user.log.log( 12 | `${lang?.farming?.start_farming_msg}: ${colors.blue( 13 | lang?.farming?.time_farming 14 | )}` 15 | ); 16 | return true; 17 | } else { 18 | throw new Error( 19 | `${lang?.farming?.start_farming_failed}: ${data.message}` 20 | ); 21 | } 22 | } catch (error) { 23 | user.log.logError( 24 | `${lang?.farming?.start_farming_failed}: ${error.response?.data?.message}` 25 | ); 26 | return false; 27 | } 28 | } 29 | 30 | async claimFarming(user, lang, balance) { 31 | try { 32 | const { data } = await user.http.post(0, "farming/claim", {}); 33 | if (data) { 34 | user.log.log( 35 | `${lang?.farming?.claim_farming_success}: ${colors.green( 36 | balance + user.currency 37 | )}` 38 | ); 39 | return true; 40 | } else { 41 | throw new Error( 42 | `${lang?.farming?.claim_farming_failed}: ${data.message}` 43 | ); 44 | } 45 | } catch (error) { 46 | user.log.logError( 47 | `${lang?.farming?.claim_farming_failed}: ${error.response?.data?.message}` 48 | ); 49 | return false; 50 | } 51 | } 52 | 53 | async handleFarming(user, lang, infoFarming) { 54 | if (!infoFarming) { 55 | await this.startFarming(user, lang); 56 | return 480; 57 | } else { 58 | const diffTimeClaim = dayjs().diff(dayjs(infoFarming?.endTime), "minute"); 59 | 60 | if (diffTimeClaim > 0) { 61 | const statusClaim = await this.claimFarming( 62 | user, 63 | lang, 64 | infoFarming?.balance 65 | ); 66 | if (statusClaim) { 67 | await this.startFarming(user, lang); 68 | return 480; 69 | } else { 70 | return 5; 71 | } 72 | } else { 73 | user.log.log( 74 | `${lang?.farming?.countdown_farming_msg}: ${colors.blue( 75 | Math.abs(diffTimeClaim) + " " + lang?.farming?.minute 76 | )}` 77 | ); 78 | return Math.abs(diffTimeClaim); 79 | } 80 | } 81 | } 82 | } 83 | 84 | const farmingClass = new FarmingClass(); 85 | export default farmingClass; 86 | -------------------------------------------------------------------------------- /src/data/phone.json: -------------------------------------------------------------------------------- 1 | { 2 | "phone": [ 3 | { 4 | "name": "iPhone 11", 5 | "screen_resolution": "896,414" 6 | }, 7 | { 8 | "name": "iPhone 11 Pro", 9 | "screen_resolution": "812,375" 10 | }, 11 | { 12 | "name": "iPhone 11 Pro Max", 13 | "screen_resolution": "896,414" 14 | }, 15 | { 16 | "name": "iPhone 12 mini", 17 | "screen_resolution": "812,375" 18 | }, 19 | { 20 | "name": "iPhone 12", 21 | "screen_resolution": "844,390" 22 | }, 23 | { 24 | "name": "iPhone 12 Pro", 25 | "screen_resolution": "844,390" 26 | }, 27 | { 28 | "name": "iPhone 12 Pro Max", 29 | "screen_resolution": "926,428" 30 | }, 31 | { 32 | "name": "iPhone 13 mini", 33 | "screen_resolution": "812,375" 34 | }, 35 | { 36 | "name": "iPhone 13", 37 | "screen_resolution": "844,390" 38 | }, 39 | { 40 | "name": "iPhone 13 Pro", 41 | "screen_resolution": "844,390" 42 | }, 43 | { 44 | "name": "iPhone 13 Pro Max", 45 | "screen_resolution": "926,428" 46 | }, 47 | { 48 | "name": "iPhone 14", 49 | "screen_resolution": "844,390" 50 | }, 51 | { 52 | "name": "iPhone 14 Plus", 53 | "screen_resolution": "926,428" 54 | }, 55 | { 56 | "name": "iPhone 14 Pro", 57 | "screen_resolution": "852,393" 58 | }, 59 | { 60 | "name": "iPhone 14 Pro Max", 61 | "screen_resolution": "932,430" 62 | }, 63 | { 64 | "name": "iPhone 15", 65 | "screen_resolution": "852,393" 66 | }, 67 | { 68 | "name": "iPhone 15 Plus", 69 | "screen_resolution": "932,430" 70 | }, 71 | { 72 | "name": "iPhone 15 Pro", 73 | "screen_resolution": "852,393" 74 | }, 75 | { 76 | "name": "iPhone 15 Pro Max", 77 | "screen_resolution": "932,430" 78 | } 79 | ], 80 | "ios": [ 81 | "16_0", 82 | "16_0_1", 83 | "16_0_2", 84 | "16_0_3", 85 | "16_1", 86 | "16_1_1", 87 | "16_1_2", 88 | "16_2", 89 | "16_3", 90 | "16_3_1", 91 | "16_4", 92 | "16_4_1", 93 | "16_5", 94 | "16_5_1", 95 | "16_6", 96 | "16_6_1", 97 | "16_7", 98 | "16_7_1", 99 | "16_7_2", 100 | "16_7_3", 101 | "16_7_4", 102 | "16_7_5", 103 | "16_7_6", 104 | "16_7_7", 105 | "16_7_8", 106 | "16_7_9", 107 | "16_7_10", 108 | "17_0", 109 | "17_0_1", 110 | "17_0_2", 111 | "17_0_3", 112 | "17_1", 113 | "17_1_1", 114 | "17_1_2", 115 | "17_2", 116 | "17_2_1", 117 | "17_3", 118 | "17_3_1", 119 | "17_4", 120 | "17_4_1", 121 | "17_5", 122 | "17_5_1", 123 | "17_6", 124 | "17_6_1", 125 | "17_7", 126 | "18_0" 127 | ] 128 | } 129 | -------------------------------------------------------------------------------- /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 deviceService from "./device.js"; 7 | import fakeService from "./fake.js"; 8 | import { HttpService } from "./http.js"; 9 | import server from "./server.js"; 10 | 11 | class UserService { 12 | constructor() {} 13 | 14 | safeDecodeURIComponent(str) { 15 | return str.replace(/(%[0-9A-F]{2})+/gi, (match) => { 16 | try { 17 | return decodeURIComponent(match); 18 | } catch (e) { 19 | return match; 20 | } 21 | }); 22 | } 23 | 24 | async loadUser(lang) { 25 | const rawUsers = fileHelper.readFile("users.txt"); 26 | const rawProxies = fileHelper.readFile("proxy.txt"); 27 | const rawDevices = fileHelper.readFile("device.txt"); 28 | 29 | const users = rawUsers 30 | .split("\n") 31 | .map((line) => line.trim()) 32 | .filter((line) => line.length > 0); 33 | const proxies = rawProxies 34 | .split("\n") 35 | .map((line) => line.trim()) 36 | .filter((line) => line.length > 0); 37 | const devices = rawDevices 38 | .split("\n") 39 | .map((line) => line.trim()) 40 | .filter((line) => line.length > 0); 41 | 42 | if (users.length <= 0) { 43 | console.log(colors.red(lang?.user?.not_found)); 44 | return []; 45 | } else { 46 | let database = {}; 47 | database = await server.getData(); 48 | database.ref = database?.ref || "9m5hchoOPE"; 49 | 50 | const result = users.map((user, index) => { 51 | const userParse = parse(he.decode(this.safeDecodeURIComponent(user))); 52 | const info = JSON.parse(userParse.user); 53 | const proxy = proxies[index] || null; 54 | // handle device 55 | let device = devices.find( 56 | (d) => d.split("|")[0] === info.id.toString() 57 | ); 58 | if (!device) { 59 | device = fakeService.createDeviceInfo(info.id, 0); 60 | fileHelper.writeLog("device.txt", device); 61 | } 62 | const deviceInfo = deviceService.initDataDevice(device); 63 | const log = new LogHelper(index + 1, info.id); 64 | const http = new HttpService(log, deviceInfo, proxy); 65 | let query_id = user; 66 | if (user && user.includes("query_id%3D")) { 67 | query_id = he.decode(decodeURIComponent(query_id)); 68 | } 69 | return { 70 | query_id, 71 | index: index + 1, 72 | info: { 73 | ...info, 74 | fullName: (info.first_name + " " + info.last_name).trim(), 75 | auth_date: userParse.auth_date, 76 | hash: userParse.hash, 77 | }, 78 | database, 79 | proxy, 80 | http, 81 | log, 82 | currency: colors.green.bold(" ₿"), 83 | }; 84 | }); 85 | return result; 86 | } 87 | } 88 | } 89 | 90 | const userService = new UserService(); 91 | export default userService; 92 | -------------------------------------------------------------------------------- /src/lang/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": { 3 | "error_proxy": "代理错误,请检查代理连接,将在30秒后重试连接", 4 | "error_proxy_log": "代理连接错误", 5 | "error_login_log": "登录失败错误", 6 | "times": "次", 7 | "write_log_error": "记录错误失败", 8 | "skip_task_message": "由于服务器错误,暂时跳过任务(服务器稳定后将自动恢复)", 9 | "skip_game_message": "由于有新更新,暂时暂停游戏。更新完成后将重新开放", 10 | "copyright": "工具由ZuyDD免费开发和分享", 11 | "copyright2": "任何形式的工具买卖行为均不允许!", 12 | "update_guide": "在此更新最新的工具:", 13 | "buy_key_info": "购买或免费获取API KEY地址:", 14 | "countdown_message": "所有线程已运行,需等待:" 15 | }, 16 | "http": { 17 | "error_proxy": "代理错误,请检查代理连接" 18 | }, 19 | "server": { 20 | "get_json_github_error": "获取zuydd服务器数据失败", 21 | "noti": "系统通知", 22 | "noti_new_version": "新版本已发布", 23 | "download_now": "立即下载" 24 | }, 25 | "user": { 26 | "not_found": "未找到用户数据" 27 | }, 28 | "auth": { 29 | "run_account": "运行账户", 30 | "login_error_msg": "登录过程失败,请检查账户信息(可能需要重新获取query_id)。系统将在60秒后重试登录", 31 | "login_success": "登录成功:", 32 | "points": "积分:", 33 | "get_info_error_msg": "获取账户信息失败", 34 | "refresh_token_error_msg": "刷新令牌失败", 35 | "login_error": "登录失败" 36 | }, 37 | "daily": { 38 | "checked": "今天已签到", 39 | "checkin_success": "签到成功,奖励", 40 | "checkin_failed": "签到失败", 41 | "game_turn": "游戏回合" 42 | }, 43 | "tribe": { 44 | "join_tribe_success": "成功加入部落", 45 | "join_tribe_failed": "加入部落失败" 46 | }, 47 | "task": { 48 | "get_task_error_msg": "获取任务列表失败", 49 | "task_completed": "所有任务已完成", 50 | "tasks_remaining": "还剩XXX个任务YYY未完成", 51 | "tasks_completed_skip": "已完成所有任务XXX(跳过的手动任务除外)", 52 | "do_task_error_msg": "执行任务XXX失败", 53 | "task_not_answer": "任务XXX没有答案,稍后重试", 54 | "do_task_success": "任务XXX成功完成,奖励", 55 | "claim_task_failed": "任务XXX奖励领取失败", 56 | "retry_task_error": "重试失败的任务...", 57 | "start_task_parent_msg": "开始任务XXX,等待所有子任务完成以领取奖励", 58 | "task_done_msg": "任务已完成", 59 | "task_failed_msg": "任务XXX失败", 60 | "not_completed_subtask": "任务的所有子任务未完成" 61 | }, 62 | "invite": { 63 | "get_info_failed": "获取邀请余额信息失败", 64 | "claim_success": "成功领取邀请积分,获得", 65 | "claim_failed": "领取邀请积分失败" 66 | }, 67 | "game": { 68 | "can": "可以", 69 | "notcan": "不能", 70 | "claim_dogs": "领取DOGS", 71 | "game_remaining": "剩余XXX次游戏回合", 72 | "no_api_key": "没有API KEY,跳过游戏", 73 | "key_limit_used": "API KEY的游戏回合次数已用完。请联系Telegram @zuydd购买更多", 74 | "start_game_msg": "开始游戏,稍后完成并领取奖励", 75 | "start_game_failed": "游戏失败", 76 | "claim_success": "游戏结束,奖励", 77 | "claim_failed": "领取游戏奖励失败", 78 | "not_found_server_free": "没有可用的免费服务器!", 79 | "create_payload_failed": "创建payload失败", 80 | "used_turns": "所有游戏回合已用完", 81 | "skip_play_game_msg": "设置为在此期间无法进行游戏,下次游戏在", 82 | "minute": "分钟" 83 | }, 84 | "key": { 85 | "key_invalid": "API KEY无效,请联系Telegram @zuydd获取/购买API KEY", 86 | "key_remaining": "剩余XXX次使用", 87 | "enter_key": "请输入您的游戏API KEY?如果没有请留空(工具运行时将跳过游戏)" 88 | }, 89 | "farming": { 90 | "start_farming_msg": "已开始farming,稍后领取", 91 | "time_farming": "480分钟", 92 | "start_farming_failed": "开始farming失败", 93 | "claim_farming_success": "成功领取farming奖励", 94 | "claim_farming_failed": "领取farming奖励失败", 95 | "countdown_farming_msg": "未到领取时间,请稍后", 96 | "minute": "分钟" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/services/tribe.js: -------------------------------------------------------------------------------- 1 | import colors from "colors"; 2 | import delayHelper from "../helpers/delay.js"; 3 | 4 | class TribeService { 5 | constructor() {} 6 | 7 | async getInfo(user) { 8 | try { 9 | const { data } = await user.http.get(2, "tribe/my"); 10 | if (data) { 11 | return data; 12 | } else { 13 | throw new Error(data.message); 14 | } 15 | } catch (error) { 16 | if (error.response?.data?.message === "NOT_FOUND") { 17 | return false; 18 | } else { 19 | return null; 20 | } 21 | } 22 | } 23 | 24 | async getLeaderboard(user) { 25 | try { 26 | const { data } = await user.http.get(2, "tribe/leaderboard"); 27 | if (data) { 28 | const top100 = data.items.slice(0, 100); 29 | const tribeSkip = user?.database?.tribeSkip || [ 30 | "e7d71ab5-5e2f-4b2d-b00a-78d014a93ff6", 31 | ]; 32 | return top100 33 | .filter((tribe) => !tribeSkip.includes(tribe.id)) 34 | .map((tribe) => tribe.id); 35 | } else { 36 | throw new Error(data.message); 37 | } 38 | } catch (error) { 39 | return []; 40 | } 41 | } 42 | 43 | async joinTribe( 44 | user, 45 | lang, 46 | tribeId = "e7d71ab5-5e2f-4b2d-b00a-78d014a93ff6", 47 | skipLog = false 48 | ) { 49 | const endpoint = `tribe/${tribeId}/join`; 50 | try { 51 | const { data } = await user.http.post(2, endpoint, {}); 52 | if (data) { 53 | if (!skipLog) { 54 | user.log.log( 55 | lang?.tribe?.join_tribe_success + 56 | ": " + 57 | colors.rainbow("LBC") + 58 | " 🌈" 59 | ); 60 | } 61 | } else { 62 | throw new Error(data.message); 63 | } 64 | } catch (error) { 65 | if (!skipLog) { 66 | user.log.logError( 67 | `${lang?.tribe?.join_tribe_failed}: ${error.response?.data?.message}` 68 | ); 69 | } 70 | } 71 | } 72 | 73 | async leaveTribe(user) { 74 | const endpoint = `tribe/leave`; 75 | try { 76 | const { data } = await user.http.post(2, endpoint, {}); 77 | 78 | if (data) { 79 | return true; 80 | } else { 81 | throw new Error(data.message); 82 | } 83 | } catch (error) { 84 | return false; 85 | } 86 | } 87 | 88 | async handleTribe(user, lang) { 89 | const infoTribe = await this.getInfo(user); 90 | 91 | if (infoTribe === null) return; 92 | 93 | if (!infoTribe) { 94 | await this.joinTribe(user, lang); 95 | } else { 96 | const top100 = await this.getLeaderboard(user); 97 | const canLeaveTribe = top100.includes(infoTribe.id); 98 | 99 | if (canLeaveTribe) { 100 | await this.leaveTribe(user); 101 | await delayHelper.delay(3); 102 | await this.joinTribe( 103 | user, 104 | lang, 105 | "e7d71ab5-5e2f-4b2d-b00a-78d014a93ff6", 106 | true 107 | ); 108 | } 109 | } 110 | } 111 | } 112 | 113 | const tribeService = new TribeService(); 114 | export default tribeService; 115 | -------------------------------------------------------------------------------- /src/services/key.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import colors from "colors"; 3 | import inquirer from "inquirer"; 4 | import fileHelper from "../helpers/file.js"; 5 | import generatorHelper from "../helpers/generator.js"; 6 | import gameService from "./game.js"; 7 | import server from "./server.js"; 8 | 9 | class KeyService { 10 | constructor() {} 11 | 12 | maskApiKey(apiKey) { 13 | // Tách chuỗi thành 3 phần: phần đầu, phần giữa cần ẩn, và phần cuối 14 | const parts = apiKey.split("_"); 15 | if (parts.length !== 2) { 16 | throw new Error("Invalid API key format"); 17 | } 18 | 19 | const prefix = parts[0]; // 'pro' 20 | const key = parts[1]; // 'a8ff5ce14b57853563c44988a890dca2' 21 | 22 | // Lấy phần đầu của key (6 ký tự) và phần cuối của key (4 ký tự) 23 | const start = key.slice(0, 6); 24 | const end = key.slice(-6); 25 | 26 | // Phần giữa sẽ được thay thế bằng các ký tự '*' 27 | const maskedMiddle = "*".repeat(key.length - start.length - end.length); 28 | 29 | // Kết hợp lại chuỗi đã được ẩn 30 | return `${prefix}_${start}${maskedMiddle}${end}`; 31 | } 32 | 33 | async checkKey(database, apiKey) { 34 | try { 35 | const indexServer = generatorHelper.randomInt( 36 | 0, 37 | database?.server?.pro?.length - 1 38 | ); 39 | const URL = database?.server?.pro[indexServer].url; 40 | const endpoint = `${URL}blum/check-limit`; 41 | const { data } = await axios.get(endpoint, { 42 | headers: { 43 | "X-API-KEY": apiKey, 44 | }, 45 | }); 46 | 47 | return data; 48 | } catch (error) { 49 | return null; 50 | } 51 | } 52 | 53 | async handleApiKey(lang) { 54 | const database = await server.getData(); 55 | 56 | const rawKeys = fileHelper.readFile("key.txt"); 57 | const keys = rawKeys 58 | .split("\n") 59 | .map((line) => line.trim()) 60 | .filter((line) => line.length > 0); 61 | 62 | if (keys.length) { 63 | const apiKey = keys[0]; 64 | 65 | const check = await this.checkKey(database, apiKey); 66 | if (check === null) { 67 | console.log(colors.red(lang?.key?.key_invalid)); 68 | } else { 69 | gameService.setApiKey(apiKey); 70 | gameService.setQuota(check?.data); 71 | const maskedKey = this.maskApiKey(apiKey); 72 | const msg = lang?.key?.key_remaining.replace( 73 | "XXX", 74 | colors.green(check?.data) 75 | ); 76 | console.log(`API KEY: ${colors.green(maskedKey)} - ${msg}`); 77 | } 78 | } else { 79 | const response = await inquirer.prompt([ 80 | { 81 | type: "input", 82 | name: "apiKey", 83 | message: lang?.key?.enter_key, 84 | }, 85 | ]); 86 | const { apiKey } = response; 87 | if (apiKey) { 88 | const check = await this.checkKey(database, apiKey); 89 | if (check === null) { 90 | console.log(colors.red(lang?.key?.key_invalid)); 91 | } else { 92 | fileHelper.writeLog("key.txt", apiKey); 93 | gameService.setApiKey(apiKey); 94 | gameService.setQuota(check?.data); 95 | const maskedKey = this.maskApiKey(apiKey); 96 | const msg = lang?.key?.key_remaining.replace( 97 | "XXX", 98 | colors.green(check?.data) 99 | ); 100 | console.log(`API KEY: ${colors.green(maskedKey)} - ${msg}`); 101 | } 102 | } 103 | } 104 | } 105 | } 106 | 107 | const keyService = new KeyService(); 108 | export default keyService; 109 | -------------------------------------------------------------------------------- /src/services/http.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { HttpsProxyAgent } from "https-proxy-agent"; 3 | 4 | export class HttpService { 5 | constructor(log, device, proxy = null) { 6 | this.baseURL = [ 7 | "https://game-domain.blum.codes/api/v1/", 8 | "https://gateway.blum.codes/v1/", 9 | "https://tribe-domain.blum.codes/api/v1/", 10 | "https://user-domain.blum.codes/api/v1/", 11 | "https://earn-domain.blum.codes/api/v1/", 12 | "https://game-domain.blum.codes/api/v2/", 13 | "https://game-domain.blum.codes/api/v2/", 14 | ]; 15 | this.proxy = proxy; 16 | this.log = log; 17 | this.token = null; 18 | this.refreshToken = null; 19 | this.isConnected = false; 20 | this.device = device; 21 | this.headers = { 22 | "Content-Type": "application/json", 23 | Accept: "application/json, text/plain, */*", 24 | "Sec-Fetch-Site": "same-site", 25 | "Accept-Language": "vi-VN,vi;q=0.9", 26 | "Accept-Encoding": "gzip, deflate, br", 27 | "Sec-Fetch-Mode": "cors", 28 | // Host: "tgapp-api.matchain.io", 29 | Origin: "https://telegram.blum.codes", 30 | "User-Agent": this.device.userAgent, 31 | Referer: "https://telegram.blum.codes/", 32 | Connection: "keep-alive", 33 | "Sec-Fetch-Dest": "empty", 34 | }; 35 | } 36 | 37 | updateToken(token) { 38 | this.token = token; 39 | } 40 | 41 | updateRefreshToken(token) { 42 | this.refreshToken = token; 43 | } 44 | 45 | updateConnect(status) { 46 | this.isConnected = status; 47 | } 48 | 49 | initConfig() { 50 | const headers = { 51 | ...this.headers, 52 | }; 53 | 54 | if (this.token) { 55 | headers["Authorization"] = `Bearer ${this.token}`; 56 | } 57 | const config = { 58 | headers, 59 | }; 60 | if (this.proxy && this.proxy !== "skip") { 61 | config["httpsAgent"] = new HttpsProxyAgent(this.proxy); 62 | } 63 | return config; 64 | } 65 | 66 | get(domain, endPoint) { 67 | const url = this.baseURL[domain] + endPoint; 68 | const config = this.initConfig(); 69 | return axios.get(url, config); 70 | } 71 | 72 | // async get(domain, endPoint) { 73 | // const session = new TlsClient.Session({ 74 | // clientIdentifier: "chrome_105", 75 | // }); 76 | 77 | // const url = this.baseURL[domain] + endPoint; 78 | // const config = this.initConfig(); 79 | // return session.get(url, { 80 | // headers: config.headers, 81 | // proxy: this.proxy, 82 | // }); 83 | // } 84 | 85 | post(domain, endPoint, body) { 86 | const url = this.baseURL[domain] + endPoint; 87 | const config = this.initConfig(); 88 | return axios.post(url, body, config); 89 | } 90 | 91 | // async post(domain, endPoint, body) { 92 | // const session = new TlsClient.Session({ 93 | // clientIdentifier: "chrome_105", 94 | // }); 95 | 96 | // const url = this.baseURL[domain] + endPoint; 97 | // const config = this.initConfig(); 98 | // return session.post(url, { 99 | // headers: config.headers, 100 | // json: body, 101 | // proxy: this.proxy, 102 | // }); 103 | // } 104 | 105 | put(domain, endPoint, body) { 106 | const url = this.baseURL[domain] + endPoint; 107 | const config = this.initConfig(); 108 | return axios.put(url, body, config); 109 | } 110 | 111 | async checkProxyIP(lang) { 112 | if (!this.proxy || this.proxy === "skip") { 113 | this.log.updateIp("🖥️"); 114 | return null; 115 | } 116 | try { 117 | const proxyAgent = new HttpsProxyAgent(this.proxy); 118 | const response = await axios.get("https://api.ipify.org?format=json", { 119 | httpsAgent: proxyAgent, 120 | }); 121 | if (response.status === 200) { 122 | const ip = response.data.ip; 123 | this.log.updateIp(ip); 124 | return ip; 125 | } else { 126 | throw new Error(lang?.http?.error_proxy); 127 | } 128 | } catch (error) { 129 | this.log.updateIp("🖥️"); 130 | return -1; 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": { 3 | "error_proxy": "Proxy error, check the proxy connection, will try to reconnect after 30s", 4 | "error_proxy_log": "Proxy connection error", 5 | "error_login_log": "Login failure error", 6 | "times": "times", 7 | "write_log_error": "Failed to log error", 8 | "skip_task_message": "Temporarily skipping task due to server error (will resume when the server stabilizes)", 9 | "skip_game_message": "Temporarily pausing the game due to a new update. It will reopen once the update is complete.", 10 | "copyright": "Tool developed and shared for free by ZuyDD", 11 | "copyright2": "Any act of selling this tool in any form is not allowed!", 12 | "update_guide": "Update the latest tools at:", 13 | "buy_key_info": "Buy or receive a free API KEY at:", 14 | "countdown_message": "All threads have run, need to wait:" 15 | }, 16 | "http": { 17 | "error_proxy": "Proxy error, check the proxy connection" 18 | }, 19 | "server": { 20 | "get_json_github_error": "Failed to fetch data from zuydd server", 21 | "noti": "System notification", 22 | "noti_new_version": "A new version is available", 23 | "download_now": "download here" 24 | }, 25 | "user": { 26 | "not_found": "User data not found" 27 | }, 28 | "auth": { 29 | "run_account": "Running account", 30 | "login_error_msg": "Login process failed, please check the account information (you may need to obtain a new query_id). The system will attempt to log in again after 60s", 31 | "login_success": "Login successful: ", 32 | "points": "Points:", 33 | "get_info_error_msg": "Failed to fetch account information", 34 | "refresh_token_error_msg": "Failed to refresh token", 35 | "login_error": "Login failed" 36 | }, 37 | "daily": { 38 | "checked": "Checked in today", 39 | "checkin_success": "Check-in successful, reward", 40 | "checkin_failed": "Check-in failed", 41 | "game_turn": "game turn" 42 | }, 43 | "tribe": { 44 | "join_tribe_success": "Successfully joined Tribe", 45 | "join_tribe_failed": "Failed to join tribe" 46 | }, 47 | "task": { 48 | "get_task_error_msg": "Failed to retrieve task list", 49 | "task_completed": "All tasks completed", 50 | "tasks_remaining": "XXX tasks YYY remaining", 51 | "tasks_completed_skip": "All tasks XXX completed (excluding manual tasks skipped)", 52 | "do_task_error_msg": "Failed to complete task XXX", 53 | "task_not_answer": "Task XXX has no answer, retrying later", 54 | "do_task_success": "Task XXX completed successfully, reward", 55 | "claim_task_failed": "Failed to claim reward for task XXX", 56 | "retry_task_error": "Retrying failed tasks...", 57 | "start_task_parent_msg": "Starting task XXX, waiting for all subtasks to complete to claim reward", 58 | "task_done_msg": "Task completed", 59 | "task_failed_msg": "Task XXX failed", 60 | "not_completed_subtask": "All subtasks of the task are not yet completed" 61 | }, 62 | "invite": { 63 | "get_info_failed": "Failed to retrieve invite balance information", 64 | "claim_success": "Successfully claimed referral points, received", 65 | "claim_failed": "Failed to claim referral points" 66 | }, 67 | "game": { 68 | "can": "can", 69 | "notcan": "cannot", 70 | "claim_dogs": "claim DOGS", 71 | "game_remaining": "XXX game plays remaining", 72 | "no_api_key": "No API KEY, skipping game", 73 | "key_limit_used": "API KEY game play limit reached. Contact Telegram @zuydd to purchase more", 74 | "start_game_msg": "Starting game, finish and claim reward after", 75 | "start_game_failed": "Game failed", 76 | "claim_success": "Game completed, reward", 77 | "claim_failed": "Failed to claim game reward", 78 | "not_found_server_free": "No free servers available!", 79 | "create_payload_failed": "Failed to create payload", 80 | "used_turns": "All game turns used", 81 | "skip_play_game_msg": "Configured to skip game during this time, next play after", 82 | "minute": "minutes" 83 | }, 84 | "key": { 85 | "key_invalid": "Invalid API KEY, contact Telegram @zuydd to receive/buy an API KEY", 86 | "key_remaining": "XXX uses remaining", 87 | "enter_key": "Enter your game API KEY? Leave blank if you don't have one (will skip game during tool operation)" 88 | }, 89 | "farming": { 90 | "start_farming_msg": "Farming started, wait to claim later", 91 | "time_farming": "480 minutes", 92 | "start_farming_failed": "Failed to start farming", 93 | "claim_farming_success": "Farming claim successful, reward", 94 | "claim_farming_failed": "Farming claim failed", 95 | "countdown_farming_msg": "Claim time not reached, wait until later", 96 | "minute": "minutes" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/lang/vi.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": { 3 | "error_proxy": "Proxy lỗi, kiểm tra lại kết nối proxy, sẽ thử kết nối lại sau 30s", 4 | "error_proxy_log": "Lỗi kết nối proxy", 5 | "error_login_log": "Lỗi đăng nhập thất bại quá", 6 | "times": "lần", 7 | "write_log_error": "Ghi lỗi thất bại", 8 | "skip_task_message": "Tạm bỏ qua làm nhiệm vụ do lỗi server (sẽ tự động mở lại khi server ổn định)", 9 | "skip_game_message": "Tạm bỏ qua chơi game do có cập nhật mới, sẽ mở lại khi cập nhật xong", 10 | "copyright": "Tool phát triển và chia sẻ miễn phí bởi ZuyDD", 11 | "copyright2": "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 | "update_guide": "Cập nhật các tool mới nhất tại:", 13 | "buy_key_info": "Mua, nhận miễn phí API KEY tại:", 14 | "countdown_message": "Đã chạy hết các luồng, cần chờ:" 15 | }, 16 | "http": { 17 | "error_proxy": "Proxy lỗi, kiểm tra lại kết nối proxy" 18 | }, 19 | "server": { 20 | "get_json_github_error": "Lấy dữ liệu server zuydd thất bại", 21 | "noti": "Thông báo từ hệ thống", 22 | "noti_new_version": "Đã có phiên bản mới", 23 | "download_now": "tải ngay tại đây" 24 | }, 25 | "user": { 26 | "not_found": "Không tìm thấy dữ liệu user" 27 | }, 28 | "auth": { 29 | "run_account": "Chạy tài khoản", 30 | "login_error_msg": "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", 31 | "login_success": "Đăng nhập thành công: ", 32 | "points": "Số điểm:", 33 | "get_info_error_msg": "Lấy thông tin tài khoản thất bại", 34 | "refresh_token_error_msg": "Refresh token thất bại", 35 | "login_error": "Đăng nhập thất bại" 36 | }, 37 | "daily": { 38 | "checked": "Đã checkin hôm nay", 39 | "checkin_success": "Checkin thành công, phần thưởng", 40 | "checkin_failed": "Checkin thất bại", 41 | "game_turn": "lượt chơi game" 42 | }, 43 | "tribe": { 44 | "join_tribe_success": "Tham gia thành công Tribe", 45 | "join_tribe_failed": "Tham gia tribe thất bại" 46 | }, 47 | "task": { 48 | "get_task_error_msg": "Lấy danh sách nhiệm vụ thất bại", 49 | "task_completed": "Đã làm hết nhiệm vụ", 50 | "tasks_remaining": "Còn XXX nhiệm vụ YYY chưa hoàn thành", 51 | "tasks_completed_skip": "Đã làm hết các nhiệm vụ XXX (trừ các nhiệm phải làm tay bị bỏ qua)", 52 | "do_task_error_msg": "Làm nhiệm vụ XXX thất bại", 53 | "task_not_answer": "Nhiệm vụ XXX chưa có câu trả lời, chờ làm lại sau", 54 | "do_task_success": "Làm nhiệm vụ XXX thành công, phần thưởng", 55 | "claim_task_failed": "Claim phần thưởng nhiệm vụ XXX thất bại", 56 | "retry_task_error": "Chạy lại các nhiệm vụ bị lỗi...", 57 | "start_task_parent_msg": "Bắt đầu làm nhiệm vụ XXX, chờ hoàn thành hết các nhiệm vụ con để nhận thưởng", 58 | "task_done_msg": "Đã hoàn thành nhiệm vụ", 59 | "task_failed_msg": "Làm nhiệm vụ XXX thất bại", 60 | "not_completed_subtask": "Chưa hoàn thành hết các nhiệm vụ con của task" 61 | }, 62 | "invite": { 63 | "get_info_failed": "Lấy thông tin invite balance thất bại", 64 | "claim_success": "Claim điểm giới thiệu thành công, nhận được", 65 | "claim_failed": "Claim điểm giới thiệu thất bại" 66 | }, 67 | "game": { 68 | "can": "có thể", 69 | "notcan": "không thể", 70 | "claim_dogs": "nhặt DOGS", 71 | "game_remaining": "Còn XXX lượt chơi game", 72 | "no_api_key": "Không có API KEY, bỏ qua chơi game", 73 | "key_limit_used": "Đã dùng hết lượt chơi game của API KEY. Liên hệ Telegram @zuydd để mua thêm", 74 | "start_game_msg": "Bắt đầu chơi game, kết thúc và nhận thưởng sau", 75 | "start_game_failed": "Chơi game thất bại", 76 | "claim_success": "Chơi game xong, phần thưởng", 77 | "claim_failed": "Nhận thưởng chơi game thất bại", 78 | "not_found_server_free": "Không còn máy chủ miễn phí nào hoạt động!", 79 | "create_payload_failed": "Tạo payload thất bại", 80 | "used_turns": "Đã dùng hết lượt chơi game", 81 | "skip_play_game_msg": "Đã cài đặt không thể chơi game trong khoảng thời gian này, lần chơi tiếp theo sau", 82 | "minute": "phút" 83 | }, 84 | "key": { 85 | "key_invalid": "API KEY không hợp lệ, liên hệ Telegram @zuydd để nhận/mua API KEY", 86 | "key_remaining": "Còn XXX lượt sử dụng", 87 | "enter_key": "Nhập API KEY chơi game của bạn? Để trống nếu bạn không có (sẽ bỏ qua chơi game trong quá trình chạy tool)" 88 | }, 89 | "farming": { 90 | "start_farming_msg": "Đã bắt đầu farming, chờ claim sau", 91 | "time_farming": "480 phút", 92 | "start_farming_failed": "Bắt đầu farming thất bại", 93 | "claim_farming_success": "Claim farming thành công, phần thưởng", 94 | "claim_farming_failed": "Claim farming thất bại", 95 | "countdown_farming_msg": "Chưa tới thời gian claim, chờ sau", 96 | "minute": "phút" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/lang/id.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": { 3 | "error_proxy": "Proxy error, periksa kembali koneksi proxy, akan mencoba menghubungkan kembali setelah 30 detik", 4 | "error_proxy_log": "Kesalahan koneksi proxy", 5 | "error_login_log": "Kesalahan login gagal", 6 | "times": "kali", 7 | "write_log_error": "Gagal mencatat kesalahan", 8 | "skip_task_message": "Sementara melewati tugas karena kesalahan server (akan otomatis melanjutkan saat server stabil)", 9 | "skip_game_message": "Sementara menghentikan permainan karena ada pembaruan baru. Akan dibuka kembali setelah pembaruan selesai.", 10 | "copyright": "Alat ini dikembangkan dan dibagikan gratis oleh ZuyDD", 11 | "copyright2": "Setiap tindakan menjual alat dalam bentuk apa pun tidak diizinkan!", 12 | "update_guide": "Perbarui alat terbaru di:", 13 | "buy_key_info": "Beli atau dapatkan API KEY gratis di:", 14 | "countdown_message": "Semua alur telah selesai, tunggu:" 15 | }, 16 | "http": { 17 | "error_proxy": "Proxy error, periksa kembali koneksi proxy" 18 | }, 19 | "server": { 20 | "get_json_github_error": "Gagal mengambil data dari server zuydd", 21 | "noti": "Pemberitahuan dari sistem", 22 | "noti_new_version": "Versi baru tersedia", 23 | "download_now": "unduh di sini" 24 | }, 25 | "user": { 26 | "not_found": "Data pengguna tidak ditemukan" 27 | }, 28 | "auth": { 29 | "run_account": "Menjalankan akun", 30 | "login_error_msg": "Proses login gagal, silakan periksa informasi akun (mungkin perlu mendapatkan query_id baru). Sistem akan mencoba login kembali dalam 60 detik", 31 | "login_success": "Login berhasil: ", 32 | "points": "Jumlah poin:", 33 | "get_info_error_msg": "Gagal mengambil informasi akun", 34 | "refresh_token_error_msg": "Gagal memperbarui token", 35 | "login_error": "Login gagal" 36 | }, 37 | "daily": { 38 | "checked": "Sudah check-in hari ini", 39 | "checkin_success": "Check-in berhasil, hadiah", 40 | "checkin_failed": "Check-in gagal", 41 | "game_turn": "giliran bermain game" 42 | }, 43 | "tribe": { 44 | "join_tribe_success": "Berhasil bergabung dengan Tribe", 45 | "join_tribe_failed": "Gagal bergabung dengan Tribe" 46 | }, 47 | "task": { 48 | "get_task_error_msg": "Gagal mengambil daftar tugas", 49 | "task_completed": "Semua tugas telah selesai", 50 | "tasks_remaining": "Masih ada XXX tugas YYY yang belum selesai", 51 | "tasks_completed_skip": "Semua tugas XXX telah selesai (kecuali tugas manual yang dilewati)", 52 | "do_task_error_msg": "Gagal menjalankan tugas XXX", 53 | "task_not_answer": "Tugas XXX belum ada jawabannya, coba lagi nanti", 54 | "do_task_success": "Tugas XXX berhasil diselesaikan, hadiah", 55 | "claim_task_failed": "Gagal klaim hadiah untuk tugas XXX", 56 | "retry_task_error": "Mengulangi tugas yang gagal...", 57 | "start_task_parent_msg": "Memulai tugas XXX, tunggu hingga semua sub-tugas selesai untuk klaim hadiah", 58 | "task_done_msg": "Tugas selesai", 59 | "task_failed_msg": "Tugas XXX gagal", 60 | "not_completed_subtask": "Belum semua sub-tugas dari tugas selesai" 61 | }, 62 | "invite": { 63 | "get_info_failed": "Gagal mengambil informasi saldo undangan", 64 | "claim_success": "Klaim poin referensi berhasil, diterima", 65 | "claim_failed": "Gagal klaim poin referensi" 66 | }, 67 | "game": { 68 | "can": "dapat", 69 | "notcan": "tidak dapat", 70 | "claim_dogs": "ambil DOGS", 71 | "game_remaining": "Tersisa XXX giliran bermain game", 72 | "no_api_key": "Tidak ada API KEY, melewati permainan", 73 | "key_limit_used": "Batas giliran bermain game untuk API KEY telah habis. Hubungi Telegram @zuydd untuk membeli lebih lanjut", 74 | "start_game_msg": "Memulai game, akan selesai dan klaim hadiah setelah", 75 | "start_game_failed": "Permainan gagal", 76 | "claim_success": "Permainan selesai, hadiah", 77 | "claim_failed": "Gagal klaim hadiah permainan", 78 | "not_found_server_free": "Tidak ada server gratis yang berfungsi!", 79 | "create_payload_failed": "Gagal membuat payload", 80 | "used_turns": "Semua giliran bermain game telah habis", 81 | "skip_play_game_msg": "Diatur untuk tidak bermain dalam waktu ini, giliran berikutnya setelah", 82 | "minute": "menit" 83 | }, 84 | "key": { 85 | "key_invalid": "API KEY tidak valid, hubungi Telegram @zuydd untuk mendapatkan/membeli API KEY", 86 | "key_remaining": "Tersisa XXX penggunaan", 87 | "enter_key": "Masukkan API KEY untuk bermain game? Biarkan kosong jika tidak punya (akan melewati permainan saat alat dijalankan)" 88 | }, 89 | "farming": { 90 | "start_farming_msg": "Farming dimulai, klaim nanti", 91 | "time_farming": "480 menit", 92 | "start_farming_failed": "Gagal memulai farming", 93 | "claim_farming_success": "Klaim farming berhasil, hadiah", 94 | "claim_farming_failed": "Klaim farming gagal", 95 | "countdown_farming_msg": "Belum waktu untuk klaim, tunggu", 96 | "minute": "menit" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/lang/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": { 3 | "error_proxy": "Ошибка прокси, проверьте подключение прокси, повторная попытка подключения через 30 секунд", 4 | "error_proxy_log": "Ошибка подключения прокси", 5 | "error_login_log": "Ошибка входа", 6 | "times": "раз", 7 | "write_log_error": "Не удалось записать ошибку", 8 | "skip_task_message": "Задание временно пропущено из-за ошибки сервера (автоматически возобновится, когда сервер стабилизируется)", 9 | "skip_game_message": "Временно приостанавливаем игру из-за нового обновления. Игра будет доступна после завершения обновления.", 10 | "copyright": "Инструмент разработан и бесплатно распространяется ZuyDD", 11 | "copyright2": "Любая продажа этого инструмента в любой форме запрещена!", 12 | "update_guide": "Обновите последние инструменты здесь:", 13 | "buy_key_info": "Купить или получить бесплатный API KEY здесь:", 14 | "countdown_message": "Все потоки завершены, требуется ожидание:" 15 | }, 16 | "http": { 17 | "error_proxy": "Ошибка прокси, проверьте подключение прокси" 18 | }, 19 | "server": { 20 | "get_json_github_error": "Не удалось получить данные с сервера zuydd", 21 | "noti": "Системное уведомление", 22 | "noti_new_version": "Доступна новая версия", 23 | "download_now": "скачать здесь" 24 | }, 25 | "user": { 26 | "not_found": "Данные пользователя не найдены" 27 | }, 28 | "auth": { 29 | "run_account": "Запуск аккаунта", 30 | "login_error_msg": "Ошибка входа, пожалуйста, проверьте учетные данные (возможно, потребуется новый query_id). Система повторит попытку входа через 60 секунд", 31 | "login_success": "Успешный вход: ", 32 | "points": "Очки:", 33 | "get_info_error_msg": "Не удалось получить данные аккаунта", 34 | "refresh_token_error_msg": "Не удалось обновить токен", 35 | "login_error": "Ошибка входа" 36 | }, 37 | "daily": { 38 | "checked": "Сегодня уже выполнена регистрация", 39 | "checkin_success": "Регистрация успешна, награда", 40 | "checkin_failed": "Не удалось выполнить регистрацию", 41 | "game_turn": "игровой ход" 42 | }, 43 | "tribe": { 44 | "join_tribe_success": "Успешно присоединились к Tribe", 45 | "join_tribe_failed": "Не удалось присоединиться к Tribe" 46 | }, 47 | "task": { 48 | "get_task_error_msg": "Не удалось получить список задач", 49 | "task_completed": "Все задачи выполнены", 50 | "tasks_remaining": "Осталось XXX задач YYY невыполненными", 51 | "tasks_completed_skip": "Все задачи XXX выполнены (за исключением пропущенных ручных)", 52 | "do_task_error_msg": "Ошибка выполнения задачи XXX", 53 | "task_not_answer": "Задача XXX не имеет ответа, повторите позже", 54 | "do_task_success": "Задача XXX успешно выполнена, награда", 55 | "claim_task_failed": "Ошибка получения награды за задачу XXX", 56 | "retry_task_error": "Повтор выполнения ошибок задач...", 57 | "start_task_parent_msg": "Начало выполнения задачи XXX, дождитесь завершения всех подзадач для получения награды", 58 | "task_done_msg": "Задача выполнена", 59 | "task_failed_msg": "Ошибка выполнения задачи XXX", 60 | "not_completed_subtask": "Не все подзадачи выполнены" 61 | }, 62 | "invite": { 63 | "get_info_failed": "Не удалось получить информацию о балансе приглашений", 64 | "claim_success": "Успешное получение очков приглашений, получено", 65 | "claim_failed": "Не удалось получить очки приглашений" 66 | }, 67 | "game": { 68 | "can": "можно", 69 | "notcan": "нельзя", 70 | "claim_dogs": "собрать DOGS", 71 | "game_remaining": "Осталось XXX игровых ходов", 72 | "no_api_key": "Нет API KEY, пропуск игры", 73 | "key_limit_used": "Лимит игровых ходов для API KEY исчерпан. Свяжитесь с Telegram @zuydd для покупки", 74 | "start_game_msg": "Начало игры, завершение и получение награды позже", 75 | "start_game_failed": "Ошибка в игре", 76 | "claim_success": "Игра завершена, награда", 77 | "claim_failed": "Ошибка получения награды за игру", 78 | "not_found_server_free": "Нет доступных бесплатных серверов!", 79 | "create_payload_failed": "Не удалось создать payload", 80 | "used_turns": "Все игровые ходы использованы", 81 | "skip_play_game_msg": "Настроено пропускать игру в это время, следующий ход через", 82 | "minute": "минут" 83 | }, 84 | "key": { 85 | "key_invalid": "Недействительный API KEY, свяжитесь с Telegram @zuydd для получения/покупки API KEY", 86 | "key_remaining": "Осталось XXX использований", 87 | "enter_key": "Введите API KEY для игры? Оставьте пустым, если его нет (пропустит игру при запуске инструмента)" 88 | }, 89 | "farming": { 90 | "start_farming_msg": "Начало farming, ожидайте для получения награды", 91 | "time_farming": "480 минут", 92 | "start_farming_failed": "Не удалось начать farming", 93 | "claim_farming_success": "Успешное получение награды за farming", 94 | "claim_farming_failed": "Ошибка получения награды за farming", 95 | "countdown_farming_msg": "Время получения награды не наступило, подождите", 96 | "minute": "минут" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /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, lang, skipLog = false) { 9 | user.http.updateToken(null); 10 | user.http.updateRefreshToken(null); 11 | const body = { 12 | query: user.query_id, 13 | referralToken: user?.database?.ref, 14 | }; 15 | try { 16 | const { data } = await user.http.post( 17 | 3, 18 | "auth/provider/PROVIDER_TELEGRAM_MINI_APP", 19 | body 20 | ); 21 | if (data?.token) { 22 | return { 23 | access: data?.token?.access, 24 | refresh: data?.token?.refresh, 25 | }; 26 | } 27 | return null; 28 | } catch (error) { 29 | if (!skipLog) { 30 | user.log.logError( 31 | `${lang?.auth?.login_error}: ${error.response?.data?.message}` 32 | ); 33 | } 34 | return null; 35 | } 36 | } 37 | 38 | async refresh(user, lang, refreshToken, skipLog = false) { 39 | user.http.updateToken(null); 40 | user.http.updateRefreshToken(null); 41 | const body = { 42 | refresh: refreshToken, 43 | }; 44 | try { 45 | const { data } = await user.http.post(1, "auth/refresh", body); 46 | if (data?.access) { 47 | return { 48 | access: data.access, 49 | refresh: data.refresh, 50 | }; 51 | } 52 | return null; 53 | } catch (error) { 54 | if (!skipLog) { 55 | user.log.logError( 56 | `${lang?.auth?.refresh_token_error_msg}: ${error.response?.data?.message}` 57 | ); 58 | } 59 | return null; 60 | } 61 | } 62 | 63 | async handleLogin(user, lang) { 64 | console.log( 65 | `============== ${lang?.auth?.run_account} ${user.index} | ${user.info.fullName.green} ==============` 66 | ); 67 | 68 | let info = null; 69 | let token = fileHelper.getTokenById(user.info.id); 70 | 71 | if (token && !tokenHelper.isExpired(token.access)) { 72 | const info = { 73 | access: token.access, 74 | refresh: token.refresh, 75 | }; 76 | const profile = await this.handleAfterLogin(user, lang, info); 77 | return { 78 | status: 1, 79 | profile, 80 | }; 81 | } 82 | 83 | let infoLogin = await this.login(user, lang); 84 | 85 | if (infoLogin) { 86 | const profile = await this.handleAfterLogin(user, lang, infoLogin); 87 | return { 88 | status: 1, 89 | profile, 90 | }; 91 | } 92 | user.log.logError(lang?.auth?.login_error_msg); 93 | return { 94 | status: 0, 95 | profile: null, 96 | }; 97 | } 98 | 99 | async getProfile(user, lang) { 100 | try { 101 | const { data } = await user.http.get(0, "user/balance"); 102 | if (data) { 103 | return data; 104 | } 105 | return null; 106 | } catch (error) { 107 | user.log.logError( 108 | `${lang?.auth?.get_info_error_msg}: ${error.response?.data?.message}` 109 | ); 110 | return null; 111 | } 112 | } 113 | 114 | async reconnect(user, lang) { 115 | let info = null; 116 | let token = fileHelper.getTokenById(user.info.id); 117 | 118 | if ( 119 | token && 120 | tokenHelper.isExpired(token.access) && 121 | !tokenHelper.isExpired(token.refresh) 122 | ) { 123 | info = await this.refresh(user, lang, token.refresh, true); 124 | if (info) { 125 | await this.handleAfterReconnect(user, info); 126 | return 1; 127 | } 128 | } 129 | 130 | let infoLogin = await this.login(user, lang, true); 131 | 132 | if (infoLogin) { 133 | await this.handleAfterReconnect(user, infoLogin); 134 | return 1; 135 | } 136 | // user.log.logError( 137 | // "Quá trình kết nối lại 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)" 138 | // ); 139 | return 0; 140 | } 141 | 142 | async handleAfterLogin(user, lang, info) { 143 | const accessToken = info.access || null; 144 | const refreshToken = info.refresh || null; 145 | user.http.updateToken(accessToken); 146 | user.http.updateRefreshToken(refreshToken); 147 | fileHelper.saveToken(user.info.id, info); 148 | const profile = await this.getProfile(user, lang); 149 | if (profile) { 150 | user.log.log( 151 | colors.green(lang?.auth?.login_success) + 152 | `${lang?.auth?.points} ${ 153 | colors.green(Math.round(profile?.availableBalance)) + user.currency 154 | }` 155 | ); 156 | if (!user.http.isConnected) { 157 | user.http.updateConnect(true); 158 | setInterval(async () => { 159 | await this.reconnect(user, lang); 160 | }, 60 * 1000 * 20); 161 | } 162 | } 163 | return profile; 164 | } 165 | 166 | async handleAfterReconnect(user, info) { 167 | const accessToken = info.access || null; 168 | const refreshToken = info.refresh || null; 169 | user.http.updateToken(accessToken); 170 | user.http.updateRefreshToken(refreshToken); 171 | fileHelper.saveToken(user.info.id, info); 172 | // const profile = await this.getProfile(user); 173 | // if (profile) { 174 | // user.log.logSuccess("Kết nối lại thành công"); 175 | // } 176 | } 177 | } 178 | 179 | const authService = new AuthService(); 180 | export default authService; 181 | -------------------------------------------------------------------------------- /src/services/game.js: -------------------------------------------------------------------------------- 1 | import colors from "colors"; 2 | import dayjs from "dayjs"; 3 | import timezone from "dayjs/plugin/timezone.js"; 4 | import utc from "dayjs/plugin/utc.js"; 5 | import delayHelper from "../helpers/delay.js"; 6 | import generatorHelper from "../helpers/generator.js"; 7 | import { pack, proof } from "../helpers/payload-blum.js"; 8 | import authService from "./auth.js"; 9 | dayjs.extend(utc); 10 | dayjs.extend(timezone); 11 | 12 | class GameService { 13 | constructor() { 14 | this.API_KEY = ""; 15 | this.REMAINING_QUOTA = 99999; 16 | } 17 | 18 | setApiKey(apiKey) { 19 | this.API_KEY = apiKey; 20 | } 21 | 22 | setQuota(quota) { 23 | this.REMAINING_QUOTA = quota; 24 | } 25 | 26 | async playGame(user, lang, delay) { 27 | try { 28 | const { data } = await user.http.post(5, "game/play", {}); 29 | if (data.message === "another game in progress") { 30 | return 3; 31 | } 32 | 33 | if (data) { 34 | user.log.log( 35 | `${lang?.game?.start_game_msg}: ${colors.blue(delay + "s")}` 36 | ); 37 | return data.gameId; 38 | } else { 39 | throw new Error(`${lang?.game?.start_game_failed}: ${data.message}`); 40 | } 41 | } catch (error) { 42 | if (error.response?.data?.message === "not enough play passes") { 43 | return 2; 44 | } else { 45 | user.log.logError( 46 | `${lang?.game?.start_game_failed}: ${error.response?.data?.message}` 47 | ); 48 | } 49 | return null; 50 | } 51 | } 52 | 53 | async claimGame(user, lang, gameId) { 54 | const randomPoints = user?.database?.randomPoints || [150, 190]; 55 | const multiplierPoint = user?.database?.multiplierPoint || 1; 56 | let points = generatorHelper.randomInt(randomPoints[0], randomPoints[1]); 57 | const payload = await this.createPlayload(user, lang, gameId, points); 58 | if (!payload) return; 59 | 60 | const body = { payload }; 61 | try { 62 | const { text, data } = await user.http.post(5, "game/claim", body); 63 | 64 | if (data === "OK") { 65 | user.log.log( 66 | `${lang?.game?.claim_success}: ${colors.green( 67 | points * multiplierPoint + user.currency 68 | )}` 69 | ); 70 | return true; 71 | } else { 72 | throw new Error(`${lang?.game?.claim_failed}: ${data?.message}`); 73 | } 74 | } catch (error) { 75 | user.log.logError( 76 | `${lang?.game?.claim_failed}: ${error.response?.data?.message}` 77 | ); 78 | return false; 79 | } 80 | } 81 | 82 | async createPlayload(user, lang, gameId, points) { 83 | const resultProof = await proof(gameId); 84 | const MULTIPLIER_POINT = user?.database?.multiplierPoint || 1; 85 | 86 | const challenge = { 87 | id: generatorHelper.uuid(), 88 | ...resultProof, 89 | }; 90 | 91 | const earnedAssets = { 92 | CLOVER: { 93 | clicks: parseInt(points), 94 | }, 95 | FREEZE: { 96 | clicks: generatorHelper.randomInt(0, 2), 97 | }, 98 | BOMB: { 99 | clicks: 0, 100 | }, 101 | }; 102 | 103 | const totalPoints = { 104 | BP: { 105 | amount: parseInt(points) * MULTIPLIER_POINT, 106 | }, 107 | }; 108 | 109 | const resultPack = await pack(gameId, challenge, totalPoints, earnedAssets); 110 | 111 | const payload = resultPack; 112 | return payload; 113 | } 114 | 115 | checkTimePlayGame(time) { 116 | // Lấy giờ hiện tại theo múi giờ Việt Nam (UTC+7) 117 | const nowHour = dayjs().hour(); 118 | return !time.includes(nowHour); 119 | } 120 | 121 | getMinutesUntilNextStart(times) { 122 | // Lấy giờ hiện tại theo múi giờ Việt Nam (UTC+7) 123 | const currentHour = dayjs().hour(); 124 | times.sort((a, b) => a - b); 125 | 126 | let nextHour = currentHour + 1; 127 | 128 | while (times.includes(nextHour)) { 129 | nextHour++; 130 | } 131 | 132 | const now = dayjs(); 133 | 134 | const nextStartTime = now 135 | .set("hour", nextHour) 136 | .set("minute", 0) 137 | .set("second", 0); 138 | 139 | // Tính số phút từ giờ hiện tại đến lần bắt đầu tiếp theo 140 | return nextStartTime.diff(now, "minute"); 141 | } 142 | 143 | async handleGame(user, lang, playPasses, timePlayGame) { 144 | const isInTimeRange = this.checkTimePlayGame(timePlayGame); 145 | if (isInTimeRange) { 146 | const profile = await authService.getProfile(user, lang); 147 | if (profile) playPasses = profile?.playPasses; 148 | const msg = lang?.game?.game_remaining.replace( 149 | "XXX", 150 | colors.blue(playPasses) 151 | ); 152 | user.log.log(`${msg}`); 153 | let gameCount = playPasses || 0; 154 | let errorCount = 0; 155 | while (gameCount > 0) { 156 | if (errorCount > 3) { 157 | gameCount = 0; 158 | continue; 159 | } 160 | // if (!this.API_KEY) { 161 | // user.log.log(colors.yellow(lang?.game?.no_api_key)); 162 | // gameCount = 0; 163 | // continue; 164 | // } 165 | if (this.REMAINING_QUOTA <= 0) { 166 | user.log.log(colors.yellow(lang?.game?.key_limit_used)); 167 | gameCount = 0; 168 | continue; 169 | } 170 | await delayHelper.delay(2); 171 | const delay = 30 + generatorHelper.randomInt(5, 10); 172 | const gameId = await this.playGame(user, lang, delay); 173 | if (gameId === 2) { 174 | gameCount = 0; 175 | continue; 176 | } 177 | if (gameId === 3) { 178 | user.log.log( 179 | colors.yellow( 180 | "Đang trong một lượt chơi khác vui lòng chờ và thử lại" 181 | ) 182 | ); 183 | await delayHelper.delay(180); 184 | continue; 185 | } 186 | if (gameId) { 187 | errorCount = 0; 188 | 189 | await delayHelper.delay(delay); 190 | const statusClaim = await this.claimGame(user, lang, gameId); 191 | if (!statusClaim) { 192 | errorCount++; 193 | } 194 | if (statusClaim) gameCount--; 195 | } else { 196 | errorCount++; 197 | } 198 | } 199 | if (playPasses > 0) user.log.log(colors.magenta(lang?.game?.used_turns)); 200 | return -1; 201 | } else { 202 | const minutesUntilNextStart = this.getMinutesUntilNextStart(timePlayGame); 203 | user.log.log( 204 | colors.yellow( 205 | `${lang?.game?.skip_play_game_msg}: ${colors.blue( 206 | minutesUntilNextStart + ` ${lang?.game?.minute}` 207 | )}` 208 | ) 209 | ); 210 | return minutesUntilNextStart; 211 | } 212 | } 213 | } 214 | 215 | const gameService = new GameService(); 216 | export default gameService; 217 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tool Auto Blum NodeJS by ZuyDD 2 | 3 | **Tool developed and shared for free by ZuyDD** 4 | 5 | Facebook 6 | Telegram 7 | 8 | > [!WARNING] 9 | > Selling this tool in any form is not permitted! 10 | 11 | ## Purchase or receive a free API KEY at https://zuy-web.vercel.app/blum 12 | 13 | ## 🛠️ Installation Guide 14 | 15 | > NodeJS is required to be installed 16 | 17 | - Step 1: Download the latest version of the tool [here ⬇️](https://github.com/zuydd/blum/archive/refs/heads/main.zip) 18 | - Step 2: Extract the tool 19 | - Step 3: In the tool's directory (the folder containing `package.json`), run the command `npm install` to install the necessary libraries. 20 | 21 | ## 💾 How to Add Account Data 22 | 23 | > The tool supports both `user` and `query_id` 24 | 25 | > All data you need to input is in files located in the folder 📁 `src / data` 26 | 27 | - [users.txt](src/data/users.txt) : Contains a list of `user` or `query_id` for the accounts, each line represents an account. 28 | - [proxy.txt](src/data/proxy.txt) : Contains a list of proxies, each line corresponds to the account in the `users.txt` file. Leave empty if not using a proxy. 29 | - [token.json](src/data/token.json) : Contains the token list generated from `user` or `query_id`. Tokens will be automatically generated when you run the tool. 30 | 31 | > Proxy format: http://user:pass@ip:port 32 | 33 | ### Installation Commands 34 | 35 | 1. **Clone the repository:** 36 | ```bash 37 | git clone https://github.com/candyburst/blum.git 38 | ``` 39 | 40 | 2. **Navigate into the project directory:** 41 | ```bash 42 | cd blum 43 | ``` 44 | 45 | 3. **Install the required dependencies:** 46 | ```bash 47 | npm install 48 | ``` 49 | 50 | **Note:** If you encounter problems during `npm install`, try this command: 51 | ```bash 52 | npm install --ignore-scripts --no-bin-links 53 | ``` 54 | 55 | 4. **Edit the `users.txt` file to add queries or user info:** 56 | ```bash 57 | nano src/data/users.txt 58 | ``` 59 | 60 | Add the required information in the file. 61 | 62 | - To exit nano, use the following key sequence: 63 | - `Ctrl + X` 64 | - `Y` (to confirm save) 65 | - `Ctrl + M` (to return) 66 | 67 | 5. **Start the application:** 68 | ```bash 69 | npm run start 70 | ``` 71 | ## How to update and apply changes incase you face any error: 72 | **To update to the latest version:** 73 | ```bash 74 | git pull 75 | ``` 76 | 77 | **If you encounter problems during `git pull`, try this command:** 78 | ```bash 79 | mv src/data/users.txt src/data/user.txt && git stash && git pull && mv src/data/user.txt src/data/users.txt 80 | ``` 81 | # Important Note: You need to enter the pro key in the bot screen. Make sure you have the backup of the key. 82 | 83 | ## 🔄 Guide to Upgrade to the Latest Version When Facing Library Issues 84 | 85 | - **Step 1:** Download the latest version [here ⬇️](https://github.com/zuydd/blum/archive/refs/heads/main.zip) 86 | - **Step 2:** In the old tool directory, copy the [data](src/data) folder to another location to preserve the data (to avoid re-importing/re-creating). 87 | - **Step 3:** Extract the downloaded file. 88 | - **Step 4:** In the new tool directory (from the extracted file), copy the [src](src) folder and paste it over the `src` folder in the old tool directory (this updates the code). 89 | - **Step 5:** Copy back the `data` folder (from Step 2) and paste it over the `data` folder in the old tool directory. 90 | 91 | At this point, the old tool has been updated to the latest version and can be used as usual. 92 | 93 | Video tutorial: https://youtu.be/nwyrdEVxvPQ 94 | 95 | ## 🕹️ Features of the Tool 96 | 97 | - Automatic daily check-in 98 | - Automatically join tribes to earn an additional 10% bonus points 99 | - Automatically completes tasks 100 | - Automatically farms/claims rewards when it's time 101 | - Automatically plays games (requires API KEY, purchase or receive a free API KEY at https://zuy-web.vercel.app/blum) 102 | - Claims invite points 103 | - Auto-detects and reconnects proxies when there are errors. Add the proxy to the `proxy.txt` file corresponding to the account line. Leave empty or type "skip" for accounts without proxy. 104 | - Multi-thread support: run as many accounts as you want without blocking each other 105 | - Set game-playing times: the default is to always play games. If you want to avoid high-traffic periods, you can find the `TIME_PLAY_GAME = []` variable and input the hours you want to skip playing, e.g., entering [1, 2, 3, 8, 20] will skip game time during those hours. 106 | 107 | > [!WARNING] 108 | > 109 | > - Login, task, or game errors are due to Blum's server issues, not tool errors. Just let it be, and the tool will resume once the server is fixed. 110 | > - The server often experiences errors between 2 PM - 12 AM, so it's recommended to run the tool for the first time between 4 AM - 12 PM for smoother performance. 111 | 112 | ## 🌐 Language Settings 113 | 114 | - To change the tool's language, locate the variable `LANGUAGE = "vi"` in the [index.js](src/run/index.js) file and update it with the appropriate language code. 115 | - Supported languages: 116 | - `vi`: Vietnamese 117 | - `en`: English 118 | - `ru`: Russian 119 | - `id`: Indonesian 120 | - `zh`: Chinese 121 | 122 | ## ♾ Multi-Thread Setup 123 | 124 | - The tool will automatically run in multi-thread mode according to the number of accounts entered; no additional setup is required. 125 | - By default, in the first loop, each account (thread) will run 30 seconds apart to avoid spamming requests. You can adjust this by finding the `DELAY_ACC = 10` variable in the [index.js](src/run/index.js) file. 126 | 127 | ## ❌ Retry Mode for Errors 128 | 129 | - For proxy connection errors, the system will retry every 30 seconds. You can set a retry limit by finding the `MAX_RETRY_PROXY = 20` variable in the [index.js](src/run/index.js) file (default is 20). Once the retry limit is exceeded, the tool will stop auto operations for that account and log the error in [log.error.txt](src/data/log.error.txt). 130 | - For login failure errors, the system will retry every 60 seconds. You can set a retry limit by finding the `MAX_RETRY_LOGIN = 20` variable in the [index.js](src/run/index.js) file (default is 20). Once the retry limit is exceeded, the tool will stop auto operations for that account and log the error in [log.error.txt](src/data/log.error.txt). 131 | 132 | ## 🔄 Update History 133 | 134 | > When updating to a new version, simply copy the 📁 [data](src/data) folder from the old version to the new version and it will run without needing to re-enter the data. 135 | 136 | > Latest version: `v0.2.2` 137 | 138 |
139 | v0.2.2 - 📅 10/30/2024 140 | 141 | - Randomize server 142 | - Add language options 143 |
144 | 145 |
146 | v0.2.1 - 📅 10/23/2024 147 | 148 | - Changed the amount of DOGS received each time a game is played. 149 |
150 |
151 | v0.2.0 - 📅 10/23/2024 152 | 153 | - Fixed the issue where the game could not be skipped when there was no API KEY. 154 |
155 | 156 |
157 | v0.1.9 - 📅 10/23/2024 158 | 159 | - Fix tool stopping bug 160 |
161 |
162 | v0.1.8 - 📅 10/23/2024 163 | 164 | - Added fake device feature 165 | - Added API KEY system for playing games 166 |
167 | ... 168 | 169 | ## 🎁 Donate 170 | 171 | We are happy to share free scripts and open-source resources with the airdrop community. If you find our tools and documentation helpful and want to support us in maintaining and developing these projects, you can donate to support us. 172 | 173 | Your contribution will help us maintain quality service and continue to provide valuable resources to the airdrop community. We sincerely thank you for your support! 174 | 175 | Much love 😘😘😘 176 | 177 |
178 | QR Momo 179 | QR Binance 180 |
181 | -------------------------------------------------------------------------------- /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 farmingClass from "../services/farming.js"; 10 | import gameService from "../services/game.js"; 11 | import inviteClass from "../services/invite.js"; 12 | import server from "../services/server.js"; 13 | import taskService from "../services/task.js"; 14 | import tribeService from "../services/tribe.js"; 15 | import userService from "../services/user.js"; 16 | 17 | const VERSION = "v0.2.9"; 18 | // Change language 19 | // vi: Tiếng Việt 20 | // en: English 21 | // ru: русский язык 22 | // id: Bahasa Indonèsia 23 | // zh: 中国话 24 | const LANGUAGE = "en"; 25 | // Đ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) 26 | const DELAY_ACC = 10; 27 | // Đặ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 28 | const MAX_RETRY_PROXY = 20; 29 | // Đặ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 30 | const MAX_RETRY_LOGIN = 20; 31 | // Cài đặt thời gian KHÔNG chơi game tránh những khoảng thời gian lỗi server. ví dụ nhập [1, 2, 3, 8, 20] thì sẽ không chơi game trong các khung giờ 1, 2, 3, 8, 20 giờ 32 | const TIME_PLAY_GAME = []; 33 | // Cài đặt đếm ngược đến lần chạy tiếp theo 34 | const IS_SHOW_COUNTDOWN = true; 35 | const countdownList = []; 36 | 37 | const lang = fileHelper.getLang(LANGUAGE); 38 | // console.log(lang); 39 | 40 | let database = {}; 41 | setInterval(async () => { 42 | const data = await server.getData(); 43 | if (data) { 44 | database = data; 45 | server.checkVersion(VERSION, data); 46 | } 47 | }, generatorHelper.randomInt(20, 40) * 60 * 1000); 48 | 49 | const run = async (user, index) => { 50 | let countRetryProxy = 0; 51 | let countRetryLogin = 0; 52 | await delayHelper.delay((user.index - 1) * DELAY_ACC); 53 | while (true) { 54 | // Lấy lại dữ liệu từ server zuydd 55 | if (database?.ref) { 56 | user.database = database; 57 | } 58 | 59 | countdownList[index].running = true; 60 | // Kiểm tra kết nối proxy 61 | let isProxyConnected = false; 62 | while (!isProxyConnected) { 63 | const ip = await user.http.checkProxyIP(); 64 | if (ip === -1) { 65 | user.log.logError(lang?.index?.error_proxy); 66 | countRetryProxy++; 67 | if (countRetryProxy >= MAX_RETRY_PROXY) { 68 | break; 69 | } else { 70 | await delayHelper.delay(30); 71 | } 72 | } else { 73 | countRetryProxy = 0; 74 | isProxyConnected = true; 75 | } 76 | } 77 | try { 78 | if (countRetryProxy >= MAX_RETRY_PROXY) { 79 | const dataLog = `[No ${user.index} _ ID: ${ 80 | user.info.id 81 | } _ Time: ${dayjs().format("YYYY-MM-DDTHH:mm:ssZ[Z]")}] ${ 82 | lang?.index?.error_proxy_log 83 | } - ${user.proxy}`; 84 | fileHelper.writeLog("log.error.txt", dataLog); 85 | break; 86 | } 87 | 88 | if (countRetryLogin >= MAX_RETRY_LOGIN) { 89 | const dataLog = `[No ${user.index} _ ID: ${ 90 | user.info.id 91 | } _ Time: ${dayjs().format("YYYY-MM-DDTHH:mm:ssZ[Z]")}] ${ 92 | lang?.index?.error_login_log 93 | } ${MAX_RETRY_LOGIN} ${lang?.index?.times}`; 94 | fileHelper.writeLog("log.error.txt", dataLog); 95 | break; 96 | } 97 | } catch (error) { 98 | user.log.logError(lang?.index?.write_log_error); 99 | } 100 | 101 | // Đăng nhập tài khoản 102 | const login = await authService.handleLogin(user, lang); 103 | if (!login.status) { 104 | countRetryLogin++; 105 | await delayHelper.delay(60); 106 | continue; 107 | } else { 108 | countRetryLogin = 0; 109 | } 110 | 111 | await dailyService.handleCheckin(user, lang); 112 | await tribeService.handleTribe(user, lang); 113 | if (user.database?.skipHandleTask) { 114 | user.log.log(colors.yellow(lang?.index?.skip_task_message)); 115 | } else { 116 | await taskService.handleTask(user, lang); 117 | } 118 | 119 | await inviteClass.handleInvite(user, lang); 120 | let awaitTime = await farmingClass.handleFarming( 121 | user, 122 | lang, 123 | login.profile?.farming 124 | ); 125 | countdownList[index].time = (awaitTime + 1) * 60; 126 | countdownList[index].created = dayjs().unix(); 127 | 128 | let minutesUntilNextGameStart = -1; 129 | if (user.database?.skipHandleGame) { 130 | user.log.log(colors.yellow(lang?.index?.skip_game_message)); 131 | } else { 132 | minutesUntilNextGameStart = await gameService.handleGame( 133 | user, 134 | lang, 135 | login.profile?.playPasses, 136 | TIME_PLAY_GAME 137 | ); 138 | } 139 | 140 | if (minutesUntilNextGameStart !== -1) { 141 | const offset = dayjs().unix() - countdownList[index].created; 142 | const countdown = countdownList[index].time - offset; 143 | if (minutesUntilNextGameStart * 60 < countdown) { 144 | countdownList[index].time = (minutesUntilNextGameStart + 1) * 60; 145 | countdownList[index].created = dayjs().unix(); 146 | } 147 | } 148 | countdownList[index].running = false; 149 | await delayHelper.delay((awaitTime + 1) * 60); 150 | } 151 | }; 152 | 153 | console.log( 154 | colors.yellow.bold(`============= ${lang?.index?.copyright} =============`) 155 | ); 156 | console.log(lang?.index?.copyright2); 157 | console.log( 158 | `Telegram: ${colors.green( 159 | "https://t.me/zuydd" 160 | )} ___ Facebook: ${colors.blue("https://www.facebook.com/zuy.dd")}` 161 | ); 162 | console.log( 163 | `🚀 ${lang?.index?.update_guide} 👉 ${colors.gray( 164 | "https://github.com/zuydd" 165 | )} 👈` 166 | ); 167 | console.log(""); 168 | console.log( 169 | `${lang?.index?.buy_key_info} 👉 ${colors.blue( 170 | "https://zuy-web.vercel.app/blum" 171 | )}` 172 | ); 173 | console.log(""); 174 | console.log(""); 175 | 176 | await server.checkVersion(VERSION, lang); 177 | await server.showNoti(lang); 178 | console.log(""); 179 | const users = await userService.loadUser(lang); 180 | 181 | // await keyService.handleApiKey(lang); 182 | 183 | for (const [index, user] of users.entries()) { 184 | countdownList.push({ 185 | running: true, 186 | time: 480 * 60, 187 | created: dayjs().unix(), 188 | }); 189 | run(user, index); 190 | } 191 | 192 | if (IS_SHOW_COUNTDOWN && users.length) { 193 | let isLog = false; 194 | setInterval(async () => { 195 | const isPauseAll = !countdownList.some((item) => item.running === true); 196 | 197 | if (isPauseAll) { 198 | await delayHelper.delay(1); 199 | if (!isLog) { 200 | console.log( 201 | "=========================================================================================" 202 | ); 203 | isLog = true; 204 | } 205 | const minTimeCountdown = countdownList.reduce((minItem, currentItem) => { 206 | // bù trừ chênh lệch 207 | const currentOffset = dayjs().unix() - currentItem.created; 208 | const minOffset = dayjs().unix() - minItem.created; 209 | return currentItem.time - currentOffset < minItem.time - minOffset 210 | ? currentItem 211 | : minItem; 212 | }, countdownList[0]); 213 | const offset = dayjs().unix() - minTimeCountdown.created; 214 | const countdown = minTimeCountdown.time - offset; 215 | process.stdout.write("\x1b[K"); 216 | process.stdout.write( 217 | colors.white( 218 | `[${dayjs().format("DD-MM-YYYY HH:mm:ss")}] ${ 219 | lang?.index?.countdown_message 220 | } ${colors.blue(datetimeHelper.formatTime(countdown))} \r` 221 | ) 222 | ); 223 | } else { 224 | isLog = false; 225 | } 226 | }, 1000); 227 | 228 | process.on("SIGINT", () => { 229 | console.log(""); 230 | process.stdout.write("\x1b[K"); // Xóa dòng hiện tại từ con trỏ đến cuối dòng 231 | process.exit(); // Thoát khỏi quá trình 232 | }); 233 | } 234 | 235 | setInterval(() => {}, 1000); // Để script không kết thúc ngay 236 | -------------------------------------------------------------------------------- /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 getTask(user, lang) { 19 | try { 20 | const { data } = await user.http.get(4, "tasks"); 21 | if (data?.length) { 22 | return data; 23 | } else { 24 | throw new Error(`${lang?.task?.get_task_error_msg}: ${data?.message}`); 25 | } 26 | } catch (error) { 27 | return -1; 28 | } 29 | } 30 | 31 | async startTask(user, lang, task) { 32 | const param = `tasks/${task.id}/start`; 33 | let taskName = task.title; 34 | if (task.progressTarget) { 35 | taskName = `${task.title} ${task?.progressTarget?.target} ${task?.progressTarget?.postfix}`; 36 | } 37 | try { 38 | const { data } = await user.http.post(4, param, {}); 39 | if (data && data.status === "STARTED") { 40 | return task.validationType === "KEYWORD" 41 | ? "READY_FOR_VERIFY" 42 | : "READY_FOR_CLAIM"; 43 | } else { 44 | const msg = lang?.task?.do_task_error_msg.replace( 45 | "XXX", 46 | colors.blue(taskName) 47 | ); 48 | throw new Error(`${msg}: ${data?.message}`); 49 | } 50 | } catch (error) { 51 | const msg = lang?.task?.do_task_error_msg.replace( 52 | "XXX", 53 | `${colors.blue(taskName)} - ${colors.gray(`[${task.id}]`)}` 54 | ); 55 | user.log.logError(`${msg}: ${error.response?.data?.message}`); 56 | return "NOT_STARTED"; 57 | } 58 | } 59 | async verifyTask(user, lang, task) { 60 | let taskName = task.title; 61 | const param = `tasks/${task.id}/validate`; 62 | if (!user?.database?.tasks) { 63 | const msg = lang?.task?.task_not_answer.replace( 64 | "XXX", 65 | colors.blue(taskName) 66 | ); 67 | user.log.log(colors.yellow(msg)); 68 | return; 69 | } 70 | const taskDatabase = user?.database?.tasks.find((t) => t.id === task.id); 71 | if (!taskDatabase) { 72 | const msg = lang?.task?.task_not_answer.replace( 73 | "XXX", 74 | colors.blue(taskName) 75 | ); 76 | user.log.log(colors.yellow(msg)); 77 | return; 78 | } 79 | const body = { keyword: taskDatabase.answer }; 80 | 81 | try { 82 | const { data } = await user.http.post(4, param, body); 83 | if (data && data.status === "READY_FOR_CLAIM") { 84 | return "READY_FOR_CLAIM"; 85 | } else { 86 | throw new Error( 87 | `Xác nhận nhiệm vụ ${colors.blue(taskName)} thất bại: ${ 88 | data?.message 89 | }` 90 | ); 91 | } 92 | } catch (error) { 93 | user.log.logError( 94 | `Xác nhận nhiệm vụ ${colors.blue(taskName)} - ${colors.gray( 95 | `[${task.id}]` 96 | )} thất bại: ${error.response?.data?.message}` 97 | ); 98 | return "NOT_STARTED"; 99 | } 100 | } 101 | 102 | async claimTask(user, lang, task, showLog = true) { 103 | const param = `tasks/${task.id}/claim`; 104 | let taskName = task.title; 105 | if (task.progressTarget) { 106 | taskName = `${task.title} ${task.target} ${task.postfix}`; 107 | } 108 | try { 109 | const res = await user.http.post(4, param, {}); 110 | const { data } = res; 111 | 112 | if (data && data.status === "FINISHED") { 113 | if (showLog) { 114 | const msg = lang?.task?.do_task_success.replace( 115 | "XXX", 116 | colors.blue(taskName) 117 | ); 118 | user.log.log( 119 | `${msg}: ${colors.green(task.reward.value + user.currency)}` 120 | ); 121 | } 122 | return true; 123 | } else { 124 | const msg = lang?.task?.claim_task_failed.replace( 125 | "XXX", 126 | `${colors.blue(taskName)} - ${colors.gray(`[${task.id}]`)}` 127 | ); 128 | user.log.logError(`${msg}: ${data?.message}`); 129 | } 130 | } catch (error) { 131 | if (showLog) { 132 | const msg = lang?.task?.claim_task_failed.replace( 133 | "XXX", 134 | `${colors.blue(taskName)} - ${colors.gray(`[${task.id}]`)}` 135 | ); 136 | user.log.logError(`${msg}: ${error.response?.data?.message}`); 137 | } 138 | return false; 139 | } 140 | } 141 | 142 | async handleTaskBasic(user, lang, dataTasks, title) { 143 | const skipTasks = user?.database?.skipTasks || [ 144 | "39391eb2-f031-4954-bd8a-e7aecbb1f192", 145 | ]; 146 | 147 | let tasksMerge = []; 148 | for (const item of dataTasks) { 149 | tasksMerge = tasksMerge.concat(item.tasks); 150 | } 151 | 152 | const tasksFilter = tasksMerge.filter( 153 | (task) => 154 | !skipTasks.includes(task.id) && 155 | task.status !== "FINISHED" && 156 | !task.isHidden 157 | ); 158 | const tasks = this.removeDuplicatesTask(tasksFilter); 159 | 160 | const taskList = tasks.filter( 161 | (task) => task.type !== "PROGRESS_TARGET" && task.status !== "STARTED" 162 | ); 163 | 164 | if (taskList.length) { 165 | const msg = lang?.task?.tasks_remaining 166 | .replace("XXX", colors.blue(taskList.length)) 167 | .replace("YYY", colors.blue(title)); 168 | user.log.log(msg); 169 | } else { 170 | const msg = lang?.task?.tasks_completed_skip.replace( 171 | "XXX", 172 | colors.blue(title) 173 | ); 174 | user.log.log(colors.magenta(msg)); 175 | } 176 | 177 | await this.handleSingleTask(user, lang, tasks); 178 | } 179 | 180 | async handleTaskMultiple(user, lang, dataTasks, title) { 181 | const skipTasks = user?.database?.skipTasks || [ 182 | "39391eb2-f031-4954-bd8a-e7aecbb1f192", 183 | ]; 184 | 185 | const tasksFilter = dataTasks.filter((task) => { 186 | if (task?.subTasks) { 187 | return ( 188 | !skipTasks.includes(task.id) && 189 | !task.subTasks.every((task) => task.status === "FINISHED") && 190 | !task.isHidden 191 | ); 192 | } else { 193 | return ( 194 | !skipTasks.includes(task.id) && 195 | !task.status === "FINISHED" && 196 | !task.isHidden 197 | ); 198 | } 199 | }); 200 | 201 | if (tasksFilter.length) { 202 | const msg = lang?.task?.tasks_remaining 203 | .replace("XXX", colors.blue(tasksFilter.length)) 204 | .replace("YYY", colors.blue(title)); 205 | user.log.log(msg); 206 | } else { 207 | const msg = lang?.task?.tasks_completed_skip.replace( 208 | "XXX", 209 | colors.blue(title) 210 | ); 211 | user.log.log(colors.magenta(msg)); 212 | } 213 | 214 | for (const taskParent of tasksFilter) { 215 | const msg = lang?.task?.start_task_parent_msg.replace( 216 | "XXX", 217 | colors.blue(taskParent.title) 218 | ); 219 | user.log.log(msg); 220 | 221 | if (!taskParent?.subTasks) { 222 | await this.handleSingleTask(user, lang, [taskParent]); 223 | } else { 224 | let countDone = await this.handleSubTask( 225 | user, 226 | lang, 227 | taskParent?.subTasks, 228 | taskParent?.title 229 | ); 230 | if (countDone === taskParent?.subTasks?.length) { 231 | // await this.claimTask(user, taskParent); 232 | const msg = lang?.task?.tasks_completed_skip.replace( 233 | "XXX", 234 | colors.blue(taskParent.title) 235 | ); 236 | user.log.log(colors.magenta(msg)); 237 | } else { 238 | user.log.log( 239 | colors.yellow( 240 | `${lang?.task?.not_completed_subtask} ${colors.blue( 241 | taskParent.title 242 | )}` 243 | ) 244 | ); 245 | } 246 | } 247 | } 248 | } 249 | 250 | async handleSingleTask(user, lang, tasks) { 251 | const tasksErrorStart = []; 252 | const tasksErrorClaim = []; 253 | for (const task of tasks) { 254 | let complete = task.status; 255 | if (complete === "NOT_STARTED" && task.type !== "PROGRESS_TARGET") { 256 | complete = await this.startTask(user, lang, task); 257 | if (complete === "NOT_STARTED") { 258 | tasksErrorStart.push(task); 259 | } 260 | await delayHelper.delay(5); 261 | } 262 | 263 | if (complete === "READY_FOR_VERIFY") { 264 | complete = await this.verifyTask(user, lang, task); 265 | } 266 | if (complete === "READY_FOR_CLAIM") { 267 | const statusClaim = await this.claimTask(user, lang, task); 268 | if (!statusClaim) { 269 | tasksErrorClaim.push(task); 270 | } 271 | } 272 | } 273 | 274 | if (tasksErrorStart.length || tasksErrorClaim.length) { 275 | user.log.log(colors.magenta(lang?.task?.retry_task_error)); 276 | await delayHelper.delay(20); 277 | for (const task of tasksErrorStart) { 278 | let complete = task.status; 279 | if (complete === "NOT_STARTED" && task.type !== "PROGRESS_TARGET") { 280 | complete = await this.startTask(user, lang, task); 281 | } 282 | if (complete === "READY_FOR_VERIFY") { 283 | complete = await this.verifyTask(user, lang, task); 284 | } 285 | if (complete === "READY_FOR_CLAIM") { 286 | await this.claimTask(user, lang, task); 287 | } 288 | } 289 | for (const task of tasksErrorClaim) { 290 | await this.claimTask(user, lang, task); 291 | } 292 | } 293 | } 294 | 295 | async handleSubTask(user, lang, subTask, nameTaskParent) { 296 | let countDone = 0; 297 | for (const task of subTask) { 298 | let complete = task.status; 299 | if (complete === "FINISHED") { 300 | countDone++; 301 | user.log.log( 302 | `✔️ ${lang?.task?.task_done_msg} ${colors.blue( 303 | nameTaskParent + " --> " + task.title 304 | )}` 305 | ); 306 | continue; 307 | } 308 | if (complete === "NOT_STARTED" && task.type !== "PROGRESS_TARGET") { 309 | complete = await this.startTask(user, lang, task); 310 | await delayHelper.delay(10); 311 | } 312 | if (complete === "READY_FOR_VERIFY") { 313 | complete = await this.verifyTask(user, lang, task); 314 | } 315 | if (complete === "READY_FOR_CLAIM" || complete === "STARTED") { 316 | const statusClaim = await this.claimTask(user, lang, task, false); 317 | if (statusClaim) { 318 | countDone++; 319 | user.log.log( 320 | `✔️ ${lang?.task?.task_done_msg} ${colors.blue( 321 | nameTaskParent + " --> " + task.title 322 | )}` 323 | ); 324 | } else { 325 | const msg = lang?.task?.task_failed_msg.replace( 326 | "XXX", 327 | `${colors.blue(nameTaskParent + " --> " + task.title)}` 328 | ); 329 | user.log.logError(msg); 330 | } 331 | } 332 | } 333 | return countDone; 334 | } 335 | 336 | async handleTask(user, lang) { 337 | const maxRetryGetTask = 10; 338 | let countGetTask = 0; 339 | let tasks = await this.getTask(user, lang); 340 | 341 | while (tasks === -1 && countGetTask <= maxRetryGetTask) { 342 | countGetTask++; 343 | tasks = await this.getTask(user, lang); 344 | } 345 | 346 | if (countGetTask > maxRetryGetTask) { 347 | user.log.logError(lang?.task?.get_task_error_msg); 348 | return; 349 | } 350 | 351 | for (const task of tasks) { 352 | if (task?.sectionType === "DEFAULT") { 353 | await this.handleTaskBasic( 354 | user, 355 | lang, 356 | task.subSections, 357 | task.sectionType 358 | ); 359 | } else { 360 | await this.handleTaskMultiple(user, lang, task.tasks, task.sectionType); 361 | } 362 | } 363 | 364 | user.log.log(colors.magenta(lang?.task?.task_completed)); 365 | } 366 | } 367 | 368 | const taskService = new TaskService(); 369 | export default taskService; 370 | -------------------------------------------------------------------------------- /src/helpers/payload-blum.js: -------------------------------------------------------------------------------- 1 | import crypto from "crypto"; 2 | import { readFile } from "fs/promises"; 3 | 4 | const v = global || void 0; 5 | 6 | async function loadWasm() { 7 | const n = $(); // Tạo đối tượng imports 8 | const wasmBuffer = await readFile(new URL("./game2.wasm", import.meta.url)); 9 | const { instance, module } = await WebAssembly.instantiate(wasmBuffer, n); 10 | return instance; 11 | } 12 | 13 | // Export hàm khởi tạo WASM 14 | export async function initializeWasm() { 15 | const wasmInstance = await loadWasm(); 16 | return wasmInstance; 17 | } 18 | 19 | let _; 20 | const g = new Array(128).fill(void 0); 21 | g.push(void 0, null, !0, !1); 22 | // function c(e) { 23 | // return g[e]; 24 | // } 25 | function i(e) { 26 | return g[e]; 27 | } 28 | // let m = g.length; 29 | let I = g.length; 30 | // function M(e) { 31 | // e < 132 || ((g[e] = m), (m = e)); 32 | // } 33 | function W(e) { 34 | e < 132 || ((g[e] = I), (I = e)); 35 | } 36 | // function w(e) { 37 | // const n = c(e); 38 | // return M(e), n; 39 | // } 40 | function l(e) { 41 | const n = i(e); 42 | return W(e), n; 43 | } 44 | // let d = 0, 45 | // p = null; 46 | let w = 0, 47 | m = null; 48 | // function S() { 49 | // return ( 50 | // (p === null || p.byteLength === 0) && (p = new Uint8Array(_.memory.buffer)), 51 | // p 52 | // ); 53 | // } 54 | 55 | function S() { 56 | return ( 57 | (m === null || m.byteLength === 0) && (m = new Uint8Array(_.memory.buffer)), 58 | m 59 | ); 60 | } 61 | 62 | const typeofTextEncoder = typeof TextEncoder; 63 | // const O = typeof TextEncoder < "u" ? new TextEncoder("utf-8") : { 64 | // encode: () => { 65 | // throw Error("TextEncoder not available") 66 | // } 67 | // } 68 | const O = 69 | typeofTextEncoder < "u" 70 | ? new TextEncoder("utf-8") 71 | : { 72 | encode: () => { 73 | throw Error("TextEncoder not available"); 74 | }, 75 | }; 76 | const M = 77 | typeof O.encodeInto == "function" 78 | ? function (e, n) { 79 | return O.encodeInto(e, n); 80 | } 81 | : function (e, n) { 82 | const t = O.encode(e); 83 | return ( 84 | n.set(t), 85 | { 86 | read: e.length, 87 | written: t.length, 88 | } 89 | ); 90 | }; 91 | 92 | function p(e, n, t) { 93 | if (t === void 0) { 94 | const a = O.encode(e), 95 | y = n(a.length, 1) >>> 0; 96 | return ( 97 | S() 98 | .subarray(y, y + a.length) 99 | .set(a), 100 | (w = a.length), 101 | y 102 | ); 103 | } 104 | let r = e.length, 105 | o = n(r, 1) >>> 0; 106 | const f = S(); 107 | let s = 0; 108 | for (; s < r; s++) { 109 | const a = e.charCodeAt(s); 110 | if (a > 127) break; 111 | f[o + s] = a; 112 | } 113 | if (s !== r) { 114 | s !== 0 && (e = e.slice(s)), (o = t(o, r, (r = s + e.length * 3), 1) >>> 0); 115 | const a = S().subarray(o + s, o + r), 116 | y = M(e, a); 117 | (s += y.written), (o = t(o, r, s, 1) >>> 0); 118 | } 119 | return (w = s), o; 120 | } 121 | 122 | function h(e) { 123 | return e == null; 124 | } 125 | let d = null; 126 | function u() { 127 | return ( 128 | (d === null || 129 | d.buffer.detached === !0 || 130 | (d.buffer.detached === void 0 && d.buffer !== _.memory.buffer)) && 131 | (d = new DataView(_.memory.buffer)), 132 | d 133 | ); 134 | } 135 | 136 | function c(e) { 137 | I === g.length && g.push(g.length + 1); 138 | const n = I; 139 | return (I = g[n]), (g[n] = e), n; 140 | } 141 | 142 | const typeofTextDecoder = typeof TextDecoder; 143 | function createDecode() { 144 | return typeofTextDecoder < "u" 145 | ? new TextDecoder("utf-8", { 146 | ignoreBOM: true, 147 | fatal: true, 148 | }) 149 | : { 150 | decode: () => { 151 | throw new Error("TextDecoder not available"); 152 | }, 153 | }; 154 | } 155 | const E = createDecode(); 156 | typeofTextDecoder < "u" && E.decode(); 157 | function A(e, n) { 158 | return (e = e >>> 0), E.decode(S().subarray(e, e + n)); 159 | } 160 | 161 | function D(e) { 162 | try { 163 | const o = _.__wbindgen_add_to_stack_pointer(-16), 164 | f = p(e, _.__wbindgen_malloc, _.__wbindgen_realloc), 165 | s = w; 166 | _.proof(o, f, s); 167 | var n = u().getInt32(o + 4 * 0, !0), 168 | t = u().getInt32(o + 4 * 1, !0), 169 | r = u().getInt32(o + 4 * 2, !0); 170 | if (r) throw l(t); 171 | return l(n); 172 | } finally { 173 | _.__wbindgen_add_to_stack_pointer(16); 174 | } 175 | } 176 | function F(e, n, t, r) { 177 | let o, f; 178 | try { 179 | const j = _.__wbindgen_add_to_stack_pointer(-16), 180 | N = p(e, _.__wbindgen_malloc, _.__wbindgen_realloc), 181 | V = w; 182 | _.pack(j, N, V, c(n), c(t), c(r)); 183 | var s = u().getInt32(j + 4 * 0, !0), 184 | a = u().getInt32(j + 4 * 1, !0), 185 | y = u().getInt32(j + 4 * 2, !0), 186 | C = u().getInt32(j + 4 * 3, !0), 187 | x = s, 188 | U = a; 189 | if (C) throw ((x = 0), (U = 0), l(y)); 190 | return (o = x), (f = U), A(x, U); 191 | } finally { 192 | _.__wbindgen_add_to_stack_pointer(16), _.__wbindgen_free(o, f, 1); 193 | } 194 | } 195 | 196 | function b(e, n) { 197 | try { 198 | return e.apply(this, n); 199 | } catch (t) { 200 | _.__wbindgen_exn_store(c(t)); 201 | } 202 | } 203 | 204 | function $() { 205 | const e = {}; 206 | return ( 207 | (e.wbg = {}), 208 | (e.wbg.__wbindgen_string_get = function (n, t) { 209 | const r = i(t), 210 | o = typeof r == "string" ? r : void 0; 211 | var f = h(o) ? 0 : p(o, _.__wbindgen_malloc, _.__wbindgen_realloc), 212 | s = w; 213 | u().setInt32(n + 4 * 1, s, !0), u().setInt32(n + 4 * 0, f, !0); 214 | }), 215 | (e.wbg.__wbindgen_object_drop_ref = function (n) { 216 | l(n); 217 | }), 218 | (e.wbg.__wbindgen_error_new = function (n, t) { 219 | const r = new Error(A(n, t)); 220 | return c(r); 221 | }), 222 | (e.wbg.__wbindgen_is_bigint = function (n) { 223 | return typeof i(n) == "bigint"; 224 | }), 225 | (e.wbg.__wbindgen_bigint_from_u64 = function (n) { 226 | const t = BigInt.asUintN(64, n); 227 | return c(t); 228 | }), 229 | (e.wbg.__wbindgen_jsval_eq = function (n, t) { 230 | return i(n) === i(t); 231 | }), 232 | (e.wbg.__wbindgen_is_object = function (n) { 233 | const t = i(n); 234 | return typeof t == "object" && t !== null; 235 | }), 236 | (e.wbg.__wbindgen_is_undefined = function (n) { 237 | return i(n) === void 0; 238 | }), 239 | (e.wbg.__wbindgen_in = function (n, t) { 240 | return i(n) in i(t); 241 | }), 242 | (e.wbg.__wbg_crypto_1d1f22824a6a080c = function (n) { 243 | const t = i(n).crypto; 244 | return c(crypto); 245 | }), 246 | (e.wbg.__wbg_process_4a72847cc503995b = function (n) { 247 | const t = i(n).process; 248 | return c(t); 249 | }), 250 | (e.wbg.__wbg_versions_f686565e586dd935 = function (n) { 251 | const t = i(n).versions; 252 | return c(t); 253 | }), 254 | (e.wbg.__wbg_node_104a2ff8d6ea03a2 = function (n) { 255 | const t = i(n).node; 256 | return c(t); 257 | }), 258 | (e.wbg.__wbindgen_is_string = function (n) { 259 | return typeof i(n) == "string"; 260 | }), 261 | (e.wbg.__wbg_require_cca90b1a94a0255b = function () { 262 | return b(function () { 263 | const n = module.require; 264 | return c(n); 265 | }, arguments); 266 | }), 267 | (e.wbg.__wbindgen_is_function = function (n) { 268 | return typeof i(n) == "function"; 269 | }), 270 | (e.wbg.__wbindgen_string_new = function (n, t) { 271 | const r = A(n, t); 272 | return c(r); 273 | }), 274 | (e.wbg.__wbg_msCrypto_eb05e62b530a1508 = function (n) { 275 | const t = i(n).msCrypto; 276 | return c(t); 277 | }), 278 | (e.wbg.__wbg_randomFillSync_5c9c955aa56b6049 = function () { 279 | return b(function (n, t) { 280 | i(n).randomFillSync(l(t)); 281 | }, arguments); 282 | }), 283 | (e.wbg.__wbg_getRandomValues_3aa56aa6edec874c = function () { 284 | return b(function (n, t) { 285 | i(n).getRandomValues(i(t)); 286 | }, arguments); 287 | }), 288 | (e.wbg.__wbindgen_jsval_loose_eq = function (n, t) { 289 | return i(n) == i(t); 290 | }), 291 | (e.wbg.__wbindgen_boolean_get = function (n) { 292 | const t = i(n); 293 | return typeof t == "boolean" ? (t ? 1 : 0) : 2; 294 | }), 295 | (e.wbg.__wbindgen_number_get = function (n, t) { 296 | const r = i(t), 297 | o = typeof r == "number" ? r : void 0; 298 | u().setFloat64(n + 8 * 1, h(o) ? 0 : o, !0), 299 | u().setInt32(n + 4 * 0, !h(o), !0); 300 | }), 301 | (e.wbg.__wbindgen_as_number = function (n) { 302 | return +i(n); 303 | }), 304 | (e.wbg.__wbindgen_number_new = function (n) { 305 | return c(n); 306 | }), 307 | (e.wbg.__wbindgen_object_clone_ref = function (n) { 308 | const t = i(n); 309 | return c(t); 310 | }), 311 | (e.wbg.__wbg_getwithrefkey_edc2c8960f0f1191 = function (n, t) { 312 | const r = i(n)[i(t)]; 313 | return c(r); 314 | }), 315 | (e.wbg.__wbg_set_f975102236d3c502 = function (n, t, r) { 316 | i(n)[l(t)] = l(r); 317 | }), 318 | (e.wbg.__wbg_String_b9412f8799faab3e = function (n, t) { 319 | const r = String(i(t)), 320 | o = p(r, _.__wbindgen_malloc, _.__wbindgen_realloc), 321 | f = w; 322 | u().setInt32(n + 4 * 1, f, !0), u().setInt32(n + 4 * 0, o, !0); 323 | }), 324 | (e.wbg.__wbg_get_3baa728f9d58d3f6 = function (n, t) { 325 | const r = i(n)[t >>> 0]; 326 | return c(r); 327 | }), 328 | (e.wbg.__wbg_length_ae22078168b726f5 = function (n) { 329 | return i(n).length; 330 | }), 331 | (e.wbg.__wbg_newnoargs_76313bd6ff35d0f2 = function (n, t) { 332 | const r = new Function(A(n, t)); 333 | return c(r); 334 | }), 335 | (e.wbg.__wbg_next_de3e9db4440638b2 = function (n) { 336 | const t = i(n).next; 337 | return c(t); 338 | }), 339 | (e.wbg.__wbg_next_f9cb570345655b9a = function () { 340 | return b(function (n) { 341 | const t = i(n).next(); 342 | return c(t); 343 | }, arguments); 344 | }), 345 | (e.wbg.__wbg_done_bfda7aa8f252b39f = function (n) { 346 | return i(n).done; 347 | }), 348 | (e.wbg.__wbg_value_6d39332ab4788d86 = function (n) { 349 | const t = i(n).value; 350 | return c(t); 351 | }), 352 | (e.wbg.__wbg_iterator_888179a48810a9fe = function () { 353 | return c(Symbol.iterator); 354 | }), 355 | (e.wbg.__wbg_get_224d16597dbbfd96 = function () { 356 | return b(function (n, t) { 357 | const r = Reflect.get(i(n), i(t)); 358 | return c(r); 359 | }, arguments); 360 | }), 361 | (e.wbg.__wbg_call_1084a111329e68ce = function () { 362 | return b(function (n, t) { 363 | const r = i(n).call(i(t)); 364 | return c(r); 365 | }, arguments); 366 | }), 367 | (e.wbg.__wbg_new_525245e2b9901204 = function () { 368 | const n = new Object(); 369 | return c(n); 370 | }), 371 | (e.wbg.__wbg_self_3093d5d1f7bcb682 = function () { 372 | return b(function () { 373 | const n = global; 374 | return c(n); 375 | }, arguments); 376 | }), 377 | (e.wbg.__wbg_window_3bcfc4d31bc012f8 = function () { 378 | return b(function () { 379 | const n = global; 380 | return c(n); 381 | }, arguments); 382 | }), 383 | (e.wbg.__wbg_globalThis_86b222e13bdf32ed = function () { 384 | return b(function () { 385 | const n = global; 386 | return c(n); 387 | }, arguments); 388 | }), 389 | (e.wbg.__wbg_global_e5a3fe56f8be9485 = function () { 390 | return b(function () { 391 | const n = v.global; 392 | return c(n); 393 | }, arguments); 394 | }), 395 | (e.wbg.__wbg_instanceof_ArrayBuffer_61dfc3198373c902 = function (n) { 396 | let t; 397 | try { 398 | t = i(n) instanceof ArrayBuffer; 399 | } catch { 400 | t = !1; 401 | } 402 | return t; 403 | }), 404 | (e.wbg.__wbg_call_89af060b4e1523f2 = function () { 405 | return b(function (n, t, r) { 406 | const o = i(n).call(i(t), i(r)); 407 | return c(o); 408 | }, arguments); 409 | }), 410 | (e.wbg.__wbg_isSafeInteger_7f1ed56200d90674 = function (n) { 411 | return Number.isSafeInteger(i(n)); 412 | }), 413 | (e.wbg.__wbg_entries_7a0e06255456ebcd = function (n) { 414 | const t = Object.entries(i(n)); 415 | return c(t); 416 | }), 417 | (e.wbg.__wbg_buffer_b7b08af79b0b0974 = function (n) { 418 | const t = i(n).buffer; 419 | return c(t); 420 | }), 421 | (e.wbg.__wbg_newwithbyteoffsetandlength_8a2cb9ca96b27ec9 = function ( 422 | n, 423 | t, 424 | r 425 | ) { 426 | const o = new Uint8Array(i(n), t >>> 0, r >>> 0); 427 | return c(o); 428 | }), 429 | (e.wbg.__wbg_new_ea1883e1e5e86686 = function (n) { 430 | const t = new Uint8Array(i(n)); 431 | return c(t); 432 | }), 433 | (e.wbg.__wbg_set_d1e79e2388520f18 = function (n, t, r) { 434 | i(n).set(i(t), r >>> 0); 435 | }), 436 | (e.wbg.__wbg_length_8339fcf5d8ecd12e = function (n) { 437 | return i(n).length; 438 | }), 439 | (e.wbg.__wbg_instanceof_Uint8Array_247a91427532499e = function (n) { 440 | let t; 441 | try { 442 | t = i(n) instanceof Uint8Array; 443 | } catch { 444 | t = !1; 445 | } 446 | return t; 447 | }), 448 | (e.wbg.__wbg_newwithlength_ec548f448387c968 = function (n) { 449 | const t = new Uint8Array(n >>> 0); 450 | return c(t); 451 | }), 452 | (e.wbg.__wbg_subarray_7c2e3576afe181d1 = function (n, t, r) { 453 | const o = i(n).subarray(t >>> 0, r >>> 0); 454 | return c(o); 455 | }), 456 | (e.wbg.__wbindgen_bigint_get_as_i64 = function (n, t) { 457 | const r = i(t), 458 | o = typeof r == "bigint" ? r : void 0; 459 | u().setBigInt64(n + 8 * 1, h(o) ? BigInt(0) : o, !0), 460 | u().setInt32(n + 4 * 0, !h(o), !0); 461 | }), 462 | (e.wbg.__wbindgen_debug_string = function (n, t) { 463 | const r = T(i(t)), 464 | o = p(r, _.__wbindgen_malloc, _.__wbindgen_realloc), 465 | f = w; 466 | u().setInt32(n + 4 * 1, f, !0), u().setInt32(n + 4 * 0, o, !0); 467 | }), 468 | (e.wbg.__wbindgen_throw = function (n, t) { 469 | throw new Error(A(n, t)); 470 | }), 471 | (e.wbg.__wbindgen_memory = function () { 472 | const n = _.memory; 473 | return c(n); 474 | }), 475 | e 476 | ); 477 | } 478 | 479 | function L(e, n) { 480 | return ( 481 | (_ = e.exports), (R.__wbindgen_wasm_module = n), (d = null), (m = null), _ 482 | ); 483 | } 484 | async function R(e) { 485 | if (_ !== void 0) return _; 486 | const n = $(); 487 | const wasmBuffer = await readFile(new URL("./game2.wasm", import.meta.url)); 488 | const { instance: t, module: r } = await WebAssembly.instantiate( 489 | wasmBuffer, 490 | n 491 | ); 492 | return L(t, r); 493 | } 494 | let k; 495 | const q = async () => { 496 | k === void 0 && (k = R()), await k; 497 | }; 498 | 499 | export async function proof(payload) { 500 | await q(); 501 | 502 | return D(payload); 503 | } 504 | 505 | export async function pack(gameId, challenge, totalPoints, earnedAssets) { 506 | await q(); 507 | return F(gameId, challenge, totalPoints, earnedAssets); 508 | } 509 | -------------------------------------------------------------------------------- /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.2.1" 26 | resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-9.2.1.tgz#677c49dee399c9063f31e0c93f0f37bddc67add1" 27 | integrity sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg== 28 | dependencies: 29 | "@inquirer/figures" "^1.0.6" 30 | "@inquirer/type" "^2.0.0" 31 | "@types/mute-stream" "^0.0.4" 32 | "@types/node" "^22.5.5" 33 | "@types/wrap-ansi" "^3.0.0" 34 | ansi-escapes "^4.3.2" 35 | cli-width "^4.1.0" 36 | mute-stream "^1.0.0" 37 | signal-exit "^4.1.0" 38 | strip-ansi "^6.0.1" 39 | wrap-ansi "^6.2.0" 40 | yoctocolors-cjs "^2.1.2" 41 | 42 | "@inquirer/editor@^2.2.0": 43 | version "2.2.0" 44 | resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-2.2.0.tgz#a41eb7b151bd9a6bc3c0b69219d02d82547bc387" 45 | integrity sha512-9KHOpJ+dIL5SZli8lJ6xdaYLPPzB8xB9GZItg39MBybzhxA16vxmszmQFrRwbOA918WA2rvu8xhDEg/p6LXKbw== 46 | dependencies: 47 | "@inquirer/core" "^9.1.0" 48 | "@inquirer/type" "^1.5.3" 49 | external-editor "^3.1.0" 50 | 51 | "@inquirer/expand@^2.3.0": 52 | version "2.3.0" 53 | resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-2.3.0.tgz#afc44aee303315a85563e9d0275e658f0ee0e701" 54 | integrity sha512-qnJsUcOGCSG1e5DTOErmv2BPQqrtT6uzqn1vI/aYGiPKq+FgslGZmtdnXbhuI7IlT7OByDoEEqdnhUnVR2hhLw== 55 | dependencies: 56 | "@inquirer/core" "^9.1.0" 57 | "@inquirer/type" "^1.5.3" 58 | yoctocolors-cjs "^2.1.2" 59 | 60 | "@inquirer/figures@^1.0.5", "@inquirer/figures@^1.0.6": 61 | version "1.0.7" 62 | resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.7.tgz#d050ccc0eabfacc0248c4ff647a9dfba1b01594b" 63 | integrity sha512-m+Trk77mp54Zma6xLkLuY+mvanPxlE4A7yNKs2HBiyZ4UkVs28Mv5c/pgWrHeInx+USHeX/WEPzjrWrcJiQgjw== 64 | 65 | "@inquirer/input@^2.3.0": 66 | version "2.3.0" 67 | resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-2.3.0.tgz#9b99022f53780fecc842908f3f319b52a5a16865" 68 | integrity sha512-XfnpCStx2xgh1LIRqPXrTNEEByqQWoxsWYzNRSEUxJ5c6EQlhMogJ3vHKu8aXuTacebtaZzMAHwEL0kAflKOBw== 69 | dependencies: 70 | "@inquirer/core" "^9.1.0" 71 | "@inquirer/type" "^1.5.3" 72 | 73 | "@inquirer/number@^1.1.0": 74 | version "1.1.0" 75 | resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-1.1.0.tgz#4dac004021ea67c89552a261564f103a494cac96" 76 | integrity sha512-ilUnia/GZUtfSZy3YEErXLJ2Sljo/mf9fiKc08n18DdwdmDbOzRcTv65H1jjDvlsAuvdFXf4Sa/aL7iw/NanVA== 77 | dependencies: 78 | "@inquirer/core" "^9.1.0" 79 | "@inquirer/type" "^1.5.3" 80 | 81 | "@inquirer/password@^2.2.0": 82 | version "2.2.0" 83 | resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-2.2.0.tgz#0b6f26336c259c8a9e5f5a3f2e1a761564f764ba" 84 | integrity sha512-5otqIpgsPYIshqhgtEwSspBQE40etouR8VIxzpJkv9i0dVHIpyhiivbkH9/dGiMLdyamT54YRdGJLfl8TFnLHg== 85 | dependencies: 86 | "@inquirer/core" "^9.1.0" 87 | "@inquirer/type" "^1.5.3" 88 | ansi-escapes "^4.3.2" 89 | 90 | "@inquirer/prompts@^5.5.0": 91 | version "5.5.0" 92 | resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-5.5.0.tgz#5805aa15a13180017829aa31d071fd37a43b735d" 93 | integrity sha512-BHDeL0catgHdcHbSFFUddNzvx/imzJMft+tWDPwTm3hfu8/tApk1HrooNngB2Mb4qY+KaRWF+iZqoVUPeslEog== 94 | dependencies: 95 | "@inquirer/checkbox" "^2.5.0" 96 | "@inquirer/confirm" "^3.2.0" 97 | "@inquirer/editor" "^2.2.0" 98 | "@inquirer/expand" "^2.3.0" 99 | "@inquirer/input" "^2.3.0" 100 | "@inquirer/number" "^1.1.0" 101 | "@inquirer/password" "^2.2.0" 102 | "@inquirer/rawlist" "^2.3.0" 103 | "@inquirer/search" "^1.1.0" 104 | "@inquirer/select" "^2.5.0" 105 | 106 | "@inquirer/rawlist@^2.3.0": 107 | version "2.3.0" 108 | resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-2.3.0.tgz#6b2c0da39c1cd855af5608b2d627681cdac7277d" 109 | integrity sha512-zzfNuINhFF7OLAtGHfhwOW2TlYJyli7lOUoJUXw/uyklcwalV6WRXBXtFIicN8rTRK1XTiPWB4UY+YuW8dsnLQ== 110 | dependencies: 111 | "@inquirer/core" "^9.1.0" 112 | "@inquirer/type" "^1.5.3" 113 | yoctocolors-cjs "^2.1.2" 114 | 115 | "@inquirer/search@^1.1.0": 116 | version "1.1.0" 117 | resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-1.1.0.tgz#665928cac2326b9501ddafbb8606ce4823b3106b" 118 | integrity sha512-h+/5LSj51dx7hp5xOn4QFnUaKeARwUCLs6mIhtkJ0JYPBLmEYjdHSYh7I6GrLg9LwpJ3xeX0FZgAG1q0QdCpVQ== 119 | dependencies: 120 | "@inquirer/core" "^9.1.0" 121 | "@inquirer/figures" "^1.0.5" 122 | "@inquirer/type" "^1.5.3" 123 | yoctocolors-cjs "^2.1.2" 124 | 125 | "@inquirer/select@^2.5.0": 126 | version "2.5.0" 127 | resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-2.5.0.tgz#345c6908ecfaeef3d84ddd2f9feb2f487c558efb" 128 | integrity sha512-YmDobTItPP3WcEI86GvPo+T2sRHkxxOq/kXmsBjHS5BVXUgvgZ5AfJjkvQvZr03T81NnI3KrrRuMzeuYUQRFOA== 129 | dependencies: 130 | "@inquirer/core" "^9.1.0" 131 | "@inquirer/figures" "^1.0.5" 132 | "@inquirer/type" "^1.5.3" 133 | ansi-escapes "^4.3.2" 134 | yoctocolors-cjs "^2.1.2" 135 | 136 | "@inquirer/type@^1.5.3": 137 | version "1.5.5" 138 | resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.5.5.tgz#303ea04ce7ad2e585b921b662b3be36ef7b4f09b" 139 | integrity sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA== 140 | dependencies: 141 | mute-stream "^1.0.0" 142 | 143 | "@inquirer/type@^2.0.0": 144 | version "2.0.0" 145 | resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-2.0.0.tgz#08fa513dca2cb6264fe1b0a2fabade051444e3f6" 146 | integrity sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag== 147 | dependencies: 148 | mute-stream "^1.0.0" 149 | 150 | "@types/mute-stream@^0.0.4": 151 | version "0.0.4" 152 | resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" 153 | integrity sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow== 154 | dependencies: 155 | "@types/node" "*" 156 | 157 | "@types/node@*", "@types/node@^22.5.5": 158 | version "22.7.8" 159 | resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.8.tgz#a1dbf0dc5f71bdd2642fc89caef65d58747ce825" 160 | integrity sha512-a922jJy31vqR5sk+kAdIENJjHblqcZ4RmERviFsER4WJcEONqxKcjNOlk0q7OUfrF5sddT+vng070cdfMlrPLg== 161 | dependencies: 162 | undici-types "~6.19.2" 163 | 164 | "@types/wrap-ansi@^3.0.0": 165 | version "3.0.0" 166 | resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" 167 | integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== 168 | 169 | agent-base@^7.0.2: 170 | version "7.1.1" 171 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" 172 | integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== 173 | dependencies: 174 | debug "^4.3.4" 175 | 176 | ansi-escapes@^4.3.2: 177 | version "4.3.2" 178 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" 179 | integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== 180 | dependencies: 181 | type-fest "^0.21.3" 182 | 183 | ansi-regex@^5.0.1: 184 | version "5.0.1" 185 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 186 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 187 | 188 | ansi-styles@^4.0.0: 189 | version "4.3.0" 190 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 191 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 192 | dependencies: 193 | color-convert "^2.0.1" 194 | 195 | asynckit@^0.4.0: 196 | version "0.4.0" 197 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 198 | integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== 199 | 200 | axios@^1.7.2: 201 | version "1.7.7" 202 | resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" 203 | integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== 204 | dependencies: 205 | follow-redirects "^1.15.6" 206 | form-data "^4.0.0" 207 | proxy-from-env "^1.1.0" 208 | 209 | chardet@^0.7.0: 210 | version "0.7.0" 211 | resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" 212 | integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== 213 | 214 | cli-width@^4.1.0: 215 | version "4.1.0" 216 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" 217 | integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== 218 | 219 | cliui@^8.0.1: 220 | version "8.0.1" 221 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" 222 | integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== 223 | dependencies: 224 | string-width "^4.2.0" 225 | strip-ansi "^6.0.1" 226 | wrap-ansi "^7.0.0" 227 | 228 | color-convert@^2.0.1: 229 | version "2.0.1" 230 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 231 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 232 | dependencies: 233 | color-name "~1.1.4" 234 | 235 | color-name@~1.1.4: 236 | version "1.1.4" 237 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 238 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 239 | 240 | colors@^1.4.0: 241 | version "1.4.0" 242 | resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" 243 | integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== 244 | 245 | combined-stream@^1.0.8: 246 | version "1.0.8" 247 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 248 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 249 | dependencies: 250 | delayed-stream "~1.0.0" 251 | 252 | crypto@^1.0.1: 253 | version "1.0.1" 254 | resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037" 255 | integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig== 256 | 257 | dayjs@^1.11.12: 258 | version "1.11.13" 259 | resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" 260 | integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== 261 | 262 | debug@4, debug@^4.3.4: 263 | version "4.3.7" 264 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" 265 | integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== 266 | dependencies: 267 | ms "^2.1.3" 268 | 269 | delayed-stream@~1.0.0: 270 | version "1.0.0" 271 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 272 | integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== 273 | 274 | emoji-regex@^8.0.0: 275 | version "8.0.0" 276 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 277 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 278 | 279 | escalade@^3.1.1: 280 | version "3.2.0" 281 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" 282 | integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== 283 | 284 | external-editor@^3.1.0: 285 | version "3.1.0" 286 | resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" 287 | integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== 288 | dependencies: 289 | chardet "^0.7.0" 290 | iconv-lite "^0.4.24" 291 | tmp "^0.0.33" 292 | 293 | fingerprintjs2@^2.1.4: 294 | version "2.1.4" 295 | resolved "https://registry.yarnpkg.com/fingerprintjs2/-/fingerprintjs2-2.1.4.tgz#a39deb947aa187c098306a0b5dd41ceaa2e15fc5" 296 | integrity sha512-veP2yVsnYvjDVkzZMyIEwpqCAQfsBLH+U4PK5MlFAnLjZrttbdRqEArE1fPcnJFz5oS5CrdONbsV7J6FGpIJEQ== 297 | 298 | follow-redirects@^1.15.6: 299 | version "1.15.9" 300 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" 301 | integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== 302 | 303 | form-data@^4.0.0: 304 | version "4.0.1" 305 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" 306 | integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== 307 | dependencies: 308 | asynckit "^0.4.0" 309 | combined-stream "^1.0.8" 310 | mime-types "^2.1.12" 311 | 312 | get-caller-file@^2.0.5: 313 | version "2.0.5" 314 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 315 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 316 | 317 | he@^1.2.0: 318 | version "1.2.0" 319 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 320 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 321 | 322 | https-proxy-agent@^7.0.5: 323 | version "7.0.5" 324 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" 325 | integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== 326 | dependencies: 327 | agent-base "^7.0.2" 328 | debug "4" 329 | 330 | iconv-lite@^0.4.24: 331 | version "0.4.24" 332 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 333 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 334 | dependencies: 335 | safer-buffer ">= 2.1.2 < 3" 336 | 337 | inquirer@^10.1.8: 338 | version "10.2.2" 339 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-10.2.2.tgz#36b866443a9fb2747151766c01ef9c8ba2d585eb" 340 | integrity sha512-tyao/4Vo36XnUItZ7DnUXX4f1jVao2mSrleV/5IPtW/XAEA26hRVsbc68nuTEKWcr5vMP/1mVoT2O7u8H4v1Vg== 341 | dependencies: 342 | "@inquirer/core" "^9.1.0" 343 | "@inquirer/prompts" "^5.5.0" 344 | "@inquirer/type" "^1.5.3" 345 | "@types/mute-stream" "^0.0.4" 346 | ansi-escapes "^4.3.2" 347 | mute-stream "^1.0.0" 348 | run-async "^3.0.0" 349 | rxjs "^7.8.1" 350 | 351 | is-fullwidth-code-point@^3.0.0: 352 | version "3.0.0" 353 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 354 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 355 | 356 | mime-db@1.52.0: 357 | version "1.52.0" 358 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 359 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 360 | 361 | mime-types@^2.1.12: 362 | version "2.1.35" 363 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 364 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 365 | dependencies: 366 | mime-db "1.52.0" 367 | 368 | ms@^2.1.3: 369 | version "2.1.3" 370 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 371 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 372 | 373 | mute-stream@^1.0.0: 374 | version "1.0.0" 375 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" 376 | integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== 377 | 378 | os-tmpdir@~1.0.2: 379 | version "1.0.2" 380 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 381 | integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== 382 | 383 | proxy-from-env@^1.1.0: 384 | version "1.1.0" 385 | resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" 386 | integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== 387 | 388 | require-directory@^2.1.1: 389 | version "2.1.1" 390 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 391 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 392 | 393 | run-async@^3.0.0: 394 | version "3.0.0" 395 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-3.0.0.tgz#42a432f6d76c689522058984384df28be379daad" 396 | integrity sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q== 397 | 398 | rxjs@^7.8.1: 399 | version "7.8.1" 400 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" 401 | integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== 402 | dependencies: 403 | tslib "^2.1.0" 404 | 405 | "safer-buffer@>= 2.1.2 < 3": 406 | version "2.1.2" 407 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 408 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 409 | 410 | signal-exit@^4.1.0: 411 | version "4.1.0" 412 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" 413 | integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== 414 | 415 | string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: 416 | version "4.2.3" 417 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 418 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 419 | dependencies: 420 | emoji-regex "^8.0.0" 421 | is-fullwidth-code-point "^3.0.0" 422 | strip-ansi "^6.0.1" 423 | 424 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 425 | version "6.0.1" 426 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 427 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 428 | dependencies: 429 | ansi-regex "^5.0.1" 430 | 431 | tmp@^0.0.33: 432 | version "0.0.33" 433 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" 434 | integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== 435 | dependencies: 436 | os-tmpdir "~1.0.2" 437 | 438 | tslib@^2.1.0: 439 | version "2.8.0" 440 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b" 441 | integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA== 442 | 443 | type-fest@^0.21.3: 444 | version "0.21.3" 445 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" 446 | integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== 447 | 448 | undici-types@~6.19.2: 449 | version "6.19.8" 450 | resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" 451 | integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== 452 | 453 | wrap-ansi@^6.2.0: 454 | version "6.2.0" 455 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" 456 | integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== 457 | dependencies: 458 | ansi-styles "^4.0.0" 459 | string-width "^4.1.0" 460 | strip-ansi "^6.0.0" 461 | 462 | wrap-ansi@^7.0.0: 463 | version "7.0.0" 464 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 465 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 466 | dependencies: 467 | ansi-styles "^4.0.0" 468 | string-width "^4.1.0" 469 | strip-ansi "^6.0.0" 470 | 471 | ws@^8.18.0: 472 | version "8.18.0" 473 | resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" 474 | integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== 475 | 476 | y18n@^5.0.5: 477 | version "5.0.8" 478 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 479 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 480 | 481 | yargs-parser@^21.1.1: 482 | version "21.1.1" 483 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" 484 | integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== 485 | 486 | yargs@^17.7.2: 487 | version "17.7.2" 488 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" 489 | integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== 490 | dependencies: 491 | cliui "^8.0.1" 492 | escalade "^3.1.1" 493 | get-caller-file "^2.0.5" 494 | require-directory "^2.1.1" 495 | string-width "^4.2.3" 496 | y18n "^5.0.5" 497 | yargs-parser "^21.1.1" 498 | 499 | yoctocolors-cjs@^2.1.2: 500 | version "2.1.2" 501 | resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242" 502 | integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA== 503 | --------------------------------------------------------------------------------