Greasy Fork is available in English.

屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music.

Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music

Asenna tämä skripti?
Author's suggested script

Saatat myös pitää

Asenna tämä skripti
// ==UserScript==
// @name         屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:zh-CN   屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:zh-TW   屏蔽所有Youtube廣告 Youtube AD blocker (Block all ad). Including blocking Youtube Music.
// @name:ar      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:bg      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:cs      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:da      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:de      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:el      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:eo      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:es      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:fi      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:fr      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:fr-CA   屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:he      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:hu      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:id      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:it      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:ja      YoutubeMusicを含むすべてのYoutube広告をブロックする
// @name:ko      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:kr      Youtube Music을 포함한 모든 YouTube 광고 차단
// @name:nb      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:nl      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:pl      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:pt-BR   屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:ro      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:ru      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:sk      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:sr      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:sv      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:th      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:tr      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:uk      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:ug      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 
// @name:vi      屏蔽所有Youtube广告 Youtube AD blocker (Block all ad). Including blocking Youtube Music. 


// @description         Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:zh-CN   屏蔽所有视频广告、插入广告、页面广告
// @description:zh-TW   屏蔽所有視頻廣告、插入廣告、頁面廣告
// @description:ar      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:bg      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:cs      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:da      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:de      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:el      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:eo      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:es      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:fi      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:fr      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:fr-CA   Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:he      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:hu      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:id      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:it      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:ja      すべてのビデオ広告をブロックし、広告を挿入し、ページ広告を挿入します。YoutubeMusicを含みます。
// @description:ko      Youtube Music을 포함한 모든 비디오 광고, 삽입 광고, 페이지 광고 차단.
// @description:kr      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:nb      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:nl      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:pl      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:pt-BR   Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:ro      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:ru      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:sk      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:sr      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:sv      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:th      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:tr      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:uk      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:ug      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music
// @description:vi      Block all video ads, insert ads, page ads. Including Youtube Music. 屏蔽所有视频广告、插入广告、页面广告。包括Youtube Music.

// @namespace    https://github.com/ChenZihan-sudo/Youtube-AD-blocker/
// @version      6.0.1 [Beta]
// @author       ChenZihan
// @match        *.youtube.com/*
// @icon
// @grant        none
// ==/UserScript==

