UNPKG

zixineabra

Version:

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

305 lines (270 loc) 10.1 kB
const fs = require("fs"); const path = require("path"); const axios = require("axios"); const readline = require("readline"); const { DateTime } = require("luxon"); const crypto = require("crypto"); const winston = require("winston"); const printBanner = require("./banner/galkurta-banner.js"); printBanner(); // Configure Winston logger const logger = winston.createLogger({ level: "info", format: winston.format.combine( winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss", }), // Remove or modify colorize // winston.format.colorize({ all: true }), winston.format.printf(({ timestamp, level, message }) => { // Capitalize the log level and ensure it's displayed const uppercaseLevel = level.toUpperCase().padEnd(5); return `${timestamp} | ${uppercaseLevel} | ${message}`; }) ), transports: [new winston.transports.Console()], }); class FreeDogs { constructor() { this.headers = { Accept: "application/json, text/plain, */*", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "vi-VN,vi;q=0.9,fr-FR;q=0.8,fr;q=0.7,en-US;q=0.6,en;q=0.5", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", Origin: "https://app.freedogs.bot", Referer: "https://app.freedogs.bot/", "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-site", "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", }; } async countdown(seconds) { for (let i = seconds; i >= 0; i--) { readline.cursorTo(process.stdout, 0); process.stdout.write(`Wait ${i} seconds to continue the loop`); await new Promise((resolve) => setTimeout(resolve, 1000)); } logger.info(""); } async callAPI(initData) { const url = `https://api.freedogs.bot/miniapps/api/user/telegram_auth?invitationCode=oscKOfyL&initData=${initData}`; try { const response = await axios.post(url, {}, { headers: this.headers }); if (response.status === 200 && response.data.code === 0) { return { success: true, data: response.data.data }; } else { return { success: false, error: response.data.msg }; } } catch (error) { return { success: false, error: error.message }; } } isExpired(token) { const [header, payload, sign] = token.split("."); const decodedPayload = Buffer.from(payload, "base64").toString(); try { const parsedPayload = JSON.parse(decodedPayload); const now = Math.floor(DateTime.now().toSeconds()); if (parsedPayload.exp) { const expirationDate = DateTime.fromSeconds( parsedPayload.exp ).toLocal(); logger.info( `Token expires on: ${expirationDate.toFormat("yyyy-MM-dd HH:mm:ss")}` ); const isExpired = now > parsedPayload.exp; logger.info( `Has the token expired? ${ isExpired ? "Yes, you need to replace the token" : "Not yet, you can continue using the token" }` ); return isExpired; } else { logger.warn(`Perpetual token, expiration time cannot be read`); return false; } } catch (error) { logger.error(`Error: ${error.message}`); return true; } } async getGameInfo(token) { const url = "https://api.freedogs.bot/miniapps/api/user_game_level/GetGameInfo?"; const headers = { ...this.headers, Authorization: `Bearer ${token}` }; try { const response = await axios.get(url, { headers }); if (response.status === 200 && response.data.code === 0) { const data = response.data.data; logger.info(`The current balance: ${data.currentAmount}`); logger.info(`Coin Pool: ${data.coinPoolLeft}/${data.coinPoolLimit}`); logger.info( `Number of clicks today: ${data.userToDayNowClick}/${data.userToDayMaxClick}` ); return { success: true, data: data }; } else { return { success: false, error: response.data.msg }; } } catch (error) { return { success: false, error: error.message }; } } md5(input) { return crypto.createHash("md5").update(input).digest("hex"); } async collectCoin(token, gameInfo) { const url = "https://api.freedogs.bot/miniapps/api/user_game/collectCoin"; const headers = { ...this.headers, Authorization: `Bearer ${token}` }; let collectAmount = Math.min( gameInfo.coinPoolLeft, 10000 - gameInfo.userToDayNowClick ); const collectSeqNo = Number(gameInfo.collectSeqNo); const hashCode = this.md5( collectAmount + String(collectSeqNo) + "7be2a16a82054ee58398c5edb7ac4a5a" ); const params = new URLSearchParams({ collectAmount: collectAmount, hashCode: hashCode, collectSeqNo: collectSeqNo, }); try { const response = await axios.post(url, params, { headers }); if (response.status === 200 && response.data.code === 0) { logger.info(`Successfully collected ${collectAmount} coins`); return { success: true, data: response.data.data }; } else { return { success: false, error: response.data.msg }; } } catch (error) { return { success: false, error: error.message }; } } async getTaskList(token) { const url = "https://api.freedogs.bot/miniapps/api/task/lists?"; const headers = { ...this.headers, Authorization: `Bearer ${token}` }; try { const response = await axios.get(url, { headers }); if (response.status === 200 && response.data.code === 0) { const tasks = response.data.data.lists.filter( (task) => task.isFinish === 0 ); return { success: true, data: tasks }; } else { return { success: false, error: response.data.msg }; } } catch (error) { return { success: false, error: error.message }; } } async completeTask(token, taskId) { const url = `https://api.freedogs.bot/miniapps/api/task/finish_task?id=${taskId}`; const headers = { ...this.headers, Authorization: `Bearer ${token}` }; try { const response = await axios.post(url, {}, { headers }); if (response.status === 200 && response.data.code === 0) { return { success: true }; } else { return { success: false, error: response.data.msg }; } } catch (error) { return { success: false, error: error.message }; } } async processTasks(token, userId) { const taskListResult = await this.getTaskList(token); if (taskListResult.success) { for (const task of taskListResult.data) { logger.info(`Performing task: ${task.name}`); const completeResult = await this.completeTask(token, task.id); if (completeResult.success) { logger.info( `Completed task ${task.name} successfully | Reward: ${task.rewardParty}` ); } else { logger.error( `Cannot complete task ${task.name}: ${completeResult.error}` ); } await new Promise((resolve) => setTimeout(resolve, 1000)); } } else { logger.error( `Unable to get task list for account ${userId}: ${taskListResult.error}` ); } } async main() { const dataFile = path.join(__dirname, "./../data/theFreeDogs_bot.txt"); const tokenFile = path.join(__dirname, "./token/freedogs-token.json"); let tokens = {}; if (fs.existsSync(tokenFile)) { tokens = JSON.parse(fs.readFileSync(tokenFile, "utf8")); } const data = fs .readFileSync(dataFile, "utf8") .replace(/\r/g, "") .split("\n") .filter(Boolean); while (true) { for (let i = 0; i < data.length; i++) { const rawInitData = data[i]; const initData = rawInitData.replace(/&/g, "%26").replace(/=/g, "%3D"); const userDataStr = decodeURIComponent( initData.split("user%3D")[1].split("%26")[0] ); const userData = JSON.parse(decodeURIComponent(userDataStr)); const userId = userData.id; const firstName = userData.first_name; logger.info(`Account ${i + 1} | ${firstName}`); let token = tokens[userId]; let needNewToken = !token || this.isExpired(token); if (needNewToken) { logger.info(`Need to get new token for account ${userId}...`); const apiResult = await this.callAPI(initData); if (apiResult.success) { logger.info(`Successfully obtained token for account ${userId}`); tokens[userId] = apiResult.data.token; token = apiResult.data.token; fs.writeFileSync(tokenFile, JSON.stringify(tokens, null, 2)); logger.info(`New token has been saved for account ${userId}`); } else { logger.error( `Failed to get token for account ${userId}: ${apiResult.error}` ); continue; } } const gameInfoResult = await this.getGameInfo(token); if (gameInfoResult.success) { if (gameInfoResult.data.coinPoolLeft > 0) { await this.collectCoin(token, gameInfoResult.data); } else { logger.warn(`No coins to collect for account ${userId}`); } await this.processTasks(token, userId); } else { logger.error( `Unable to get game information for account ${userId}: ${gameInfoResult.error}` ); } await new Promise((resolve) => setTimeout(resolve, 1000)); } await this.countdown(60); } } } const client = new FreeDogs(); client.main().catch((err) => { logger.error(err.message); process.exit(1); });