Greasy Fork

来自缓存

Greasy Fork is available in English.

隐藏B站视频详情页右侧的"活动推广"和"大家围观的直播"以及首页广告

使用MutationObserver隐藏Bilibili视频详情页右侧的"活动推广"和"大家围观的直播"模块,以及首页的广告内容,提升浏览体验。

当前为 2025-03-25 提交的版本,查看 最新版本

// ==UserScript==
// @name         隐藏B站视频详情页右侧的"活动推广"和"大家围观的直播"以及首页广告
// @name:en      Hide Promotions on Bilibili Video Details Page and Homepage
// @name:zh-TW   隱藏B站影片詳情頁右側的「活動推廣」與「大家圍觀的直播」及首頁廣告
// @name:ja      Bilibili動画詳細ページ右側の「イベントプロモーション」と「みんなが見ているライブ」およびホームページ広告を非表示
// @name:ko      Bilibili 비디오 상세 페이지 오른쪽의 "활동 프로모션"과 "모두가 보는 라이브" 및 홈페이지 광고 숨기기
// @name:fr      Masquer les promotions sur la page de détails vidéo Bilibili et la page d'accueil
// @name:es      Ocultar promociones en la página de detalles de video de Bilibili y la página principal
// @name:de      Werbung auf der Bilibili-Videodetailseite und der Startseite ausblenden
// @name:ru      Скрыть рекламу на странице деталей видео Bilibili и главной странице
// @namespace    http://tampermonkey.net/
// @version      0.2.2
// @description  使用MutationObserver隐藏Bilibili视频详情页右侧的"活动推广"和"大家围观的直播"模块,以及首页的广告内容,提升浏览体验。
// @description:en  Hide the "Event Promotions" and "Live Streams Everyone’s Watching" sections on the right side of Bilibili’s video details page, as well as homepage ads, using MutationObserver for a cleaner browsing experience.
// @description:zh-TW  利用MutationObserver技術,隱藏Bilibili影片詳情頁右側的「活動推廣」和「大家圍觀的直播」區域,以及首頁的廣告內容,讓您的觀看體驗更純淨。
// @description:ja  MutationObserverを使用して、Bilibili動画詳細ページ右側の「イベントプロモーション」と「みんなが見ているライブ」セクション、およびホームページの広告を非表示にし、快適な閲覧環境を提供します。
// @description:ko  MutationObserver를 활용하여 Bilibili 비디오 상세 페이지 오른쪽의 "활동 프로모션"과 "모두가 보는 라이브" 섹션, 그리고 홈페이지 광고를 숨겨 더 깔끔한 브라우징 경험을 제공합니다。
// @description:fr  Utilisez MutationObserver pour masquer les sections "Promotions d'événements" et "Diffusions en direct populaires" à droite de la page de détails vidéo de Bilibili, ainsi que les publicités de la page d'accueil, pour une expérience plus fluide.
// @description:es  Oculta las secciones de "Promociones de eventos" y "Transmisiones en vivo que todos miran" en el lado derecho de la página de detalles de video de Bilibili, además de los anuncios de la página principal, usando MutationObserver para una navegación más limpia.
// @description:de  Blende mit MutationObserver die Bereiche "Event-Werbung" und "Live-Streams, die jeder sieht" auf der rechten Seite der Bilibili-Videodetailseite sowie Werbung auf der Startseite aus, für ein angenehmeres Surferlebnis.
// @description:ru  Скрывает с помощью MutationObserver разделы "Промоакции мероприятий" и "Прямые трансляции, которые все смотрят" справа на странице деталей видео Bilibili, а также рекламу на главной странице для более комфортного просмотра.
// @namespace    http://tampermonkey.net/
// @description  Hide specified Bilibili elements using MutationObserver
// @description:en  Hide specified Bilibili elements using MutationObserver
// @author       aspen138
// @match        *://www.bilibili.com/video/*
// @match        *://www.bilibili.com/*
// @match        *://www.bilibili.com
// @match        *://search.bilibili.com/*
// @icon         https://www.bilibili.com/favicon.ico
// @grant        none
// @license      MIT
// ==/UserScript==



