pta2002 / Robin Enhancement Suite

// ==UserScript==
// @name        Robin Enhancement Suite
// @namespace   com.pta2002.robines
// @description Enhances robin
// @include     https://www.reddit.com/robin
// @include     http://www.reddit.com/robin
// @include     https://reddit.com/robin
// @include     http://reddit.com/robin
// @include     https://www.reddit.com/robin/
// @include     http://www.reddit.com/robin/
// @include     https://reddit.com/robin/
// @include     http://reddit.com/robin/
// @version     1.4.4
// @grant       none
// ==/UserScript==

var l = document.createElement('script');
l.src = "https://cdnjs.cloudflare.com/ajax/libs/jQuery-linkify/1.1.7/jquery.linkify.min.js";
document.getElementsByTagName('body')[0].appendChild(l);

// CSS setup
$('head').append('<style>\
    .robin--user-class--self {\
                 background: #eee;\
                 }\
     .robin--user-class.self .robin--username {font-weight: bold !important;}\
     .robin--user-class--self.robin--flair-class--flair-0 .robin--username {\
                 color: #e50000 !important;}\
.robin--user-class--self.robin--flair-class--flair-1 .robin--username {\
                 color: #db8e00 !important;}\
.robin--user-class--self.robin--flair-class--flair-2 .robin--username {\
                 color: #ccc100 !important;}\
.robin--user-class--self.robin--flair-class--flair-3 .robin--username {\
                 color: #02be01 !important;}\
.robin--user-class--self.robin--flair-class--flair-4 .robin--username {\
                 color: #0083c7 !important;}\
.robin--user-class--self.robin--flair-class--flair-5 .robin--username {\
                 color: #820080 !important;}\
');

function sendMessage(message){
    $("#robinSendMessage > input[type='text']").val(message);
    $("#robinSendMessage > input[type='submit']").click();
}

username = $('.user a:first').text();

$('#robinVoteWidget').prepend($('<div id="RESUserCount" class="robin-chat--vote" style="width: 100%;">').text("Current participants: "));

settingsPage = $('<div class="robin-chat--sidebar" style="display:none;" id="RESSettings">');
settingsWidget = $('<div class="robin-chat--sidebar-widget robin-chat--vote-widget" id="RESSettingsWidget">');

settingsPage.append(settingsWidget);

openSettingsButton = $('<div id="RESOpenSettings" class="robin-chat--vote" style="cursor: pointer">').text('Open settings');
closeSettingsButton = $('<div id="RESCloseSettings" class="robin-chat--vote" style="cursor: pointer">').text('Close settings');

function openSettings() {
    $('.robin-chat--sidebar').hide();
    $('#RESSettings').show();
}

function closeSettings() {
    $('.robin-chat--sidebar').show();
    $('#RESSettings').hide();
}

openSettingsButton.on('click', openSettings);
closeSettingsButton.on('click', closeSettings);

settingsWidget.append(closeSettingsButton);

curTime = $('<div class="robin-chat--vote" id="RESTimeLeft" style="width: 100%;">')
$('#robinVoteWidget').prepend(curTime);

// SETTINGS SETUP
function saveSetting(setting) {
    localStorage["res-settings"] = JSON.stringify(setting);
}

function loadSetting() {
    var setting = localStorage["res-settings"];
    if (setting) {
        setting = JSON.parse(setting);
    } else {
        setting = {};
    }
    return setting;
}

var settings = loadSetting();

function addBoolSetting(name, description, defaultSetting) {

    defaultSetting = settings[name] || defaultSetting;

    settingsWidget.append('<div class="robin-chat--sidebar-widget robin-chat--notification-widget"><label><input type="checkbox" name="setting-' + name + '">' + description + '</label></div>');
    $("input[name='setting-" + name + "']").on("click", function() {
        settings[name] = !settings[name];
        saveSetting(settings);
    });
    if (settings[name] !== undefined) {
        $("input[name='setting-" + name + "']").prop("checked", settings[name]);
    } else {
        settings[name] = defaultSetting;
    }
}

function addButtonSetting(description, action) {
    button = $('<div class="robin-chat--sidebar-widget robin-chat--vote-widget">');
    button.append($('<div class="robin-chat--vote" style="width: 100%; cursor: pointer;">').text(description));
    button.on("click", action);
    settingsWidget.append(button);
}

$('.robin-chat--sidebar').before(settingsPage);
$('#robinVoteWidget').append(openSettingsButton);

addBoolSetting("spamFilter", "Enable spam filter", true);
addBoolSetting("autoGrow", "Auto click grow", false);

