bili_rebuild

b站评论过滤器

// ==UserScript==
// @name bili_rebuild
// @description b站评论过滤器
// @license MIT
// @namespace dreamcenter
// @version 1.0.0.5
// @match *://*.bilibili.com/*
// @grant GM_xmlhttpRequest
// ==/UserScript==

/*******************************下方内容可以修改***************************************/

// 通常文本词汇屏蔽
let banMap = [
    'test','随机','恶心','病','纯','ch','CH','op','策划'
];

// 小表情屏蔽,按个人需要填写
let banSmallEmoji = [
    // '吃瓜','给心心','嗑瓜子'
];

// 屏蔽带有 @某人 的,默认不开启,按个人需要开启
let banAtSomeone = false

// 屏蔽笔记功能,默认不开启,按个人需要开启
let banNote = false

/*************** 下方内容通常不需要修改 *****************/

// 是否对屏蔽条目隐藏[true/false]
let hiddenMode = true

// 是否连接到云屏蔽词库[true/false]
let cloudBanMap = false

// 是否控制台打印屏蔽日志[true/false]
let logShield = false

/*******************************下方内容不要修改***************************************/

function filterStr(item){
    var str=''
    var childs = item.childNodes;
    childs.forEach((subitem,index)=>{
        if(subitem.nodeType===3){
            str = subitem.nodeValue;
            for(var i=0;i<banMap.length;i++){
                // only chromn: str = str.replaceAll(banMap[i],'█')
                str = str.replace(new RegExp(banMap[i],"gm"),'█')
            }
            subitem.nodeValue = str;
        }
    })
}

function hiddenWay(item, newVer){
    var str=''
    var childs = item.childNodes;
    childs.forEach((subitem,index)=>{
        if(subitem.nodeType===3){ // 纯文本
            str = subitem.nodeValue;
            for(var i=0;i<banMap.length;i++){
                // only chromn: str = str.replaceAll(banMap[i],'█(' + banMap[i] + ')')
                str = str.replace(new RegExp(banMap[i],"gm"),'█(' + banMap[i] + ')')
            }
            subitem.nodeValue = str;

            if(str.indexOf('█')!=-1){
                if (logShield) console.log('!  :\n' + subitem.nodeValue)
                handleHidden(item, newVer, false)
            }
        } else if (subitem.className != '' && subitem.className != undefined){ // 富文本
            switch(subitem.className) {
                case 'jump-link user': // @某人
                    if (banAtSomeone) {
                        handleHidden(item, newVer, false)
                    }
                    break;
                case 'emoji-small': // 小表情
                    for(var j=0;j<banSmallEmoji.length;j++){
                        if (subitem.getAttribute('alt').indexOf(banSmallEmoji[j]) >= 0){
                            handleHidden(item, newVer, false)
                        }
                    }
                    break;
                case 'note-prefix':
                    if (banNote) {
                        handleHidden(item, newVer, false)
                    }
                    break;
                default:
                    // console.log(subitem.className)
                    break;
            }
        }
    })
}

function handleHidden(item, newVer, testMode) {
    let targetItem = item.parentNode.parentNode;
    if (newVer && item.parentNode.parentNode.getAttribute("class").indexOf("root-reply") != -1) {
        // new version root reply
        targetItem = targetItem.parentNode.parentNode.parentNode
    }

    if (!newVer && item.nodeName.toLocaleLowerCase() == 'span'){
        // old version  root reply
        targetItem = targetItem.parentNode
    }

    if (testMode) targetItem.style.background = 'gray'
    else targetItem.style.display = 'none'
}

function cloud(){
    GM_xmlhttpRequest({
        method: 'GET',
        url: "https://dreamcenter.github.io/test",
        onload: function (res) {
            let str = res.response.replace('\n','')
            banMap.push(...str.split(','))
            console.log(banMap)
        },
        onerror: function (err) {
            alert("服务器连接失败")
        }
    })
}

(function () {
    'use strict';
    window.onload = function(){

        // connect to the cloud ban map to get common ban map
        if(cloudBanMap) cloud()

        // detect and filter
        let newVersion = true
        setInterval(()=>{
            let replies = document.querySelectorAll('p.text:not([filtered]),span.text-con:not([filtered])')

            // version judge
            newVersion = replies.length == 0
            if (newVersion) replies = document.querySelectorAll('span.reply-content:not([filtered]),span.sub-reply-content:not([filtered])')

            replies.forEach((item,index)=>{
                if (hiddenMode) hiddenWay(item, newVersion)
                else filterStr(item)
                item.setAttribute('filtered',true)
            })
        },100)
    }
})();