Embedded diep lobby selector

Embed diep lobby selector into diep.io page

// ==UserScript==
// @name         Embedded diep lobby selector
// @namespace    http://tampermonkey.net/
// @version      2
// @description  Embed diep lobby selector into diep.io page
// @author       discord@celestial_raccoon_80621
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @match        diep.io/*
// @grant        none
// @license      MIT
// ==/UserScript==

/*
This script (unless in TypeScript form) is the result of
transpiling TypeScript into JavaScript, hence why this
code looks so messy. This is because i want types with
TypeScript, but tampermonkey doesn't support TypeScript
so i have to transpile my TypeScript code with the `tsc`
compiler, then put it here, if you want the TypeScript
source, DM on discord and i'll likely respond
in a few hours or less, discord username is in the
author field above or in any gui of the script
*/

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};

(() => {
    'use strict';
    // Top level variables, change TOGGLE_KEYBIND to whatever you want (to change display visibility)
    const TOGGLE_KEYBIND = 'q';
    const UPDATE_DELAY = 1000; // miliseconds
    const storageKey = "diepioLobbyselect_";
    const API = "https://lb.diep.io/api/lb/pc"; // or you can change this to /mobile
    // todo: add these in accurately
    let colors = {
        fra: "rgba(255, 0, 0, 0.5)",
        atl: "rgba(255, 255, 0, 0.5)",
        sgp: "rgba(50, 50, 200, 0.5)",
        syd: "rgba(0, 255, 0, 0.5)"
    };
    let intToTeam = {
        0: "blue",
        1: "red",
        2: "purple",
        3: "green"
    };
    let intToColor = {
        0: "rgb(33, 143, 221)",
        1: "rgb(232, 27, 27)",
        2: "rgb(184, 13, 207)",
        3: "rgb(81, 220, 34)",
    };
    let data = [];
    // local storage management
    const storage = {
        get(key, defaultValue) {
            return localStorage.getItem(storageKey + key) || defaultValue;
        },
        set(key, value) {
            return __awaiter(this, void 0, void 0, function* () {
                localStorage.setItem(storageKey + key, value);
            });
        },
        getBool(key, defaultValue) {
            let value = this.get(key, null);
            return value === null ? defaultValue : value === "true";
        },
        getNumber(key, defaultValue) {
            let value = this.get(key, null);
            return value === null ? defaultValue : parseFloat(value);
        },
    };
    let showUI = storage.getBool('showUI', false);
    // inject CSS into the head element
    // https://stackoverflow.com/questions/79614720/how-do-i-add-hover-and-active-events-to-my-tampermonkey-injected-script
    const styleElem = document.createElement('style');
    styleElem.textContent = `
    .lobby-button {
        padding: 5px;
        border: 1px solid black;
        background-color: rgba(255, 255, 255, 0.5);
        cursor: pointer;
        transition: background-color 0.2s ease;
    }
    .lobby-button:hover {
        background-color: rgba(200, 200, 200, 0.7);
    }
    .lobby-button:active {
        background-color: rgba(150, 150, 150, 0.9);
    }
    `;
    document.head.appendChild(styleElem);
    function getTextForNumPlayers(numPlayers) {
        // this function was vibe coded
        if (numPlayers < 850)
            return "Very Low";
        if (numPlayers < 900)
            return "Low";
        if (numPlayers < 950)
            return "Below Average";
        if (numPlayers < 1050)
            return "Average";
        if (numPlayers < 1100)
            return "Above Average";
        if (numPlayers < 1200)
            return "High";
        return "Very High";
    }
    // update the values in the UI every second
    function update() {
        return __awaiter(this, void 0, void 0, function* () {
            let response = yield fetch(API);
            let value = yield response.json();
            data = value.regions;
            let count = 0;
            for (let region of data) {
                count += region.numPlayers;
            }
            numPlayers.textContent = `Players Active: ${count} (${getTextForNumPlayers(count)})`;
            // https://stackoverflow.com/questions/3955229/remove-all-child-elements-of-a-dom-node-in-javascript
            buttons.textContent = "";
            for (let region of data) {
                let playerCount = document.createElement('p');
                playerCount.textContent = `${region.regionName} ${region.numPlayers} Players`;
                playerCount.style.marginRight = "0px";
                buttons.appendChild(playerCount);
                for (let index = 0; index < region.lobbies.length; index++) {
                    // put every sixth lobby on a new row
                    if (index % 6 === 0 && index > 5) {
                        buttons.appendChild(document.createElement('br'));
                    }
                    const lobby = region.lobbies[index];
                    const button = document.createElement('button');
                    button.textContent = `${lobby.gamemode} ${lobby.numPlayers}p`;
                    button.className = 'lobby-button';
                    button.addEventListener('click', () => {
                        let teamIndex = buttonIndex;
                        if (lobby.gamemode === "teams"
                            && teamIndex > 1
                            || !lobby.gamemode.includes("teams")) {
                            teamIndex = 0;
                        }
                        window.open(`https://diep.io/?ip=${lobby.ip}&g=${lobby.gamemode}&l=0x${teamIndex}`);
                    });
                    button.style.padding = "5px";
                    button.style.border = "1px solid black";
                    button.style.backgroundColor = colors[region.region] || "rgba(255, 255, 255, 0.5)";
                    button.style.marginLeft = "5px";
                    button.style.marginBottom = "2px";
                    buttons.appendChild(button);
                }
                buttons.appendChild(document.createElement('br'));
            }
        });
    }
    update();
    let IntervalID = setInterval(update, UPDATE_DELAY);
    // toggle display visibility
    function toggle() {
        return __awaiter(this, void 0, void 0, function* () {
            let display = container.style.display;
            container.style.display = display === 'block' ? 'none' : 'block';
            showUI = !showUI;
            storage.set('showUI', showUI);
            console.log("ShowUI is: ", showUI);
            if (showUI) {
                update();
                IntervalID = setInterval(update, UPDATE_DELAY);
            }
            else {
                clearInterval(IntervalID);
            }
        });
    }
    // handle display visibility update
    document.addEventListener('keydown', (ev) => {
        if (ev.key === TOGGLE_KEYBIND) {
            toggle();
        }
    });
    const container = document.createElement('div');
    let style = container.style;
    style.position = 'absolute';
    style.left = '0%';
    style.top = '0';
    style.zIndex = '999999';
    style.backgroundColor = 'rgba(255, 255, 255, 0.5)';
    style.padding = '5px';
    style.border = '1px solid black';
    style.borderRadius = '5px';
    style.display = 'block';
    document.body.append(container);
    const title = document.createElement('p');
    title.textContent = 'Diep lobby selector by EclipSyS';
    title.style.position = 'relative';
    title.style.zIndex = '999999';
    title.style.padding = '0px';
    title.style.margin = '0px';
    container.appendChild(title);
    const numPlayers = document.createElement('p');
    numPlayers.textContent = "Players Active: ?";
    numPlayers.style.position = 'relative';
    numPlayers.style.zIndex = '999999';
    numPlayers.style.padding = '0px';
    numPlayers.style.margin = '0px';
    numPlayers.style.marginBottom = "3px";
    container.appendChild(numPlayers);
    const teamDiv = document.createElement('div');
    teamDiv.style.zIndex = '999999';
    teamDiv.style.backgroundColor = 'rgb(25, 160, 205)';
    teamDiv.style.border = '1px solid black';
    teamDiv.style.borderRadius = '5px';
    teamDiv.style.display = 'flex';
    teamDiv.style.height = "20px";
    const teamTitle = document.createElement('p');
    teamTitle.textContent = "Switch target team:";
    teamTitle.style.marginTop = "0px";
    teamDiv.appendChild(teamTitle);
    let buttonIndex = storage.getNumber('teamIndex', 0);
    const teamButton = document.createElement('button');
    teamButton.style.marginLeft = "5px";
    teamButton.textContent = intToTeam[buttonIndex];
    teamButton.style.backgroundColor = intToColor[buttonIndex];
    teamButton.addEventListener('click', () => {
        buttonIndex++;
        if (buttonIndex >= Object.keys(intToTeam).length) {
            buttonIndex = 0;
        }
        teamButton.textContent = intToTeam[buttonIndex];
        teamButton.style.backgroundColor = intToColor[buttonIndex];
        storage.set('teamIndex', buttonIndex);
    });
    teamDiv.appendChild(teamButton);
    container.appendChild(teamDiv);
    const buttons = document.createElement('div');
    let btnStyle = buttons.style;
    btnStyle.right = '0%';
    btnStyle.top = '0';
    btnStyle.zIndex = '999999';
    btnStyle.backgroundColor = 'rgb(141, 24, 187)';
    btnStyle.padding = '5px';
    btnStyle.border = '1px solid black';
    btnStyle.borderRadius = '5px';
    btnStyle.display = 'block';
    container.appendChild(buttons);
    console.log("Initial showUi is", showUI);
    if (!showUI) {
        // by default the div is visible, we set this here to synchronize the values
        showUI = true;
        toggle();
    }
})();