Greasy Fork

Greasy Fork is available in English.

Kickass Torrents Enhancements with Ad Remover

Enhances KickassTorrents (KAT) by forcing HTTPS, using a max-width layout, enabling navigation in search results using the arrow keys and removing ads.

当前为 2015-01-08 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Kickass Torrents Enhancements with Ad Remover
// @id          kickass-enhancements
// @namespace   urn:uuid:53d8a5b1-8677-481a-8096-939db3c8d0b3
// @version     1.4.1
// @description Enhances KickassTorrents (KAT) by forcing HTTPS, using a max-width layout, enabling navigation in search results using the arrow keys and removing ads.
// @license     MIT; http://opensource.org/licenses/MIT
// @match       http://kickass.so/*
// @match       https://kickass.so/*
// @grant       unsafeWindow
// @run-at      document-start
// ==/UserScript==

(function () {
    "use strict";

    var contentContainer;
    var sidebar;
    var prevPageHref;
    var nextPageHref;
    var hideSidebar;
    var showSidebar;

    (function () {
        // Force HTTPS
        if (/^http:\/\//.test(window.location.href)) {
            // Hide document during redirection
            var style = document.createElement("style");
            style.type = "text/css";
            style.textContent = "* { display: none; }";

            var parent = document.documentElement || document;
            parent.appendChild(style);

            // Redirect to HTTPS
            window.location.replace(window.location.href.replace(/^http:\/\//, "https://"));
            return;
        }

        // Disable pop-up windows
        var code = function (unsafeWindow, exportFunction) {
            // Prevent overwriting
            var Error = window.Error;
            var HTMLAnchorElement = window.HTMLAnchorElement;

            // Break the script creating advertisements
            Object.defineProperty(unsafeWindow, "_scq", {
                configurable: false,
                enumerable: false,
                get: exportFunction(function () {
                    throw new Error("Advertisements are disabled");
                }, unsafeWindow)
            });

            // Prevent opening pop-up windows using window.open()
            unsafeWindow.open = exportFunction(function open() {
                return null;
            }, unsafeWindow);

            // Prevent opening pop-up windows using a.click()
            var prevClick = HTMLElement.prototype.click;
            prevClick = prevClick.apply.bind(prevClick);
            unsafeWindow.HTMLElement.prototype.click = exportFunction(function click() {
                if (this instanceof HTMLAnchorElement && this.target != "")
                    return;

                return prevClick(this, arguments);
            }, unsafeWindow);

            // Prevent opening pop-up windows using a.dispatchEvent()
            var prevDispatchEvent = EventTarget.prototype.dispatchEvent;
            prevDispatchEvent = prevDispatchEvent.apply.bind(prevDispatchEvent);
            unsafeWindow.EventTarget.prototype.dispatchEvent = exportFunction(function dispatchEvent(event) {
                if (this instanceof HTMLAnchorElement && this.target != "" && event && event.type == "click")
                    return;

                return prevDispatchEvent(this, arguments);
            }, unsafeWindow);
        };

        if (typeof (unsafeWindow) != "undefined" && typeof (exportFunction) != "undefined" && unsafeWindow !== window) {
            // Execute code in privileged context
            code(unsafeWindow, exportFunction);
        } else {
            // Execute code in non-privileged context
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.textContent = '"use strict";\n(' + code.toString() + ')(window, function (func) { return func; });';

            // Run script before any other script is run
            var parent = document.documentElement || document;
            parent.appendChild(script);
            parent.removeChild(script);
        }

        // Ignore errors in the script creating advertisements
        window.addEventListener("error", onError, true);

        // Prevent advertisements from being created
        if ("onbeforescriptexecute" in document)
            document.addEventListener("beforescriptexecute", onBeforeScriptExecute, true);

        // Continue when DOM is available
        document.addEventListener("DOMContentLoaded", onContentLoaded, true);
    })();

    function onError(event) {
        if (!/Advertisements are disabled/.test(event.message))
            return;

        var script = document.evaluate("descendant::*[last()]/self::script", document, null, 8 /*ANY_UNORDERED_NODE_TYPE*/, null).singleNodeValue;
        if (!script)
            return;

        // Match the script creating advertisements
        var code = script.textContent;
        if (!/\b_scq\b/.test(code))
            return;

        // Prevent error from being logged
        event.preventDefault();
        event.stopPropagation();
    }

    function onBeforeScriptExecute(event) {
        // Ignore external scripts
        var script = event.target;
        if (script.src != "")
            return;

        // Prevent advertisements from being created
        var code = script.textContent;
        if (!/\b_scq\b/.test(code))
            return;

        // Prevent script from executing
        event.preventDefault();
        event.stopPropagation();
    }

    function onContentLoaded() {
        document.removeEventListener("DOMContentLoaded", onContentLoaded, true);

        if ("onbeforescriptexecute" in document)
            document.removeEventListener("beforescriptexecute", onBeforeScriptExecute, true);

        window.removeEventListener("error", onError, true);

        // Force HTTPS for KickassTorrents and Torcache links
        var items = document.querySelectorAll('a[href^="http://kickass.so/"], link[href^="http://kickass.so/"], a[href^="http://torcache.net/"]');
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            item.href = item.href.replace(/^http:\/\//, "https://")
        }

        // Inline referrer anonymizer (for IMDb links)
        var items = document.querySelectorAll('a[href^="http://blankrefer.com/?http"]');
        for (var i = 0; i < items.length; i++) {
            var a = items[i];
            var match = a.href.match(/^http:\/\/blankrefer\.com\/\?(https?:\/\/.*)$/);
            if (!match)
                continue;

            var encodedURL = match[1].replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
            var html = '<meta http-equiv="refresh" content="0;url=' + encodedURL + '">';

            // Specify UTF-8 for non-ASCII characters
            var charset = "";
            if (/[^\x00-\x7f]/.test(html))
                charset = ";charset=utf-8";

            a.href = "data:text/html" + charset + "," + encodeURIComponent(html);
        }

        // Apply style sheet to support the max-width layout and hide advertisements
        var style = document.createElement("style");
        style.type = "text/css";
        style.textContent = 'body { min-width: 0; }' +
            'footer { width: auto; }' +
            'iframe[style*="visibility:hidden"], iframe[style*="visibility: hidden"] { display: none; }' +
            '.tabs { overflow: visible; }' +
            'ul.tabNavigation li a span { padding-left: 7px; padding-right: 7px; }' +
            '.pages a:not(.blank) { min-width: 15px; padding-left: 7px; padding-right: 7px; }' +
            '.advertising, .partner1Button { display: none; }';
        document.head.appendChild(style);

        // Select original content container
        var mainContent = document.querySelector(".mainpart .doublecelltable td");
        sidebar = document.querySelector("#sidebar");
        if (!mainContent && !sidebar)
            mainContent = document.querySelector(".mainpart");

        // Create max-width content container
        if (mainContent) {
            contentContainer = document.createElement("div");
            contentContainer.style.margin = "15px auto 0";
            contentContainer.style.maxWidth = "900px";

            while (mainContent.firstChild)
                contentContainer.appendChild(mainContent.firstChild);

            // Include float elements in parent height
            var clearDiv = document.createElement("div");
            clearDiv.style.clear = "both";
            contentContainer.appendChild(clearDiv);

            mainContent.appendChild(contentContainer);

            // Remove width from nested content containers
            var items = contentContainer.querySelectorAll(':scope > div.margauto[class*="width"]');
            for (var i = 0; i < items.length; i++) {
                var item = items[i];
                if (/(^|\s)width\d+px($|\s)/.test(item.className))
                    item.style.setProperty("width", "auto", "important");
            }
        }

        // Hide advertisements
        var items = document.evaluate("//div[starts-with(@id, '_') and string-length(@id) = 33]", document, null, 6 /*UNORDERED_NODE_SNAPSHOT_TYPE*/, null);
        for (var i = 0; i < items.snapshotLength; i++) {
            var item = items.snapshotItem(i);
            item.style.display = "none";

            // Remove children when added
            var observer = new MutationObserver(onAdContainerMutation);
            observer.observe(item, { childList: true });
        }

        // Hide single tabs with no content (Sponsored Links)
        var items = document.querySelectorAll(".tabs");
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            if (!item.querySelector(":scope > :not(.tabNavigation):not(.tabsSeparator)") && document.evaluate("not(descendant::li[2])", item, null, 3 /*BOOLEAN_TYPE*/, null).booleanValue)
                item.style.display = "none";
        }

        // Hide line breaks after hidden elements
        var items = document.querySelectorAll("* + br");
        for (var i = 0; i < items.length; i++) {
            var br = items[i];

            // Ignore line breaks after visible elements
            if (window.getComputedStyle(br.previousElementSibling, null).display != "none")
                continue;

            for (var prevNode = br.previousSibling; prevNode; prevNode = prevNode.previousSibling) {
                switch (prevNode.nodeType) {
                    case 1 /*ELEMENT_NODE*/:
                        // Found previous hidden element
                        br.style.display = "none";
                        break;
                    case 3 /*TEXT_NODE*/:
                        // Ignore white space
                        if (!/\S/.test(prevNode.textContent))
                            continue;
                        break;
                    default:
                        // Ignore comments
                        continue;
                }

                // Found text between the line break and the previous element
                break;
            }
        }

        // Enhance navigation
        var activePages = document.querySelectorAll(".pages a.active");
        for (var i = 0; i < activePages.length; i++) {
            var activePage = activePages[i];
            var parent = activePage.parentNode;

            // Add Prev button
            var prevPage = document.evaluate("preceding-sibling::a[1]", activePage, null, 8 /*ANY_UNORDERED_NODE_TYPE*/, null).singleNodeValue;
            if (prevPage) {
                if (i == 0)
                    prevPageHref = prevPage.href;

                prevPage = prevPage.cloneNode(false);
                prevPage.textContent = "< Prev";
                parent.insertBefore(prevPage, parent.firstElementChild);
            }

            // Add Next button
            var nextPage = document.evaluate("following-sibling::a[1]", activePage, null, 8 /*ANY_UNORDERED_NODE_TYPE*/, null).singleNodeValue;
            if (nextPage) {
                if (i == 0)
                    nextPageHref = nextPage.href;

                nextPage = nextPage.cloneNode(false);
                nextPage.textContent = "Next >";
                parent.insertBefore(nextPage, parent.lastElementChild.nextSibling);
            }
        }

        // Navigate using arrow keys
        if (prevPageHref || nextPageHref)
            window.addEventListener("keypress", onKeyPress, false);

        if (sidebar) {
            // Create sidebar toggles
            if (!sidebar.classList.contains("sidebarLogged")) {
                sidebar.classList.add("sidebarLogged");
                sidebar.classList.add("font11px");

                // Create hideSidebar
                hideSidebar = document.createElement("a");
                hideSidebar.classList.add("hideSidebar");
                hideSidebar.addEventListener("click", onHideSidebarClick, false);

                // Create showSidebar
                showSidebar = document.createElement("a");
                showSidebar.classList.add("showSidebar");
                showSidebar.style.display = "none";
                showSidebar.addEventListener("click", onShowSidebarClick, false);

                // Insert sidebar toggles
                sidebar.parentNode.insertBefore(hideSidebar, sidebar);
                sidebar.parentNode.insertBefore(showSidebar, sidebar);
            }

            var items = sidebar.querySelectorAll(".sliderbox");
            var i = items.length - 1;
            while (i >= 0) {
                var section = items[i--];

                var sectionHeader = section.querySelector("h3");
                if (!sectionHeader)
                    continue;

                var foldClose = sectionHeader.querySelector(".foldClose");
                if (!foldClose)
                    continue;

                var block = section.querySelector(".showBlockJS");
                if (!block)
                    continue;

                // Enable toggling sidebar section by clicking on the section header
                sectionHeader.style.cursor = "pointer";
                sectionHeader.addEventListener("click", onSectionHeaderClick, false);

                // Close sidebar sections while the viewport is shorter than the document and sidebar is higher than content
                if (contentContainer && window.innerWidth > document.documentElement.clientWidth && sidebar.offsetTop + sidebar.offsetHeight > contentContainer.offsetTop + contentContainer.offsetHeight) {
                    foldClose.classList.add("ka-180");
                    block.classList.remove("showBlockJS");
                    block.classList.add("hideBlockJS");
                }
            }
        }
    }

    function onAdContainerMutation(mutations) {
        for (var i = 0; i < mutations.length; i++) {
            var mutation = mutations[i];
            var parent = mutation.target;
            var addedNodes = mutation.addedNodes;

            for (var i = 0; i < addedNodes.length; i++)
                parent.removeChild(addedNodes[i]);
        }
    }

    function onKeyPress(event) {
        switch (event.key) {
            case "Left":
                if (prevPageHref)
                    window.location.assign(prevPageHref);
                break;
            case "Right":
                if (nextPageHref)
                    window.location.assign(nextPageHref);
                break;
            default:
                return;
        }

        event.preventDefault();
    }

    function onHideSidebarClick(event) {
        sidebar.style.display = "none";
        hideSidebar.style.display = "none";
        showSidebar.style.display = "";

        event.preventDefault();
    }

    function onShowSidebarClick(event) {
        sidebar.style.display = "";
        hideSidebar.style.display = "";
        showSidebar.style.display = "none";

        event.preventDefault();
    }

    function onSectionHeaderClick(event) {
        var foldClose = this.querySelector(".foldClose");
        if (!foldClose)
            return;

        // Ignore click event bubbling from foldClose
        if (event.target == foldClose)
            return;

        foldClose.click();
        event.preventDefault();
    }

})();