(function () {
    'use strict';

    if (window.location.hostname.includes('bilibili.com')) {
        const styleElement1 = document.createElement('style');
        styleElement1.textContent = `.login-tip, .vip-login, .vip-login-tip, .login-panel-popover { display: none !important; }`;
        document.head.appendChild(styleElement1);
    }


    if (document.cookie.includes('DedeUserID')) {
        //console.log("has loged in.");
        // add CSS to hide some elements
        const styleElement = document.createElement('style');
        styleElement.textContent = ` .desktop-download-tip { display: none !important; }`; //隐藏右下角的下载客户端的推广弹窗
        document.head.appendChild(styleElement);
    }
    else {
        //console.log("not loged in.");
        // add CSS to hide some elements
        const originAppendChild = Node.prototype.appendChild;
        Node.prototype.appendChild = function (childElement) {
            if (childElement.tagName === 'SCRIPT' && childElement.src.includes("login")) {
                console.log("src=", src);
                return null;
            }
            else {
                return originAppendChild.call(this, childElement);
            }
        }
    }

    // Select elements with href containing 'cm.bilibili.com/cm/api'
    var elements = document.querySelectorAll('a[href*="cm.bilibili.com/cm/api"]');
    elements.forEach(function(element) {
        var parentCard = element.closest('.bili-video-card');
        if (parentCard) {
            var originalHeight = parentCard.children[0].children[0].offsetHeight;

            var messageDiv = document.createElement('div');
            messageDiv.style.cssText = `
            background-color: #f0f0f0;
            color: #666;
            padding: 15px;
            text-align: center;
            font-size: 14px;
            height: ${originalHeight}px;
            min-height: 100px; /* Added fallback */
            display: flex;
            align-items: center;
            justify-content: center;
            box-sizing: border-box; /* Added to handle padding correctly */
        `;
            messageDiv.textContent = "The AD content is hidden";

            parentCard.innerHTML = '';
            parentCard.appendChild(messageDiv);
        }
    });

    // Enhanced function to thoroughly hide elements
    function hideElement(element) {
        if (!element) return;

        // Apply more aggressive hiding styles
        const hideStyles = {
            'display': 'none !important',
            'visibility': 'hidden !important',
            'opacity': '0 !important',
            'background': 'white !important',
            'color': 'white !important',
            'pointer-events': 'none !important',
            'height': '0 !important',
            'width': '0 !important',
            'overflow': 'hidden !important',
            'position': 'absolute !important',
            'z-index': '-9999 !important',
            'clip': 'rect(0, 0, 0, 0) !important'
        };

        // Apply styles using both direct style and cssText for maximum effectiveness
        Object.entries(hideStyles).forEach(([property, value]) => {
            element.style.setProperty(property, value.replace(' !important', ''), 'important');
        });

        // Hide all child elements recursively
        Array.from(element.children).forEach(child => {
            hideElement(child);
        });

        // Remove any inline event listeners
        element.onclick = null;
        element.onmouseover = null;
        element.onmouseenter = null;
        element.onmouseleave = null;
    }

    // Function to handle all target elements
    function hideAllTargetElements() {
        const targetElements = [
            '#slide_ad',
            '#right-bottom-banner',
            '.pop-live-small-mode.part-1',
            '.ad-floor-cover.b-img',
            '#bannerAd',
            '.vcd',
            'a[data-loc-id="4331"]',
            '#activity_vote',
            '.ad-report.video-card-ad-small',
            '.ad-report.ad-floor-exp',
            '.slide-ad-exp',
            '.activity-m-v1.act-now',
            '.video-page-special-card-small',
            '.btn-ad',
            'div[data-v-2ce37bb8].btn-ad',
            '.palette-button-adcard.is-bottom', // New element
            '.palette-button-adcard' // More specific selector for the new element
            //,'div[data-v-7b35db32].vip-login-tip'
        ];

        targetElements.forEach(selector => {
            const elements = document.querySelectorAll(selector);
            elements.forEach(hideElement);
        });
    }

    // Create a more specific MutationObserver
    const observer = new MutationObserver((mutations) => {
        mutations.forEach(mutation => {
            // Check for added nodes
            if (mutation.addedNodes.length) {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1) { // Element node
                        // Check if the added node is a target element
                        if (node.id === 'slide_ad' ||
                            node.classList.contains('slide-ad-exp') ||
                            node.classList.contains('ad-report') ||
                            node.classList.contains('activity-m-v1') ||
                            node.classList.contains('video-page-special-card-small') ||
                            node.classList.contains('btn-ad') ||
                            node.classList.contains('palette-button-adcard')) { // Added new class check
                            hideElement(node);
                        }
                        // Also check children of added nodes
                        const targetElements = node.querySelectorAll('#slide_ad, .slide-ad-exp, .ad-report, .activity-m-v1, .video-page-special-card-small, .btn-ad, .palette-button-adcard');
                        targetElements.forEach(hideElement);
                    }
                });
            }

            // Check for attribute changes
            if (mutation.type === 'attributes') {
                const element = mutation.target;
                if (element.id === 'slide_ad' ||
                    element.classList.contains('slide-ad-exp') ||
                    element.classList.contains('ad-report') ||
                    element.classList.contains('activity-m-v1') ||
                    element.classList.contains('video-page-special-card-small') ||
                    element.classList.contains('btn-ad') ||
                    element.classList.contains('palette-button-adcard')
                    // ||element.classList.contains('vip-login-tip')
                ) { // Added new class check
                    hideElement(element);
                }
            }
        });
    });

    // Configure the observer to watch for everything
    const observerConfig = {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: ['style', 'class']
    };

    // Initial hiding
    hideAllTargetElements();

    // Start observing
    observer.observe(document.body, observerConfig);

    // Set up periodic checks just in case
    const checkInterval = setInterval(hideAllTargetElements, 1000);

    // Cleanup after 30 seconds
    setTimeout(() => {
        clearInterval(checkInterval);
        observer.disconnect(); // Optionally disconnect the observer after cleanup
    }, 30000);
})();