RubixYT1

DianondBot v7.1 textwall [OLD WARNING!]

Nov 28th, 2025
20
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 43.00 KB | None | 0 0
  1. // TextWall Bot - diamondbot v7.1
  2. // Fixed recursion and console-only command display
  3.  
  4. (async function() {
  5. 'use strict';
  6.  
  7. // Verify tw.2s4.me API is available
  8. if (typeof w === 'undefined') {
  9. console.error("TextWall API (w) not found! Make sure you're on tw.2s4.me");
  10. return;
  11. }
  12.  
  13. // Bot Configuration
  14. const BOT_CONFIG = {
  15. username: "diamondbot",
  16. color: 0, // Color index (0-15 for textwall)
  17. prefix: "\\", // Changed prefix to backslash
  18. authorizedUsers: ["Diamond25", "KiwiTest"], // List of authorized users
  19. messageDelay: 150, // Delay between messages in ms
  20. position: { x: 0, y: 0 },
  21. heightSafetyEnabled: true, // Height safety for tetration
  22. lastAuthorityMessage: "", // Track last authority message to prevent recursion
  23. authorityEchoEnabled: false // Toggle authority echo to prevent recursion
  24. };
  25.  
  26. // State management
  27. const state = {
  28. wall: "",
  29. subwall: "",
  30. perms: 0, // 0=user, 1=member, 2=owner
  31. isRegistered: false,
  32. isAdmin: false,
  33. readonly: false,
  34. hidecursors: false,
  35. disablechat: false,
  36. disablecolor: false,
  37. disablebraille: false,
  38. members: [],
  39. walllist: [],
  40. activeTimers: new Map(),
  41. commandCooldowns: new Map(),
  42. messageQueue: [],
  43. isProcessingQueue: false,
  44. lastMessageTime: 0,
  45. cursors: new Map(),
  46. adminUsers: new Set(), // Track users with ADMIN tag
  47. processedMessages: new Set() // Track processed messages to prevent recursion
  48. };
  49.  
  50. // Color mappings for textwall
  51. const COLORS = {
  52. "#000000": 0, "#ffffff": 1, "#ff0000": 2, "#00ff00": 3,
  53. "#0000ff": 4, "#ffff00": 5, "#ff00ff": 6, "#00ffff": 7,
  54. "#808080": 8, "#ff8800": 9, "#8800ff": 10, "#0088ff": 11,
  55. "#88ff00": 12, "#ff0088": 13, "#884400": 14, "#448800": 15
  56. };
  57.  
  58. // Command pages
  59. const COMMAND_PAGES = {
  60. 1: [
  61. { cmd: "help", desc: "Show command pages", auth: false },
  62. { cmd: "calculate", desc: "Calculate p1^p2", auth: false },
  63. { cmd: "calc2", desc: "Calculate p1^^p2 (tetration)", auth: false },
  64. { cmd: "rng", desc: "Random number between min and max", auth: false },
  65. { cmd: "timer", desc: "Set a timer (h m s)", auth: false }
  66. ],
  67. 2: [
  68. { cmd: "say", desc: "Make bot say something", auth: false },
  69. { cmd: "status", desc: "Show bot status", auth: false },
  70. { cmd: "pos", desc: "Show current position", auth: false },
  71. { cmd: "page", desc: "Show detailed page info", auth: false },
  72. { cmd: "members", desc: "List wall members", auth: false }
  73. ],
  74. 3: [
  75. { cmd: "walls", desc: "List available subwalls", auth: false },
  76. { cmd: "authlist", desc: "Show authorized users", auth: false },
  77. { cmd: "to", desc: "Teleport bot to X Y (Authority)", auth: true },
  78. { cmd: "colorid", desc: "Change bot color (Authority)", auth: true },
  79. { cmd: "addauth", desc: "Add user to authority list (Authority)", auth: true }
  80. ],
  81. 4: [
  82. { cmd: "removeauth", desc: "Remove user from authority (Authority)", auth: true },
  83. { cmd: "disableHS", desc: "Toggle height safety (Authority)", auth: true },
  84. { cmd: "echoauth", desc: "Toggle authority echo (Authority)", auth: true }
  85. ]
  86. };
  87.  
  88. // Load break_eternity.js
  89. async function loadBreakEternity() {
  90. if (typeof window.Decimal !== 'undefined') {
  91. console.log("✓ Break Eternity already loaded");
  92. return true;
  93. }
  94.  
  95. const sources = [
  96. 'https://cdn.jsdelivr.net/npm/break_eternity.js@latest/break_eternity.min.js',
  97. 'https://unpkg.com/break_eternity.js@latest/dist/break_eternity.min.js',
  98. 'https://cdnjs.cloudflare.com/ajax/libs/break_eternity.js/1.3.0/break_eternity.min.js'
  99. ];
  100.  
  101. for (let src of sources) {
  102. try {
  103. await loadScript(src);
  104. if (typeof window.Decimal !== 'undefined') {
  105. console.log(`✓ Break Eternity loaded from: ${src}`);
  106. return true;
  107. }
  108. } catch (e) {
  109. console.warn(`Failed to load from ${src}`);
  110. }
  111. }
  112.  
  113. // Fallback implementation
  114. window.Decimal = createFallbackDecimal();
  115. console.log("✓ Using fallback Decimal implementation");
  116. return true;
  117. }
  118.  
  119. function loadScript(src) {
  120. return new Promise((resolve, reject) => {
  121. const script = document.createElement('script');
  122. script.src = src;
  123. script.onload = resolve;
  124. script.onerror = reject;
  125. document.head.appendChild(script);
  126. });
  127. }
  128.  
  129. function createFallbackDecimal() {
  130. return class Decimal {
  131. constructor(value) {
  132. this.value = typeof value === 'string' || typeof value === 'number'
  133. ? parseFloat(value) || 0
  134. : value?.value || 0;
  135. }
  136.  
  137. static pow(base, exp) {
  138. const b = base instanceof Decimal ? base.value : parseFloat(base);
  139. const e = exp instanceof Decimal ? exp.value : parseFloat(exp);
  140.  
  141. if (e === 0) return new Decimal(1);
  142. if (b === 0) return new Decimal(0);
  143.  
  144. let result;
  145. if (Math.abs(e) > 308) {
  146. result = e > 0 ? Infinity : 0;
  147. } else {
  148. result = Math.pow(b, e);
  149. }
  150. return new Decimal(result);
  151. }
  152.  
  153. static tetrate(base, height) {
  154. const b = base instanceof Decimal ? base.value : parseFloat(base);
  155. const h = parseInt(height);
  156.  
  157. if (h === 0) return new Decimal(1);
  158. if (h === 1) return new Decimal(b);
  159. if (b === 0) return new Decimal(0);
  160.  
  161. const maxHeight = BOT_CONFIG.heightSafetyEnabled ? 5 : 10;
  162. let result = b;
  163. for (let i = 1; i < h && i < maxHeight; i++) {
  164. result = Math.pow(b, result);
  165. if (!isFinite(result)) break;
  166. }
  167. return new Decimal(result);
  168. }
  169.  
  170. toString() {
  171. if (!isFinite(this.value)) return this.value > 0 ? "Infinity" : "-Infinity";
  172. if (Math.abs(this.value) < 1e-6) return "0";
  173. if (Math.abs(this.value) < 1e6 && Math.abs(this.value) > 1e-3) {
  174. return this.value.toString();
  175. }
  176. return this.value.toExponential(2);
  177. }
  178. };
  179. }
  180.  
  181. // Main Bot Class
  182. class TextWallBot {
  183. constructor(config) {
  184. this.config = config;
  185. this.state = state;
  186. this.eventHandlers = {};
  187. this.running = true;
  188. }
  189.  
  190. async init() {
  191. console.log("═══════════════════════════════════");
  192. console.log(" TextWall Bot v7.1 Initializing ");
  193. console.log("═══════════════════════════════════");
  194.  
  195. // Load dependencies
  196. await loadBreakEternity();
  197.  
  198. // Set up all event listeners
  199. this.setupEventListeners();
  200.  
  201. // Set username
  202. this.setUsername(this.config.username);
  203.  
  204. // Set initial color
  205. this.setColor(this.config.color);
  206.  
  207. // Initial position
  208. this.teleportCursor(0, 0);
  209.  
  210. // Announce bot is online after a short delay
  211. setTimeout(() => {
  212. this.sendMessage(`${this.config.username} v7.1 online! Type ${this.config.prefix}help for commands`);
  213. }, 2000);
  214.  
  215. console.log("✓ Bot initialized successfully!");
  216. console.log(`✓ Prefix: ${this.config.prefix}`);
  217. console.log(`✓ Authorized users: ${this.config.authorizedUsers.join(', ')}`);
  218. console.log("✓ Type window.showCommands() to see all commands in console");
  219. console.log("═══════════════════════════════════");
  220. }
  221.  
  222. setupEventListeners() {
  223. // Store handlers for cleanup
  224. this.eventHandlers = {
  225. // Connection events
  226. join: (data) => this.onJoin(data),
  227. alert: (data) => this.onAlert(data),
  228.  
  229. // Chat events
  230. msg: (data) => this.onMessage(data),
  231.  
  232. // Editor events
  233. edit: (data) => this.onEdit(data),
  234. protect: (data) => this.onProtect(data),
  235. clear: (data) => this.onClear(data),
  236.  
  237. // Cursor events
  238. cursor: (data) => this.onCursor(data),
  239. cursorleft: (id) => this.onCursorLeft(id),
  240.  
  241. // Permission events
  242. perms: (level) => this.onPerms(level),
  243. memberadded: (member) => this.onMemberAdded(member),
  244. memberlist: (members) => this.onMemberList(members),
  245. walllist: (walls) => this.onWallList(walls),
  246.  
  247. // State events
  248. readonly: (state) => this.onReadonly(state),
  249. hidecursors: (state) => this.onHideCursors(state),
  250. disablechat: (state) => this.onDisableChat(state),
  251. disablecolor: (state) => this.onDisableColor(state),
  252. disablebraille: (state) => this.onDisableBraille(state),
  253.  
  254. // Account events
  255. nametaken: () => this.onNameTaken(),
  256. passfail: () => this.onPassFail(),
  257. tokenfail: () => this.onTokenFail(),
  258. regclosed: () => this.onRegClosed(),
  259. namechanged: (name) => this.onNameChanged(name),
  260. accountdeleted: () => this.onAccountDeleted(),
  261.  
  262. // Heartbeat
  263. pong: (ms) => this.onPong(ms)
  264. };
  265.  
  266. // Register all event listeners
  267. for (let [event, handler] of Object.entries(this.eventHandlers)) {
  268. if (w && w.on) {
  269. w.on(event, handler);
  270. }
  271. }
  272.  
  273. console.log(`✓ Registered ${Object.keys(this.eventHandlers).length} event listeners`);
  274. }
  275.  
  276. cleanup() {
  277. this.running = false;
  278.  
  279. // Remove all event listeners
  280. for (let [event, handler] of Object.entries(this.eventHandlers)) {
  281. if (w && w.off) {
  282. w.off(event, handler);
  283. }
  284. }
  285.  
  286. // Clear timers
  287. this.state.activeTimers.forEach(timer => {
  288. clearTimeout(timer.timeout);
  289. if (timer.intervalId) clearInterval(timer.intervalId);
  290. });
  291.  
  292. console.log("✓ Bot cleaned up");
  293. }
  294.  
  295. // Check if user has authority
  296. isAuthorized(username, isAdmin) {
  297. // Admins always have authority
  298. if (isAdmin) {
  299. this.state.adminUsers.add(username);
  300. return true;
  301. }
  302.  
  303. // Check if user is in authorized list
  304. return this.config.authorizedUsers.includes(username);
  305. }
  306.  
  307. // Event Handlers
  308. onJoin(data) {
  309. this.state.wall = data.wall || "";
  310. this.state.subwall = data.subwall || "";
  311. console.log(`📍 Joined: ${this.state.wall}/${this.state.subwall}`);
  312. }
  313.  
  314. onAlert(data) {
  315. console.log(`⚠️ Server Alert: ${data.message}`);
  316. }
  317.  
  318. onMessage(data) {
  319. if (!data || !data.msg) return;
  320.  
  321. // Skip bot's own messages to prevent recursion
  322. if (data.nick === this.config.username) return;
  323.  
  324. const message = data.msg.trim();
  325. const sender = data.nick || "Unknown";
  326. const isAdmin = data.isAdmin || false;
  327.  
  328. // Create unique message ID to prevent duplicate processing
  329. const messageId = `${sender}-${message}-${Date.now()}`;
  330.  
  331. // Skip if already processed (prevents recursion)
  332. if (this.state.processedMessages.has(messageId)) return;
  333.  
  334. // Mark as processed
  335. this.state.processedMessages.add(messageId);
  336.  
  337. // Clean up old processed messages (keep only last 100)
  338. if (this.state.processedMessages.size > 100) {
  339. const messages = Array.from(this.state.processedMessages);
  340. messages.slice(0, messages.length - 100).forEach(msg => {
  341. this.state.processedMessages.delete(msg);
  342. });
  343. }
  344.  
  345. // Track admin users
  346. if (isAdmin) {
  347. this.state.adminUsers.add(sender);
  348. }
  349.  
  350. // Check authority
  351. const hasAuth = this.isAuthorized(sender, isAdmin);
  352.  
  353. // Log message with authority indicator if applicable
  354. if (hasAuth) {
  355. console.log(`🔑 [AUTHORITY] ${sender} ~ ${message}`);
  356.  
  357. // Only echo authority messages if enabled AND it's not a command AND not a duplicate
  358. if (this.config.authorityEchoEnabled &&
  359. !message.startsWith(this.config.prefix) &&
  360. this.config.lastAuthorityMessage !== `${sender}:${message}`) {
  361.  
  362. this.config.lastAuthorityMessage = `${sender}:${message}`;
  363. this.sendMessage(`[AUTHORITY] ${sender} ~ ${message}`);
  364. }
  365. } else {
  366. console.log(`💬 [${sender}${data.isRegistered ? ' ®' : ''}]: ${message}`);
  367. }
  368.  
  369. // Check for commands
  370. if (message.startsWith(this.config.prefix)) {
  371. this.handleCommand(message, sender, data);
  372. }
  373. }
  374.  
  375. onEdit(data) {
  376. if (data.edits && data.edits.length > 0) {
  377. console.log(`✏️ ${data.edits.length} edit(s) made`);
  378. }
  379. }
  380.  
  381. onProtect(data) {
  382. console.log(`🔒 Chunk ${data.cell} protection: ${data.protect ? 'ON' : 'OFF'}`);
  383. }
  384.  
  385. onClear(data) {
  386. console.log(`🧹 Area cleared: (${data.x1},${data.y1}) to (${data.x2},${data.y2})`);
  387. }
  388.  
  389. onCursor(data) {
  390. if (!data.id) return;
  391.  
  392. this.state.cursors.set(data.id, {
  393. name: data.n || "",
  394. location: data.l || [0, 0],
  395. color: data.c || 0
  396. });
  397.  
  398. if (data.n === this.config.username && data.l) {
  399. this.config.position.x = data.l[0];
  400. this.config.position.y = data.l[1];
  401. }
  402. }
  403.  
  404. onCursorLeft(id) {
  405. this.state.cursors.delete(id);
  406. }
  407.  
  408. onPerms(level) {
  409. this.state.perms = level;
  410. const permName = ['User', 'Member', 'Owner'][level] || 'Unknown';
  411. console.log(`🔑 Permission level: ${permName} (${level})`);
  412. }
  413.  
  414. onMemberAdded(member) {
  415. console.log(`➕ Member added: ${member}`);
  416. if (!this.state.members.includes(member)) {
  417. this.state.members.push(member);
  418. }
  419. }
  420.  
  421. onMemberList(members) {
  422. this.state.members = members || [];
  423. console.log(`👥 Members: ${this.state.members.join(', ') || 'None'}`);
  424. }
  425.  
  426. onWallList(walls) {
  427. this.state.walllist = walls || [];
  428. console.log(`📋 Available walls: ${walls.length / 2} wall(s)`);
  429. }
  430.  
  431. onReadonly(state) {
  432. this.state.readonly = state;
  433. if (state) console.log("📝 Wall is now READONLY");
  434. }
  435.  
  436. onHideCursors(state) {
  437. this.state.hidecursors = state;
  438. if (state) console.log("👤 Cursors are now HIDDEN");
  439. }
  440.  
  441. onDisableChat(state) {
  442. this.state.disablechat = state;
  443. if (state) console.log("🔇 Chat is DISABLED");
  444. }
  445.  
  446. onDisableColor(state) {
  447. this.state.disablecolor = state;
  448. if (state) console.log("🎨 Colors are DISABLED");
  449. }
  450.  
  451. onDisableBraille(state) {
  452. this.state.disablebraille = state;
  453. if (state) console.log("⠿ Braille is DISABLED");
  454. }
  455.  
  456. onNameTaken() {
  457. console.log("❌ Name is already taken!");
  458. }
  459.  
  460. onPassFail() {
  461. console.log("❌ Invalid password!");
  462. }
  463.  
  464. onTokenFail() {
  465. console.log("❌ Invalid token!");
  466. }
  467.  
  468. onRegClosed() {
  469. console.log("❌ Registration is closed!");
  470. }
  471.  
  472. onNameChanged(name) {
  473. console.log(`✅ Name changed to: ${name}`);
  474. this.config.username = name;
  475. }
  476.  
  477. onAccountDeleted() {
  478. console.log("❌ Account has been deleted!");
  479. }
  480.  
  481. onPong(ms) {
  482. // Heartbeat
  483. }
  484.  
  485. // Command handling
  486. handleCommand(message, sender, messageData) {
  487. const commandLine = message.slice(this.config.prefix.length);
  488. const [command, ...args] = commandLine.split(/\s+/);
  489. const cmd = command.toLowerCase();
  490.  
  491. // Check cooldown
  492. const cooldownKey = `${cmd}-${sender}`;
  493. const lastUsed = this.state.commandCooldowns.get(cooldownKey) || 0;
  494. const now = Date.now();
  495.  
  496. const hasAuth = this.isAuthorized(sender, messageData.isAdmin);
  497.  
  498. if (now - lastUsed < 2000 && !hasAuth) {
  499. return; // 2 second cooldown (except for authorized users)
  500. }
  501.  
  502. this.state.commandCooldowns.set(cooldownKey, now);
  503.  
  504. // Execute command
  505. this.executeCommand(cmd, args, sender, messageData);
  506. }
  507.  
  508. executeCommand(command, args, sender, messageData) {
  509. const hasAuth = this.isAuthorized(sender, messageData.isAdmin);
  510.  
  511. const commands = {
  512. // Basic commands
  513. 'help': () => this.cmdHelp(args),
  514. 'calculate': () => this.cmdCalculate(args),
  515. 'calc2': () => this.cmdTetration(args),
  516. 'rng': () => this.cmdRandom(args),
  517.  
  518. // General commands
  519. 'timer': () => this.cmdTimer(args),
  520. 'say': () => this.cmdSay(args),
  521. 'status': () => this.cmdStatus(),
  522. 'pos': () => this.cmdPosition(),
  523. 'page': () => this.cmdPage(args),
  524.  
  525. // Info commands
  526. 'members': () => this.cmdMembers(),
  527. 'walls': () => this.cmdWalls(),
  528. 'authlist': () => this.cmdAuthList(),
  529.  
  530. // Authority commands
  531. 'to': () => hasAuth ? this.cmdTeleport(args) : this.sendMessage("Permission invalid - Authority required"),
  532. 'colorid': () => hasAuth ? this.cmdColor(args) : this.sendMessage("Permission invalid"),
  533. 'addauth': () => hasAuth ? this.cmdAddAuth(args) : this.sendMessage("Permission invalid - Authority required"),
  534. 'removeauth': () => hasAuth ? this.cmdRemoveAuth(args) : this.sendMessage("Permission invalid - Authority required"),
  535. 'disablehs': () => hasAuth ? this.cmdDisableHeightSafety() : this.sendMessage("Permission invalid - Authority required"),
  536. 'echoauth': () => hasAuth ? this.cmdToggleEcho() : this.sendMessage("Permission invalid - Authority required")
  537. };
  538.  
  539. const cmdFunc = commands[command];
  540. if (cmdFunc) {
  541. cmdFunc();
  542. }
  543. }
  544.  
  545. // Commands
  546. cmdHelp(args) {
  547. const page = parseInt(args[0]) || 1;
  548. const maxPage = Object.keys(COMMAND_PAGES).length;
  549.  
  550. if (page < 1 || page > maxPage) {
  551. this.sendMessage(`Invalid page. Use ${this.config.prefix}help 1-${maxPage}`);
  552. return;
  553. }
  554.  
  555. // Send page header
  556. this.sendMessage(`📖 Commands Page ${page}/${maxPage}:`);
  557.  
  558. // Send each command as separate message
  559. const commands = COMMAND_PAGES[page];
  560. commands.forEach((cmd, index) => {
  561. setTimeout(() => {
  562. this.sendMessage(`${this.config.prefix}${cmd.cmd}${cmd.auth ? ' 🔐' : ''} - ${cmd.desc}`);
  563. }, (index + 1) * 200);
  564. });
  565. }
  566.  
  567. cmdPage(args) {
  568. const page = parseInt(args[0]) || 1;
  569. const maxPage = Object.keys(COMMAND_PAGES).length;
  570.  
  571. if (page < 1 || page > maxPage) {
  572. this.sendMessage(`Invalid page. Pages: 1-${maxPage}`);
  573. return;
  574. }
  575.  
  576. this.sendMessage(`📄 Page ${page} Detailed Info:`);
  577.  
  578. const commands = COMMAND_PAGES[page];
  579. commands.forEach((cmd, i) => {
  580. setTimeout(() => {
  581. this.sendMessage(`${i+1}. ${this.config.prefix}${cmd.cmd} - ${cmd.desc}`);
  582. }, (i + 1) * 200);
  583. });
  584. }
  585.  
  586. cmdSay(args) {
  587. if (args.length < 1) {
  588. this.sendMessage(`Usage: ${this.config.prefix}say [message]`);
  589. return;
  590. }
  591.  
  592. const message = args.join(' ');
  593. this.sendMessage(message);
  594. }
  595.  
  596. cmdCalculate(args) {
  597. if (args.length < 2) {
  598. this.sendMessage(`Usage: ${this.config.prefix}calculate base exponent`);
  599. return;
  600. }
  601.  
  602. try {
  603. const base = args[0];
  604. const exp = args[1];
  605.  
  606. const result = window.Decimal.pow(new window.Decimal(base), new window.Decimal(exp));
  607. this.sendMessage(`${base}^${exp} = ${result.toString()}`);
  608. } catch (error) {
  609. this.sendMessage("Error: Invalid input for calculation");
  610. }
  611. }
  612.  
  613. cmdTetration(args) {
  614. if (args.length < 2) {
  615. this.sendMessage(`Usage: ${this.config.prefix}calc2 base height`);
  616. return;
  617. }
  618.  
  619. try {
  620. const base = args[0];
  621. const height = parseInt(args[1]);
  622.  
  623. if (height < 0 || !Number.isInteger(height)) {
  624. this.sendMessage("Height must be a non-negative integer");
  625. return;
  626. }
  627.  
  628. const maxHeight = this.config.heightSafetyEnabled ? 5 : 10;
  629. if (height > maxHeight) {
  630. this.sendMessage(`Height too large! Maximum is ${maxHeight}${this.config.heightSafetyEnabled ? ' (Height Safety ON)' : ' (Height Safety OFF)'}`);
  631. return;
  632. }
  633.  
  634. const result = window.Decimal.tetrate(new window.Decimal(base), height);
  635. this.sendMessage(`${base}^^${height} = ${result.toString()}`);
  636. } catch (error) {
  637. this.sendMessage("Error: Invalid input for tetration");
  638. }
  639. }
  640.  
  641. cmdRandom(args) {
  642. if (args.length < 2) {
  643. this.sendMessage(`Usage: ${this.config.prefix}rng min max`);
  644. return;
  645. }
  646.  
  647. const min = parseFloat(args[0]);
  648. const max = parseFloat(args[1]);
  649.  
  650. if (isNaN(min) || isNaN(max)) {
  651. this.sendMessage("Invalid input. Please provide valid numbers.");
  652. return;
  653. }
  654.  
  655. if (min > max) {
  656. this.sendMessage("Min must be less than or equal to max.");
  657. return;
  658. }
  659.  
  660. const randomNum = Math.random() * (max - min) + min;
  661. this.sendMessage(`Random number between ${min} and ${max}: ${randomNum.toFixed(2)}`);
  662. }
  663.  
  664. cmdTimer(args) {
  665. if (args.length < 3) {
  666. this.sendMessage(`Usage: ${this.config.prefix}timer hours minutes seconds (use 0 to skip)`);
  667. return;
  668. }
  669.  
  670. const hours = Math.max(0, parseInt(args[0]) || 0);
  671. const minutes = Math.max(0, parseInt(args[1]) || 0);
  672. const seconds = Math.max(0, parseInt(args[2]) || 0);
  673.  
  674. if (hours === 0 && minutes === 0 && seconds === 0) {
  675. this.sendMessage("Timer must have at least one non-zero value");
  676. return;
  677. }
  678.  
  679. if (hours > 24) {
  680. this.sendMessage("Maximum timer is 24 hours");
  681. return;
  682. }
  683.  
  684. const totalMs = (hours * 3600 + minutes * 60 + seconds) * 1000;
  685.  
  686. // Build display string (ignore 0 values)
  687. let timeStr = [];
  688. if (hours > 0) timeStr.push(`${hours}h`);
  689. if (minutes > 0) timeStr.push(`${minutes}m`);
  690. if (seconds > 0) timeStr.push(`${seconds}s`);
  691.  
  692. const timerId = Date.now();
  693.  
  694. this.sendMessage(`⏰ Timer set for ${timeStr.join(' ')} (ID: ${timerId})`);
  695.  
  696. // Create timer
  697. const timerObj = setTimeout(() => {
  698. this.sendMessage(`⏰ TIMER COMPLETE! ${timeStr.join(' ')} has elapsed (ID: ${timerId})`);
  699. this.state.activeTimers.delete(timerId);
  700. }, totalMs);
  701.  
  702. // Store timer
  703. this.state.activeTimers.set(timerId, {
  704. timeout: timerObj,
  705. duration: timeStr.join(' '),
  706. startTime: Date.now(),
  707. endTime: Date.now() + totalMs
  708. });
  709.  
  710. // Progress updates for long timers
  711. if (totalMs > 60000) {
  712. let updateCount = 0;
  713. const maxUpdates = 3;
  714. const updateInterval = Math.max(30000, totalMs / 4);
  715.  
  716. const intervalId = setInterval(() => {
  717. const timer = this.state.activeTimers.get(timerId);
  718. if (!timer || updateCount >= maxUpdates) {
  719. clearInterval(intervalId);
  720. return;
  721. }
  722.  
  723. const remaining = timer.endTime - Date.now();
  724. if (remaining > 1000) {
  725. const h = Math.floor(remaining / 3600000);
  726. const m = Math.floor((remaining % 3600000) / 60000);
  727. const s = Math.floor((remaining % 60000) / 1000);
  728.  
  729. let remStr = [];
  730. if (h > 0) remStr.push(`${h}h`);
  731. if (m > 0) remStr.push(`${m}m`);
  732. if (s > 0) remStr.push(`${s}s`);
  733.  
  734. this.sendMessage(`⏰ Timer ${timerId}: ${remStr.join(' ')} remaining`);
  735. updateCount++;
  736. }
  737. }, updateInterval);
  738.  
  739. this.state.activeTimers.get(timerId).intervalId = intervalId;
  740. }
  741. }
  742.  
  743. cmdStatus() {
  744. const status = [
  745. `Wall: ${this.state.wall}/${this.state.subwall}`,
  746. `Perms: ${['User', 'Member', 'Owner'][this.state.perms]}`,
  747. `Pos: (${this.config.position.x}, ${this.config.position.y})`,
  748. `Timers: ${this.state.activeTimers.size}`,
  749. `Color: ${this.config.color}`,
  750. `HS: ${this.config.heightSafetyEnabled ? 'ON' : 'OFF'}`,
  751. `Echo: ${this.config.authorityEchoEnabled ? 'ON' : 'OFF'}`,
  752. `Auth: ${this.config.authorizedUsers.length}`
  753. ];
  754. this.sendMessage(`📊 ${status.join(' | ')}`);
  755. }
  756.  
  757. cmdPosition() {
  758. this.sendMessage(`📍 Current position: (${this.config.position.x}, ${this.config.position.y})`);
  759. }
  760.  
  761. cmdMembers() {
  762. if (this.state.members.length === 0) {
  763. this.sendMessage("No members in this wall");
  764. } else {
  765. this.sendMessage(`Members: ${this.state.members.join(', ')}`);
  766. }
  767. }
  768.  
  769. cmdWalls() {
  770. if (this.state.walllist.length === 0) {
  771. this.sendMessage("No subwalls available");
  772. } else {
  773. const walls = [];
  774. for (let i = 0; i < this.state.walllist.length; i += 2) {
  775. const wallName = this.state.walllist[i];
  776. const isPrivate = this.state.walllist[i + 1];
  777. walls.push(`${wallName}${isPrivate ? ' (private)' : ''}`);
  778. }
  779. this.sendMessage(`Subwalls: ${walls.join(', ')}`);
  780. }
  781. }
  782.  
  783. cmdTeleport(args) {
  784. if (args.length < 2) {
  785. this.sendMessage(`Usage: ${this.config.prefix}to X Y`);
  786. return;
  787. }
  788.  
  789. const x = parseInt(args[0]);
  790. const y = parseInt(args[1]);
  791.  
  792. if (isNaN(x) || isNaN(y)) {
  793. this.sendMessage("Invalid coordinates. Please provide integers.");
  794. return;
  795. }
  796.  
  797. if (Math.abs(x) > 10000 || Math.abs(y) > 10000) {
  798. this.sendMessage("Coordinates out of range (max ±10000)");
  799. return;
  800. }
  801.  
  802. this.teleportCursor(x, y);
  803. this.sendMessage(`📍 Teleported to (${x}, ${y})`);
  804. }
  805.  
  806. cmdColor(args) {
  807. if (args.length < 1) {
  808. this.sendMessage(`Usage: ${this.config.prefix}colorid #hex or 0-15`);
  809. return;
  810. }
  811.  
  812. const input = args[0].toLowerCase();
  813. let colorIndex;
  814.  
  815. if (!isNaN(input)) {
  816. colorIndex = parseInt(input);
  817. if (colorIndex < 0 || colorIndex > 15) {
  818. this.sendMessage("Invalid colot");
  819. return;
  820. }
  821. } else if (input.startsWith('#')) {
  822. colorIndex = COLORS[input];
  823. if (colorIndex === undefined) {
  824. this.sendMessage("Invalid colot");
  825. return;
  826. }
  827. } else {
  828. this.sendMessage("Invalid colot");
  829. return;
  830. }
  831.  
  832. this.setColor(colorIndex);
  833. this.sendMessage(`🎨 Color changed to ${colorIndex}`);
  834. }
  835.  
  836. cmdAddAuth(args) {
  837. if (args.length < 1) {
  838. this.sendMessage(`Usage: ${this.config.prefix}addauth username`);
  839. return;
  840. }
  841.  
  842. const username = args[0];
  843.  
  844. if (this.config.authorizedUsers.includes(username)) {
  845. this.sendMessage(`${username} already has authority`);
  846. return;
  847. }
  848.  
  849. this.config.authorizedUsers.push(username);
  850. this.sendMessage(`✅ Added ${username} to authority list`);
  851. console.log(`🔑 Authority granted to: ${username}`);
  852. }
  853.  
  854. cmdRemoveAuth(args) {
  855. if (args.length < 1) {
  856. this.sendMessage(`Usage: ${this.config.prefix}removeauth username`);
  857. return;
  858. }
  859.  
  860. const username = args[0];
  861.  
  862. if (username === "Diamond25" || username === "KiwiTest") {
  863. this.sendMessage(`Cannot remove default authority from ${username}`);
  864. return;
  865. }
  866.  
  867. const index = this.config.authorizedUsers.indexOf(username);
  868. if (index === -1) {
  869. this.sendMessage(`${username} doesn't have authority`);
  870. return;
  871. }
  872.  
  873. this.config.authorizedUsers.splice(index, 1);
  874. this.sendMessage(`❌ Removed ${username} from authority list`);
  875. console.log(`🔑 Authority revoked from: ${username}`);
  876. }
  877.  
  878. cmdDisableHeightSafety() {
  879. this.config.heightSafetyEnabled = !this.config.heightSafetyEnabled;
  880. const status = this.config.heightSafetyEnabled ? "ENABLED" : "DISABLED";
  881. this.sendMessage(`⚠️ Height safety is now ${status} (Max tetration height: ${this.config.heightSafetyEnabled ? '5' : '10'})`);
  882. console.log(`Height safety: ${status}`);
  883. }
  884.  
  885. cmdToggleEcho() {
  886. this.config.authorityEchoEnabled = !this.config.authorityEchoEnabled;
  887. const status = this.config.authorityEchoEnabled ? "ENABLED" : "DISABLED";
  888. this.sendMessage(`📢 Authority echo is now ${status}`);
  889. console.log(`Authority echo: ${status}`);
  890. }
  891.  
  892. cmdAuthList() {
  893. const authUsers = [...this.config.authorizedUsers];
  894. const adminUsers = Array.from(this.state.adminUsers);
  895.  
  896. const allAuth = [...new Set([...authUsers, ...adminUsers])];
  897.  
  898. this.sendMessage(`🔑 Authorized users (${allAuth.length}): ${allAuth.join(', ')}`);
  899. }
  900.  
  901. // Core functions
  902. setUsername(username) {
  903. if (typeof api !== 'undefined' && api.nick) {
  904. api.nick(username);
  905. } else if (typeof setNick === 'function') {
  906. setNick(username);
  907. } else if (typeof changeNick === 'function') {
  908. changeNick(username);
  909. }
  910.  
  911. console.log(`👤 Username: ${username}`);
  912. }
  913.  
  914. setColor(colorIndex) {
  915. if (typeof api !== 'undefined' && api.color) {
  916. api.color(colorIndex);
  917. } else if (typeof setColor === 'function') {
  918. setColor(colorIndex);
  919. }
  920.  
  921. this.config.color = colorIndex;
  922. console.log(`🎨 Color set to: ${colorIndex}`);
  923. }
  924.  
  925. teleportCursor(x, y) {
  926. if (typeof api !== 'undefined' && api.cursor) {
  927. api.cursor(x, y);
  928. } else if (typeof moveCursor === 'function') {
  929. moveCursor(x, y);
  930. } else if (typeof cursor === 'object' && cursor.move) {
  931. cursor.move(x, y);
  932. }
  933.  
  934. this.config.position.x = x;
  935. this.config.position.y = y;
  936. }
  937.  
  938. sendMessage(message) {
  939. if (this.state.disablechat) {
  940. console.log("Chat is disabled, cannot send message");
  941. return;
  942. }
  943.  
  944. this.state.messageQueue.push(message);
  945.  
  946. if (!this.state.isProcessingQueue) {
  947. this.processMessageQueue();
  948. }
  949. }
  950.  
  951. async processMessageQueue() {
  952. if (this.state.messageQueue.length === 0 || !this.running) {
  953. this.state.isProcessingQueue = false;
  954. return;
  955. }
  956.  
  957. this.state.isProcessingQueue = true;
  958. const message = this.state.messageQueue.shift();
  959.  
  960. // Rate limiting
  961. const now = Date.now();
  962. const timeSinceLastMessage = now - this.state.lastMessageTime;
  963. if (timeSinceLastMessage < this.config.messageDelay) {
  964. await new Promise(resolve =>
  965. setTimeout(resolve, this.config.messageDelay - timeSinceLastMessage)
  966. );
  967. }
  968.  
  969. this.state.lastMessageTime = Date.now();
  970.  
  971. // Send using w.chat.send
  972. try {
  973. if (w && w.chat && w.chat.send) {
  974. w.chat.send(message);
  975. console.log(`📤 Sent: ${message}`);
  976. } else {
  977. if (typeof sendChat === 'function') {
  978. sendChat(message);
  979. } else if (typeof api !== 'undefined' && api.chat) {
  980. api.chat(message);
  981. } else {
  982. console.error("No chat send method available!");
  983. }
  984. }
  985. } catch (error) {
  986. console.error("Failed to send message:", error);
  987. }
  988.  
  989. // Continue processing queue
  990. setTimeout(() => this.processMessageQueue(), this.config.messageDelay);
  991. }
  992. }
  993.  
  994. // Initialize the bot
  995. console.clear();
  996. console.log("Starting TextWall Bot v7.1...");
  997.  
  998. const bot = new TextWallBot(BOT_CONFIG);
  999. await bot.init();
  1000.  
  1001. // Make bot globally accessible
  1002. window.diamondBot = bot;
  1003.  
  1004. // Utility commands
  1005. window.stopBot = function() {
  1006. console.log("Stopping bot...");
  1007. bot.cleanup();
  1008. bot.sendMessage("Bot shutting down...");
  1009. console.log("✅ Bot stopped");
  1010. };
  1011.  
  1012. window.restartBot = async function() {
  1013. console.log("Restarting bot...");
  1014. window.stopBot();
  1015. await new Promise(resolve => setTimeout(resolve, 1000));
  1016. const newBot = new TextWallBot(BOT_CONFIG);
  1017. await newBot.init();
  1018. window.diamondBot = newBot;
  1019. console.log("✅ Bot restarted");
  1020. };
  1021.  
  1022. window.botStatus = function() {
  1023. console.table({
  1024. 'Username': bot.config.username,
  1025. 'Prefix': bot.config.prefix,
  1026. 'Wall': `${bot.state.wall}/${bot.state.subwall}`,
  1027. 'Position': `(${bot.config.position.x}, ${bot.config.position.y})`,
  1028. 'Color': bot.config.color,
  1029. 'Permissions': ['User', 'Member', 'Owner'][bot.state.perms] || 'Unknown',
  1030. 'Active Timers': bot.state.activeTimers.size,
  1031. 'Authorized Users': bot.config.authorizedUsers.length,
  1032. 'Height Safety': bot.config.heightSafetyEnabled ? 'ON' : 'OFF',
  1033. 'Authority Echo': bot.config.authorityEchoEnabled ? 'OFF (Default)' : 'ON',
  1034. 'Queue Size': bot.state.messageQueue.length
  1035. });
  1036. };
  1037.  
  1038. window.showCommands = function() {
  1039. console.log("\n╔══════════════════════════════════════════════════╗");
  1040. console.log("║ ALL BOT COMMANDS (v7.1) ║");
  1041. console.log("╚══════════════════════════════════════════════════╝\n");
  1042.  
  1043. for (let pageNum in COMMAND_PAGES) {
  1044. console.log(`\n📄 PAGE ${pageNum}:`);
  1045. console.log("─".repeat(50));
  1046.  
  1047. const page = COMMAND_PAGES[pageNum];
  1048. page.forEach(cmd => {
  1049. const authIcon = cmd.auth ? '🔐' : ' ';
  1050. const cmdName = `\\${cmd.cmd}`.padEnd(15);
  1051. console.log(`${authIcon} ${cmdName} - ${cmd.desc}`);
  1052. });
  1053. }
  1054.  
  1055. console.log("\n" + "═".repeat(50));
  1056. console.log("🔐 = Authority Required");
  1057. console.log("Default Authorities: Diamond25, KiwiTest");
  1058. console.log("Admins (ADMIN tag) have automatic authority");
  1059. console.log("═".repeat(50) + "\n");
  1060. };
  1061.  
  1062. window.botHelp = function() {
  1063. console.log("╔══════════════════════════════════════════╗");
  1064. console.log("║ TextWall Bot v7.1 - Help ║");
  1065. console.log("╠══════════════════════════════════════════╣");
  1066. console.log("║ PREFIX: \\ ║");
  1067. console.log("║ ║");
  1068. console.log("║ MAIN COMMANDS: ║");
  1069. console.log("║ \\help [1-4] - Show command page ║");
  1070. console.log("║ \\say text - Make bot say something ║");
  1071. console.log("║ ║");
  1072. console.log("║ CONSOLE COMMANDS: ║");
  1073. console.log("║ window.showCommands() - List all cmds ║");
  1074. console.log("║ window.stopBot() - Stop bot ║");
  1075. console.log("║ window.restartBot() - Restart bot ║");
  1076. console.log("║ window.botStatus() - Show status ║");
  1077. console.log("║ window.botHelp() - This help ║");
  1078. console.log("║ ║");
  1079. console.log("║ FEATURES: ║");
  1080. console.log("║ • Recursion bug fixed ║");
  1081. console.log("║ • Authority echo OFF by default ║");
  1082. console.log("║ • Console-only command list ║");
  1083. console.log("╚══════════════════════════════════════════╝");
  1084. };
  1085.  
  1086. // Show help on start
  1087. window.botHelp();
  1088.  
  1089. })();
Advertisement
Add Comment
Please, Sign In to add comment