UNPKG

zixineabra

Version:

A Telegram utility bot for managing sessions, logging in accounts, and retrieving WebView data.

554 lines (497 loc) 15.9 kB
const fs = require("fs").promises; const axios = require("axios"); const colors = require("colors"); const { DateTime } = require("luxon"); const config = require("./config/major-config"); const { spawn } = require("child_process"); const printBanner = require("./banner/galkurta-banner.js"); printBanner(); class Major { constructor() { this.baseUrl = "https://major.glados.app/api"; this.endpoints = { auth: `${this.baseUrl}/auth/tg/`, userInfo: `${this.baseUrl}/users/`, streak: `${this.baseUrl}/user-visits/streak/`, visit: `${this.baseUrl}/user-visits/visit/`, roulette: `${this.baseUrl}/roulette/`, holdCoins: `${this.baseUrl}/bonuses/coins/`, tasks: `${this.baseUrl}/tasks/`, swipeCoin: `${this.baseUrl}/swipe_coin/`, durov: `${this.baseUrl}/durov/`, }; this.totalBalance = 0; this.durovPayloadUrl = "./json/major.json"; this.useTelegramBot = config.useTelegramBot; this.summary = { totalAccounts: 0, totalBalance: 0, }; this.botProcess = null; } headers(token = null) { const headers = { Accept: "application/json, text/plain, */*", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en-US,en;q=0.6", "Content-Type": "application/json", Origin: "https://major.glados.app/reward", Referer: "https://major.glados.app/", "Sec-Ch-Ua": '"Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"', "Sec-Ch-Ua-Mobile": "?0", "Sec-Ch-Ua-Platform": '"Windows"', "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36", }; if (token) { headers["Authorization"] = `Bearer ${token}`; } return headers; } log(msg, type = "info") { const colorMap = { acc: colors.cyan, info: colors.bold.blue, success: colors.bold.green, warning: colors.bold.yellow, error: colors.bold.red, }; console.log(colorMap[type](msg)); } async waitWithCountdown(seconds) { for (let i = seconds; i >= 0; i--) { const hours = Math.floor(i / 3600); const minutes = Math.floor((i % 3600) / 60); const secs = i % 60; process.stdout.write( `\rWaiting ${hours}h:${minutes}m:${secs}s to continue...` ); await this.sleep(1000); } process.stdout.write("\r" + " ".repeat(60) + "\r"); } async apiRequest(method, url, data = null, token = null) { try { const config = { method, url, headers: this.headers(token), ...(data && { data }), }; const response = await axios(config); return response.data; } catch (error) { if (error.response && error.response.data) { return error.response.data; } this.log(`Error in API request: ${error.message}`, "error"); return null; } } async authenticate(init_data) { const result = await this.apiRequest("post", this.endpoints.auth, { init_data, }); if (!result) { this.log("Error during authentication", "error"); } return result; } async getUserInfo(userId, token) { const result = await this.apiRequest( "get", `${this.endpoints.userInfo}${userId}/`, null, token ); if (result) { this.totalBalance += result.rating; } return result; } async getStreak(token) { return await this.apiRequest("get", this.endpoints.streak, null, token); } async postVisit(token) { return await this.apiRequest("post", this.endpoints.visit, {}, token); } async spinRoulette(token) { const result = await this.apiRequest( "post", this.endpoints.roulette, {}, token ); if (result && result.rating_award > 0) { this.totalBalance += result.rating_award; } return result; } async holdCoins(token) { const coins = Math.floor(Math.random() * (950 - 900 + 1)) + 900; return await this.apiRequest( "post", this.endpoints.holdCoins, { coins }, token ); } async swipeCoin(token) { const getResult = await this.apiRequest( "get", this.endpoints.swipeCoin, null, token ); if (getResult.success) { const coins = Math.floor(Math.random() * (1300 - 1000 + 1)) + 1000; return await this.apiRequest( "post", this.endpoints.swipeCoin, { coins }, token ); } return null; } async getDailyTasks(token) { return await this.apiRequest( "get", `${this.endpoints.tasks}?is_daily=false`, null, token ); } async completeTask(token, task) { return await this.apiRequest( "post", this.endpoints.tasks, { task_id: task.id }, token ); } formatBlockedTime(timestamp) { return DateTime.fromSeconds(timestamp) .setZone("system") .toLocaleString(DateTime.DATETIME_MED); } async sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } async getDurovPayload() { try { if (this.useTelegramBot) { const data = await fs.readFile(this.durovPayloadUrl, "utf8"); const durovData = JSON.parse(data); const today = DateTime.now().setZone("system").toFormat("dd/MM/yyyy"); const todayPayload = durovData.find((item) => item.date === today); return todayPayload || null; } else { const rl = require("readline").createInterface({ input: process.stdin, output: process.stdout, }); const today = DateTime.now().setZone("system").toFormat("dd/MM/yyyy"); console.log( `Enter Durov puzzle choices for ${today} (comma-separated, e.g., 7,4,12,5):` ); const choices = await new Promise((resolve) => { rl.question("", (answer) => { rl.close(); resolve(answer.split(",").map(Number)); }); }); return { date: today, tasks: [ { choice_1: choices[0], choice_2: choices[1], choice_3: choices[2], choice_4: choices[3], }, ], }; } } catch (error) { this.log(`Error reading Durov payload: ${error.message}`, "error"); return null; } } async handleDurovTask(token) { try { const getResult = await this.apiRequest( "get", this.endpoints.durov, null, token ); if (getResult.detail && getResult.detail.blocked_until) { const blockedTime = this.formatBlockedTime( getResult.detail.blocked_until ); this.log( `Durov puzzle search failed, need to invite ${getResult.detail.need_invites} more friends or wait until ${blockedTime}`, "warning" ); return; } if (!getResult.success) { this.log("Durov GET request failed", "error"); return; } const payloadData = await this.getDurovPayload(); if (!payloadData) { this.log("No Durov payload for today", "warning"); return; } const payload = payloadData.tasks[0]; const postResult = await this.apiRequest( "post", this.endpoints.durov, payload, token ); if ( postResult.correct && JSON.stringify(postResult.correct) === JSON.stringify(Object.values(payload)) ) { this.log("Durov puzzle search successful", "success"); } else { this.log("Durov puzzle search unsuccessful", "error"); } } catch (error) { if ( error.response && error.response.status === 400 && error.response.data.detail ) { const detail = error.response.data.detail; if (detail.blocked_until) { const blockedTime = this.formatBlockedTime(detail.blocked_until); this.log( `Durov puzzle search failed, need to invite ${detail.need_invites} more friends or wait until ${blockedTime}`, "warning" ); } else { this.log(`Error in Durov task: ${detail}`, "error"); } } else { this.log(`Error in Durov task: ${error.message}`, "error"); } } } async saveSummary() { const formattedSummary = { totalAccounts: this.summary.totalAccounts.toLocaleString(), totalBalance: Number(this.summary.totalBalance).toLocaleString( undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2, } ), }; await fs.writeFile( "summary.json", JSON.stringify(formattedSummary, null, 2) ); } async processAccount(init_data, accountIndex) { const authResult = await this.authenticate(init_data); if (!authResult || !authResult.access_token || !authResult.user) { this.log( `Unable to authenticate account ${ accountIndex + 1 }. Auth result: ${JSON.stringify(authResult)}`, "error" ); return; } const { access_token, user } = authResult; if (!user.id || !user.first_name) { this.log( `Invalid user data for account ${ accountIndex + 1 }. User data: ${JSON.stringify(user)}`, "error" ); return; } const { id, first_name } = user; this.log(`\n[ Account ${accountIndex + 1} | ${first_name} ]`, "acc"); try { const userInfo = await this.getUserInfo(id, access_token); if (!userInfo) { throw new Error("Failed to get user info"); } const streakInfo = await this.getStreak(access_token); const visitResult = await this.postVisit(access_token); const rouletteResult = await this.spinRoulette(access_token); const holdCoinsResult = await this.holdCoins(access_token); const swipeCoinResult = await this.swipeCoin(access_token); this.log(`Stars: ${userInfo.rating}`, "info"); this.log( `Streak: ${streakInfo ? streakInfo.streak : "N/A"} days`, "info" ); if (visitResult && visitResult.is_increased) { this.log(`Check-in: Success (Day ${visitResult.streak})`, "success"); } else if (visitResult) { this.log( `Check-in: Already done (Day ${visitResult.streak})`, "warning" ); } else { this.log("Check-in: Failed", "error"); } if (rouletteResult && rouletteResult.rating_award > 0) { this.log(`Roulette: +${rouletteResult.rating_award} stars`, "success"); } else if ( rouletteResult && rouletteResult.detail && rouletteResult.detail.blocked_until ) { this.log( `Roulette: Blocked until ${this.formatBlockedTime( rouletteResult.detail.blocked_until )}`, "warning" ); } else { this.log("Roulette: Failed", "error"); } if (holdCoinsResult && holdCoinsResult.success) { this.log(`Hold Coins: Success`, "success"); } else if ( holdCoinsResult && holdCoinsResult.detail && holdCoinsResult.detail.blocked_until ) { this.log( `Hold Coins: Blocked until ${this.formatBlockedTime( holdCoinsResult.detail.blocked_until )}`, "warning" ); } else { this.log("Hold Coins: Failed", "error"); } if (swipeCoinResult && swipeCoinResult.success) { this.log(`Swipe Coin: Success`, "success"); } else if ( swipeCoinResult && swipeCoinResult.detail && swipeCoinResult.detail.blocked_until ) { this.log( `Swipe Coin: Blocked until ${this.formatBlockedTime( swipeCoinResult.detail.blocked_until )}`, "warning" ); } else { this.log("Swipe Coin: Failed", "error"); } const tasks = await this.getDailyTasks(access_token); if (tasks) { let completedTasks = 0; for (const task of tasks) { const result = await this.completeTask(access_token, task); if (result && result.is_completed) { completedTasks++; } await this.sleep(1000); } this.log(`Tasks: Completed ${completedTasks}/${tasks.length}`, "info"); } else { this.log("Tasks: Failed to retrieve", "error"); } // Handle Durov task await this.handleDurovTask(access_token); // Get updated user info to ensure we have the latest balance await this.getUserInfo(id, access_token); // Update summary after processing each account this.summary.totalBalance = this.totalBalance; await this.saveSummary(); } catch (error) { this.log( `Error processing account ${accountIndex + 1}: ${error.message}`, "error" ); } } async startTelegramBot() { if (this.useTelegramBot && !this.botProcess) { this.log("Starting Telegram bot...", "info"); this.botProcess = spawn("node", ["./config/major-bot.js"], { stdio: "inherit" }); this.botProcess.on("error", (err) => { this.log(`Failed to start Telegram bot: ${err}`, "error"); }); this.botProcess.on("exit", (code, signal) => { if (code !== null) { this.log(`Telegram bot exited with code ${code}`, "warning"); } else if (signal !== null) { this.log(`Telegram bot was killed with signal ${signal}`, "warning"); } this.botProcess = null; }); } } async stopTelegramBot() { if (this.botProcess) { this.log("Stopping Telegram bot...", "info"); this.botProcess.kill(); this.botProcess = null; } } async main() { const dataFile = "./data/major.txt"; const data = await fs.readFile(dataFile, "utf8"); const accounts = data.split("\n").filter(Boolean); this.summary.totalAccounts = accounts.length; if (this.useTelegramBot) { await this.startTelegramBot(); } else { this.log( "Not using Telegram bot. You'll be prompted for Durov puzzle choices.", "info" ); } try { while (true) { this.totalBalance = 0; for (let i = 0; i < accounts.length; i++) { const init_data = accounts[i].trim(); await this.processAccount(init_data, i); if (i < accounts.length - 1) { await this.waitWithCountdown(3); } } this.log( `\nTotal balance for all accounts: ${this.totalBalance} stars`, "success" ); // Final summary update after processing all accounts this.summary.totalBalance = this.totalBalance; await this.saveSummary(); await this.waitWithCountdown(28850); } } finally { // Ensure bot is stopped when the main process exits await this.stopTelegramBot(); } } } if (require.main === module) { const major = new Major(); major.main().catch((err) => { console.error(err); process.exit(1); }); }