bkBliBli

哔哩哔哩首页快捷拉黑,去广告,直播推广

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         bkBliBli
// @github       https://github.com/hunmeng/bkBilibili
// @description  哔哩哔哩首页快捷拉黑,去广告,直播推广
// @author       lkj
// @namespace    lkj
// @version      1.0.7
// @create       2024-05-06
// @lastmodified 2025-01-09
// @note         首次更新,拉黑功能覆盖到首页分区
// @charset      UTF-8
// @match        *://www.bilibili.com/
// @match        *://www.bilibili.com/?*
// @match        *://www.bilibili.com/v/*
// @match        https://api.bilibili.com/x/relation/modify
// @grant        unsafeWindow
// @compatible   chrome
// @license      MIT
// ==/UserScript==
(async function() {
    'use strict';
    const bili_jct = (await cookieStore.get('bili_jct')).value;
    console.log('bili_jct=======',bili_jct)
    // 添加自定义CSS样式
    var style = document.createElement('style');
    style.type = 'text/css';
    // 设置a标签的样式
    style.innerHTML = '.custom-link { margin-left: auto; }.feed-card { margin-top: 0px !important; margin-bottom: 0px !important; }.bili-video-card{ margin-top: 5px !important; margin-bottom: 20px !important; }.bili-video-card.is-rcmd.enable-no-interest { margin-top: 5px !important; margin-bottom: 20x !important; }';
    document.head.appendChild(style);

    async function addToBlack(uid,act) {
        return fetch('https://api.bilibili.com/x/relation/modify', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            credentials: 'include',
            body: `fid=${uid}&act=${act}&csrf=${bili_jct}`
        })
            .then(async res => void console.log('请求成功, 响应体: ', await res.text()))
            .catch(err => void console.error('请求错误', err));
    }

    // 函数用于排序类名数组并返回字符串
    function sortClassNames(classList) {
        if (typeof classList === 'string') {
            return classList;
        } else if (classList === undefined) {
            // 处理未定义的情况
            //console.warn('classList is undefined');
            return '';
        } else {
            // 处理其他非字符串情况
            console.error('Invalid classList:', classList);
            return classList;
        }
    }

    // 定义要删除的类名集合
    var classNamesToRemove = [
        'bili-video-card is-rcmd',
        'floor-single-card',
        'bili-live-card is-rcmd enable-no-interest',
        'recommended-swipe grid-anchor'
    ];

    function reEl(childNode){
        var classNames = sortClassNames(childNode.className);
        // 检查子节点的类名是否包含要删除的类名
        if (classNamesToRemove.some(cn => classNames == cn)) {
            childNode.remove();
            return false;
        } else if (classNames == 'feed-card') { // 如果子节点的类名包含 'feed-card'
            // 获取 feed-card 的子节点
            var feedCardChildren = childNode.children;
            var isRe = false;

            // 函数用于检查子节点的类名是否包含要删除的类名
            function hasClassToRemove(child) {
                var childNames = sortClassNames(child.className);
                return classNamesToRemove.some(cn => childNames == cn);
            }

            // 遍历 feed-card 的子节点,检查是否包含要删除的类名
            for (var j = 0; j < feedCardChildren.length; j++) {
                var feedCardChild = feedCardChildren[j];
                // 如果子节点的类名包含要删除的类名,则设置 isRe 为 true 并结束循环
                if (hasClassToRemove(feedCardChild)) {
                    isRe = true;
                    break;
                }
            }

            if(isRe){
                childNode.remove();
                return false;
            }
        }
        return true;
    }

    // 处理视频条目函数
    function handleVideoItems(videoItems) {
        // 正则表达式匹配数字ID的模式
        var regex = /\/(\d+)$/;

        // 遍历每个视频条目
        videoItems.forEach(function(item) {
            // 查找带有类名为 "bili-video-card__info--owner" 的元素
            var ownerLink = item.querySelector('.bili-video-card__info--owner');
            var idtext = '';
            // 检查是否找到了链接元素
            if (ownerLink) {
                // 获取链接的 href 属性值
                var hrefValue = ownerLink.getAttribute('href');
                // 使用正则表达式匹配数字ID
                var match = hrefValue.match(regex);
                if (match) {
                    idtext = match[1]; // 提取匹配到的数字ID
                } else {
                    console.error('未能匹配到数字ID');
                }
            }

            // 检查是否已经添加过“拉黑”链接
            if (!item.classList.contains('blacklisted')) {
                // 创建一个a标签元素
                var link = document.createElement('a');
                link.textContent = '拉黑'; // 链接显示的文本
                link.href = '#'; // 链接的目标URL

                // 添加自定义类以应用样式
                link.classList.add('custom-link');

                // 添加点击事件处理程序
                var isBlacklisted = false; // 拉黑状态,默认为 false
                link.addEventListener('click', function(event) {
                    // 阻止默认行为,例如不跳转到链接的href
                    event.preventDefault();

                    if (!isBlacklisted) {
                        // 如果未拉黑,则执行拉黑操作
                        addToBlack(idtext, 5);
                        link.textContent = '取消拉黑'; // 修改链接文本
                        isBlacklisted = true; // 更新状态为已拉黑
                    } else {
                        // 如果已拉黑,则执行取消拉黑操作
                        addToBlack(idtext, 6);
                        link.textContent = '拉黑'; // 修改链接文本
                        isBlacklisted = false; // 更新状态为未拉黑
                    }
                });

                // 将链接添加到视频条目中
                item.appendChild(link);

                // 添加已处理标记
                item.classList.add('blacklisted');
            }
        });
    }

    // 创建一个 MutationObserver 实例,监听 DOM 变化
    var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            // 检查每个变化是否是节点的添加
            mutation.addedNodes.forEach(function(addedNode) {
                //处理广告/推广等视频推广
                if(reEl(addedNode)){
                    // 如果添加的节点是你想要的视频条目元素,则执行相应的操作
                    if (addedNode.querySelectorAll && addedNode.querySelectorAll('.bili-video-card__info--bottom').length > 0) {
                        // 获取所有新增的视频条目的元素
                        var newVideoItems = addedNode.querySelectorAll('.bili-video-card__info--bottom');
                        // 处理新增的视频条目
                        handleVideoItems(newVideoItems);
                    }
                }

            });
        });
    });
    // 监听指定元素的变化
    var targetElement = document.querySelector('.container.is-version8') || document.querySelector('.channel-layout');

    if (!targetElement) {
        console.error('未找到指定元素');
        return;
    }

    // 配置 MutationObserver,指定要观察的节点和要观察的变化类型
    var config = {
        childList: true, subtree: true
    };

    // 将观察器绑定到指定元素上,并开始观察
    observer.observe(targetElement, config);

    // 获取所有子节点,并使用箭头函数遍历处理每个子节点
    Array.from(targetElement.children).forEach(childNode => reEl(childNode));

    // 处理初始视频条目
    var initialVideoItems = targetElement.querySelectorAll('.bili-video-card__info--bottom');
    //handleVideoItems(initialVideoItems);
    setTimeout(() => {
        handleVideoItems(initialVideoItems);
    }, 300);
    //test

})();