FA Content Filter

Filters user-defined content while browsing FA.

目前為 2015-12-18 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        FA Content Filter
// @namespace   fa-filter
// @description Filters user-defined content while browsing FA.
// @include     *://www.furaffinity.net/*
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js
// @version     1.4.0
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_deleteValue
// @grant       GM_openInTab
// ==/UserScript==

// === WARNING ===
// THE TAG FUNCTIONS ARE COMMENTED OUT IN ORDER TO PREVENT ACCIDENTAL DDoS DETECTION ON FURAFFINITY.
this.$ = this.jQuery = jQuery.noConflict(true);

// === INITIALIZE USER ARRAY ===
var userArray = JSON.parse(GM_getValue('userList', '{}'));
//var tagArray = JSON.parse(GM_getvalue('tagList', '{}'));

// === FILTER ===
var parseSettings = function() {
    if (!(userArray instanceof Array)) {
        $.each(userArray, function(username, data) {
            if (data['subs'] === 1) { hideSubmissions(username); }
            if (data['shouts'] === 1) { hideShouts(username); }
            if (data['coms'] === 1) { hideComments(username); }
            if (data['notifications'] === 1) { hideNotifications(username); }
        });
    }
}

//var parseTagSettings = function() {
//    $('.t-image a[href^="/view"]').each(function() {
//        var url = $(this).attr('href');
//        console.log(url);
//        $.post(url, function(data) {
//            console.log($('#keywords', data).text());
//        });
//    });
//}


// === SAVE ===
function writeSettings() {
    GM_setValue('userList', JSON.stringify(userArray));
}

// === FUNCTIONS ===
    // Hide user submissions
    function hideSubmissions(username) {
        // Browse/Submissions
        var submission1 = $('b[id^="sid_"] a[href="/user/' + username + '/"]').closest('b');
        stylizeHidden(submission1);
        // Mark Submissions as Checked
        submission1.children('small').children('input').prop('checked', true);
        submission1.addClass('hidden-sub').hide();
        
        // Favorites/Front Page
        var submission2 = $('b[id^="sid_"] img[src$="#' + username + '"]').closest('b');
        stylizeHidden(submission2);
        submission2.addClass('hidden-sub').hide();
    }

    // Hide user shouts
    function hideShouts(username) {
        // Classic
        var shout = $('table[id^="shout-"] td.alt1 img[alt="' + username + '"]').closest('table[id^="shout-"]');
        shout.addClass('hidden-shout').hide();
        stylizeHidden(shout.find('table'));
        shout.next('br').addClass('hidden-shout-br').hide();
        
        // Beta
        var shoutBeta = $('table[id^="shout-"] .comments-flex-item-icon img[alt="' + username +'"]').closest('table[id^="shout-"]');
        shoutBeta.addClass('hidden-shout').hide();
        stylizeHidden(shoutBeta.find('.comments-flex-item-main'));
    }

    // Hide user comments and threads
    function hideComments(username) {
        // Classic
        var comments = $('.container-comment td.icon img[alt="' + username + '"]').closest('.container-comment');
        
        $(comments).each(function() {
            // Hide comment and get width
            if (!($(this).hasClass('hidden-comment'))) {
                var width = Number($(this).addClass('hidden-comment').hide().attr('width').slice(0,-1));
                var current = $(this).next('.container-comment');

                // Iterate through comments until there's a width that is greater than or equal
                while (true) {
                    if (current.length) {
                        if (Number(current.attr('width').slice(0,-1)) < width) {
                            current.addClass('hidden-comment').hide();
                            current = current.next('.container-comment');
                        } else {
                            break;
                        }
                    } else {
                       break;
                    }
                }
            }
        });
        
        // Beta
        var commentsBeta = $('.container-comment .comments-flex-item-icon img[alt="' + username + '"]').closest('.container-comment');
        stylizeHidden(commentsBeta.find('.comments-flex-item-main'));
        
        $(commentsBeta).each(function() {
            // Hide comment and get width
            if (!($(this).hasClass('hidden-comment'))) {
                var width = Number($(this).addClass('hidden-comment').hide().attr('width').slice(0,-1));
                var current = $(this).next('.container-comment');
                
                // Iterate through the comments until there's a width that is greater than or equal
                while (true) {
                    if (current.length) {
                        if (Number(current.attr('width').slice(0,-1)) < width) {
                            current.addClass('hidden-comment').hide();
                            current = current.next('.container-comment');
                        } else {
                            break;
                        }
                    } else {
                        break;
                    }
                }
            }
        });
    }
    
    // Hide user notifications
    function hideNotifications(username) {
        var notification = $('.message-stream a[href="/user/' + username + '/"]').closest('li');
        notification.addClass('hidden-notification').hide();
        stylizeHidden(notification);
        notification.children('input').prop('checked', true);
        
        // Classic only
        notification.children('table').children('tbody').children('tr').children('td').children('.checkbox').children('input').prop('checked', true);
    }
    
    function stylizeHidden(item) {
        item.css('background-color', '#FFBBBB');
        item.css('color', '#FF0000');
        $('a:link', item).css('color', '#FF0000');
        $('a:visited', item).css('color', '#FF0000');
    }

