// ==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();
// --
})();