Greasy Fork

Greasy Fork is available in English.

BiliBili Tags Blocker BiliBili标签屏蔽助手

眼不见为净,耳不听为清,心不想则静

当前为 2022-11-07 提交的版本,查看 最新版本

// ==UserScript==
// @name         BiliBili Tags Blocker BiliBili标签屏蔽助手
// @namespace    http://greasyfork.icu/zh-CN/users/924205-xiao-xi
// @version      0.10.1
// @description  眼不见为净,耳不听为清,心不想则静
// @author       xiaoxi
// @license      MIT
// @include      *://www.bilibili.com/*
// @include      *://t.bilibili.com/*
// @include      *://search.bilibili.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @require      https://cdn.bootcdn.net/ajax/libs/jquery/2.2.4/jquery.min.js
// @require      https://unpkg.com/[email protected]/dist/ajaxhook.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/minified/arrive.min.js
// @require      http://greasyfork.icu/scripts/407543-block-obj/code/Block_Obj.js?version=963893
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @grant        GM_getValue
// @grant        GM.getValue
// @grant        GM_setValue
// @grant        GM.setValue
// @grant        GM_setClipboard
// @grant        GM.setClipboard
// @grant        GM_registerMenuCommand
// @grant        GM_addValueChangeListener
// @run-at       document-start
// ==/UserScript==
var tagsBlocker = {
    functionEnable: true,
    onlyChangeColorEnable: false,
    blurMode: false,
    hiddenMode: false,
    tagsArray: [],
    titlesArray: [],

};

var href = location.href;
var matchSearch = href.match(/search.bilibili/);
var matchPopular = href.match(/popular/);
var matchRank = href.match(/\/popular\/rank/);
var matchPost = href.match(/t.bilibili/);
var matchVideo = href.match(/video/);
var matchHome = href.match(/bilibili.com/);

var blockObj = new Block_Obj('Tags_Blocker');

const BASIC_STYLE = `
     .block_obj_checkbox_label {
         padding-left: 13px;
     }
  `;

const tagsApi = 'https://api.bilibili.com/x/web-interface/view/detail/tag?bvid=';

//加载选项
document.arrive("body", { fireOnAttributesModification: true, onceOnly: true, existing: true }, function() {
    initSettingUI()

});

function initSettingUI(){
    blockObj.init({
        id: 'tagsBlocker',
        menu: '屏蔽设置',
        style: BASIC_STYLE,
        field: [
            {
                id: 'version',
                label: 'v0.10.1',
                type: 's',
            },
            {
                id: 'functionEnable',
                label: '启用屏蔽功能',
                title: '总开关',
                type: 'c',
                default: true,
            },
            {
                id: 'onlyChangeColorEnable',
                label: '看看屏蔽了什么',
                title: '更改屏蔽视频的背景色',
                type: 'c',
                default: false,
            },
            {
                label: '屏蔽模式',
                type: 's',
            },
            {
                id: 'blurMode',
                label: '模糊模式',
                type: 'c',
                default: false,
            },
            {
                id: 'hiddenMode',
                label: '隐藏模式',
                type: 'c',
                default: false,
            },
            {
                id: 'tagInput',
                label: '',
                placeholder: ' 同时输入多个时以英文逗号分隔 ',
                type: 'i',
                list_id: 'tagsArray',
            },
            {
                id: 'tagsArray',
                type: 'l',
                default: [],
            },
            {
                label: '标题关键字 (例如‘原 神’标题,请输入‘原神’)',
                type: 's',
            },
            {
                id: 'titleInput',
                label: '',
                placeholder: ' 同时输入多个时以英文逗号分隔 ',
                type: 'i',
                list_id: 'titlesArray',
            },
            {
                id: 'titlesArray',
                type: 'l',
                default: [],
            },

        ],
        events: {
            save: config => {
                tagsBlocker = config;
            },
            change: config => {
                tagsBlocker = config;
            },
        },
    })
}

