Greasy Fork

来自缓存

Greasy Fork is available in English.

Twitter Video Popup Blocker (Enhanced)

Eliminates popup ads from Twitter video players - Generic version

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Twitter Video Popup Blocker (Enhanced)
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  Eliminates popup ads from Twitter video players - Generic version
// @author       You
// @match        https://twitter.com/*
// @match        https://x.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // 🎯 Enhanced multi-layered defense

    // Strategy 1: Broad popup interception
    function blockPopups() {
        const originalOpen = window.open;
        window.open = function(url, name, specs) {
            // Block any suspicious external URL (generic - anything not twitter/x)
            if (url && !url.startsWith('https://twitter.com') &&
                !url.startsWith('https://x.com') &&
                !url.startsWith('https://t.co') &&  // Twitter's shortener
                url !== '_self' && url !== '_blank' && url !== '_parent') {
                console.log('🚫 Blocked generic popup:', url);
                return null;
            }
            return originalOpen.call(this, url, name, specs);
        };

        // Also block location assignments that could cause navigation
        const originalAssign = location.assign;
        location.assign = function(url) {
            if (url && !url.startsWith('https://twitter.com') &&
                !url.startsWith('https://x.com') &&
                !url.startsWith('https://t.co')) {
                console.log('🚫 Blocked navigation:', url);
                return;
            }
            return originalAssign.call(this, url);
        };
    }

    // Strategy 2: Generic promotional link removal
    function removePromotionalElements() {
        // Generic selectors for "From [site]" links
        const genericSelectors = [
            // Text-based: Any link with "From " text inside video cards
            '[data-testid="card.wrapper"] a',
            '[data-testid="card.layoutLarge.media"] ~ a',
            '[data-testid="placementTracking"] ~ a'
        ];

        genericSelectors.forEach(selector => {
            document.querySelectorAll(selector).forEach(element => {
                const a = element.tagName === 'A' ? element : element.closest('a');
                if (a) {
                    const text = a.textContent.trim().toLowerCase();
                    const href = a.getAttribute('href') || '';

                    // Generic detection: "From " text + external target (super broad for any advertiser)
                    if ((text.startsWith('from ') || text.includes('from ')) &&
                        (a.hasAttribute('target') || a.rel.includes('noopener') || a.rel.includes('nofollow')) &&
                        !href.startsWith('https://twitter.com') &&
                        !href.startsWith('https://x.com') &&
                        !href.startsWith('https://t.co')) {

                        // Fallback: Strip href and remove rel/target to neuter the link
                        a.removeAttribute('href');
                        a.removeAttribute('target');
                        a.setAttribute('rel', '');
                        a.style.display = 'none';  // Hide it

                        console.log('🗑️ Neutered/Removed generic promo link:', text, href);

                        // If that fails, remove entirely
                        setTimeout(() => a.remove(), 0);
                    }
                }
            });
        });

        // Also target by class patterns (your dynamic example)
        const dynamicSelectors = [
            'a.css-146c3p1.r-bcqeeo.r-1ttztb7.r-qvutc0.r-37j5jr',
            'a.r-n6v787.r-1cwl3u0.r-16dba41.r-1loqt21'
        ];

        dynamicSelectors.forEach(selector => {
            document.querySelectorAll(selector).forEach(a => {
                const text = a.textContent.trim().toLowerCase();
                if (text.startsWith('from ') && a.closest('[data-testid="card.wrapper"]')) {
                    a.removeAttribute('href');
                    a.style.display = 'none';
                    setTimeout(() => a.remove(), 0);
                    console.log('🗑️ Removed dynamic class promo link:', text);
                }
            });
        });
    }

    // Strategy 3: Enhanced click prevention in video areas
    function interceptVideoClicks() {
        document.addEventListener('click', function(event) {
            const target = event.target;

            // Broader detection of video/promoted content areas
            const videoContainer = target.closest('[data-testid="videoPlayer"]') ||
                                 target.closest('[data-testid="videoComponent"]') ||
                                 target.closest('[data-testid="card.wrapper"]') ||
                                 target.closest('[data-testid="placementTracking"]') ||
                                 target.closest('[data-testid="card.layoutLarge.media"]');

            if (videoContainer) {
                // Always allow native video controls
                const isVideoControl = target.closest('button') ||
                                     target.closest('[role="slider"]') ||
                                     target.closest('video') ||
                                     target.tagName === 'VIDEO' ||
                                     target.closest('[data-testid="scrubber"]');

                if (!isVideoControl) {
                    // Check for any promotional links in the container (even hidden)
                    const promoLinks = videoContainer.querySelectorAll('a[target="_blank"], a[rel*="noopener"], a[href*="?spot_id="], a[href*="subid="]');

                    // Also check ancestor for "From " text links
                    const ancestorPromo = videoContainer.closest('[data-testid="card.wrapper"]')?.querySelector('a')?.textContent?.trim().toLowerCase().startsWith('from ');

                    if (promoLinks.length > 0 || ancestorPromo) {
                        console.log('🛡️ Blocked click on promo video area - links detected:', promoLinks.length);
                        event.preventDefault();
                        event.stopPropagation();
                        event.stopImmediatePropagation();
                        return false;
                    }

                    // Generic block: If the container has any external href that would trigger popup
                    const containerLink = videoContainer.closest('a');
                    if (containerLink) {
                        const href = containerLink.getAttribute('href') || '';
                        if (href && !href.startsWith('https://twitter.com') &&
                            !href.startsWith('https://x.com') &&
                            !href.startsWith('https://t.co') &&
                            (href.includes('=') || href.includes('?') || href.match(/https?:\/\/[^\/]+/))) {
                            console.log('🛡️ Blocked external video container click:', href);
                            event.preventDefault();
                            event.stopPropagation();
                            event.stopImmediatePropagation();
                            containerLink.removeAttribute('href');  // Disable the link
                            return false;
                        }
                    }
                }
            }
        }, true);  // Capture phase for early intervention
    }

    // Strategy 4: Supercharged dynamic handling
    function setupObservers() {
        // Immediate setup
        blockPopups();
        removePromotionalElements();
        interceptVideoClicks();

        // DOM ready
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', () => {
                setTimeout(removePromotionalElements, 50);  // Quick check after DOM loads
            });
        }

        // Window loaded (catches lazy-loaded content)
        window.addEventListener('load', () => {
            setTimeout(removePromotionalElements, 100);
        });

        // Enhanced MutationObserver - more sensitive to video/promoted additions
        const observer = new MutationObserver((mutations) => {
            let shouldCheck = false;

            mutations.forEach((mutation) => {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === 1) {  // Element only
                            const el = node.nodeType === 1 ? node : node.querySelector?.('[data-testid="card.wrapper"], [data-testid="videoPlayer"]');
                            if (el || node.matches('[data-testid="card.wrapper"], [data-testid="videoPlayer"], [data-testid="placementTracking"]')) {
                                shouldCheck = true;
                            }
                        }
                    });
                }
            });

            if (shouldCheck) {
                // Immediate and delayed checks for async rendering
                removePromotionalElements();
                setTimeout(removePromotionalElements, 100);
                setTimeout(removePromotionalElements, 500);  // For slower loads
            }
        });

        observer.observe(document.body || document.documentElement, {
            childList: true,
            subtree: true
        });

        // More frequent periodic cleanup (every 1s for aggressive ad hunting)
        setInterval(() => {
            removePromotionalElements();
        }, 1000);

        // Also observe for attribute changes (e.g., href added dynamically)
        const attrObserver = new MutationObserver(() => {
            removePromotionalElements();
        });
        attrObserver.observe(document.body || document.documentElement, {
            attributes: true,
            attributeFilter: ['href', 'target', 'rel'],
            subtree: true
        });
    }

    // 🚀 Fire it up
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', setupObservers);
    } else {
        setupObservers();
    }

    console.log('✅ Enhanced Twitter Video Popup Blocker v2.0 activated! Ready for any ad site.');
})();