// === UI ===
// == Filter Toggle ==
// Submissions
function filtersSubs() {
    if ($('.hidden-sub').length > 0) {
        $display = '<input style="float:right;" id="faf-toggle-subs" class="button" type="button" value="Toggle Filtered Submissions (' + $('.hidden-sub').length + ')"></input>';
        $('form').first().append($display);
    }
}

// Followed Submissions
function filtersSubsFollow() {
    if ($('.hidden-sub').length > 0) {
        $display = '<input id="faf-toggle-subs" class="button" type="button" value="Toggle Filtered Submissions (' + $('.hidden-sub').length + ')"></input>';
        $('.actions').append($display);
    }
}

// Shouts
function filtersShouts() {
    if ($('.hidden-shout').length > 0) {
        $display = '<center><input id="faf-toggle-shouts" class="button" type="button" value="Toggle Filtered Shouts (' + $('.hidden-shout').length + ')"></input></center>';
        // Classic
        $('table[id^="shout-"]').first().prevAll('table.maintable:first').append($display);
        // Beta
        $('.shoutboxcontainer').append($display);
    }
}

// Shouts (Controls, Beta Only)
function filtersShoutsControl() {
    if ($('.hidden-shout').length > 0) {
        $display = '<br><br><input id="faf-toggle-shouts" class="button" type="button" value = "Toggle Filtered Shouts (' + $('.hidden-shout').length + ')"></input>';
        $('div[id="controlpanel"] .alignright').append($display);
        $('.hidden-shout input').prop('checked', true);
    }
}

// Comments
function filtersComments() {
    if ($('.hidden-comment').length > 0) {
        $display = '<input style="float:right;" id="faf-toggle-comments" class="button" type="button" value="Toggle Filtered Comments (' + $('.hidden-comment').length + ')"></input>';
        // Classic
        $('table.container-comment').first().parent().parent().prev().children().append($display);
        // Beta
        $($display).insertAfter('.tags-row');
    }
}