class VideoCard{
    constructor(card,title,bv) {
        this.card = card;
        this.title = replaceAllSymbol(title);
        this.bv = bv;
        this.tags = null;
        this.typeName = null;
    }
}

class Listener{
    constructor(targetNode, nth, options = {}) {
        this.targetNode = targetNode;
        this.nth = nth;
        this.options = options;

    }
    init(initMethod,callMethod){
        let targetNode = $(this.targetNode)[this.nth];
        let options = this.options;
        function callback(mutationsList, observer) {
            if(mutationsList.length >= 1 && mutationsList[0].addedNodes.length!=0){
                callFunc(callMethod,mutationsList)
            }
        }
        let mutationObserver = new MutationObserver(callback);
        let checkTarget = setInterval(function () {
            if(targetNode !=  undefined && targetNode != null){
                mutationObserver.observe(targetNode, options);
                callFunc(initMethod,targetNode)
                clearInterval(checkTarget);
            }
            else
            {
                targetNode = $(this.targetNode)[this.nth];
            }

        }, 50);
    }
}

class Match{
    init(url,parameter,callMethod){
        $.ajax(url + parameter.bv, {
            method: 'GET',
            headers: {
                "content-type": "application/json"
            },
            async: true,
            success: function (result) {
                parameter.tags = result.data
                callFunc(callMethod,parameter)

            },
        });
    }
}
var match = new Match();
//==视频页==//
function videoInit(card){
    let info = $(card).children(".card-box").children(".info").children("a")
    let href = $(info).attr("href");
    let title = $(info).children('span').attr("title");
    let videoCard = $(card);
    let bv = getBvcountber(href);
    let v1 = new VideoCard(videoCard,title,bv);
    return v1
}
function videoListenerInit(targetNode){
    $.each($(targetNode).children(".video-page-card"), function(i, card){
        let v1 = videoInit(card)
        match.init(tagsApi,v1,finalMatch)
    });
}
function videoListenerCall(targetNode){
    $.each(targetNode, function(i, m){
        let v1 = videoInit(m.addedNodes[0])
        match.init(tagsApi,v1,finalMatch)
    });
}
function ad1(){
    //.video-page-special-card
    //#live_recommand_report
    //#activity_vote
    document.arrive(".video-page-special-card", { fireOnAttributesModification: true, onceOnly: true, existing: true }, function() {
        $(this).css({"display":"none"});
    });
    document.arrive("#live_recommand_report", { fireOnAttributesModification: true, onceOnly: true, existing: true }, function() {
        $(this).css({"display":"none"});
    });
    document.arrive("#activity_vote", { fireOnAttributesModification: true, onceOnly: true, existing: true }, function() {
        $(this).css({"display":"none"});
    });
    //结束视频
    $(document).arrive('.bpx-player-ending-related', {fireOnAttributesModification: true, onceOnly: true, existing: true},function(){
        $(this).remove();
        $('.bpx-player-ending-functions').animate({
            marginTop: 145, opacity: 'show'
        }, "slow");
    })
    $(document).arrive('.bpx-player-popup', {fireOnAttributesModification: true, onceOnly: false, existing: true},function(){
        $(this).remove();
    })
    $(document).arrive('.bpx-player-follow', {fireOnAttributesModification: true, onceOnly: false, existing: true},function(){
        $(this).remove();
    })
    //三连
    $(document).arrive('.bpx-player-popup-guide-all', {fireOnAttributesModification: true, onceOnly: false, existing: true},function(){
        $(this).remove();
    })
    //投票
    $(document).arrive('.bpx-player-popup-vote', {fireOnAttributesModification: true, onceOnly: false, existing: true},function(){
        $(this).remove();
    })
    //跳转其他视频
    $(document).arrive('.bpx-player-link', {fireOnAttributesModification: true, onceOnly: false, existing: true},function(){
        $(this).remove();
    })
    //评分
    $(document).arrive('.bpx-player-score', {fireOnAttributesModification: true, onceOnly: false, existing: true},function(){
        $(this).remove();
    })
    //推广视频
    $(document).arrive('.video-ad-creative-card', {fireOnAttributesModification: true, onceOnly: true, existing: true},function(){
        $(this).css({"display":"none"})
    })
    //右下角推广
    $(document).arrive('#right-bottom-banner', {fireOnAttributesModification: true, onceOnly: true, existing: true},function(){
        $(this).css({"display":"none"})
    })
}
$(document).arrive('.reply-notice', {fireOnAttributesModification: true, onceOnly: false, existing: true},function(){
    $(this).css({"display":"none"})
})
$(document).arrive('.trending', {fireOnAttributesModification: true, onceOnly: false, existing: true},function(){
    $(this).css({"display":"none"})
})
//==动态导航栏==//
function navbarInit(card){
    let href = $(card).children(".main-container").children("a").attr("href");
    let title = $(card).children(".main-container").children(".center-box").children("a").attr('title')
    let videoCard = $(card);
    let bv = getBvcountber(href)
    let v1 = new VideoCard(videoCard,title,bv);
    return v1
}
function navbarListenerInit(targetNode){
    $.each($(targetNode).children(".list-item"), function(i, card){
        let v1 = navbarInit(card)
        match.init(tagsApi,v1,finalMatch)
    });
}
function navbarListenerCall(targetNode){
    $.each(targetNode, function(i, m){
        let v1 = navbarInit(m.addedNodes[0])
        match.init(tagsApi,v1,finalMatch)
    });
}

