richardgrechko2

Dominoguy's Ultra Stable HUD (Richard Version)

Feb 23rd, 2026 (edited)
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ============================================================
  2. // FINAL ULTRA STABLE HUD + CHAT + LOGGING (TABBED + SAFE ADMIN + /YT + HUD LINES + JOIN/LEAVE TOGGLE + CLEAN CLOSE)
  3. // ============================================================
  4.  
  5. let msgListener = null;
  6. let chatObserver = null;
  7. let joinLeaveInterval = null;
  8.  
  9. // ---------------- CONFIG ----------------
  10. const HUD_CONFIG = {
  11.   storageKey: "ultraCommandHudPosition",
  12.   historyLimit: 100,
  13.   owners: ["richardelta","richardlab"],
  14.   adminNicks: [this.owners,"dominoguy_","haster","bzuki","mangojansapascual"/*mango catalan :trol:*/,"penthexium56","falling23"].flat(),
  15.   joinLeaveKey: "ultraCommandHudJL" // toggle state storage
  16. };
  17.  
  18. // ---------------- Utilities ----------------
  19. function getCmd(str) { return str.split(" ")[0]; }
  20. function getImpArr(str) { return str.split(" ").slice(1); }
  21. function getImp(str) { return getImpArr(str).join(" "); }
  22.  
  23. // ✅ LOCAL ADMIN CHECK
  24. function isAdmin(nick) { return HUD_CONFIG.adminNicks.includes(nick); }
  25. function isOwner(nick) { return HUD_CONFIG.owners.includes(nick); }
  26.  
  27. // ---------------- CHAT LOG STORAGE ----------------
  28. let chatLog = [];
  29.  
  30. // ============================================================
  31. // CREATE HUD
  32. // ============================================================
  33. const hud = document.createElement("div");
  34. hud.style.position = "fixed";
  35. hud.style.width = "360px";
  36. hud.style.height = "440px";
  37. hud.style.background = "rgba(18,18,18,0.97)";
  38. hud.style.color = "#fff";
  39. hud.style.fontFamily = "Times New Roman";
  40. hud.style.borderRadius = "13px";
  41. hud.style.boxShadow = "0 0 30px rgba(0,0,0,0.7)";
  42. hud.style.zIndex = "999999";
  43. hud.style.display = "flex";
  44. hud.style.flexDirection = "column";
  45. hud.style.overflow = "hidden";
  46.  
  47. // Restore position
  48. const saved = JSON.parse(localStorage.getItem(HUD_CONFIG.storageKey));
  49. if (saved && saved.left && saved.top) {
  50.     hud.style.left = saved.left;
  51.     hud.style.top = saved.top;
  52. } else {
  53.     hud.style.top = "100px";
  54.     hud.style.right = "40px";
  55. }
  56.  
  57. // ---------------- HEADER ----------------
  58. const header = document.createElement("div");
  59. header.style.background = "#111";
  60. header.style.padding = "6px";
  61. header.style.cursor = "move";
  62. header.style.display = "flex";
  63. header.style.justifyContent = "space-between";
  64. header.style.alignItems = "center";
  65. header.style.fontWeight = "bold";
  66. header.textContent = "Made by DG_, Verison by Richard";
  67.  
  68. // Buttons wrapper
  69. const btnWrap = document.createElement("div");
  70. function makeBtn(txt) {
  71.     const b = document.createElement("button");
  72.     b.textContent = txt;
  73.     b.style.background = "#222";
  74.     b.style.color = "#fff";
  75.     b.style.border = "none";
  76.     b.style.cursor = "pointer";
  77.     b.style.width = "24px";
  78.     b.style.height = "24px";
  79.     b.style.borderRadius = "6px";
  80.     b.style.marginLeft = "4px";
  81.     return b;
  82. }
  83.  
  84. const minBtn = makeBtn("–");
  85. const closeBtn = makeBtn("×");
  86. btnWrap.appendChild(minBtn);
  87. btnWrap.appendChild(closeBtn);
  88.  
  89. // ---------------- JOIN/LEAVE TOGGLE ----------------
  90. let showJoinLeave = JSON.parse(localStorage.getItem(HUD_CONFIG.joinLeaveKey)) ?? true;
  91.  
  92. const joinLeaveToggle = document.createElement("button");
  93. joinLeaveToggle.textContent = showJoinLeave ? "JL: ON" : "JL: OFF";
  94. joinLeaveToggle.style.background = "#222";
  95. joinLeaveToggle.style.color = "#fff";
  96. joinLeaveToggle.style.border = "none";
  97. joinLeaveToggle.style.cursor = "pointer";
  98. joinLeaveToggle.style.padding = "4px 6px";
  99. joinLeaveToggle.style.borderRadius = "6px";
  100. joinLeaveToggle.style.marginLeft = "4px";
  101.  
  102. joinLeaveToggle.onclick = () => {
  103.     showJoinLeave = !showJoinLeave;
  104.     joinLeaveToggle.textContent = showJoinLeave ? "JL: ON" : "JL: OFF";
  105.     localStorage.setItem(HUD_CONFIG.joinLeaveKey, JSON.stringify(showJoinLeave));
  106. };
  107.  
  108. btnWrap.appendChild(joinLeaveToggle);
  109. header.appendChild(btnWrap);
  110. hud.appendChild(header);
  111.  
  112. // ============================================================
  113. // TABS
  114. // ============================================================
  115. const tabBar = document.createElement("div");
  116. tabBar.style.display = "flex";
  117. tabBar.style.background = "#151515";
  118.  
  119. function makeTab(name) {
  120.     const t = document.createElement("div");
  121.     t.textContent = name;
  122.     t.style.flex = "1";
  123.     t.style.textAlign = "center";
  124.     t.style.padding = "6px";
  125.     t.style.cursor = "pointer";
  126.     t.style.borderBottom = "2px solid transparent";
  127.     t.addEventListener("mouseenter", () => t.style.background = "#1a1a1a");
  128.     t.addEventListener("mouseleave", () => t.style.background = "#151515");
  129.     return t;
  130. }
  131.  
  132. const tabAll = makeTab("All");
  133. const tabChat = makeTab("Chat");
  134. const tabCmd = makeTab("Commands");
  135.  
  136. tabBar.appendChild(tabAll);
  137. tabBar.appendChild(tabChat);
  138. tabBar.appendChild(tabCmd);
  139. hud.appendChild(tabBar);
  140.  
  141. function makeLogPanel() {
  142.     const panel = document.createElement("div");
  143.     panel.style.flex = "1";
  144.     panel.style.padding = "8px";
  145.     panel.style.overflowY = "auto";
  146.     panel.style.fontSize = "13px";
  147.     panel.style.display = "none";
  148.     return panel;
  149. }
  150.  
  151. const logAll = makeLogPanel();
  152. const logChat = makeLogPanel();
  153. const logCmd = makeLogPanel();
  154.  
  155. hud.appendChild(logAll);
  156. hud.appendChild(logChat);
  157. hud.appendChild(logCmd);
  158.  
  159. function activateTab(tab, panel) {
  160.     [tabAll, tabChat, tabCmd].forEach(t => t.style.borderBottom = "2px solid transparent");
  161.     [logAll, logChat, logCmd].forEach(p => p.style.display = "none");
  162.  
  163.     tab.style.borderBottom = "2px solid #00aaff";
  164.     panel.style.display = "block";
  165. }
  166.  
  167. tabAll.onclick = () => activateTab(tabAll, logAll);
  168. tabChat.onclick = () => activateTab(tabChat, logChat);
  169. tabCmd.onclick = () => activateTab(tabCmd, logCmd);
  170.  
  171. activateTab(tabAll, logAll);
  172.  
  173. // ============================================================
  174. // INPUT
  175. // ============================================================
  176. const input = document.createElement("input");
  177. input.type = "text";
  178. input.placeholder = "Enter command...";
  179. input.style.border = "none";
  180. input.style.outline = "none";
  181. input.style.padding = "8px";
  182. input.style.background = "#222";
  183. input.style.color = "#fff";
  184. hud.appendChild(input);
  185.  
  186. // ============================================================
  187. // DOWNLOAD LOG
  188. // ============================================================
  189. const downloadBtn = document.createElement("button");
  190. downloadBtn.textContent = "Download Log";
  191. downloadBtn.style.background = "#222";
  192. downloadBtn.style.color = "#fff";
  193. downloadBtn.style.border = "none";
  194. downloadBtn.style.cursor = "pointer";
  195. downloadBtn.style.padding = "6px";
  196. downloadBtn.style.borderRadius = "6px";
  197. downloadBtn.onclick = () => {
  198.     const blob = new Blob([chatLog.join("\n")], { type: "text/plain" });
  199.     const url = URL.createObjectURL(blob);
  200.     const a = document.createElement("a");
  201.     a.href = url;
  202.     a.download = "chat_log.txt";
  203.     a.click();
  204.     URL.revokeObjectURL(url);
  205. };
  206. hud.appendChild(downloadBtn);
  207.  
  208. document.body.appendChild(hud);
  209.  
  210. // ============================================================
  211. // DRAG SYSTEM
  212. // ============================================================
  213. let dragging = false, offsetX = 0, offsetY = 0;
  214. header.addEventListener("mousedown", e => {
  215.     dragging = true;
  216.     offsetX = e.clientX - hud.offsetLeft;
  217.     offsetY = e.clientY - hud.offsetTop;
  218. });
  219. document.addEventListener("mousemove", e => {
  220.     if (!dragging) return;
  221.     hud.style.left = (e.clientX - offsetX) + "px";
  222.     hud.style.top = (e.clientY - offsetY) + "px";
  223.     hud.style.right = "auto";
  224. });
  225. document.addEventListener("mouseup", () => {
  226.     if (dragging) {
  227.         localStorage.setItem(HUD_CONFIG.storageKey, JSON.stringify({ left: hud.style.left, top: hud.style.top }));
  228.     }
  229.     dragging = false;
  230. });
  231.  
  232. // ============================================================
  233. // MINIMIZE / CLOSE FIX
  234. // ============================================================
  235. let hudCollapsed = false;
  236. minBtn.onclick = () => {
  237.     if (!hudCollapsed) {
  238.         hud.dataset.prevHeight = hud.style.height;
  239.         hud.style.height = "40px";
  240.         tabBar.style.display = "none";
  241.         logAll.style.display = "none";
  242.         logChat.style.display = "none";
  243.         logCmd.style.display = "none";
  244.         input.style.display = "none";
  245.         downloadBtn.style.display = "none";
  246.         hudCollapsed = true;
  247.     } else {
  248.         hud.style.height = hud.dataset.prevHeight || "440px";
  249.         tabBar.style.display = "flex";
  250.         const activePanel = logAll.style.display === "block" ? [tabAll, logAll] :
  251.                             logChat.style.display === "block" ? [tabChat, logChat] : [tabCmd, logCmd];
  252.         activateTab(activePanel[0], activePanel[1]);
  253.         input.style.display = "block";
  254.         downloadBtn.style.display = "block";
  255.         input.focus();
  256.         hudCollapsed = false;
  257.     }
  258. };
  259.  
  260. closeBtn.onclick = () => {
  261.     hud.remove();
  262.     if (msgListener) { w.off("msg", msgListener); msgListener = null; }
  263.     if (chatObserver) { chatObserver.disconnect(); chatObserver = null; }
  264.     if (joinLeaveInterval) { clearInterval(joinLeaveInterval); joinLeaveInterval = null; }
  265.     w.chat.send("Bot stopped.");
  266. };
  267.  
  268. // ============================================================
  269. // LOGGING FUNCTION
  270. // ============================================================
  271. function hudLog(text, type = "all") {
  272.     function append(panel) {
  273.         const line = document.createElement("div");
  274.         line.textContent = text;
  275.         panel.appendChild(line);
  276.         panel.scrollTop = panel.scrollHeight;
  277.     }
  278.     append(logAll);
  279.     if (type === "chat") append(logChat);
  280.     if (type === "cmd") append(logCmd);
  281.     chatLog.push(text);
  282. }
  283.  
  284. // ============================================================
  285. // HUD LINES SYSTEM (NO TOAST)
  286. // ============================================================
  287. const HUD_LINES = 5;        // max visible lines
  288. const HUD_LIFETIME = 8000; // ms before line expires
  289.  
  290. let hudLines = [];
  291. let lastCursors = new Map();
  292. let initialized = false;
  293.  
  294. function pushHUD(text) {
  295.   hudLines.push({ text, time: Date.now() });
  296.   if (hudLines.length > HUD_LINES) hudLines.shift();
  297. }
  298.  
  299. // clean up expired lines periodically
  300. let hudLinesCleanup = setInterval(() => {
  301.   const now = Date.now();
  302.   hudLines = hudLines.filter(l => now - l.time < HUD_LIFETIME);
  303. }, 500);
  304.  
  305. // ============================================================
  306. // TRACK JOINS / LEAVES
  307. // ============================================================
  308. joinLeaveInterval = setInterval(() => {
  309.   const nowMap = new Map(w.cursors);
  310.  
  311.   if (initialized && showJoinLeave) {
  312.     for (const [id, c] of nowMap) {
  313.       if (!lastCursors.has(id)) {
  314.         pushHUD(`→ ${c.n || "Anon "+id} | Joined or went to this wall.`);
  315.         hudLog(`→ ${c.n || "Anon "+id} | Joined or went to this wall.`, "chat");
  316.       }
  317.     }
  318.  
  319.     for (const [id, c] of lastCursors) {
  320.       if (!nowMap.has(id)) {
  321.         pushHUD(`← ${c.n || "Anon "+id} | Left or went to another wall.`);
  322.         hudLog(`← ${c.n || "Anon "+id} | Left or went to another wall.`, "chat");
  323.       }
  324.     }
  325.   } else if (!initialized) {
  326.     initialized = true;
  327.   }
  328.  
  329.   lastCursors = nowMap;
  330. }, 1000);
  331.  
  332. // ============================================================
  333. // COMMAND SYSTEM
  334. // ============================================================
  335. const commands = [
  336.     "dg:warp", "dg:tp", "dg:users", "dg:changetheme",
  337.     "dg:whereis", "dg:whereisid", "dg:help", "dg.admin:sethudcolor", "dg.owner:shutdown", "dg:time", "dg:yt", "dg:getid", "dg:getcursorid"
  338. ];
  339.  
  340. function executeCommand(message, fromChat = false) {
  341.     const cursors = Object.fromEntries(w.cursors);
  342.     const cmd = getCmd(message).toLowerCase();
  343.     const inputsArr = getImpArr(message);
  344.     const inputs = getImp(message);
  345.  
  346.     function output(text) {
  347.         hudLog(text, "cmd");
  348.         pushHUD(text);
  349.         if (!fromChat) w.chat.send("[Log] " + text);
  350.     }
  351.     function hudThrow(text) {
  352.         hudLog(text, "cmd");
  353.         pushHUD("<span style=\"color:#F00\">"+text+"</span>");
  354.         if (!fromChat) w.chat.send("<start #f00>[Error]<end> " + text);
  355.     }
  356.  
  357.     switch (cmd) {
  358.         case "dg:help":
  359.             output("Commands: " + commands.join(", "));
  360.             break;
  361.         case "dg:getid":
  362.             if (!inputs) { output("Syntax: dg:getid <username>"); break; }
  363.             const userObj = Object.values(cursors).find(c => c.n?.toLowerCase() === inputs.toLowerCase());
  364.             if (!userObj) { output("User not found."); break; }
  365.             const possibleId = userObj.aid ?? userObj.userId ?? userObj.accountId ?? userObj._id ?? userObj.id ?? null;
  366.             if (!possibleId) { output("Anon ID not available client-side."); break; }
  367.             output(`${userObj.n}'s anon id is ${possibleId}`);
  368.            break;
  369.        case "dg:getcursorid":
  370.            if (!inputs) { output("Syntax: dg:getcursorid <username>"); break; }
  371.            const cursorUser = Object.values(cursors).find(c => c.n?.toLowerCase() === inputs.toLowerCase());
  372.            if (!cursorUser) { output("User not found."); break; }
  373.            output(`${cursorUser.n}'s cursor id is ${cursorUser.id}`);
  374.             break;
  375.         case "dg:warp":
  376.             if (!inputs) output("Syntax: dg:warp <wall>");
  377.             else { w.goto(inputs); output("Warped to /" + inputs); }
  378.             break;
  379.         case "dg.owner:shutdown":
  380.             if (!isOwner()) hudThrow("You are not the owner.")
  381.             closeBtn.onclick();
  382.             break;
  383.         case "dg:tp":
  384.             if (inputsArr.length < 2 || isNaN(inputsArr[0]) || isNaN(inputsArr[1]))
  385.                 output("Syntax: dg:tp <x> <y>");
  386.             else {
  387.                 const x = Number(inputsArr[0]);
  388.                 const y = Number(inputsArr[1]);
  389.                 w.tp(x, -y);
  390.                 output(`Teleported to ${x}, ${y}`);
  391.             }
  392.             break;
  393.         case "dg:users":
  394.             output("Users: " + Object.values(cursors).map(c => c.n || c.id).join(", "));
  395.             break;
  396.         case "dg:time":
  397.             output("Current time: " + new Date().toString());
  398.             break;
  399.         case "dg:changetheme":
  400.             if (inputsArr.length < 2)
  401.                 output("Syntax: dg:changeTheme <primary> <secondary>");
  402.             else {
  403.                 w.changeTheme(2);
  404.                 w.setPrimaryColor(inputsArr[0]);
  405.                 w.setSecondaryColor(inputsArr[1]);
  406.                 output("Theme changed.");
  407.             }
  408.             break;
  409.         case "dg:whereis":
  410.             if (!inputs) { output("Syntax: dg:whereIs <username>"); break; }
  411.             const user = Object.values(cursors).find(c => c.n === inputs);
  412.             output(user ? `${inputs} at ${user.l[0]}, ${-user.l[1]}` : "User not found.");
  413.             break;
  414.         case "dg:whereisid":
  415.             if (!inputs) { output("Syntax: dg:whereIsId <id>"); break; }
  416.             const u = cursors[inputs];
  417.             output(u ? `ID ${inputs} at ${u.l[0]}, ${-u.l[1]}` : "ID not found.");
  418.             break;
  419.         case "dg.admin:sethudcolor":
  420.             if (!isAdmin()) { hudThrow("Admin only."); break; }
  421.             if (!inputs) output("Syntax: dg.admin:sethudcolor <color>");
  422.             else { hud.style.background = inputs; output("HUD color changed."); }
  423.             break;
  424.         case "dg:yt":
  425.             if (!inputs) { output("Syntax: dg:yt <channel URL>"); break; }
  426.             output("Fetching stats for " + inputs + "...");
  427.             const proxy = "https://api.allorigins.win/raw?url=";
  428.             const url = encodeURIComponent(inputs);
  429.             fetch(proxy + url)
  430.                 .then(res => res.text())
  431.                 .then(html => {
  432.                     const match = html.match(/ytInitialData\s*=\s*(\{.*?\});/s);
  433.                     if (!match) throw new Error("ytInitialData not found");
  434.                     const json = JSON.parse(match[1]);
  435.                     const header = json?.header?.c4TabbedHeaderRenderer || json?.header?.pageHeaderRenderer;
  436.                     const subs = header?.subscriberCountText?.simpleText || "Hidden";
  437.                     const videos = header?.videosCountText?.runs?.[0]?.text || header?.videosCountText?.simpleText || "N/A";
  438.                     const views = header?.viewCountText?.simpleText || "N/A";
  439.                     hudLog(`[BOT] Stats for ${inputs}: ${subs} subscribers - ${videos} videos - ${views}`, "cmd");
  440.                     pushHUD(`[BOT] Stats: ${subs} subs, ${videos} vids, ${views} views`);
  441.                 })
  442.                 .catch(err => {
  443.                     hudLog("[CLIENT] Failed to fetch stats: " + err.message, "cmd");
  444.                     pushHUD("[CLIENT] Failed to fetch stats");
  445.                 });
  446.             break;
  447.     }
  448. }
  449.  
  450. // ============================================================
  451. // INPUT HANDLER
  452. // ============================================================
  453. input.addEventListener("keydown", e => {
  454.     if (e.key === "Enter") {
  455.         const value = input.value.trim();
  456.         if (!value.startsWith("/")) return;
  457.         executeCommand(value, false);
  458.         input.value = "";
  459.     }
  460. });
  461.  
  462. // ============================================================
  463. // CHAT LISTENER
  464. // ============================================================
  465. msgListener = d => {
  466.   if (d.msg.toLowerCase().startsWith("dg:")||
  467.         d.msg.toLowerCase().startsWith("dg.admin:")||
  468.         d.msg.toLowerCase().startsWith("dg.owner:")) executeCommand(d.msg, true);
  469.   else {
  470.     hudLog(`${d.nick}: ${d.msg}`, "chat");
  471.     pushHUD(`${d.nick}: ${d.msg}`);
  472.   }
  473. };
  474. w.on("msg", msgListener);
Tags: textwall
Advertisement
Add Comment
Please, Sign In to add comment