Anti-Adblock Killer (Safe + Exceptions + Hotkeys)

Neutralizes adblock detection scripts without breaking major websites. Includes hotkeys for adding/removing exceptions (Ctrl+Shift+E / Ctrl+Shift+X).

目前為 2025-11-19 提交的版本,檢視 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Anti-Adblock Killer (Safe + Exceptions + Hotkeys)
// @namespace    https://tampermonkey.net/
// @version      3.2
// @description  Neutralizes adblock detection scripts without breaking major websites. Includes hotkeys for adding/removing exceptions (Ctrl+Shift+E / Ctrl+Shift+X).
// @author       TAUÃ B. KLOCH LEITE
// @match        *://*/*
// @license      GPL-3.0
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    /* -------------------------------
       Storage & defaults
    ------------------------------- */
    const STORAGE_KEY = 'antiAdblockExceptions';
    const DEFAULT_EXCEPTIONS = [
        "google",
        "youtube",
        "greasyfork.org",
        "instagram",
        "whatsapp",
        "reddit",
        "github",
        "x.com",
        "twitter",
        "tiktok",
        "wikipedia",
        "linkedin",
        "amazon",
        "netflix",
        "hbo",
        "disney",
        "spotify",
        "paypal",
        "microsoft",
        "office",
        "live",
        "outlook",
        "steam",
        "epicgames",
        "roblox",
        "discord",
        "twitch"
    ];

    // load saved exceptions (user edits persist)
    let exceptions;
    try {
        const saved = localStorage.getItem(STORAGE_KEY);
        exceptions = saved ? JSON.parse(saved) : DEFAULT_EXCEPTIONS.slice();
        if (!Array.isArray(exceptions)) exceptions = DEFAULT_EXCEPTIONS.slice();
    } catch (e) {
        exceptions = DEFAULT_EXCEPTIONS.slice();
    }

    function saveExceptions() {
        try { localStorage.setItem(STORAGE_KEY, JSON.stringify(exceptions)); } catch(e){}
    }

    /* -------------------------------
       Helper: normalized hostname & matching
    ------------------------------- */
    function normalizeHost(h) {
        if (!h) return '';
        return h.toLowerCase().replace(/^www\./, '').trim();
    }
    const currentHost = normalizeHost(window.location.hostname);

    // returns exception that matches this host (or undefined)
    function findMatchingExceptionForHost(host) {
        for (const ex of exceptions) {
            const exNorm = ex.toLowerCase().replace(/^www\./, '').trim();
            if (!exNorm) continue;
            if (host === exNorm) return ex;                     // exact
            if (host.endsWith('.' + exNorm)) return ex;         // subdomain
            if (host.includes(exNorm)) return ex;               // fallback substring (keeps behavior compatible)
        }
        return undefined;
    }

    /* -------------------------------
       HOTKEYS: register BEFORE early-return so remove works on exception sites
       Ctrl+Shift+E => add current site to exceptions
       Ctrl+Shift+X => remove current site from exceptions
    ------------------------------- */
    document.addEventListener('keydown', (ev) => {
        // require ctrl + shift
        if (!ev.ctrlKey || !ev.shiftKey) return;

        // normalize current host on key press (fresh)
        const hostNow = normalizeHost(window.location.hostname);

        // ADD: Ctrl + Shift + E
        if (ev.key.toLowerCase() === 'e') {
            ev.preventDefault();
            const existing = findMatchingExceptionForHost(hostNow);
            if (existing) {
                alert(`This site is already in exceptions: ${existing}`);
                return;
            }
            // save normalized host (without www) so matching works consistently
            exceptions.push(hostNow);
            saveExceptions();
            alert(`Added to exceptions: ${hostNow}\nReload page to apply.`);
            return;
        }

        // REMOVE: Ctrl + Shift + X
        if (ev.key.toLowerCase() === 'x') {
            ev.preventDefault();
            const match = findMatchingExceptionForHost(hostNow);
            if (!match) {
                alert(`This site is not in exceptions:\n${hostNow}`);
                return;
            }
            // remove all entries that equal match (keeps duplicates cleared)
            exceptions = exceptions.filter(e => {
                const eNorm = e.toLowerCase().replace(/^www\./, '').trim();
                return eNorm !== match.toLowerCase().replace(/^www\./, '').trim();
            });
            saveExceptions();
            alert(`Removed from exceptions: ${match}\nReload page to apply.`);
            return;
        }
    }, true);

    /* -------------------------------
       Now check exception list
    ------------------------------- */
    const matched = findMatchingExceptionForHost(currentHost);
    if (matched) {
        console.log(`[Anti-Adblock Killer] Exception applied for: ${currentHost} (matched '${matched}')`);
        // do not run the anti-adblock remover on this site
        return;
    }

    /* -------------------------------
       The original working behavior 
    ------------------------------- */

    // Neutralize known adblock detection scripts
    try {
        Object.defineProperty(window, 'FuckAdBlock', { value: function(){}, writable: false });
    } catch(e){}
    try {
        Object.defineProperty(window, 'BlockAdBlock', { value: function(){}, writable: false });
    } catch(e){}

    // Block future adblock detection scripts from executing
    const blockScripts = ["fuckadblock", "blockadblock", "adblock-detector"];
    const observer = new MutationObserver((mutations) => {
        for (const mutation of mutations) {
            mutation.addedNodes.forEach(node => {
                try {
                    if (node.tagName === 'SCRIPT') {
                        const src = (node.src || '').toLowerCase();
                        if (blockScripts.some(s => src.includes(s))) {
                            node.type = 'javascript/blocked';
                            node.remove();
                            console.log('Blocked an anti-adblock script:', src);
                        }
                    }
                } catch(e){}
            });
        }
    });
    observer.observe(document.documentElement, { childList: true, subtree: true });

    // Remove visual "disable adblock" messages
    const removeWarnings = () => {
        const warningKeywords = ['adblock', 'disable', 'whitelist', 'bloqueador'];
        document.querySelectorAll('div,section,aside,dialog').forEach(el => {
            try {
                if (warningKeywords.some(k => (el.textContent || '').toLowerCase().includes(k))) {
                    el.style.display = 'none';
                }
            } catch(e){}
        });
    };
    setInterval(removeWarnings, 1500);

    console.log('✅ Anti-Adblock Killer is active (hotkeys enabled)');
})();