//==热门页面==//
function initPopularVideoInfo(url){
    let l1 = url.indexOf('pn=');
    let num = url.substring(l1+3,url.length)
    let checkTarget = setInterval(function () {
        let videoCardList = $(".video-card__content");
        if(videoCardList != null && videoCardList != undefined){
            if(num != 1){
                if(BiliBiliTagsBlocker.blurMode){
                    videoCardList = videoCardList.slice((num-1)*20,videoCardList.length)
                }
            }
            videoCardList.each(function(i){
                let href = $(this).children("a").attr("href");
                let videoCard = $(this).parent(".video-card");
                let title = $($(videoCard).children(".video-card__info")).children("p").attr("title");
                let v1 = new VideoCard(videoCard,title,"BV"+getBvcountber(href));
                match.init(tagsApi,v1,finalMatch)

            });
        }
    }, 50);
}

//==排行榜==//
function initRankVideoInfo(){
    let videoCardList = $(".rank-item");
    if(!location.href.match(/\/rank\/bangumi/) || !location.href.match(/\/rank\/guochan/) || !location.href.match(/\/rank\/documentary/) || !location.href.match(/\/rank\/movie/) || !location.href.match(/\/rank\/tv/) || !location.href.match(/\/rank\/variety/)){
        let checkTarget = setInterval(function () {
            if(videoCardList != null && videoCardList != undefined && videoCardList.length != 0){
                clearInterval(checkTarget);
                videoCardList.each(function(i){
                    let info = $(this).children(".content").children(".info").children("a");
                    let href = $(info).attr("href");
                    let title = $(info).text();
                    let videoCard = $(this);
                    let v1 = new VideoCard(videoCard,title,"BV"+getBvcountber(href));
                    match.init(tagsApi,v1,finalMatch)
                });
            }
            else{
                videoCardList = $(".rank-item");
            }
        }, 50);

    }
}

//==搜索页==//
function initSearchVideoInfo(responses){
    let checkTarget = setInterval(function () {
        if(responses.length >= 1){
            let r = []
            let checkTarget1 = setInterval(function () {
                if(r.length > 1 ){
                    setVideoInfo(r[0])
                    clearInterval(checkTarget1);

                }
                else
                {
                    $.each(responses,function(i,t){
                        if(t.result_type == 'video'){
                            r.push(t)
                        }
                    })
                }
            }, 50);
            clearInterval(checkTarget);
        }

    }, 50);
}

