Greasy Fork

Advanced Agma

clickable chat links, discord in game chat, remove specific animations, remove food completely (toggle mouse), advanced user stats (agma.io/stats.php), increase number of stackable animations

目前为 2024-07-06 提交的版本。查看 最新版本

// ==UserScript==
// @name         Advanced Agma
// @namespace    http://tampermonkey.net/
// @version      0.1.0
// @author       Big watermelon (credits: Nersai, Vintrex)
// @description  clickable chat links, discord in game chat, remove specific animations, remove food completely (toggle mouse), advanced user stats (agma.io/stats.php), increase number of stackable animations
// @match        https://agma.io
// @match        https://discord.com/*
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/pako.min.js
// @license      GPL-3.0-or-later
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAMAAADDpiTIAAAC9FBMVEUAAAC9vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb0VZcATXrgNR6ENR6EVZcAVZcAVZcAVZcARVrEOSaMNR6ENR6ENR6ENR6EVZcAVZcAVY74QUq0NR6ENR6EVZcATXrgOS6UNR6ENR6G9vb0RVK+9vb0VZcANR6ESWrQNR6EVZcAUX7oPTacNR6EVZcAQUKu0tLSrq6uwsLAVZcC5ubmenp5+fn51dXV6enqQkJCTp74qcMCnp6ezuL1Uhr8NR6GVlZWioqKJor4ga8CMjIyosr01dr+Dg4PGxsbJycnDw8NfjL/c3Nzu7u7o6Oh+nL7MzMzr6+vi4uKerb7W1tZKgb91dXV1dXXS0tLl5eXAwMBpkb8PT6l1dXV1dXWZmZmJiYl1dXV1dXV1dXV1dXV1dXV1dXXZ2dk/e791dXV1dXVvcniusbdbaoAUSp4YTqOGmLTf398SWLJIYYhEbKqytruHh4cRV7IUYbzPz88VZcCRoLZae60uXaanrroVZcA5ZagjVqWcp7hwibFPc6wWaMMad9MbftoYcc0Xa8YdhOAhlvMTXLZ7kbMgkO0VZcAcgd0NR6EVZcAXbsofjekaetYdh+N1dXUeiuYgk/AZdNBlgq+ZmZm9vb2apbcNR6Gosr2yt70ha8Cbq751l77/wQf/wQf/wQdTfo//wQf/wQf/wQfFqjVQfJL/wQf/wQe2pEEycamKk2Qka7Tith5egobwuxN7jW//wQf/wQdtiHuZmVinn0zTsCpBdp0PTqgSWbQjabOHhlbwuRErVo6kk0FKZnvDoy5FY33/wQccT5d3fF6GhFT/wQf/wQcQUasOSaMOSqQOSaMOSqQPTacvX6goWaVpaWmPj4+bm5usrKxhYWFhYWFnZ2eEhISgoKBhYWFtbW23t7d4eHhhYWFhYWGysrJhYWFhYWFycnJhYWFhYWGGhoZnZ2dhYWGpqalhYWGMjIx6enphYWFhYWFhYWFhYWFhYWFiRaieAAAA/HRSTlMAMIC/3//Pn2AQr0DvjzBAQBAQcM//////v49QQO///++fj///32BQ/3CvIP+AgP//zyD/////UP//////////////MP/////////////////////////////fv///////nzAgr89AYI/vIP//EK////////////////+v//9g/////5////////////////////+//3Df/////4D//////yBQr4Dv3+9wEFCA74/v////MN///////////3C///////+PUP/////////PYP///59AMM+P769Q/8+v////QP////+/////IJ//EO//YHDv71Dfj+/vzzDfgK9Air+ZAAAYg0lEQVR4AezBtQHDMAAAsMRM/79bmkprJks6AAAAAAAAAAC41hliyi+ltn6wlR5S/jDmwTZ6yL/iPNjDXPmvOzt3oeTGDkQBtAMdRq8VK2R2mDkxhJk83jAzMzMv/PWCrDGM3LJf0ZO2+vzCvSW1BjQX7ObNX7AQvMcmI2UaPQrE+uJCiEUJuXjJUmA+m460OZOgs2XLhZJMSSnTmQUw8XD+dANiWdGQy8sxhRXAPM6fNmclGObFRYvkKul/BTh/2gyI6FsulMgiIAs+DwOcP201tIqtEYZkSiqL14L3OH/TdGP6M6xLSGU9eI7ztzdggyBs3CSVzbwIeJ8//UBgS1yQklulkuZh0Nf8t23fvoNswOTJMybtXC5sFsm6zEJgzps5Ddvs2r2nOKZU3oakyl5htU7yNuBr/vtKxVB5F1L2HxBWuYRU0geBeZX/oWKL0mEkHTkqbDYmeBDwMP9dx4pa90Xg+ImeGiC5AR7lf7IYdTI6CZw6ffr0GVTOTuwGcP5KqfU8cKYaKLXqKRzTb90GctLrBnD+ZgPOnQ8aLoxX4KJ1G1jncwM4f7MBZ3T+2iVE3H9ZWKzyswGc/5WrV0sdGnAtaHf9BiLeFBa3pObRaZDzv30HAO7eKzbtQ+VSEFE71WUQSIaDYHotOIVNmkrkf/8B1D0shvYgUYDgvBoEjvYwCG5eCA5hk+YQ+T+ChjuPi3WHwhkg6NyA/Sd6GAMy4D7O//FDaPHkflHZjtrTwFC7Md6AZ4K0yaNBkPO/A22evyiOefkKQxcCw3Ucd0BQNnozBnD+959A1KNi8fWbt+9Qu/E+MFxCtB4GPkhtMTiN87/6HEwPP8oxnz6jVg0Mp3Bcv6Dc4k3A5fzxS3j6gw5iX6Xy9h09B1xAewO+SS29EJhz+ZeN8b/9u//cJinbFoHvQdRpVCpHyQ+EtCXAXM3/IXTwY3lLfm9/Gm8EtPeokA8Eknmp8Rzo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
// @grant        unsafeWindow
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-start
// ==/UserScript==

