广告终结者

一个手机端via浏览器能用的强大的广告拦截器

目前为 2025-05-17 提交的版本。查看 最新版本

// ==UserScript==
// @name         广告终结者
// @namespace    http://tampermonkey.net/
// @version      3.9.6
// @description  一个手机端via浏览器能用的强大的广告拦截器
// @match        *://*/*
// @license      MIT
// @grant        unsafeWindow
// @grant        GM_registerMenuCommand
// @grant        GM_notification
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_getResourceText
// @grant        GM_addStyle
// @grant        GM_openInTab
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    const globalHooks = {
        observers: new Set(),
        originalFunctions: {
            MutationObserver: window.MutationObserver,
            appendChild: Node.prototype.appendChild,
            createElement: document.createElement
        }
    };

    const createSafeObserver = () => {
        const originalMutationObserver = globalHooks.originalFunctions.MutationObserver;

        class SafeMutationObserver extends originalMutationObserver {
            constructor(callback) {
                super((mutations, observer) => {
                    if (CONFIG.modules.main) {
                        callback(mutations, observer);
                    }
                });
                globalHooks.observers.add(this);
            }

            observe(target, options) {
                if (!CONFIG.modules.main) return;
                const sanitizedOptions = {
                    childList: options.childList ? true : false,
                    attributes: options.attributes ?
                        [...(options.attributeFilter || []), 'data-ad-', 'src', 'id', 'style', 'class'].some(f => f) :
                        false,
                    subtree: true,
                    characterData: false
                };
                return super.observe(target, Object.assign({}, options, sanitizedOptions));
            }

            disconnect() {
                globalHooks.observers.delete(this);
                super.disconnect();
            }
        }

        return SafeMutationObserver;
    };

    window.MutationObserver = createSafeObserver();

    const HOSTNAME = location.hostname.replace(/\./g, '\\.');

    const REGEX = {
        dynamicId: /^(?:([0-9a-f]{4}-?){4,}|[0-9a-f]{16,}|[\dA-F-]{18,}|[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12})$/i,
        jsAdPattern: /(?:window\.open|document\.write|createElement\(['"]script['"]|location\.replace|setTimeout\s*\([^)]*?\b(?:window\.open|document\.write)|eval\s*\(|new\s+Function\s*\(|appendChild\s*\(.*?\bscript\b|on(?:click|load)\s*=\s*['"]?\s*(?:window\.open))/i,
        adAttributes: /(推广|广告|gg|sponsor|推荐|guanggao|syad|bfad|弹窗|悬浮|葡京|banner|pop(?:up|under)|track(?:ing)?)(?:$|[_-])/i,
        thirdParty: new RegExp(`^(https?:\\/\\/(.*\\.)?${HOSTNAME}(\\/|$)|data:|about:blank)`, 'i'),
        obfuscationPatterns: [
            { type: '字符串混淆属性访问', pattern: /\\x73\\x72\\x63\\s*=/i, riskLevel: 3 },
            { type: '数学对象长属性访问', pattern: /Math\[\s*["']\w{5,}["']\s*\]/im, riskLevel: 2 },
            { type: '十六进制/Unicode转义序列', pattern: /(?:\\x[0-9a-f]{2}(?:\\x[0-9a-f]{2}){5,}|\\u[0-9a-f]{4}(?:\\u[0-9a-f]{4}){3,})/gi, riskLevel: 3 },
            { type: '数组数值操作', pattern: /\[(?:0x[0-9a-f]+|\d+),?(?:0x[0x][0-9a-f]+|\d+)\]\.(?:join|reverse|map)/i, riskLevel: 2 },
            { type: '动态代码执行', pattern: /(eval|(?:new\s+Function\s*\(\s*(['"])\s*)\2|set(?:Timeout|Interval|Immediate)\s*\(\s*function\s*\(\)\s*\{)/i, riskLevel: 4 },
            { type: '文档对象长属性访问', pattern: /(?:document|window)\[\s*["']\w{5,}["']\s*\]/im, riskLevel: 3 },
            { type: '短变量名长字符串赋值', pattern: /\b[a-z\d]{1,3}\s*=\s*["']\w{16,}["']/gi, riskLevel: 2 },
            { type: '可疑变量初始化', pattern: /(var|let|const)\s+([a-z\d]{2,4})\s*=\s*(?:\d{8,}|"(?:[0-9a-f]{16,}|[\w+/=]{20,})")/gi, riskLevel: 3 },
            { type: '多重属性混淆', pattern: /(?:'src'|"data-rc")\.forEach\(function\(a\)\{this\.setAttribute\(a,/im, riskLevel: 4 },
            { type: '定时器混淆链', pattern: /setTimeout\(function\(\)\{setInterval\(function\(\)\{new\s+Function\(.*?\)/gim, riskLevel: 5 },
            { type: '编码payload执行', pattern: /(?:eval\(\s*atob\(\s*["'][A-Za-z0-9+/=]{40,}["']\s*\)|eval\(\s*decodeURIComponent\(\s*escape\(\s*atob\(\s*["'][A-Za-z0-9+/=]{40,}["']\s*\)\s*\)\s*\))/gi, riskLevel: 5 },
            { type: '长Base64字符串', pattern: /[A-Za-z0-9+/=]{60,}/gi, riskLevel: 3 },
            { type: '多级属性访问', pattern: /window\[\w{5,}\]\[\w{5,}\]\[\w{5,}\]/gim, riskLevel: 3 },
            { type: '异常函数调用链', pattern: /function\s+\w{1,3}\(\)\{return\s+\w{1,3}\(\)\.call\(this\)\}\(\)\.apply\(window\)/gim, riskLevel: 4 },
            { type: '异常事件监听', pattern: /addEventListener\s*\(["']click["'],\s*function\s*\(\)\{[^}]*eval\s*\(/gim, riskLevel: 4 },
            { type: '环境检测代码', pattern: /navigator\.\w+\s*===?\s*undefined/g, riskLevel: 5 },
            { type: '时间戳混淆', pattern: /0x[a-f0-9]{8}(?:\+0x[a-f0-9]{8}){3,}/g, riskLevel: 3 },
            { type: '反格式化字符串', pattern: /%[0-9a-f]{2}%[0-9a-f]{2}%[0-9a-f]{2}/g, riskLevel: 3 }
        ],
    };

    const DEFAULT_MODULES = {
        main: false,
        dynamicSystem: false,
        layoutSystem: false,
        mergedMediaSystem: false,
        thirdPartyBlock: false,
        specialUA: true
    };

    const DEFAULT_CSP_RULES = [
        { id: 1, name: '仅允许同源脚本', rule: "script-src 'self'", enabled: true },
        { id: 2, name: '禁止内联脚本', rule: "script-src 'unsafe-inline'", enabled: false },
        { id: 3, name: '禁止eval执行', rule: "script-src 'unsafe-eval'", enabled: false },
        { id: 4, name: '阻止外部样式加载', rule: "style-src 'self'", enabled: false },
        { id: 5, name: '阻止内联样式执行', rule: "style-src 'unsafe-inline'", enabled: false },
        { id: 6, name: '阻止外部图片加载', rule: "img-src 'self'", enabled: true },
        { id: 7, name: '禁止所有框架加载', rule: "frame-src 'none'", enabled: false },
        { id: 8, name: '禁止媒体资源加载', rule: "media-src 'none'", enabled: false },
        { id: 9, name: '禁止对象嵌入', rule: "object-src 'none'", enabled: false }
    ];

    const safeInit = () => {
        globalHooks.observers.forEach(obs => obs.disconnect());
        globalHooks.observers.clear();

        if (globalHooks.originalFunctions.MutationObserver) {
            window.MutationObserver = globalHooks.originalFunctions.MutationObserver;
        }
        if (globalHooks.originalFunctions.appendChild) {
            Node.prototype.appendChild = globalHooks.originalFunctions.appendChild;
        }
        if (globalHooks.originalFunctions.createElement) {
            document.createElement = globalHooks.originalFunctions.createElement;
        }

        if (CONFIG.modules.main) {
            window.MutationObserver = createSafeObserver();
            UIController.init();
            ModuleManager.init();
            Processor.collectAds();
        }
    };

    const CONFIG = {
        modules: { ...DEFAULT_MODULES },
        protectionRules: {
            dynamicIdLength: 32,
            zIndexThreshold: 500
        },
        csp: {
            enabled: false,
            rules: DEFAULT_CSP_RULES.map(rule => ({ ...rule }))
        },
        mobileOptimizations: {
            lazyLoadImages: true,
            removeImagePlaceholders: true
        },
        moduleNames: {
            dynamicSystem: '动态检测系统',
            layoutSystem: '布局检测系统',
            mergedMediaSystem: '图片广告移除',
            thirdPartyBlock: '第三方拦截',
            specialUA: '添加特殊UA'
        },
        modulePriority: [
            'thirdPartyBlock',
            'specialUA',
            'dynamicSystem',
            'mergedMediaSystem',
            'layoutSystem',
        ],
        performance: {
            highRiskModules: ['thirdPartyBlock', 'dynamicSystem'],
            visibleAreaPriority: true,
            styleCacheTimeout: 600000,
            mutationProcessLimit: 40,
            mutationProcessTimeLimit: 10,
            idleCallbackTimeout: 2500,
            throttleScrollDelay: 200,
            debounceMutationDelay: 300,
            longTaskThreshold: 500,
            degradeThreshold: 5
        },
        originalUA: {
            userAgent: navigator.userAgent,
            platform: navigator.platform
        },
        whitelist: {}
    };

    const Utils = {
        throttle(fn, delay) {
            let last = 0, timer = null;
            return function(...args) {
                const now = Date.now();
                if (now - last >= delay) {
                    fn.apply(this, args);
                    last = now;
                } else {
                    clearTimeout(timer);
                    timer = setTimeout(() => {
                        fn.apply(this, args);
                        last = now;
                    }, delay - (now - last));
                }
            };
        },

        debounce(fn, delay) {
            let timer = null;
            return function(...args) {
                clearTimeout(timer);
                timer = setTimeout(() => {
                    try {
                        fn.apply(this, args);
                    } catch(e) {
                        Logs.add('error', this, {
                            type: 'debounceError',
                            detail: e.message
                        });
                    }
                }, delay);
            }
        }
    };

    const SharedUtils = {
        generateElementPattern(element) {
            try {
                if (!element || !(element instanceof Element)) return '';
                let pattern = element.tagName || '';
                if (element.id) pattern += `#${element.id}`;
                if (element.className) {
                    const firstClass = element.className.split(/\s+/)[0];
                    if (firstClass) pattern += `.${firstClass}`;
                }
                return pattern;
            } catch(e) {
                console.error('生成元素模式失败:', e);
                return '';
            }
        },
        getElementContent(element) {
            try {
                if (!element || !(element instanceof Element)) return '[无效元素]';

                if (element.tagName === 'SCRIPT') {
                    const src = element.src;
                    const content = element.textContent;
                    if (src) return `SCRIPT_SRC: ${src.slice(0, 200)}` + (src.length > 200 ? '...' : '');
                    if (content) return `SCRIPT_CONTENT: ${content.replace(/\s+/g, ' ').slice(0, 200)}` + (content.length > 200 ? '...' : '');
                    return 'SCRIPT_EMPTY';
                }
                 if (element.tagName === 'IFRAME') {
                    const src = element.src;
                     if (src) return `IFRAME_SRC: ${src.slice(0, 200)}` + (src.length > 200 ? '...' : '');
                     return 'IFRAME_EMPTY';
                 }
                 if (element.tagName === 'IMG') {
                    const src = element.src || element.dataset.src;
                    if (src) return `IMG_SRC: ${src.slice(0, 200)}` + (src.length > 200 ? '...' : '');
                    return 'IMG_EMPTY';
                 }

                const outerHTML = element.outerHTML;
                if (outerHTML) {
                   return outerHTML.replace(/\s+/g, ' ')
                       .replace(/<!--.*?-->/g, '')
                       .slice(0, 200) +
                       (outerHTML.length > 200 ? '...' : '');
                }
                return '[无法获取内容]';

            } catch(e) {
                return '[安全限制无法获取内容]';
            }
        }
    };

    const Logs = {
        logs: [],
        processedElements: new WeakSet(),
        maxLogs: 30,
        add(moduleKey, element, reason) {
            if (!(element instanceof Element) || this.processedElements.has(element)) return;

            const currentDomain = new URL(location.href).hostname;
            const elementPattern = SharedUtils.generateElementPattern(element);

            const getElementInfoForLog = (el) => {
                try {
                    const attrs = {};
                    const attributeNames = ['id', 'class', 'src', 'href', 'data-src', 'style'];
                     for (const name of attributeNames) {
                         if (el.hasAttribute(name)) {
                             attrs[name] = el.getAttribute(name).slice(0, 100) + (el.getAttribute(name).length > 100 ? '...' : '');
                         }
                     }
                    return {
                        tag: el.tagName || '未知标签',
                        id: el.id ? `#${el.id}` : '',
                        class: el.className ? `.${el.className.split(/\s+/).join('.')}` : '',
                        src: el.src || el.href || el.dataset.src || '',
                        attributes: attrs
                    };
                } catch(e) {
                    return { error: '元素解析失败' };
                }
            };

            const elementInfo = getElementInfoForLog(element);
            const content = SharedUtils.getElementContent(element);

            this.processedElements.add(element);
            this.logs.push({
                module: CONFIG.moduleNames[moduleKey] || moduleKey,
                elementSummary: `${elementInfo.tag}${elementInfo.id}${elementInfo.class}`,
                content: content,
                context: {
                    src: (elementInfo.src || '').slice(0, 200),
                    attributes: elementInfo.attributes || {},
                    parentTag: element.parentElement ? element.parentElement.tagName : '无父节点',
                    domain: currentDomain
                },
                reason: {
                    type: reason.type || '自动拦截',
                    detail: (reason.detail || '').slice(0, 150),
                    pattern: reason.regex ? reason.regex.map(r => r.source.slice(0, 100)) : []
                },
                timestamp: Date.now(),
                elementPattern: elementPattern
            });

            if (this.logs.length > this.maxLogs) {
                this.logs = this.logs.slice(this.logs.length - this.maxLogs);
            }
        },
        clear() {
            this.logs = [];
            this.processedElements = new WeakSet();
            GM_notification('日志已清空');
             console.log('广告拦截日志已清空');
        },
        showInAlert() {
            const logText = this.logs.map((log, index) => {
                const parts = [];
                if (log.reason && log.reason.type) parts.push(`类型: ${log.reason.type}`);
                if (log.reason && log.reason.detail) parts.push(`详细: ${log.reason.detail}`);
                if (log.reason && log.reason.pattern && log.reason.pattern.length) parts.push(`匹配规则: ${log.reason.pattern.join(', ')}`);

                const contextParts = [];
                if (log.context && log.context.src) contextParts.push(`来源: ${log.context.src}`);
                if (log.context && log.context.parentTag) contextParts.push(`父节点: ${log.context.parentTag}`);
                const contextString = contextParts.length > 0 ? `上下文: ${contextParts.join(' ')}` : '';

                return [
                    `序号: ${index + 1}`,
                    `模块: ${log.module}`,
                    `元素: ${log.elementSummary}`,
                    `内容: ${log.content}`,
                    contextString,
                    ...parts
                ].filter(line => line.trim() !== '').join('\n');
            }).join('\n\n');

            const promptMessage = `广告拦截日志(最近${this.logs.length}条):\n\n${logText || '暂无日志'}\n\n请输入序号将该项内容添加到白名单,或输入 0 清空当前域名的白名单:`;
            const input = prompt(promptMessage, "");

            if (input === null) return;

            if (input.trim() === "0") {
                Whitelist.clearCurrentDomain();
                GM_notification('白名单已清空', `当前域名 (${location.hostname}) 的白名单已清空`);
                location.reload();
            } else {
                const index = parseInt(input, 10) - 1;
                if (index >= 0 && index < this.logs.length) {
                    const logEntry = this.logs[index];
                    const contentToAdd = logEntry.content;
                    if (contentToAdd && contentToAdd.trim() !== '[无效元素]' && contentToAdd.trim() !== '[无法获取内容]' && !contentToAdd.includes('[安全限制无法获取内容]')) {
                         Whitelist.add(location.hostname, contentToAdd);
                         GM_notification('已添加到白名单', `内容 "${contentToAdd.slice(0, 50)}..." 已添加到白名单`);
                         location.reload();
                    } else {
                         alert('无法将此日志内容添加到白名单,内容无效或为空');
                    }
                } else {
                    alert("无效输入或序号超出范围");
                }
            }
        }
    };

    const Whitelist = {
        init() {
             if (!CONFIG.whitelist) {
                 CONFIG.whitelist = {};
             }
            const currentDomain = new URL(location.href).hostname;
             if (!CONFIG.whitelist[currentDomain]) {
                 CONFIG.whitelist[currentDomain] = [];
             }
        },

        add(domain, content) {
             if (!domain || !content) return;
             if (!CONFIG.whitelist[domain]) {
                 CONFIG.whitelist[domain] = [];
             }
             if (!CONFIG.whitelist[domain].includes(content)) {
                 CONFIG.whitelist[domain].push(content);
                 UIController.saveConfig();
             }
        },

        isWhitelisted(element) {
             if (!element || !(element instanceof Element)) return false;
             const currentDomain = new URL(location.href).hostname;
             if (!CONFIG.whitelist[currentDomain] || CONFIG.whitelist[currentDomain].length === 0) {
                 return false;
             }
             const elementContent = SharedUtils.getElementContent(element);
             return CONFIG.whitelist[currentDomain].includes(elementContent);
        },

        clear(domain) {
             if (CONFIG.whitelist[domain]) {
                 CONFIG.whitelist[domain] = [];
                 UIController.saveConfig();
             }
        },

        clearCurrentDomain() {
             const currentDomain = new URL(location.href).hostname;
             this.clear(currentDomain);
        },

        clearAll() {
             CONFIG.whitelist = {};
             UIController.saveConfig();
        }
    };

    const perf = {
        pendingTasks: [],
        isProcessing: false,
        processed: new WeakSet(),
        adElements: new Set(),
        styleCache: new Map(),
        lastStyleCacheClear: Date.now(),
        longTaskCount: 0,
        degraded: true
    };

    const ModuleManager = {
        modules: {},
        register(name, module) {
            this.modules[name] = module;
        },
        init() {
            Object.values(this.modules).forEach(module => {
                if (typeof module.init === 'function') {
                    module.init();
                }
            });
        },
        run(moduleName, element) {
            if (!CONFIG.modules.main || !CONFIG.modules[moduleName]) return false;
            if (Whitelist.isWhitelisted(element)) return false;
            const module = this.modules[moduleName];
            if (module && typeof module.check === 'function') {
                return module.check(element);
            }
            return false;
        }
    };

    const AdUtils = {
        processedScripts: new WeakSet(),
        originalAppendChild: Node.prototype.appendChild,
        originalCreateElement: document.createElement,
        isDynamicSystemActive: false,
        observer: null,
        throttleQueue: new Set(),
        abortControllers: new WeakMap(),

        removeElement(element, moduleKey, reason, isNuclear = false) {
             if (Whitelist.isWhitelisted(element)) return false;
            if (!(element instanceof Element)) {
                 console.warn('尝试移除无效节点:', element);
                 return false;
             }

            if (!CONFIG.modules.main || Logs.processedElements.has(element)) {
                element.dataset.adRemoved = 'true';
                return false;
            }

            if (Logs.processedElements.has(element)) {
                element.dataset.adRemoved = 'true';
                return false;
            }


            try {
                Logs.add(moduleKey, element, {
                    ...reason,
                    detail: (isNuclear ? '[原子级移除] ' : '') + (reason.detail || ''),
                    nuclear: isNuclear
                });

                if (element.parentNode) {
                    if (isNuclear) {
                        const unsafeAttributes = element.tagName === 'SCRIPT' ?
                            ['src', 'onload', 'onerror', 'integrity'] :
                            ['src', 'href', 'data-src'];

                        unsafeAttributes.forEach(attr => {
                            if (element.hasAttribute(attr)) {
                                try {
                                    element.removeAttribute(attr);
                                } catch(e) {}
                            }
                        });

                        element.parentNode.removeChild(element);
                        const comment = document.createComment(`Removed ad by ${moduleKey} [Nuclear]: ${reason.type}`);
                        try { element.parentNode.insertBefore(comment, element); } catch (e) {}
                        element.dataset.adNuclearRemoved = 'true';
                    } else {
                        element.style.setProperty('display', 'none', 'important');
                        element.style.setProperty('visibility', 'hidden', 'important');
                        element.style.setProperty('opacity', '0', 'important');
                        element.style.setProperty('width', '0', 'important');
                        element.style.setProperty('height', '0', 'important');
                        element.style.setProperty('pointer-events', 'none', 'important');
                        element.style.setProperty('z-index', '-9999', 'important');
                        element.setAttribute('data-ad-removed', 'true');
                    }
                    return true;
                } else {
                     element.dataset.adRemoved = 'true';
                    console.debug('元素没有父节点,无法移除:', element);
                    return false;
                }
            } catch(e) {
                console.error('元素移除失败:', e, element);
                if (element instanceof Element) {
                    element.dataset.adRemovalFailed = 'true';
                }
                return false;
            }
        },

        safeRemove(element, moduleKey, reason) {
            return this.removeElement(element, moduleKey, reason, false);
        },

        nuclearRemove(element, moduleKey, reason) {
            return this.removeElement(element, moduleKey, reason, true);
        },

        initScriptObserver() {
            Node.prototype.appendChild = function(node) {
                if (AdUtils.isDynamicSystemActive && node.tagName === 'SCRIPT') {
                    AdUtils.processScriptElement(node);
                    return node;
                }
                return AdUtils.originalAppendChild.call(this, node);
            };

            document.createElement = function(tagName) {
                const el = AdUtils.originalCreateElement.call(document, tagName);
                if (AdUtils.isDynamicSystemActive && tagName.toLowerCase() === 'script') {
                    return AdUtils.createScriptProxy(el);
                }
                return el;
            };

            this.observer = new MutationObserver(mutations => {
                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === 1 && node.tagName === 'SCRIPT') {
                            AdUtils.processScriptElement(node);
                        }
                    });
                });
            });

            if (this.isDynamicSystemActive) {
                this.observer.observe(document.documentElement, {
                    childList: true,
                    subtree: true
                });
            }
        },

        createScriptProxy(scriptElement) {
            return new Proxy(scriptElement, {
                set: (target, prop, value) => {
                     if (Whitelist.isWhitelisted(target)) {
                         target[prop] = value;
                        return true;
                     }
                    if (prop === 'src' || prop === 'innerHTML') {
                        AdUtils.processScriptElement(target);
                    }
                    target[prop] = value;
                    return true;
                }
            });
        },

        processScriptElement(scriptElement) {
            if (this.processedScripts.has(scriptElement) || Whitelist.isWhitelisted(scriptElement)) return;
            this.processedScripts.add(scriptElement);

            if (ModuleManager.modules.dynamicSystem?.enabled) {
                this.nuclearRemove(scriptElement, 'dynamicSystem', {
                    type: '动态脚本防御',
                    detail: '拦截动态创建的脚本元素'
                });

                ['src', 'onload', 'onerror', 'integrity'].forEach(prop => {
                    try { delete scriptElement[prop]; } catch(e) {}
                });
            }
        },

        enableDynamicSystem() {
            if (!this.isDynamicSystemActive) {
                this.isDynamicSystemActive = true;
                this.initScriptObserver();
            }
        },

        disableDynamicSystem() {
            if (this.isDynamicSystemActive) {
                this.isDynamicSystemActive = false;
                Node.prototype.appendChild = this.originalAppendChild;
                document.createElement = this.originalCreateElement;

                if (this.observer) {
                    this.observer.disconnect();
                }
            }
        },

        processQueue() {
            requestIdleCallback(() => {
                const startTime = performance.now();
                const iterator = this.throttleQueue.values();
                let entry = iterator.next();

                while (!entry.done && performance.now() - startTime < 8) {
                    const element = entry.value;
                    if (Whitelist.isWhitelisted(element)) {
                        this.throttleQueue.delete(entry.value);
                        entry = iterator.next();
                        continue;
                    }
                    if (element.tagName === 'SCRIPT') {
                        ModuleManager.run('dynamicSystem', element);
                    } else {
                        ModuleManager.run('thirdPartyBlock', element);
                    }
                    this.throttleQueue.delete(entry.value);
                    entry = iterator.next();
                }

                if (this.throttleQueue.size > 0) {
                    this.processQueue();
                }
            });
        },

        throttleCheck(element) {
            if (this.throttleQueue.has(element) || Whitelist.isWhitelisted(element)) return;
            this.throttleQueue.add(element);
            if (this.throttleQueue.size === 1) {
                this.processQueue();
            }
        }
    };

    const StyleManager = {
        styleElement: null,
        injectedSheets: new Set(),

        inject() {
            if (this.injectedSheets.size > 0) return;

            const sheet = new CSSStyleSheet();
            sheet.replaceSync(`
                [data-ad-cleaned] {
                    all: initial !important;
                    display: none !important;
                    visibility: hidden !important;
                    opacity: 0 !important;
                    position: absolute !important;
                    z-index: -9999 !important;
                    width: 0 !important;
                    height: 0 !important;
                    pointer-events: none !important;
                }
                [data-ad-cleaned] * {
                    all: unset !important;
                }
            `);
            document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
            this.injectedSheets.add(sheet);

            const style = document.createElement('style');
            style.textContent = `
                @layer adBlocker {
                    :not([data-ad-cleaned]) {
                        contain: style !important;
                    }
                    [data-ad-cleaned] {
                        animation: none !important;
                        transition: none !important;
                    }
                }
            `;
            style.setAttribute('data-ad-permanent', 'true');
            document.documentElement.prepend(style);

            const checkStyles = () => {
                if (!document.contains(style)) {
                    document.documentElement.prepend(style);
                }
                if (!document.adoptedStyleSheets.includes(sheet)) {
                    document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
                }
                requestAnimationFrame(checkStyles);
            };
            checkStyles();
        },

        remove() {
            this.injectedSheets.forEach(sheet => {
                document.adoptedStyleSheets = document.adoptedStyleSheets.filter(s => s !== sheet);
            });
            document.querySelectorAll('style[data-ad-permanent]').forEach(s => s.remove());
        },

        toggle(enable) {
            enable ? this.inject() : this.remove();
        }
    };

    const CSPManager = {
        currentPolicy: null,

        generatePolicy() {
            const merged = {};
            CONFIG.csp.rules.filter(rule => rule.enabled).forEach(rule => {
                const [directive, ...values] = rule.rule.split(/\s+/);
                merged[directive] = (merged[directive] || []).concat(values);
            });

            return Object.entries(merged)
                .map(([k, v]) => `${k} ${[...new Set(v)].join(' ')}`)
                .join('; ');
        },

        inject() {
            this.remove();
            if (!CONFIG.csp.enabled) return;

            const policy = this.generatePolicy();
            this.currentPolicy = policy;

            const meta = document.createElement('meta');
            meta.httpEquiv = "Content-Security-Policy";
            meta.content = policy;
            if (document.head) {
                document.head.appendChild(meta);
            } else {
                document.documentElement.insertBefore(meta, document.documentElement.firstChild);
            }
        },

        remove() {
            const meta = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
            if (meta) meta.remove();
        },

        toggleRule(ruleId, enable) {
            const rule = CONFIG.csp.rules.find(r => r.id === ruleId);
            if (rule) rule.enabled = enable;
        },

        injectInitialCSP() {
            if (!CONFIG.csp.enabled) return;

            const initialRules = CONFIG.csp.rules
                .filter(rule => [1, 6].includes(rule.id) && rule.enabled)
                .map(rule => rule.rule)
                .join('; ');

            if (initialRules) {
                const meta = document.createElement('meta');
                meta.httpEquiv = "Content-Security-Policy";
                meta.content = initialRules;
                if (document.head) {
                    document.head.appendChild(meta);
                } else {
                    document.documentElement.insertBefore(meta, document.documentElement.firstChild);
                }
            }
        }
    };

    const Detector = {
        getCachedStyle(el) {
            if (Date.now() - perf.lastStyleCacheClear > CONFIG.performance.styleCacheTimeout) {
                perf.styleCache.clear();
                perf.lastStyleCacheClear = Date.now();
            }
            const key = `${el.nodeName}#${el.id}.${Array.from(el.classList).join('.')}`;
            if (!perf.styleCache.has(key)) {
                try {
                    perf.styleCache.set(key, getComputedStyle(el));
                } catch (e) {
                    console.warn("Error getting computed style:", e);
                    return {};
                }
            }
            return perf.styleCache.get(key);
        },

        isVisible(el) {
            const style = getComputedStyle(el);
            if (style.display === 'none' || style.visibility === 'hidden') return false;

            const rect = el.getBoundingClientRect();
            return !(
                rect.width === 0 ||
                rect.height === 0 ||
                (rect.top >= window.innerHeight || rect.bottom <= 0) ||
                (rect.left >= window.innerWidth || rect.right <= 0)
            );
        }
    };

    const Processor = {
        collectAds() {
            const treeWalker = document.createTreeWalker(
                document.documentElement,
                NodeFilter.SHOW_ELEMENT,
                null,
                false
            );

            perf.adElements.clear();

            while (treeWalker.nextNode()) {
                const element = treeWalker.currentNode;
                if (perf.processed.has(element) || Whitelist.isWhitelisted(element)) continue;

                let modulePriority = CONFIG.modulePriority;

                if (CONFIG.performance.visibleAreaPriority && Detector.isVisible(element)) {
                    modulePriority = [...CONFIG.performance.highRiskModules, ...modulePriority.filter(m => !CONFIG.performance.highRiskModules.includes(m))];
                }

                if (CONFIG.modules.main) {
                    for (const moduleKey of modulePriority) {
                        if (ModuleManager.run(moduleKey, element)) {
                            perf.adElements.add(element);
                            perf.processed.add(element);
                            break;
                        }
                    }
                }
            }
        },

        processElements() {
            if (perf.degraded) return;

            let startTime = performance.now();
            let elementCount = 0;

            for (let element of perf.adElements) {
                if (elementCount >= CONFIG.performance.mutationProcessLimit ||
                    performance.now() - startTime > CONFIG.performance.mutationProcessTimeLimit) {
                    perf.pendingTasks.push(() => Processor.processElements());
                    break;
                }

                if (perf.processed.has(element) || Whitelist.isWhitelisted(element)) continue;

                let modulePriority = CONFIG.modulePriority;

                if (CONFIG.performance.visibleAreaPriority && Detector.isVisible(element)) {
                    modulePriority = [...CONFIG.performance.highRiskModules, ...modulePriority.filter(m => !CONFIG.performance.highRiskModules.includes(m))];
                }

                for (const moduleKey of modulePriority) {
                    if (ModuleManager.run(moduleKey, element)) {
                        perf.processed.add(element);
                        break;
                    }
                }
                elementCount++;
            }

            perf.isProcessing = false;
            if (perf.pendingTasks.length > 0) {
                scheduleProcess();
            }
        }
    };

    const observer = new MutationObserver(mutations => {
        ModuleManager.modules.performanceOptimizer.throttleMutationProcessing(mutations);

        mutations.forEach(mutation => {
            if (mutation.type === 'childList') {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 8 && node.data.includes('Removed ad')) {
                        node.parentNode.removeChild(node);
                    }
                });
            }

            if (mutation.type === 'childList') {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1) {
                         if (Whitelist.isWhitelisted(node)) return;
                        if (node.matches('[data-ad-permanent],[data-ad-removed],[data-ad-cleaned]')) {
                            AdUtils.safeRemove(node, 'mutationClean', {
                                type: 'DOM清理',
                                detail: '检测到被移除元素的重新插入'
                            });
                            return;
                        }

                        const walker = document.createTreeWalker(
                            node,
                            NodeFilter.SHOW_ELEMENT,
                            {
                                acceptNode: (n) => {
                                     if (Whitelist.isWhitelisted(n)) return NodeFilter.FILTER_SKIP;
                                    return n.hasAttribute('data-ad-permanent') ?
                                        NodeFilter.FILTER_ACCEPT :
                                        NodeFilter.FILTER_SKIP;
                                }
                            }
                        );

                        let currentNode;
                        while ((currentNode = walker.nextNode())) {
                            AdUtils.safeRemove(currentNode, 'mutationClean', {
                                type: 'DOM深度清理',
                                detail: '检测到被移除元素的子元素'
                            });
                        }
                    }
                });
            } else if (mutation.type === 'attributes') {
                 if (Whitelist.isWhitelisted(mutation.target)) return;
                if (mutation.target.hasAttribute('data-ad-permanent') &&
                    mutation.attributeName !== 'data-ad-permanent') {
                    mutation.target.removeAttribute(mutation.attributeName);
                }
            }
        });
    });

    const scheduleProcess = (() => {
        const tasks = [];
        let isScheduled = false;

        function runTasks(deadline) {
            while (tasks.length && (deadline.timeRemaining() > 2 || deadline.didTimeout)) {
                const task = tasks.shift();
                try {
                    task();
                } catch(e) {
                    console.error('Task error:', e);
                }
            }
            if (tasks.length) {
                requestIdleCallback(runTasks, { timeout: CONFIG.performance.idleCallbackTimeout });
            } else {
                isScheduled = false;
            }
        }

        return function(task) {
            tasks.push(task);
            if (!isScheduled) {
                isScheduled = true;
                if (typeof requestIdleCallback === 'function') {
                    requestIdleCallback(runTasks, { timeout: CONFIG.performance.idleCallbackTimeout });
                } else {
                    setTimeout(() => runTasks({
                        timeRemaining: () => 50,
                        didTimeout: true
                    }), 50);
                }
            }
        };
    })();

    const debouncedScheduleProcess = Utils.debounce(scheduleProcess, CONFIG.performance.debounceMutationDelay);

    const UIController = {
        init() {
            this.loadConfig();
            Whitelist.init();
            this.registerMainSwitch();
            this.registerModuleSwitches();
            this.registerLogCommands();
            this.registerCSPCommands();
            this.registerResetCommand();
            StyleManager.toggle(CONFIG.modules.main);
        },

        registerMainSwitch() {
            GM_registerMenuCommand(
                `🔘 主开关 [${CONFIG.modules.main ? '✅' : '❌'}]`,
                () => this.toggleMain()
            );
        },

        registerModuleSwitches() {
            Object.entries(CONFIG.moduleNames).forEach(([key, name]) => {
                GM_registerMenuCommand(
                    `${name} [${CONFIG.modules[key] ? '✅' : '❌'}]`,
                    () => this.toggleModule(key, name)
                );
            });
        },

        registerLogCommands() {
            GM_registerMenuCommand('📜 查看拦截日志', () => Logs.showInAlert());
            GM_registerMenuCommand('🧹 清空日志', () => Logs.clear());
        },

        registerCSPCommands() {
            GM_registerMenuCommand('🛡️ CSP策略管理', () => this.manageCSP());
        },

        registerResetCommand() {
            GM_registerMenuCommand('🔄 重置设置', () => this.resetSettings());
        },

        toggleMain() {
            const newState = !CONFIG.modules.main;
            Object.keys(CONFIG.modules).forEach(key => {
                if (key !== 'main') CONFIG.modules[key] = newState;
            });
            CONFIG.modules.main = newState;
            this.saveConfig();
            StyleManager.toggle(newState);
            GM_notification(`主开关已${newState ? '启用' : '禁用'}`, `所有模块${newState ? '✅ 已激活' : '❌ 已停用'}`);
            location.reload();
        },

        toggleModule(key, name) {
            CONFIG.modules[key] = !CONFIG.modules[key];
            CONFIG.modules.main = Object.values(CONFIG.modules)
                .slice(1).some(v => v);
            this.saveConfig();
            StyleManager.toggle(CONFIG.modules.main);
            GM_notification(`${name} ${CONFIG.modules[key] ? '✅ 已启用' : '❌ 已禁用'}`);
            location.reload();
        },

        manageCSP() {
            const rulesDisplay = CONFIG.csp.rules
                .map(r => `${r.id}. ${r.name} (${r.enabled ? '✅' : '❌'})`)
                .join('\n');

            let input = prompt(
                `当前CSP策略状态: ${CONFIG.csp.enabled ? '✅ 已启用' : '❌ 已禁用'}\n\n` +
                "当前策略规则:\n" + rulesDisplay + "\n\n" +
                "输入选项:\n1. 开启策略 (输入 'enable')\n2. 关闭策略 (输入 'disable')\n" +
                "修改规则示例:输入 '1on' 启用规则1\n输入 '23off' 禁用规则2和规则3\n\n"+
                "请输入你的选择:",
                ""
            );

            if (input === null) return;

            input = input.trim().toLowerCase();

            switch (input) {
                case 'enable':
                    CONFIG.csp.enabled = true;
                    this.saveConfig();
                    CSPManager.inject();
                    alert("CSP策略已启用");
                    location.reload();
                    break;
                case 'disable':
                    CONFIG.csp.enabled = false;
                    this.saveConfig();
                    CSPManager.remove();
                    alert("CSP策略已禁用");
                    location.reload();
                    break;
                default:
                    if (/^\d+(?:on|off)$/i.test(input)) {
                        this.modifyCSPRules(input);
                    } else {
                        alert("无效输入");
                    }
            }
        },

        modifyCSPRules(actionInput) {
            const matches = actionInput.match(/^(\d+)(on|off)$/i);

            if (matches) {
                const ruleIds = matches[1].split('').map(Number);
                const enable = matches[2].toLowerCase() === 'on';

                let updatedRules = [];
                ruleIds.forEach(id => {
                    const rule = CONFIG.csp.rules.find(r => r.id === id);
                    if (rule) {
                        rule.enabled = enable;
                        updatedRules.push(id);
                    }
                });

                this.saveConfig();
                CSPManager.inject();
                alert(`规则 ${updatedRules.join(',')} 已更新为 ${enable ? '启用' : '禁用'}`);
                location.reload();
            } else {
                alert("输入格式错误,请按示例输入如'1on'或'123off'");
            }
        },

        resetSettings() {
            if (confirm("确定要重置所有设置吗?这将清空设置和白名单")) {
                Object.assign(CONFIG.modules, DEFAULT_MODULES);
                CONFIG.csp.enabled = false;
                CONFIG.csp.rules = DEFAULT_CSP_RULES.map(rule => ({ ...rule }));
                Whitelist.clearAll();
                this.saveConfig();
                CSPManager.remove();
                Logs.clear();
                alert("所有设置已重置为默认值");
                location.reload();
            }
        },

        saveConfig() {
            GM_setValue(`adblockConfig_${location.hostname}`, JSON.stringify({
                modules: CONFIG.modules,
                csp: CONFIG.csp,
                 whitelist: CONFIG.whitelist
            }));
        },

        loadConfig() {
            try {
                const savedConfig = JSON.parse(GM_getValue(`adblockConfig_${location.hostname}`, '{}'));
                if (savedConfig.modules) {
                    Object.keys(CONFIG.modules).forEach(key => {
                        if (savedConfig.modules.hasOwnProperty(key)) {
                            CONFIG.modules[key] = savedConfig.modules[key];
                        }
                    });
                }
                if (savedConfig.csp) {
                    Object.assign(CONFIG.csp, savedConfig.csp);
                }
                 if (savedConfig.whitelist) {
                     CONFIG.whitelist = savedConfig.whitelist;
                 }
            } catch (e) {
                console.error("加载配置失败:", e);
            }
        }
    };

    function init() {
        UIController.init();
        CSPManager.injectInitialCSP();
        ModuleManager.init();

        observer.observe(document.documentElement, {
            childList: true,
            subtree: true,
            attributes: true,
            attributeFilter: ['id', 'class', 'data-ad', 'src']
        });

        Processor.collectAds();
        scheduleProcess(() => Processor.processElements());

        window.addEventListener('scroll', Utils.throttle(() => {
            Processor.collectAds();
            scheduleProcess(() => Processor.processElements());
        }, CONFIG.performance.throttleScrollDelay));

        window.addEventListener('resize', Utils.debounce(() => {
            Processor.collectAds();
            scheduleProcess(() => Processor.processElements());
        }, 150));

        if (CONFIG.mobileOptimizations.lazyLoadImages) {
            document.addEventListener('DOMContentLoaded', () => {
                const images = document.querySelectorAll('img[data-src]');
                images.forEach(img => {
                    img.src = img.dataset.src;
                    img.removeAttribute('data-src');
                });
            });
        }

        if (CONFIG.mobileOptimizations.removeImagePlaceholders) {
            document.addEventListener('DOMContentLoaded', () => {
                const placeholders = document.querySelectorAll('.image-placeholder');
                placeholders.parentNode.removeChild(placeholders);
            });
        }
    }

    const ASTAnalyzer = (function() {
        const tokenTypes = {
            IDENTIFIER: 'identifier',
            STRING: 'string',
            KEYWORD: 'keyword',
            OPERATOR: 'operator'
        };

        return {
            getObfuscationRules: function(minLevel) {
                return REGEX.obfuscationPatterns.filter(r => r.riskLevel >= minLevel);
            },

            checkObfuscation: function(code, minLevel) {
                const rules = this.getObfuscationRules(minLevel);
                for (let i = 0; i < rules.length; i++) {
                    try {
                        if (rules[i].pattern.test(code)) {
                            return true;
                        }
                    } catch (e) {
                        console.error('[AST]规则执行错误:', rules[i].type, e);
                    }
                }
                return false;
            },

            tokenize: function(code) {
                const tokens = [];
                const regex = /(\b[a-zA-Z_$][\w$]*\b)|(["'])(?:(?!\2).|\\.)*?\2|([{}()\[\].,;=+*/-])|(\S)/g;
                let match;
                while ((match = regex.exec(code)) !== null) {
                    if (match[1]) {
                        tokens.push({type: tokenTypes.IDENTIFIER, value: match[1]});
                    } else if (match[2]) {
                        tokens.push({type: tokenTypes.STRING, value: match[0]});
                    } else if (match[3]) {
                        tokens.push({type: tokenTypes.OPERATOR, value: match[3]});
                    } else {
                        tokens.push({type: 'other', value: match[4]});
                    }
                }
                return tokens;
            },

            checkLexicalPatterns: function(code) {
                const tokens = this.tokenize(code);
                return this.checkLongIdentifiers(tokens) ||
                       this.checkObfuscation(code, 2);
            },

            checkDynamicBehavior: function(code) {
                return this.checkObfuscation(code, 3) ||
                       this.checkDynamicElementCreation(code);
            },

            checkDynamicElementCreation: function(code) {
                const rules = this.getObfuscationRules(3).filter(
                    r => r.type.includes('iframe') || r.type.includes('元素创建')
                );
                return rules.some(r => r.pattern.test(code));
            },

            checkLongIdentifiers: function(tokens) {
                return tokens.some(t =>
                    t.type === tokenTypes.IDENTIFIER &&
                    t.value.length > CONFIG.protectionRules.dynamicIdLength
                );
            }
        };
    })();

    ModuleManager.register('thirdPartyBlock', {
        originals: {
            createElement: document.createElement,
            setAttribute: Element.prototype.setAttribute,
            appendChild: Node.prototype.appendChild,
            insertBefore: Node.prototype.insertBefore,
            replaceChild: Node.prototype.replaceChild,
            fetch: window.fetch,
            xhrOpen: XMLHttpRequest.prototype.open,
            xhrSend: XMLHttpRequest.prototype.send,
            documentWrite: document.write,
            documentWriteln: document.writeln,
            insertAdjacentHTML: Element.prototype.insertAdjacentHTML
        },
        blockedUrls: new Set(),
        processedElements: new WeakSet(),
        hostCache: new Map(),
        requestInterceptors: new WeakMap(),
        interceptedRequests: new WeakSet(),
        mutationObserver: null,

        init() {
            if (!CONFIG.modules.thirdPartyBlock) return this.disable();
            this.enable();
        },

        enable() {
            if (this.enabled) return;
            this.enabled = true;
            this.setupRequestInterception();
            document.addEventListener('beforescriptexecute', this.handleBeforeScriptExecute.bind(this));
        },

        disable() {
            if (!this.enabled) return;
            this.enabled = false;
            this.cleanupRequestInterception();
            document.removeEventListener('beforescriptexecute', this.handleBeforeScriptExecute);
        },

        setupRequestInterception() {
            const interceptRequest = (target, url, requestType) => {
                 if (target instanceof Element && Whitelist.isWhitelisted(target)) return false;
                if (!url || this.blockedUrls.has(url)) return true;
                if (!this.isThirdParty(url)) return false;

                this.blockedUrls.add(url);
                this.interceptedRequests.add(target);

                if (target?.tagName === 'SCRIPT') {
                    const abort = new AbortController();
                    AdUtils.abortControllers.set(target, abort);
                    if (target.src) {
                        fetch(target.src, { signal: abort.signal }).catch(() => {});
                        abort.abort();
                    }
                    this.logRemoval(target, 'thirdPartyBlock', {
                        type: '第三方脚本拦截',
                        detail: `原子级移除脚本: ${url.slice(0, 80)}`,
                        context: { requestType }
                    });
                    return this.completeRemove(target);
                }
                return this.blockElement(target);
            };

            const unifiedRequestHandler = (target, url, requestType) => {
                if (target instanceof Element && Whitelist.isWhitelisted(target)) return false; // Added whitelist check
                if (this.interceptedRequests.has(target)) return true;
                return interceptRequest(target, url, requestType);
            };

            window.fetch = (input, init) => {
                const url = typeof input === 'string' ? input : input?.url;
                if (unifiedRequestHandler(null, url, 'Fetch')) {
                    this.logRemoval(document.createElement('div'), 'thirdPartyBlock', {
                        type: 'Fetch请求拦截',
                        detail: `URL: ${url?.slice(0,150) || 'unknown'}`,
                        context: { method: init?.method || 'GET' }
                    });
                    return Promise.reject(new Error('TPI: 第三方请求被拦截'));
                }
                return this.originals.fetch(input, init);
            };

            XMLHttpRequest.prototype.open = function(method, url) {
                if (unifiedRequestHandler(this, url, 'XHR')) {
                    this.requestInterceptors.set(this, true);
                    return;
                }
                return this.originals.xhrOpen.call(this, method, url);
            };

            XMLHttpRequest.prototype.send = function(body) {
                if (this.requestInterceptors.has(this)) {
                    this.requestInterceptors.delete(this);
                    return;
                }
                return this.originals.xhrSend.call(this, body);
            };

            document.createElement = (tagName) => {
                const element = this.originals.createElement.call(document, tagName);
                if (['script', 'iframe', 'img'].includes(tagName.toLowerCase())) {
                    return new Proxy(element, {
                        set: (target, prop, value) => {
                             if (Whitelist.isWhitelisted(target)) {
                                target[prop] = value;
                                return true;
                             }
                            if (prop === 'src' && unifiedRequestHandler(target, value, '元素创建')) {
                                return true;
                            }
                            target[prop] = value;
                            return true;
                        }
                    });
                }
                return element;
            };

            Element.prototype.setAttribute = function(name, value) {
                 if (Whitelist.isWhitelisted(this)) {
                     return this.originals.setAttribute.call(this, name, value);
                 }
                if (name === 'src' && unifiedRequestHandler(this, value, '属性设置')) {
                    return;
                }
                return this.originals.setAttribute.call(this, name, value);
            };

            const interceptDOMOperation = (operation, nodes, operationType) => {
                for (const node of nodes) {
                    if (node.nodeType === 1) {
                         if (Whitelist.isWhitelisted(node)) continue;
                        const src = node.src || node.getAttribute('data-src') || '';
                        if (unifiedRequestHandler(node, src, operationType)) {
                            return null;
                        }
                    }
                }
                return operation;
            };

            Node.prototype.appendChild = function(node) {
                return interceptDOMOperation(
                    this.originals.appendChild.call(this, node),
                    [node],
                    'DOM插入'
                );
            };

            Node.prototype.insertBefore = function(newNode, referenceNode) {
                return interceptDOMOperation(
                    this.originals.insertBefore.call(this, newNode, referenceNode),
                    [newNode],
                    'DOM插入'
                );
            };

            Node.prototype.replaceChild = function(newChild, oldChild) {
                return interceptDOMOperation(
                    this.originals.replaceChild.call(this, newChild, oldChild),
                    [newChild],
                    'DOM替换'
                );
            };

            const handleHTMLInsertion = (html, insertionType, originalFunction) => {
                const tempDiv = document.createElement('div');
                tempDiv.innerHTML = html;
                Array.from(tempDiv.querySelectorAll('script, iframe, img')).forEach(el => {
                    const src = el.src || el.getAttribute('src') || '';
                    const clonedEl = el.cloneNode();
                     if (Whitelist.isWhitelisted(clonedEl)) return;
                    if (unifiedRequestHandler(clonedEl, src, insertionType)) {
                        this.logRemoval(clonedEl, 'thirdPartyBlock', {
                            type: '动态插入拦截',
                            detail: `插入方式: ${insertionType}`,
                            context: { originalHTML: html.slice(0, 200) }
                        });
                        this.completeRemove(clonedEl);
                    }
                });
                return originalFunction(html);
            };

            document.write = (content) =>
                handleHTMLInsertion(content, 'document.write', this.originals.documentWrite);

            document.writeln = (content) =>
                handleHTMLInsertion(content, 'document.writeln', this.originals.documentWriteln);

            Element.prototype.insertAdjacentHTML = function(position, html) {
                return handleHTMLInsertion(html, 'insertAdjacentHTML',
                    (html) => this.originals.insertAdjacentHTML.call(this, position, html));
            };
        },

        cleanupRequestInterception() {
            AdUtils.abortControllers.forEach(controller => controller.abort());
            AdUtils.abortControllers.clear();

            Object.keys(this.originals).forEach(key => {
                if (key === 'fetch') {
                    window.fetch = this.originals.fetch;
                } else if (key === 'xhrOpen') {
                    XMLHttpRequest.prototype.open = this.originals.xhrOpen;
                } else if (key === 'xhrSend') {
                    XMLHttpRequest.prototype.send = this.originals.xhrSend;
                } else if (key === 'documentWrite') {
                    document.write = this.originals.documentWrite;
                } else if (key === 'documentWriteln') {
                    document.writeln = this.originals.documentWriteln;
                }
                else {
                    const [obj, prop] = key.split(/(?=[A-Z])/);
                    const target = obj === 'document' ? document :
                        obj === 'Element' ? Element.prototype : Node.prototype;
                    if (target) target[prop] = this.originals[key];
                }
            });
        },

        isThirdParty(url) {
            try {
                if (!url || url.startsWith('data:') || url.startsWith('blob:')) return false;
                if (this.hostCache.has(url)) return this.hostCache.get(url);

                const currentHost = new URL(location.href).hostname;
                const resourceHost = new URL(url, location.href).hostname;
                const isThirdParty = !(
                    resourceHost.endsWith(`.${currentHost}`) ||
                    resourceHost === currentHost ||
                    REGEX.thirdParty.test(resourceHost)
                );

                this.hostCache.set(url, isThirdParty);
                return isThirdParty;
            } catch(e) {
                return true;
            }
        },

        logRemoval(element, moduleKey, reason) {
             if (Whitelist.isWhitelisted(element)) return;
            try {
                const elementInfo = {
                    tag: element.tagName,
                    id: element.id ? `#${element.id}` : '',
                    class: element.className ? `.${element.className.split(/\s+/).join('.')}` : '',
                    src: element.src || element.href || element.dataset.src || ''
                };

                Logs.add(moduleKey, element, {
                    ...reason,
                    element: `${elementInfo.tag}${elementInfo.id}${elementInfo.class}`,
                    content: element.outerHTML.slice(0, 200)
                });
            } catch(e) {
                console.error('记录日志失败:', e);
            }
        },

        completeRemove(element) {
            if (!element || this.processedElements.has(element) || Whitelist.isWhitelisted(element)) return false;
            this.processedElements.add(element);

            try {
                const clone = element.cloneNode(true);
                element.parentNode.replaceChild(clone, element);

                clone.style.cssText = `
                    display: none !important;
                    visibility: hidden !important;
                    position: absolute !important;
                    z-index: -9999 !important;
                `;

                while (clone.attributes.length > 0) {
                    clone.removeAttribute(clone.attributes[0].name);
                }

                clone.setAttribute('data-ad-removed', 'true');

                setTimeout(() => {
                    try {
                        if (clone.parentNode) clone.parentNode.removeChild(clone);
                    } catch(e) {
                        console.debug('最终移除失败:', e);
                    }
                }, 100);

                return true;
            } catch(e) {
                console.error('完全移除元素失败:', e);
                return false;
            }
        },

        blockElement(element) {
            if (!element || this.processedElements.has(element) || Whitelist.isWhitelisted(element)) return false;
            this.processedElements.add(element);

            try {
                element.style.cssText = `
                    pointer-events: none !important;
                    user-select: none !important;
                    display: none !important;
                    visibility: hidden !important;
                `;

                const clone = element.cloneNode(true);
                element.parentNode.replaceChild(clone, element);
                clone.setAttribute('data-ad-blocked', 'true');

                this.logRemoval(clone, 'thirdPartyBlock', {
                    type: '元素拦截',
                    detail: '彻底禁用第三方元素'
                });

                return true;
            } catch(e) {
                console.error('元素拦截失败:', e);
                return false;
            }
        },

        handleBeforeScriptExecute(e) {
            const script = e.target;
            if (Whitelist.isWhitelisted(script)) return;
            const src = script.src || script.getAttribute('data-src') || '';

            if (this.isThirdParty(src)) {
                this.logRemoval(script, 'thirdPartyBlock', {
                    type: '预执行脚本拦截',
                    detail: `脚本类型: ${script.type || '常规脚本'}`,
                    context: { src: src.slice(0, 200) }
                });

                e.preventDefault();
                e.stopImmediatePropagation();

                requestIdleCallback(() => {
                    this.completeRemove(script);
                }, { timeout: 50 });
            }
        },

        check(el) {
             if (Whitelist.isWhitelisted(el)) return false;
            if (!CONFIG.modules.thirdPartyBlock || this.processedElements.has(el)) {
                 if(el instanceof Element && el.hasAttribute('data-ad-blocked')) return true;
                 return false;
            }

             if (!(el instanceof Element)) return false;

            if (this.processedElements.has(el)) {
                 if(el.hasAttribute('data-ad-blocked')) return true;
                 return false;
            }

            const src = el.src || el.getAttribute('data-src') || '';

            if (!src || this.blockedUrls.has(src)) {
                 if (this.blockedUrls.has(src) && el instanceof Element) {
                      this.processedElements.add(el);
                      el.dataset.adBlockedSrc = 'true';
                 }
                 return false;
            }

            if (this.isThirdParty(src)) {
                this.blockedUrls.add(src);
                this.logRemoval(el, 'thirdPartyBlock', {
                    type: '静态资源拦截',
                    detail: `源: ${src.slice(0, 150)}`,
                    context: { tag: el.tagName }
                });
                if (el instanceof Element) this.processedElements.add(el);
                return this.completeRemove(el);
            }
            return false;
        }
    });

    ModuleManager.register('dynamicSystem', {
        checkedScripts: new WeakSet(),
        scriptProxies: new WeakMap(),
        observer: null,
        enabled: false,
        pendingAnalysis: new Map(),
        analysisQueue: [],
        isProcessingQueue: false,

        init() {
            if (CONFIG.modules.dynamicSystem) {
                this.enableSystem();
            } else {
                this.disableSystem();
            }
            this.setupMutationObserver();
            this.startRecoveryCheck();
            this.startQueueProcessor();
        },

        enableSystem() {
            if (this.enabled) return;
            this.enabled = true;
            AdUtils.enableDynamicSystem();
            if (this.observer) {
                this.observer.observe(document.documentElement, {
                    childList: true,
                    subtree: true,
                    attributes: true,
                    attributeFilter: ['id', 'class', 'style', 'src']
                });
            }
        },

        disableSystem() {
            if (!this.enabled) return;
            this.enabled = false;
            AdUtils.disableDynamicSystem();
            if (this.observer) {
                this.observer.disconnect();
            }
            this.pendingAnalysis.clear();
        },

        setupMutationObserver() {
            this.observer = new MutationObserver(mutations => {
                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === 1) {
                             if (Whitelist.isWhitelisted(node)) return;
                            this.handleNodeInsertion(node);
                        }
                    });
                });
            });

            if (this.enabled) {
                this.observer.observe(document.documentElement, {
                    childList: true,
                    subtree: true,
                    attributes: true,
                    attributeFilter: ['id', 'class', 'style', 'src']
                });
            }
        },

        handleNodeInsertion(node) {
            if (Whitelist.isWhitelisted(node)) return;
            if (node.tagName === 'SCRIPT') {
                this.asyncCheckScript(node);
            } else {
                this.checkStaticElements(node);
            }
        },

        asyncCheckScript(scriptEl) {
            if (!this.enabled || this.checkedScripts.has(scriptEl) || Whitelist.isWhitelisted(scriptEl)) return;
            this.checkedScripts.add(scriptEl);

            if (this.quickDetect(scriptEl)) {
                this.blockImmediately(scriptEl);
                return;
            }

            const analysisId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
            this.pendingAnalysis.set(scriptEl, analysisId);
            this.analysisQueue.push({ script: scriptEl, id: analysisId });

            if (!this.isProcessingQueue) {
                this.processAnalysisQueue();
            }
        },

        async processAnalysisQueue() {
            if (this.isProcessingQueue || this.analysisQueue.length === 0) return;
            this.isProcessingQueue = true;

            while (this.analysisQueue.length > 0) {
                const { script, id } = this.analysisQueue.shift();
                if (!document.contains(script) || this.pendingAnalysis.get(script) !== id || Whitelist.isWhitelisted(script)) {
                    continue;
                }
                await this.analyzeScript(script);

                if (this.analysisQueue.length > 5) {
                    await new Promise(resolve => setTimeout(resolve, 0));
                }
            }
            this.isProcessingQueue = false;
        },

        async analyzeScript(scriptEl) {
             if (Whitelist.isWhitelisted(scriptEl)) return;
            try {
                if (scriptEl.src) {
                    await this.analyzeRemoteScript(scriptEl);
                } else {
                    await this.analyzeInlineScript(scriptEl);
                }
            } catch (e) {
                console.error('脚本分析错误:', e);
            } finally {
                this.pendingAnalysis.delete(scriptEl);
            }
        },

        async analyzeRemoteScript(scriptEl) {
             if (Whitelist.isWhitelisted(scriptEl)) return;
            const controller = new AbortController();
            AdUtils.abortControllers.set(scriptEl, controller);

            try {
                const response = await fetch(scriptEl.src, {
                    signal: controller.signal,
                    priority: 'low'
                });
                const reader = response.body.getReader();
                let chunk = '', isSafe = true;

                while (true) {
                    const { done, value } = await reader.read();
                    if (done) break;
                    chunk += new TextDecoder().decode(value);

                    if (this.detectHighRiskPatterns(chunk)) {
                        isSafe = false;
                        reader.cancel();
                        break;
                    }
                    if (chunk.length > 4096) break;
                }

                if (!isSafe) {
                    this.blockImmediately(scriptEl);
                    Logs.add('dynamicSystem', scriptEl, {
                        type: '流式特征阻断',
                        detail: `检测到前4KB风险内容`
                    });
                }
            } catch(e) {
                if (e.name !== 'AbortError') {
                    console.warn('脚本分析失败:', e);
                }
            } finally {
                AdUtils.abortControllers.delete(scriptEl);
            }
        },

        async analyzeInlineScript(scriptEl) {
             if (Whitelist.isWhitelisted(scriptEl)) return;
            const content = scriptEl.textContent;
            const dangerLevel = this.calculateDangerLevel(content);

            if (dangerLevel >= 3) {
                this.blockImmediately(scriptEl);
                Logs.add('dynamicSystem', scriptEl, {
                    type: '内联脚本风险',
                    detail: `危险级别: ${dangerLevel}`,
                    analysis: {
                        ast: ASTAnalyzer.checkLexicalPatterns(content),
                        obfuscation: ASTAnalyzer.checkObfuscation(content, 2) ? 2 : 0,
                        dynamic: ASTAnalyzer.checkDynamicBehavior(content) ? 3 : 0
                    }
                });
            }
        },

        calculateDangerLevel(content) {
            let dangerLevel = 0;
            if (ASTAnalyzer.checkLexicalPatterns(content)) dangerLevel += 2;
            if (ASTAnalyzer.checkObfuscation(content, 2)) dangerLevel += 2;
            if (ASTAnalyzer.checkDynamicBehavior(content)) dangerLevel += 3;
            if (REGEX.jsAdPattern.test(content)) dangerLevel += 2;

            const highRiskPatterns = REGEX.obfuscationPatterns.filter(p => p.riskLevel >= 3);
            if (highRiskPatterns.some(p => p.pattern.test(content.slice(0, 500)))) {
                dangerLevel += 3;
            }

            return dangerLevel;
        },

        detectHighRiskPatterns(content) {
            return REGEX.obfuscationPatterns.some(p =>
                p.riskLevel >= 3 && p.pattern.test(content)
            );
        },

        checkObfuscatedAttributes(attrs) {
            const shortVarPattern = /^[a-z\d]{1,3}$/i;
            const signaturePattern = /^(?:[\da-f]{32}|[\w+/=]{40,})$/i;
            const alphanumAlternate = /(?:[a-z]\d|\d[a-z]){5,}/gi;

            return attrs.some(attr => {
                const isShortVar = shortVarPattern.test(attr.name);
                const isObfuscatedValue = signaturePattern.test(attr.value) ||
                    attr.value.match(alphanumAlternate)?.length > 3;
                const isDynamicName = /\[(?:0x[a-f\d]+|\d+)\]/.test(attr.name);

                return (isShortVar && isObfuscatedValue) ||
                    attr.name.length > 20 ||
                    isDynamicName ||
                    (attr.value.includes(';') && attr.value.length > 60);
            });
        },

        checkStaticElements(el) {
             if (Whitelist.isWhitelisted(el)) return false;
            if (!this.enabled) return false;

            if (el.id && (
                el.id.length > CONFIG.protectionRules.dynamicIdLength ||
                REGEX.dynamicId.test(el.id)
            )) {
                return AdUtils.safeRemove(el, 'dynamicSystem', {
                    type: '可疑动态ID',
                    detail: `ID特征: ${el.id.slice(0, 50)}`
                });
            }

            if (el.tagName === 'A') {
                const href = el.getAttribute('href') || '';
                if (href.startsWith('javascript:') && REGEX.jsAdPattern.test(href)) {
                    return AdUtils.safeRemove(el, 'dynamicSystem', {
                        type: '可疑JS链接广告',
                        detail: `执行代码: ${href.slice(0, 100)}`,
                        regex: [REGEX.jsAdPattern.source]
                    });
                }
            }
            return false;
        },

        quickDetect(scriptEl) {
             if (Whitelist.isWhitelisted(scriptEl)) return false;
            if (!this.enabled) return false;
            const attrs = Array.from(scriptEl.attributes);

            if (this.checkObfuscatedAttributes(attrs)) {
                Logs.add('dynamicSystem', scriptEl, {
                    type: '混淆属性检测',
                    detail: `属性列表: ${attrs.map(a => a.name).join(', ')}`
                });
                return true;
            }

            if (!scriptEl.src && scriptEl.textContent) {
                const content = scriptEl.textContent.slice(0, 200);
                return REGEX.obfuscationPatterns.some(p =>
                    p.riskLevel >= 3 && p.pattern.test(content)
                );
            }
            return false;
        },

        blockImmediately(scriptEl) {
            if (!scriptEl.parentNode || Whitelist.isWhitelisted(scriptEl)) return;
            scriptEl.setAttribute('data-ad-blocked', 'true');
            scriptEl.style.setProperty('display', 'none', 'important');

            requestIdleCallback(() => {
                try {
                    if (scriptEl.parentNode) scriptEl.parentNode.removeChild(scriptEl);
                } catch(e) {
                    console.warn('移除失败:', e);
                }
            }, { timeout: 200 });
        },

        check(el) {
             if (Whitelist.isWhitelisted(el)) return false;
            if (!this.enabled) return false;
            if (this.checkedScripts.has(el) || (el instanceof Element && el.dataset.dynamicChecked)) return false;

            if (!(el instanceof Element)) return false;

            if (this.checkedScripts.has(el) || (el instanceof Element && el.dataset.dynamicChecked)) {
                return false;
            }

            const attrs = Array.from(el.attributes);
            if (this.checkObfuscatedAttributes(attrs)) {
                AdUtils.safeRemove(el, 'dynamicSystem', {
                    type: '混淆属性检测',
                    detail: `属性列表: ${attrs.map(a => a.name).join(', ')}`
                });
                this.checkedScripts.add(el);
                el.dataset.dynamicChecked = 'true';
                return true;
            }

            if (el.tagName === 'SCRIPT') {
                AdUtils.throttleCheck(el);
                this.checkedScripts.add(el);
                el.dataset.dynamicChecked = 'true';
                return true;
            }

            if (this.checkStaticElements(el)) {
                this.checkedScripts.add(el);
                el.dataset.dynamicChecked = 'true';
                return true;
            }

            return false;
        },

        startRecoveryCheck() {
            setInterval(() => {
                document.querySelectorAll('script:not([data-ad-checked])').forEach(script => {
                     if (Whitelist.isWhitelisted(script)) return;
                    AdUtils.throttleCheck(script);
                });
            }, 500);
        },

        startQueueProcessor() {
            setInterval(() => {
                if (!this.isProcessingQueue && this.analysisQueue.length > 0) {
                    this.processAnalysisQueue();
                }
            }, 1000);
        }
    });

    ModuleManager.register('layoutSystem', {
        check(el) {
             if (Whitelist.isWhitelisted(el)) return false;
            if (!CONFIG.modules.layoutSystem) return false;
            const style = Detector.getCachedStyle(el);
            const zIndex = parseInt(style.zIndex, 10);

            if (!isNaN(zIndex) && zIndex > CONFIG.protectionRules.zIndexThreshold) {
                const parent = el.parentElement;
                const isLegitPopup = (
                    parent &&
                    (parent.classList.contains('modal') ||
                     parent.getAttribute('role') === 'dialog')
                );
                if (!isLegitPopup) {
                    return AdUtils.safeRemove(el, 'layoutSystem', {
                        type: '高Z轴元素',
                        detail: `z-index: ${zIndex}`
                    });
                }
            }

            if (style.overflow === 'hidden' && el.scrollHeight > el.clientHeight) {
                return AdUtils.safeRemove(el, 'layoutSystem', {
                    type: '隐藏溢出内容的容器'
                });
            }

            if (el.children.length === 0 &&
                el.textContent.trim() === '' &&
                style.width === '0px' &&
                style.height === '0px') {
                return AdUtils.safeRemove(el, 'layoutSystem', {
                    type: '空的不可见容器'
                });
            }

            if (el.children.length > 0 &&
                Array.from(el.children).every(child =>
                    child.style.display === 'none' ||
                    child.style.visibility === 'hidden')) {
                return AdUtils.safeRemove(el, 'layoutSystem', {
                    type: '子元素的不可见容器'
                });
            }

            if (['fixed', 'sticky'].includes(style.position)) {
                const rect = el.getBoundingClientRect();
                const isBottomFloat = (
                    rect.bottom > window.innerHeight - 50 &&
                    rect.height < 100
                );
                if (isBottomFloat) {
                    return AdUtils.safeRemove(el, 'layoutSystem', {
                        type: '底部悬浮元素',
                        detail: `位置: bottom=${rect.bottom}px`
                    });
                }
            }

            return false;
        }
    });

    ModuleManager.register('mergedMediaSystem', {
        checkedParents: new WeakSet(),
        imageExtensions: /\.(gif|webp|png|jpe?g|svg)(\?.*)?$/i,
        jsExtensionPattern: /\.js(\?|$)/i,
        visibilityThreshold: 0.1,
        minValidSize: 32,

        mobileAdRatios: [
            { w: 320, h: 50 },
            { w: 300, h: 250 },
            { w: 336, h: 280 },
            { w: 1, h: 1 }
        ],

        mobileRatioThreshold: { min: 0.2, max: 5 },

        check(el) {
             if (Whitelist.isWhitelisted(el)) return false;
            if (!CONFIG.modules.mergedMediaSystem) return false;

            if (this.isImageElement(el)) {
                return this.checkImageElement(el);
            }

            if (this.isSuspiciousContainer(el)) {
                return this.handleSuspiciousContainer(el);
            }

            return false;
        },

        isImageElement(el) {
            const tag = el.tagName;
            return tag === 'IMG' ||
                   tag === 'IMAGE' ||
                   (tag === 'DIV' && this.hasImageBackground(el));
        },

        checkImageElement(el) {
             if (Whitelist.isWhitelisted(el)) return false;
            const src = el.src || el.getAttribute('src') || '';
            const dynamicSrc = el.getAttribute('data-src') || '';

            if (this.jsExtensionPattern.test(src) || this.jsExtensionPattern.test(dynamicSrc)) {
                return this.handleAd(el, 'JS扩展名图片',
                    `异常图片源: ${(src || dynamicSrc).slice(0, 80)}`, 3);
            }

            if (!this.isVisible(el)) return false;

            const rect = el.getBoundingClientRect();
            const viewportArea = window.innerWidth * window.innerHeight;

            if (rect.width * rect.height < this.minValidSize * this.minValidSize) {
                return this.handleAd(el, '微型隐藏图片',
                    `尺寸: ${rect.width}x${rect.height}px`, 2);
            }

            const naturalWidth = el.naturalWidth || rect.width;
            const naturalHeight = el.naturalHeight || rect.height;

            if (this.isCommonAdSize(naturalWidth, naturalHeight)) {
                return this.handleAd(el, '标准广告尺寸',
                    `${naturalWidth}x${naturalHeight}`, 2);
            }

            const aspectRatio = naturalWidth / naturalHeight;
            if (aspectRatio < this.mobileRatioThreshold.min ||
                aspectRatio > this.mobileRatioThreshold.max) {
                return this.handleAd(el, '异常宽高比',
                    `比例:${aspectRatio.toFixed(1)}`, 2);
            }

            if (this.isEdgePositioned(rect, viewportArea)) {
                return this.handleAd(el, '边缘定位图片',
                    `位置: ${rect.top}px`, 2);
            }

            return false;
        },

        isVisible(el) {
             if (Whitelist.isWhitelisted(el)) return true;
            const style = Detector.getCachedStyle(el);
            const rect = el.getBoundingClientRect();

            return (
                style.opacity > this.visibilityThreshold &&
                style.visibility !== 'hidden' &&
                style.display !== 'none' &&
                rect.width > 0 &&
                rect.height > 0 &&
                !this.isCoveredByParent(el)
            );
        },

        isCommonAdSize(width, height) {
            return this.mobileAdRatios.some(ratio => {
                const targetRatio = ratio.w / ratio.h;
                return Math.abs(width/height - targetRatio) < 0.1 &&
                       Math.abs(width - ratio.w) < 10 &&
                       Math.abs(height - ratio.h) < 10;
            });
        },

        isEdgePositioned(rect, viewportArea) {
            const elementArea = rect.width * rect.height;
            return (
                (rect.top < 50 && elementArea > viewportArea * 0.3) ||
                (rect.bottom > window.innerHeight - 100 && elementArea > viewportArea * 0.2)
            );
        },

        hasImageBackground(el) {
            const style = Detector.getCachedStyle(el);
            return (
                style.backgroundImage !== 'none' &&
                this.imageExtensions.test(style.backgroundImage)
            );
        },

        isSuspiciousContainer(el) {
            const style = Detector.getCachedStyle(el);

            return (
                ['fixed', 'sticky'].includes(style.position) ||
                style.zIndex > 999 ||
                this.hasScrollDisabled(style) ||
                this.containsTrackingPixel(el)
            );
        },

        hasScrollDisabled(style) {
            return (
                style.overflow === 'hidden' &&
                (style.touchAction === 'none' || style.overscrollBehavior === 'contain')
            );
        },

        containsTrackingPixel(el) {
            return el.querySelectorAll('img[width="1" i], img[height="1" i]').length > 0;
        },

        handleSuspiciousContainer(el) {
             if (Whitelist.isWhitelisted(el)) return false;
            const style = Detector.getCachedStyle(el);
            const rect = el.getBoundingClientRect();

            if (['fixed', 'sticky'].includes(style.position)) {
                return this.handleAd(el, '固定位置容器',
                    `定位方式: ${style.position}`, 2);
            }

            if (rect.width >= window.innerWidth * 0.9 &&
                rect.height >= window.innerHeight * 0.7) {
                return this.handleAd(el, '全屏覆盖容器',
                    `尺寸: ${rect.width}x${rect.height}px`, 3);
            }

            return false;
        },

        isCoveredByParent(el) {
            let parent = el.parentElement;
            while (parent) {
                const pStyle = Detector.getCachedStyle(parent);
                if (pStyle.display === 'none' || pStyle.visibility === 'hidden') {
                    return true;
                }
                parent = parent.parentElement;
            }
            return false;
        },

        handleAd(el, type, detail, priority = 1) {
            return AdUtils.safeRemove(el, 'mergedMediaSystem', {
                type: `图片广告[${type}]`,
                detail: detail,
                priority: priority
            });
        }
    });

    ModuleManager.register('specialUA', {
        navigatorProxy: null,
        originalNavigator: Object.create(navigator),
        fakeUA: 'NokiaE7-00/5.0 UCWEB/2.0 Mozilla/5.0 (Symbian/3; Series60/5.2; Windows Phone 10.0; Android 14; Microsoft; Lumia 950 XL Dual SIM; Java) Gecko/131 Firefox/131 SearchCraft/3.10.2 (Baidu; P1 13) baiduboxapp/4.3.0.10',
        fakePlatform: 'Win32',
        fakeAppVersion: 'Mozilla/5.0 (Linux; Android 12; LIO-AN00 Build/HUAWEILIO-AN00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.196 Mobile Safari/537.36',

        init() {
            this.createProxy();
            if (CONFIG.modules.specialUA) this.enable();
        },

        createProxy() {
            this.navigatorProxy = new Proxy(navigator, {
                get: (target, prop) => {
                    if (!CONFIG.modules.specialUA)
                        return Reflect.get(target, prop);

                    switch(prop) {
                        case 'userAgent':
                            return this.fakeUA;
                        case 'platform':
                            return this.fakePlatform;
                        case 'appVersion':
                            return this.fakeAppVersion;
                        case 'vendor':
                            return 'Google Inc.';
                        default:
                            return Reflect.get(target, prop);
                    }
                }
            });

            Object.defineProperty(window, 'navigator', {
                value: this.navigatorProxy,
                configurable: true,
                writable: false
            });
        },

        enable() {
            CONFIG.modules.specialUA = true;
        },

        disable() {
            CONFIG.modules.specialUA = false;
            Object.defineProperty(window, 'navigator', {
                value: this.originalNavigator,
                configurable: true,
                writable: false
            });
        },

        check() {
            return false;
        }
    });

    ModuleManager.register('performanceOptimizer', {
        mutationQueue: new Set(),
        pendingFrames: 0,
        lastProcessTime: 0,
        performanceEntries: [],
        degradationThreshold: 3,
        isMonitoring: false,

        init() {
            this.optimizeMutationObserver();
            this.setupPerformanceMonitor();
            this.startPerformanceObserver();
        },

        optimizeMutationObserver() {
            const originalObserve = MutationObserver.prototype.observe;
            MutationObserver.prototype.observe = function(target, options) {
                const optimizedOptions = {
                    childList: options.childList,
                    attributes: options.attributes,
                    subtree: options.subtree && !options.subtreeOptimized,
                    attributeFilter: ['id', 'class', 'data-ad', 'src']
                };
                originalObserve.call(this, target, optimizedOptions);
            };
        },

        setupPerformanceMonitor() {
            if (this.isMonitoring) return;
            this.isMonitoring = true;

            const checkPerformance = () => {
                const now = performance.now();
                const recentEntries = this.performanceEntries.filter(
                    entry => entry.startTime > now - 5000
                );

                const longTasks = recentEntries.filter(
                    entry => entry.duration > CONFIG.performance.longTaskThreshold
                );

                if (longTasks.length >= this.degradationThreshold && !perf.degraded) {
                    this.activateDegradedMode();
                } else if (longTasks.length < this.degradationThreshold && perf.degraded) {
                    this.deactivateDegradedMode();
                }

                requestAnimationFrame(checkPerformance);
            };

            checkPerformance();
        },

        startPerformanceObserver() {
            const observer = new PerformanceObserver(list => {
                this.performanceEntries.push(...list.getEntries());
            });
            observer.observe({ entryTypes: ['longtask'] });
        },

        activateDegradedMode() {
            perf.degraded = true;
            observer.disconnect();
            document.removeEventListener('DOMNodeInserted', captureInsertion);

            CONFIG.modules.dynamicSystem = false;
            ModuleManager.modules.dynamicSystem?.disable();

            console.warn('进入性能降级模式,停止动态监测');
        },

        deactivateDegradedMode() {
            perf.degraded = false;

            observer.observe(document.documentElement, {
                childList: true,
                subtree: true,
                attributes: true,
                attributeFilter: ['id', 'class', 'data-ad', 'src']
            });

            document.addEventListener('DOMNodeInserted', captureInsertion, true);

            if (CONFIG.modules.dynamicSystem) {
                ModuleManager.modules.dynamicSystem?.enable();
            }

            console.log('退出性能降级模式,恢复动态监测');
        },

        scheduleFrame(callback) {
            if (this.pendingFrames < 2) {
                this.pendingFrames++;
                requestAnimationFrame(() => {
                    callback();
                    this.pendingFrames--;
                    this.lastProcessTime = performance.now();
                });
            } else {
                setTimeout(() => {
                    callback();
                    this.lastProcessTime = performance.now();
                }, 16);
            }
        },

        throttleMutationProcessing(mutations) {
            if (perf.degraded) return;

            const startTime = performance.now();
            let processedCount = 0;

            for (const mutation of mutations) {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === 1 && !perf.processed.has(node) && !Whitelist.isWhitelisted(node)) {
                            perf.adElements.add(node);
                            processedCount++;

                            if (processedCount >= CONFIG.performance.mutationProcessLimit ||
                                performance.now() - startTime > CONFIG.performance.mutationProcessTimeLimit) {
                                this.scheduleFrame(() => Processor.processElements());
                                return;
                            }
                        }
                    });
                }
            }

            if (perf.adElements.size > 0) {
                this.scheduleFrame(() => Processor.processElements());
            }
        }
    });

    const captureInsertion = (function() {
        const handler = function(e) {
            if (perf.degraded) return;
            const element = e.target;
            if (!perf.processed.has(element) && !Whitelist.isWhitelisted(element)) {
                perf.adElements.add(element);
                ModuleManager.modules.performanceOptimizer.scheduleFrame(
                    () => Processor.processElements()
                );
            }
        };
        document.addEventListener('DOMNodeInserted', handler, true);
        return handler;
    })();

    (function ensureDOMInjection() {
        const originalCreateElement = document.createElement;
        document.createElement = function(tagName) {
            const element = originalCreateElement.call(document, tagName);
            if (tagName.toLowerCase() === 'meta' && !document.head) {
                document.documentElement.insertBefore(element, document.documentElement.firstChild);
            }
            return element;
        };

        const originalAppendChild = Node.prototype.appendChild;
        Node.prototype.appendChild = function(node) {
            if (node.nodeType === 1 && node.tagName === 'STYLE' && !document.head) {
                return document.documentElement.insertBefore(node, document.documentElement.firstChild);
            }
            return originalAppendChild.call(this, node);
        };
    })();

    window.addEventListener('load', () => {
        if (!perf.degraded) {
            Processor.collectAds();
            ModuleManager.modules.performanceOptimizer.scheduleFrame(() => {
                Processor.processElements();
            });
        }
    });

    init();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址