function setVideoInfo(tagList){
    let videoList = $('.video-list.clearfix').children('.video-item.matrix')
    videoList.each(function(i,v){
        let tags = tagList.data[i].tag.split(',');
        let typeName = tagList.data[i].typename;
        let title = $($($(v).children('.info')).children('.headline')).children('a').attr('title')
        let v1 = new VideoCard($(v),title,-1);
        let newTags = [];
        tags.map(function(item) {
            let t = {tag_name : item}
            newTags.push(t)
        });
        v1.tags = newTags;
        v1.typeName = typeName;
        finalMatch(v1)

    })
}

//==动态==//
function initPostVideoInfo(){
    let postCardList = $(".bili-dyn-list__items").children(".bili-dyn-list__item");
    $(postCardList).each(function(i){
        let info = $(this).children(".bili-dyn-item").children(".bili-dyn-item__main").children(".bili-dyn-item__body").children(".bili-dyn-content").children(".bili-dyn-content__orig").children(".bili-dyn-content__orig__major").children("a");
        let bv = getBvcountber($(info).attr("href"));
        let title = $(info).children('.bili-dyn-card-video__body');
        if (title.length == 1){
            title = title.children('.bili-dyn-card-video__title').text();
        }
        else{
            title = '';
        }
        let videoCard = $(this).children(".bili-dyn-item").children(".bili-dyn-item__main");
        let v1 = new VideoCard($(this),title,bv);
        match.init(tagsApi,v1,finalMatch)

    });
}
function matchTopic(){
    $(document).arrive('.relevant-topic__title', {fireOnAttributesModification: true, onceOnly: true, existing: true},function(){
        let parent = $($(this).parents('.relevant-topic'));
        let title = $(this).text();
        let successed = false;
        $.each(tagsBlocker.tagsArray,function(i,tag){
            if((title.indexOf(tag) != -1 || title.indexOf(tagsBlocker.titlesArray[i]) != -1) && !successed)
            {
                if(tagsBlocker.onlyChangeColorEnable){
                    parent.css({"background":"blue"})
                }else{
                    if(tagsBlocker.blurMode){
                        parent.css({"filter":"blur(1rem)"});
                    }
                    if(tagsBlocker.hiddenMode){
                        parent.css({"display":"none"});
                    }
                }

                successed = true;
            }
        })
    })
}

//==首页==//
function homeInit(card){
    let href = $(card).children(".info-box").children("a").attr("href");
    let title =  $(card).children(".info-box").children("a").children(".info").children(".title").attr('title')
    let videoCard = $(card);
    let bv = getBvcountber(href)
    let v1 = new VideoCard(videoCard,title,bv);
    return v1
}
function homeListenerInit(){
    $.each($('.video-card-reco'), function(i, card){
        let v1 = homeInit(card)
        match.init(tagsApi,v1,finalMatch)
    });
}

function finalMatch(parameter){
    let successed = false;
    $.each(parameter.tags,function(i,tag){
        $.each(tagsBlocker.tagsArray,function(i,mtag){
            //匹配到
            if((tag.tag_name.indexOf(mtag) != -1 || parameter.title.indexOf(tagsBlocker.titlesArray[i]) != -1 || tag.tag_name.indexOf(parameter.typeName) != -1) && !successed)
            {
                if(tagsBlocker.onlyChangeColorEnable){
                    parameter.card.css({"background":"blue"})
                }else{
                    if(tagsBlocker.blurMode){
                        parameter.card.css({"filter":"blur(1rem)"});
                    }
                    if(tagsBlocker.hiddenMode){
                        parameter.card.css({"display":"none"});
                    }
                }
                successed = true
            }
        })
    })
}