/*
TODO: message doesn't send => color in red
TODO: message edit => edit message
TODO: message too long to fit in chat => wrap arround
TODO: implement support for:
- RECIPIENT_ADD (1)             { color: "#00FF00", name: "→", message: `... joined the group` }
- RECIPIENT_REMOVE (2)          { color: "#FF0000", name: "←", message: `... left the group` }
- CALL (3)                      { color: "#00FF00", name: "📞", message: `... started a phone call` }
- CHANNEL_NAME_CHANGE (4)       { color: "#00FF00", name: "🖊️", message: `... changed the group name to ...` }
- CHANNEL_PINNED_MESSAGE (6)    { color: "#00FF00", name: "🖊️", message: `... pinned a message` }
- GUILD_MEMBER_JOIN (7)         { color: "#00FF00", name: "→", message: `... joined the server` }
*/

(function() {
    "use strict";

    if (unsafeWindow.top !== unsafeWindow.self || document.querySelector('title')?.textContent?.includes("Just a moment")) {
        return;
    }

    const discordToken = GM_getValue("discordToken", null);
    if (unsafeWindow.location.href.startsWith("https://discord.com")) {
        if (!discordToken) {
            GM_setValue("discordToken", JSON.parse(unsafeWindow.localStorage.token));
            unsafeWindow.alert("Discord Chat for agma.io has updated your token !");
        }
        return;
    }

    const numberFormat = Intl.NumberFormat("fr-FR");
    const userprofiles = unsafeWindow.localStorage.userprofiles ? JSON.parse(unsafeWindow.localStorage.userprofiles) : {};
    const settings = GM_getValue("settings", {
        removeFood: true,
        removeAnimations: [3, 6, 7, 8, 11],
        maxStackableAnimations: 3,
        discordChat: true,
        discordSavedChannels: {},
        discordPresence: true
    });
    if (!discordToken) {
        unsafeWindow.alert("Discord Chat can not work since you didnt log in into your browser with discord.\nIf you want to use the discord chat feature wait for an alert saying that your token has been saved.\n\nhttps://discord.com");
        settings.discordChat = false;
    }

    const discordIcon = new Image();
    discordIcon.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAMAAADTRh9nAAAAS1BMVEVHcExYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfJYZfLaTvQiAAAAGHRSTlMAGTDyq+e2/N/4CMgjf1vXSTaJZ5HSEHVuv+kNAAAAqElEQVQY02VQSRLDMAgjXvGSxGvC/19acNpDphwQyIA0BgDYDoN7Virv1hwbrFApEGm0FjVRSEq4aOgVJjJZwpsM5X9wjVYrhX/6BbbCLuiOxiK6HU66HQQsK/IVA5BlzwFyPtncIBps+eQWQYtgj2rym4pdrARYt3WSBcKkl9wivf/ZeSpwDDgc6hA0usEb3sHVp6eUt1pK3XIiP/sln3TPBt9o82YnH6drET/OdjF6AAAAAElFTkSuQmCC";

    const discordPresence = {
        status: "online",
        since: 0,
        activities: [{
            name: "Agma.io",
            type: 0,
            url: "https://agma.io",
            details: "Playing Agma.io",
            timestamps: {
                start: Date.now()
            }
        }],
        afk: false
    }

    const animations = {
        1:  { name: "Recombine", style: "border-color: #337ab7; background-image: url('./img/store/recombine-min.png'); padding-left: 30px; padding-left: 30px;" },
        2:  { name: "Cell Select", style: "border-color: #fe3f3f;" },
        3:  { name: "Spin", style: "border-color: #b3b3b3;" },
        4:  { name: "360 Shot", style: "border-color: #337ab7; background-image: url('./img/push_lo.png'); padding-left: 30px;" },
        5:  { name: "Level Up", style: "border-color: #fe3f3f;" },
        6:  { name: "Flip Spin", style: "border-color: #b3b3b3;" },
        7:  { name: "Flip", style: "border-color: #b3b3b3;" },
        8:  { name: "Shake", style: "border-color: #b3b3b3;" },
        9:  { name: "Explosion", style: "border-color: #f0ad4e; background-image: url('./emotes/1f4a5.png'); padding-left: 30px;" },
        10: { name: "1st Medal", style: "border-color: #f0ad4e;" },
        11: { name: "Jump", style: "border-color: #b3b3b3;" },
        12: { name: "Wacky", style: "border-color: #f0ad4e; background-image: url('./emotes/1f61c.png'); padding-left: 30px;" },
        13: { name: "White cell for 1 frame", style: "border-color: #fe3f3f;" },
        14: { name: "Freeze", style: "border-color: #337ab7; background-image: url('./img/inv_freeze2.png'); padding-left: 30px;" },
        15: { name: "Speed", style: "border-color: #337ab7; background-image: url('./img/store/speed-min.png'); padding-left: 30px;" },
        16: { name: "Idk", style: "border-color: #fe3f3f;" }, // weird nothing
        17: { name: "Upgrade", style: "border-color: #fe3f3f;" },
        18: { name: "Snowball", style: "border-color: #fe3f3f;" },
        20: { name: "Anti freeze", style: "border-color: #337ab7; background-image: url('./skins/objects/20.png'); padding-left: 30px;" },
        21: { name: "Anti recombine", style: "border-color: #337ab7; background-image: url('./skins/objects/21.png'); padding-left: 30px;" },
        23: { name: "Shield", style: "border-color: #337ab7; background-image: url('img/inv_shield5.png'); color: rgba(82, 152, 203, 0.6); padding-left: 30px;" },
        24: { name: "Shield", style: "border-color: #337ab7; background-image: url('img/inv_shield5.png'); color: rgba(84, 211, 77, 0.6); padding-left: 30px;" },
        25: { name: "Shield", style: "border-color: #337ab7; background-image: url('img/inv_shield5.png'); color: rgba(243, 46, 46, 0.6); padding-left: 30px;" },
        26: { name: "Shield", style: "border-color: #337ab7; background-image: url('img/inv_shield5.png'); color: rgba(127, 59, 227, 0.6); padding-left: 30px;" },
        30: { name: "Wave", style: "border-color: #f0ad4e; background-image: url('./emotes/1f44b.png'); padding-left: 30px;" },
        31: { name: "Head Explosion", style: "border-color: #f0ad4e; background-image: url('./emotes/1f61cd.png'); padding-left: 30px;" },
        32: { name: "Hearts Face", style: "border-color: #f0ad4e; background-image: url('./emotes/1f60d.png'); padding-left: 30px;" },
        41: { name: "Angry Pumpkin", style: "border-color: #f0ad4e; background-image: url('./emotes/angry_emote3.png'); padding-left: 30px;" },
        42: { name: "Scared Pumpkin", style: "border-color: #f0ad4e; background-image: url('./emotes/scared_emote.png'); padding-left: 30px;" },
        43: { name: "Yawn Pumpkin", style: "border-color: #f0ad4e; background-image: url('./emotes/yawn_emote.png'); padding-left: 30px;" },
        44: { name: "Throwup", style: "border-color: #f0ad4e; background-image: url('./emotes/throwup.png'); padding-left: 30px;" },
        45: { name: "Hot face", style: "border-color: #f0ad4e; background-image: url('./emotes/hotface.png'); padding-left: 30px;" },
        46: { name: "Tears Joy", style: "border-color: #f0ad4e; background-image: url('./emotes/tearsjoy.png'); padding-left: 30px;" },
        47: { name: "No No", style: "border-color: #f0ad4e; background-image: url('./emotes/nonu.png'); padding-left: 30px;" },
        48: { name: "Clap", style: "border-color: #f0ad4e;" },
        49: { name: "Crying", style: "border-color: #f0ad4e;" },
        50: { name: "Devil Smile", style: "border-color: #f0ad4e;" },
        51: { name: "Eatman", style: "border-color: #f0ad4e;" },
        52: { name: "Trophy", style: "border-color: #f0ad4e;" },
        53: { name: "Hearts", style: "border-color: #f0ad4e;" }
    };
    const animationsIds = [
        1, 4, 14, 15, 20, 21, 23, 24, 25, 26, // Powers
        3, 6, 7, 8, 11, // Annoying
        9, 10, 12, 30, 31, 32, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, // Emotes
        2, 5, 13, 16, 17, 18 // System
    ];

    const urlRegex = /https?:\/\/[^\s]+/g;
    const invisibleChar = "᠋";
    const wordsToReplace = ["https", "www", ".gg", ".com", ".io", ".net", ".biz", "miracle", "palestine"].map(word => [
        new RegExp(`\\b(${word})\\b`, "gi"),
        word[0] + invisibleChar + word.slice(1)
    ]);

    var discordUsername;
    var discordAuthor = null;

    var discordWebSocket;
    var discordHeartbeatInterval;
    var discordReconnectRetryCount = 0;
    const discordGatewayUrl = "wss://gateway.discord.gg/?v=9&encoding=json";
    const sentMessagesIds = [];
    const originalSend = WebSocket.prototype.send;
    const sendWebsocketDiscordMessage = (op, d) => originalSend.call(discordWebSocket, JSON.stringify({ op, d }));

    var chtTabs;
    var currentTab = '';
    var localChatMessages;
    var cellProtoOverwritten = false;

    function initDiscordWebSocket() {
        discordWebSocket = new WebSocket(discordGatewayUrl);
        discordWebSocket.onopen = () => console.debug("[🔵] Connected");
        discordWebSocket.onmessage = ({ data }) => {
            if (data instanceof Blob) {
                const reader = new FileReader();
                reader.onload = () => {
                    handleMessage(JSON.parse(pako.inflate(new Uint8Array(reader.result), { to: 'string' })));
                };
                reader.readAsArrayBuffer(data);
            } else {
                handleMessage(JSON.parse(data));
            }
        };
        discordWebSocket.onclose = () => {
            console.debug("[🔵] Disconnected");
            clearInterval(discordHeartbeatInterval);
            if (++discordReconnectRetryCount < 5) {
                initDiscordWebSocket();
            }
        };
    }
    function createDiscordChatMessage(message) {
        if (sentMessagesIds.includes(message.id)) {
            return;
        }
        for (const name in settings.discordSavedChannels) {
            if (settings.discordSavedChannels[name] === message.channel_id) {
                sentMessagesIds.push(message.id);
                console.debug("[🔵] New message:", message);
                switch (message.type) {
                    case 0:  // MESSAGE
                    case 19: // REPLY
                        const tab = chtTabs.querySelector(`div[data-username="discord-${message.channel_id}"]`);
                        if (!tab) {
                            newDiscordTab(name, message.channel_id);
                        } else if (!tab.classList.contains('selected')) {
                            tab.classList.add('blink');
                            setTimeout(() => tab.classList.remove('blink'), 2000);
                        }
                        localChatMessages.push({
                            O: true,
                            v: 0,
                            o: 0,
                            P: 0,
                            U: 0,
                            name: message.author.global_name,
                            G: "discord-" + message.channel_id,
                            get color() {
                                discordAuthor = this._discordAuthor;
                                return discordUsername === this._discordAuthor.username ? "#313338" : "#5662E9";
                            },
                            message: (message.content || '') + message?.attachments?.map?.(({ filename }) => `<${filename}>`)?.join?.(' '),
                            category: 2,
                            goldMember: 0,
                            L: 0,
                            Y: 0,
                            q: 0,
                            j: 0,
                            J: 0,
                            time: Date.now(),
                            _cache: null,
                            get cache() {
                                return this._cache;
                            },
                            set cache(value) {
                                value.icons = [ 14 ];
                                return this._cache = value;
                            },
                            _discordAuthor: message.author
                        });
                        break;
                }
                break;
            }
        }
    }
    function handleMessage(message) {
        const { op, t, d } = message;
        switch (op) {
            case 10: // Hello
                console.debug("[🔵] Connection accepted");
                discordHeartbeatInterval = setInterval(() => sendWebsocketDiscordMessage(1, null), d.heartbeat_interval);
                sendWebsocketDiscordMessage(2, {
                    token: discordToken,
                    capabilities: 30717,
                    properties: {}
                });
                settings.discordPresence && setTimeout(() => sendWebsocketDiscordMessage(3, discordPresence), 2000);
                break;
            case 0: // Dispatch
                switch (t) {
                    case "MESSAGE_CREATE":
                        createDiscordChatMessage(d);
                        break;
                    case "READY":
                        discordUsername = d.user?.username || discordUsername;
                        console.debug("[🔵] Logged as", discordUsername);
                        break;
                }
                break;
            case 1: // HEARTBEAT
                sendWebsocketDiscordMessage(1, null);
                break;
            case 11: // HEARTBEAT_ACK
                break;
            default:
                console.debug("[🔵] Unhandled message type:", message);
        }
    }
    function findUrlToOpen(event) {
        const x = event.clientX - event.target.offsetLeft,
              y = event.clientY - event.target.offsetTop;
        for (const message of localChatMessages) {
            if (message.cache && message.cache._urls) {
                for (const { url, rect } of message.cache._urls) {
                    if (x >= rect.x0 && y >= rect.y0 && x <= rect.x1 && y <= rect.y1) {
                        unsafeWindow.open(url, '_blank');
                    }
                }
            }
        }
    }
    function timeFormat(s) {
        s /= 1000;
        const h = Math.floor(s / 3600);
        const m = Math.floor(s % 3600 / 60);
        return (h ? h + 'h ' : '') + (m ? m + 'm ' : '') + Math.floor(s % 3600 % 60) + 's';
    }
    function getTable(payload) {
        if (payload === null) {
            return "<table style=\"width: 100%; text-align: left;\"><tr><td>Player not registered</td><tr><td>You need to play at least 1 game of batle royale to be registered on <a href=\"https://agma.io/stats.php\" target=\"_blank\">Agma Stats</a></td></tr></table>";
        }
        return (
            "<table style=\"width: 100%; text-align: left;\"><tr><td>Players Consumed: </td><td>"
            + numberFormat.format(payload.players_consumed)
            + "</td></tr><tr><td>Death Count: </td><td>"
            + numberFormat.format(payload.death_count)
            + "</td></tr><tr><td>K/D: </td><td>"
            + (payload.players_consumed / payload.death_count).toFixed(2)
            + "</td></tr><tr><td>Splits count: </td><td>"
            + numberFormat.format(payload.splits_count)
            + "</td></tr><tr><td>Total time alive: </td><td>"
            + timeFormat(payload.total_time_alive * 1000)
            + "</td></tr><tr><td>Splits per seconds: </td><td>"
            + (payload.splits_count / payload.total_time_alive).toFixed(2)
            + "</td></tr></table>"
        );
    }

    let jQueryWrapper = unsafeWindow.$;
    Object.defineProperty(unsafeWindow, "$", {
        set: function(jQuery) {
            const jQueryFind = jQuery.prototype.find;
            jQuery.prototype.find = function() {
                const res = jQueryFind.apply(this, arguments);
                if (
                    this.selector === "#contextMenu"
                    && arguments?.[0] === "li.enabled.hover"
                    && res?.length
                    && res[0].id === "contextUserProfile"
                    && discordAuthor
                ) {
                    // FIXIT: This is bugged but whatever I'm lazy
                    swal({
                        title: `<img src="https://cdn.discordapp.com/avatars/${discordAuthor.id}/${discordAuthor.avatar}" width="128" height="128" style="border-radius:50%;"><br><br><span>${discordAuthor.global_name}</span><br><span style="font-size:12px;">${discordAuthor.username}</span>`,
                        html: true
                    });
                    discordAuthor = null;
                    return [];
                }
                return res;
            }
            const jQueryShow = jQuery.prototype.show;
            jQuery.prototype.show = function() {
                if (discordAuthor !== null && this.selector === "#contextMenu") {
                    jQuery("#contextUserProfile").addClass("enabled");
                    jQuery("#contextFriendAdd").removeClass("enabled");
                    jQuery("#contextPrivateMessage").removeClass("enabled");
                    jQuery("#contextMute").removeClass("enabled");
                }
                return jQueryShow.apply(this, arguments)
            }
            const jQueryHide = jQuery.prototype.hide;
            jQuery.prototype.hide = function() {
                if (discordAuthor !== null && this.selector === "#contextMenu") {
                    discordAuthor = null;
                }
                return jQueryHide.apply(this, arguments)
            }
            return jQueryWrapper = jQuery
        },
        get: function() {
            return jQueryWrapper;
        }
    });
    let swalWrapper = unsafeWindow.swal;
    Object.defineProperty(unsafeWindow, "swal", {
        set: function(originalSwal) {
            let waitingResponse = false;
            swalWrapper = function(params, callback) {
                if (!discordAuthor && params?.title?.startsWith("<img src=\"")) {
                    if (waitingResponse) {
                        return;
                    }
                    const username = params.title.match(/>([^>]+)<\/span>/)?.[1];
                    if (!username) {
                        return originalSwal(params, callback);
                    }
                    if (Date.now() - userprofiles[username]?.at < 86400000) {
                        params.text += getTable(userprofiles[username].data);
                        originalSwal(params, callback);
                    } else {
                        waitingResponse = true;
                        $.getJSON("https://agma.io/royale_stats.php?user=" + username, payload => {
                            userprofiles[username] = { at: Date.now(), data: payload };
                            params.text += getTable(payload);
                            waitingResponse = false;
                            originalSwal(params, callback);
                        }).fail(() => {
                            userprofiles[username] = { at: Date.now(), data: null };
                            params.text += getTable(null);
                            waitingResponse = false;
                            originalSwal(params, callback);
                        }).always(() => {
                            waitingResponse = false;
                        });
                    }
                } else {
                    return originalSwal(params, callback);
                }
            }
            swalWrapper.close = function() {
                discordAuthor = null;
                return originalSwal.close.apply(this, arguments);
            }
            return swalWrapper;
        },
        get: function() {
            return swalWrapper;
        }
    });
    const originalDrawImage = unsafeWindow.CanvasRenderingContext2D.prototype.drawImage;
    unsafeWindow.CanvasRenderingContext2D.prototype.drawImage = function() {
        if (arguments[0] instanceof Image && arguments[0].src.startsWith("https://agma.io/img/chaticons") && arguments[1] === 280) {
            arguments[0] = discordIcon;
            arguments[1] = 0;
            arguments[6] += 3;
        }
        return originalDrawImage.apply(this, arguments);
    }
    const originalReplace = unsafeWindow.String.prototype.replace;
    unsafeWindow.String.prototype.replace = function(pattern, replacement) {
        return originalReplace.call(this, pattern, replacement instanceof Function && pattern instanceof RegExp && pattern.source.startsWith(":rolling") ? (match, offset) => match === ":/" && this?.[offset + 1] === '/' ? match : replacement(match, offset) : replacement);
    }
    const originalPush = unsafeWindow.Array.prototype.push;
    unsafeWindow.Array.prototype.push = function(elem) {
        if (
            elem?.time !== undefined
            && elem?.cache === null
        ) {
            if (localChatMessages === undefined) {
                localChatMessages = this;
            }
            if ((elem.message = elem.message.replaceAll(invisibleChar, "")).includes("https://")) {
                Object.defineProperty(elem, "cache", {
                    get: function() {
                        return this._cache;
                    },
                    set: function(cache) {
                        if (elem._discordAuthor) {
                            cache.icons = [ 14 ];
                        }
                        Object.defineProperty(cache, "ctx", {
                            get: function() {
                                return this._ctx;
                            },
                            set: function(ctx) {
                                ctx.fillText = function(text, x, y) {
                                    if (this.fillStyle !== "#f5f6ce" && this.fillStyle !== "#444444") {
                                        return CanvasRenderingContext2D.prototype.fillText.call(this, text, x, y);
                                    }
                                    // ngl I asked chatgpt cuz Im lazy (and I edited some stuff)
                                    let match;
                                    let lastIndex = 0;
                                    let currentX = x;
                                    cache._urls = [];
                                    while ((match = urlRegex.exec(text)) !== null) {
                                        const url = match[0];
                                        const urlStart = match.index;
                                        const urlEnd = urlStart + url.length;

                                        const preText = text.slice(lastIndex, urlStart);
                                        if (preText) {
                                            CanvasRenderingContext2D.prototype.fillText.call(this, preText, currentX, y);
                                            currentX += ctx.measureText(preText).width;
                                        }
                                        ctx.save();
                                        ctx.fillStyle = '#1E90FF';
                                        CanvasRenderingContext2D.prototype.fillText.call(this, url, currentX, y);

                                        const urlWidth = ctx.measureText(url).width;
                                        const textSize = parseInt(ctx.font.match(/\d+/), 10);
                                        const underlineY = y + 2;

                                        ctx.beginPath();
                                        ctx.moveTo(currentX, underlineY);
                                        ctx.lineTo(currentX + urlWidth, underlineY);
                                        ctx.strokeStyle = '#1E90FF';
                                        ctx.lineWidth = 1;
                                        ctx.stroke();
                                        ctx.restore();
                                        cache._urls.push({
                                            url,
                                            rect: {
                                                x0: currentX,
                                                yd0: y - textSize,
                                                x1: currentX + urlWidth,
                                                yd1: y
                                            }
                                        });
                                        currentX += urlWidth;
                                        lastIndex = urlEnd;
                                    }
                                    const remainingText = text.slice(lastIndex);
                                    if (remainingText) {
                                        CanvasRenderingContext2D.prototype.fillText.call(this, remainingText, currentX, y);
                                    }
                                }
                                return this._ctx = ctx;
                            }
                        });
                        return this._cache = cache
                    }
                });
            }
        } else if (elem?.ch !== undefined && elem?.x0 !== undefined) {
            elem.ch.cache?._urls?.forEach(urlObject => {
                urlObject.rect.y0 = urlObject.rect.yd0 + elem.y0;
                urlObject.rect.y1 = urlObject.rect.yd1 + elem.y0;
            });
        } else if (elem?.namePart !== undefined && elem?.clanPart !== undefined) {
            if (!cellProtoOverwritten) {
                if (settings.removeAnimations.length) {
                    elem.constructor.prototype.ge = function(animation) {
                        if (1 == this.a || settings.removeAnimations.includes(animation.H)) {
                            return;
                        }
                        animation = { H: animation.H, K: animation.K, received: animation.received };
                        if (this.Ne) {
                            for (var i = 0; i < this.Ne.length; i++) {
                                if (this.Ne[i].received > animation.received) {
                                    this.Ne.splice(i, 0, animation);
                                    if (this.Ne.length > settings.maxStackableAnimations) {
                                        this.Ne.splice(this.Ne.length - 2, 1);
                                    }
                                    return;
                                }
                            }
                            if (this.Ne.length < settings.maxStackableAnimations) {
                                originalPush.call(this.Ne, animation);
                            } else {
                                this.Ne[this.Ne.length - 1] = animation;
                            }
                        } else {
                            this.Ne = [animation];
                        }
                    }
                }
                cellProtoOverwritten = true;
            }
            if (settings.removeFood && elem.Pe) { // elem.a === 1
                return 0;
            }
        }
        return originalPush.apply(this, arguments);
    }

    unsafeWindow.setAnimation = (id, value) => settings.removeAnimations[settings.removeAnimations.includes(id) ? 'remove' : 'push'](id);
    unsafeWindow.setMaxStackableAnimations = value => settings.maxStackableAnimations = parseInt(value);
    unsafeWindow.setRemoveFood = value => settings.removeFood = value;
    unsafeWindow.setDiscordChat = value => {
        if (settings.discordChat = value) {
            !discordWebSocket && initDiscordWebSocket();
        } else if (discordWebSocket !== null) {
            discordWebSocket.close();
            discordWebSocket = null;
        }
    };
    unsafeWindow.setDiscordPresenceChat = value => settings.discordPresence = value;
    unsafeWindow.newDiscordTab = (name, channel) => chtTabs && (chtTabs.innerHTML += `<div data-category="2" data-username="discord-${channel}" data-insert data-tooltip="Discord chat: ${name}" class="chat-tab semi-selected">${name}</div>`);
    unsafeWindow.sendDiscordMessage = (channel, content) => settings.discordChat && fetch(`https://discord.com/api/v9/channels/${channel}/messages`, {
            method: 'POST',
            headers: {
                'Authorization': discordToken,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                content,
                tts: false
            })
        })
        .then(async response => createDiscordChatMessage(await response.json()))
        .catch(error => console.error('[🔵] Error while trying to send a message:', error));

    var documentLoaded = false;
    document.addEventListener("DOMContentLoaded", () => {
        if (documentLoaded) {
            return;
        }
        documentLoaded = true;
        const chtCanvas = document.getElementById("chtCanvas");
        chtCanvas.addEventListener("dblclick", findUrlToOpen);
        chtCanvas.addEventListener("click", event => event.ctrlKey && findUrlToOpen(event));
        document.getElementById("chtbox").addEventListener("keydown", function(event) {
            if (event.keyCode === 13) {
                if (!currentTab && this.value.startsWith("/discord ")) {
                    const args = this.value.slice(9).split(' ');
                    const channelName = args.shift();
                    this.value = args.join(' ').trim();
                    if (settings.discordSavedChannels[channelName] && !chtTabs.querySelector(`div[data-username="discord-${settings.discordSavedChannels[channelName]}"]`)) {
                        newDiscordTab(channelName, settings.discordSavedChannels[channelName]);
                    }
                    if (this.value) {
                        sendDiscordMessage(settings.discordSavedChannels[channelName], this.value);
                        this.value = '';
                    }
                } else if (currentTab.startsWith("discord-")) {
                    if (this.value = this.value.trim()) {
                        sendDiscordMessage(currentTab.slice(8), this.value);
                        this.value = '';
                    }
                } else {
                    for (const [reg, rep] of wordsToReplace) {
                        this.value = this.value.replaceAll(reg, rep);
                    }
                }
            }
        });
        chtTabs = document.getElementById("chtTabs");
        chtTabs.addEventListener("click", () => setTimeout(() => currentTab = chtTabs.querySelector("div.chat-tab.selected").dataset.username, 1));
        document.querySelector(".setting-tabs").innerHTML += `<button id="settingTab5" class="setting-tablink" onclick="openSettingPage(5);" style="width: 9%; font-size: calc(0.3vw + 7.5px);"><div class="fa fa-plus fa-lg" style="font-size: 15px; color: lightgray;"></div></button>`;
        document.getElementById("setting").innerHTML += `
            <div id="settingPage5" class="setting-tabcontent">
                <div class="col-md-10 col-md-offset-1 stng" style="padding-left:20px;padding-right:10px;max-height:550px;overflow-y:auto;overflow-x:hidden;margin:0;width:calc(100% - 5px);">
                    <span style="margin:0;" class="hotkey-paragraph"> Animations</span>
                    <div class="row stng-row" style="font-size:14px;">
                        <div style="width:100%;padding:4px;">
                            <div style="display:flex;flex-wrap:wrap;padding:0px;width:100%;">
                                ${animationsIds.map(id => `<div style="${animations[id].style}" onclick="setAnimation(${id}, !this.classList.toggle('disabled'));" class="emote${settings.removeAnimations.includes(id) ? " disabled" : ''}">${animations[id].name}</div>`).join('')}
                            </div>
                        </div>
                    </div>
                    <span style="margin:0;" class="hotkey-paragraph"> Other</span>
                    <div class="row stng-row" style="font-size:14px;">
                        <label>
                            <input type="number" min="0" style="max-width:30px" value="${settings.maxStackableAnimations}" onchange="setMaxStackableAnimations(this.value);">
                            <span> Stackable Animations *</span>
                        </label>
                        <br>
                        <label>
                            <input type="checkbox" onchange="setRemoveFood(this.checked);" ${settings.removeFood ? " checked" : ''}>
                            <span> Remove Food *</span>
                        </label>
                    </div>
                    <span style="margin:0;" class="hotkey-paragraph"> Discord</span>
                    <div class="row stng-row" style="font-size:14px;">
                        <label>
                            <input type="checkbox" onchange="setDiscordChat(this.checked);" ${settings.discordChat ? " checked" : ''}>
                            <span> Discord Chat *</span>
                        </label>
                        <br>
                        <label>
                            <input type="checkbox" onchange="setDiscordPresenceChat(this.checked);" ${settings.discordPresence ? " checked" : ''}>
                            <span> Discord Agma.io Presence *</span>
                        </label>
                        <br>
                        <label>
                            <span> Discord Saved Channels *</span>
                            <textarea id="discordSavedChannels" style="resize: vertical; min-height: 100px; width: 100%;" placeholder="agma.io,942193976063197214\nname,channelId">${Object.entries(settings.discordSavedChannels).map(entry => entry.join(',')).join('\n')}</textarea>
                        </label>
                    </div>
                </div>
            </div>
        `;
        const discordSavedChannelsTextarea = document.getElementById("discordSavedChannels");
        discordSavedChannelsTextarea.addEventListener("blur", function(event) {
            const result = {};
            for (const line of this.value.split('\n')) {
                let [name, channel] = line.split(',');
                name = name.trim();
                channel = channel.trim();
                if (name && channel) {
                    result[name] = channel;
                } else {
                    alert('Invalid content. Please ensure each line has exactly one comma separating the key and value.');
                    this.value = Object.entries(settings.discordSavedChannels).map(entry => entry.join(',')).join('\n')
                    return 
                }
            }
            settings.discordSavedChannels = result;
        });
        discordSavedChannelsTextarea.addEventListener("keydown", function(event) {
            event.stopPropagation();
        });
        const style = document.createElement("style");
        style.innerHTML = `
            div.chat-tab[data-username^="discord-"] {
                background: #4954c5;
            }
            .setting-tablink {
                width: auto !important;
            }
            #settingTab4, #settingTab5 {
                width: 9% !important;
            }
            .setting-tabcontent > div::-webkit-scrollbar {
                width: 8px;
                height: 8px;
            }
            .setting-tabcontent > div::-webkit-scrollbar-track {
                background: #282934;
                border-radius: 10px;
            }
            .setting-tabcontent > div::-webkit-scrollbar-thumb {
                background-color: #df8500;
                border-radius: 10px;
                border: 2px solid #282934;
            }
            div.emote {
                min-width: 30px;
                height: 30px;
                padding: 3px;
                border-radius: 5px;
                border-width: 1px;
                border-style: solid;
                margin: 4px;
                background-size: contain;
                background-repeat: no-repeat;
                cursor: pointer;
                text-overflow: ellipsis;
            }
            div.emote.disabled {
                text-decoration: line-through;
                text-decoration-thickness: 3px;
                text-decoration-color: red;
            }
        `;
        document.body.appendChild(style);
    });
    unsafeWindow.addEventListener("beforeunload", () => {
        GM_setValue("settings", settings);
    });
    settings.discordChat && initDiscordWebSocket();
    console.log("%cAdvanced Agma - 0.0.2 Loaded", "padding: 40px; font-weight: bold; font-size: 32pt; color: black;");
})();