Reddit Robin Filter

Filters comments. Works on usernames and messages.

Устаревшая версия за 05.04.2016. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         Reddit Robin Filter
// @namespace    http://kmcgurty.com
// @version      2.3
// @description  Filters comments. Works on usernames and messages.
// @author       Kmc - [email protected]
// @match        https://www.reddit.com/robin
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @grant        GM_addStyle
// ==/UserScript==

//GM_deleteValue("filter_list");

//will click the grow button and type /count every 15 seconds (to prevent abandoning)
setInterval(function() {
    if($(".text-counter-input")[0].value == ""){
        $(".robin-chat--vote-increase").click();
        $(".text-counter-input")[0].value = "/count";
        $("input[type=submit]").click();
    }
}, 15000);

//setup the default filter
var defaultFilter = ["voted to grow", "voted to stay", "voted to abandon"];
if (GM_getValue("filter_list") === undefined || typeof GM_getValue("filter_list") !== "object") GM_setValue("filter_list", defaultFilter);

//filtery things
function doFilter(div) {
    var filter = GM_getValue("filter_list");

    for (var i = 0; i < filter.length; i++) {
        var messageDiv = $(div).find(".robin-message--message");
        var usernameDiv = messageDiv.parent().find(".robin--username");

        //messageDiv[0] is occasionally undefined?
        if (messageDiv[0] != undefined) {
            var message = messageDiv[0].innerHTML.toLowerCase();
            
            var currentFilter = filter[i].toLowerCase();
            var matches = message.includes(currentFilter);

            var isAscii = $("#remove-ascii")[0].checked && isAsciiArt(message);

            var silentDelete = $("#silent-delete")[0].checked;

            if (matches || isAscii) {
                deleteMessage(messageDiv, silentDelete);
            }
        }

        if(usernameDiv[0] != undefined){
            var username = usernameDiv[0].innerHTML.toLowerCase();
            var matches = username.includes(currentFilter);

            var silentDelete = $("#silent-delete")[0].checked;

            if (matches) {
                deleteMessage(messageDiv, silentDelete);
            }
        }
    }
}

function parseURLs(messageDiv){
    var messageDiv = $(messageDiv).find(".robin-message--message")[0];

    var text = messageDiv.innerHTML;
    var parsedText = text.replace(/(\r\n|\r|\n)/g, '<br/>').replace(/((?:(http|https|Http|Https|rtsp|Rtsp):\/\/(?:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,64}(?:\:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,25})?\@)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}\.)+(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\:\d{1,5})?)(\/(?:(?:[a-zA-Z0-9\;\/\?\:\@\&\=\#\~\-\.\+\!\*\'\(\)\,\_])|(?:\%[a-fA-F0-9]{2}))*)?(?:\b|$)/gi, "<a class='link' href='http://$3$4' target='_blank'>$3$4</a>");

    messageDiv.innerHTML = parsedText;
}

function deleteMessage(messageDiv, silent){
    if(silent){
        messageDiv.parent().remove();
    } else {
        messageDiv.replaceWith(`
            <span class='deleted'>
                <a href="#" data-deleted="` + messageDiv[0].innerHTML + `">&#x3c;deleted&#x3e;</a>
            </span>
        `);
    }
}


function removeMaxMessages(){
    var maxMessages = parseInt($("#max-messages")[0].value);
    var numberOfMessages = $("#robinChatMessageList").children().length;

    if(numberOfMessages > maxMessages){
        var messages = $("#robinChatMessageList").children();
        
        for(var i = numberOfMessages; i > maxMessages; i--){
            if(messages[0] != undefined){
                messages[0].remove();
            }
        }
    }
}


//checks for a new message, and then calls doFilter();
createObserver();
function createObserver() {
    var target = $('#robinChatMessageList')[0];

    var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            var messageDiv = mutation.addedNodes[0];
            
            if(messageDiv != undefined){
                doFilter(messageDiv);
                parseURLs(messageDiv);
            }

            removeMaxMessages();
        });
    });

    // configuration of the observer:
    var config = { childList: true };

    // pass in the target node, as well as the observer options
    observer.observe(target, config);
}

