NeoGAF: Blacklists

Experimental blocking based on user-set blacklists

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.

Tendrás que 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.

Tendrás que instalar una extensión como Tampermonkey antes de poder 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)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

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

// ==UserScript==
// @id             neo-blacklist
// @name           NeoGAF: Blacklists
// @namespace      hateradio)))
// @author         hateradio
// @version        1.1
// @description    Experimental blocking based on user-set blacklists
// @include        http*://*.neogaf.com/forum/*
// @match          *://*.neogaf.com/forum/*
// @updated        28 Feb 2016
// @grant          unsafeWindow
// @run-at         document-end
// ==/UserScript==
/*jslint indent: 4, maxerr: 50, browser: true, devel: true, sub: false, fragment: false, nomen: true, plusplus: true, bitwise: true, regexp: true, newcap: true */

//var blacklist = ['NSFW', 'G/A/F/?', 'Pop*', 'Ariana Grande', 'Iggy', 'Nicki', 'Police', 'WorldStar', 'OT', 'Do you*', 'Help me*', 'bug', '...', 'Florida', 'GAF, I just*', 'LTTP'];

(function () {

	'use strict';

	/** Array intersection */
	function intersectClassList(a, cl) {
		// console.log(a, cl);
		return a.filter(function (e) { return cl.contains(e); });
	}

	/** Basic functionallity to find an element's parent
	 * The parentTag can contain a CSS selector, but it has to match exactly
	 *
	 * Eg: 'div.post' and 'p.purple'
	 *
	 * A 'div' has to have 'post' as a class name
	 * A 'p' has to have a 'purple' class
	 *
	 * parentTag can also contiain multiple class names
	 *
	 * Eg: 'div.post.alt2'
	 * Where 'post' and 'alt2' are class selectors
	 */
	function findParent(el, parentTag) {
		var splits = parentTag.toLowerCase().split('.'),
			tag = splits[0].trim(),
			classList = splits.slice(1).filter(function (e) { return !!e.trim(); });

		// console.log("Tag:", tag, classList);
		function loop(parent) {
			var ptag = parent.tagName.toLowerCase(), inter;

			if (classList.length > 0) {
				inter = intersectClassList(classList, parent.classList);
				// console.log('Inter:', tag, inter);
				// console.log(parent, parent.tagName.toLowerCase() === tag, inter.length === classList.length);
				if (ptag === tag &&	inter.length === classList.length) {
					// console.log('found parent');
					return parent;
				}
			} else if (ptag === tag) {
				return parent;
			}

			if (parent.parentElement) {
				return loop(parent.parentElement);
			}

			return null;
		}

		return tag ? loop(el.parentElement) : null;
	}

	function Block(selector, parent, blacklist) {
		if (!selector) {
			return;
		}

		this.selector = selector;
		this.parent = parent;
		this.blacklist = blacklist;
	}

	Block.createFromBlacklist = function (set) {
		return new Block[set.type](set.selector, set.parent, set.blacklist);
	};

	Block.prototype.toggle = function (display) {
		display = !!display;

		var i, j, p, s = document.querySelectorAll(this.selector), style = display ? '' : 'none';

		for (i = 0; i < s.length; i++) {
			for (j = 0; j < this.blacklist.length; j++) {
				if (this.compare(s[i].textContent, this.blacklist[j])) {
					p = findParent(s[i], this.parent);
					// console.log(p);

					if (p) {
						p.style.display = style;
						p.dataset.gmhide = display;
					}
				}
			}
		}
	};

	Block.prototype.hide = function () {
		this.toggle(false);
	};

	Block.prototype.show = function () {
		this.toggle(true);
	};

	/** Only matches words that are identical to some text */
	Block.Exact = function (selector, parent, blacklist) {
		Block.call(this, selector, parent, blacklist);
	};

	/** Simply matches word "OT" inside of phrase "Marvel |OT| jk Marvel doesn't have an OT" */
	Block.Simple = function (selector, parent, blacklist) {
		Block.call(this, selector, parent, blacklist);
	};

	/** Uses RegExps to match text; plain text is converted to a RegExp */
	Block.Complex = function (selector, parent, blacklist) {
		Block.call(this, selector, parent, blacklist);
	};

	Block.Exact.prototype = new Block();
	Block.Simple.prototype = new Block();
	Block.Complex.prototype = new Block();

	Block.Exact.prototype.compare = function (text, word) {
		return text.trim() === word.trim();
	};

	Block.Simple.prototype.compare = function (text, word) {
		return text.trim().toLowerCase().contains(word.trim().toLowerCase());
	};

	Block.Complex.prototype.compare = function (text, regexp) {
		var r = regexp instanceof RegExp ? regexp : new RegExp(regexp, 'ig');
		return r.test(text);
	};

	/** Modify and add items to the set */
	var massBlock = {
		set: {
			userThreads: { // block threads from these users
				selector: '.threadbit.alt1 td[nowrap]:nth-child(3)',
				parent: 'tr', // hide the table row that the element belongs to
				blacklist: ['user1', 'user2', 'etc-users'], // Block some usernames
				type: 'Exact'
			},
			topics: { // block threads with these phrases
				selector: 'td[id^="td_threadtitle"]',
				parent: 'tr',
				blacklist: ['NSFW', 'G/A/F', 'Pop', 'Ariana Grande', 'Iggy', 'Nicki', 'Police', 'WorldStar', 'OT', 'Do you', 'Help me', 'bug', '...', 'Florida', 'GAF, I just', 'LTTP', 'Marvel'],
				type: 'Simple'
			},
			posts: { // block posts from these users
				selector: '.postbit-details-username a',
				parent: 'div.postbit',
				blacklist: ['user1', 'user2', 'etc-users'],
				type: 'Exact'
			},
			RegExample: { // block using regular expressions
				selector: '.RegExample',
				parent: 'div.RegExample',
				blacklist: [/badWord/ig, /an*/ig, /LOL/g],
				type: 'Complex'
			}
		},
		main: function () {
			var s;
			for (s in this.set) {
				if (this.set.hasOwnProperty(s)) {
					Block.createFromBlacklist(this.set[s]).hide();
				}
			}
		}
	};

	massBlock.main();

}());