TheFallenOne / Rrrather script

// ==UserScript==
// @name         Rrrather script
// @namespace    http://tampermonkey.net/
// @version      0.1.4
// @description  Rrrather blacklist + notifications in page title
// @author       The Fallen (aka ActualFrisk)
// @match        https://www.rrrather.com/*
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-start
// @licence      MIT
// @require      http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// ==/UserScript==


function saveSettings(settings) {
    GM_setValue('blacklist', settings.blacklist.join('|'));
    GM_setValue('BL_usernames', settings.BL_usernames.join('|'));
    GM_setValue('silentMode', settings.silentMode);
    GM_setValue('notif', settings.notif);
}

function loadSettings() {
    var settings = {};
    settings.blacklist = GM_getValue('blacklist', '');
	if (settings.blacklist) {
		settings.blacklist = settings.blacklist.split('|').map(function(n) { return parseInt(n); });
	} else {
		settings.blacklist = [];
	}
    settings.BL_usernames = GM_getValue('BL_usernames', '');
	if (settings.BL_usernames) {
		settings.BL_usernames = settings.BL_usernames.split('|');
	} else {
		settings.BL_usernames = [];
	}
    settings.silentMode = GM_getValue('silentMode', false);
    settings.notif = GM_getValue('notif', true);
    return settings;
}

function recursiveDelete($comment) {
    var indent = $comment.data('indent');
    var $siblings = $comment.siblings();
    var index = $comment.index();
    $comment.remove();

    for (var i = index; i<$siblings.length; i++) {
        var $comment1 = $siblings.eq(i);
        if ($comment1.data('indent')<=indent) break;
        $comment1.remove();
    }
}

function softBlacklist($content, username, type) {
    $content.wrap('<div></div>');
    $content.hide();

    var $link = $('<a href="#">You have blacklisted ' + username + '. Click to show ' + type + '</a>');
    $link.click(function() {
        $(this).hide();
        $content.show();
        return false;
    });
    $content.after($link);
}