(function () {
    let rmAry = new Array();
    let { href } = location;

    setInterval(() => {
        let bufHref = location.href; //detect the change of href and execute 

        let detectBasicAd; //detect the activity of insert ad in video
        if (document.getElementsByClassName("ytp-ad-preview-text").length) {
            detectBasicAd = (document.getElementsByClassName("ytp-ad-preview-text")[0].innerHTML.constructor == String);
        }

        //* skipShitVideoAD() can only reset by change of href
        //! check if the frame exist
        if (bufHref != href && document.getElementById("iframe")) {
            console.log("isCallSkipShitVideoAD = false");
            isCallSkipShitVideoAD = false;
        }

        //* check change of href
        if (bufHref != href) {
            console.log("[YT AD block] Detect the change of href.", href);
            href = bufHref;
            executeManager('f');
        }

        //* check the insert AD
        if (detectBasicAd) {
            console.log("[YT AD block] Found the insert AD.");
            executeManager('f');
        }
    }, 500);

    if (location.hostname.search("youtube") != -1) {
        addBData('id', 'player-ads', 'f'); //add data
        addBData('id', 'masthead-ad', 'f');
        addBData('path', '#YtKevlarVisibilityIdentifier', 'f');
        addBData('class', 'ytp-ad-overlay-container', 'a');
        addBData('csClick', [
            ['ytp-ad-feedback-dialog-reason-input', 'randomPara(0, 2)'],
            ['ytp-ad-feedback-dialog-confirm-button', '0'], 1
        ], 'f');
        addBData('csClick', [
            ['ytp-ad-skip-button', '0'], 0
        ], 'a');
        addBData('tag', 'ytd-display-ad-renderer', 'a');
        addBData("exe", "skipShitVideoAD();", 'f');
        addBData("exe", "addBlockText();", 'f');
        addBData("remTactic1", ["badge-style-type-ad", 7, "ytd-section-list-renderer"], 'f');
        addBData("remTactic1", ["badge-style-type-ad", 5, "ytd-item-section-renderer"], 'f');
        addBData("remTactic1", ["badge-style-type-ad", 5, "ytd-watch-next-secondary-results-renderer"], 'f');

        executeManager(); //execute at first time
    }


    /**
     * @param {String} exePara (undefined) or ('f' => execute the data for 20 times, every time interval 500ms )
     * */
    function executeManager(exePara) {
        let len = rmAry.length;

        for (let i = 0; i < len; i++) {
            if (rmAry[i][2] == 'a' && exePara == undefined) {

                setInterval(() => {
                    // console.log("[YT AD block] Execute remove insert AD loop");
                    execute(); //always execute the data
                }, 800);

            } else if (rmAry[i][2] == 'f' || exePara == 'f') { //execute only in first time

                // console.log("[YT AD block] Execute remove AD");

                window.onload = function () { intervalExecute(); } //if player already load
                if (exePara == 'f') { intervalExecute(); }
                intervalExecute();

                function intervalExecute() {
                    let times = 0;
                    let timer = setInterval(() => {
                        times++;
                        if (times > 20) { clearInterval(timer); };
                        execute(); //excute 20 times in every 500ms
                    }, 500);
                }
            }

            function execute() {
                let isUniExeTag = rmAry[i][0] == "universal"; //Check is universal tag or not
                if (!isUniExeTag) {
                    let exeTag = rmAry[i][0]; //Execute Type
                    let exeData = rmAry[i][1]; //Data container of execute type
                    executeBase(exeTag, exeData);
                } else {
                    //[Beta] Execute Type: universal
                    // let exeLength = rmAry[i][1].length;
                    // for (let layeri = 0; layeri < exeLength; layeri++) {
                    //     let layerExeData = rmAry[i][1][layeri];
                    //     let exeTag = layerExeData[0];
                    //     let exeData = layerExeData[1];
                    //     executeBase(layerExeData, exeTag, exeData);
                    // }
                };
            }


            function executeBase(exeTag, exeData) {
                let cckClassDataPosi, cckType, cckCs;
                switch (exeTag) {
                    case 'id':
                        idRm(exeData);
                        break;
                    case 'path':
                        pathRm(exeData);
                        break;
                    case 'class':
                        classRm(exeData);
                        break;
                    case 'csClick':
                        {
                            len = rmAry[i][1].length - 1; //find last one num
                            cckClassDataPosi = rmAry[i][1][len];
                            cckType = rmAry[i][1][len].constructor;

                            if (cckType == Number) {
                                cckCs = rmAry[i][1][cckClassDataPosi][0];
                            } else if (cckType == String) {
                                cckCs = rmAry[i][1][2];
                            }

                            csClick(cckCs, rmAry[i][1]);
                            break;
                        }
                    case 'tag':
                        tagRm(exeData);
                        break;
                    case 'exe':
                        { dataExe(exeData); }
                        break;
                    case 'remTactic1':
                        {
                            let className = exeData[0];
                            let parentNum = exeData[1];
                            let expParentClassName = exeData[2];
                            remTactic1(className, parentNum, expParentClassName);
                        }
                        break;
                }
            }
        }
    }

    function addUniData(d2, d3) {
        addBData('universal', d2, d3);
    }

    function addExeData(d2, d3) {
        addBData('exe', d2, d3);
    }

    /**
     * @param d1 - Execute Type: 'id' => Use document.getElementById() to remove
     * @param d1 - Execute Type: 'path' => Use document.querySelector() to remove
     * @param d1 - Execute Type: 'class' => Use document.getElementsByClassName() to remove 
     * @param d1 - Execute Type: 'csClick' => css click event
     * @param d1 - Execute Type: 'tag' => Use document.getElementsByTagName() to remove
     * @param d1 - Execute Type: 'exe' => Use eval to execute the code
     * @param d1 - Execute Type: 'remTactic1' => See remTactic1();
     * @param d2 - Data container of d1 execute type
     * @param d3 - 'a' => Always execute the data, interval 800ms
     * @param d3 - 'f' => First execute the data for 20 times, every time interval 500ms
     */
    function addBData(d1, d2, d3) {
        let len = apdAry(rmAry);
        rmAry[len][0] = d1;
        rmAry[len][1] = d2;
        rmAry[len][2] = d3;
        rmAry[len][3] = rmAry.length - 1;
    }

    /**
     * By finding a className to find higher level of its parent element by class name and remove it
     * @param {String} className The child node class name (signature class name recommend)
     * @param {Number} parentNum How many node layers it parent elements have to get className(child node)
     * @param {String} expParentClassName The parent node class name(signature class name recommend)
     */
    function remTactic1(className, parentNum, expParentClassName) {
        var sl_length = document.getElementsByClassName(className).length;
        if (sl_length != 0) {
            if (parentNum == 0) {
                var len = document.getElementsByClassName(className).length;
                for (let i = 0; i < len; i++) {
                    document.getElementsByClassName(className)[0].remove();
                }
            } else {
                for (var s_i = 0; s_i < sl_length; s_i++) {
                    var parent = ".parentElement";
                    var finalParent = "";
                    for (var p_i = 0; p_i < parentNum; p_i++) {
                        finalParent = finalParent + parent;
                    }

                    //Find the parent name
                    var parentNode = "document.getElementsByClassName('" + className + "')[0]" + finalParent;
                    var parentNodeClassListLength = eval(parentNode + ".classList.length");
                    var isParentClassName = false;
                    for (let ii = 0; ii < parentNodeClassListLength; ii++) {
                        var parentClassName = eval(parentNode + ".classList[" + ii + "]");
                        if (parentClassName == expParentClassName) {
                            isParentClassName = true;
                            break;
                        }
                    }

                    if (isParentClassName) {
                        eval("document.getElementsByClassName('" + className + "')[0]" + finalParent + ".remove();");
                        remTactic1(className, parentNum, expParentClassName);
                        break;
                    }
                }
            }
        }
    }

    function csClick(cckCs, exAry) {
        if (document.getElementsByClassName(cckCs).length != 0) {
            let len = exAry.length;
            for (let i = 0; i < len; i++) {
                if (exAry[i].constructor != Array) { break; } //cck data type
                document.getElementsByClassName(exAry[i][0])[eval(exAry[i][1])].click(); //choose feedback option
            }
        }
    }

    function classRm(_class) {
        let times = 0;
        while (document.getElementsByClassName(_class).length != 0) {
            times++;
            if (times > 100) { break; }
            document.getElementsByClassName(_class)[0].remove();
        }
    }

    function idRm(id) {
        if (document.getElementById(id) != null) {
            document.getElementById(id).remove();
        }
    }

    function pathRm(path) {
        if (document.querySelector(path) != null) {
            document.querySelector(path).remove();
        }
    }

    function tagRm(tag) {
        let times = 0;
        while (document.getElementsByTagName(tag).length != 0) {
            times++;
            if (times > 100) { break; }
            document.getElementsByTagName(tag)[0].parentNode.parentNode.remove();
        }
    }

    function dataExe(exeData) {
        if (exeData) {
            let isArray = exeData.constructor == Array;
            if (!isArray) {
                eval(exeData);
            } else {
                //[Beta Test] Execute Type: universal
                if (exeData[0]) {
                    let finalData = exeData[0] + exeData[1];
                    eval(finalData);
                }
            }
        }
    }

    function randomPara(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    function apdAry(ary) {
        ary.splice(ary.length, 0, []);
        return ary.length - 1;
    }

    function addBlockText() {
        //本屏蔽器自带嘲讽功能[doge]
        if (document.getElementById("ad-text:a") != (null || undefined)) { document.getElementById("ad-text:a").innerHTML = "Trying Blocking AD..."; }
        if (document.getElementById("ad-text:b") != (null || undefined)) { document.getElementById("ad-text:b").innerHTML = "[Youtube AD block]"; }
        let blockText = document.getElementsByClassName("ytp-ad-button-text");
        if (blockText.length != 0) {
            for (let i = 0; i < blockText.length; i++) {
                blockText[i].innerHTML = "Blocking..."
            }
        }
    }

    var isCallSkipShitVideoAD = false;

    function skipShitVideoAD() {
        if (document.getElementsByClassName("ytp-ad-button-icon").length != 0 && !isCallSkipShitVideoAD && !document.getElementsByClassName('ytp-ad-skip-button').length != 0) {
            console.log("进入执行");

            isCallSkipShitVideoAD = true; //set identifier as true to avoid call this function again

            console.log("===>", new DocumentTimeline().currentTime);

            //Open the shit ad card
            document.getElementsByClassName("ytp-ad-button-icon")[0].click();

            // Wait the card load
            let shitIframeTimes = 0;
            let iframeDomPosi = 0; //find the iframe document posi 
            let shitIframeTimer = setInterval(function () {
                shitIframeTimes++;

                setDisplay("none");

                if (document.getElementById("iframe") != (null || undefined) || shitIframeTimes > 50) {
                    console.log("[YT] Detected the ad penel");
                    //find the iframe document posi 
                    for (let i = 0; i < window.frames.length; i++) {
                        let frameId = "iframe";
                        try {
                            if (window.frames[i].frameElement.id == frameId) {
                                iframeDomPosi = i;
                                break;
                            }
                        } catch (e) { /*console.log(e);*/ }
                    }
                    clearInterval(shitIframeTimer);
                }
            }, 40);

            //Wait for document loaded
            var waitCardTimes = 0;
            let frameDom;
            let waitCardTimer = setInterval(() => {
                waitCardTimes++;

                let bodyNodesLength = 0; //iframe body length of child node
                try {
                    bodyNodesLength = window.frames[iframeDomPosi].document.body.childNodes.length;
                } catch { }

                if (waitCardTimes > 100 || bodyNodesLength != 0) {
                    clearInterval(waitCardTimer);

                    //get the iframe document
                    frameDom = window.frames[iframeDomPosi].document;
                    try {
                        let shitStopDisplayBtn = frameDom.childNodes[1].childNodes[1].childNodes[2].childNodes[0].childNodes[0].childNodes[1].childNodes[1].childNodes[0].childNodes[0].childNodes[0].childNodes[0].childNodes[1].childNodes[1].childNodes[0].childNodes[0];
                        shitStopDisplayBtn.click();

                        let deleteClickTimes = 0;
                        let deleteClickTimer = setInterval(() => {
                            deleteClickTimes++;
                            let isCatchErr = false;
                            try {
                                let clickStopAdBtn = frameDom.childNodes[1].childNodes[1].childNodes[9].childNodes[0].childNodes[1].childNodes[1].childNodes[0].childNodes[0].childNodes[1].childNodes[1].childNodes[0];
                                clickStopAdBtn.click();
                                console.log("获取到移除按钮,移除===>", clickStopAdBtn);
                            } catch (e) {
                                isCatchErr = true;
                                console.log("错误捕获");
                            }

                            if (deleteClickTimes > 100 || isCatchErr == false) {
                                clearInterval(deleteClickTimer);
                                console.log("===>", new DocumentTimeline().currentTime);
                            }
                        }, 100);
                    } catch (e) { console.log("2", e); }
                }
            }, 100);

            //close the card
            let checkCloseTimes = 0;
            let checkCloseTimer = setInterval(() => {
                checkCloseTimes++;

                var alreadyRemoveDisplay = "none";
                try {
                    alreadyRemoveDisplay = getComputedStyle(frameDom.childNodes[1].childNodes[1].childNodes[2].childNodes[0].childNodes[0].childNodes[1].childNodes[0]).display;
                } catch { }

                if (alreadyRemoveDisplay != "none" || checkCloseTimes > 200) {
                    console.log("close card");
                    clearInterval(checkCloseTimer);
                    //* close the card
                    let closeShitPanelBtn = frameDom.childNodes[1].childNodes[1].childNodes[2].childNodes[0].childNodes[0].childNodes[0].childNodes[2].childNodes[0].childNodes[0];
                    closeShitPanelBtn.click();
                    //* reset the backdrop, setTimeout didn't effect the use.
                    setTimeout(() => {
                        document.getElementsByTagName("tp-yt-iron-overlay-backdrop")[0].style.display = "";
                        console.log("reback display");
                    }, 1000);
                }
            }, 100);

            function setDisplay(str) {
                //* Set the shit backdrop display "none" or ""
                try { document.getElementsByTagName("tp-yt-iron-overlay-backdrop")[0].style.display = str; } catch { }

                //* Set the shit ad card display "none" or ""
                try { document.getElementById("iframe").parentNode.parentNode.style.display = str; } catch { }
            }
        }
    }
})();