// ==UserScript==
// @name trovonicknamecolorizer
// @namespace http://tampermonkey.net/
// @version 0.2.5.9
// @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 = 20;
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"],//салатовый
]);
// Palette icon made by Google from www.flaticon.com (https://www.flaticon.com/authors/google)
const colorizerSvg = '<svg aria-hidden="true" class="svg-icon btn-icon size24" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="24" height="24"><path d="M12 1.5C6.202 1.5 1.5 6.202 1.5 12S6.202 22.5 12 22.5a1.748 1.748 0 0 0 1.295-2.923 1.733 1.733 0 0 1-.437-1.16c0-.969.781-1.75 1.75-1.75h2.059a5.835 5.835 0 0 0 5.833-5.834C22.5 5.677 17.798 1.5 12 1.5zM5.583 12c-.968 0-1.75-.782-1.75-1.75s.782-1.75 1.75-1.75c.969 0 1.75.782 1.75 1.75S6.552 12 5.583 12zm3.5-4.667c-.968 0-1.75-.781-1.75-1.75 0-.968.782-1.75 1.75-1.75.969 0 1.75.782 1.75 1.75 0 .969-.781 1.75-1.75 1.75zm5.834 0c-.969 0-1.75-.781-1.75-1.75 0-.968.781-1.75 1.75-1.75.968 0 1.75.782 1.75 1.75 0 .969-.782 1.75-1.75 1.75zm3.5 4.667c-.969 0-1.75-.782-1.75-1.75s.781-1.75 1.75-1.75c.968 0 1.75.782 1.75 1.75S19.385 12 18.417 12z" style="stroke-width:.0546871"/></svg>';
// 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();
}
let settings = loadData('colorizerSettings');
if(!settings){
settings = new Map([['baseLock',false],['interfaceState',true]]);
}
function addUser(username){
let userColor = getRandomColor();
setUserColor(username,userColor,true);
return userColor;
}
function delUser(username){
users.delete(username);
saveData(users);
}
// --
// color tools
let colorNames;
function getColorNames(){
if(!colorNames){
let colorNamesIterator=colorMap.keys();
colorNames=[];
for(let colorName of colorNamesIterator){
colorNames.push(colorName);
}
}
return colorNames
}
function getRandomColor(){
let colors=getColorNames();
return colors[Math.round(Math.random()*colors.length)];
}
function getUserColor(username){
let userColor;
if(users.has(username)){
userColor = users.get(username);
}else{
userColor = addUser(username);
}
return userColor;
}
function setUserColor(username,colorName,force=false){
if(!settings.get('baseLock')||force){
let ccr=checkColor(colorName);
if(ccr){
let cv;
if(ccr==1){
cv=colorMap.get(colorName.toLocaleLowerCase());
}else if(ccr==2){
cv=colorName;
}
users.set(username,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;
}
}
// --
// iterface
function getSettingsButtonElement(){
let featureBox=document.getElementsByClassName('input-feature-box')[0];
if(featureBox){
return featureBox.getElementsByClassName('cat-button normal icon')[0];
}
}
let cbtn;
function createColorizerButton(){
let sbe=getSettingsButtonElement();
if(sbe){
cbtn=sbe.cloneNode(false);
cbtn.setAttribute('data-enclave','colorizer');
cbtn.innerHTML=colorizerSvg;
cbtn.color='white';
if(settings.get('interfaceState')){
cbtn.classList.add('active');
}
getSettingsButtonElement().after(cbtn);
cbtn.addEventListener('click',toggleInterface);
}
}
function toggleInterface(){
if(settings.get('interfaceState')){
// on disable interface
cbtn.classList.remove('active');
}else{
// on enable interface
cbtn.classList.add('active');
}
toggleBaseLock();
settings.set('interfaceState',!settings.get('interfaceState'));
saveData(settings,'colorizerSettings');
}
// --
// local users base settings
function toggleBaseLock(){
if(settings.get('baseLock')){
// on unlock base
}else{
// on lock base
}
settings.set('baseLock',!settings.get('baseLock'));
}
// --
// ***, ****** ******* *****
let kostyl=true;
// *--
function onmessage(mutations,observer){
if(kostyl){
kostyl=false;
createColorizerButton();
}
for(let mutation of mutations){
for(let msgel of mutation.addedNodes){
let nameel=msgel.getElementsByClassName('nickname-box')[0];
let nickname;
if(nameel){
nickname=nameel.getElementsByClassName('nick-name')[0].title;
// команда на изменение цвета
let msgtextel=msgel.getElementsByClassName('content')[0];
if(msgtextel){
let msgtext=msgtextel.innerText;
let res=msgtext.match(/^!color (.*)/);
if(res){
let args=res[1].split(' ');
let colorValue=args[args.length-1];
if(checkColor(colorValue)){
if(args.length>1){
for(let i=0;i<args.length-1;i++){
if(args[i][0]=='@'){
args[i]=args[i].slice(1);
}
setUserColor(args[i],args[args.length-1]);
}
}else{
setUserColor(nickname,res[1]);
}
}else{
console.warn('color is not available');
}
}
}
// применение цвета к новому сообщению
nameel.style.color=getUserColor(nickname);
}
}
}
}
// initialization
let launched=false;
let chatElement;
let chatObserver;
const obsConfig={childList:true};
function setChatElement(){
chatElement = document.getElementsByClassName('chat-list')[0];
return chatElement;
}
let attemptsLeft = maxAttemptsCount;
let attemptsTimer;
function initChat(){
if(setChatElement()){
chatObserver = new MutationObserver(onmessage);
chatObserver.observe(chatElement,obsConfig);
//createColorizerButton();
console.warn('started');
launched=true;
}else{
if(attemptsLeft>0){
console.warn('attempts left to start: ',attemptsLeft);
attemptsLeft--;
attemptsTimer=setTimeout(initChat,attmeptDelay);
}else{
console.warn('cant find chat element');
}
}
}
function init(){
initChat();
let baseElement = document.getElementsByClassName('base-container')[0];
if(baseElement){
let baseObserver = new MutationObserver(restart);
baseObserver.observe(baseElement,obsConfig);
}else{
console.warn('cant find base-container');
}
}
function restart(){
console.warn('restarted');
attemptsLeft=maxAttemptsCount;
if(launched){
chatObserver.disconnect();
if(cbtn){
cbtn.remove();
kostyl=true;
}
launched=false;
initChat();
}
}
init();
// --
})();