优化Bilibili

优化Bilibili主页和文章页面

Per 04-11-2024. Zie de nieuwste versie.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         优化Bilibili
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  优化Bilibili主页和文章页面
// @match        https://www.bilibili.com/
// @match        *://www.bilibili.com/read/*
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

(function() {
    'use strict';

    // 从GM_getValue获取保存的状态,如果没有保存过,默认为false(关闭状态)
    let isAdRemovalEnabled = GM_getValue('bilibiliAdRemovalEnabled', false);
    let isSwiperRemovalEnabled = GM_getValue('bilibiliSwiperRemovalEnabled', false);
    let isNonVideoCardRemovalEnabled = GM_getValue('bilibiliNonVideoCardRemovalEnabled', false);
    let isCopySuffixRemovalEnabled = GM_getValue('bilibiliCopySuffixRemovalEnabled', false);

    // 创建设置按钮和开关控件
    function createSettingsButton() {
        // 等待页面加载完成
        const waitForPaletteButton = setInterval(() => {
            // 首先检查是否在主页上有adcard-content元素
            const adcardContent = document.querySelector('.adcard-content');
            if (adcardContent) {
                clearInterval(waitForPaletteButton);

                // 创建设置按钮
                const settingsButton = document.createElement('div');
                settingsButton.className = 'settings-button';
                settingsButton.innerHTML = `
                    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <circle cx="12" cy="12" r="3"></circle>
                        <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
                    </svg>
                `;
                settingsButton.style.cssText = `
                    width: 40px;
                    height: 40px;
                    background: #fff;
                    border-radius: 6px;
                    margin-bottom: 12px;
                    cursor: pointer;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    color: #18191c;
                    box-shadow: 0 2px 4px rgba(0,0,0,.1);
                    transition: all .2s;
                `;

                // 添加悬停效果
                settingsButton.addEventListener('mouseover', function() {
                    this.style.color = '#00aeec';
                    this.style.backgroundColor = '#fff';
                });

                settingsButton.addEventListener('mouseout', function() {
                    this.style.color = '#18191c';
                    this.style.backgroundColor = '#fff';
                });

                // 替换adcard-content的内容
                adcardContent.innerHTML = '';
                adcardContent.appendChild(settingsButton);

                // 创建设置面板容器
                const toggleContainer = document.createElement('div');
                toggleContainer.id = 'settingsToggleContainer';
                toggleContainer.style.cssText = `
                    position: fixed;
                    top: 65%;
                    right: 1px;
                    transform: translateY(-50%);
                    z-index: 100000;
                    background-color: white;
                    padding: 15px;
                    border-radius: 8px;
                    box-shadow: 0 2px 10px rgba(0,0,0,0.2);
                    display: none;
                    min-width: 100px;
                `;

                // 添加设置面板内容
                toggleContainer.innerHTML = `
                    <label style="display: block; margin-bottom: 10px;">
                        <input type="checkbox" id="adRemovalToggle" ${isAdRemovalEnabled ? 'checked' : ''}>
                        移除广告
                    </label>
                    <label style="display: block; margin-bottom: 10px;">
                        <input type="checkbox" id="swiperRemovalToggle" ${isSwiperRemovalEnabled ? 'checked' : ''}>
                        移除轮播图
                    </label>
                    <label style="display: block; margin-bottom: 10px;">
                        <input type="checkbox" id="nonVideoCardRemovalToggle" ${isNonVideoCardRemovalEnabled ? 'checked' : ''}>
                        移除非视频卡片
                    </label>
                    <label style="display: block;">
                        <input type="checkbox" id="copySuffixRemovalToggle" ${isCopySuffixRemovalEnabled ? 'checked' : ''}>
                        移除复制后缀
                    </label>
                `;

                // 添加点击事件
                settingsButton.addEventListener('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    const container = document.getElementById('settingsToggleContainer');
                    if (container) {
                        const isVisible = container.style.display === 'block';
                        container.style.display = isVisible ? 'none' : 'block';
                    }
                });

                // 将设置面板添加到页面
                document.body.appendChild(toggleContainer);

                // 添加点击外部关闭面板的功能
                document.addEventListener('click', function(e) {
                    const container = document.getElementById('settingsToggleContainer');
                    if (container && !container.contains(e.target) && !settingsButton.contains(e.target)) {
                        container.style.display = 'none';
                    }
                });

                // 添加复选框的事件监听器
                toggleContainer.addEventListener('change', function(e) {
                    if (e.target.type === 'checkbox') {
                        switch(e.target.id) {
                            case 'adRemovalToggle':
                                isAdRemovalEnabled = e.target.checked;
                                GM_setValue('bilibiliAdRemovalEnabled', isAdRemovalEnabled);
                                break;
                            case 'swiperRemovalToggle':
                                isSwiperRemovalEnabled = e.target.checked;
                                GM_setValue('bilibiliSwiperRemovalEnabled', isSwiperRemovalEnabled);
                                break;
                            case 'nonVideoCardRemovalToggle':
                                isNonVideoCardRemovalEnabled = e.target.checked;
                                GM_setValue('bilibiliNonVideoCardRemovalEnabled', isNonVideoCardRemovalEnabled);
                                break;
                            case 'copySuffixRemovalToggle':
                                isCopySuffixRemovalEnabled = e.target.checked;
                                GM_setValue('bilibiliCopySuffixRemovalEnabled', isCopySuffixRemovalEnabled);
                                break;
                        }
                    }
                });
            }
        }, 500);
    }

    // 主页功能
    if (window.location.href === 'https://www.bilibili.com/') {
        function removeAds() {
            if (!isAdRemovalEnabled) return;

            // 处理被feed-card包裹的情况
            const feedCards = document.querySelectorAll('.feed-card');
            feedCards.forEach(card => {
                const videoCard = card.querySelector('.bili-video-card.is-rcmd');
                if (videoCard && !videoCard.classList.contains('enable-no-interest')) {
                    card.remove();
                }
            });

            // 处理直接的bili-video-card
            const directVideoCards = document.querySelectorAll('.bili-video-card.is-rcmd:not(.enable-no-interest)');
            directVideoCards.forEach(card => {
                if (!card.parentElement.classList.contains('feed-card')) {
                    card.remove();
                }
            });

            // 删除flexible-roll-btn中的span标签和内容
            const flexibleRollBtns = document.querySelectorAll('.flexible-roll-btn');
            flexibleRollBtns.forEach(btn => {
                const spans = btn.querySelectorAll('span');
                spans.forEach(span => {
                    span.remove();
                });
            });

            // 删除feed-roll-btn
            const feedRollBtns = document.querySelectorAll('.feed-roll-btn');
            feedRollBtns.forEach(btn => {
                btn.remove();
            });
        }

        function removeSwiper() {
            if (!isSwiperRemovalEnabled) return;

            // 删除轮播图
            const swiper = document.querySelector('.recommended-swipe.grid-anchor');
            if (swiper) {
                swiper.remove();
            }

            // 删除特定的CSS规则
            const style = document.createElement('style');
            style.textContent = `
                .recommended-container_floor-aside .container>*:nth-of-type(n + 8) {
                    margin-top: 0 !important;
                }
                .recommended-container_floor-aside .container.is-version8>*:nth-of-type(n + 13) {
                    margin-top: 0 !important;
                }
            `;
            document.head.appendChild(style);
        }

        function removeNonVideoCards() {
            if (!isNonVideoCardRemovalEnabled) return;

            // 删除 floor-single-card 类的元素
            const nonVideoCards = document.querySelectorAll('.floor-single-card');
            nonVideoCards.forEach(card => {
                card.remove();
            });

            // 删除 bili-live-card 类的元素(直播卡片)
            const liveCards = document.querySelectorAll('.bili-live-card');
            liveCards.forEach(card => {
                card.remove();
            });
        }

        // 初始执行
        createSettingsButton();
        if (isAdRemovalEnabled) {
            removeAds();
        }
        if (isSwiperRemovalEnabled) {
            removeSwiper();
        }
        if (isNonVideoCardRemovalEnabled) {
            removeNonVideoCards();
        }

        // 创建一个MutationObserver来监视DOM变化
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if (mutation.type === 'childList') {
                    removeAds();
                    removeSwiper();
                    removeNonVideoCards();
                }
            });
        });

        // 配置观察选项
        const config = { childList: true, subtree: true };

        // 开始观察文档体
        observer.observe(document.body, config);
    }

    // 文章页面功能
    if (window.location.href.includes('www.bilibili.com/read/')) {
        // 创建设置按钮
        createSettingsButton();

        // 移除文本复制后缀
        function removeCopySuffix() {
            if (isCopySuffixRemovalEnabled) {
                window.addEventListener('copy', function(e) {
                    e.stopPropagation();
                }, true);
            } else {
                window.removeEventListener('copy', function(e) {
                    e.stopPropagation();
                }, true);
            }
        }

        // 在页面加载完成后执行removeCopySuffix
        window.addEventListener('load', removeCopySuffix);

        // 监听设置变化并重新应用removeCopySuffix
        const checkInterval = setInterval(() => {
            const currentSetting = GM_getValue('bilibiliCopySuffixRemovalEnabled', false);
            if (currentSetting !== isCopySuffixRemovalEnabled) {
                isCopySuffixRemovalEnabled = currentSetting;
                removeCopySuffix();
            }
        }, 1000);  // 每秒检查一次
    }
})();