Greasy Fork is available in English.

Moomoo.io 1.8.0 AutoGG & Interactive Menu

Press 'Esc' to open the menu and customize the AutoGG message, delay, and toggle keycode. Your settings will be saved even if you reload the page.

// ==UserScript==
// @name         Moomoo.io 1.8.0 AutoGG & Interactive Menu
// @description  Press 'Esc' to open the menu and customize the AutoGG message, delay, and toggle keycode. Your settings will be saved even if you reload the page.
// @author       Seryo
// @version      1
// @namespace    https://greasyfork.org/users/1190411
// @match        *://*.moomoo.io/*
// @grant        none
// @license      MIT
// @icon         https://cdn.glitch.com/82ae8945-dcc6-4276-98a9-665381b4cd2b/cursor12.png
// @require      https://greasyfork.org/scripts/423602-msgpack/code/msgpack.js?version=1005014
// ==/UserScript==

const msgpack5 = window.msgpack;

let ws, autoGGEnabled = true;
let menuVisible = false;
let messageSpeed = parseInt(localStorage.getItem("autogg-message-speed"), 10) || 1400;
let toggleKeyCode = parseInt(localStorage.getItem("autogg-toggle-keycode"), 10) || 219;
let editedMessage = localStorage.getItem("autogg-edited-message") || "";
let lastKillCount = 0;
let originalMessageSpeed = messageSpeed;
let originalToggleKeyCode = toggleKeyCode;

function loadSettings() {
  const savedMessageSpeed = localStorage.getItem("autogg-message-speed");
  if (savedMessageSpeed !== null) {
    messageSpeed = parseInt(savedMessageSpeed, 10);
  } else {
    messageSpeed = 1400;
  }

  const savedToggleKeyCode = localStorage.getItem("autogg-toggle-keycode");
  if (savedToggleKeyCode !== null) {
    toggleKeyCode = parseInt(savedToggleKeyCode, 10);
  } else {
    toggleKeyCode = 219;
  }

  const savedEditedMessage = localStorage.getItem("autogg-edited-message");
  if (savedEditedMessage !== null) {
    editedMessage = savedEditedMessage || "";
  }
}

WebSocket.prototype.oldSend = WebSocket.prototype.send;

WebSocket.prototype.send = function (e) {
  if (!ws) {
    [document.ws, ws] = [this, this];
    attachWebSocketListener(this);
  }
  this.oldSend(e);
};

const attachWebSocketListener = (e) => {
  e.addEventListener("message", hookWS);
};

const hookWS = (e) => {};

const sendPacket = (e) => {
  if (ws) {
    ws.send(msgpack5.encode(e));
  }
};

const sendMessageToChat = (e) => {
  setTimeout(() => {
  sendPacket(["6", [e]]);
  }, messageSpeed);
};

function isChatOpen() {
  return document.activeElement.id.toLowerCase() === "chatbox";
}

function isAllianceInputActive() {
  return document.activeElement.id.toLowerCase() === "allianceinput";
}

function shouldHandleHotkeys() {
  return !isChatOpen() && !isAllianceInputActive();
}

const handleMutations = (mutationsList) => {
  for (const mutation of mutationsList) {
    if (mutation.target.id === "killCounter") {
      const count = parseInt(mutation.target.innerText, 10) || 0;

      if (count === 0) {
        lastKillCount = 0;
      }

      if (count > lastKillCount) {
        lastKillCount = count;
        if (autoGGEnabled) {
          sendMessageToChat(editedMessage);
        }
      }
    }
  }
};

const observer = new MutationObserver(handleMutations);
observer.observe(document, {
  subtree: true,
  childList: true,
});

const gradientColorStyle = document.createElement("style");
gradientColorStyle.textContent = `
  #autogg-character-count {
    transition: color 1s;
    color: #909090;
  }
`;
document.head.appendChild(gradientColorStyle);

