New Collab VM

Adds new features to Collab VM chat

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey, Greasemonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

You will need to install an extension such as Tampermonkey to install this script.

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

Advertisement:

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

Advertisement:

// ==UserScript==
// @name New Collab VM
// @description Adds new features to Collab VM chat
// @namespace collabvm
// @version 2016.04.17
// @match http://computernewb.com/*
// @run-at document-end
// @grant none
// ==/UserScript==
'use strict';

var ignoredusers={'chocolatebot':1,'ha3orx':1,'eeveevulpix':1,'inspector gadget bot':1,'grok gimme cock':1,'fuck you 1337':1}
var hideusers=/^(666|afk|c3po)$/i
var guests=/^guest\d+$/i


var chatbox=document.getElementById('chat-box')
var onlineusers=document.getElementById('online-users')
var chatpanel=document.getElementById('chat-panel')
var chatinput=document.getElementById('chat-input')

if(chatbox&&onlineusers&&chatpanel){

var initial=1
var changedusers=[]
var sentmessages=[]
var sentindex=-1
var lastli
var lastdiv
var ignoredialog=element(
	document.body,
	['div#ignoredialog',{
		class:'ignoredialog',
		tabIndex:-1
	},
		['div',{
			onclick:function(event){
				ignoredialog.blur()
				var name=event.currentTarget.parentNode.dataset.name.toLowerCase()
				var add
				if(ignoredusers[name]){
					ignoredusers[name]=0
				}else{
					ignoredusers[name]=1
					add=1
				}
				var usernames=document.querySelectorAll('#chat-box .username')
				for(var i=0;i<usernames.length;i++){
					if(usernames[i].firstChild.nodeValue.toLowerCase()==name){
						usernames[i].parentNode.parentNode.style.display=add?'none':''
					}
				}
			}
		},'Ignore user']
	]
).ignoredialog

// Detect changes in user list
new MutationObserver(function(mutations){
	mutations.forEach(function(mutation){
		for(var i=0;i<mutation.addedNodes.length;i++){
			var thisnode=mutation.addedNodes[i]
			var name=thisnode.firstChild.nodeValue
			if(hideusers.test(name)){
				thisnode.style.display='none'
			}else if(!guests.test(name)){
				changedusers.push([1,name])
				thisnode.style.color='hsl('+(random(strtonum(name))*20|0)*18+',50%,50%)'
			}
			thisnode.addEventListener('contextmenu',function(event){
				event.preventDefault()
				ignoredialog.style.left=(document.body.scrollLeft+event.clientX+5)+'px'
				ignoredialog.style.top=(document.body.scrollTop+event.clientY+5)+'px'
				ignoredialog.dataset.name=name
				if(ignoredusers[name.toLowerCase()]){
					ignoredialog.classList.add('ignored')
				}else{
					ignoredialog.classList.remove('ignored')
				}
				ignoredialog.focus()
			})
		}
		for(var i=0;i<mutation.removedNodes.length;i++){
			var name=mutation.removedNodes[i].firstChild.nodeValue
			if(!hideusers.test(name)&&!guests.test(name)){
				changedusers.push([-1,name])
			}
		}
	})
}).observe(onlineusers,{childList:1})

// Detect changes in chat
new MutationObserver(function(mutations){
	var date=new Date()
	mutations.forEach(function(mutation){
		for(var i=0;i<mutation.addedNodes.length;i++){
			var thisnode=mutation.addedNodes[i]
			var username=thisnode.getElementsByClassName('username')[0]
			if(!initial){
				var minute=date.getMinutes()
				if(minute<10){
					minute='0'+minute
				}
				thisnode.firstChild.dataset.time=date.getHours()+':'+minute
			}
			if(username){
				var user=username.firstChild.nodeValue
				var ignored
				if(ignoredusers[user.toLowerCase()]){
					thisnode.style.display='none'
				}else{
					changedusers=[]
					lastli=lastdiv=null
				}
				if(!guests.test(user)){
					username.style.color='hsl('+(random(strtonum(user))*20|0)*18+',50%,50%)'
				}
				var textnode=thisnode.firstChild.lastChild
				var text=textnode.nodeValue
				textnode.nodeValue=text=text.replace(/(\\x[\da-f]{2}|\\u[\da-f]{4}|\\u{1[\da-f]{4}})+/g,function(){
					return eval('"'+arguments[0]+'"')
				})
				if(text[0]=='>'){
					var textnode=element(
						['span#textnode',{
							class:'quote'
						},text]
					).textnode
					thisnode.firstChild.replaceChild(textnode,thisnode.firstChild.lastChild)
					textnode=textnode.firstChild
				}
				var pos=[]
				var found
				var nameregex=new RegExp(window.username,'ig')
				while((found=nameregex.exec(text))!=null){
					pos.push([found.index,found[0].length])
				}
				var urlregex=/(^|\b)(https?:\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#\-()]*[\w@?^=%&/~+#\-()])?|(i\.)?imgur\.com\/[\w\-.?#]+)/ig
				while((found=urlregex.exec(text))!=null){
					pos.push([found.index,found[0].length])
				}
				pos.sort(function(a,b){
					return a<b?1:-1
				})
				for(var i in pos){
					var rightpart=text.slice(pos[i][0]+pos[i][1])
					var highlighttext=text.slice(pos[i][0],pos[i][0]+pos[i][1])
					text=text.slice(0,pos[i][0])
					textnode.nodeValue=text
					if(nameregex.test(highlighttext)){
						var highlight=element(
							['b#highlight',{
								class:'mentioned'
							},highlighttext]
						).highlight
					}else{
						var highlight=element(
							['a#highlight',{
								href:highlighttext,
								target:'_blank',
								rel:'noreferrer'
							},highlighttext]
						).highlight
					}
					insertAfter(highlight,textnode)
					insertAfter(document.createTextNode(rightpart),highlight)
				}
			}
		}
	})
	chatpanel.scrollTop=chatpanel.scrollHeight-chatpanel.offsetHeight
	initial=0
}).observe(chatbox,{childList:1})

// Notify when a user joins or leaves in chat
setInterval(function(){
	if(initial){
		if(changedusers.length){
			initial=0
			changedusers=[]
		}
	}else{
		var actualchanges={}
		for(var i in changedusers){
			actualchanges[changedusers[i][1]]=(actualchanges[changedusers[i][1]]||0)+changedusers[i][0]
		}
		var joined=[]
		var left=[]
		for(var i in actualchanges){
			if(!ignoredusers[i.toLowerCase()]){
				if(actualchanges[i]>0){
					joined.push(i)
				}else if(actualchanges[i]<0){
					left.push(i)
				}
			}
		}
		var message=[]
		if(left.length){
			message.push(left.join(', ')+' left')
		}
		if(joined.length){
			message.push(joined.join(', ')+' joined')
		}
		message=message.join('. ')
		if(message){
			if(lastdiv){
				lastdiv.firstChild.nodeValue=message
			}else{
				chatmessage(message)
			}
		}else if(lastdiv){
			chatbox.removeChild(lastli)
			lastli=lastdiv=null
		}
	}
},1000)

// Chat box extensions
chatinput.maxLength=maxChatMsgLen
chatinput.onkeydown=function(event){
	if(event.keyCode==13){ // Enter
		event.preventDefault()
		var text=event.currentTarget.value
		sentmessages.unshift(text)
		sentindex=-1
		event.currentTarget.value=text.replace(/[^\da-z`~!@#$%^&*()\-_=+[\]{};'\\:"|,.\/<>? ]+/gi,jsesc).slice(0,maxChatMsgLen)
		document.getElementById('chat-send-btn').click()
	}else if(event.keyCode==38){ // Up
		event.preventDefault()
		sentindex++
		if(sentindex>=sentmessages.length){
			sentindex=sentmessages.length-1
		}
		if(sentindex>-1){
			event.currentTarget.value=sentmessages[sentindex]
			event.currentTarget.selectionStart=event.currentTarget.selectionEnd=event.currentTarget.value.length
		}
	}else if(event.keyCode==40){ // Down
		event.preventDefault()
		sentindex--
		if(sentindex<0){
			sentindex=-1
			event.currentTarget.value=''
		}else{
			event.currentTarget.value=sentmessages[sentindex]
			event.currentTarget.selectionStart=event.currentTarget.selectionEnd=event.currentTarget.value.length
		}
	}
}

function blurchat(){
	var canvas=document.querySelector('#display>div>div>div')
	if(canvas&&!canvas.onmousedown){
		canvas.onmousedown=function(){
			document.getElementById('chat-input').blur()
		}
	}
}
blurchat()
setInterval(blurchat,500)

} // if(chatbox&&onlineusers&&chatpanel)

element(
	document.head,
	['style',`
.quote{
	color:#789922;
}
.mentioned{
	background:#dedede;
}
[data-time]::before{
	content:attr(data-time);
	font-size:12px;
	padding-right:3px;
}
.ignoredialog{
	position:absolute;
	background:#eee;
	cursor:default;
	z-index:1;
	outline:none;
}
.ignoredialog:not(:focus){
	top:-999px!important
}
.ignoredialog>div{
	min-width:150px;
	overflow:hidden;
	display:flex;
	justify-content:center;
	flex-direction:column;
	padding:5px;
	padding:5px 5px 5px calc(1em + 5px);
}
.ignoredialog>div:hover{
	background:#e6e6e6;
}
.ignoredialog.ignored>div::before {
	content:'\\2713';
	position:absolute;
	margin-left:-1em;
}
#display :not(:first-child){
	pointer-events:none;
}
`]
)

function chatmessage(text){
	lastli=document.createElement('li')
	lastdiv=document.createElement('div')
	lastdiv.appendChild(document.createTextNode(text))
	lastli.appendChild(lastdiv)
	chatbox.appendChild(lastli)
}
function strtonum(str){
	return parseInt(str.replace(/[^\da-z]/gi,''),36)
}
function random(seed){
	seed=Math.sin(seed)*10000
	return (seed-(seed|0)+1)/2
}
function element(){
	var parent
	var lasttag
	var createdtag
	var toreturn={}
	for(var i=0;i<arguments.length;i++){
		var current=arguments[i]
		if(current){
			if(current.nodeType){
				parent=lasttag=current
			}else if(Array.isArray(current)){
				for(var j=0;j<current.length;j++){
					if(current[j]){
						if(!j&&typeof current[j]=='string'){
							var tagname=current[0].split('#')
							lasttag=createdtag=document.createElement(tagname[0])
							if(tagname[1]){
								toreturn[tagname[1]]=createdtag
							}
						}else if(current[j].constructor==Object){
							if(lasttag){
								for(var value in current[j]){
									if(value!='style'&&value in lasttag){
										lasttag[value]=current[j][value]
									}else{
										lasttag.setAttribute(value,current[j][value])
									}
								}
							}
						}else{
							var returned=element(lasttag,current[j])
							for(var k in returned){
								toreturn[k]=returned[k]
							}
						}
					}
				}
			}else if(current){
				createdtag=document.createTextNode(current)
			}
			if(parent&&createdtag){
				parent.appendChild(createdtag)
			}
			createdtag=0
		}
	}
	return toreturn
}
function insertAfter(append,target){
	var parent=target.parentNode
	var next=target.nextSibling
	if(next){
		parent.insertBefore(append,next)
	}else{
		parent.appendChild(append)
	}
}
function jsesc(argument){
	var result=''
	for(var i=0;i<argument.length;i++){
		var character=argument.charAt(i)
		var first=argument.charCodeAt(i)
		if(first>=55296&&first<=56319&&argument.length>i+1){
			var second=argument.charCodeAt(i+1)
			if(second>=56320&&second<=57343){
				var hex=((first-55296)*1024+second-56320+65536).toString(16)
				result+='\\u{'+hex+'}'
				i++
				continue
			}
		}
		var hex=character.charCodeAt(0).toString(16)
		var longhand=hex.length>2
		result+='\\'+(longhand?'u':'x')+('0000'+hex).slice(longhand?-4:-2)
	}
	return result
}