BilinovelAntiBlock

抑制 Bilinovel 检测到广告屏蔽插件后隐藏内容

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         BilinovelAntiBlock
// @name:zh      Bilinovel 反广告屏蔽
// @namespace    https://github.com/SuniRein/scripts
// @version      1.4.2
// @description  抑制 Bilinovel 检测到广告屏蔽插件后隐藏内容
// @author       SuniRein
// @match        https://www.bilinovel.com/*
// @match        https://www.linovelib.com/*
// @grant        none
// @run-at       document-start
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bilinovel.com
// @license      GPL3
// @supportURL   https://github.com/SuniRein/scripts/blob/main/CHANGELOG.md
// ==/UserScript==

// 灵感来源: https://greasyfork.org/zh-CN/scripts/533617-bilinovel

(function () {
    'use strict';

    if (window.self !== window.top) return;

    const checkElementInterval = 100;
    const maxWaitTime = 15000;
    let timeWaited = 0;

    // 保护 console 不被覆盖
    Object.freeze(console);

    // 根据不同网页定位目标元素
    function analyzePage() {
        const hostname = window.location.hostname;
        const href = window.location.href;
        if (hostname == 'www.bilinovel.com') {
            console.log('Bilinovel: 检测到 Bilinovel 网站');
            if (href.includes('/catalog') || href.includes('/vol')) {
                return {
                    getContent: () => document.querySelector('.content'),
                    isTitle: (ele) => ele.classList.contains('module-header'),
                };
            }
            return {
                getContent: () => document.getElementById('acontent'),
                isTitle: (ele) => ele.classList.contains('atitle'),
            };
        } else if (hostname == 'www.linovelib.com') {
            console.log('Bilinovel: 检测到 Linovelib 网站');
            if (href.includes('/catalog') || href.includes('/vol')) {
                return {
                    getContent: () => document.getElementById('volume-list'),
                    isTitle: (ele) => ele.classList.contains('section_title'),
                };
            }
            return {
                getContent: () => document.getElementById('TextContent'),
                isTitle: (ele) => ele.tagName === 'H1',
            };
        }
    }

    function showElement(element) {
        element.removeAttribute('style');
    }

    function hideElement(element) {
        element.style.setProperty('display', 'none', 'important');
    }

    const { getContent, isTitle } = analyzePage();

    console.log('Bilinovel: 开始轮询获取目标元素...');

    function displayContent(content) {
        try {
            // 显示文本
            showElement(content);
            content.classList.remove('adv-box');
            console.log('Bilinovel: 显示目标元素');

            // 移除广告框
            const adBox = content.previousElementSibling;
            if (adBox && !isTitle(adBox)) {
                hideElement(adBox);
                console.log('Bilinovel: 隐藏广告框');
            }
        } catch (e) {
            console.error('Bilinovel: 修改目标元素时出错:', e);
        }
    }

    const intervalId = setInterval(() => {
        const content = getContent();
        timeWaited += checkElementInterval;

        if (content) {
            console.log('Bilinovel: 找到目标元素');
            clearInterval(intervalId);

            displayContent(content);

            // 监测目标元素样式改变
            const observer = new MutationObserver((mutationsList) => {
                for (const mutation of mutationsList) {
                    if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
                        displayContent(content);
                    }
                }
            });
            observer.observe(content, {
                attributes: true,
                attributeFilter: ['style'],
            });

            // 监测广告横幅
            const headerElement = document.body.firstChild;
            if (headerElement) {
                const headerObserver = new MutationObserver((mutationsList) => {
                    for (const mutation of mutationsList) {
                        if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
                            hideElement(headerElement);
                            console.log('Bilinovel: 隐藏广告横幅');
                        }
                    }
                });
                headerObserver.observe(headerElement, {
                    attributes: true,
                    attributeFilter: ['style'],
                });
            }

            // 检测广告弹窗
            function removeDialog(node) {
                const bnt = node.querySelector('#close-btn');
                if (bnt) {
                    console.log('Bilinovel: 发现广告弹窗,尝试关闭');
                    bnt.click();
                }
            }

            removeDialog(document);

            const bodyObserver = new MutationObserver((mutationsList) => {
                for (const mutation of mutationsList) {
                    if (mutation.type === 'childList') {
                        mutation.addedNodes.forEach((node) => {
                            if (node.nodeType === Node.ELEMENT_NODE) {
                                removeDialog(node);
                            }
                        });
                    }
                }
            });
            bodyObserver.observe(document.body, { childList: true, subtree: true });
        } else if (timeWaited >= maxWaitTime) {
            console.warn('Bilinovel: 获取目标元素超时 (' + maxWaitTime + 'ms),停止检查。');
            clearInterval(intervalId);
        }
    }, checkElementInterval);
})();