twitch spam filter

this script reduces twitch's chat spam

// ==UserScript==
// @name        twitch spam filter
// @description this script reduces twitch's chat spam
// @namespace   twitch
// @include     /^https?://www\.twitch\.tv/[a-zA-Z0-9_]+$/
// @version     0.1
// @grant       none
// ==/UserScript==

/* known issues :
** - the last chat message is sometimes hidden, you need to scroll a bit,
**   or wait for the next message to see it.
** - if you naviguate to another stream through the website,
**   the spam count will not show. You need to refresh the page to 
**   reset it.
*/

/* todo :
** - filter 'weird' text, which is most likely copypasta
*/

window.onload = function() {
    /* helper functions */
    var uniq = function(str) {
	var seen = {};
	return str.filter(function(item) {
            return seen.hasOwnProperty(item) ? false : (seen[item] = true);
	});
    };
    /* objects */
    /* Bucket */
    var Bucket = function(size) {
	this.maxSize = size;
	this.currentSize = 0;
	this.array = [];
    };
    Bucket.prototype.add = function(elem) {
	if (this.currentSize < this.maxSize) {
	    this.array.push(elem);
	    this.currentSize++;
	    return ;
	}
	this.array.shift();
	this.array.push(elem);
    };
    Bucket.prototype.contains = function(elem) {
	return this.array.indexOf(elem) != -1;
    };
    /* * Message */
    var Message = function(object) {
	this.object = object;
	this.parse(object);
    };
    Message.prototype.parse = function(object) {
	this.from = $(".from", object).text();
	this.content = $(".message", object).text().trim();
	this.emoticons = this.parseEmoticons($(".emoticon", object));
	this.badges = this.parseBadges($(".badge", object));
    };
    Message.prototype.parseEmoticons = function(object) {
	var parsed = [];
	object.each(function() {
	    parsed.push($(this).attr("alt"));
	});
	return parsed;
    };
    Message.prototype.parseBadges = function(object) {
	var parsed = [];
	object.each(function() {
	    parsed.push($(this).attr("class").split(" ").slice(3)[0]);
	});
	return parsed;
    };
    Message.prototype.show = function() {
	$(this.object).addClass("filtered");
	return $(this.object).show();
    };
    Message.prototype.remove = function() {
	return $(this.object).remove();
    };
    /* * MessageHandler */
    var MessageHandler = function() {
	this.filtered = 0;
	this.filteredBox = null;
	this.filterBoxActive = false
	this.whiteHandlers = []; // the message is shown if one hadnler returns true
	this.blackHandlers = []; // the message is filtered if one handler returns false
    };
    MessageHandler.prototype.init = function() {

    };
    MessageHandler.prototype.handleMessage = function(message) {
	for (var i = 0, max = this.whiteHandlers.length; i < max; i++) {
	    if (this.whiteHandlers[i](message) === true) {
		return true;
	    }
	}
	for (var i = 0, max = this.blackHandlers.length; i < max; i++) {
	    if (this.blackHandlers[i](message) === false) {
		return false;
	    }
	}
	return true;
    };
    MessageHandler.prototype.registerHandler = function(type, handler) {
	if (! this.hasOwnProperty(type)) {
	    return false;
	}
	this[type].push(handler);
	return true;
    };
    MessageHandler.prototype.createFilterBox = function() {
	this.filteredBox = $("<p class='filterbox' title='spam count' style='position:relative;top:-2px;left:8px;color: rgb(166, 142, 210)'></p>");
	if ($(".chat-buttons-container").append(this.filteredBox)) {
	    $(this.filteredBox).text(this.filtered);
	    this.filterBoxActive = true;
	}
    };
    MessageHandler.prototype.incFilterCount = function() {
	if (! this.filterBoxActive) {
	    this.createFilterBox();
	}
	this.filtered++;
	$(this.filteredBox).text(this.filtered);
    };
    /* whiteHandlers */
    var whitelist = [
	$(".username").text()
    ];
    var whitelistHandler = function(message) {
	for (var i = 0, max = whitelist.length; i < max; i++) {
	    if (message.from == whitelist[i]) {
		return true;
	    }
	}
	if (message.from == "") { // admin messages leave username blank
	    return true;
	}
	return false;
    };
    /* blackHandlers */
    var emoteHandler = function(message) {
	/* if the message is empty, it only contains emotes */
	if (! message.content.length) {
	    return false;
	}
	/* that's too much */
	if (message.emoticons.length >= 5) {
	    return false;
	}
	return true;
    };
    var numericHandler = function(message) {
	/* Kappa 123 */
	return isNaN(message.content);
    };
    var oneWordHandler = function(message) {
	/* who cares of false positives */
	return message.content.indexOf(" ") != -1;
    };
    var capsLockPleaseHandler = function(message) {
	var caps = 0;
	var alphaNum = 0;
	for (var i = 0, max = message.content.length; i < max; i++) {
	    if (message.content[i] >= 'A' && message.content[i] <= 'Z') {
		caps++;
		alphaNum++;
	    }
	    else if (message.content[i] != " ") {
		alphaNum++;
	    }
	}
	if (alphaNum / caps <= 2.0) {
	    return false;
	}
	return true;
    };
    var sameSameHandler = function(message) {
	var msg = message.content.split(" ");
	var uniqMsg = uniq(msg);
	if (msg.length / uniqMsg.length >= 1.7) {
	    return false;
	}
	return true;
    };
    var latestMessages = new Bucket(30);
    /* r9kHandler should be executed last, as storing a filtered
    ** message is useless */
    var r9kHandler = function(message) {
	var ret = true;
	if (latestMessages.contains(message.content)) {
	    ret = false;
	}
	latestMessages.add(message.content);
	return ret;
    };
    /* code */
    var hideMessages = function() {
	$("head").append("<style type='text/css'>.chat-line { display: none; }</style>");
    };
    var messageHandler = new MessageHandler();
    var whiteHandlers = [
	whitelistHandler
    ];
    var blackHandlers = [
	emoteHandler,
	numericHandler,
	oneWordHandler,
	capsLockPleaseHandler,
	sameSameHandler,
	r9kHandler
    ];
    messageHandler.init();
    for (var i = 0, max = whiteHandlers.length; i < max; i++) {
	messageHandler.registerHandler("whiteHandlers", whiteHandlers[i]);
    }
    for (var i = 0, max = blackHandlers.length; i < max; i++) {
	messageHandler.registerHandler("blackHandlers", blackHandlers[i]);
    }
    hideMessages();
    setInterval(function() {
	var messages = $(".chat-line").not(".filtered");
	messages.each(function() {
	    var message = new Message(this);
	    if (messageHandler.handleMessage(message)) {
		message.show();
	    }
	    else {
		message.remove();
		messageHandler.incFilterCount();
	    }
	});
    }, 200);
};
长期地址
遇到问题?请前往 GitHub 提 Issues,或加Q群1031348184

赞助商

Fishcpy

广告

Rainyun

注册一下就行

Rainyun

一年攒够 12 元