// Notifications
function filtersNotifications() {
    if ($('.hidden-notification').length > 0) {
        $display = '<input id="faf-toggle-notifications" class="button" type="button" value="Toggle Filtered Notifications (' + $('.hidden-notification').length + ')"></input>';
        $('.global-controls').append($display);
        
        // = Notification Count =
        // Classic
        if ($('fieldset[id^="messages-watches"] .hidden-notification').length > 0)
            $('fieldset[id^="messages-watches"] h3').append(' (' + $('fieldset[id^="messages-watches"] .hidden-notification').length + ' filtered)');
        if ($('fieldset[id^="messages-comments-submission"] .hidden-notification').length > 0)
            $('fieldset[id^="messages-comments-submission"] h3').append(' (' + $('fieldset[id^="messages-comments-submission"] .hidden-notification').length + ' filtered)');
        if ($('fieldset[id^="messages-shouts"] .hidden-notification').length > 0)
            $('fieldset[id^="messages-shouts"] h3').append(' (' + $('fieldset[id^="messages-shouts"] .hidden-notification').length + ' filtered)');
        if ($('fieldset[id^="messages-favorites"] .hidden-notification').length > 0)
            $('fieldset[id^="messages-favorites"] h3').append(' (' + $('fieldset[id^="messages-favorites"] .hidden-notification').length + ' filtered)');
        
        // Beta
        if ($('div[id^="messages-watches"] .hidden-notification').length > 0)
            $('div[id^="messages-watches"]').prev().find('h3').append(' (' + $('div[id^="messages-watches"] .hidden-notification').length + ' filtered)');
        if ($('div[id^="messages-comments-submission"] .hidden-notification').length > 0)
            $('div[id^="messages-comments-submission"]').prev().find('h3').append(' (' + $('div[id^="messages-comments-submission"] .hidden-notification').length + ' filtered)');
        if ($('div[id^="messages-shouts"] .hidden-notification').length > 0)
            $('div[id^="messages-shouts"]').prev().find('h3').append(' (' + $('div[id^="messages-shouts"] .hidden-notification').length + ' filtered)');
        if ($('div[id^="messages-favorites"] .hidden-notification').length > 0)
            $('div[id^="messages-favorites"]').prev().find('h3').append(' (' + $('div[id^="messages-favorites"] .hidden-notification').length + ' filtered)');
        if ($('div[id^="messages-journals"] .hidden-notification').length > 0)
            $('div[id^="messages-journals"]').prev().find('h3').append(' (' + $('div[id^="messages-journals"] .hidden-notification').length + ' filtered)');
    }
}

// Show/Hide Submissions
$(document.body).on('click', '#faf-toggle-subs', function() {
    $('.hidden-sub').toggle();
});

// Show/Hide Shouts
$(document.body).on('click', '#faf-toggle-shouts', function() {
    $('.hidden-shout').toggle();
    $('.hidden-shout-br').toggle();
});

// Show/Hide Comments
$(document.body).on('click', '#faf-toggle-comments', function() {
    $('.hidden-comment').toggle();
})

// Show/Hide Notifications
$(document.body).on('click', '#faf-toggle-notifications', function() {
    $('.hidden-notification').toggle();
})

