Greasy Fork is available in English.

bkBliBli

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

// ==UserScript==
// @name         bkBliBli
// @github       https://github.com/hunmeng/bkBilibili
// @description  哔哩哔哩首页快捷拉黑,去广告,直播推广
// @author       lkj
// @namespace    lkj
// @version      1.0.6
// @create       2024-05-06
// @lastmodified 2024-05-16
// @note         首次更新
// @charset      UTF-8
// @match        *://www.bilibili.com/*
// @match        https://api.bilibili.com/x/relation/modify
// @run-at       document-end
// @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');

    if (!targetElement) {
        console.error('未找到指定元素');
        return;
    }
    // 配置 MutationObserver,指定要观察的节点和要观察的变化类型
    var config = {
        childList: true // 观察子节点的添加或移除
    };

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

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

    // 处理初始视频条目
    var initialVideoItems = targetElement.querySelectorAll('.bili-video-card__info--bottom');
    handleVideoItems(initialVideoItems);

})();