setInterval(function(){
    $('.robin-message--message').linkify();
    $('.robin-message--message:contains(' + username + ')').parent().css({'background': '#9DF595', 'font-weight': 'bold'})
    var users = 0;
    $.get("/robin/", function(a) {
        var start = "{" + a.substring(a.indexOf("\"robin_user_list\": ["));
        var end = start.substring(0, start.indexOf("}]") + 2) + "}";
        list = JSON.parse(end).robin_user_list;
        var increaseCount = list.filter(function(voter) {
            return voter.vote === "INCREASE";
        }).length;
        var abandonCount = list.filter(function(voter) {
            return voter.vote === "ABANDON";
        }).length;
        var novoteCount = list.filter(function(voter) {
            return voter.vote === "NOVOTE";
        }).length;
        var continueCount = list.filter(function(voter) {
            return voter.vote === "CONTINUE";
        }).length;
        $('#robinVoteWidget .robin--vote-class--increase .robin-chat--vote-label').html('grow<br>(' + increaseCount + ')');
        $('#robinVoteWidget .robin--vote-class--abandon .robin-chat--vote-label').html('abandon<br>(' + abandonCount + ')');
        $('#robinVoteWidget .robin--vote-class--continue .robin-chat--vote-label').html('stay<br>(' + continueCount + ')');
        users = list.length;
        $("#RESUserCount").text("Current participants: " + users);
    });
    
    var lastChatString = $(".robin-message--timestamp").last().attr("datetime");
    var timeSinceLastChat = new Date() - (new Date(lastChatString));
    var now = new Date();
    if (timeSinceLastChat !== undefined && (timeSinceLastChat > 60000 && now - timeStarted > 60000)) {
        window.location.reload(); // reload if we haven't seen any activity in a minute.
    }
    
    timeLeftU = r.config.robin_room_reap_time-(new Date).getTime();
    if (timeLeftU > 0) {
       timeLeft = new Date(timeLeftU);
       curTime.text("Time left: " + timeLeft.getMinutes() + ':'  + timeLeft.getSeconds());
    }else {
        curTime.text("Ending soon");
    }
    
    // SPAM FILTER - FROM ROBIN-GROW
    if (loadSettings().spamFilter) {
        function hashString(str) {
            var hash = 0;

            if (str != 0) {
                for (i = 0; i < str.length; i++) {
                    char = str.charCodeAt(i);
                    if (str.charCodeAt(i) > 0x40) { // Let's try to not include the number in the hash in order to filter bots
                        hash = ((hash << 5) - hash) + char;
                        hash = hash & hash; // Convert to 32bit integer
                    }
                }
            }

            return hash;
        }

        // Searches through all messages to find and hide spam
        var spamCounts = {};

        function findAndHideSpam() {
            var $messages = $(".robin-message");

            var maxprune = parseInt("1000", 10);
            if (maxprune < 10 || isNaN(maxprune)) {
                maxprune = 1000;
            }

            if ($messages.length > maxprune) {
                $messages.slice(0, $messages.length - maxprune).remove();
            }

            if (loadSettings().spamFilter) {
                // skips over ones that have been hidden during this run of the loop
                $('.robin--user-class--user .robin-message--message:not(.addon--hide)').each(function() {
                    var $this = $(this);

                    var hash = hashString($this.text());
                    var user = $('.robin-message--from', $this.closest('.robin-message')).text();

                    if (!(user in spamCounts)) {
                        spamCounts[user] = {};
                    }

                    if (hash in spamCounts[user]) {
                        spamCounts[user][hash].count++;
                        spamCounts[user][hash].elements.push(this);
                    } else {
                        spamCounts[user][hash] = {
                            count: 1,
                            text: $this.text(),
                            elements: [this]
                        };
                    }
                    $this = null;
                });

                $.each(spamCounts, function(user, messages) {
                    $.each(messages, function(hash, message) {
                        if (message.count >= 3) {
                            $.each(message.elements, function(index, element) {
                                //console.log("SPAM REMOVE: "+$(element).closest('.robin-message').text())
                                $(element).closest('.robin-message').addClass('addon--hide').remove();
                            });
                        } else {
                            message.count = 0;
                        }

                        message.elements = [];
                    });
                });
            }
        }
    }
}, 100);

setTimeout(function() {
    if (loadSetting().autoGrow) {
        $(".robin-chat--vote.robin--vote-class--increase:not('.robin--active')").click();
    }
}, 3000);

var muted=[];

addButtonSetting("Clear muted list", function() {muted=[];});

setInterval(function(){
  $('.robin-message--from.robin--username').css('cursor', 'pointer').attr('alt', 'Click to block this user');
  $('.robin-message--from.robin--username').click(function(){
      if ($(this).text() != username) muted.push($(this).text());});
  $.each(muted,function(i,v){$('.robin--username:contains('+v+')').parent().remove();});}
,100);

$("#robinDesktopNotifier").detach().appendTo("#RESSettingsWidget");
$('.robin-chat--report').detach().appendTo(settingsWidget);