Bili-Recommended-List-Blocker

屏蔽b站首页推荐中的指定up

目前为 2021-12-25 提交的版本。查看 最新版本

// ==UserScript==
// @name         Bili-Recommended-List-Blocker
// @description  屏蔽b站首页推荐中的指定up
// @icon         http://www.bilibili.com/favicon.ico
// @namespace    https://gf.qytechs.cn/zh-CN/users/xxxxx
// @version      1.5
// @author       kuzen
// @run-at       document-start
// @include      *://www.bilibili.com/
// @include      *://www.bilibili.com/?*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';
    class BiliBlocker {
        constructor(blockList) {
            this.blockList = blockList;
            this.css = {
                blockDiv: '.bili-block-uid .bili-block-uid__icon{pointer-events:none;user-select:none;width:22px;height:22px;color:#fff}.bili-block-uid__icon{pointer-events:none;user-select:none;width:22px;height:22px;color:#fff;background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIyMiIgaGVpZ2h0PSIyMiIgdmlld0JveD0iMCAwIDQ4IDQ4IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgZmlsbD0id2hpdGUiIGZpbGwtb3BhY2l0eT0iMC4wMSIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjQgNDRDMzUuMDQ1NyA0NCA0NCAzNS4wNDU3IDQ0IDI0QzQ0IDEyLjk1NDMgMzUuMDQ1NyA0IDI0IDRDMTIuOTU0MyA0IDQgMTIuOTU0MyA0IDI0QzQgMzUuMDQ1NyAxMi45NTQzIDQ0IDI0IDQ0WiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZjNmM2YzIiBzdHJva2Utd2lkdGg9IjQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIGQ9Ik0xNSAxNUwzMyAzMyIgc3Ryb2tlPSIjZjNmM2YzIiBzdHJva2Utd2lkdGg9IjQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjwvc3ZnPg==)}.bili-block-uid{display:-webkit-flex;display:flex;align-items:center;justify-content:center;position:absolute;top:72px;right:8px;width:28px;height:28px;border-radius:6px;cursor:pointer;background-color:rgba(33,33,33,.8);z-index:9;transform:translateZ(0)}.bili-block-uid .bili-block-uid__tip{pointer-events:none;user-select:none;position:absolute;bottom:-6px;right:-10px;transform:translateY(100%);font-size:12px;color:#fff;border-radius:4px;line-height:18px;padding:4px 8px;background-color:rgba(0,0,0,.8);white-space:nowrap}',
                settingBtn: 'padding:0 4px;height:40px;text-align:center;font-size:12px',
                settings: '#balh-settings {font-size: 12px;color: #6d757a;}  #balh-settings h1 {color: #161a1e}  #balh-settings a {color: #00a1d6;}  #balh-settings a:hover {color: #f25d8e}  #balh-settings input {margin-left: 3px;margin-right: 3px;}  @keyframes balh-settings-bg { from {background: rgba(0, 0, 0, 0)} to {background: rgba(0, 0, 0, .7)} }  #balh-settings label {width: 100%;display: inline-block;cursor: pointer}  #balh-settings label:after {content: "";width: 0;height: 1px;background: #4285f4;transition: width .3s;display: block}  #balh-settings label:hover:after {width: 100%}  form {margin: 0}  #balh-settings input[type="radio"] {-webkit-appearance: radio;-moz-appearance: radio;appearance: radio;}  #balh-settings input[type="checkbox"] {-webkit-appearance: checkbox;-moz-appearance: checkbox;appearance: checkbox;} '
            };
            // 屏蔽块样式
            var blockDivSty = document.createElement('style');
            blockDivSty.innerHTML = this.css.blockDiv;
            document.head.appendChild(blockDivSty);

            this.blockBtnEnterFlag = false;

        }

        addBlockUid(blockList, uid) {
            var index = this.search(blockList, uid);
            if (blockList[index] !== uid) {
                blockList.splice(index, 0, uid);
                GM_setValue('blockList', JSON.stringify(blockList));
                return true;
            }
            return false;
        }

        // 添加屏蔽按钮
        addBlockBtn(cardView) {
            var blockBtnDiv = document.createElement("div");
            blockBtnDiv.setAttribute("class", "bili-block-uid");
            blockBtnDiv.setAttribute("style", "display: none;");
            blockBtnDiv.innerHTML = '<svg class="bili-block-uid__icon" style></svg>'
            this.blockBtnBind = this.blockBtnClick.bind(this);
            blockBtnDiv.addEventListener("click", this.blockBtnBind);
            blockBtnDiv.addEventListener("mouseleave", function () {
                this.blockBtnEnterFlag = false;
            });
            blockBtnDiv.addEventListener("mouseenter", function () {
                this.blockBtnEnterFlag = true;
            });
            cardView.insertBefore(blockBtnDiv, cardView.childNodes[1]);
        }

        // mouseEnter才显示按钮
        setCardViewEvent(cardView) {
            var cardImage = cardView.getElementsByClassName("bili-video-card__image--wrap")[0];
            cardImage.addEventListener("mouseenter", function (event) {
                var cardView = event.currentTarget.parentElement.parentElement.parentElement;
                // console.log(cardView)
                var blockDiv = cardView.getElementsByClassName("bili-block-uid")[0];
                blockDiv.setAttribute("style", "");
            });
            cardView.addEventListener("mouseleave", function (event) {
                var cardView = event.currentTarget;
                var blockDiv = cardView.getElementsByClassName("bili-block-uid")[0];
                if (this.blockBtnEnterFlag == false) {
                    blockDiv.setAttribute("style", "display: none;");
                }
            });
        }

        addSettingBtn() {
            var settingsDOM = createElement('div', {
                id: 'brlb-settings',
                style: {
                    position: 'fixed',
                    top: 0,
                    bottom: 0,
                    left: 0,
                    right: 0,
                    background: 'rgba(0,0,0,.7)',
                    animationName: 'brlb-settings-bg',
                    animationDuration: '.5s',
                    zIndex: 10000,
                    cursor: 'pointer'
                },
                event: {
                    click: function (e) {
                        if (e.target === this)
                            document.body.style.overflow = '', this.remove();
                    }
                }
            }, [
                createElement('style', {}, [createElement('text', this.css.settings)]),
                createElement('div', {
                    style: {
                        position: 'absolute',
                        background: '#FFF',
                        borderRadius: '10px',
                        padding: '20px',
                        top: '50%',
                        left: '50%',
                        width: '600px',
                        transform: 'translate(-50%,-50%)',
                        cursor: 'default'
                    }
                }, [
                    createElement('h1', {}, [createElement('text', `${GM_info.script.name} v${GM_info.script.version} 设置`)]),
                    createElement('br'),
                    createElement('br'),
                    createElement('form', {
                        id: 'brlb-settings-form',
                        // event: {
                        //     change: onSettingsFormChange
                        // }
                    }, [
                        createElement('a', {
                            href: 'javascript:',
                            'data-sign': 'in',
                            event: {
                                click: this.clrBlockList
                            }
                        }, [createElement('text', '清空黑名单 (刷新生效)')]),
                        createElement('text', ' '),
                        createElement('br'), createElement('br'),
                        createElement('div', {
                            style: {
                                whiteSpace: 'pre-wrap'
                            },
                            // event: {
                            //     mouseenter: onMouseEnterSettingBottom
                            // }
                        }, [
                            createElement('a', {
                                href: 'https://gf.qytechs.cn/zh-CN/scripts/437528-bili-recommended-list-blocker',
                                target: '_blank'
                            }, [createElement('text', '脚本主页')]),
                            createElement('text', ' '),
                            createElement('a', {
                                href: 'https://github.com/kuzen/Bili-Recommended-List-Blocker/blob/master/README.md',
                                target: '_blank'
                            }, [createElement('text', '帮助说明')]),

                        ])
                    ])
                ])
            ]);

            var btnWrap = document.getElementsByClassName("palette-button-wrap")[0];
            var firstBtn = btnWrap.getElementsByClassName("primary-btn")[1];
            var settingBtn = document.createElement("button");
            settingBtn.innerHTML = "屏蔽设置"
            settingBtn.setAttribute("class", "primary-btn block-setting-btn");
            settingBtn.setAttribute("style", this.css.settingBtn);
            settingBtn.addEventListener("click", function () {
                document.body.appendChild(settingsDOM);
            });
            btnWrap.insertBefore(settingBtn, firstBtn);
        }

        blockCardView(cardView, uid) {
            var blockContext = '<a target="_blank" data-spmid="333.851" data-mod="b_7265636f6d6d656e64" data-idx="1""><div class="bili-video-card__image __scale-player-wrap"><div class="bili-video-card__image--wrap"><div class="bili-watch-later" style="display: none;"><svg class="bili-watch-later__icon"><use xlink:href="#widget-watch-later"></use></svg><span class="bili-watch-later__tip" style="display: none;"></span></div><picture class="v-img bili-video-card__cover"><source srcset="//s6.jpg.cm/2021/12/23/LbJgzO.jpg" type="image/jpg"><img src="//s6.jpg.cm/2021/12/23/LbJgzO.jpg" alt="黑名单内容" loading="eager" onload="fsrCb()"></picture></div></div></a><div class="bili-video-card__info __scale-disable"><a target="_blank" data-spmid="333.851" data-mod="b_7265636f6d6d656e64" data-idx="1""><div class="v-avatar bili-video-card__avatar"><picture class="v-img v-avatar__face"><source srcset="//s6.jpg.cm/2021/12/23/LbJ0Iw.jpg" type="image/jpg"><img src="//s6.jpg.cm/2021/12/23/LbJ0Iw.jpg" alt="黑名单" loading="lazy" onload=""></picture></div></a><div class="bili-video-card__info--right"><a target="_blank" data-spmid="333.851" data-mod="b_7265636f6d6d656e64" data-idx="1""><h3 class="bili-video-card__info--tit" title="黑名单内容">黑名单内容</h3></a><p class="bili-video-card__info--bottom"><a class="bili-video-card__info--owner" data-spmid="333.851" data-mod="b_7265636f6d6d656e64" data-idx="1""><span class="bili-video-card__info--author">已屏蔽</span></a></p></div></div>';
            cardView.setAttribute("class", "bili-video-card__wrap __scale-wrap bili-block");
            cardView.setAttribute("data-uid", uid.toString());
            cardView.innerHTML = blockContext;
        }

        blockBtnClick(event) {
            var cardView = event.currentTarget.parentElement;
            var cardInfo = cardView.getElementsByClassName("bili-video-card__info")[0];
            var uidStr = cardInfo.firstElementChild["href"]
            if (uidStr.length > 0) {
                var uid = uidStr.substr(uidStr.lastIndexOf("/") + 1);
                console.log(uid + " 已屏蔽");
                if (this.addBlockUid(this.blockList, uid) == true) {
                    this.blockCardView(cardView, uid);
                }
                this.addBlockBtn(cardView);
                this.setCardViewEvent(cardView);
            }
            return false;
        };

        run(cardViewList) {
            // "eva-extension-area" or "recommend-container__"
            for (let cardView of cardViewList) {
                // item.replaceChildren(blockDom);
                // 判断是否屏蔽
                if (cardView.getElementsByClassName("bili-video-card__info--ad-img").length > 0) {
                    // 推广链接
                    this.blockCardView(cardView, 0);
                    this.addBlockBtn(cardView);
                    this.setCardViewEvent(cardView);
                } else {
                    // 普通视频
                    var uidStr = cardView.lastElementChild.firstElementChild["href"]
                    if (uidStr.length > 0) {
                        var uid = uidStr.substr(uidStr.lastIndexOf("/") + 1);
                        // console.log(uid);
                        var index = this.search(this.blockList, uid);
                        if (this.blockList[index] == uid) {
                            this.blockCardView(cardView, uid);
                        }
                    }
                    this.addBlockBtn(cardView);
                    this.setCardViewEvent(cardView);
                }
            }
        }

        clrBlockList() {
            GM_setValue("blockList", '[]');
            this.blockList = [];
        }

        search(nums, target) {
            const n = nums.length;
            let left = 0,
                right = n - 1,
                ans = n;
            while (left <= right) {
                let mid = ((right - left) >> 1) + left;
                if (target <= nums[mid]) {
                    ans = mid;
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
            return ans;
        };
    }

    var removeDuplicates = function (nums) {
        const n = nums.length;
        if (n === 0) {
            return 0;
        }
        let fast = 1,
            slow = 1;
        while (fast < n) {
            if (nums[fast] !== nums[fast - 1]) {
                nums[slow] = nums[fast];
                ++slow;
            }
            ++fast;
        }
        return slow;
    };

    /**
     * 创建元素的快捷方法:
     * 1. type, props, children
     * 2. type, props, innerHTML
     * 3. 'text', text
     * refer to: https://github.com/ipcjs/bilibili-helper
     * @param type string, 标签名; 特殊的, 若为text, 则表示创建文字, 对应的t为文字的内容
     * @param props object, 属性; 特殊的属性名有: className, 类名; style, 样式, 值为(样式名, 值)形式的object; event, 值为(事件名, 监听函数)形式的object;
     * @param children array, 子元素; 也可以直接是html文本;
     */
    function createElement(type, props, children) {
        let elem = null;
        if (type === "text") {
            return document.createTextNode(props);
        } else {
            elem = document.createElement(type);
        }
        for (let n in props) {
            if (n === "style") {
                for (let x in props.style) {
                    elem.style[x] = props.style[x];
                }
            } else if (n === "className") {
                elem.className = props[n];
            } else if (n === "event") {
                for (let x in props.event) {
                    elem.addEventListener(x, props.event[x]);
                }
            } else {
                // 用undefined表示不设置这个属性
                props[n] !== undefined && elem.setAttribute(n, props[n]);
            }
        }
        if (children) {
            if (typeof children === 'string') {
                elem.innerHTML = children;
            } else {
                for (let i = 0; i < children.length; i++) {
                    if (children[i] != null)
                        elem.appendChild(children[i]);
                }
            }
        }
        return elem;
    }

    // 读黑名单
    var blockList = JSON.parse(GM_getValue('blockList') || '[]');
    blockList.sort();
    console.log(GM_getValue('blockList'))
    removeDuplicates(blockList);
    var biliBlocker = new BiliBlocker(blockList);

    setTimeout(function () {

        //推荐列表
        var recommendList = document.querySelectorAll('div[class^="recommend-container__"]')[0].getElementsByClassName('bili-video-card__wrap');
        biliBlocker.run(recommendList);

        //推广列表
        var evaList = document.querySelectorAll('div[class^="eva-extension-area"]')[0].getElementsByClassName('bili-video-card__wrap');
        biliBlocker.run(evaList);

        // "换一换"按钮监听事件
        var rollBtn = document.getElementsByClassName("roll-btn-wrap")[0].firstElementChild;
        rollBtn.addEventListener("click", function () {
            setTimeout(function () {
                var recommendList = document.querySelectorAll('div[class^="recommend-container__"]')[0].getElementsByClassName('bili-video-card__wrap');
                biliBlocker.run(recommendList);
            }, 1000);
        });

        setTimeout(function () {
            // 右侧按钮栏加载更慢点
            biliBlocker.addSettingBtn();
        }, 1000);
    }, 1000);

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址