BlastarBegoner ][+

further enhancements for Kuro5hin.org

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name          BlastarBegoner ][+
// @namespace     
// @description   further enhancements for Kuro5hin.org
// @include       http://www.kuro5hin.org/*
// @include       https://www.kuro5hin.org/*
// @version       0.5.6
// ==/UserScript==

var ShitList = new Object();

// start config

/*
 * set to false to also kill replies to killed comments.
 */
var Orphans = true; 


/* 
 * if you wish to ignore a user, add them, like below.
 * note this is case sensitive.
 */
 
ShitList['Edmund Blackadder'] = true;
ShitList['Cancer'] = true;
ShitList['Thomas Hard'] = true;
ShitList['Riddick'] = true;
ShitList['Atari 2600'] = true;
ShitList['Horsecock Sodomy'] = true;
ShitList['horsecock sodomy'] = true;
ShitList['Pirate Ninja'] = true;
ShitList['i am a pretty big deal'] = true;

// end config


var xmlRequest = new XMLHttpRequest();

var forms = document.forms;

var rating_re = /^rating_(\d+)$/;
var user_re = /\/user\/uid:(\d+)$/;
var diary_re = /\/user\/([a-zA-Z0-9% ]+)\/diary$/;


// check if there's anybody on the shit list.

var DoSL = false;
for (var i in ShitList)
{
	DoSL = true;
	break;
}

//utility functions to make life easier.


// creates a new option element.  
// GreaseMonkey doesn't support new Option() / select.add()
function newOption(name, value)
{
	var x = document.createElement('option');
	x.value = value;
	x.appendChild(document.createTextNode(name));
	return x;	
}

// find a specific parent element for a tag.
// k5 is chock full of nested tables and such.
function outerElement(node, tag, count)
{
	if (count == 0) return null;
	if (node == null) return null;
		
	if (node.nodeType == 1 && node.tagName == tag)
	{
		if (--count == 0) return node;	
	}	

	node = node.parentNode;
	
	return node ? outerElement(node, tag, count) : null;
	
}

// returns the first element or null if none.
//
function firstChildElement(node)
{
	if (node == null) return null;
	node = node.firstChild;
	while (node)
	{
		if (node.nodeType == 1) return node;
	}
	return null;
}

// gets the next element (tag), ignoring text, cdata, comments, etc.
function nextElement(element)
{
	while (element = element.nextSibling)
	{
		if (element.nodeType == 1) return element;
	}
	return null;
}
// gets the previous element (tag), ignoring text, cdata, comments, etc.
function previousElement(element)
{
	while (element = element.previousSibling)
	{
		if (element.nodeType == 1) return element;
	}
	return null;
}


// copys elements from a NodeList (which is live) to an array (which is not)
function nodeArray(nodeList)
{
	var array = new Array(nodeList.length);
	for (var i = 0; i < nodeList.length; i++)
		array[i] = nodeList[i];
	return array;
}

// onclick, onsubmit callbacks.

// replacement comment rater.  This uses xmlhttprequest and is done asynchronously.
function rateComments(event)
{
			
	event.preventDefault();
	var form = event.target;
	var post = '';
	var inc = new Object();
	// build up the post data.
	for (var j = 0; j < form.elements.length; j++)
	{
		var e = form.elements[j];
		if (e.name != '')
		{
			if (inc[e.name]) continue;
			inc[e.name] = true;
			post = post + '&' + encodeURIComponent(e.name) 
				+ '=' + encodeURIComponent(e.value);
		}
	}
	post = post.substr(1);
	//alert(post);
	
	xmlRequest.open('POST', form.action, true);
	xmlRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	
	xmlRequest.onreadystatechange = function()
	{
		if (xmlRequest.readyState == 4)
		{
			//alert('done');
		}
	}
	xmlRequest.send(post);
}

// set all comment ratings to the specified rating.
function bitchSlap(event)
{

	event.preventDefault();
	var form = event.target.form;
	var value = document.getElementById('__select').value;

	for (var j = 0; j < form.elements.length; j++)
	{
		var e = form.elements[j];
		
		if (e.type == 'select-one')
		{
			if (e.name.match(rating_re))
			{
				e.value = value;
			}	
		}	
		
	}
}

// show/hide comment replies.  replies are placed in a <dl><dt> after the comment.
function showHide(event)
{
	event.preventDefault();						
	var target = event.target;
	var hide = target.firstChild.data == 'Hide Replies';
	
	target.firstChild.data = hide ? 'Show Replies' : 'Hide Replies';
		
	var comment = outerElement(target, 'TABLE', 2);
	if (comment)
	{
		comment = nextElement(comment);

		if (comment.tagName == 'DL' || comment.tagName == 'dl')
		{
			
			comment.style.visibility = hide ? 'collapse' : 'visible';	
			
		}	
		
	}	
}


// remove comments from people on the shitlist.
function killComments(form)
{
	var delta = false;
	
	var links = nodeArray(form.getElementsByTagName('a'));
	for (var j = 0; j < links.length; j++)
	{
		var link = links[j];
		//if (link.href.indexOf('uid') != -1) 
		//	alert(link.href + ' ' + link.firstChild.data);
		if (!link.href.match(user_re)) continue;
		
		var user = link.firstChild.data;
		if (!ShitList[user]) continue;
		var comment = outerElement(link, 'TABLE', 3);
		if (comment)
		{
			if (Orphans  == false)
			{
				var temp = nextElement(comment);
				if (temp && temp.tagName == 'DL')
				temp.parentNode.removeChild(temp);	
			}
			
			comment.parentNode.removeChild(comment);
			delta = true;
		}
		
	}
	if (delta)
	{
		// now go through and kill any blank indentations 
		// (<dl><dt></dt><dd></dd></dl>)
		var dls = nodeArray(form.getElementsByTagName('dl'));
		for (var j = 0; j < dls.length; j++)
		{
			var dl = dls[j];
			var kill = true;
			var x = dl.firstChild;
			while(x && kill)
			{
				if (firstChildElement(x)) kill = false;
				x = x.nextSibling();	
			}
			if (kill)
			{
				dl.parentNode.removeChild(dl);
			}		
		}
		
	}
}

// remove diary entries from people on the shitlist
function killDiaryEntries()
{
	var links = nodeArray(document.body.getElementsByTagName('a'));
	for (var j = 0; j < links.length; j++)
	{
		var match;
		var link = links[j];
		if (match = link.href.match(diary_re))
		{
			var name = match[1];
			// convert %20 to ' '
			name = decodeURIComponent(name);
			if (!ShitList[name]) continue;
			var p = outerElement(link, 'TABLE', 1);
			if (p) p.parentNode.removeChild(p);
			
		}
	}
}


// remove diary sidebar entries from people on the shitlist
function killDiarySidebars()
{

	var links = nodeArray(document.body.getElementsByTagName('a'));
	for (var j = 0; j < links.length; j++)
	{
		var match;
		var link = links[j];
		if (match = link.href.match(diary_re))
		{
			var name = match[1];
			// convert %20 to ' '
			name = decodeURIComponent(name);
			if (!ShitList[name]) continue;
			var p = outerElement(link, 'P', 1);
			if (p) p.parentNode.removeChild(p);
			
		}
	}
}

// add a link to show/hide child comments.
function addShowHide(form)
{
	// I wanted to base this on the "rate" button, but that fails
	// for your own comments.... sigh...
	
	var links = nodeArray(form.getElementsByTagName('a'));	
	
	for (var j = 0; j < links.length; j++)
	{
		var link = links[j];
		if (link.href.indexOf('/post#here') == -1) continue;
		
		var comment = outerElement(link, 'TABLE', 2);		
		// check for any replies...

		var temp = nextElement(comment);
		if (temp && temp.tagName == 'DL')
		{			
			var parent = link.parentNode;
			
			parent.insertBefore(document.createTextNode(' '), link);
			var newlink = parent.insertBefore(document.createElement('a'), link);
			newlink.href = '#';
			newlink.appendChild(document.createTextNode('Hide Replies'));
			newlink.addEventListener('click', showHide, true);	
			
			parent.insertBefore(document.createTextNode(' | '), link);

								
		}	
	}
		
}


if (window.location.href.indexOf('/story/') > 0 
	|| window.location.href.indexOf('/comments/') > 0 )
{
		
	for (var i = 0; i < forms.length; i++)
	{
		var form = forms[i];
		if (form.name == 'rate')
		{
			// 1. posting will be done via xmlhttprequest.
			
			form.addEventListener('submit', rateComments, true);
			
			// 4 kills comments from users on the shit list.
			// this will not kill any replies, however, 
			// which it probably should do as well.
			
			if (DoSL) killComments(form);
			
			
			// - - - - - - - - 
			
			// 2a add a reset button
			// 2b. add dhtml button to rate all comments.
			
			var div = document.createElement('div');
			var x;
	
			div.style.textAlign = 'center';
			form.insertBefore(div, form.firstChild);
			x = div.appendChild(document.createElement('input'));
			x.type = 'reset';
			x.value = 'Reset Ratings';
			
			div.appendChild(document.createTextNode(' '));
			
			x = div.appendChild(document.createElement('select'));
			x.id = '__select';
			
			// greasemonkey can't use the select.add() method.
						
			x.appendChild(newOption('None', 'none'));
			x.appendChild(newOption('Hide', 0));
			x.appendChild(newOption('Discourage', 1));
			x.appendChild(newOption('Neutral', 2));
			x.appendChild(newOption('Encourage', 3));
			
			div.appendChild(document.createTextNode(' '));
	
			x = div.appendChild(document.createElement('input'));
			x.type = 'button';
			x.value = 'Set Ratings';
			
			x.addEventListener('click', bitchSlap, true);
			
			// - - - - - - - - 

			// 3. add show/hide replies link
			addShowHide(form);
			
			
		}
		
	}
}// /story/ page
else
{
	// kill off diary pages from people in the shitlist
	if (DoSL)
	    if (window.location.href.indexOf('/section/') > 0)
		killDiaryEntries();
	    else
		killDiarySidebars();
	
}

// fix up indentation a bit.
GM_addStyle('dd { padding-left: 0px; margin-left: 0px;}');
GM_addStyle('dl { padding-left: 1.5em; margin-left: 0px;}');