Frystix / FanFiction.net Utilities

// ==UserScript==
// @namespace   https://openuserjs.org/users/Frystix
// @name        FanFiction.net Utilities
// @author      Frystix
// @description A collection of utilities related to fanfiction.net (Currently just work & author blocking)
// @license     MIT
// @version     0.1.0
// @include     http://www.fanfiction.net/*
// @include     https://www.fanfiction.net/*
// @require     http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_listValues
// @grant       GM_deleteValue
// ==/UserScript==

// ==OpenUserJS==
// @author      Frystix
// ==/OpenUserJS==

(function($) {
    // Utility stuff, not all of it is in use yet.
    // So on my test env String.replace replaces all occurances, in browser it does it replaces the first, this fixes that
    String.prototype.replace = function(search, replacement) {
        return this.split(search).join(replacement);
        //return this.replace(new RegExp(search, 'g'), replacement); // This is significantly faster (~50%), but / is a special character so this doesn't work as I don't know regex or js
    };
    String.prototype.count = function(char) {
        return this.length - this.replace(char, "").length;
    };
    function getUrl() {
        return window.location.href;
    }
    function isUser(url) {
        if (url.substr(26, 3) === "/u/" && url.substr(0, 5) === "https") {
            return true;
        }
        else if (url.substr(25, 3) === "/u/") {
            return true;
        }
        else {
            return false;
        }
    }
    function isStory(url) {
        if (url.substr(26, 3) === "/s/" && url.substr(0, 5) === "https") {
            return true;
        }
        else if (url.substr(25, 3) === "/s/") {
            return true;
        }
        else {
            return false;
        }
    }
    function getUserId(url) {
        // rewrite to handle all 3 use cases
        if (url.substr(0, 5) === "https") {
            return url.substr(29, url.lastIndexOf("/") - 29);
        }
        else {
            return url.substr(28, url.lastIndexOf("/") - 28);
        }
    }
    function getStoryId(url) {
        // rewrite to handle all 3 use cases
        var modifier = 0;
        if (url.substr(0, 5) === "https") {
            modifier = 1;
        }
        if (url.count("/") > 4) {
            return url.substr(28 + modifier, url.lastIndexOf("/", url.lastIndexOf("/") - 1) - 28 - modifier);
        }
        else {
            return url.substr(28 + modifier);
        }
    }
    function UI_Init() {
        // Create dropdown menu
        // Bugs: Both this and Betas open at the same time.
        // Using .after instead of .append fixes that at the cost of a different bug
        $('#zmenu .xmenu_item:last-child')
            .append('<div class="dropdown xmenu_item"><a class="dropdown-toggle" data-toggle="dropdown">FFUtils <b class="caret"></b></a><ul class="dropdown-menu"><li class="disabled" style="text-align:center"><a href="#">General</a></li><li class="disabled" style="text-align:center"><a href="#">Debug</a></li></ul></div>');
        var works = $('div.z-list');
        for (var i = 0; i < works.length; i++) {
            $(works[i]).find('.z-padtop').append('<a href="javascript:void(0)" class="workblock blockwork">Block Work</a><a href="javascript:void(0)" class="workblock blockauthor">Block Author</a>');
        }
        // Move block buttons slightly apart
        $('<style>').text('.workblock a {cursor:pointer;} a.workblock.blockauthor {margin-left: 15px;}').appendTo($('head'));
        // Hide blocked works
        var blockedStories = JSON.parse(GM_getValue('stories'));
        var blockedUsers = JSON.parse(GM_getValue('users'));
        for (var j = 0; j < works.length; j++) {
            var storyId = getStoryId("https://www.fanfiction.net" + $(works[j]).find('.stitle').attr('href'));
            var userId = getUserId($(works[j]).find('a[href*="/u/"]')[0].href);
            if ($.inArray(storyId, blockedStories) != -1) {
                $(works[j]).hide();
            }
            if ($.inArray(userId, blockedUsers) != -1) {
                $(works[j]).hide();
            }
        }
        return works;
    }
    function blockWork(work) {
        var id = getStoryId("https://www.fanfiction.net" + $(work).find('.stitle').attr('href'));
        var blocked = JSON.parse(GM_getValue('stories'));
        blocked.push(id);
        GM_setValue('stories', JSON.stringify(blocked));
        GM_setValue('last_story', id);
    }
    function blockUser(user) {
        var id = getUserId(user.find('a[href*="/u/"]')[0].href);
        var blocked = JSON.parse(GM_getValue('users'));
        blocked.push(id);
        GM_setValue('users', JSON.stringify(blocked));
        GM_setValue('last_user', id);
    }
    $(document).ready(function() {
        var works = UI_Init();
        $('.workblock.blockwork').click(function() {
            var work = $(this).parents('div.z-list');
            blockWork(work);
            $(work).hide();
        });
        $('.workblock.blockauthor').click(funcction() {
            // prompt user if certain
            var work = $(this).parents('div.z-list');
            if (confirm('Are you sure you want to block ' + $(work).find('a[href*="/u/"]')[0].innerHTML + '?')) {
                blockUser(work);
                $(work).hide();
            }
        });
    });
})(window.jQuery);