Youtube-Adblock v4

Youtube Adblock v4

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Youtube-Adblock v4
// @namespace    http://tampermonkey.net/
// @version      2025-09-21
// @description  Youtube Adblock v4
// @author       Anton
// @match        *://*.youtube.com/*
// @exclude      *://accounts.youtube.com/*
// @exclude      *://www.youtube.com/live_chat_replay*
// @exclude      *://www.youtube.com/persist_identity*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=YouTube.com
// @grant        none
// @license MIT
// ==/UserScript==

// Array of CSS selectors for different types of YouTube ads to block
var cssArrObject = [
    `#masthead-ad`,                                                                    // Top banner ads
    `ytd-rich-item-renderer.style-scope.ytd-rich-grid-row #content:has(.ytd-display-ad-renderer)`, // Rich grid display ads
    `.video-ads.ytp-ad-module`,                                                       // Video overlay ads
    `tp-yt-paper-dialog:has(yt-mealbar-promo-renderer)`,                             // Mealbar promo dialogs
    `ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-ads"]`, // Engagement panel ads
    `#related #player-ads`,                                                           // Related video ads
    `#related ytd-ad-slot-renderer`,                                                 // Related ad slots
    `ytd-ad-slot-renderer`,                                                          // General ad slot renderers
    `yt-mealbar-promo-renderer`,                                                     // Mealbar promo renderers
    `ytd-popup-container:has(a[href="/premium"])`,                                   // Premium subscription popups
    `ad-slot-renderer`,                                                              // Generic ad slot renderers
    `ytm-companion-ad-renderer`,                                                     // Companion ads (mobile)
    `#related #-ad-`,                                                                // Related section ads
];

(function() {
    'use strict'; // Enable strict mode for better error handling
    window.dev = false; // Development mode flag (currently disabled)


    function removeNonVideoAds(arry) {
        // Convert each selector to a CSS rule that hides the element
        arry.forEach((selector, index) => {
            arry[index] = `${selector}{display:none!important}`; // Force hide with !important
        });

        // Find and remove YouTube Premium subscription popup containers
        const premiumContainers = [...document.querySelectorAll(`ytd-popup-container`)];
        const matchingContainers = premiumContainers.filter(container =>
            container.querySelector(`a[href="/premium"]`) // Look for premium subscription links
        );

        // Remove all premium popup containers if found
        if (matchingContainers.length > 0) {
            matchingContainers.forEach(container => container.remove());
        }

        // Handle overlay backdrops that might block interaction
        const backdrops = document.querySelectorAll(`tp-yt-iron-overlay-backdrop`);
        const targetBackdrop = Array.from(backdrops).find(
            (backdrop) => backdrop.style.zIndex === `2201` // Specific z-index for premium overlays
        );

        // Remove the target backdrop if found
        if (targetBackdrop) {
            targetBackdrop.className = ``; // Clear CSS classes
            targetBackdrop.removeAttribute(`opened`); // Remove opened attribute
        }
        
        // Create and inject CSS style element to hide ads
        let style = document.createElement(`style`);
        (document.head || document.body).appendChild(style); // Add to document head or body
        style.appendChild(document.createTextNode(arry.join(` `))); // Join all CSS rules with spaces
    }

    /**
     * Skips video ads by fast-forwarding to the end
     * @param {HTMLVideoElement} video - The video element showing the ad
     */
    function skipAd(video) {
        // Look for various ad skip button indicators
        const adIndicator = document.querySelector(
            '.ytp-ad-skip-button, .ytp-skip-ad-button, .ytp-ad-skip-button-modern, ' +
            '.video-ads.ytp-ad-module .ytp-ad-player-overlay, .ytp-ad-button-icon'
        );

        // Only skip ads if indicator is found and not on mobile YouTube
        if (adIndicator && !window.location.href.includes('https://m.youtube.com/')) {
            video.muted = true; // Mute the ad video
            video.currentTime = video.duration - 0.1; // Jump to near the end (0.1 seconds before finish)
        }
    }

    function removeAdblockWarning() {
        // Check for adblock warning every random interval (0-0.5 seconds)
        var warningInterval = setInterval(function() {
            // Check for adblock warning popup elements
            var popupExists = document.getElementsByClassName("style-scope ytd-popup-container").length > 0;
            var dismissButton = document.getElementById("dismiss-button"); // Dismiss button in popup
            var divider = document.getElementById("divider"); // Divider element in popup
            
            // If all warning elements are present, handle the popup
            if (popupExists && dismissButton && divider) {
                // Wait random time (0-3 seconds) before closing to avoid detection
                setTimeout(function() {
                    dismissButton.click(); // Click dismiss button to close warning
                    document.getElementsByClassName("ytp-play-button ytp-button")[0].click(); // Resume video playback
                    console.log("banner closed"); // Log successful closure
                    clearInterval(warningInterval); // Stop monitoring since warning is closed
                }, Math.random() * 3); // Random delay between 0-3 seconds
            }
        }, Math.random() * 0.5); // Random interval between 0-0.5 seconds
    }
    
    // Main execution loop - runs every 500ms to continuously monitor and block ads
    setInterval(() => {
        // Only run when page is fully loaded
        if (document.readyState !== 'loading') {
            // Save current URL to localStorage when leaving page (for potential resume functionality)
            window.addEventListener('beforeunload', () => {
                window.localStorage.setItem('lastUrl', window.location.href);
            }, { once: true }); // Only add listener once
            
            // Remove all non-video ads using CSS injection
            removeNonVideoAds(cssArrObject);

            // Monitor and remove adblock warning popups
            removeAdblockWarning();

            // Get video elements for ad skipping and player status monitoring
            var adsVideo = document.querySelector('.ad-showing video'); // Video element showing ads
            var mainVideo = document.querySelector('video'); // Main video player element
            
            // Monitor main video player status and handle auto-play functionality
            if(mainVideo) {
                // Get current player status information
                var playerStatus = {
                    currentTime: mainVideo.currentTime,  // Current playback position in seconds
                    isPaused: mainVideo.paused,          // Whether video is paused (true/false)
                    speed: mainVideo.playbackRate        // Current playback speed (1.0 = normal)
                };
                
                // Uncomment the line below to log player status to console for debugging
                // console.log('YouTube Player Status:', playerStatus);
                
                // Auto-play video if it's paused and at the beginning (5 seconds or less)
                if(playerStatus.currentTime <= 5 && playerStatus.isPaused == true){
                    mainVideo.play().catch(error => {
                        console.error('Failed to play video:', error); // Log play errors
                    });
                }
            }
            
            // Skip any video ads that are currently playing
            skipAd(adsVideo);
        }
    }, 500); // Run every 500ms for real-time ad blocking

})();