finesseshot / Permaban

// ==UserScript==
// @name         Permaban
// @namespace    http://tampermonkey.net/
// @version      3.3.1
// @description  Ignores and hides users in blacklist. Bolds the names of your friends. Minimize and max cams using chat commands. Other quality-of-life enhancements.
// @author       fin
// @match        https://*.bromo.chat/
// @grant        unsafeWindow
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    //known limitation: doesn't not search all usernames

    /* add names here to permaban list */
    var bannedNicknamesStore = GM_getValue("bannedNicknames", JSON.stringify([]));
    var bannedNicknames = JSON.parse(bannedNicknamesStore);
    var bestFriendNicknamesStore = GM_getValue("bestFriendNicknames", JSON.stringify([]));
    var bestFriendNicknames = JSON.parse(bestFriendNicknamesStore);
    var hideIgnoredNickStore = GM_getValue("hideIgnoredNick", JSON.stringify(false));
    var hideIgnoredNick = JSON.parse(hideIgnoredNickStore);
    var maximizedNickname;
    var maximizedFriends = false;

    /* Prototypes */
    Function.prototype.clone = function() {
        var that = this;
        var temp = function temporary() { return that.apply(this, arguments); };
        for(var key in this) {
            if (this.hasOwnProperty(key)) {
                temp[key] = this[key];
            }
        }
        return temp;
    };


    /* Find-in-list Functions */
    var ignoreNickname = function(nickname) {
        var name = findName(nickname);

        if (name !== undefined) {
            chatcommand("ignore " + name, "#");
        }
    };

    var hideNickname = function(nickname) {
        var name = findName(nickname);

        if (name !== undefined) {
            chatcommand("hide " + name, "#");
        }
    };

    var unignoreNickname = function(nickname) {
        var name = findName(nickname);

        if (name !== undefined) {
            chatcommand("unignore " + name, "#");
        }
    };

    var unhideNickname = function(nickname) {
        var name = findName(nickname);

        if (name !== undefined) {
            chatcommand("unhide " + name, "#");
        }
    };

    //finds full string match then looks for first match
    var findName = function(nickname, minLength = 2) {
        var userName;
        var users = unsafeWindow.BC.users;

        for (var i = 0; i < users.length; i++) {
            var userNickname = users[i].nickname.toLowerCase();

            if (userNickname == nickname.toLowerCase()) {
                userName = users[i].nickname;
                return userName;
            }
        }

        if (nickname.length > minLength) {
            for (var i = 0; i < users.length; i++) {
                var userNickname = users[i].nickname.toLowerCase();

                if (userNickname.includes(nickname.toLowerCase())) {
                    userName = users[i].nickname;
                    return userName;
                }
            }
        }

        return undefined;
    };

    //finds first match
    // serverId is defined as the chat ID. alphanumeric (looks like base 64).
    var findServerId = function(nickname) {
        var userServerId;
        var users = unsafeWindow.BC.users;

        for (var i = 0; i < users.length; i++) {
            var userNickname = users[i].nickname.toLowerCase();

            if (userNickname == nickname.toLowerCase()) {
                userServerId = users[i].id;
                return userServerId;
            }
        }

        for (var i = 0; i < users.length; i++) {
            var userNickname = users[i].nickname.toLowerCase();

            if (userNickname.includes(nickname.toLowerCase())) {
                userServerId = users[i].id;
                break;
            }
        }

        return userServerId;
    };

    //finds first match
    // streamId is defined as the video stream ID. numbers only.
    var findStreamId = function(nickname) {
        var id = findServerId(nickname);
        var streamId;
        var userStreams = unsafeWindow.BC.userStreams;

        for (var i = 0; i < userStreams.length; i++) {
            var serverId = userStreams[i].origin;

            if (serverId == id) {
                streamId = userStreams[i].id;
                break;
            }
        }

        return streamId;
    };

    var findServerIdFromStreamId = function(id) {
        var userServerId;
        var userStreams = unsafeWindow.BC.userStreams;

        for (var i = 0; i < userStreams.length; i++) {
            var streamId = userStreams[i].id;

            if (streamId == id) {
                userServerId = userStreams[i].origin;
                break;
            }
        }

        return userServerId;
    };

    var findNicknameFromServerId = function(id) {
        var userNickname;
        var users = unsafeWindow.BC.users;

        for (var i = 0; i < users.length; i++) {
            var userServerId = users[i].id;

            if (userServerId == id) {
                userNickname = users[i].nickname;
                break;
            }
        }

        return userNickname;
    };

    var findNicknameFromStreamId = function(streamId) {
        var serverId = findServerIdFromStreamId(streamId);

        return findNicknameFromServerId(serverId);
    };


    /* Helper functions */
    var removeFromArray = function(array, target) {
        var index = array.indexOf(target);
        if (index > -1) {
            array.splice(index, 1);
        }
    };


    /* Print functions */
    var printMessage = function(msg) {
        var mainTab = document.getElementById("tab_#");

        var message = {};
        message.type = "appnotice";
        message.message = msg;

        drawmsg(mainTab, [message]);
    };

    var showBanList = function() {
        if (bannedNicknames.length == 0) {
            printMessage("No users on blacklist.");
        } else {
            printMessage("Blacklisted Users: " + bannedNicknames.join(", "));
        }
    };

    var showBestFriendList = function() {
        if (bestFriendNicknames.length == 0) {
            printMessage("No best friends.");
        } else {
            printMessage("Best friends: " + bestFriendNicknames.join(", "));
        }
    };

    var showBanUsage = function() {
        printMessage("Nicknames that contain string matches found in the blacklist are automatically ignored/hidden.");
        printMessage("To blacklist users, use \"/ban [nickname]\"");
        printMessage("To unblacklist users, use \"/unban [nickname]\"");
        printMessage("To show blacklisted users, use \"/banlist\"");
        printMessage("");
        printMessage("");
        printMessage("To minimize users, use \"/min [nickname]\" or  \"/minimize [nickname]\"");
        printMessage("To unminimize users, use \"/unmin [nickname]\" or  \"/unminimize [nickname]\"");
        printMessage("To maximize a single user, use \"/max [nickname]\" or  \"/maximize [nickname]\"");
        printMessage("To unmaximize all users (except banned users), use \"/unmax\" or  \"/unmaximize\"");
        printMessage("");
        printMessage("");
        printMessage("To friend users, use \"/friend [nickname]\"");
        printMessage("To unfriend users, use \"/unfriend [nickname]\"");
        printMessage("To maximize friends only, use \"/maxfriends\"");
        printMessage("To show friends list, use \"/friendlist\"");
        printMessage("");
        printMessage("");
        printMessage("Hover over ignored messages to show the contents.");
        printMessage("To show ignored messages, use \"/showignored\"");
        printMessage("To hide ignored messages, use \"/hideignored\"");
        printMessage("To hide ignored messages completely, use \"/ignorenick\"");
        printMessage("To show ignored messages with nicknames, use \"/unignorenick\"");
        printMessage("");
        printMessage("");
        printMessage("Double-click on cam names to send that user a private message.");
        printMessage("");
        printMessage("");
        printMessage("");
    };


    /* Banning functions */
    var minimizeNickname = function(nickname) {
        var name = findName(nickname);

        if (name !== undefined) {
            chatcommand("min " + name, "#");
        }
        // var streamId = findStreamId(nickname)
        // var serverId = findServerId(nickname)

        // if (!BC.minlist.includes(serverId)) {
        //     BC.minlist.push(serverId);
        //     console.log("minimizing " + nickname);

        //     if (conference.userStreams.hasOwnProperty(streamId)) {
        //         if (serverId == BC.self.id) {
        //             streamId = "local";
        //         }

        //         remakecambox(streamId);
        //     }
        // }
    };

    var unminimizeNickname = function(nickname) {
        var name = findName(nickname);

        if (name !== undefined) {
            chatcommand("unmin " + name, "#");
        }
        // var streamId = findStreamId(nickname)
        // var serverId = findServerId(nickname)

        // if (BC.minlist.includes(serverId)) {
        //     removeFromArray(BC.minlist, serverId);
        //     console.log("unminimizing " + nickname);

        //     if (conference.userStreams.hasOwnProperty(streamId)) {
        //         if (serverId == BC.self.id) {
        //             streamId = "local";
        //         }

        //         remakecambox(streamId);
        //     }
        // }
    };

    var maximizeNickname = function(nickname) {
        maximizedNickname = nickname;
        var streamId = findStreamId(nickname);
        var userStreams = BC.userStreams;

        for (var key in userStreams) {
            var keyStreamId = userStreams[key].id
            var name = findNicknameFromStreamId(keyStreamId);

            if (keyStreamId != streamId && name !== undefined) {
                minimizeNickname(name);
            }
        }

        unminimizeNickname(nickname);
    }


    var unmaximizeNickname = function() {
        var userStreams = BC.userStreams;

        for (var key in userStreams) {
            var keyStreamId = userStreams[key].id
            var name = findNicknameFromStreamId(keyStreamId);

            if (name !== undefined && !bannedNicknames.includes(name)) {
                unminimizeNickname(name);
            }
        }

        maximizedNickname = undefined;
        maximizedFriends = false;
    }

    var maximizeBestFriends = function() {
        unmaximizeNickname();

        var streamIds = [];
        for (var i = 0; i < bestFriendNicknames.length; i++) {
            var streamId = findStreamId(bestFriendNicknames[i]);

            streamIds.push(streamId);
        }

        var userStreams = BC.userStreams;

        for (var key in userStreams) {
            var keyStreamId = userStreams[key].id
            var name = findNicknameFromStreamId(keyStreamId);

            if (!streamIds.includes(keyStreamId) && name !== undefined) {
                minimizeNickname(name);
            }
        }

        maximizedFriends = true;
    }

    var banNickname = function(nickname) {
        bannedNicknamesStore = GM_getValue("bannedNicknames", JSON.stringify([]));
        bannedNicknames = JSON.parse(bannedNicknamesStore);

        if (!bannedNicknames.includes(nickname)) {
            bannedNicknames.push(nickname);
            GM_setValue("bannedNicknames", JSON.stringify(bannedNicknames));
            printMessage(nickname + " added to blacklist.");

            ignoreNickname(nickname);
            hideNickname(nickname);
            minimizeNickname(nickname);
        } else {
            printMessage(nickname + " already blacklisted");
        }

        showBanList();
    };

    var unbanNickname = function(nickname) {
        bannedNicknamesStore = GM_getValue("bannedNicknames", JSON.stringify([]));
        bannedNicknames = JSON.parse(bannedNicknamesStore);

        if (bannedNicknames.includes(nickname)) {
            removeFromArray(bannedNicknames, nickname);
            GM_setValue("bannedNicknames", JSON.stringify(bannedNicknames));
            printMessage(nickname + " removed from blacklist.");

            unignoreNickname(nickname);
            unhideNickname(nickname);
            unminimizeNickname(nickname);
        } else {
            printMessage(nickname + " not found on blacklist.");
        }

        showBanList();
    }

    var bestFriendNickname = function(nickname) {
        bestFriendNicknamesStore = GM_getValue("bestFriendNicknames", JSON.stringify([]));
        bestFriendNicknames = JSON.parse(bestFriendNicknamesStore);

        if (!bestFriendNicknames.includes(nickname)) {
            bestFriendNicknames.push(nickname);
            GM_setValue("bestFriendNicknames", JSON.stringify(bestFriendNicknames));
            printMessage(nickname + " is now a best friend.");

            addBestFriendStyle(nickname);
        } else {
            printMessage(nickname + " is already a best friend!");
        }

        showBestFriendList();
    };

    var unBestFriendNickname = function(nickname) {
        bestFriendNicknamesStore = GM_getValue("bestFriendNicknames", JSON.stringify([]));
        bestFriendNicknames = JSON.parse(bestFriendNicknamesStore);

        if (bestFriendNicknames.includes(nickname)) {
            removeFromArray(bestFriendNicknames, nickname);
            GM_setValue("bestFriendNicknames", JSON.stringify(bestFriendNicknames));
            printMessage(nickname + " is no longer a best friend.");

            removeBestFriendStyle(nickname);
        } else {
            printMessage(nickname + " is not a best friend.");
        }

        showBestFriendList();
    }

    var addBestFriendStyle = function(nickname) {
        var serverId = findServerId(nickname);

        if (serverId !== undefined) {
            var sheet = window.document.styleSheets[0];
            sheet.insertRule('div.nick[data-userid="' + serverId + '"] { font-weight: bold; }', sheet.cssRules.length);
        }
    }

    var removeBestFriendStyle = function(nickname) {
        var serverId = findServerId(nickname);

        if (serverId !== undefined) {
            var sheet = window.document.styleSheets[0];
            sheet.deleteRule('div.nick[data-userid="' + serverId + '"] { font-weight: bold; }', sheet.cssRules.length);
        }
    }


    var showIgnored = function() {
        var sheet = window.document.styleSheets[0];
        sheet.deleteRule('div.chatentry.ignored > div.msg { display: none; color: #EEEEEE; }', sheet.cssRules.length);
        sheet.deleteRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.msg { display: none; color: #333333; }', sheet.cssRules.length);

        sheet.insertRule('div.chatentry.ignored > div.nick, div.chatentry.ignored:hover > div.msg  { display: inline; color: #EEEEEE; }', sheet.cssRules.length);
        sheet.insertRule('div.chatentry.ignored > div.msg { display: inline; color: #EEEEEE; }', sheet.cssRules.length);

        sheet.insertRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.nick, #theapp[data-darkmode="on"] div.chatentry.ignored:hover > div.msg  { display: inline; color: #33333; }', sheet.cssRules.length);
        sheet.insertRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.msg { display: inline; color: #333333; }', sheet.cssRules.length);

        var scrollWindow = document.getElementById("tab_#").getElementsByClassName("sendre")[0];
        var isScrollDown = !checkscrolllock(scrollWindow);

        if (hideIgnoredNick == "true") {
            printMessage("Type '/unignorenick' to show ignored chats, then /showignored again.");
        }

        decidescroll(scrollWindow, isScrollDown);
    }

    var hideIgnored = function() {
        var sheet = window.document.styleSheets[0];
        sheet.deleteRule('div.chatentry.ignored > div.msg { display: inline; color: #EEEEEE; }', sheet.cssRules.length);
        sheet.deleteRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.msg { display: inline; color: #333333; }', sheet.cssRules.length);

        sheet.insertRule('div.chatentry.ignored > div.nick, div.chatentry.ignored:hover > div.msg { display: inline; color: #EEEEEE; }', sheet.cssRules.length);
        sheet.insertRule('div.chatentry.ignored > div.msg { display: none; color: #EEEEEE; }', sheet.cssRules.length);

        sheet.insertRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.nick, #theapp[data-darkmode="on"] div.chatentry.ignored:hover > div.msg { display: inline; color: #333333; }', sheet.cssRules.length);
        sheet.insertRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.msg { display: none; color: #333333; }', sheet.cssRules.length);
    }

    var hideIgnoredNickname = function() {
        GM_setValue("hideIgnoredNick", JSON.stringify(true));
        hideIgnoredNick = GM_getValue("hideIgnoredNick", JSON.stringify(false));

        var sheet = window.document.styleSheets[0];
        sheet.deleteRule('div.chatentry.ignored > div.msg { display: inline; color: #EEEEEE; }', sheet.cssRules.length);
        sheet.deleteRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.msg { display: inline; color: #333333; }', sheet.cssRules.length);

        sheet.insertRule('div.chatentry.ignored > div.nick, div.chatentry.ignored:hover > div.msg { display: none; color: #EEEEEE; }', sheet.cssRules.length);
        sheet.insertRule('div.chatentry.ignored { display: none; color: #EEEEEE; }', sheet.cssRules.length);

        sheet.insertRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.nick, #theapp[data-darkmode="on"] div.chatentry.ignored:hover > div.msg { display: none; color: #333333; }', sheet.cssRules.length);
        sheet.insertRule('#theapp[data-darkmode="on"] div.chatentry.ignored { display: none; color: #333333; }', sheet.cssRules.length);

        printMessage("Ignored chat messages are no longer shown.")
    }

    var showIgnoredNickname = function() {
        GM_setValue("hideIgnoredNick", JSON.stringify(false));
        hideIgnoredNick = GM_getValue("hideIgnoredNick", JSON.stringify(false));

        var sheet = window.document.styleSheets[0];
        sheet.deleteRule('div.chatentry.ignored > div.nick, div.chatentry.ignored:hover > div.msg { display: none; color: #EEEEEE; }', sheet.cssRules.length);
        sheet.deleteRule('div.chatentry.ignored { display: none; color: #EEEEEE; }', sheet.cssRules.length);

        sheet.deleteRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.nick, #theapp[data-darkmode="on"] div.chatentry.ignored:hover > div.msg { display: none; color: #333333; }', sheet.cssRules.length);
        sheet.deleteRule('#theapp[data-darkmode="on"] div.chatentry.ignored { display: none; color: #333333; }', sheet.cssRules.length);
        sheet.deleteRule('div.chatentry.ignored > div.msg { display: none; color: #EEEEEE; }', sheet.cssRules.length);
        sheet.deleteRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.msg { display: none; color: #333333; }', sheet.cssRules.length);

        sheet.insertRule('div.chatentry.ignored { display: inline; color: #EEEEEE; }', sheet.cssRules.length);
        sheet.insertRule('#theapp[data-darkmode="on"] div.chatentry.ignored { display: inline; color: #333333; }', sheet.cssRules.length);

        sheet.insertRule('div.chatentry.ignored > div.nick, div.chatentry.ignored:hover > div.msg { display: inline; color: #EEEEEE; }', sheet.cssRules.length);
        sheet.insertRule('div.chatentry.ignored > div.msg { display: none; color: #EEEEEE; }', sheet.cssRules.length);

        sheet.insertRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.nick, #theapp[data-darkmode="on"] div.chatentry.ignored:hover > div.msg { display: inline; color: #333333; }', sheet.cssRules.length);
        sheet.insertRule('#theapp[data-darkmode="on"] div.chatentry.ignored > div.msg { display: none; color: #333333; }', sheet.cssRules.length);

        printMessage("Ignored chat messages are now shown.")

        var scrollWindow = document.getElementById("tab_#").getElementsByClassName("sendre")[0];
        var isScrollDown = !checkscrolllock(scrollWindow);

        decidescroll(scrollWindow, isScrollDown);
    }


    var privateMessage = function(event) {
        var serverId = this.parentNode.parentNode.getAttribute("data-from");

        if (document.getElementById("tab_" + serverId) == null) {
            addtab("chatbox_1", serverId);
        }

        switchtab(serverId);
    }

    var addContactClickListeners = function() {
        var camNames = document.getElementsByClassName("camname");
        for (var i = 0; i < camNames.length; i++) {
            var node = camNames[i];
            var serverId = findServerId(node.innerText);

            node.addEventListener("dblclick", privateMessage);
            node.setAttribute("style", "pointer-events: all; cursor: pointer;");
            node.setAttribute("alt", "Double-click to private message");
        }
    }

    var addContactClickListener = function(streamId) {
        var serverId = findServerIdFromStreamId(streamId);

        if (serverId === undefined) {
            return;
        }

        var node = document.querySelector('div.cambox[data-from="' + serverId + '"] > div.overlay > div.camname');

        node.addEventListener("dblclick", privateMessage);
        node.setAttribute("style", "pointer-events: all; cursor: pointer;");
        node.setAttribute("alt", "Double-click to private message");
    }

    var tabListener = function(event) {
        if (event.keyCode == 9) { //tab
            event.preventDefault();
            var string = event.target.value;
            var cursorPosition = event.target.selectionStart;

            if (string.length == 0) {
                var tabs = document.getElementsByClassName('chattab')
                var tabHasFocus = document.querySelector("div[data-chatfocus='yes']")

                var nextTab;
                for (var i = 0; i < tabs.length; i++) {
                    var currentId = tabs[i].id;

                    if (currentId == tabHasFocus.id) {
                        if (i + 1 == tabs.length) {
                            i = -1;
                        }

                        nextTab = tabs[i+1];
                        break;
                    }
                }

                var userId = nextTab.id.slice(4)
                switchtab(userId)
            } else {
                var stringArray = string.split(" ");
                var wordIndex = 0
                var wordStartPosition = 0
                for (var i = 0; i < stringArray.length; i++) {
                    var word = stringArray[i];

                    var wordEndPosition = wordStartPosition + word.length;
                    if (cursorPosition >= wordStartPosition && cursorPosition <= wordEndPosition) { //word found
                        var replacement = findName(word, 0)

                        if (replacement !== undefined) {
                            stringArray[i] = replacement;
                        }
                        break;

                    } else {
                        wordStartPosition = wordEndPosition + 1 //to accound for space
                    }
                }

                var replacementString = stringArray.join(" ")
                event.target.value = replacementString
            }
        }
    }

    var addTabListener = function() {
        var chatInput = document.querySelector("#chatbox_1 .chatinput");
        chatInput.addEventListener("keydown", tabListener);
    }

    var addTitleChatListener = function() {
        var chatTitle = document.querySelector("#chatbox_1 .titleinfo");
        chatTitle.addEventListener("click", function(event) {
            switchtab("#");
        })
    }

    var customCss = function() {
        var sheet = window.document.styleSheets[0];
        sheet.insertRule('div.chatentry[data-color="color0"] { color: #888888; }', sheet.cssRules.length);
        sheet.insertRule('.sendre div.emoji { display: inline; font-size: 15px; }', sheet.cssRules.length);
    }

    var writeTitle = function() {
        var title = "";
        var tabs = window.document.getElementsByClassName("chattab");

        //show number of unread chats window title
        var unread = 0;
        var unreadpm = false;

        if (window.document.querySelector("div.chatswapbutton i").classList.contains("blinking")) {
            unreadpm = true;
            title = title + "* ";
        }

        for (var i = 0; i < tabs.length; i++) {
            var tab = tabs[i];

            unread = unread + parseFloat(tab.getAttribute("data-unread"));
        }

        if (unread > 0) {
            title = title + "(" + unread + ") ";
        }

        title = title + " Bromo.chat";

        if (unreadpm && unread == 0) {
            title = "Bromo.chat";
        }
        
        document.title = title;
    }

    /* Rain Function Clones */
    var subscribeToClone = unsafeWindow.subscribeTo.clone();
    var justjoinedClone = unsafeWindow.justjoined.clone();
    var chatcommandClone = unsafeWindow.chatcommand.clone();
    var drawmsgClone = unsafeWindow.drawmsg.clone();
    var switchtabClone = unsafeWindow.switchtab.clone();
    var remakeCamBoxClone = unsafeWindow.remakeCamBox.clone();
    var makeCamBoxClone = unsafeWindow.makeCamBox.clone();
    var getStreamByStreamIdClone = unsafeWindow.BC.tools.getStreamByStreamId.clone();

    //successfully joined the chat (post password and nickname entry)
    unsafeWindow.justjoined = function(resp, type) {
        justjoinedClone(resp, type);

        printMessage("Permaban v3.2.2")
        //showBanList();
        //showBestFriendList();
        printMessage("Type \"/usage\" to learn how to use this script.");
        hideIgnored();
        addContactClickListeners();
        addTabListener();
        addTitleChatListener();
        customCss();

        //ignore all whether the user exists or not
        for (var i = 0; i < bannedNicknames.length; i++) {
            ignoreNickname(bannedNicknames[i]);
            hideNickname(bannedNicknames[i]);
            minimizeNickname(bannedNicknames[i]);
        }

        for (var i = 0; i < bestFriendNicknames.length; i++) {
            addBestFriendStyle(bestFriendNicknames[i]);
        }

        window.setTimeout(function() {
            //console.log("Injecting custom subscribeto function");
            //On new cam up
            unsafeWindow.subscribeTo = function(stream, options) {
                subscribeToClone(stream, options);
                var streamId = stream.id

                addContactClickListener(streamId);
                var name = findNicknameFromStreamId(streamId).toLowerCase();

                for (var i = 0; i < bannedNicknames.length; i++) {
                    var targetNickname = bannedNicknames[i];

                    if (name.includes(targetNickname)) {
                        hideNickname(name);
                        minimizeNickname(name);
                    }
                }

                if (maximizedFriends) {
                    maximizeBestFriends();
                }

                if (maximizedNickname !== undefined) {
                    maximizeNickname(maximizedNickname);
                }

            };
        }, 5000);

        if (hideIgnoredNick) {
            hideIgnoredNickname();
        } else {
            showIgnoredNickname();
        }
    };

    unsafeWindow.chatcommand = function(input, to) {
        chatcommandClone(input, to);

        var args = input.split(" ");
        var command = args[0];
        var parameter = args[1];

        if (command == "ban") {
            if (parameter === undefined || parameter === "") {
                printMessage("A nickname must be specified.");
                showBanUsage();

                return;
            }

            banNickname(parameter);
        } else if (command == "unban") {
            if (parameter === undefined || parameter === "") {
                printMessage("A nickname must be specified.");
                showBanUsage();

                return;
            }

            unbanNickname(parameter);
        } else if (command == "banlist") {
            showBanList();

        }
        //  else if (command == "minimize" || command == "min") {
        //     if (parameter === undefined || parameter === "") {
        //         printMessage("A nickname must be specified.");
        //         showBanUsage();

        //         return;
        //     }

        //     minimizeNickname(parameter);
        // } else if (command == "unminimize" || command == "unmin") {
        //     if (parameter === undefined || parameter === "") {
        //         printMessage("A nickname must be specified.");
        //         showBanUsage();

        //         return;
        //     }

        //     unminimizeNickname(parameter);
        // }
        else if (command == "maximize" || command == "max") {
            if (parameter === undefined || parameter === "") {
                printMessage("A nickname must be specified.");
                showBanUsage();

                return;
            }

            maximizeNickname(parameter);
        } else if (command == "unmaximize" || command == "unmax") {
            unmaximizeNickname();

        } else if (command == "friend") {
            if (parameter === undefined || parameter === "") {
                printMessage("A nickname must be specified.");

                return;
            }

            bestFriendNickname(parameter);
        } else if (command == "unfriend") {
            if (parameter === undefined || parameter === "") {
                printMessage("A nickname must be specified.");

                return;
            }

            unBestFriendNickname(parameter);
        } else if (command == "friendlist") {
            showBestFriendList();

        } else if (command == "maxfriends") {
            maximizeBestFriends();

        } else if (command == "showignored") {
            showIgnored();

        } else if (command == "hideignored") {
            hideIgnored();

        } else if (command == "ignorenick") {
            hideIgnoredNickname();

        } else if (command == "unignorenick") {
            showIgnoredNickname();

        } else if (command == "usage") {
            showBanUsage();

        }

    };

    unsafeWindow.remakeCamBox = function(stream) {
        remakeCamBoxClone(stream);

        addContactClickListener(stream.id);
    };

    unsafeWindow.makeCamBox = function(stream) {
        makeCamBoxClone(stream);

        addContactClickListener(stream.id);
    };


    unsafeWindow.BC.tools.getStreamByStreamId = function(streamId) {
        for (let i = 0; i < unsafeWindow.BC.localStreams.length; i++) {
            if (unsafeWindow.BC.localStreams[i].id == streamId) {
                return unsafeWindow.BC.localStreams[i];
            }
        }

        return getStreamByStreamIdClone(streamId);
    };


    unsafeWindow.conference.addEventListener('participantjoined', function(event) {
        for (var i = 0; i < bannedNicknames.length; i++) {
            var targetNickname = bannedNicknames[i];
            var name = event.participant.nickname.toLowerCase();

            if (name.includes(targetNickname)) {
                var nicknameArray = name.split("-");
                var nickname = nicknameArray[nicknameArray.length - 1];

                ignoreNickname(nickname);
            }
        }

        for (var i = 0; i < bestFriendNicknames.length; i++) {
            var targetNickname = bestFriendNicknames[i];
            var name = event.participant.nickname.toLowerCase();

            if (name.includes(targetNickname)) {
                var nicknameArray = name.split("-");
                var nickname = nicknameArray[nicknameArray.length - 1];

                addBestFriendStyle(nickname);
            }
        }
    });

    unsafeWindow.document.querySelector(".tabselection").addEventListener("click", function(event) {
        var tab = window.document.querySelector(".chattab")

        writeTitle();
    });

    unsafeWindow.drawmsg = function(tab, entry) {
        drawmsgClone(tab, entry);

        writeTitle();
    };

    unsafeWindow.switchtab = function(userid) {
        switchtabClone(userid);
        var tab = document.getElementById("tab_" + userid);

        document.getElementById("chatbox_1").getElementsByTagName("input")[0].focus();
        writeTitle()
    };

    unsafeWindow.spookdice = function() {
        return;
    }

    unsafeWindow.spookdo = function(num, time, set) {
        return;
    }
})();