No Ad IFrame

No Ad IFrame created by Stay

Version au 16/12/2024. Voir la dernière version.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         No Ad IFrame
// @namespace    https://staybrowser.com/
// @version      0.1.0

// @description         No Ad IFrame created by Stay
// @description:en      No Ad IFrame created by Stay
// @description:ja      No Ad IFrame created by Stay
// @description:zh-TW   No Ad IFrame created by Stay
// @description:zh-CN   No Ad IFrame created by Stay

// @author       You
// @match        *://*/*
// @grant        none
// @inject-into page
// @unwrap
// @run-at              document-start
// @license             MIT
// @compatible          chrome
// @compatible          firefox
// @compatible          opera
// @compatible          edge
// @compatible          safari
// @allFrames           true
// ==/UserScript==
(function () {
    'use strict';

    const TURN_ON_BLOCK_REMOVAL = true;

    if (Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, "__src437__")) return;

    Object.defineProperty(HTMLIFrameElement.prototype, "__src437__", {
        value: undefined,
        writable: true,
        configurable: false,
        enumerable: false
    });

    if (!Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, "__src437__")) return;

    const pd1 = Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, "src");
    const pd2 = Object.assign({}, pd1, {
        configurable: true,
        enumerable: true
    });

    const wSnb = Symbol();

    const adFilter = {

        'iframe[src*="doubleclick.net"]': 1,
        'iframe[src*="googlesyndication.com"]': 1,
        'iframe[src*="googleadservices.com"]': 1,
        'iframe[src*="googletagservices.com"]': 1,
        'iframe[src*="adservice.google.com"]': 1,
        'iframe[src*="adservice.yahoo.com"]': 1,
        'iframe[src*="amazon-adsystem.com"]': 1,
        'iframe[src*="adroll.com"]': 1,
        'iframe[src*="ads-twitter.com"]': 1,
        'iframe[src*="criteo.com"]': 1,
        'iframe[src*="taboola.com"]': 1,
        'iframe[src*="outbrain.com"]': 1,
        'iframe[src*="smartadserver.com"]': 1,
        'iframe[src*="openx.net"]': 1,
        'iframe[src*="rubiconproject.com"]': 1,

        'iframe[id^="aswift_"][src*="ads"][3]': 1,
        'iframe[id^="google_ads_iframe_"]': 1,
        'iframe[name^="google_ads_iframe_"]': 1,
        // 'iframe[src*="doubleclick.net"]': 1,
        // 'iframe[src*="googlesyndication.com"]': 1,
        'iframe[src*="adservice"]': 1,
        'iframe[src*="adserver"]': 1,
        // 'iframe[src*="/ads/"]': 1,
        // 'iframe[class*="ad-"]': 1,
        'iframe[data-ad-slot]': 1,

        // Additional patterns
        'iframe[id*="adframe"]': 1,         // Common variation like "adframe"
        'iframe[id*="ad_iframe"]': 1,       // "ad_iframe" naming pattern
        'iframe[id*="ad_container"]': 1,    // Container-like naming often used for ads
        'iframe[id*="ad_wrapper"]': 1,      // Another container naming pattern

        'iframe[class*="adslot"]': 1,       // "adslot" is a known pattern (e.g., GPT ad slots)
        'iframe[class*="adsense"]': 1,      // "adsense" typically indicates Google AdSense
        'iframe[class*="ad_frame"]': 1,     // Variation with underscore
        // 'iframe[class*="advert"]': 1,       // "advert" is another clue

        // Attribute patterns
        'iframe[data-ad-client]': 1,         // Data attribute used by some ad scripts
        'iframe[data-ad-region]': 1,         // Another ad-related data attribute

    };

    function createBase64DataURL(title) {
        // Construct a minimal HTML5 page with the given title
        const html = `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><title>${title}</title></head><body></body></html>`;

        // Encode the HTML string into Base64
        const base64String = btoa(html);

        // Return as a Data URL
        return `data:text/html;base64,${base64String}`;
    }


    const dynamicGeneration = () => {
        const key = Math.floor(Math.random() * 314159265359 + 314159265359).toString(36);
        return createBase64DataURL(key);
    }

    const caching = new Map();

    const hKey = `e-${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;

    const checkOnly = (elm) => {

        let noP = true;
        let noQ = true;
        let t = elm || 0;
        while (t = t.previousSibling) {

            if (t instanceof Text) {
                if (t.textContent.trim().length > 0) {
                    noP = false;
                    break;
                }
            } else if (t instanceof Element) {
                const nd = t.nodeName;
                if (nd === 'NOSCRIPT' || nd === 'SCRIPT' || nd === 'STYLE') continue;
                noP = false;
                break;
            } else if (t instanceof Comment) {

            } else {
                noP = false;
                break;
            }
        }
        if (noP === false) return false;

        t = elm || 0;
        while (t = t.nextSibling) {

            if (t instanceof Text) {
                if (t.textContent.trim().length > 0) {
                    noQ = false;
                    break;
                }
            } else if (t instanceof Element) {
                const nd = t.nodeName;
                if (nd === 'NOSCRIPT' || nd === 'SCRIPT' || nd === 'STYLE') continue;
                noQ = false;
                break;
            } else if (t instanceof Comment) {

            } else {
                noQ = false;
                break;
            }
        }

        if (noQ === false) return false;

        return true;


    };
    const hideIframe = (iframe) => {
        let noscriptWrapOK = false;
        try {
            if (iframe instanceof HTMLIFrameElement && iframe.isConnected === true && (iframe.parentNode || 0).nodeName !== 'NOSCRIPT') {
                const noscript = document.createElement('noscript');
                iframe.replaceWith(noscript);
                noscript.appendChild(iframe);
                noscriptWrapOK = true;
            }
        } catch (e) {
            console.warn(e);
        }

        if (TURN_ON_BLOCK_REMOVAL && noscriptWrapOK) {
            let layerNMax = 8;
            let parent = iframe;
            let lastSuccess = iframe;
            while (parent instanceof HTMLElement && checkOnly(parent)) {
                lastSuccess = parent;
                parent = parent.parentNode;
                layerNMax--;
                if (!layerNMax) break;
            }

            const effectNode = parent instanceof HTMLElement ? parent : lastSuccess;

            if ((effectNode instanceof HTMLElement) && effectNode.nodeName !== "NOSCRIPT") {
                effectNode.setAttribute(hKey, '');
                let noscriptWrapOK = false;
                try {
                    const noscript = document.createElement('noscript');
                    effectNode.replaceWith(noscript);
                    noscript.appendChild(effectNode);
                    noscriptWrapOK = true;
                } catch (e) { }
                if (!noscriptWrapOK) {
                    effectNode.style.setProperty('position', 'fixed', 'important');
                    effectNode.style.setProperty('left', '-130vw', 'important');
                    effectNode.style.setProperty('top', '-140vh', 'important');
                }
            }

        }

    };


    const convertionUrl = (nv, iframe) => {

        if (typeof nv == 'string' && nv.length > 15 && iframe instanceof HTMLIFrameElement) {
            if ((iframe.parentNode || 0).nodeName === 'NOSCRIPT') return null;
            if (nv.length >= 22 && nv.startsWith('data:text/html;base64,')) return null;

            const cv = caching.get(nv);
            if (cv !== undefined) return cv;

            for (const adf of Object.keys(adFilter)) {
                const adk = adf.replace(/\[\d+\w*\]/g, '');
                if (iframe.matches(adk)) {
                    const w = adFilter[adf];
                    const bv = typeof w === 'string' ? w : dynamicGeneration();
                    caching.set(nv, bv);
                    caching.set(bv, bv);
                    return bv;
                }
            }
            caching.set(nv, null);
        }
        return null;
    };
    const pd3 = {
        set(nv) {
            if (typeof nv === 'string') {
                if (this[wSnb] === nv) return true;
                if (nv.length >= 22 && nv.startsWith('data:text/html;base64,')) {
                } else if (nv.length > 15) {
                    const bv = convertionUrl(nv, this);
                    if (bv) {
                        hideIframe(this);
                        if ((this.parentNode || 0).nodeName !== 'NOSCRIPT') nv = bv;
                    }
                }
            }
            this[wSnb] = nv;
            return true;
        },
        get() {
            return this[wSnb];
        },
        configurable: true,
        enumerable: true
    };

    Object.defineProperty(HTMLIFrameElement.prototype, wSnb, pd2);


    Object.defineProperty(HTMLIFrameElement.prototype, "src", pd3);


    document.addEventListener('load', function (evt) {
        const evtTarget = evt.target;
        if (evtTarget instanceof HTMLIFrameElement) {
            const bv = convertionUrl(evtTarget.src, evtTarget);
            if (bv) {
                hideIframe(evtTarget);
                if ((evtTarget.parentNode || 0).nodeName !== 'NOSCRIPT') evtTarget.src = bv;
                evt.stopPropagation();
                evt.stopImmediatePropagation();
                evt.preventDefault();
            }
        }
    }, true);

    const um = new WeakSet();

    const iframeAll = document.getElementsByTagName('iframe');
    let iframeLC = 0;
    new MutationObserver(() => {
        const iframeTC = iframeAll.length;
        if (iframeTC !== iframeLC) {
            iframeLC = iframeTC;
            for (const iframe of iframeAll) {
                if (um.has(iframe)) continue;
                um.add(iframe);
                const bv = convertionUrl(iframe.src, iframe);
                if (bv) {
                    hideIframe(iframe);
                    if ((iframe.parentNode || 0).nodeName !== 'NOSCRIPT') iframe.src = bv;
                }
            }
        }
    }).observe(document, { subtree: true, childList: true });

    // Your code here...
})();