function updateCharacterCount() {
  const messageInput = document.getElementById("autogg-message-input");
  const characterCount = document.getElementById("autogg-character-count");
  const newCharacterCount = 30 - messageInput.value.length;

  characterCount.style.transition = "color 1s";

  if (newCharacterCount >= 1) {
    characterCount.style.color = "#909090";
  } else if (newCharacterCount >= 1) {

      const redValue = 255 - (newCharacterCount - 10) * 12;
    const color = `rgb(255, ${redValue}, ${redValue})`;
    characterCount.style.color = color;
  } else {
    characterCount.style.color = "red";
  }

  characterCount.textContent = newCharacterCount;
}

document.addEventListener("keydown", (e) => {
  if (e.keyCode === toggleKeyCode && shouldHandleHotkeys()) {
    if (shouldHandleHotkeys()) {
      autoGGEnabled = !autoGGEnabled;
      document.title = autoGGEnabled ? "𝙲𝚑𝚊𝚝 𝙾𝙽" : "𝙲𝚑𝚊𝚝 𝙾𝙵𝙵";
      console.log("AutoGG is now " + (autoGGEnabled ? "ON" : "OFF"));
      updateAutoGGStatus();
      updateCharacterCount();
    } else if (isChatOpen() && autoGGEnabled) {
      sendMessageToChat(editedMessage);
    }
  }

  if (e.keyCode === 27 && shouldHandleHotkeys() && storeMenu.style.display !== 'block') {
    toggleMenu();
  }
});

function updateAutoGGStatus() {
  const statusText = document.getElementById("autogg-status");
  statusText.textContent = autoGGEnabled ? "On" : "Off";
}

function saveMessage() {
  const messageInput = document.getElementById("autogg-message-input");
  editedMessage = messageInput.value;
  saveSettings();
  updateCharacterCount();
}

function saveSpeed() {
  const speedInput = document.getElementById("autogg-speed-input");
  const newSpeed = parseInt(speedInput.value, 10);

  if (!isNaN(newSpeed) && newSpeed > 0) {
    messageSpeed = newSpeed;
    saveSettings();
  } else {
    alert("Speed must be greater than 0");
  }
}

function saveToggleKey() {
  const toggleKeyInput = document.getElementById("autogg-toggle-key-input");
  const newToggleKey = toggleKeyInput.value;
  if (newToggleKey === "") {
    return;
  }
  if (!isNaN(newToggleKey) && newToggleKey >= 0 && newToggleKey <= 255) {
    toggleKeyCode = parseInt(newToggleKey, 10);
    saveSettings();
    updateToggleKeyText();
  } else {
    alert("Key must be between 0 and 255");
  }
}

function saveSettings() {
  localStorage.setItem("autogg-message-speed", messageSpeed);
  localStorage.setItem("autogg-toggle-keycode", toggleKeyCode);
  localStorage.setItem("autogg-edited-message", editedMessage);
}

loadSettings();

function updateToggleKeyText() {
  const toggleKeyLabel = document.getElementById("autogg-toggle-key-label");
  toggleKeyLabel.textContent = `Toggle Key: ${toggleKeyCode}`;
}

function toggleMenu() {
  const menu = document.getElementById("autogg-menu");
  menuVisible = !menuVisible;
  if (menuVisible) {
    const messageInput = document.getElementById("autogg-message-input");
    messageInput.value = editedMessage;
    const speedInput = document.getElementById("autogg-speed-input");
    speedInput.value = messageSpeed.toString();
    const toggleKeyInput = document.getElementById("autogg-toggle-key-input");
    toggleKeyInput.value = toggleKeyCode.toString();
    updateCharacterCount();
  } else {
  }
  menu.style.display = menuVisible ? "block" : "none";
}

const menu = document.createElement("div");
menu.id = "autogg-menu";
menu.style.display = "none";
menu.style.background = 'rgba(0, 0, 0, 0.8)';
menu.style.fontFamily = 'Hammersmith One, sans-serif';
menu.style.position = 'fixed';
menu.style.top = '20px';
menu.style.left = '20px';
menu.style.border = '1px solid #000';
menu.style.borderRadius = '8px';
menu.style.boxShadow = '0px 0px 10px rgba(0, 0, 0, 0.25)';
menu.style.boxShadow = '5px 5px 10px rgba(0, 0, 0, 0.4)';
menu.style.width = '240px';
menu.style.color = '#fff';
menu.style.fontSize = '17px';
menu.style.zIndex = '9999';
menu.style.overflowY = 'auto';
menu.style.padding = '10px';
menu.style.textAlign = 'center';

