您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Turns the Twitch chat into a civilized chat room by removing spam, all caps messages, repeated phrases, repeated messages, banned messages, repeated letters and more.
// ==UserScript== // @name Civilized Twitch Chat // @description Turns the Twitch chat into a civilized chat room by removing spam, all caps messages, repeated phrases, repeated messages, banned messages, repeated letters and more. // @version 0.2.1 // @author Sewil // @match *://*.twitch.tv/* // @require http://code.jquery.com/jquery-latest.min.js // @namespace https://greasyfork.org/users/14470 // ==/UserScript== /* * arrive.js * v2.2.0 * https://github.com/uzairfarooq/arrive * MIT licensed * * Copyright (c) 2014-2015 Uzair Farooq */ (function(n,q,v){function r(a,b,c){if(e.matchesSelector(a,b.selector)&&(a._id===v&&(a._id=w++),-1==b.firedElems.indexOf(a._id))){if(b.options.onceOnly)if(0===b.firedElems.length)b.me.unbindEventWithSelectorAndCallback.call(b.target,b.selector,b.callback);else return;b.firedElems.push(a._id);c.push({callback:b.callback,elem:a})}}function p(a,b,c){for(var d=0,f;f=a[d];d++)r(f,b,c),0<f.childNodes.length&&p(f.childNodes,b,c)}function t(a){for(var b=0,c;c=a[b];b++)c.callback.call(c.elem)}function x(a, b){a.forEach(function(a){var d=a.addedNodes,f=a.target,e=[];null!==d&&0<d.length?p(d,b,e):"attributes"===a.type&&r(f,b,e);t(e)})}function y(a,b){a.forEach(function(a){a=a.removedNodes;var d=[];null!==a&&0<a.length&&p(a,b,d);t(d)})}function z(a){var b={attributes:!1,childList:!0,subtree:!0};a.fireOnAttributesModification&&(b.attributes=!0);return b}function A(a){return{childList:!0,subtree:!0}}function k(a){a.arrive=l.bindEvent;e.addMethod(a,"unbindArrive",l.unbindEvent);e.addMethod(a,"unbindArrive", l.unbindEventWithSelectorOrCallback);e.addMethod(a,"unbindArrive",l.unbindEventWithSelectorAndCallback);a.leave=m.bindEvent;e.addMethod(a,"unbindLeave",m.unbindEvent);e.addMethod(a,"unbindLeave",m.unbindEventWithSelectorOrCallback);e.addMethod(a,"unbindLeave",m.unbindEventWithSelectorAndCallback)}if(n.MutationObserver&&"undefined"!==typeof HTMLElement){var w=0,e=function(){var a=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector; return{matchesSelector:function(b,c){return b instanceof HTMLElement&&a.call(b,c)},addMethod:function(a,c,d){var f=a[c];a[c]=function(){if(d.length==arguments.length)return d.apply(this,arguments);if("function"==typeof f)return f.apply(this,arguments)}}}}(),B=function(){var a=function(){this._eventsBucket=[];this._beforeRemoving=this._beforeAdding=null};a.prototype.addEvent=function(a,c,d,f){a={target:a,selector:c,options:d,callback:f,firedElems:[]};this._beforeAdding&&this._beforeAdding(a);this._eventsBucket.push(a); return a};a.prototype.removeEvent=function(a){for(var c=this._eventsBucket.length-1,d;d=this._eventsBucket[c];c--)a(d)&&(this._beforeRemoving&&this._beforeRemoving(d),this._eventsBucket.splice(c,1))};a.prototype.beforeAdding=function(a){this._beforeAdding=a};a.prototype.beforeRemoving=function(a){this._beforeRemoving=a};return a}(),u=function(a,b,c){function d(a){"number"!==typeof a.length&&(a=[a]);return a}var f=new B,e=this;f.beforeAdding(function(b){var d=b.target,h;if(d===n.document||d===n)d= document.getElementsByTagName("html")[0];h=new MutationObserver(function(a){c.call(this,a,b)});var g=a(b.options);h.observe(d,g);b.observer=h;b.me=e});f.beforeRemoving(function(a){a.observer.disconnect()});this.bindEvent=function(a,c,h){if("undefined"===typeof h)h=c,c=b;else{var g={},e;for(e in b)g[e]=b[e];for(e in c)g[e]=c[e];c=g}e=d(this);for(g=0;g<e.length;g++)f.addEvent(e[g],a,c,h)};this.unbindEvent=function(){var a=d(this);f.removeEvent(function(b){for(var c=0;c<a.length;c++)if(b.target===a[c])return!0; return!1})};this.unbindEventWithSelectorOrCallback=function(a){var b=d(this);f.removeEvent("function"===typeof a?function(c){for(var d=0;d<b.length;d++)if(c.target===b[d]&&c.callback===a)return!0;return!1}:function(c){for(var d=0;d<b.length;d++)if(c.target===b[d]&&c.selector===a)return!0;return!1})};this.unbindEventWithSelectorAndCallback=function(a,b){var c=d(this);f.removeEvent(function(d){for(var e=0;e<c.length;e++)if(d.target===c[e]&&d.selector===a&&d.callback===b)return!0;return!1})};return this}, l=new u(z,{fireOnAttributesModification:!1,onceOnly:!1},x),m=new u(A,{},y);q&&k(q.fn);k(HTMLElement.prototype);k(NodeList.prototype);k(HTMLCollection.prototype);k(HTMLDocument.prototype);k(Window.prototype)}})(this,"undefined"===typeof jQuery?null:jQuery,void 0); /* */ var bannedMessages = [ 'LUL' ]; var bannedPhrases = [ '୧༼ಠ益ಠ༽୨' ]; var messages = {}; var allowedEmoticons = {':D':true, ':)':true}; var capsLimit = 0.5; var capsOffset = 5; var r9kcooldown = 120000; // ms var r9klimit = 5; var r9koffset = 0; var repeatedPhrasesOffset = 0; var repeatedPhrasesLimit = 5; var repeatedLettersLimit = 5; $(document).ready(function() { $(document).arrive('.chat-line, .rechat-chat-line', function() { removeEmoticons($(this).find('span.message')); if($(this).find('span.message').html() !== undefined) { var html = $(this).find('span.message').html().trim(); var lowerHtml = html.toLowerCase(); if(!html || bannedPhrase(lowerHtml) || bannedMessage(lowerHtml) || allCaps(html) || repeatedLetters(html) || repeatedPhrases(html) || repeatedMessage(html)) { $(this).remove(); } else { $(this).find('span.message').html(html); } } else { $(this).remove(); } }); }); function bannedPhrase(str) { for(var i = 0; i < bannedPhrases.length; i++) { var phrase = bannedPhrases[i]; if(str.indexOf(phrase) > -1) { return true; } } return false; } function bannedMessage(str) { for(var i = 0; i < bannedMessages.length; i++) { var message = bannedMessages[i]; if(str == message.toLowerCase()) { return true; } } return false; } function repeatedMessage(str) { if(str.length >= r9koffset) { var lowerStr = str.toLowerCase(); if(messages[lowerStr] === undefined) { messages[lowerStr] = 1; } var timeNow = new Date().getTime(); var notRepeated = messages[lowerStr] < r9klimit; var cooledDown = r9kcooldown < timeNow - messages[lowerStr]; if(notRepeated || cooledDown) { if(notRepeated) { messages[lowerStr]++; if(messages[lowerStr] == r9klimit) { messages[lowerStr] = timeNow; } } else { messages[lowerStr] = 1; } } else { return true; } } return false; } function repeatedPhrases(str) { var phrases = str.split(" "); var arr = {}; for(var i = 0; i < phrases.length; i++) { var lowerPhrase = phrases[i].toLowerCase(); if(lowerPhrase.length >= repeatedPhrasesOffset) { if(arr[lowerPhrase] === undefined) { arr[lowerPhrase] = 1; } else if(arr[lowerPhrase] < repeatedPhrasesLimit) { arr[lowerPhrase]++; } else { return true; } } } return false; } function repeatedLetters(str) { var pattern = "(.)"; for(var i = 1; i < repeatedLettersLimit;i++) { pattern += "\\1"; } var patt = new RegExp(pattern); return patt.test(str); } function allCaps(str) { var caps = str.replace(/[^A-Z]/g, "").length; var percentage = caps / str.length; return str.length >= capsOffset && percentage >= capsLimit; } function removeEmoticons($message) { var $emoticons = $message.find('img'); $.each($emoticons, function() { var alt = decodeURIComponent($(this).attr('alt')); var dr = decodeURIComponent($(this).attr('data-regex')); if(allowedEmoticons[alt] !== true && allowedEmoticons[dr] !== true) { $(this).remove(); } }); }