SHEIN Ad Annihilator by HYPERR.

Blocks ads, popups, gambling games, and giveaways on SHEIN

// ==UserScript==
// @name         SHEIN Ad Annihilator by HYPERR.
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Blocks ads, popups, gambling games, and giveaways on SHEIN
// @author       HYPERR.
// @license MIT
// @match        *://*.shein.com/*
// @match        *://*.shein.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // Block known ad/tracking domains
    const blockedPatterns = [
        '*://adservice.google.com/*',
        '*://*.adsense.com/*',
        '*://*.doubleclick.net/*',
        '*://*.facebook.com/tr/*',
        '*://*.snapchat.com/*',
        '*://*.tiktok.com/api/ad/*',
        '*://*.shein.com/*/ad_*',
        '*://*.shein.com/*/ads/*',
        '*://*.shein.com/*/popup*',
        '*://*.shein.com/*/game*',
        '*://*.shein.com/*/giveaway*',
        '*://*.shein.com/*/promotion*',
        '*://*.shein.com/*/lottery*'
    ];

    // Block network requests
    const originalOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function() {
        if (blockedPatterns.some(pattern => matchesPattern(arguments[1], pattern))) {
            return;
        }
        originalOpen.apply(this, arguments);
    };

    const originalFetch = window.fetch;
    window.fetch = function() {
        if (blockedPatterns.some(pattern => matchesPattern(arguments[0], pattern))) {
            return Promise.reject(new Error('Blocked by SHEIN Ad Annihilator'));
        }
        return originalFetch.apply(this, arguments);
    };

    function matchesPattern(url, pattern) {
        const regex = pattern
            .replace(/\*/g, '.*')
            .replace(/\//g, '\\/');
        return new RegExp(`^${regex}$`).test(url);
    }

    // DOM cleanup function
    const cleanPage = () => {
        // Remove ad elements
        const adSelectors = [
            // Popups and overlays
            'div[class*="popup"]',
            'div[class*="modal"]',
            'div[class*="overlay"]',
            'div[class*="mask"]',
            'div[class*="dialog"]',
            'div[class*="notification"]',
            'div[class*="prompt"]',
            
            // Games and gambling
            '[class*="game"]',
            '[class*="casino"]',
            '[class*="slot"]',
            '[class*="gambling"]',
            '[class*="lottery"]',
            '[class*="spin"]',
            '[class*="scratch"]',
            '[class*="roulette"]',
            
            // Giveaways and promotions
            '[class*="giveaway"]',
            '[class*="promotion"]',
            '[class*="coupon"]',
            '[class*="reward"]',
            '[class*="deal"]',
            '[class*="special-offer"]',
            
            // Tracking elements
            'iframe[src*="ad"]',
            'div[class*="tracking"]',
            'div[class*="analytics"]',
            'div[id*="google_ads"]',
            'div[class*="ad_"]'
        ];

        adSelectors.forEach(selector => {
            document.querySelectorAll(selector).forEach(element => {
                if (element.offsetHeight > 0 || element.offsetWidth > 0) {
                    element.remove();
                }
            });
        });

        // Clean body classes
        document.body.classList.remove('no-scroll', 'popup-open', 'modal-open');
        document.body.style.overflow = 'auto';
        document.body.style.position = 'static';
    };

    // Run cleaner on DOM changes
    const observer = new MutationObserver(cleanPage);
    observer.observe(document, {
        childList: true,
        subtree: true,
        attributes: true,
        characterData: true
    });

    // Initial cleanup
    window.addEventListener('DOMContentLoaded', () => {
        cleanPage();
        setInterval(cleanPage, 2000); // Periodic cleanup
    });

    // Block scroll locking
    Object.defineProperty(document.body.style, 'overflow', {
        set: () => 'auto',
        configurable: true
    });
})();