function reSetUI(){
    let count = 0;
    document.arrive(".block_obj_input_btn", { fireOnAttributesModification: true, onceOnly: false, existing: true }, function() {
        if($(this).attr('title') == '展开列表'){
            let index = count
            let targetNode = $($('.block_obj_list_textarea_div')[index]);
            $(this).click(function(){
                if(!targetNode.hasClass('expand')){
                    targetNode.animate({
                        maxHeight: 300, opacity: 'show'
                    }, "slow");
                    targetNode.addClass("expand");
                }
                else
                {
                    targetNode.animate({
                        maxHeight: 65, opacity: 'show'
                    }, "slow");
                    targetNode.removeClass("expand");
                }
            });
            count ++
        }
    });
    if (window.parent == window) {
        // 当前页面不在iframe中
    }
    else
    {
        $('#blockObj_tagsBlocker_expandSpan').animate({
            opacity: 'hide'
        }, 140);
    }
}


if (window.parent == window) {
    // 当前页面不在iframe中
    ajaxHook();
}
else
{
    // 当前页面在iframe或者frameset中

}



function ajaxHook() {
    ah.proxy(
        {
            onResponse: (response, handler) => {
                //搜索页 例/all?keyword=原神
                if (!response.config.url.includes('/web-interface/search/default') && !response.config.url.includes('/web-interface/search/square') && response.config.url.includes('/web-interface/search')){
                    let responses = [];
                    let data = JSON.parse(response.response).data
                    if(data.result.length == 11){
                        responses.push(data.result[data.result.length-1])
                    }
                    if(data.result.length == 20){
                        let data1 = {
                            data: data.result,
                            result_type: 'video'
                        }
                        responses.push(data1)
                    }
                    initSearchVideoInfo(responses)

                }
                //热门页面
                if (response.config.url.includes('/web-interface/popular')){
                    initPopularVideoInfo(response.config.url)
                }
                //排行榜
                if (response.config.url.includes('rank')){
                    initRankVideoInfo()
                }
                //首页
                if (response.config.url.includes('web-interface/index/top/rcmd')){
                    setTimeout(function(){
                        homeListenerInit()
                    },50);
                }
                //动态
                if (response.config.url.includes('web-dynamic/v1/feed/all')){
                    setTimeout(function(){
                        initPostVideoInfo()
                    },50);

                }
                handler.next(response);
            },
        },
        unsafeWindow
    );

}

//移除所有符号
var symbols = [' ','♂','【','】']

function replaceAllSymbol(title) {
    $.each(symbols,function(i,k){
        if(title.indexOf(k) != -1){
            title = title.replaceAll(k,'')
        }
    })
    return title;
}

//通过url获得BV号
function getBvcountber(video_link) {
    let bvcount = '';
    try {
        bvcount = /\/video\/(?:av|bv)(\w+)/i.exec(video_link)[1];
    } catch (e) {
        bvcount = null;
    }
    return bvcount;
}

//通过名称调用方法
function callFunc(functionName){
    //根据函数名得到函数类型
    var  func=eval(functionName);
    //创建函数对象,并调用
    new func(arguments[1],arguments[2],arguments[3]);
}

