jx filter ad

jx filter ad,不保证适用所有的jx页面,自用~

// ==UserScript==
// @name         jx filter ad
// @namespace    http://tampermonkey.net/
// @version      3.0.0
// @description  jx filter ad,不保证适用所有的jx页面,自用~
// @author       ltxlong
// @match        *://*/*
// @grant        none
// @license      MIT
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    let jx_filter_ad_open_flag = false;
    const the_jx_url_trait = [
        'v.qq.com',
        'iqiyi.com',
        'iq.com',
        'youku.com',
        'le.com',
        'tudou.com',
        'mgtv.com',
        'sohu.com',
        '1905.com',
        'bilibili.com',
        'pptv.com',
        'baofeng.com',
        'acfun.cn',
        'miguvideo.com',
        'yinyuetai.com',
        'fun.tv',
        'wasu.cn'
    ];

    const originUrl = window.location.origin;
    const originSearch = window.location.search;

    const hasMatchInSearch = the_jx_url_trait.some(trait => originSearch.includes(trait));
    if (hasMatchInSearch) {
        jx_filter_ad_open_flag = true;
    }

    if (!jx_filter_ad_open_flag) {
        return;
    }

    // 可以自定义需要去掉的id和class和其他定义的元素
    const adEleId = [];
    const adEleClass = [];
    const adEleOther = ['span[id]'];

    // 固定为PC ua
    Object.defineProperty(navigator, 'userAgent', {
        get: function () {
            return 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36';
        }
    });

    // Hook setInterval
    try {
        const originalSetInterval = window.setInterval;
        window.setInterval = function(callback, delay, ...args) {

            const callbackString = callback.toString();
            const filterPatterns = [
                '.appendChild(',
                '.insertBefore(',
                '.insertAfter(',
                '.append(',
                '.prepend(',
                '.after(',
                '.before(',
                '.appendTo(',
                '.prependTo(',
                '.html(',
                '.replaceWith(',
                '.wrap(',
                '.wrapAll(',
                '.wrapInner(',
            ];

            let isBlockFlag = false;
            if (typeof callbackString === 'string' && callbackString !== '[native code]') {
                for (const pattern of filterPatterns) {
                    if (callbackString.includes(pattern)) {
                        console.warn(`HOOK: Callback string contains filter pattern: "${pattern}"`);
                        isBlockFlag = true;
                        break;
                    }
                }
            }

            if (isBlockFlag) {
                return 0;
            }

            // --- 如果没有阻止,调用原始的 setInterval ---
            const intervalId = originalSetInterval.call(this, callback, delay, ...args);
            return intervalId;
        }
    } catch (error) {
        console.error('Error getting callback toString() or during string analysis:', error);
    }

    // 确保浏览器支持 Navigation API
    try {
        if ('navigation' in window) {

            window.navigation.addEventListener('navigate', (event) => {
                const destinationUrl = event.destination.url;

                const destinationOrigin = new URL(destinationUrl).origin;

                // Check if the destination origin is different from the current origin
                if (destinationOrigin !== originUrl) {
                    console.warn(`阻止了到非同源地址的跳转: ${destinationUrl}`);

                    // Prevent the default navigation behavior
                    // event.canIntercept must be true for preventDefault to work on this event type
                    if (event.canIntercept) {
                        event.preventDefault();;
                    } else {
                        console.log(`Navigation to ${destinationUrl} cannot be intercepted.`);
                        // Note: Some navigations like target="_blank" might not be interceptable this way
                    }


                } else {
                    console.log(`允许同源跳转: ${destinationUrl}`);
                    // Let the navigation proceed
                }

            });

            console.log(`当前页面源: ${window.location.origin}`);
            console.log('Navigation API 监听已启动...');

        } else {
            console.warn('当前浏览器不支持 Navigation API,请考虑使用 click/submit 监听作为替代。');
            // Fallback to click/submit method if necessary
        }

    } catch (e) {
        // Handle potential errors if the URL is invalid or cannot be parsed
        console.error('无法解析目标URL或发生错误:', e);
        // Decide whether to prevent or allow on error - usually allowing is safer
        // Let's assume allowing is the default if we can't verify
    }

    function removeTargetBlankDivs() {
        try {
            const blankTargetAnchors = document.querySelectorAll('a[target="_blank"]');
            if (blankTargetAnchors.length === 0) {
                //console.log("----------------No target='_blank' anchors found.");
                return;
            }

            blankTargetAnchors.forEach(anchor => {
                const parentDiv = anchor.closest('div');
                if (parentDiv) {
                    if (parentDiv.parentNode) {
                        //console.log("----------------Removing div: ", anchor.outerHTML);
                        parentDiv.remove();
                    }
                }
            });
        } catch (error) {
            console.error("----------------Error accessing or modifying content: ", error);
        }
    }

    function removeAdElement() {

        if (adEleId.length === 0 && adEleClass.length === 0 && adEleOther.length === 0) {
            return;
        }

        const selectors = [];
        if (adEleId.length > 0) {
            selectors.push(...adEleId.map(id => `#${id}`));
        }
        if (adEleClass.length > 0) {
            selectors.push(...adEleClass.map(className => `.${className}`));
        }
        if (adEleOther.length > 0) {
            selectors.push(...adEleOther.map(otherEle => `${otherEle}`));
        }
        if (selectors.length === 0) {
            return;
        }

        const combinedSelector = selectors.join(', ');
        try {
            const elementsToRemove = document.querySelectorAll(combinedSelector);

            elementsToRemove.forEach(element => {
                // 使用 element.remove() 是现代且推荐的删除元素方法
                // 兼容性:IE(Edge 除外)不支持,但现代浏览器都支持
                if (element && typeof element.remove === 'function') {
                    element.remove();
                    // console.log("已删除元素:", element); // 可选:记录删除的元素
                } else if (element && element.parentNode) {
                    // 兼容旧浏览器,通过父节点删除
                    element.parentNode.removeChild(element);
                    // console.log("已删除元素 (旧方法):", element); // 可选:记录删除的元素
                }
            });
        } catch(error) {
            console.error("删除元素时发生错误:", error);
        }
    }

    removeTargetBlankDivs();
    removeAdElement();

    // 考虑网速慢和卡顿的情况
    setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 1000)
    setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 2000)
    setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 3000)
    setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 5000)
    setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 10000)
    setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 20000)
    setTimeout(() => { removeTargetBlankDivs(); removeAdElement(); }, 30000)

    try {
        window.addEventListener('load', () => {
            removeTargetBlankDivs();
            removeAdElement();
        })
    } catch (error) {
        console.error("监听页面load发生错误:", error);
    }

})();