Last active
December 13, 2021 08:01
-
-
Save oexlkinq/523821df7b2a7c2868a5f3bcb35f7a7e to your computer and use it in GitHub Desktop.
trovo nickname colorizer tampermonkey script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name trovonicknamecolorizer | |
// @namespace http://tampermonkey.net/ | |
// @version 0.2.7 | |
// @description colorize nicknames in Trovo chat | |
// @author yyko | |
// @match https://trovo.live/* | |
// @icon https://icons.duckduckgo.com/ip2/trovo.live.ico | |
// @run-at document-end | |
// @grant GM_addStyle | |
// ==/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()); | |
// Palette icon made by Google (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>'; | |
const obsConfig={childList:true}; | |
const classPrefix='clrz_'; | |
const cpCSSbase='.cp_list,.cp_color{display: inline-block;line-height: 0px;}.cp_list{max-width: 125px;}.cp_color{margin: 0px;width: 25px;height: 25px;transition: all 0.2s ease;}.cp_color_active{box-shadow: 0 0 0 5px white inset;}'; | |
const onlyChat=!!document.location.href.match('https://trovo.live/chat/.*'); | |
// 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 sessionUsers=new Map(); | |
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,4}$|^#(?:[0-9a-f]{2}){3,4}$/)){ | |
return 2; | |
}else{ | |
return false; | |
} | |
} | |
function findColorByCode(cc){ | |
for(let i of colorMap){ | |
if(i[1]==cc) | |
return i[0]; | |
} | |
} | |
// -- | |
// stylesheet | |
let ss; | |
function initSS(){ | |
if(ss) | |
document.head.appendChild(ss); | |
else | |
ss=GM_addStyle(makeStyleText()); | |
} | |
function createUserClass(name,color){ | |
ss.innerHTML=ss.innerHTML+`.${getUserClassName(name)}{color:${color} !important;}`; | |
sessionUsers.set(name,color); | |
} | |
function changeUserClass(name,newcolor){ | |
let ucn=getUserClassName(name); | |
ss.innerHTML=ss.innerHTML.replace(`.${ucn}{color:${getUserColor(name)} !important;}`,`.${ucn}{color:${newcolor} !important;}`); | |
} | |
function getUserClassName(name){ | |
return `${classPrefix}${name}`; | |
} | |
// -- | |
// pallete | |
function makeStyleText(lumshift=0.2){ | |
let cpCSS=cpCSSbase; | |
function cpbCSS(cn,cc){ | |
function parseCol(a){ | |
let outp=[]; | |
a=a.slice(1); | |
for(let i=0;i<3;i++){ | |
outp.push(parseInt(a.slice(i*a.length/3,(i+1)*a.length/3),16)); | |
if(a.length==3) | |
outp[i]*=16; | |
} | |
return outp; | |
} | |
function clamp(a,min,max){ | |
return (a<min)?min:(a>max)?max:a; | |
} | |
function hex(from){ | |
let outp='#',tl=true,t; | |
for(let i in from) | |
from[i]=Math.round(from[i]); | |
for(let i of from) | |
tl=tl&(i%0x11==0); | |
for(let i of from){ | |
t=i.toString(16); | |
outp+=(tl)?t[0]:(t.length>1)?t:'0'+t; | |
} | |
return outp; | |
} | |
function slum(col,s){ | |
col=col.slice(); | |
let as=s*3*0xff; | |
let sow=0; | |
if(s>0){ | |
for(let i of col) | |
sow+=1-i/0xff; | |
for(let i=0;i<3;i++) | |
col[i]=clamp(col[i]+(1-col[i]/0xff)/sow*as,0,0xff); | |
return col; | |
}else{ | |
for(let i of col) | |
sow+=i/0xff; | |
for(let i=0;i<3;i++) | |
col[i]=clamp(col[i]+col[i]/0xff/sow*as,0,0xff); | |
return col; | |
} | |
} | |
function shiftCol(col,s){ | |
return hex(slum(parseCol(col),s)); | |
} | |
return `.cp_color_${cn}{background-color: ${cc};}.cp_color_${cn}:hover{background-color: ${shiftCol(cc,lumshift)};}`; | |
} | |
for(let i of colorMap) | |
cpCSS+=cpbCSS(i[0],i[1]); | |
return cpCSS; | |
} | |
function createPalleteElement(lstn){ | |
function n(t){return document.createElement(t);} | |
let outp=n('div'); | |
outp.className='cp_list'; | |
function onselect(e,me,silent=false){ | |
me=me||this; | |
for(let i of outp.childNodes) | |
i.classList.remove('cp_color_active'); | |
me.classList.toggle('cp_color_active'); | |
if(!silent&&lstn) | |
lstn(outp.nick,me.getAttribute('mycolor')); | |
} | |
let colblock; | |
outp.colblocks=[]; | |
for(let i of colorMap){ | |
colblock=n('div'); | |
colblock.className='cp_color cp_color_'+i[0]; | |
colblock.setAttribute('mycolor',i[0]); | |
colblock.addEventListener('click',onselect); | |
outp.appendChild(colblock); | |
outp.colblocks.push(colblock); | |
} | |
outp.style.position='fixed'; | |
outp.style.zIndex='99999'; | |
outp.style.display='none'; | |
outp.setPos=function(x,y){ | |
outp.style.left=x+'px'; | |
outp.style.top=y+'px'; | |
}; | |
outp.select=function(color){ | |
for(let i of outp.colblocks){ | |
if(i.getAttribute('mycolor')==color){ | |
onselect(null,i,true); | |
break; | |
} | |
} | |
}; | |
return outp; | |
} | |
function onclick(e){ | |
switch(true){ | |
case e.target.classList.contains('nick-name'): | |
palleteElement.nick=e.target.getAttribute('title'); | |
palleteElement.select(findColorByCode(getUserColor(palleteElement.nick))); | |
//kostyl | |
setTimeout(function(){ | |
try{ | |
let boxpos=document.getElementsByClassName('card-container')[0].getBoundingClientRect(); | |
palleteElement.setPos((onlyChat)?boxpos.x+boxpos.width:boxpos.x-palleteElement.getBoundingClientRect().width,boxpos.y); | |
}catch(e){console.log('увы, костыль не сработал',e);} | |
},123); | |
//--kostyl | |
case e.target.classList.contains('cp_color'): | |
palleteElement.style.display='block'; | |
break; | |
default: | |
palleteElement.style.display='none'; | |
palleteElement.nick=null; | |
break; | |
} | |
//return false; | |
} | |
// -- | |
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(!sessionUsers.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; | |
let palleteElement; | |
function findChatElement(){ | |
return document.getElementsByClassName('chat-list')[0]; | |
} | |
let attemptsLeft=maxAttemptsCount; | |
let attemptsTimer; | |
function initChat(){ | |
launched=false; | |
launching=true; | |
chatElement=findChatElement(); | |
if(chatElement){ | |
initSS(); | |
palleteElement=createPalleteElement(changeUserColor); | |
document.body.appendChild(palleteElement); | |
window.addEventListener('mouseup',onclick); | |
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(); | |
// -- | |
})(); |
v0.2.7:
--при нажатии на никнейм пользователя в чате, рядом со всплывающим окном доп.информации появляется палитра, с помощью которой можно выбрать цвет ника для этого пользователя (цвет меняется только для вас)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
v0.2.6.3:
--цвета новых пользователей генеририруются исходя из их имени = ваш цвет будет одинаковым у всех пользователей