// == User Settings ==
function displaySettings() {
    // Navbar link
    $('<li class="noblock"><a target="_blank" href="/controls/site-settings#fa-filter">FA Filter</a></li>').insertAfter($('li.sfw-toggle'));
    
    if (window.location.pathname.lastIndexOf('/controls/site-settings', 0) === 0) {
        // Brute forced, but there are no tables in the beta layout site-settings page. This is one of the major differences.
        if (!$('table').length) {
            // Beta HTML Code
            var settingsDisplay = '<div class="container-item-top" style="margin-top: 10px">' +
                '<h3 id="fa-filter">FA Filter</h3>' +
                'Hide the things that you dislike!' +
            '</div>' +
            '<div class="container-item-bot">' +
                '<div class="lineitem">' +
                    '<div class="row">' +
                        '<div class="cell mobiletoggle">' +
                            '<strong>Add a User</strong><br/>' +
                            '<p>Tired of seeing somebody\'s contributions on the site? Add them to your filter list!<br/><strong>Note:</strong> Enter in the username of the person you want to filter, which is the username that would appear after "furaffinity.net/user/".' +
                        '</div>' +
                        '<div class="cell mobiletoggle cptoggle">' +
                            '<input class="textbox" type="text" id="faf-add-username" maxlength="50" style="margin-bottom:10px"></input><br\><input id="faf-add" class="button" type="button" value="Add User" />' +
                        '</div>' +
                    '</div>' +
                '</div>' +
            '</div>' +
            '<div class="maintable rounded">' +
                '<table class="sessions-list faf-list faf-list-beta" width="100%" cellspacing="0" cellpadding="0" border="0" style="padding:0 15px 10px 15px">' +
                    '<tbody>' +
                        '<tr>' +
                            '<td class="p10t p5r p5b"><h3>Username</h3></td>' +
                            '<td class="p10t p5r p5b" width="200px"><h3>Submissions</h3></td>' +
                            '<td class="p10t p5r p5b" width="200px"><h3>Shouts</h3></td>' +
                            '<td class="p10t p5r p5b" width="200px"><h3>Comments</h3></td>' +
                            '<td class="p10t p5r p5b" width="200px"><h3>Notifications</h3></td>' +
                        '</tr>' +
                    '</tbody>' +
                '</table>' +
            '</div>' +
            '<div class="alignleft p10t">' +
                '<input class="button" id="faf-update" type="button" value="Update Filters"> <span class="faf-update-status" style="font-weight: bold; color: #006600; display: none;">Update successful!</span>' +
            '</div>';
            $(settingsDisplay).insertAfter('.container-item-bot-last');
        } else {
            // Classic HTML Code
            var settingsDisplay = '<table id="fa-filter" cellpadding="0" cellspacing="1" border="0" class="section maintable"><tbody>' +
                '<tr><td height="22" class="cat links">&nbsp;<strong>FA Filter</strong></td></tr>' +
                '<tr><td class="alt1 addpad ucp-site-settings" align="center">' +
                    '<table cellspacing="1" cellpadding="0" border="0"><tbody>' +
                        '<tr>' +
                            '<th><strong>Add a User</strong></th>' +
                            '<td><input type="text" id="faf-add-username" maxlength="50"></input>&nbsp;<input id="faf-add" class="button" type="button" value="Add User"></td>' +
                            '<td class="option-description">' +
                                '<h3>Hide a user\'s contributions to the site.</h3>' +
                                '<p>Tired of seeing somebody\'s contributions on the site? Add them to your filter list!<br>Note: Enter in the username of the person you want to filter, which is the username that would appear after "furaffinity.net/user/".</p>' +
                            '</td>' +
                        '</tr>' +
                        '<tr>' +
                            '<th class="noborder" style="vertical-align: text-top;"><strong style="position: relative; top: 25px;">Modify Filters</strong></th>' +
                            '<td class="noborder">' +
                                '<table cellspacing="0" cellpadding="0" border="0" class="faf-list faf-list-classic">' +
                                    '<tr><th><strong>Username</strong></th><th><strong>Submissions</strong></th><th><strong>Shouts</strong></th><th><strong>Comments</strong></th><th><strong>Notifications</strong></th></tr>' +
                                '</table>' +
                                '<br><br><input class="button" id="faf-update" type="button" value="Update Filters"> <span class="faf-update-status" style="font-weight: bold; color: #006600; display: none;">Update successful!</span>' +
                            '</td>' +
                            '<td class="option-description noborder">' +
                                '<h3>Choose what items you don\'t want to see.</h3>' +
                                '<p>If you still want to see some of the things that a user contributes, you can control that here.</p>' +
                            '</td>' +
                        '</tr>' +
                    '</tbody></table>' +
                '</td></tr>' +
                '</tbody></table>';
            $('form').append(settingsDisplay);
        }
        
        // Populate list
        $.each(userArray, function(username, data) {
            addFilterUser(username, data);
        });
    }
}

