MohMoh Bots // UNPATCHED

Spawns bots for mohmoh.

// ==UserScript==
// @name         MohMoh Bots // UNPATCHED
// @description  Spawns bots for mohmoh.
// @match        *://hackers.mohmoh.eu/*
// @require      https://greasyfork.org/scripts/423602-msgpack/code/msgpack.js
// @license      none
// @version      2.1
// @run-at       document-start
// @namespace https://greasyfork.org/users/1185687
// ==/UserScript==

let notificationOffset = 0;
const _WebSocket_ = WebSocket;

class Prompt {

  constructor(message, callback) {
    const randomID = crypto.randomUUID().replaceAll("-", "");
    const btnId = crypto.randomUUID();

    document.documentElement.insertAdjacentHTML("beforeend", `
    <ma${randomID}ta style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%)">
      <input type="name" placeholder="${message}" style="height: 30px"> <button id="${btnId}" style="height: 32px; width: 75px"> Accept </button>
    </ma${randomID}ta>
    `);

    document.getElementById(btnId).addEventListener("click", event => {
      try {
        callback(document.getElementById(btnId).parentElement.querySelector("input").value);
      } catch(e) {
        notification("ERR: " + e);
      }
      document.getElementById(btnId).parentElement.remove();
    });
  }

};

const deployCode = function BackendCode() {
  const msgpack = require("msgpack-lite");
  const WebSocket = require("ws");

  const serverAddress = "wss://hackers.mohmoh.eu";

  function connector() {
    const socket = new WebSocket(serverAddress, {
      origin: "https://hackers.mohmoh.eu"
    });

    socket.binaryType = "arraybuffer";

    socket.addEventListener("open", e => {
      console.log("[*] WebSocket opened at " + serverAddress);
    });

    socket.addEventListener("close", e => {
      connector();
    });

    socket.addEventListener("error", e => {
      console.log(`[*] Socket error with message ${e.message} happened! Reconnecting...`);
    });

    socket.addEventListener("message", ({
      data
    }) => {
      const [packetSid, ...packetData] = msgpack.decode(new Uint8Array(data));

      console.log(`[Server] ${packetSid} -> ${packetData}`);

      switch (packetSid) {
        case "id":
          botSid = packetData[0];
          socket.send(msgpack.encode(["sp", [{
            name: "5z8 xskid",
            skin: "toString"
          }]]));
          break;
      }
    });
  }

  connector();
};

const installCode = function Installer() {
  const { execSync } = require("child_process");
  const dependencies = ["ws", "msgpack-lite"];
  
  dependencies.forEach(dependency => {
    execSync(`npm install ${dependency}`);
  });
};

function notification(text) {
  const notif = document.createElement("div");
  notif.innerHTML = text;
  notif.style = "width: 300px; text-align: center; height: 70px; z-index: 9999; background: rgba(0, 0, 0, 0.5); color: white; font-size: 20px !important; border-bottom: 4px solid green; position: fixed; right: 100px";
  notif.style.top = (notificationOffset += 90) + "px";
  document.documentElement.appendChild(notif);

  setTimeout(() => {
    notificationOffset -= 90;
    notif.remove();
  }, 2000);
};

CanvasRenderingContext2D.prototype.fillText = new Proxy(CanvasRenderingContext2D.prototype.fillText, {
  apply(target, that, args) {
    const msg = args[0];

    if (msg == "!bot_connect") {
      const pipe = new Prompt("Enter deploy server url", deployUrl => {
        notification("Deploying installCode and deployCode scripts...");

        const server = new _WebSocket_("wss://" + deployUrl);
        server.addEventListener("open", () => {
          server.send("DEPLOY " + deployCode.toString());
          server.send("PRE_DEPLOY " + installCode.toString());
        });

        server.addEventListener("message", e => {
          if (e.data == "DEPLOY") notification("The bot code has been deployed!");
          else if (e.data == "PRE_DEPLOY") notification("Server is ready to run websocket client!");
        });
      });
    } else if (msg == "!info") alert("Deploy server is a websocket server that executes a command code through eval in format 'PRE_DEPLOY {code here}' and after that executes the bots code - 'DEPLOY {code here}'. These commands are sent by client via websocket connection. Usually you can use glitch.com to host these servers in pair with ws module and node.js");

    return target.apply(that, args);
  }
});

notification("Use !bot_connect command to connect the bots, use !info command to know how to make deploy server.");