function userpageActions() {
    var pageName = $('#main h1').text();
    var pos = pageName.indexOf('\'s profile page');
    var username = pageName.substr(1,pos-1);
    var userid = parseInt($('#main .span4 h4').text().match(/#([^\)]*)\)/)[1].replace(',',''));

    var BL_index = settings.blacklist.indexOf(userid);
    var $blacklistLink = $('<a href="#"></a>');
    if (BL_index != -1) {
        $blacklistLink.text('Remove from blacklist');
    } else {
        $blacklistLink.text('Add to blacklist');
    }
    $blacklistLink.click(function() {
        settings = loadSettings();
        BL_index = settings.blacklist.indexOf(userid);
        if (BL_index == -1) {
            settings.blacklist.push(userid);
            settings.BL_usernames.push(username);
            saveSettings(settings);
            $blacklistLink.text('Remove from blacklist');
            BL_index = settings.blacklist.length-1;
        } else {
            settings.blacklist.splice(BL_index, 1);
            settings.BL_usernames.splice(BL_index, 1);
            saveSettings(settings);
            $blacklistLink.text('Add to blacklist');
            BL_index = -1;
        }
        return false;
    });
    $('#main .span4').eq(0).append($blacklistLink.appendTo($('<p></p>')));
    if (settings.silentMode && BL_index != -1) {
        $('#main .row').eq(2).remove();
    }
}

function selfpageActions() {
    var $settingsButton = $('<div class="span5"> <button data-width="120" data-height="120" class="btn selectimage" style="margin-top:10px" id="script-settings-button">Script settings</button> </div>');
    $('#main .span4 .row').append($settingsButton);
    var $settingsModal = $(
'<div id="script-settings-modal" class="modal hide" data-width="300" data-height="240" aria-hidden="false" style="display: none;"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h3>Script settings</h3> </div> <div class="modal-body"> <div class="span3"> <label><b>Blacklist</b></label> <select id="script-blacklist" select size="6"> </select><br> <button class="btn" type="button" id="script-bl-remove">Remove from blacklist</button> </div> <div class="span3"> <br> <label><b>Other settings</b></label> <label><input type="checkbox" id="script-silent-bl" name="script-silent-bl" style="margin: 0"> Silent blacklist</label> <label><input type="checkbox" id="script-notif" name="script-notif" style="margin: 0"> Notifications in page title</label> </div> <br> </div>'
    );
    $settingsModal.insertAfter('#image-modal');

    $('#script-settings-button').click(function(e) {
        e.preventDefault();

        var $backdrop = $('<div class="modal-backdrop in"></div>');
        $backdrop.appendTo('body');
        $settingsModal.show();
        function closeModal() {
            $('#script-settings-modal').hide();
            $backdrop.remove();
        }
        $settingsModal.find('button.close').click(closeModal);
        $backdrop.click(closeModal);

        function updateBlacklist() {
            $('#script-blacklist').empty();
            for (var i = 0; i<settings.blacklist.length; i++) {
                var $option = $('<option value="' + settings.blacklist[i] + '">' + settings.BL_usernames[i] + '</option>');
                $option.appendTo('#script-blacklist');
            }
        }
        settings = loadSettings();
        updateBlacklist();
        $('#script-bl-remove').click(function() {
            settings = loadSettings();
            var userid = parseInt($('#script-blacklist').val());
            var BL_index = settings.blacklist.indexOf(userid);
            settings.blacklist.splice(BL_index, 1);
            settings.BL_usernames.splice(BL_index, 1);
            saveSettings(settings);
            updateBlacklist();
        });

        $('#script-silent-bl').prop('checked', settings.silentMode);
        $('#script-silent-bl').click(function() {
            settings = loadSettings();
            settings.silentMode = $(this).prop('checked');
            saveSettings(settings);
        });

        $('#script-notif').prop('checked', settings.notif);
        $('#script-notif').click(function() {
            settings = loadSettings();
            settings.notif = $(this).prop('checked');
            saveSettings(settings);
        });

        return false;
    });
}

var newestNofifs = 0, prevNotifs = 0, chatUpdated = false, originalTitle, allowUpdateTitle = false;

function updateTitle() {
    if (settings.notif && allowUpdateTitle) {
        document.title = (newestNofifs>0 ? '('+newestNofifs+')' : '') + (chatUpdated ? '*' : '') + originalTitle;
    }
}

var settings = loadSettings();
saveSettings(settings);
if (settings.silentMode) {
    GM_addStyle('.comments>li {display:none} .well .table tbody tr {display:none} .cols {display:none}'); // this is the protection from seeing any blacklisted comments when page is still loading. It is only enabled in silent mode, which gives increased security
}

document.addEventListener('DOMContentLoaded', (function() {
    originalTitle = document.title;
    $('.comments').children().each(function() {
        var id = $(this).data('author');
        var BL_index = settings.blacklist.indexOf(id);
        if (BL_index!=-1) {
            var username = $(this).find('.user a').text();
            if (username!=settings.BL_usernames[BL_index]) { // the case when username is changed
                settings.BL_usernames[BL_index] = username;
                saveSettings(settings);
            }
            if (settings.silentMode) {
                recursiveDelete($(this));
            } else {
                softBlacklist($(this).children('.inner-comment'), username, 'comment');
            }
        }
    });
    $('.rrrather').each(function() {
        var id = $(this).data('author');
        var BL_index = settings.blacklist.indexOf(id);
        if (BL_index!=-1) {
            if (settings.silentMode) {
                $(this).parent().remove();
            } else {
                softBlacklist($(this), settings.BL_usernames[BL_index], 'question');
            }
        }
    });
    var DOM_eventLock = false;
    $('#notification-count').on('DOMSubtreeModified', function() {
        if (DOM_eventLock) return;
        DOM_eventLock = true;

        var newNotifs = parseInt($('#notification-count').text());
        var deletedNotifs = 0;
        var $notifs = $('#notifications-dropdown .comment, #notifications-dropdown .mail');
        $notifs.each(function(index) {
            var username = $(this).find('strong').text().split(' ')[0];
            if (settings.BL_usernames.indexOf(username)!=-1) {
                $(this).next().remove();
                $(this).remove();
                if (index<newNotifs) {
                    deletedNotifs++;
                }
            }
        });
        if (deletedNotifs>0) {
            $('#notification-count').text(newNotifs-deletedNotifs);
            if (newNotifs==deletedNotifs) {
                $('#notification-count').removeClass('new-notif');
                $.ajax({
                    url: baseurl + "notifications/clear"
                });
            }
        }
        if (!document.hidden) {
            prevNotifs = newNotifs-deletedNotifs;
        } else {
            newestNofifs = newNotifs-deletedNotifs-prevNotifs;
            updateTitle();
        }

        DOM_eventLock = false;
    });
    $('.well .table tbody tr').each(function() {
        var username = $(this).children().eq(1).children().text();
        if (settings.BL_usernames.indexOf(username)!=-1) {
            $(this).remove();
        }
    });
    $('#chat').on('DOMSubtreeModified', function() {
        if (DOM_eventLock) return;
        DOM_eventLock = true;

        $(this).children().each(function() {
            var id = $(this).data('author');
            var BL_index = settings.blacklist.indexOf(id);
            if (BL_index!=-1) {
                if (settings.silentMode) {
                    $(this).remove();
                } else {
                    softBlacklist($(this), settings.BL_usernames[BL_index], 'message');
                }
            }
        });

        if (document.hidden) {
            chatUpdated = true;
            updateTitle();
        }

        DOM_eventLock = false;
    });
    $('#userlist').on('DOMSubtreeModified', function() {
        if (!settings.silentMode) return;
        if (DOM_eventLock) return;
        DOM_eventLock = true;

        $(this).children().each(function() {
            var id = $(this).data('id');
            if (settings.blacklist.indexOf(id)!=-1) {
                $(this).remove();
            }
        });

        DOM_eventLock = false;
    });
    var pageName = $('#main h1').text();
    if (pageName == ' Welcome to your profile page! ') {
        selfpageActions();
    } else if ((pos = pageName.indexOf('\'s profile page')) != -1) {
        userpageActions();
    }

    document.addEventListener('visibilitychange', function(){
        if (!document.hidden) {
            prevNotifs = newestNofifs;
            chatUpdated = false;
            newestNofifs = 0;
            updateTitle();
        }
    });
    setTimeout(function() { allowUpdateTitle = true; }, 4242);

    if (settings.silentMode) {
        GM_addStyle('.comments>li {display:block;} .well .table tbody tr {display:table-row;} .cols {display:block}');
    }
}), false);