trovonicknamecolorizer

colorize nicknames in Trovo chat

目前為 2021-10-29 提交的版本,檢視 最新版本

// ==UserScript==
// @name         trovonicknamecolorizer
// @namespace    http://tampermonkey.net/
// @version      0.2.6.2
// @description  colorize nicknames in Trovo chat
// @author       yyko
// @match        https://trovo.live/*
// @icon         https://www.google.com/s2/favicons?domain=trovo.live
// @run-at       document-end
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const maxAttemptsCount=10;
    const attmeptDelay=2000;

    const colorMap=new Map([
      ["red","#FF0000"],//красный
      ["blue","#0000FF"],//синий
      ["green","#008000"],//зелёный
      ["firebrick","#B22222"],//кирпичный
      ["coral","#FF7F50"],//коралловый
      ["yellowgreen","#9ACD32"],//лайм
      ["orangered","#FF4500"],//красно-оранжевый
      ["seagreen","#2E8B57"],//морская волна
      ["goldenrod","#DAA520"],//красное золото
      ["chocolate","#D2691E"],//шоколадный
      ["cadetblue","#5F9EA0"],//серо-голубой
      ["dodgerblue","#1E90FF"],//васильковый
      ["hotpink","#FF69B4"],//ярко-розовый
      ["blueviolet","#8A2BE2"],//индиго
      ["springgreen","#00FF7F"],//салатовый
    ]);
    const colorNames=Array.from(colorMap.keys());

    const obsConfig={childList:true};
    const classPrefix='clrz_';

    // local storage tools

    function mapToStr(map){
        return JSON.stringify(Object.fromEntries(map));
    }

    function strToMap(str){
        return new Map(Object.entries(JSON.parse(str)));
    }

    function loadData(entryName='users'){
        let data=localStorage.getItem(entryName);
        if(data){
            return strToMap(data);
        }else{
            return null;
        }
    }

    function saveData(data,entryName='users'){
        localStorage.setItem(entryName,mapToStr(data));
    }

    // --

    // users tools

    let users=loadData();
    if(users){
        if(localStorage.getItem('tncts_localUsers')){
            localStorage.removeItem('tncts_localUsers');
        }
    }else{
        users=new Map();
    }

    function addUser(name){
        let userColor=getRandomColorName();
        createUserClass(name,userColor);
        changeUserColor(name,userColor);
        return userColor;
    }

    function delUser(name){
        users.delete(name);
        saveData(users);
    }

    // --

    // color tools

    function getRandomColorName(){
        return colorNames[Math.round(Math.random()*colorNames.length)];
    }

    function getUserColor(name){
        return users.get(name);
    }

    function changeUserColor(name,colorName){
        let ccr=checkColor(colorName);
        if(ccr){
            let cv;
            if(ccr==1){
                cv=colorMap.get(colorName.toLocaleLowerCase());
            }else if(ccr==2){
                cv=colorName;
            }
            changeUserClass(name,cv);
            users.set(name,cv);
            saveData(users);
        }
    }

    function checkColor(colorName){
        if(colorMap.has(colorName)){
            return 1;
        }else if(colorName.match(/^#[0-9a-f]{3}$|^#[0-9a-f]{4}$|^#[0-9a-f]{6}$|^#[0-9a-f]{8}$/)){
            return 2;
        }else{
            return false;
        }
    }

    // --

    // stylesheet

    let ss;
    let bayav=new Map();

    function initSS(){
        ss=ss||document.createElement('style');
        document.head.appendChild(ss);
    }

    function createUserClass(name,color){
        ss.innerHTML=ss.innerHTML+`.${classPrefix}${name}{color:${color} !important;}`;
        bayav.set(name,color);
    }

    function changeUserClass(name,newcolor){
        ss.innerHTML=ss.innerHTML.replace(`.${classPrefix}${name}{color:${getUserColor(name)} !important;}`,"$`"+`.${classPrefix}${name}{color:${newcolor} !important;}`+"$'");
    }

    function getUserClassName(name){
        return `${classPrefix}${name}`;
    }

    // --

    function onmessage(mutations,observer){
        for(let mutation of mutations){
            for(let msgel of mutation.addedNodes){
                let nameel=msgel.getElementsByClassName('nickname-box')[0];
                let name;
                if(nameel){
                    name=nameel.getElementsByClassName('nick-name')[0].title;
                    if(!users.has(name))
                        addUser(name);
                    else if(!bayav.has(name))
                        createUserClass(name,getUserColor(name));

                    // processing a color change command
                    let msgtextel=msgel.getElementsByClassName('content')[0];
                    if(msgtextel){
                        let msgtext=msgtextel.innerText;
                        let res=msgtext.match(/^!color (.*)/);
                        if(res){
                            let colorValue=res[1];
                            if(checkColor(colorValue)){
                                changeUserColor(name,res[1]);
                            }else{
                                console.warn('color is not available');
                            }
                        }
                    }

                    // applying the color
                    nameel.classList.add(getUserClassName(name));
                }
            }
        }
    }

    // initialization

    let launched;
    let launching;
    let chatElement;
    let chatObserver;

    function findChatElement(){
        return document.getElementsByClassName('chat-list')[0];
    }

    let attemptsLeft=maxAttemptsCount;
    let attemptsTimer;

    function initChat(){
        launched=false;
        launching=true;

        chatElement=findChatElement();
        if(chatElement){
            initSS();

            chatObserver=new MutationObserver(onmessage);
            chatObserver.observe(chatElement,obsConfig);

            launched=true;
            launching=false;
            console.warn('started');
        }else{
            if(attemptsLeft>0){
                console.warn('attempts left to start: ',attemptsLeft--);
                attemptsTimer=setTimeout(initChat,attmeptDelay);
            }else{
                console.warn('cant find chat element');
                launching=false;
            }
        }
    }

    function initBaseObs(){
        let baseElement=document.getElementsByClassName('base-container')[0];
        if(baseElement){
            let baseObserver=new MutationObserver(onbasechanged);
            baseObserver.observe(baseElement,obsConfig);
        }else{
            console.warn('cant find base-container');
        }
    }

    function onbasechanged(){
        if(findChatElement()){
            if(!launching&&!launched)
                initChat();
        }else{
            if(launched){
                console.warn('stopping');
                chatObserver.disconnect();
                ss.remove();
                attemptsLeft=maxAttemptsCount;
                launched=launching=false;
            }
        }
    }

    function init(){
        initBaseObs();
        initChat();
    }

    init();

    // --
})();