Greasy Fork

来自缓存

Greasy Fork is available in English.

RafBlocker

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

// ==UserScript==
// @name         RafBlocker
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Aggressively blocks YouTube ads and attempts to suppress the AdBlock warning by forcing the player state and instantly hiding the modal.
// @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';

    // --- Configuration and Selectors ---
    const AD_CONTAINER_SELECTOR = '.ad-container, .video-ads, .ytp-ad-module';
    const SKIP_BUTTON_SELECTOR = '.ytp-ad-skip-button, .ytp-skip-ad-button';
    const AD_OVERLAY_SELECTOR = '.ytp-player-content-container .ytp-ce-element, .ytp-ad-overlay-container, .ytp-ad-image-overlay';

    // Aggressive selectors for the warning modal and backdrop
    const WARNING_MODAL_SELECTOR = 'ytd-popup-container, #popup, .yt-spec-general-modal, tp-yt-paper-dialog';
    const DISMISS_BUTTON_SELECTOR = 'ytd-button-renderer button.ytd-popup-container, ytd-button-renderer button.yt-spec-general-modal';

    // --- Core Functions ---

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

    // Function to skip the video ad (works on pre-roll/mid-roll)
    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) {
            videoPlayer.currentTime = videoPlayer.duration;
            return true;
        }

        return false;
    }

    // --- Ad Block Warning Evasion (The Core Fix) ---
    function evadeAdDetection() {
        // 1. Aggressively Hide the Modal and Backdrop via CSS
        let style = document.getElementById('RafBlockerStyle');
        if (!style) {
            style = document.createElement('style');
            style.id = 'RafBlockerStyle';
            style.type = 'text/css';
            document.head.appendChild(style);
        }

        // Keep the modal hidden and restore scrolling
        style.innerHTML = `
            ${WARNING_MODAL_SELECTOR} {
                display: none !important;
                visibility: hidden !important;
            }
            body {
                overflow: auto !important;
            }
        `;

        // 2. Click any hidden dismiss buttons just in case
        document.querySelectorAll(DISMISS_BUTTON_SELECTOR).forEach(button => {
            if (button.innerText.toUpperCase().includes('DISMISS') || button.innerText.toUpperCase().includes('CLOSE')) {
                button.click();
            }
        });

        // 3. Forcing Player State (Most important part for persistent warnings)
        // This attempts to trick YouTube's internal ad-check functions.
        if (window.ytplayer) {
            // Force the player to believe the ad has timed out or is already skipped
            if (window.ytplayer.config.args) {
                window.ytplayer.config.args.advideo = 0; // Standard ad flag
                window.ytplayer.config.args.is_ad = false; // Is Ad flag
                window.ytplayer.config.args.ad_flags = 0; // Ad flags
            }

            // Also check for the global Player object (if available)
            const player = document.querySelector('#movie_player');
            if (player && player.getPlayerState) {
                // If the player is paused (state 2) due to the warning, try to play it (state 1 is playing)
                if (player.getPlayerState() === 2) {
                    player.playVideo();
                }
            }
        }
    }

    // --- Main Blocking Loop ---
    function blockAdsAndWarning() {
        // Always run evasion first to catch the warning instantly
        evadeAdDetection();

        // Standard ad removal
        removeElement(AD_CONTAINER_SELECTOR);
        removeElement(AD_OVERLAY_SELECTOR);

        // Attempt to skip the video ad
        skipVideoAd();
    }

    // Use a MutationObserver for dynamic content loading
    const observer = new MutationObserver((mutations, obs) => {
        // Only run the logic if we're on a YouTube page
        blockAdsAndWarning();
    });

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

    // Also run blockAdsAndWarning on a rapid interval for aggressive ad/warning removal
    setInterval(blockAdsAndWarning, 100); // Check every 100 milliseconds for maximum speed

})();