//ty to fam
//http://stackoverflow.com/questions/8746882/jquery-contains-selector-uppercase-and-lower-case-issue
//makes :contains case-insensitive
jQuery.expr[':'].Contains = function(a, i, m) { return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0; };

//also thanks to this guy
//http://stackoverflow.com/questions/147824/how-to-find-whether-a-particular-string-has-unicode-characters-esp-double-byte
function isAsciiArt(s) { // "art"
    return /[^\u0000-\u00ff]/.test(s);
}

createEventListeners();
function createEventListeners(){
    $(document.body).on("click", ".filter-img#filter-remove", function(event){
        var filterList = GM_getValue("filter_list");
        var word = event.currentTarget.getAttribute("data-word");
        var index = filterList.indexOf(word);

        filterList.splice(index, 1);
        
        GM_setValue("filter_list", filterList);

        event.currentTarget.parentElement.outerHTML = "";
    });

    $(document.body).on("click", ".filter-img#filter-create", function(){
        var newWord = window.prompt("Enter a new filter to add");
        if(newWord != null){
            appendWordToList(newWord);

            var newFilterList = GM_getValue("filter_list");
            newFilterList.push(newWord);
            GM_setValue("filter_list", newFilterList);
        }
    });
    
    $(document.body).on("click", ".deleted a", function(event){
        event.preventDefault();
        var element = event.toElement;

        element.outerHTML = $(element).attr("data-deleted");
    });
}

//everything below is html/css stuff

createHTML();
function createHTML(){
    var html = `
    <div>
        <div>Create word or username filters below by clicking the green +. Message /u/kmcgurty1 for help.</div>
        <input id="remove-ascii" type="checkbox" checked>&nbsp;Remove ascii art<br>
        <input id="silent-delete" type="checkbox" checked>&nbsp;Silently delete<br>
        <input id="max-messages" type="number" value="150" style="width: 3em">&nbsp;Max messages to keep
        <div class="filter-list">
            <div class="item-wrapper">
                <div class="filter-img" id="filter-create"></div>
            </div>
        </div>
    </div>
    `;

    $("div[role=main]").after(html);

    var filterList = GM_getValue("filter_list");

    for (var i = 0; i < filterList.length; i++) {
        appendWordToList(filterList[i]);
    }

    createButton = ``;
}

function appendWordToList(word){
    var html = `
        <div class="item-wrapper">
            <div class="filter-word">` + word + `</div>
            <div class="filter-img" id="filter-remove" data-word="` + word + `" ></div>
        </div>
    `;

    $(html).insertBefore(".item-wrapper:last");
}

var css = `
.deleted a{
    color: rgba(0,0,0, .4);
}

div input{
    display: inline-block;    
    vertical-align: bottom; 
}

.filter-word{
    color: black;
    height: 25px;
    padding-right: 10px;
}

.filter-img{
    cursor:  pointer;
    width: 15px;
    height: 15px;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    
}

.filter-img#filter-create{
    height: 25px;
    width: 25px;
    background-image: url(https://i.imgur.com/nw1I62o.png);
}

.filter-img#filter-remove{
    background-image: url(https://i.imgur.com/3bYSOxq.png);
}

.item-wrapper{
    display: inline-block;
    background-color: rgb(235, 235, 235);
    border: 4px solid rgba(20, 20, 20, .7);
    border-radius: 5px;
    padding: 2px;
    margin: 4px;
}

.item-wrapper div{
    vertical-align: middle;
    display: table-cell;
}

.filter-list{
    font: normal small verdana,arial,helvetica,sans-serif;
    line-height: 1em;
    margin: 5px;
}

input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
    /* display: none; <- Crashes Chrome on hover */
    -webkit-appearance: none;
    margin: 0; /* <-- Apparently some margin are still there even though it's hidden */
}

a.link{
    color: blue;
}

a.link:link {
    color: #0000EE;
}

a:hover{
    text-decoration: underline;
}
`;

GM_addStyle(css);