├── .github └── workflows │ └── npm-publish-github-packages.yml ├── .gitignore ├── README.md ├── assets ├── gamesocket.png ├── image1.png └── image2.png ├── config.js ├── index.js ├── package-lock.json ├── package.json └── src ├── .gitignore ├── account_tmp.js ├── event.js └── utils └── helper.js /.github/workflows/npm-publish-github-packages.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-node@v3 16 | with: 17 | node-version: 22 18 | - run: cp src/account_tmp.js src/account.js 19 | - run: npm ci 20 | 21 | publish-npm: 22 | needs: build 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: actions/setup-node@v3 27 | with: 28 | node-version: 22 29 | registry-url: https://registry.npmjs.org/ 30 | - run: npm ci 31 | - run: npm publish 32 | env: 33 | NODE_AUTH_TOKEN: ${{secrets.NPMJS_TOKEN}} 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .node_modules 3 | .DS_Store 4 | test.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # METABOSS BOT 2 | 3 | Meta boss auto attack boss bot, What is Metaboss ? Metaboss is tap tap game on telegram that run on TON chain. 4 | 5 | ## Prerequisite 6 | 7 | - Node JS (v22.1.0) 8 | - Git 9 | - Metaboss Account 10 | 11 | ## BOT Feature 12 | 13 | - Auto attack bos 14 | - Auto claim boss reward 15 | - Auto complete missions 16 | - Auto claim misisons reward 17 | - Auto Start Mining (if unlocked) 18 | - Auto open item on bag (Boss Chest, Mission Reward Chest, Mining Reward) 19 | 20 | ## Register Metaboss Account 21 | 22 | - join metaboss on telegram [HERE](https://t.me/metaboss_2024_bot?start=ref_5703822759) 23 | - Start bot `/start` 24 | - play `/play` 25 | 26 | ## Set Up And Run 27 | 28 | - clone the project `git clone https://github.com/Widiskel/metaboss-bot.git`, or download from [RELEASE](https://github.com/Widiskel/metaboss-bot/releases) 29 | - run `cd metaboss-bot`. 30 | - run `npm install`. 31 | - run `cp src/account_tmp.js src/account.js` 32 | 33 | Since metaboss team add more security to the app, botting is not easy like before, here i will tell you how to run the bot 34 | 35 | 1. Install [Telegram Desktop](https://desktop.telegram.org/). 36 | 2. Go to Settings > Advance > Experimental Settings > And enable Webview inspecting. 37 | ![image](https://github.com/Widiskel/metaboss-bot/blob/master/assets/image2.png) 38 | 39 | Also read how to do inspect on your Operating system. 40 | 41 | 3. Now open Metaboss Webview game on your Telegram Desktop. 42 | 4. On the Webview window right click > inspect (on Windows) or open Safari > Develop > Your Device > Telegram (on Mac) 43 | 5. On Inspect Element or Developer Tools > go to Network tab > find the game socket 44 | 6. Now refresh the Metaboss Webview on your Telegram Desktop. 45 | 7. Back to Developer Tools > Network tab > game socket You will see something like this 46 | ![image](https://github.com/Widiskel/metaboss-bot/blob/master/assets/gamesocket.png) 47 | 8. Copy the request that contains your account data, the data is seems like this 48 | 49 | ```js 50 | { 51 | code: 1, 52 | type: 2, 53 | data: { 54 | id: 0, 55 | username: "X", 56 | hash: "X", 57 | timeAuth: 0, 58 | data: 'query=xx', //copy value inside data 59 | }, 60 | }, 61 | ``` 62 | 63 | you can copy all of it, or just copy the data `query=xxx`. if you copy only the data `query=xxx` or `user=xxx` remember to wrap it with single quotes `'`. 64 | 65 | 9. Now open `account.js` and fill up or paste your data using template data provided 66 | 67 | ```js 68 | const account = [ 69 | "query_id=xxx", 70 | { 71 | code: 1, 72 | type: 2, 73 | data: { 74 | id: 0, 75 | username: "X", 76 | hash: "X", 77 | timeAuth: 0, 78 | data: "query_id=xxx", 79 | }, 80 | }, 81 | "user=xxx", 82 | ]; 83 | 84 | export { account }; 85 | ``` 86 | 87 | 10. Finnally run `npm run start` 88 | 89 | ## Configure Mining 90 | 91 | to configure or decide what mining you want to focused, look at `config.js` , change the mine type with type you want, i'm already add description about mining priority on that file. If you not configure it, it will be use the Black Mine as default 92 | 93 | ## How To Update 94 | 95 | - run `git pull` 96 | - run `npm update` 97 | - run the bot again `npm run start` 98 | 99 | ## Note 100 | 101 | The account data can be expired (query data livetime around 1-2 day), because it have `hash` and `timeAuth`, so if your run the bot and your username and id is undefined or it stuck on some process (get user info, get boss info etc), you need to get new account data. follow the ## Set Up And Run from no 3 102 | 103 | if any error happen please check [HERE](https://github.com/Widiskel/metaboss-bot) 104 | check the commit if any new commit, then update the bot. 105 | 106 | remember to not open telegram metaboss game while the bot running cause it may cause bot freeze. 107 | 108 | ## CONTRIBUTE 109 | 110 | Feel free to fork and contribute adding more feature thanks. 111 | 112 | ## SUPPORT 113 | 114 | want to support me for creating another bot ? 115 | buy me a coffee on 116 | 117 | EVM : `0x0fd08d2d42ff086bf8c6d057d02d802bf217559a` 118 | 119 | SOLANA : `3tE3Hs7P2wuRyVxyMD7JSf8JTAmEekdNsQWqAnayE1CN` 120 | -------------------------------------------------------------------------------- /assets/gamesocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Widiskel/metaboss-bot/487c0773eebce9a2e4c09dced3994377b2af15df/assets/gamesocket.png -------------------------------------------------------------------------------- /assets/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Widiskel/metaboss-bot/487c0773eebce9a2e4c09dced3994377b2af15df/assets/image1.png -------------------------------------------------------------------------------- /assets/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Widiskel/metaboss-bot/487c0773eebce9a2e4c09dced3994377b2af15df/assets/image2.png -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | export class Config { 2 | /** 3 | * 4 | * Blue Gem - $TON, $MTB, $NOT 5 | * Black Gem - $NOT, $MTB, $TON 6 | * Gold Gem - $MTB, $NOT, $TON 7 | * 8 | * miningType 1 = Blue (TON Dom) 9 | * miningType 2 = Black Mine (NOT Dom) 10 | * miningType 3 = Gold Mine (MTB Dom) 11 | */ 12 | static miningType = 2; 13 | } 14 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import WebSocket from "ws"; 2 | import * as event from "./src/event.js"; 3 | import { account } from "./src/account.js"; 4 | import { Twisters } from "twisters"; 5 | import { Config } from "./config.js"; 6 | 7 | const socketUrl = "wss://apiv2.metaboss.xyz:2000/game"; 8 | var client; 9 | const twisters = new Twisters(); 10 | 11 | async function initWebSocket() { 12 | console.log("-> Connecting to Websocket"); 13 | return new Promise((resolve, reject) => { 14 | client = new WebSocket(socketUrl); 15 | client.setMaxListeners(0); 16 | 17 | client.on("open", () => { 18 | // console.log(""); 19 | twisters.put(1, { 20 | text: ` 21 | Status : Connecting to metaboss web socket 22 | `, 23 | }); 24 | 25 | client.ping(); 26 | }); 27 | 28 | client.on("close", () => { 29 | reject(new Error("WebSocket connection closed unexpectedly")); 30 | }); 31 | 32 | client.on("ping", () => { 33 | twisters.put(1, { 34 | text: ` 35 | Status : Received ping from server 36 | `, 37 | }); 38 | 39 | client.pong(); 40 | }); 41 | 42 | client.on("pong", () => { 43 | twisters.put(1, { 44 | text: ` 45 | Status : Received pong from server 46 | `, 47 | }); 48 | console.log("-> Connected"); 49 | twisters.remove(1); 50 | resolve(); 51 | }); 52 | }); 53 | } 54 | 55 | async function getUserInfo(userData) { 56 | twisters.put(1, { 57 | text: ` 58 | Status : Getting User Info Event 59 | 60 | USER DATA 61 | Username : ${event.userData.name} 62 | Id : ${event.userData.id} 63 | Total Misison : ${event.userData.mission.length} 64 | 65 | BALANCE 66 | MTB : ${event.userData.coin} 67 | TON : ${event.userData.ton} 68 | NOT : ${event.userData.notCoin} 69 | 70 | BOSS INFO 71 | Boss Max HP : ${event.bossInfo.maxHp} 72 | Current HP : ${event.bossInfo.currentHp} 73 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 74 | `, 75 | }); 76 | 77 | return new Promise(async (resolve, reject) => { 78 | await client.send(event.getUserInfo(userData)); 79 | await client.once("message", async (wsMsg) => { 80 | const messages = JSON.parse(wsMsg.toString("utf8")); 81 | const rc = messages.code; 82 | const data = messages.data; 83 | // console.log(messages); 84 | 85 | if (rc == 2) { 86 | event.setUserData(data); 87 | event.setMission(data.mission); 88 | twisters.put(1, { 89 | text: ` 90 | Status : Running on - Account ${event.userData.id} 91 | 92 | USER DATA 93 | Username : ${data.name} 94 | Id : ${data.id} 95 | Total Misison : ${data.mission.length} 96 | 97 | BALANCE 98 | MTB : ${event.userData.coin} 99 | TON : ${event.userData.ton} 100 | NOT : ${event.userData.notCoin} 101 | 102 | BOSS INFO 103 | Boss Max HP : ${event.bossInfo.maxHp} 104 | Current HP : ${event.bossInfo.currentHp} 105 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 106 | `, 107 | }); 108 | 109 | resolve(); 110 | } else { 111 | reject(new Error("Received unexpected response" + data)); 112 | } 113 | }); 114 | }); 115 | } 116 | 117 | async function openChest(id) { 118 | return new Promise(async (resolve, reject) => { 119 | twisters.put(1, { 120 | text: ` 121 | Status : Opening Item id ${id} from Bag 122 | 123 | USER DATA 124 | Username : ${event.userData.name} 125 | Id : ${event.userData.id} 126 | Total Misison : ${event.userData.mission.length} 127 | 128 | 129 | BALANCE 130 | MTB : ${event.userData.coin} 131 | TON : ${event.userData.ton} 132 | NOT : ${event.userData.notCoin} 133 | 134 | BOSS INFO 135 | Boss Max HP : ${event.bossInfo.maxHp} 136 | Current HP : ${event.bossInfo.currentHp} 137 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 138 | `, 139 | }); 140 | 141 | try { 142 | const handleRes = async (wsMsg) => { 143 | const messages = JSON.parse(wsMsg.toString("utf8")); 144 | const rc = messages.code; 145 | const data = messages.data; 146 | // console.log(messages); 147 | 148 | if (rc == 12) { 149 | console.log( 150 | `-> Successfully Opening chest for Account ${ 151 | event.userData.id 152 | } got => ${data.number} ${ 153 | data.type == 1 ? "MTB" : data.type == 2 ? "TON" : "NOT" 154 | }` 155 | ); 156 | await client.off("message", handleRes); 157 | resolve(); 158 | } 159 | }; 160 | await client.send(event.claimChest(id)); 161 | await client.on("message", handleRes); 162 | } catch (error) { 163 | reject(error); 164 | } 165 | }); 166 | } 167 | 168 | async function claimBossChest() { 169 | return new Promise(async (resolve, reject) => { 170 | twisters.put(1, { 171 | text: ` 172 | Status : Getting Chess Info Event 173 | 174 | USER DATA 175 | Username : ${event.userData.name} 176 | Id : ${event.userData.id} 177 | Total Misison : ${event.userData.mission.length} 178 | 179 | BALANCE 180 | MTB : ${event.userData.coin} 181 | TON : ${event.userData.ton} 182 | NOT : ${event.userData.notCoin} 183 | 184 | BOSS INFO 185 | Boss Max HP : ${event.bossInfo.maxHp} 186 | Current HP : ${event.bossInfo.currentHp} 187 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 188 | `, 189 | }); 190 | 191 | try { 192 | const handleRes = async (wsMsg) => { 193 | const messages = JSON.parse(wsMsg.toString("utf8")); 194 | const rc = messages.code; 195 | const data = messages.data; 196 | // console.log(messages); 197 | 198 | if (rc == 12) { 199 | console.log( 200 | `-> Successfully claimed chest for Account ${ 201 | event.userData.id 202 | } got => ${data.number} ${data.type == 1 ? "MTB" : "TON"}` 203 | ); 204 | await client.off("message", handleRes); 205 | resolve(); 206 | } 207 | 208 | if (rc == 1000) { 209 | console.log("-> All Boss chest claimed"); 210 | twisters.put(1, { 211 | text: ` 212 | Status : All Chest Claimed for Account ${event.userData.id} 213 | 214 | USER DATA 215 | Username : ${event.userData.name} 216 | Id : ${event.userData.id} 217 | Total Misison : ${event.userData.mission.length} 218 | 219 | BALANCE 220 | MTB : ${event.userData.coin} 221 | TON : ${event.userData.ton} 222 | NOT : ${event.userData.notCoin} 223 | 224 | BOSS INFO 225 | Boss Max HP : ${event.bossInfo.maxHp} 226 | Current HP : ${event.bossInfo.currentHp} 227 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 228 | 229 | Continue action 230 | `, 231 | }); 232 | 233 | await client.off("message", handleRes); 234 | resolve(); 235 | } 236 | }; 237 | await client.send(event.claimBossChest()); 238 | await client.on("message", handleRes); 239 | } catch (error) { 240 | reject(error); 241 | } 242 | }); 243 | } 244 | 245 | async function startMining() { 246 | return new Promise(async (resolve, reject) => { 247 | twisters.put(1, { 248 | text: ` 249 | Status : Start mining 250 | 251 | USER DATA 252 | Username : ${event.userData.name} 253 | Id : ${event.userData.id} 254 | Total Misison : ${event.userData.mission.length} 255 | 256 | BALANCE 257 | MTB : ${event.userData.coin} 258 | TON : ${event.userData.ton} 259 | NOT : ${event.userData.notCoin} 260 | 261 | BOSS INFO 262 | Boss Max HP : ${event.bossInfo.maxHp} 263 | Current HP : ${event.bossInfo.currentHp} 264 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 265 | `, 266 | }); 267 | 268 | try { 269 | const handleRes = async (wsMsg) => { 270 | const messages = JSON.parse(wsMsg.toString("utf8")); 271 | const rc = messages.code; 272 | const data = messages.data; 273 | // console.log(messages); 274 | 275 | if (rc == 32) { 276 | if (data.timeRemaining != 0) { 277 | console.log( 278 | `-> Mining already started for Account ${ 279 | event.userData.id 280 | }, Remaining ${millisecondsToHoursAndMinutes(data.timeRemaining)}` 281 | ); 282 | } else { 283 | console.log( 284 | `-> Successfully Start mining for Account ${event.userData.id}` 285 | ); 286 | } 287 | event.setMiningData(data); 288 | await client.off("message", handleRes); 289 | 290 | resolve(); 291 | } else if (rc == 1000) { 292 | console.log("-> Failed to start mining, Mining not unlocked"); 293 | event.setMiningData(data); 294 | await client.off("message", handleRes); 295 | 296 | resolve(); 297 | } 298 | }; 299 | await client.send(event.startMining(Config.miningType)); 300 | await client.on("message", handleRes); 301 | } catch (error) { 302 | reject(error); 303 | } 304 | }); 305 | } 306 | 307 | async function autoCompleteMissions() { 308 | return new Promise(async (resolve, reject) => { 309 | try { 310 | twisters.put(1, { 311 | text: ` 312 | Status : Auto Complete Mission 313 | 314 | USER DATA 315 | Username : ${event.userData.name} 316 | Id : ${event.userData.id} 317 | Total Misison : ${event.userData.mission.length} 318 | 319 | BALANCE 320 | MTB : ${event.userData.coin} 321 | TON : ${event.userData.ton} 322 | NOT : ${event.userData.notCoin} 323 | 324 | BOSS INFO 325 | Boss Max HP : ${event.bossInfo.maxHp} 326 | Current HP : ${event.bossInfo.currentHp} 327 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 328 | `, 329 | }); 330 | 331 | const unCompleteMissions = event.missions.filter( 332 | (item) => 333 | !item.completed && item.id != 6 && item.id != 4 && item.id != 2 334 | ); 335 | const unCompleteMissionsIds = unCompleteMissions.map((item) => item.id); 336 | for (const missionId of unCompleteMissionsIds) { 337 | console.log(event.completeMissions(missionId)); 338 | await client.send(event.completeMissions(missionId)); 339 | await new Promise((resolve) => { 340 | client.once("message", async (wsMsg) => { 341 | const messages = JSON.parse(wsMsg.toString("utf8")); 342 | const rc = messages.code; 343 | const data = messages.data; 344 | // console.log(messages); 345 | 346 | if (rc == 19 || rc == 28) { 347 | const missionDetail = unCompleteMissions.find( 348 | (item) => item.id === missionId 349 | ); 350 | 351 | twisters.put(1, { 352 | text: ` 353 | Status : Missions id ${missionId} (${missionDetail.des}) Completed 354 | 355 | USER DATA 356 | Username : ${event.userData.name} 357 | Id : ${event.userData.id} 358 | Total Misison : ${event.userData.mission.length} 359 | 360 | BALANCE 361 | MTB : ${event.userData.coin} 362 | TON : ${event.userData.ton} 363 | NOT : ${event.userData.notCoin} 364 | 365 | BOSS INFO 366 | Boss Max HP : ${event.bossInfo.maxHp} 367 | Current HP : ${event.bossInfo.currentHp} 368 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 369 | `, 370 | }); 371 | await client.send(event.claimMission(missionId)); 372 | await new Promise((resolve) => { 373 | client.once("message", async (wsMsg) => { 374 | const messages = JSON.parse(wsMsg.toString("utf8")); 375 | const rc = messages.code; 376 | const data = messages.data; 377 | // console.log(messages); 378 | 379 | if (rc == 19 || rc == 3 || rc == 12) { 380 | twisters.put(1, { 381 | text: ` 382 | Status : Missions id ${missionId} (${missionDetail.des}) Claimed 383 | 384 | USER DATA 385 | Username : ${event.userData.name} 386 | Id : ${event.userData.id} 387 | Total Misison : ${event.userData.mission.length} 388 | 389 | BALANCE 390 | MTB : ${event.userData.coin} 391 | TON : ${event.userData.ton} 392 | NOT : ${event.userData.notCoin} 393 | 394 | BOSS INFO 395 | Boss Max HP : ${event.bossInfo.maxHp} 396 | Current HP : ${event.bossInfo.currentHp} 397 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 398 | `, 399 | }); 400 | } 401 | resolve(); 402 | }); 403 | }); 404 | } 405 | resolve(); 406 | }); 407 | }); 408 | } 409 | console.log("-> All missions completed"); 410 | resolve(); 411 | } catch (error) { 412 | reject(error); 413 | } 414 | }); 415 | } 416 | 417 | async function getBossInfo(attack = false, msg = "") { 418 | return new Promise(async (resolve, reject) => { 419 | try { 420 | const handleRes = async (wsMsg) => { 421 | const messages = JSON.parse(wsMsg.toString("utf8")); 422 | const rc = messages.code; 423 | const data = messages.data; 424 | // console.log(messages); 425 | 426 | if (rc == 10 || rc == 8 || rc == 11) { 427 | event.setBossInfo(data, rc); 428 | twisters.put(1, { 429 | text: ` 430 | Status : ${attack ? `Attacking ${msg}` : "Getting Boss Info Event"} 431 | 432 | USER DATA 433 | Username : ${event.userData.name} 434 | Id : ${event.userData.id} 435 | Total Misison : ${event.userData.mission.length} 436 | 437 | BALANCE 438 | MTB : ${event.userData.coin} 439 | TON : ${event.userData.ton} 440 | NOT : ${event.userData.notCoin} 441 | 442 | BOSS INFO 443 | Boss Max HP : ${event.bossInfo.maxHp} 444 | Current HP : ${event.bossInfo.currentHp} 445 | Colldown : ${await millisecondsToHoursAndMinutes(event.bossInfo.remain)} 446 | 447 | `, 448 | }); 449 | 450 | client.off("message", handleRes); 451 | if (attack) { 452 | setTimeout(() => resolve(), 1000); 453 | } else { 454 | resolve(); 455 | } 456 | } else if (rc == 1000) { 457 | client.off("message", handleRes); 458 | resolve(); 459 | } 460 | }; 461 | if (attack) { 462 | twisters.put(1, { 463 | text: ` 464 | Status : Attacking ${msg} 465 | 466 | USER DATA 467 | Username : ${event.userData.name} 468 | Id : ${event.userData.id} 469 | Total Misison : ${event.userData.mission.length} 470 | 471 | BALANCE 472 | MTB : ${event.userData.coin} 473 | TON : ${event.userData.ton} 474 | NOT : ${event.userData.notCoin} 475 | 476 | BOSS INFO 477 | Boss Max HP : ${event.bossInfo.maxHp} 478 | Current HP : ${event.bossInfo.currentHp} 479 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 480 | `, 481 | }); 482 | await client.send(event.attackBoss()); 483 | } else { 484 | await client.send(event.getBossInfo()); 485 | twisters.put(1, { 486 | text: ` 487 | Status : Getting Boss Info Event 488 | 489 | USER DATA 490 | Username : ${event.userData.name} 491 | Id : ${event.userData.id} 492 | Total Misison : ${event.userData.mission.length} 493 | 494 | BALANCE 495 | MTB : ${event.userData.coin} 496 | TON : ${event.userData.ton} 497 | NOT : ${event.userData.notCoin} 498 | 499 | BOSS INFO 500 | Boss Max HP : ${event.bossInfo.maxHp} 501 | Current HP : ${event.bossInfo.currentHp} 502 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 503 | `, 504 | }); 505 | } 506 | await client.on("message", handleRes); 507 | } catch (error) { 508 | reject(error); 509 | } 510 | }); 511 | } 512 | 513 | async function delay(ms) { 514 | return new Promise((resolve) => { 515 | setTimeout(resolve, ms); 516 | }); 517 | } 518 | 519 | function millisecondsToHoursAndMinutes(milliseconds) { 520 | const hours = Math.floor(milliseconds / (1000 * 60 * 60)); 521 | const remainingMilliseconds = milliseconds % (1000 * 60 * 60); 522 | const minutes = Math.round(remainingMilliseconds / (1000 * 60)); 523 | 524 | return hours + " Hours " + minutes + " Minutes"; 525 | } 526 | 527 | async function startBot(acc) { 528 | return new Promise(async (resolve, reject) => { 529 | const idx = accountList.indexOf(acc); 530 | console.log("Using Account " + (idx + 1)); 531 | 532 | twisters.put(1, { 533 | text: ` 534 | Status : Running Bot for Account : ${idx + 1} 535 | 536 | USER DATA 537 | Username : ${event.userData.name} 538 | Id : ${event.userData.id} 539 | Total Misison : ${event.userData.mission.length} 540 | 541 | BALANCE 542 | MTB : ${event.userData.coin} 543 | TON : ${event.userData.ton} 544 | NOT : ${event.userData.notCoin} 545 | 546 | BOSS INFO 547 | Boss Max HP : ${event.bossInfo.maxHp} 548 | Current HP : ${event.bossInfo.currentHp} 549 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 550 | `, 551 | }); 552 | // try { 553 | var userData = accountList[idx][0]; 554 | 555 | await initWebSocket() 556 | .then(async (_) => { 557 | if (client.readyState == WebSocket.OPEN) { 558 | await getUserInfo(userData) 559 | .then(async (_) => { 560 | var accountID = event.userData.id; 561 | await autoCompleteMissions() 562 | .then(async () => { 563 | const availableResources = []; 564 | for (const [id, value] of Object.entries( 565 | event.userData.resource 566 | )) { 567 | if (value !== 0) { 568 | availableResources.push({ id, value }); 569 | } 570 | } 571 | for (const res of availableResources) { 572 | for (let i = 0; i < res.value; i++) { 573 | try { 574 | await openChest(res.id); 575 | } catch (err) { 576 | throw err; 577 | } 578 | } 579 | } 580 | console.log(`-> All chest claimed`); 581 | await startMining() 582 | .then(async (_) => { 583 | await getBossInfo(false) 584 | .then(async () => { 585 | if (event.bossInfo.remain != 0) { 586 | twisters.remove(1); 587 | console.log( 588 | "-> Account " + 589 | event.userData.id + 590 | " In cooldown for " + 591 | millisecondsToHoursAndMinutes( 592 | event.bossInfo.remain 593 | ) 594 | ); 595 | console.log(); 596 | 597 | // Update account status to true 598 | accountList[idx][1] = true; 599 | resolve(); 600 | } else { 601 | accountList[idx][1] = false; 602 | twisters.put(1, { 603 | text: ` 604 | Status : Boss Currently have ${event.bossInfo.currentHp} HP 605 | 606 | USER DATA 607 | Username : ${event.userData.name} 608 | Id : ${event.userData.id} 609 | Total Misison : ${event.userData.mission.length} 610 | 611 | Boss Max HP : ${event.bossInfo.maxHp} 612 | Current HP : ${event.bossInfo.currentHp} 613 | Colldown : ${millisecondsToHoursAndMinutes( 614 | event.bossInfo.remain 615 | )} 616 | Attacking for ${event.bossInfo.currentHp} Times 617 | `, 618 | }); 619 | while (event.bossInfo.currentHp != 0) { 620 | await getBossInfo( 621 | true, 622 | `- (${event.bossInfo.currentHp - 1} Left)` 623 | ); 624 | } 625 | twisters.put(1, { 626 | text: ` 627 | Status : Boss HP now ${event.bossInfo.currentHp} HP 628 | 629 | USER DATA 630 | Username : ${event.userData.name} 631 | Id : ${event.userData.id} 632 | Total Misison : ${event.userData.mission.length} 633 | 634 | Boss Max HP : ${event.bossInfo.maxHp} 635 | Current HP : ${event.bossInfo.currentHp} 636 | Colldown : ${millisecondsToHoursAndMinutes( 637 | event.bossInfo.remain 638 | )} 639 | 640 | Claiming Chest 641 | `, 642 | }); 643 | twisters.remove(1); 644 | console.log("-> Claiming boss chest"); 645 | await claimBossChest().then(async () => { 646 | twisters.remove(1); 647 | await startBot(acc) 648 | .then(resolve) 649 | .catch((err) => reject(err)); 650 | }); 651 | } 652 | }) 653 | .catch((err) => { 654 | throw err; 655 | }); 656 | }) 657 | .catch((err) => { 658 | throw err; 659 | }); 660 | }) 661 | .catch(async (err) => { 662 | throw err; 663 | }); 664 | }) 665 | .catch((err) => { 666 | throw err; 667 | }); 668 | } else { 669 | throw err; 670 | } 671 | }) 672 | .catch(async (err) => { 673 | throw err; 674 | }); 675 | // } catch (error) { 676 | // twisters.remove(1); 677 | // console.log("ERROR " + error + " , Retrying"); 678 | // await startBot(acc) 679 | // .then(resolve) 680 | // .catch((err) => reject(err)); 681 | // } 682 | }); 683 | } 684 | 685 | async function initBot() { 686 | twisters.remove(1); 687 | accountList = account.map((item) => [item, false]); 688 | for (const acc of accountList) { 689 | console.log(); 690 | await startBot(acc); 691 | client.close(); 692 | console.log(); 693 | await delay(1000); 694 | } 695 | twisters.remove(1); 696 | twisters.put(1, { 697 | text: ` 698 | Status : All accounts are in cooldown waiting for 5 Minutes 699 | `, 700 | }); 701 | console.log(); 702 | await delay(300000); // Wait for 5 minutes 703 | twisters.put(1, { 704 | text: ` 705 | Status : Restarting with the first account 706 | 707 | USER DATA 708 | Username : ${event.userData.name} 709 | Id : ${event.userData.id} 710 | Total Misison : ${event.userData.mission.length} 711 | 712 | Boss Max HP : ${event.bossInfo.maxHp} 713 | Current HP : ${event.bossInfo.currentHp} 714 | Colldown : ${millisecondsToHoursAndMinutes(event.bossInfo.remain)} 715 | `, 716 | }); 717 | await initBot(); 718 | } 719 | var accountList; 720 | (async () => { 721 | try { 722 | await initBot(); 723 | } catch (error) { 724 | console.log("Error During executing bot", error); 725 | console.log(); 726 | console.log("Restarting from first account..."); 727 | console.log(); 728 | await initBot(); 729 | } 730 | })(); 731 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "metaboss", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "metaboss", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "twisters": "^1.1.0", 13 | "ws": "^8.17.0" 14 | } 15 | }, 16 | "node_modules/ansi-regex": { 17 | "version": "5.0.1", 18 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 19 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 20 | "engines": { 21 | "node": ">=8" 22 | } 23 | }, 24 | "node_modules/ansi-styles": { 25 | "version": "4.3.0", 26 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 27 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 28 | "dependencies": { 29 | "color-convert": "^2.0.1" 30 | }, 31 | "engines": { 32 | "node": ">=8" 33 | }, 34 | "funding": { 35 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 36 | } 37 | }, 38 | "node_modules/cli-cursor": { 39 | "version": "3.1.0", 40 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", 41 | "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", 42 | "dependencies": { 43 | "restore-cursor": "^3.1.0" 44 | }, 45 | "engines": { 46 | "node": ">=8" 47 | } 48 | }, 49 | "node_modules/color-convert": { 50 | "version": "2.0.1", 51 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 52 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 53 | "dependencies": { 54 | "color-name": "~1.1.4" 55 | }, 56 | "engines": { 57 | "node": ">=7.0.0" 58 | } 59 | }, 60 | "node_modules/color-name": { 61 | "version": "1.1.4", 62 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 63 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 64 | }, 65 | "node_modules/emoji-regex": { 66 | "version": "8.0.0", 67 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 68 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 69 | }, 70 | "node_modules/is-fullwidth-code-point": { 71 | "version": "3.0.0", 72 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 73 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 74 | "engines": { 75 | "node": ">=8" 76 | } 77 | }, 78 | "node_modules/mimic-fn": { 79 | "version": "2.1.0", 80 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 81 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 82 | "engines": { 83 | "node": ">=6" 84 | } 85 | }, 86 | "node_modules/mute-stream": { 87 | "version": "0.0.8", 88 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", 89 | "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" 90 | }, 91 | "node_modules/onetime": { 92 | "version": "5.1.2", 93 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 94 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 95 | "dependencies": { 96 | "mimic-fn": "^2.1.0" 97 | }, 98 | "engines": { 99 | "node": ">=6" 100 | }, 101 | "funding": { 102 | "url": "https://github.com/sponsors/sindresorhus" 103 | } 104 | }, 105 | "node_modules/restore-cursor": { 106 | "version": "3.1.0", 107 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", 108 | "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", 109 | "dependencies": { 110 | "onetime": "^5.1.0", 111 | "signal-exit": "^3.0.2" 112 | }, 113 | "engines": { 114 | "node": ">=8" 115 | } 116 | }, 117 | "node_modules/signal-exit": { 118 | "version": "3.0.7", 119 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 120 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 121 | }, 122 | "node_modules/string-width": { 123 | "version": "4.2.3", 124 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 125 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 126 | "dependencies": { 127 | "emoji-regex": "^8.0.0", 128 | "is-fullwidth-code-point": "^3.0.0", 129 | "strip-ansi": "^6.0.1" 130 | }, 131 | "engines": { 132 | "node": ">=8" 133 | } 134 | }, 135 | "node_modules/strip-ansi": { 136 | "version": "6.0.1", 137 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 138 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 139 | "dependencies": { 140 | "ansi-regex": "^5.0.1" 141 | }, 142 | "engines": { 143 | "node": ">=8" 144 | } 145 | }, 146 | "node_modules/twisters": { 147 | "version": "1.1.0", 148 | "resolved": "https://registry.npmjs.org/twisters/-/twisters-1.1.0.tgz", 149 | "integrity": "sha512-sl1XvWbIF7H8tuGXkjcUMrxKeyhco0fhzckXHZFJ9+IIDQPy/tLkKkRSWC85D883nJaMdJxxkNAO00hN/TD/Dg==", 150 | "dependencies": { 151 | "cli-cursor": "^3.1.0", 152 | "mute-stream": "^0.0.8", 153 | "string-width": "^4.2.0", 154 | "wrap-ansi": "^7.0.0" 155 | } 156 | }, 157 | "node_modules/wrap-ansi": { 158 | "version": "7.0.0", 159 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 160 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 161 | "dependencies": { 162 | "ansi-styles": "^4.0.0", 163 | "string-width": "^4.1.0", 164 | "strip-ansi": "^6.0.0" 165 | }, 166 | "engines": { 167 | "node": ">=10" 168 | }, 169 | "funding": { 170 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 171 | } 172 | }, 173 | "node_modules/ws": { 174 | "version": "8.17.0", 175 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", 176 | "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", 177 | "engines": { 178 | "node": ">=10.0.0" 179 | }, 180 | "peerDependencies": { 181 | "bufferutil": "^4.0.1", 182 | "utf-8-validate": ">=5.0.2" 183 | }, 184 | "peerDependenciesMeta": { 185 | "bufferutil": { 186 | "optional": true 187 | }, 188 | "utf-8-validate": { 189 | "optional": true 190 | } 191 | } 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "metaboss", 3 | "version": "1.0.2", 4 | "description": "Metaboss Bot", 5 | "type": "module", 6 | "main": "index.js", 7 | "scripts": { 8 | "start": "node index.js", 9 | "test": "node test.js" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/Widiskel/metaboss-bot.git" 14 | }, 15 | "keywords": [ 16 | "metaboss" 17 | ], 18 | "author": "Widiskel", 19 | "license": "ISC", 20 | "bugs": { 21 | "url": "https://github.com/Widiskel/metaboss-bot/issues" 22 | }, 23 | "homepage": "https://github.com/Widiskel/metaboss-bot#readme", 24 | "dependencies": { 25 | "twisters": "^1.1.0", 26 | "ws": "^8.17.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | account.js -------------------------------------------------------------------------------- /src/account_tmp.js: -------------------------------------------------------------------------------- 1 | const account = [ 2 | "query_id=xxx", 3 | { 4 | code: 1, 5 | type: 2, 6 | data: { 7 | id: 0, 8 | username: "X", 9 | hash: "X", 10 | timeAuth: 0, 11 | data: "query_id=xxx", 12 | }, 13 | }, 14 | "user=xxx", 15 | ]; 16 | 17 | export { account }; 18 | -------------------------------------------------------------------------------- /src/event.js: -------------------------------------------------------------------------------- 1 | import { Helper } from "./utils/helper.js"; 2 | 3 | var missions = []; 4 | 5 | var bossInfo = { 6 | maxHp: 100, 7 | currentHp: 0, 8 | remain: 0, 9 | type: 0, 10 | }; 11 | 12 | var userData = { 13 | name: undefined, 14 | id: undefined, 15 | coin: 0, 16 | ton: 0, 17 | notCoin: 0, 18 | mission: [], 19 | resource: [], 20 | }; 21 | 22 | var miningData = { 23 | timeConst: undefined, 24 | timeEndMining: undefined, 25 | mineType: 3, //GOLD MINING 26 | timeRemaining: undefined, 27 | }; 28 | 29 | function setMission(data) { 30 | missions = data; 31 | } 32 | 33 | function setUserData(data) { 34 | userData = data; 35 | } 36 | 37 | function setMiningData(data) { 38 | miningData = data; 39 | } 40 | 41 | function setBossInfo(data, code) { 42 | if (code == 8) { 43 | bossInfo = data; 44 | } else if (code == 10) { 45 | bossInfo.currentHp = data.hpBoss; 46 | userData.coin = data.coin; 47 | } else if (code == 11) { 48 | bossInfo.remain = data.remain; 49 | } 50 | } 51 | function getUserInfo(userData) { 52 | // console.log(userData); 53 | if (userData.code) { 54 | return JSON.stringify(userData); 55 | } else { 56 | const data = Helper.teleQueryConvert(userData); 57 | // console.log(data); 58 | const sendData = { 59 | code: 1, 60 | type: 2, 61 | data: { 62 | id: data.user.id, 63 | username: data.user.first_name + " " + data.user.last_name, 64 | hash: data.hash, 65 | timeAuth: data.auth_date, 66 | data: userData, 67 | }, 68 | }; 69 | // console.log(sendData); 70 | return JSON.stringify(sendData); 71 | } 72 | } 73 | 74 | function claimBossChest() { 75 | return JSON.stringify({ 76 | code: 1, 77 | type: 11, 78 | data: { type: 10 }, 79 | }); 80 | } 81 | function claimChest(id) { 82 | return JSON.stringify({ 83 | code: 1, 84 | type: 11, 85 | data: { type: id }, 86 | }); 87 | } 88 | 89 | function getBossInfo() { 90 | return JSON.stringify({ code: 1, type: 7, data: {} }); 91 | } 92 | function startMining(type) { 93 | return JSON.stringify({ 94 | code: 1, 95 | type: 45, 96 | data: { mineType: type }, 97 | }); 98 | } 99 | 100 | function claimMission(id) { 101 | return JSON.stringify({ code: 1, type: 15, data: { type: id } }); 102 | } 103 | 104 | function completeMissions(id) { 105 | return JSON.stringify({ code: 1, type: 50, data: { type: id } }); 106 | } 107 | 108 | function attackBoss() { 109 | return JSON.stringify({ code: 1, type: 3, data: {} }); 110 | } 111 | 112 | export { 113 | missions, 114 | bossInfo, 115 | userData, 116 | miningData, 117 | setUserData, 118 | setMission, 119 | claimBossChest, 120 | getUserInfo, 121 | getBossInfo, 122 | startMining, 123 | setBossInfo, 124 | attackBoss, 125 | setMiningData, 126 | completeMissions, 127 | claimMission, 128 | claimChest, 129 | }; 130 | -------------------------------------------------------------------------------- /src/utils/helper.js: -------------------------------------------------------------------------------- 1 | export class Helper { 2 | static teleQueryConvert(dataString) { 3 | const pairs = dataString.split("&"); 4 | const result = {}; 5 | 6 | pairs.forEach((pair) => { 7 | const [key, value] = pair.split("="); 8 | 9 | if (key === "user") { 10 | result[key] = JSON.parse(decodeURIComponent(value)); 11 | } else if (!isNaN(value)) { 12 | result[key] = Number(value); 13 | } else if (value === "true" || value === "false") { 14 | result[key] = value === "true"; 15 | } else { 16 | result[key] = decodeURIComponent(value); 17 | } 18 | }); 19 | 20 | return result; 21 | } 22 | } 23 | --------------------------------------------------------------------------------