├── 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
--------------------------------------------------------------------------------