// Display user in the filter table
function addFilterUser(username, data) {
    // Classic
    if ($('table.faf-list-classic').length) {
        
        var row = '<tr class="checked" id="filter-' + username + '"><td class="noborder"><a class="fa-filter-remove" id="faf-rm-' + username + '" href="#!">[x]</a> ' + username + '</td>';
        if (data['subs'] === 1) { row += '<td class="noborder"><input id="faf-check-subs-' + username + '" type="checkbox" checked="checked"></td>'; } else { row += '<td class="noborder"><input id="faf-check-subs-' + username + '" type="checkbox"></td>'; }
        if (data['shouts'] === 1) { row += '<td class="noborder"><input id="faf-check-shouts-' + username + '" type="checkbox" checked="checked"></td>'; } else { row += '<td class="noborder"><input id="faf-check-shouts-' + username + '" type="checkbox"></td>'; }
        if (data['coms'] === 1) { row += '<td class="noborder"><input id="faf-check-coms-' + username + '" type="checkbox" checked="checked"></td>'; } else { row += '<td class="noborder"><input id="faf-check-coms-' + username + '" type="checkbox"></td>'; }
        if (data['notifications'] === 1) { row += '<td class="noborder"><input id="faf-check-notifications-' + username + '" type="checkbox" checked="checked"></td>'; } else { row += '<td class="noborder"><input id="faf-check-notifications-' + username + '" type="checkbox"></td>'; }
        
        row += '</tr>';
        
        $('table.faf-list tr:last').after(row);
    // Beta
    } else {
        var rowBeta = '<tr id="filter-' + username + '"><td class="p5r" valign="middle" width="auto"><a class="fa-filter-remove" id="faf-rm-' + username + '" href="#!">[x]</a> ' + username + '</td>';
        if (data['subs'] === 1) { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-subs-' + username + '" type="checkbox" checked="checked"></td>'; } else { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-subs-' + username + '" type="checkbox"></td>'; }
        if (data['shouts'] === 1) { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-shouts-' + username + '" type="checkbox" checked="checked"></td>'; } else { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-shouts-' + username + '" type="checkbox"></td>'; }
        if (data['coms'] === 1) { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-coms-' + username + '" type="checkbox" checked="checked"></td>'; } else { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-coms-' + username + '" type="checkbox"></td>'; }
        if (data['notifications'] === 1) { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-notifications-' + username + '" type="checkbox" checked="checked"></td>'; } else { rowBeta += '<td class="p5r" valign="middle" width="auto"><input id="faf-check-notifications-' + username + '" type="checkbox"></td>'; }

        rowBeta += '</tr>';
    
        $('table.faf-list tr:last').after(rowBeta);
    }
}

// Add
$(document.body).on('click', '#faf-add', function() {
    var username = $.trim($('#faf-add-username').val());
    $('#faf-add-username').val('');
    if (username !== '') {
        username = username.toLowerCase();
        if (!(username in userArray)) {
            userArray[username] = {'subs':1, 'shouts':1, 'coms':1, 'notifications':1};
            addFilterUser(username, userArray[username]);
        }
    }
});

// Remove
$(document.body).on('click', 'a.fa-filter-remove', function(event) {
    var username = event.target.id.substr(7);
    delete userArray[username];
    
    // Replace periods/colons with escaped versions. Who the fuck allows periods in usernames, seriously?
    userEsc = username.replace(/\./, '\\.');
    userEsc = userEsc.replace(/:/, '\:');
    
    console.log(userEsc)
    $('table.faf-list tr#filter-' + userEsc).remove();
});

// Update
$(document.body).on('click', '#faf-update', function() {
    $('.faf-list tr[id^="filter-"]').each(function() {
        var username = this.id.substr(7);
        var vals = {'subs':0, 'shouts':0, 'coms':0, 'notifications':0};
        
        // Replace periods/colons with escaped versions. Who the fuck allows periods in usernames, seriously?
        userEsc = username.replace(/\./, '\\.');
        userEsc = userEsc.replace(/:/, '\:');
        
        // Check checkboxes
        if ($('#faf-check-subs-' + userEsc).is(':checked')) { vals['subs'] = 1; }
        if ($('#faf-check-shouts-' + userEsc).is(':checked')) { vals['shouts'] = 1; }
        if ($('#faf-check-coms-' + userEsc).is(':checked')) { vals['coms'] = 1; }
        if ($('#faf-check-notifications-' + userEsc).is(':checked')) { vals['notifications'] = 1; }
        
        userArray[username] = vals;
    });
    
    // Save
    writeSettings();
    
    // Display message
    $('.faf-update-status').fadeIn('slow');
    setTimeout(function() {
        $('.faf-update-status').fadeOut('slow');
    }, 5000);
});

displaySettings();

setTimeout(parseSettings, 50);
//setTimeout(parseTagSettings, 100);

// Submissions
if (window.location.pathname.lastIndexOf('/browse', 0) === 0) setTimeout(filtersSubs, 100);
else if (window.location.pathname.lastIndexOf('/favorites', 0) === 0) setTimeout(filtersSubs, 100);
else if (window.location.pathname.lastIndexOf('/msg/submissions', 0) === 0) setTimeout(filtersSubsFollow, 100);
// Shouts
else if (window.location.pathname.lastIndexOf('/user', 0) === 0) setTimeout(filtersShouts, 100);
else if (window.location.pathname.lastIndexOf('/controls/shouts', 0) === 0) setTimeout(filtersShoutsControl, 100);
// Comments
else if (window.location.pathname.lastIndexOf('/view', 0) === 0) setTimeout(filtersComments, 100);
// Notifications
else if (window.location.pathname.lastIndexOf('/msg/others', 0) === 0) setTimeout(filtersNotifications, 100);