├── LICENSE ├── README.md ├── data.txt ├── index.js ├── package.json └── proxy.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Furqonflynn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🇳 nodego-bot-js 2 | NODEGO Point Mining Automation: Automate NODEGO point mining with this robust Node.js script. 3 | 4 | > [!TIP] 5 | > If you find this script helpful and beneficial, please star ⭐ this repository. Your support motivates me to create more useful tools in the future. 6 | 7 | 8 | > [!WARNING] 9 | > ## The use of this bot is entirely at your own risk. I assume no liability for any losses, damages, or consequences arising from its use. 10 | 11 | ## 🦾 Script Features 12 | 13 | - Single Direct Connection 14 | - Multiple Accounts Connection through Proxy 15 | - Daily Login 16 | 17 | ## 🔓 Register 18 | 19 | - If you don't have a NODEGO account yet 20 | - Register Here [https://app.nodego.ai](https://app.nodego.ai/r/NODEB3716AB29E21) 21 | - Referral code 22 | ```bash 23 | NODEB3716AB29E21 24 | ``` 25 | ## 🤔 How To Do 26 | 27 | - Clone This Repo 28 | - ```bash 29 | git clone https://github.com/cmalf/nodego-bot-js.git 30 | ``` 31 | - Go To Folder 32 | - ```bash 33 | cd nodego-bot-js 34 | ``` 35 | - Install Dependencies 36 | ```bash 37 | npm install 38 | ``` 39 | - To Run the script 40 | 41 | ```bash 42 | npm start 43 | ``` 44 | ## ⚙️ Configuration 45 | 46 | - Add your Bearer Token to `DATA.txt` 47 | - Add Proxy to proxy.txt (`The number of proxies cannot be less than the number of accounts`) 48 | - Get Token 49 | - Make sure you Alredy logged into your accounts and NODEGO Extension are enabled, Right Click Open New Tab [GetToken](https://chrome-extensions/dhffhdepkkepbcienheompkncklalogf/index.html) 50 | - Right click and Inspect -> Go to Tab Network 51 | - Search {;}me 52 | - Or see ss below 53 | 54 | 55 | ## [◉°] ScreenShoot 56 | 57 | - script interface 58 | 59 | 60 | 61 | - run multiple accounts 62 | 63 | 64 | 65 | ## Note 66 | 67 | > [!TIP] 68 | > Yesterday I made a script to be able to use multiple proxies using only 1 Bearer Token and it was successful, 69 | > but maybe it was just a bug and has been fixed by the developer, 70 | > and now it can only be done with the rule of 1 proxy 1 Bearer Token. 71 | -------------------------------------------------------------------------------- /data.txt: -------------------------------------------------------------------------------- 1 | token1 2 | token2 3 | etc -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | /** 4 | ######################################################## 5 | # # 6 | # CODE : NODEGO Bot v1.0.0 (Exstension v1.1.4) # 7 | # NodeJs: v23.6.1 # 8 | # Author: Furqonflynn (cmalf) # 9 | # TG : https://t.me/furqonflynn # 10 | # GH : https://github.com/cmalf # 11 | # # 12 | ######################################################## 13 | */ 14 | /** 15 | * This code is open-source and welcomes contributions! 16 | * 17 | * If you'd like to add features or improve this code, please follow these steps: 18 | * 1. Fork this repository to your own GitHub account. 19 | * 2. Make your changes in your forked repository. 20 | * 3. Submit a pull request to the original repository. 21 | * 22 | * This allows me to review your contributions and ensure the codebase maintains high quality. 23 | * 24 | * Let's work together to improve this project! 25 | * 26 | * P.S. Remember to always respect the original author's work and avoid plagiarism. 27 | * Let's build a community of ethical and collaborative developers. 28 | */ 29 | 30 | const fs = require("fs/promises"); 31 | const readline = require("readline"); 32 | const axios = require("axios"); 33 | const { HttpsProxyAgent } = require("https-proxy-agent"); 34 | const { SocksProxyAgent } = require("socks-proxy-agent"); 35 | 36 | // Global accounts list which will be populated from data.txt and proxy.txt 37 | let accountLists = []; 38 | 39 | const Colors = { 40 | Gold: "\x1b[38;5;220m", 41 | Red: "\x1b[31m", 42 | Teal: "\x1b[38;5;51m", 43 | Green: "\x1b[32m", 44 | Neon: "\x1b[38;5;198m", 45 | Blue: "\x1b[34m", 46 | Magenta: "\x1b[95m", 47 | Dim: "\x1b[2m", 48 | RESET: "\x1b[0m" 49 | }; 50 | 51 | function CoderMark() { 52 | console.log(` 53 | ╭━━━╮╱╱╱╱╱╱╱╱╱╱╱╱╱╭━━━┳╮ 54 | ┃╭━━╯╱╱╱╱╱╱╱╱╱╱╱╱╱┃╭━━┫┃${Colors.Green} 55 | ┃╰━━┳╮╭┳━┳━━┳━━┳━╮┃╰━━┫┃╭╮╱╭┳━╮╭━╮ 56 | ┃╭━━┫┃┃┃╭┫╭╮┃╭╮┃╭╮┫╭━━┫┃┃┃╱┃┃╭╮┫╭╮╮${Colors.Blue} 57 | ┃┃╱╱┃╰╯┃┃┃╰╯┃╰╯┃┃┃┃┃╱╱┃╰┫╰━╯┃┃┃┃┃┃┃ 58 | ╰╯╱╱╰━━┻╯╰━╯┣━━┻╯╰┻╯╱╱╰━┻━╮╭┻╯╰┻╯╰╯${Colors.RESET} 59 | ╱╱╱╱╱╱╱╱╱╱╱┃┃╱╱╱╱╱╱╱╱╱╱╭━╯┃${Colors.Blue}{${Colors.Neon}cmalf${Colors.Blue}}${Colors.RESET} 60 | ╱╱╱╱╱╱╱╱╱╱╱╰╯╱╱╱╱╱╱╱╱╱╱╰━━╯ 61 | \n${Colors.RESET}NODEGO Bot ${Colors.Blue}{ ${Colors.Neon}JS${Colors.Blue} }${Colors.RESET} 62 | \n${Colors.Green}${'―'.repeat(50)} 63 | \n${Colors.Gold}[+]${Colors.RESET} DM : ${Colors.Teal}https://t.me/furqonflynn 64 | \n${Colors.Gold}[+]${Colors.RESET} GH : ${Colors.Teal}https://github.com/cmalf/ 65 | \n${Colors.Green}${'―'.repeat(50)} 66 | \n${Colors.Gold}]-> ${Colors.Blue}{ ${Colors.RESET}NODEGO Extension${Colors.Neon} v1.1.4${Colors.Blue} } ${Colors.RESET} 67 | \n${Colors.Gold}]-> ${Colors.Blue}{ ${Colors.RESET}BOT${Colors.Neon} v1.0.0${Colors.Blue} } ${Colors.RESET} 68 | \n${Colors.Green}${'―'.repeat(50)} 69 | `); 70 | } 71 | 72 | class RandomUserAgent { 73 | static userAgents = [ 74 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Edge/537.36", 75 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Edge/537.36", 76 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", 77 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Edge/120.0.0.0", 78 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", 79 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2.1 Safari/605.1.15", 80 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0", 81 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", 82 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36", 83 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0", 84 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", 85 | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36", 86 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 AtContent/95.5.5462.5" 87 | ]; 88 | 89 | static getRandomUserAgent() { 90 | if (!this.userAgents || this.userAgents.length === 0) { 91 | throw new Error("User agents array is empty or undefined"); 92 | } 93 | return this.userAgents[Math.floor(Math.random() * this.userAgents.length)]; 94 | } 95 | } 96 | 97 | class ProxyError extends Error { 98 | constructor(message, proxy) { 99 | super(message); 100 | this.proxy = proxy; 101 | this.name = "ProxyError"; 102 | } 103 | } 104 | 105 | async function getProxyAgent(proxy) { 106 | if (!proxy) { 107 | throw new ProxyError("Proxy URL is required", proxy); 108 | } 109 | try { 110 | if (proxy.startsWith("http://") || proxy.startsWith("https://")) { 111 | return new HttpsProxyAgent(proxy); 112 | } 113 | if (proxy.startsWith("socks://") || proxy.startsWith("socks5://")) { 114 | return new SocksProxyAgent(proxy); 115 | } 116 | throw new ProxyError(`Unsupported proxy protocol: ${proxy}`, proxy); 117 | } catch (error) { 118 | if (error instanceof ProxyError) { 119 | throw error; 120 | } 121 | throw new ProxyError(`Failed to create proxy agent: ${error.message}`, proxy); 122 | } 123 | } 124 | 125 | // Utility function to load accounts from data.txt and proxies from proxy.txt, 126 | // then map each account token to its corresponding proxy (based on index). 127 | async function loadAccountsAndProxies() { 128 | try { 129 | const dataContent = await fs.readFile("data.txt", "utf8"); 130 | const tokens = dataContent 131 | .split("\n") 132 | .map(line => line.trim()) 133 | .filter(Boolean); 134 | let proxies = []; 135 | try { 136 | const proxyContent = await fs.readFile("proxy.txt", "utf8"); 137 | proxies = proxyContent 138 | .split("\n") 139 | .map(line => line.trim()) 140 | .filter(Boolean); 141 | } catch (err) { 142 | console.log(`${Colors.Magenta}[INFO]${Colors.RESET} Could not read proxy file (proxy.txt), using local network for all accounts.`); 143 | } 144 | return tokens.map((token, index) => { 145 | return { Token: token, Proxy: proxies[index] || null }; 146 | }); 147 | } catch (err) { 148 | console.error(`${Colors.Red}[ERROR]${Colors.RESET} Failed to read data file (data.txt): ${err.message}`); 149 | process.exit(1); 150 | } 151 | } 152 | 153 | // Masks an email address (only first and last characters of username remain visible) 154 | const maskEmail = (email) => { 155 | const [username, domain] = email.split('@'); 156 | if (username.length <= 2) { 157 | return email; 158 | } 159 | const maskedUsername = username.charAt(0) + "*".repeat(username.length - 2) + username.charAt(username.length - 1); 160 | return `${maskedUsername}@${domain}`; 161 | }; 162 | 163 | async function getProxyIP(proxyAgent) { 164 | try { 165 | const response = await axios.get("https://api.bigdatacloud.net/data/client-ip", { 166 | httpsAgent: proxyAgent, 167 | proxy: false, 168 | timeout: 10000 169 | }); 170 | return response.data.ipString; 171 | } catch (error) { 172 | return "Unknown"; 173 | } 174 | } 175 | 176 | class APIClient { 177 | constructor(token, proxyAgent = null) { 178 | this.apiBaseUrl = "https://nodego.ai/api"; 179 | this.bearerToken = token; 180 | this.proxyAgent = proxyAgent; 181 | } 182 | 183 | async makeRequest(method, endpoint, data = null) { 184 | const url = `${this.apiBaseUrl}${endpoint}`; 185 | const config = { 186 | method, 187 | url, 188 | headers: { 189 | "Authorization": `Bearer ${this.bearerToken}`, 190 | "Content-Type": "application/json", 191 | "Accept": "*/*" 192 | }, 193 | timeout: 60000, 194 | proxy: false 195 | }; 196 | 197 | if (data) { 198 | config.data = data; 199 | } 200 | if (this.proxyAgent) { 201 | config.httpsAgent = this.proxyAgent; 202 | } 203 | 204 | try { 205 | return await axios(config); 206 | } catch (error) { 207 | throw error; 208 | } 209 | } 210 | 211 | async getUserInfo() { 212 | try { 213 | const response = await this.makeRequest("GET", "/user/me"); 214 | const metadata = response.data.metadata; 215 | return { 216 | username: metadata.username, 217 | email: metadata.email, 218 | totalPoint: metadata.rewardPoint, 219 | todayPoint: metadata.todayPoint || 0, 220 | socialTasks: metadata.socialTask || [], 221 | nodes: Array.isArray(metadata.nodes) 222 | ? metadata.nodes.map(node => ({ 223 | id: node.id, 224 | totalPoint: node.totalPoint, 225 | todayPoint: node.todayPoint, 226 | isActive: node.isActive 227 | })) 228 | : [] 229 | }; 230 | } catch (error) { 231 | throw error; 232 | } 233 | } 234 | 235 | async dailyCheckin() { 236 | try { 237 | const response = await this.makeRequest("POST", "/user/checkin"); 238 | return { 239 | statusCode: response.data.statusCode, 240 | message: response.data.message, 241 | userData: response.data.metadata.user 242 | }; 243 | } catch (error) { 244 | const statusCode = error.response?.data?.statusCode || error.response?.status || 500; 245 | const message = error.response?.data?.message || error.message; 246 | throw { statusCode, message, error: true }; 247 | } 248 | } 249 | } 250 | 251 | const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); 252 | 253 | async function pingNode(accessToken, proxyAgent = null) { 254 | const SERVER_URL = "https://nodego.ai/api/user/nodes/ping"; 255 | const config = { 256 | method: "POST", 257 | url: SERVER_URL, 258 | headers: { 259 | "Content-Type": "application/json", 260 | "Accept": "application/json, text/plain, */*", 261 | "Accept-Language": "id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7", 262 | "Authorization": `Bearer ${accessToken}`, 263 | "Origin": "chrome-extension://jbmdcnidiaknboflpljihfnbonjgegah", 264 | "Sec-Fetch-Dest": "empty", 265 | "Sec-Fetch-Mode": "cors", 266 | "Sec-Fetch-Site": "none", 267 | "Sec-Fetch-Storage-Access": "active", 268 | "User-Agent": RandomUserAgent.getRandomUserAgent() 269 | }, 270 | timeout: 30000, 271 | proxy: false, 272 | data: { type: "extension" } 273 | }; 274 | if (proxyAgent) { 275 | config.httpsAgent = proxyAgent; 276 | } 277 | try { 278 | const response = await axios(config); 279 | if (response.status >= 200 && response.status < 300) { 280 | return { success: true, status: response.status }; 281 | } else { 282 | throw new Error(`Ping failed with status: ${response.status}`); 283 | } 284 | } catch (error) { 285 | const statusCode = error.response?.data?.statusCode || error.response?.status || 0; 286 | if (statusCode === 429) { 287 | console.log("Ping ignored due to duplicate prevention (429), retrying ping in 2 minutes..."); 288 | } else { 289 | console.error(`${Colors.Red}[PING ERROR]${Colors.RESET} ${error.message}`); 290 | console.log("Retrying ping in 2 minutes..."); 291 | } 292 | await delay(120000); 293 | return await pingNode(accessToken, proxyAgent); 294 | } 295 | } 296 | 297 | async function pingCycleForAccount(accountDetail) { 298 | // If a proxy agent was successfully loaded, use it; otherwise, default to local network. 299 | const agentsToUse = (accountDetail.proxyAgents && accountDetail.proxyAgents.length > 0) 300 | ? accountDetail.proxyAgents 301 | : [null]; 302 | 303 | for (const proxyObj of agentsToUse) { 304 | const agent = proxyObj ? proxyObj.agent : null; 305 | let proxyIP; 306 | if (agent) { 307 | proxyIP = await getProxyIP(agent); 308 | } else { 309 | proxyIP = "Local network"; 310 | } 311 | try { 312 | await pingNode(accountDetail.token, agent); 313 | logShortUpdate(accountDetail.masked, "Success", "", proxyIP); 314 | } catch (error) { 315 | logShortUpdate(accountDetail.masked, "Failed", error.response?.status || error.message, proxyIP); 316 | } 317 | await delay(1000); 318 | } 319 | } 320 | 321 | function logFullUpdate(maskedEmail, todayPoint, totalPoint, totalActiveNodes, totalProxylist, pingStatus, errCode = "") { 322 | const statusColor = (pingStatus === "Success") ? Colors.Green : Colors.Red; 323 | console.log(`\n${Colors.Dim}${Colors.RESET}${'―'.repeat(50)}`); 324 | console.log( 325 | `${Colors.Gold}]>${Colors.RESET} Account ${Colors.Teal}${maskedEmail} 326 | ${Colors.Teal}[+]${Colors.RESET} point today : ${todayPoint}${Colors.RESET} 327 | ${Colors.Teal}[+]${Colors.RESET} points total: ${totalPoint}${Colors.RESET} 328 | ${Colors.Teal}[+]${Colors.RESET} Total nodes : ${Colors.Gold}${totalActiveNodes}${Colors.RESET} 329 | ${Colors.Teal}[+]${Colors.RESET} Total Proxy : ${Colors.Gold}${totalProxylist}${Colors.RESET} 330 | ${Colors.Teal}[+]${Colors.RESET} status ping : ${statusColor}${pingStatus}${(errCode ? " (" + errCode + ")" : "")}${Colors.RESET}` 331 | ); 332 | console.log(`${Colors.Dim}${Colors.RESET}${'―'.repeat(50)}`); 333 | } 334 | 335 | function logShortUpdate(maskedEmail, pingStatus, errCode = "", proxyIP = "") { 336 | const statusColor = (pingStatus === "Success" || pingStatus === "Checkin Success") ? Colors.Green : Colors.Red; 337 | console.log( 338 | `${Colors.Gold}]>${Colors.RESET} ${maskedEmail} | ProxyIP: ${Colors.Neon}${proxyIP}${Colors.RESET} | status: ${statusColor}${pingStatus}${(errCode ? " (" + errCode + ")" : "")}${Colors.RESET}` 339 | ); 340 | } 341 | 342 | async function runPinger() { 343 | const accountDetails = []; 344 | 345 | for (const acc of accountLists) { 346 | let proxyAgents = []; 347 | if (acc.Proxy) { 348 | try { 349 | const agent = await getProxyAgent(acc.Proxy); 350 | proxyAgents.push({ agent, proxy: acc.Proxy }); 351 | } catch (err) { 352 | console.error(`${Colors.Magenta}[INFO]${Colors.RESET} Skipping invalid proxy for account with token ${acc.Token}: ${err.message}`); 353 | } 354 | } 355 | 356 | let userInfo; 357 | if (proxyAgents.length > 0) { 358 | try { 359 | userInfo = await Promise.any( 360 | proxyAgents.map(proxyObj => new APIClient(acc.Token, proxyObj.agent).getUserInfo()) 361 | ); 362 | } catch (err) { 363 | try { 364 | userInfo = await new APIClient(acc.Token, null).getUserInfo(); 365 | } catch (error) { 366 | console.error(`Error fetching user info for account with token ${acc.Token}: ${error.message}`); 367 | continue; 368 | } 369 | } 370 | } else { 371 | try { 372 | userInfo = await new APIClient(acc.Token, null).getUserInfo(); 373 | } catch (error) { 374 | console.error(`Error fetching user info for account with token ${acc.Token}: ${error.message}`); 375 | continue; 376 | } 377 | } 378 | 379 | const masked = maskEmail(userInfo.email); 380 | const activeNodes = userInfo.nodes.filter(node => node.isActive); 381 | const totalTodayPoint = activeNodes.reduce((sum, node) => sum + node.todayPoint, 0); 382 | const totalNodeActive = activeNodes.length; 383 | logFullUpdate(masked, totalTodayPoint, userInfo.totalPoint, totalNodeActive, proxyAgents.length, "Pending"); 384 | 385 | accountDetails.push({ 386 | token: acc.Token, 387 | proxyAgents, 388 | masked, 389 | initialInfo: userInfo 390 | }); 391 | } 392 | 393 | for (const accDetail of accountDetails) { 394 | pingCycleForAccount(accDetail); 395 | setInterval(() => { 396 | pingCycleForAccount(accDetail); 397 | }, 120000); 398 | setInterval(async () => { 399 | let updatedInfo; 400 | if (accDetail.proxyAgents && accDetail.proxyAgents.length > 0) { 401 | try { 402 | updatedInfo = await Promise.any( 403 | accDetail.proxyAgents.map(proxyObj => new APIClient(accDetail.token, proxyObj.agent).getUserInfo()) 404 | ); 405 | } catch (err) { 406 | try { 407 | updatedInfo = await new APIClient(accDetail.token, null).getUserInfo(); 408 | } catch (error) { 409 | logFullUpdate( 410 | accDetail.masked, 411 | accDetail.initialInfo.todayPoint, 412 | accDetail.initialInfo.totalPoint, 413 | accDetail.initialInfo.nodes.filter(n => n.isActive).length, 414 | (accDetail.proxyAgents ? accDetail.proxyAgents.length : 0), 415 | "Failed", 416 | error.response?.status || error.message 417 | ); 418 | return; 419 | } 420 | } 421 | } else { 422 | try { 423 | updatedInfo = await new APIClient(accDetail.token, null).getUserInfo(); 424 | } catch (error) { 425 | logFullUpdate( 426 | accDetail.masked, 427 | accDetail.initialInfo.todayPoint, 428 | accDetail.initialInfo.totalPoint, 429 | accDetail.initialInfo.nodes.filter(n => n.isActive).length, 430 | 0, 431 | "Failed", 432 | error.response?.status || error.message 433 | ); 434 | return; 435 | } 436 | } 437 | const activeNodesUpdated = updatedInfo.nodes.filter(node => node.isActive); 438 | const totalTodayPointUpdated = activeNodesUpdated.reduce((sum, node) => sum + node.todayPoint, 0); 439 | const totalNodeActiveUpdated = activeNodesUpdated.length; 440 | logFullUpdate(maskEmail(updatedInfo.email), totalTodayPointUpdated, updatedInfo.totalPoint, totalNodeActiveUpdated, (accDetail.proxyAgents ? accDetail.proxyAgents.length : 0), "Success"); 441 | }, 600000); 442 | } 443 | } 444 | 445 | async function runDailyCheckin() { 446 | for (const acc of accountLists) { 447 | let proxyAgents = []; 448 | if (acc.Proxy) { 449 | try { 450 | const agent = await getProxyAgent(acc.Proxy); 451 | proxyAgents.push({ agent, proxy: acc.Proxy }); 452 | } catch (err) { 453 | console.error(`${Colors.Magenta}[INFO]${Colors.RESET} Skipping invalid proxy for account with token ${acc.Token}: ${err.message}`); 454 | } 455 | } 456 | const randomAgent = (proxyAgents.length > 0) 457 | ? proxyAgents[Math.floor(Math.random() * proxyAgents.length)].agent 458 | : null; 459 | const client = new APIClient(acc.Token, randomAgent); 460 | let userInfo; 461 | try { 462 | userInfo = await client.getUserInfo(); 463 | } catch (error) { 464 | console.error(`Error fetching user info for token ${acc.Token}: ${error.message}`); 465 | continue; 466 | } 467 | const masked = maskEmail(userInfo.email); 468 | let result = null; 469 | while (true) { 470 | try { 471 | result = await client.dailyCheckin(); 472 | break; 473 | } catch (error) { 474 | if (error.statusCode === 429) { 475 | console.log(`${Colors.Blue}[DAILY CHECKIN RETRY]${Colors.RESET} ${masked} encountered error 429, retrying in 15 seconds...`); 476 | await delay(15000); 477 | continue; 478 | } else if (error.statusCode === 400 && error.message.includes("once per day")) { 479 | console.log(`${Colors.Blue}[DAILY CHECKIN]${Colors.RESET} ${masked} already checked in today.`); 480 | logShortUpdate(masked, "Request Success"); 481 | result = null; 482 | break; 483 | } else { 484 | logShortUpdate(masked, "Failed", error.statusCode || error.message); 485 | result = null; 486 | break; 487 | } 488 | } 489 | } 490 | if (result) { 491 | if (result.statusCode >= 200 && result.statusCode < 300) { 492 | logShortUpdate(masked, "Checkin Success"); 493 | } else { 494 | const activeNodes = userInfo.nodes.filter(node => node.isActive); 495 | const totalTodayPoint = activeNodes.reduce((sum, node) => sum + node.todayPoint, 0); 496 | const totalNodeActive = activeNodes.length; 497 | const newTotal = result.userData?.rewardPoint || userInfo.totalPoint; 498 | logFullUpdate(masked, totalTodayPoint, newTotal, totalNodeActive, proxyAgents.length, "Success"); 499 | } 500 | } 501 | } 502 | } 503 | 504 | function displayMenu() { 505 | console.log(` 506 | ${Colors.Blue}Menu:${Colors.RESET} 507 | 508 | ${Colors.Gold}1. ${Colors.RESET}Run Pinger 509 | ${Colors.Gold}2. ${Colors.RESET}Daily Checkin 510 | ${Colors.Gold}3. ${Colors.Red}Exit${Colors.RESET} 511 | `); 512 | const rl = readline.createInterface({ 513 | input: process.stdin, 514 | output: process.stdout 515 | }); 516 | rl.question("Select option (1, 2 or 3): ", async (answer) => { 517 | if (answer.trim() === "1") { 518 | console.clear(); 519 | console.log(`\n${Colors.Dim}${Colors.RESET}${'―'.repeat(50)}`); 520 | console.log(`${Colors.Teal}Starting pinger cycles...${Colors.RESET}`); 521 | console.log(`${Colors.Dim}${Colors.RESET}${'―'.repeat(50)}\n`); 522 | await runPinger(); 523 | } else if (answer.trim() === "2") { 524 | console.clear(); 525 | console.log(`\n${Colors.Dim}${Colors.RESET}${'―'.repeat(50)}`); 526 | console.log(`${Colors.Gold}Performing daily checkin for all accounts...${Colors.RESET}`); 527 | console.log(`${Colors.Dim}${Colors.RESET}${'―'.repeat(50)}\n`); 528 | await runDailyCheckin(); 529 | rl.close(); 530 | await displayMenu(); 531 | } else if (answer.trim() === "3") { 532 | console.log(`${Colors.Red}Exiting the application. Goodbye!${Colors.RESET}`); 533 | rl.close(); 534 | process.exit(0); 535 | } else { 536 | console.log(`${Colors.Red}Invalid option. Please try again.${Colors.RESET}`); 537 | rl.close(); 538 | await displayMenu(); 539 | } 540 | }); 541 | } 542 | 543 | async function main() { 544 | console.clear(); 545 | CoderMark(); 546 | // Load accounts and proxy mappings from data.txt and proxy.txt 547 | accountLists = await loadAccountsAndProxies(); 548 | displayMenu(); 549 | } 550 | 551 | main(); 552 | 553 | process.on("SIGINT", () => { 554 | console.log(`\n${Colors.Red}Gracefully shutting down.${Colors.RESET}`); 555 | process.exit(0); 556 | }); 557 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodego-bot-js", 3 | "version": "1.0.0", 4 | "description": "https://github.com/cmalf/nodego-bot-js.git", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "author": "furqonflynn", 10 | "license": "MIT", 11 | "dependencies": { 12 | "axios": "^1.7.9", 13 | "https-proxy-agent": "^7.0.6", 14 | "proxy-agent": "^6.5.0", 15 | "readline": "^1.3.0", 16 | "socks-proxy-agent": "^8.0.5" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /proxy.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cmalf/nodego-bot-js/701f2f870d7e7a28f8544b128707f12c3217084f/proxy.txt --------------------------------------------------------------------------------