Greasy Fork

Greasy Fork is available in English.

RafBlocker

Aggressively blocks YouTube ads and attempts to suppress the AdBlock warning by instantly hiding it and managing the player state.

当前为 2025-10-23 提交的版本,查看 最新版本

// ==UserScript==
// @name         RafBlocker
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Aggressively blocks YouTube ads and attempts to suppress the AdBlock warning by instantly hiding it and managing the player state.
// @author       Raf
// @match        *://www.youtube.com/*
// @grant        none
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

/*
 * MIT License
 *
 * Copyright (c) 2025 Raf (or your chosen name)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

(function() {
    'use strict';

    // --- Selectors ---
    const AD_CONTAINER_SELECTOR = '.ad-container'; // Common pre/mid-roll ad container
    const VIDEO_AD_SELECTOR = '.video-ads, .ytp-ad-module'; // Video ad elements
    const SKIP_BUTTON_SELECTOR = '.ytp-ad-skip-button, .ytp-skip-ad-button'; // The skip ad button
    const AD_OVERLAY_SELECTOR = '.ytp-player-content-container .ytp-ce-element, .ytp-ad-overlay-container, .ytp-ad-image-overlay'; // Overlays and banners

    // !!! NEW SELECTORS FOR AD-BLOCK WARNING !!!
    const WARNING_MODAL_SELECTOR = 'ytd-popup-container, #popup, .yt-spec-general-modal';
    const DISMISS_BUTTON_SELECTOR = 'ytd-button-renderer button.ytd-popup-container, ytd-button-renderer button.yt-spec-general-modal';

    // --- Helper Functions ---

    // Function to remove elements from the DOM
    function removeElement(selector) {
        document.querySelectorAll(selector).forEach(element => {
            if (element) {
                element.remove();
            }
        });
    }

    // Function to click the skip ad button or force skip non-skippable ads
    function skipVideoAd() {
        const skipButton = document.querySelector(SKIP_BUTTON_SELECTOR);
        if (skipButton) {
            skipButton.click();
            return true;
        }

        const videoPlayer = document.querySelector('video');
        const adShowing = document.querySelector('.ad-showing');

        // Check if an ad is clearly marked as playing and try to jump to the end
        if (videoPlayer && adShowing) {
            // Attempt to force the video to the end if an ad is showing
            videoPlayer.currentTime = videoPlayer.duration;
            return true;
        }

        return false;
    }

    // --- Ad Block Warning Suppression ---
    function suppressAdBlockWarning() {
        // 1. Instantly hide the modal/popup using CSS to prevent it from appearing
        const style = document.createElement('style');
        style.type = 'text/css';
        // Hide the main warning container and the full-screen backdrop/modal
        style.innerHTML = `
            ${WARNING_MODAL_SELECTOR} {
                display: none !important;
                visibility: hidden !important;
            }
            /* Target the specific container for the backdrop */
            tp-yt-paper-dialog {
                display: none !important;
                visibility: hidden !important;
            }
            /* Hide the main content block that appears disabled/greyed out */
            body {
                overflow: auto !important; /* Restore scrolling */
            }
        `;
        document.head.appendChild(style);

        // 2. Try to find and click a 'Dismiss' or 'Close' button if the modal is briefly visible
        document.querySelectorAll(DISMISS_BUTTON_SELECTOR).forEach(button => {
            // Be cautious, only click if it's the dismiss type
            if (button.innerText.toUpperCase().includes('DISMISS') || button.innerText.toUpperCase().includes('CLOSE')) {
                button.click();
            }
        });

        // 3. Prevent the video from pausing due to the warning (experimental)
        const videoPlayer = document.querySelector('video');
        if (videoPlayer && videoPlayer.paused) {
            videoPlayer.play().catch(e => {}); // Attempt to unpause, but handle potential errors
        }
    }

    // --- Main Blocking Logic ---
    function blockAdsAndWarning() {
        // 1. Run the Warning Suppression first to handle any pop-ups
        suppressAdBlockWarning();

        // 2. Remove video ad and banner containers
        removeElement(AD_CONTAINER_SELECTOR);
        removeElement(VIDEO_AD_SELECTOR);
        removeElement(AD_OVERLAY_SELECTOR);

        // 3. Try to click the skip ad button or force-skip
        skipVideoAd();
    }

    // --- Execution ---

    // Use a MutationObserver to watch for changes in the DOM
    const observer = new MutationObserver((mutations, obs) => {
        // Only run the logic if YouTube is open (or optimize for video page)
        if (window.location.pathname.startsWith('/watch') || window.location.pathname === '/') {
            blockAdsAndWarning();
        }
    });

    // Start observing the body for configuration changes and subtree modifications
    observer.observe(document.body, { childList: true, subtree: true });

    // Also run blockAdsAndWarning on an interval for a quick check, especially useful for initial load and overlays
    setInterval(blockAdsAndWarning, 500); // Check every 500 milliseconds

})();