Xat Plus

Unaffiliated extension for the Xat HTML5 Chatbox. RIP Xat Edition.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Xat Plus
// @namespace    http://sulptax.io/
// @version      0.4.7
// @description  Unaffiliated extension for the Xat HTML5 Chatbox. RIP Xat Edition.
// @author       sulptax
// @match        https://xat.com/content/web/*/box/www/classic.html
// @require      http://code.jquery.com/jquery-3.5.1.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js
// @grant        unsafeWindow
// ==/UserScript==
const secret = 'sulptax';

function xp_encrypt(str) {
    return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(str));
}

function xp_decrypt(str) {
    return CryptoJS.enc.Base64.parse(str).toString(CryptoJS.enc.Utf8);
}

function xp_aes_encrypt(str) {
    return CryptoJS.AES.encrypt(str, secret).toString();
}

function xp_aes_decrypt(str) {
    var bytes = CryptoJS.AES.decrypt(str, secret);
    return bytes.toString(CryptoJS.enc.Utf8);
}

// Allow functions below to be used in the console, not like these are used for storing important data anyways.
// You must be at the chat directly for these to work:
// https://xat.com/content/web/R00022/box/www/classic.html
unsafeWindow.xp_encrypt = xp_encrypt;
unsafeWindow.xp_decrypt = xp_decrypt;

var users = {
    "585435788": {
        "type": "color", // color, pawn, pawn2
        "reghide": true, // like reghide power
        "v": "000001", // the color value
    },
    "400444434": {
        "type": "color",
        "v": "y",
        "effective": true, // overwrites the message pawn as well if true, This is the case by default.
        "persistent": true // keep the pawn color regardless of the pawn used in the list
    },
    "287773358": { // Shadez bot is here for demonstration purposes, because it's everywhere.
        "type": "pawn2", // pawn2 changes the pawn type
        "v": "p1bot" // examples: p1bot, p1emerald, p1pwn
    },
    "981989": {
        "type": "pawn2",
        "v": "p1emerald#y" // can also use color codes in pawn2 value
    },
    "30000013": {
        "type":"pawn2",
        "v": "p1emerald#r#r"
    }
}

var effectiveChanges = {}
const observer = new MutationObserver((mutationList, observer) => {
    mutationList.forEach((mutation) => {
        if (mutation.type === "childList") {
            if (mutation.target.id == "idvisitors" || mutation.target.id == "idfriends" || mutation.target.id == "messages") {
                mutation.addedNodes.forEach((node) => {
                    Object.keys(users).forEach(function(user) {
                        var color = "";
                        var holder = $(node).find(".holder:first");
                        var res = holder.attr("data-sm");
                        if ($(node).attr("data-user") == user) {
                            var str = res
                            if (res.split("#")[1] != "ff0000" && res.split("#")[1] != "ff0000)_20") {
                                if (users[$(node).attr("data-user")]['type'] == "color") {
                                    color = users[$(node).attr("data-user")]['v']
                                    res = str.split("#");
                                    res[1] = color;
                                    res = res.join("#");
                                    res = res + ")_20"
                                }
                                if (users[$(node).attr("data-user")]['type'] == "pawn") {
                                    res = users[$(node).attr("data-user")]['v']
                                }
                                var res3 = "";
                                if (users[$(node).attr("data-user")]['type'] == "pawn2") {
                                    var res2 = str.split("#");
                                    res2[0] = res2[0].split("(")[0] + "(" + users[$(node).attr("data-user")]['v'];
                                    res = res2.join("#")
                                    res3 = res.split("#", 2).join("#") + ")_20";
                                } else {
                                    res3 = res;
                                }
                                if (Object.keys(users[$(node).attr("data-user")]).includes("reghide")) {
                                    $(node).find(".relIcon2").hide();
                                }
                                var filters = "";
                                if (Object.keys(users[$(node).attr("data-user")]).includes("glow")) {
                                    if(isColor(users[$(node).attr("data-user")]['glow'])) {
                                        filters = filters + "drop-shadow(0px 0px 0.2rem " + users[$(node).attr("data-user")]['glow'] + ") "
                                    }
                                }
                                if(filters) {
                                   holder.css("filter", filters);
                                }
                                if (!(Object.keys(users[$(node).attr("data-user")]).includes("effective") && !(users[$(node).attr("data-user")]['effective'] == true))) {
                                    effectiveChanges[$(node).find(".message").text()] = res3
                                } else if (color && (Object.keys(users[$(node).attr("data-user")]).includes("persistent") && users[$(node).attr("data-user")]['persistent'])) {
                                    effectiveChanges[$(node).find(".message").text()] = "s_(p1pwn#" + color + ")_20"
                                }
                                holder.attr("data-sm", res)
                            }
                        }
                    });
                });
            }
        }
    });
});
messages.addMessageP = messages.addMessage
messages.addMessage = function(t) {
    messages.addMessageP(t);
}
visitors.addVisitorP = visitors.addVisitor
visitors.addVisitor = function(e, l) {
    visitors.addVisitorP(e, l);
    var e_parsed = JSON.parse(e);
    if (Object.keys(e_parsed).includes("image")) {
        e_parsed['image'].split("#").forEach((im) => {
            if (true) { // im.toString(CryptoJS.enc.Utf8)
                try {
                    var checkForPawn = xp_decrypt(im)
                    if (checkForPawn && (checkForPawn.startsWith('{') && checkForPawn.endsWith('}'))) {
                        // example JSON
                        // {"type":"pawn2", "v":"p1emerald#y#hat3#w1i0ic#y", "reghide": true}
                        // {"type":"pawn2", "v":"p1emerald#y#hat3#w1i0ic#y", "reghide": true, "glow":"red"}
                        console.log("JSON PAWN DETECTED IN avatar/image:", checkForPawn);
                        try {
                            users[e_parsed['id']] = JSON.parse(checkForPawn);
                        } catch (e) {
                            console.log("Error parsing pawn code");
                        }
                    } else if (checkForPawn && checkForPawn.substring(0, 2) == "p1") {
                        console.log("NORMAL PAWN DETECTED IN avatar/image:", checkForPawn);
                        users[e_parsed['id']] = {
                            "type": "pawn2",
                            "v": checkForPawn
                        }
                    }
                } catch(e) {
                    // decrypt error?
                }
            }
        })
    }
}
const observer2 = new MutationObserver((mutationList, observer) => {
    mutationList.forEach((mutation) => {
        if (mutation.type === "childList") {
            mutation.addedNodes.forEach((node) => {
                if (Object.keys(effectiveChanges).includes($(node).find(".messagesName").find(".message").text())) {
                    $(node).find(".messagesName").find(".holder:first").attr("data-sm", effectiveChanges[$(node).find(".messagesName").find(".message").text()])
                }
            });
        }
    });
});
observer.observe(document.querySelector("#visitorsContainer"), {
    childList: true,
    subtree: true
});
observer2.observe(document.querySelector("#messagesContainer"), {
    childList: true,
    subtree: true
});
function isColor(color) {
    var div = $("<div>");
    div.css("border", "1px solid " + color);
    return (div.css("border-color") != "")
}