document.body.appendChild(menu);

const title = document.createElement("h1");
title.style.fontSize = '28px';
title.style.marginTop = '15px';
const autoGGStatus = document.createElement("span");
autoGGStatus.id = "autogg-status";
autoGGStatus.style.fontSize = '28px';
autoGGStatus.style.marginLeft = '10px';
title.appendChild(document.createTextNode("AutoGG"));
title.appendChild(autoGGStatus);
menu.appendChild(title);

updateAutoGGStatus();

const hr1 = document.createElement("hr");
menu.appendChild(hr1);

const messageLabel = document.createElement("label");
messageLabel.textContent = "Edited Message";
const messageInputContainer = document.createElement("div");
messageInputContainer.style.display = "flex";

const messageInput = document.createElement("input");
messageInput.id = "autogg-message-input";
messageInput.name = "autogg-message";
messageInput.type = "text";
messageInput.value = editedMessage;
messageInput.maxLength = 30;
messageInput.setAttribute("autocomplete", "off");
messageInput.style.flex = "1";
messageInput.style.marginRight = "5px";
messageInput.addEventListener("input", updateCharacterCount);

messageInput.style.marginRight = "5px";

const characterCount = document.createElement("span");
characterCount.id = "autogg-character-count";
characterCount.style.fontSize = "12px";
characterCount.style.marginRight = "10px";
characterCount.style.alignSelf = "center";

characterCount.style.color = "#909090";

messageInputContainer.appendChild(messageInput);
messageInputContainer.appendChild(characterCount);

messageLabel.appendChild(messageInputContainer);
menu.appendChild(messageLabel);

const hr2 = document.createElement("hr");
menu.appendChild(hr2);

const speedLabel = document.createElement("label");
speedLabel.textContent = "Message Delay ";
const speedInput = document.createElement("input");
speedInput.id = "autogg-speed-input";
speedInput.name = "autogg-speed";
speedInput.type = "text";
speedInput.value = messageSpeed;
speedInput.maxLength = 4;
speedInput.style.width = "45px";
speedInput.setAttribute("autocomplete", "off");
speedLabel.appendChild(speedInput);
menu.appendChild(speedLabel);

speedInput.addEventListener("input", function () {
  if (this.value.length > 4) {
    this.value = this.value.slice(0, 4);
  }
speedInput.addEventListener("input", function () {
  this.value = this.value.replace(/[^0-9]/g, '');
});
});

const hr3 = document.createElement("hr");
menu.appendChild(hr3);

const toggleKeyLabel = document.createElement("label");
toggleKeyLabel.textContent = "Toggle Keycode ";
const tKeyInput = document.createElement("input");
tKeyInput.id = "autogg-toggle-key-input";
tKeyInput.name = "autogg-toggle-key";
tKeyInput.type = "text";
tKeyInput.value = toggleKeyCode;
tKeyInput.maxLength = 3;
tKeyInput.style.width = "39px";
tKeyInput.setAttribute("autocomplete", "off");
toggleKeyLabel.appendChild(tKeyInput);
menu.appendChild(toggleKeyLabel);

tKeyInput.addEventListener("input", function () {
  if (this.value.length > 3) {
    this.value = this.value.slice(0, 3);
  }
    tKeyInput.addEventListener("input", function () {
  this.value = this.value.replace(/[^0-9]/g, '');
});
});

const hr4 = document.createElement("hr");
menu.appendChild(hr4);

const saveButton = document.createElement("button");
saveButton.textContent = "Save";
saveButton.addEventListener("click", () => {
  saveMessage();
  saveSpeed();
  saveToggleKey();
});
loadSettings();
menu.appendChild(saveButton);