//检查jQuery
var checkJQuery = function () {
    let jqueryCdns = [
        'http://code.jquery.com/jquery-2.1.4.min.js',
        'https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js',
        'https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js',
        'https://cdn.staticfile.org/jquery/2.1.4/jquery.min.js',
        'https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js',
    ];
    function isJQueryValid() {
        try {
            let wd = unsafeWindow;
            if (wd.jQuery && !wd.$) {
                wd.$ = wd.jQuery;
            }
            $();
            return true;
        } catch (exception) {
            return false;
        }
    }
    function insertJQuery(url) {
        setTimeout(function(){
            let checkJQuery = setInterval(function () {
                if(document == undefined && document != null && document.createElement('script') == undefined && document.createElement('script') != null){
                    let script = document.createElement('script');
                    script.src = url;
                    document.head.appendChild(script);
                    return script;
                    clearInterval(checkJQuery);
                }
            }, 100);
        },500);
    }
    function converProtocolIfNeeded(url) {
        let isHttps = location.href.indexOf('https://') != -1;
        let urlIsHttps = url.indexOf('https://') != -1;
        return script;

        if (isHttps && !urlIsHttps) {
            return url.replace('http://', 'https://');
        } else if (!isHttps && urlIsHttps) {
            return url.replace('https://', 'http://');
        }
        return url;
    }
    function waitAndCheckJQuery(cdnIndex, resolve) {
        if (cdnIndex >= jqueryCdns.length) {
            iLog.e('无法加载 JQuery,正在退出。');
            resolve(false);
            return;
        }
        let url = converProtocolIfNeeded(jqueryCdns[cdnIndex]);
        iLog.i('尝试第 ' + (cdnIndex + 1) + ' 个 JQuery CDN:' + url + '。');
        let script = insertJQuery(url);
        setTimeout(function () {
            if (isJQueryValid()) {
                iLog.i('已加载 JQuery。');
                resolve(true);
            } else {
                iLog.w('无法访问。');
                script.remove();
                waitAndCheckJQuery(cdnIndex + 1, resolve);
            }
        }, 100);
    }
    return new Promise(function (resolve) {
        if (isJQueryValid()) {
            iLog.i('已加载 jQuery。');
            resolve(true);
        } else {
            iLog.i('未发现 JQuery,尝试加载。');
            waitAndCheckJQuery(0, resolve);
        }
    });
}

//检查脚本参数
var checkScriptVariate = setInterval(function () {
    tagsBlocker = blockObj.getConfig();
    if(tagsBlocker.tagsArray != null){
        clearInterval(checkScriptVariate);
    }
}, 500);

function ILog() {
    this.prefix = '';

    this.v = function (value) {
        if (level <= this.LogLevel.Verbose) {
            console.log(this.prefix + value);
        }
    }

    this.i = function (info) {
        if (level <= this.LogLevel.Info) {
            console.info(this.prefix + info);
        }
    }

    this.w = function (warning) {
        if (level <= this.LogLevel.Warning) {
            console.warn(this.prefix + warning);
        }
    }

    this.e = function (error) {
        if (level <= this.LogLevel.Error) {
            console.error(this.prefix + error);
        }
    }

    this.d = function (element) {
        if (level <= this.LogLevel.Verbose) {
            console.log(element);
        }
    }

    this.setLogLevel = function (logLevel) {
        level = logLevel;
    }

    this.LogLevel = {
        Verbose: 0,
        Info: 1,
        Warning: 2,
        Error: 3,
    };

    let level = this.LogLevel.Verbose;
}
var inChecking = false;
var matchSuccess = false;
var jqItv = setInterval(function () {
    if (inChecking) {
        return;
    }
    inChecking = true;
    checkJQuery().then(function (isLoad) {
        if (isLoad)
        {
            //动态导航栏
            let navbarListener = new Listener('.video-list', 0, {childList: true})
            navbarListener.init(navbarListenerInit,navbarListenerCall)
            //视频页
            if (matchVideo && tagsBlocker.functionEnable && !matchSuccess) {
                matchSuccess = true;
                let videoListener = new Listener('.rec-list', 0, {childList: true})
                videoListener.init(videoListenerInit,videoListenerCall)
                ad1()
            }
            //搜索页
            if (matchSearch && tagsBlocker.functionEnable && !matchSuccess) {
                matchSuccess = true;
                $('div.search-button').click()
            }
            //动态
            if (matchPost && tagsBlocker.functionEnable && !matchSuccess) {
                matchSuccess = true;
                matchTopic()
            }
            //排行榜
            if (matchRank && tagsBlocker.functionEnable && !matchSuccess) {
                matchSuccess = true;
                initRankVideoInfo()
            }
            //首页
            if (matchHome && tagsBlocker.functionEnable && !matchSuccess) {
                matchSuccess = true;
                homeListenerInit()
            }
            reSetUI()
            clearInterval(jqItv);
        }
        inChecking = false;
    });
}, 500);
var iLog = new ILog();