- // ==UserScript==
- // @name 哔哩哔哩 - 屏蔽指定内容
- // @namespace https://greasyfork.org/zh-CN/users/193133-pana
- // @homepage https://greasyfork.org/zh-CN/users/193133-pana
- // @version 4.8.0
- // @description 实现可分别按用户名、关键字或正则表达式对视频(或直播间/相薄)和评论(或回复)进行屏蔽; 将鼠标移至网页右下角弹出悬浮按钮
- // @author pana
- // @include *://www.bilibili.com/*
- // @include *://search.bilibili.com/*
- // @include *://live.bilibili.com/*
- // @include *://space.bilibili.com/*
- // @include *://t.bilibili.com/*
- // @include *://h.bilibili.com/*
- // @include *://manga.bilibili.com/*
- // @include *://message.bilibili.com/*
- // @require https://cdn.jsdelivr.net/npm/arrive@2.4.1/minified/arrive.min.js
- // @require https://greasyfork.org/scripts/407543-block-obj/code/Block_Obj.js?version=963893
- // @require https://unpkg.com/dayjs@1.8.21/dayjs.min.js
- // @license GNU General Public License v3.0 or later
- // @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
- // @noframes
- // @note ----------------------------------------------------------------
- // @note 与"Bilibili 旧播放页"脚本(https://greasyfork.org/zh-CN/scripts/394296)的兼容问题:
- // @note 如果同时启用脚本后发现本脚本无法保存设置到存储中,请前往脚本管理器调整脚本执行顺序。
- // @note 具体方法可参考: https://greasyfork.org/zh-CN/scripts/397669
- // @note ----------------------------------------------------------------
- // @note 关于 "读取仅拥有标题的视频的用户名信息"
- // @note 原理是通过 API: "https://api.bilibili.com/x/web-interface/view"
- // @note 这个方法本质上是不可靠的,因为可能会由于快速大量进行请求从而导致被拦截 (如:频繁地在页面内刷新)
- // @note ----------------------------------------------------------------
- // @note 更新记录:
- // @note ver.4.8.0 优化关于动态的屏蔽功能
- // @note ver.4.7.0 支持在动态、视频播放等页面按粉丝勋章屏蔽评论
- // @note ver.4.6.4 补充覆盖视频播放页下部分内容
- // @note ver.4.6.3 修复添加正则表达式中存在逗号时录入出错的问题
- // @note ver.4.6.2 修复存在错误正则表达式时造成脚本失效的问题
- // @note ver.4.6.1 修复白名单效果未作用至动态上的问题
- // @note ver.4.6.0 支持用户白名单的功能
- // @note ver.4.5.0 支持按粉丝勋章屏蔽弹幕评论
- // @note ver.4.4.2 补充覆盖转发动态中的用户名
- // @note ver.4.4.1 修复上次更新导致屏蔽评论失效的问题
- // @note ver.4.4.0 优化脚本
- // @note ver.4.3.5 修复在视频关键字/正则表达式中添加单个空格时会导致所有视频被屏蔽的情况
- // @note ver.4.3.4 修复部分页面屏蔽失效的问题
- // @note ver.4.3.3 补充覆盖当前在线页面
- // @note ver.4.3.2 修复部分页面下按用户屏蔽失效的问题
- // @note ver.4.3.1 修复了由于上一版本的改动导致的脚本失效的问题
- // @note ver.4.3.0 兼容 Greasemonkey 4
- // @note ver.4.2.0 添加支持允许作用于动态的功能
- // @note ver.4.1.1 补充覆盖频道页面下内容
- // @note ver.4.1.0 允许在评论区显示屏蔽用户和"爆炸"按钮
- // @note ver.4.0.6 修复播放器网页全屏模式下的冲突问题
- // @note ver.4.0.4 尝试修复播放器网页全屏模式下可能的冲突问题
- // @note ver.4.0.3 修复已知的问题
- // @note ver.4.0.2 更换依赖库的 CDN
- // @note ver.4.0.0 整理并优化代码; 修复对于新添加的正则表达式,其无法在其他同步数据的标签页上生效的问题
- // @note ver.3.18.0 尝试通过 API 获取其他仅拥有标题的视频的用户名信息
- // @note ver.3.17.1 尝试通过 API 的方式读取专区热门列表里视频的用户名
- // @note ver.3.17.0 处理与"Bilibili 旧播放页"脚本不兼容的问题
- // @note ver.3.16.4 补充之前忘记匹配消息中心页面的问题; 补充覆盖番剧区页内的评论区; 修复了其他已知的问题
- // @note ver.3.16.0 增加 "消息中心 >> 回复我的" 的相关屏蔽,同时允许自动删除通知
- // @note ver.3.14.4 补充覆盖漫画页内的评论区
- // @note ver.3.14.3 增加相薄区的相关屏蔽; 完善部分未被覆盖的页面内容; 调整了使用关键字匹配表情的逻辑
- // @note ver.3.13.2 补充覆盖动态首页内的评论区
- // @note ver.3.13.1 修复可能无法匹配到用户动态页的问题
- // @note ver.3.13.0 实现多标签页同步数据; 调整取消按钮的行为; 覆盖视频播放完毕后的推荐视频; 兼容"Bilibili 旧播放页"脚本; 依旧存在的兼容问题: 在主页和视频播放页等页面下同时开启脚本时,本脚本无法保存设置到存储中
- // @note ver.3.11.0 增加直播区的相关屏蔽; 覆盖个人动态内的评论; 添加展开列表按钮
- // @note ver.3.7.1 添加删除按钮; 完善部分未被覆盖的页面内容
- // @note ver.3.5.3 修复部分页面下输入框内容看不清以及其他小问题
- // @note ver.3.5.0 优化代码; 完善部分未被覆盖的页面内容; 悬浮图标自动隐藏等
- // @note ver.2.2.0 添加允许将评论中的 b 站内置表情包转换成对应文字的功能
- // @note ver.2.1.2 修复储存正则表达式出错的问题; 优化代码
- // @note ver.2.1.0 添加允许按正则表达式进行屏蔽的功能
- // @note ver.2.0.0 调整了添加与删除关键字的方式,方便操作; 将评论与视频标题的关键词分开作用
- // @note ver.1.2.1 完善部分未被覆盖的页面内容
- // @note ver.1.2.0 添加屏蔽评论的功能
- // @note ver.1.1.2 调整屏蔽按钮的位置到右下角; 尝试处理脚本偶尔会失效的问题
- // @note ver.1.1.1 修复搜索页面以关键字屏蔽无效的问题
- // @note ver.1.1.0 匹配视频播放页面; 优化代码
- // ==/UserScript==
-
- (async function () {
- 'use strict';
- const OLD_URL = location.href;
- const MODULE = {
- USERNAME: {
- className: 'li_username',
- },
- WHITELIST: {
- className: 'li_whitelist',
- },
- VIDEO_KEYWORD: {
- className: 'li_video_keyword',
- },
- COMMENT_KEYWORD: {
- className: 'li_comment_keyword',
- },
- };
- const BASIC_STYLE = `
- .player-mode-webfullscreen,
- .mode-webfullscreen,
- .webfullscreen,
- .player-module {
- z-index: 100001 !important;
- }
- .bilibili_reply_bang_button,
- .bilibili_comment_bang_button,
- .bilibili_reply_user_block_button,
- .bilibili_comment_user_block_button {
- display: inline-block;
- padding: 0px 5px;
- border-radius: 4px;
- cursor: pointer;
- }
- .bilibili_reply_bang_button:hover,
- .bilibili_comment_bang_button:hover,
- .bilibili_reply_user_block_button:hover,
- .bilibili_comment_user_block_button:hover {
- color: #00a1d6;
- background-color: #e5e9ef;
- }
- `;
- const handler = [
- {
- index: '.video-card-common',
- user: ['a.up', 'a.ex-up'],
- text: ['a.title', 'p.ex-title'],
- method: 1,
- },
- {
- clientInformation: 0,
- index: '.video-card-reco',
- user: 'p.up',
- text: 'p.title',
- },
- {
- index: '.van-slide div.item',
- user: null,
- text: 'p.title',
- },
- {
- index: '.rank-wrap',
- user: 'span.name',
- text: ['p.f-title', 'p.title', 'div.txt a.link p'],
- },
- {
- index: '.article-card',
- user: 'a.up',
- text: 'a.title',
- method: 1,
- },
- {
- index: '.live-card',
- user: 'p.name',
- text: 'p.desc',
- method: 1,
- type: {
- live: true,
- },
- },
- {
- index: '.card-live-module',
- user: '.auther',
- text: 'p.t',
- method: 1,
- type: {
- live: true,
- },
- },
- {
- index: '.live-rank-item',
- user: 'div.txt > p',
- text: 'p.p2',
- method: 0,
- type: {
- live: true,
- },
- },
- {
- index: '.manga-card',
- user: null,
- text: 'p.manga-title',
- method: 1,
- },
- {
- index: '.manga-spread-module',
- user: null,
- text: 'p.t',
- method: 1,
- },
- {
- c: 1,
- index: '.groom-module',
- user: 'p.author',
- userReg: /^up主:/,
- text: 'p.title',
- },
- {
- index: 'ul.vd-list li',
- user: 'a.v-author',
- text: 'a.title',
- },
- {
- index: '.video-page-card, .video-page-operator-card',
- user: 'div.up',
- text: '.title',
- },
- {
- index: '.rank-list li.item',
- user: null,
- text: '> a',
- },
- {
- c: 2,
- index: '.storey-box .spread-module',
- bv: 'a',
- text: 'p.t',
- },
- {
- index: '.ebox',
- user: '.author',
- text: '.etitle',
- url: ['www.bilibili.com/video/', 'www.bilibili.com/bangumi/'],
- comment: true,
- },
- {
- index: '.article-list li',
- user: '.nick-name',
- text: '.article-title',
- url: 'www.bilibili.com/read/ranking',
- },
- {
- index: '.rank-video-card, .video-card',
- user: '.up-name',
- text: '.video-name',
- url: ['www.bilibili.com/v/channel', 'www.bilibili.com/v/popular'],
- },
- {
- index: '.video-item',
- user: 'a.up-name',
- text: 'a.title',
- url: 'search.bilibili.com',
- },
- {
- index: '.live-user-item',
- user: '.uname',
- text: null,
- method: 0,
- type: {
- live: true,
- },
- url: 'search.bilibili.com',
- },
- {
- index: '.live-room-item',
- user: '.uname span',
- text: '.item-title',
- method: 0,
- type: {
- live: true,
- },
- url: 'search.bilibili.com',
- },
- {
- index: '.photo-item',
- user: '.up-name',
- text: '.title',
- method: 0,
- type: {
- pic: true,
- },
- url: 'search.bilibili.com',
- },
- {
- index: '.rank-item',
- user: '.room-anchor',
- text: '.room-title',
- method: 0,
- type: {
- live: true,
- },
- url: 'live.bilibili.com',
- comment: true,
- },
- {
- index: '.room-card-wrapper',
- user: '.room-anchor > span',
- text: '.room-title',
- method: 0,
- type: {
- live: true,
- },
- url: 'live.bilibili.com',
- },
- {
- index: '.ysly-room-ctnr li',
- user: '.uname',
- text: '.room-name',
- method: 0,
- type: {
- live: true,
- },
- url: 'live.bilibili.com',
- },
- {
- index: 'ul.list li',
- user: '.room-anchor > span',
- text: '.room-title',
- method: 0,
- type: {
- live: true,
- },
- url: 'live.bilibili.com',
- },
- {
- index: '.card-items li',
- user: '.uname',
- text: '.room-name',
- method: 0,
- type: {
- live: true,
- },
- },
- {
- index: '.content li',
- user: '.user-container a span',
- text: '.article-title a',
- method: 0,
- type: {
- pic: true,
- },
- url: 'h.bilibili.com',
- comment: true,
- },
- {
- index: '.rank-list > div',
- user: ['.name', '.user-name'],
- text: ['.title', '.work-name'],
- method: 0,
- type: {
- pic: true,
- },
- url: 'h.bilibili.com',
- },
- {
- index: '.canvas-card',
- user: '.user-container a span',
- text: '.article-title a',
- method: 1,
- type: {
- pic: true,
- },
- url: 'h.bilibili.com',
- },
- ];
- let bilibiliConfig = {
- functionEnable: true,
- usernameEnable: true,
- keywordEnable: true,
- whitelistEnable: false,
- commentEnable: false,
- commentKeywordEnable: false,
- commentFans: false,
- convertEmojiEnable: false,
- showBlockUserBtnEnable: false,
- showBangBtnEnable: false,
- liveEnable: false,
- picEnable: false,
- messageReplyEnable: false,
- messageReplyDelEnable: false,
- dynamicVideo: false,
- dynamicContent: false,
- usernameArray: [],
- keywordArray: [],
- commentArray: [],
- whitelistArray: [],
- };
- let infoRecord = [];
- const tempRecord = Block_Obj.GM.getValue('infoRecord', []);
- tempRecord.forEach(item => {
- if (dayjs().diff(item.time, 'd') <= 3) {
- infoRecord.push(item);
- }
- });
- let delNum = 0;
- let recordButton = [];
- let requestTotal = 0;
- let sendStatus = true;
- const INTERVAL_TIME = 100;
- if (typeof Block_Obj !== 'function') {
- alert('Block_Obj.js was not loaded successfully.');
- } else if (typeof Block_Obj.fn.compare !== 'function') {
- alert('The version of Block_Obj.js is too low.');
- }
- let blockObj = new Block_Obj('bilibili_config', [
- {
- key: 'keywordArray',
- ori: 'regArray',
- },
- {
- key: 'commentArray',
- ori: 'commentRegArray',
- },
- ]);
- await document.arrive('body', { fireOnAttributesModification: true, onceOnly: true, existing: true }, async function () {
- await blockObj.init({
- id: 'bilibiliConfig',
- menu: 'bilibili_屏蔽设置',
- style: BASIC_STYLE,
- field: [
- {
- id: 'functionEnable',
- label: '启用屏蔽功能',
- title: '总开关',
- type: 'c',
- default: true,
- },
- {
- id: 'whitelistEnable',
- label: '启用白名单',
- title: '白名单用户的视频(或直播间/相薄)以及评论(或回复)不会被屏蔽',
- type: 'c',
- default: false,
- move_right: true,
- },
- {
- label: '屏蔽视频(或直播间/相薄):',
- type: 's',
- },
- {
- id: 'usernameEnable',
- label: '按用户名',
- title: '屏蔽指定用户发布的视频(或直播间/相薄)',
- type: 'c',
- default: true,
- },
- {
- id: 'keywordEnable',
- label: '按关键字或正则',
- title: '屏蔽标题中包含指定关键字或匹配正则表达式的视频(或直播间/相薄)',
- type: 'c',
- default: true,
- move_right: true,
- },
- {
- id: 'liveEnable',
- label: '直播间',
- title: '扩展作用范围以同时允许屏蔽直播间',
- type: 'c',
- default: false,
- move_right: true,
- },
- {
- id: 'picEnable',
- label: '相薄',
- title: '扩展作用范围以同时允许屏蔽相薄',
- type: 'c',
- default: false,
- move_right: true,
- },
- {
- id: 'dynamicVideo',
- label: '动态',
- title: '允许屏蔽转发、分享指定用户的动态\n允许屏蔽视频标题匹配关键字或正则的动态',
- type: 'c',
- default: false,
- move_right: true,
- },
- {
- label: '屏蔽评论(或回复):',
- type: 's',
- },
- {
- id: 'commentEnable',
- label: '按用户名',
- title: '屏蔽指定用户发布的评论(或回复)',
- type: 'c',
- default: false,
- },
- {
- id: 'commentKeywordEnable',
- label: '按关键字或正则',
- title: '屏蔽内容中包含指定关键字或匹配正则表达式的评论(或回复)',
- type: 'c',
- default: false,
- move_right: true,
- },
- {
- id: 'commentFans',
- label: '按粉丝勋章',
- title: '屏蔽直播间中挂有指定粉丝勋章用户发布的弹幕评论\n屏蔽动态、视频播放等页面中挂有指定粉丝勋章用户发布的评论',
- type: 'c',
- default: false,
- move_right: true,
- },
- {
- id: 'dynamicContent',
- label: '动态',
- title: '允许屏蔽动态内容(包含转发、分享)匹配关键字或正则的动态',
- type: 'c',
- default: false,
- move_right: true,
- },
- {
- type: 'br',
- },
- {
- id: 'convertEmojiEnable',
- label: '表情转成文字',
- title:
- '判定时将表情包转换成对应的标识文字,例:[鸡腿]、[tv_白眼]等\n注意:使用关键字来匹配表情时,必须包含完整的中括号对;\n如 "鸡腿" 是无法匹配表情 [鸡腿] 的,需使用 "[鸡腿]" 进行匹配',
- type: 'c',
- default: false,
- },
- {
- id: 'showBlockUserBtnEnable',
- label: '显示屏蔽用户按钮',
- title: '在评论在底部显示一个屏蔽该用户的按钮',
- type: 'c',
- default: false,
- move_right: true,
- },
- {
- id: 'showBangBtnEnable',
- label: '显示"爆炸"按钮',
- title: '在评论底部显示一个可以拆分并选择文本内容的按钮',
- type: 'c',
- default: false,
- move_right: true,
- },
- {
- type: 'br',
- },
- {
- id: 'messageReplyEnable',
- label: '消息中心里的回复',
- title: '扩展作用范围以同时允许屏蔽消息中心里的回复',
- type: 'c',
- default: false,
- },
- {
- id: 'messageReplyDelEnable',
- label: '自动删除回复通知',
- title: '同时将屏蔽的回复通知自动删除\n删除的记录可在控制台中查看\n请谨慎启用该选项,因为删除操作是不可逆的!',
- type: 'c',
- default: false,
- move_right: true,
- },
- {
- type: 's',
- },
- {
- type: 's',
- label: '白名单 (用户名):',
- classname: MODULE.WHITELIST.className,
- },
- {
- id: 'whitelistInput',
- label: '输入:',
- placeholder: ' 同时输入多个时以半角逗号分隔 ',
- type: 'i',
- list_id: 'whitelistArray',
- classname: MODULE.WHITELIST.className,
- },
- {
- id: 'whitelistArray',
- type: 'l',
- default: [],
- classname: MODULE.WHITELIST.className,
- },
- {
- type: 's',
- },
- {
- type: 's',
- label: '黑名单 (用户名/粉丝勋章名):',
- classname: MODULE.USERNAME.className,
- },
- {
- id: 'usernameInput',
- label: '输入:',
- placeholder: ' 同时输入多个时以半角逗号分隔 ',
- type: 'i',
- list_id: 'usernameArray',
- classname: MODULE.USERNAME.className,
- },
- {
- id: 'usernameArray',
- type: 'l',
- default: [],
- classname: MODULE.USERNAME.className,
- },
- {
- type: 's',
- },
- {
- type: 's',
- label: '视频(或直播间/相薄)关键字或正则:',
- classname: MODULE.VIDEO_KEYWORD.className,
- },
- {
- id: 'videoKeywordInput',
- label: '输入:',
- placeholder: ' 正则表达式格式: /Pattern/Modifier ',
- type: 'i',
- list_id: 'keywordArray',
- classname: MODULE.VIDEO_KEYWORD.className,
- },
- {
- id: 'keywordArray',
- type: 'l',
- default: [],
- classname: MODULE.VIDEO_KEYWORD.className,
- },
- {
- type: 's',
- },
- {
- type: 's',
- label: '评论(或回复)关键字或正则:',
- classname: MODULE.COMMENT_KEYWORD.className,
- },
- {
- id: 'commentKeywordInput',
- label: '输入:',
- placeholder: ' 正则表达式格式: /Pattern/Modifier ',
- type: 'i',
- list_id: 'commentArray',
- classname: MODULE.COMMENT_KEYWORD.className,
- },
- {
- id: 'commentArray',
- type: 'l',
- default: [],
- classname: MODULE.COMMENT_KEYWORD.className,
- },
- {
- type: 's',
- },
- ],
- events: {
- save: config => {
- bilibiliConfig = config;
- hideEvent();
- },
- change: config => {
- bilibiliConfig = config;
- hideEvent();
- },
- },
- });
- bilibiliConfig = blockObj.getConfig();
- hideEvent();
- try {
- let observer = new MutationObserver(() => {
- hideEvent();
- });
- observer.observe(document.querySelector('body'), {
- childList: true,
- subtree: true,
- });
- } catch (e) {
- console.error(e);
- }
- if (/www\.bilibili\.com\/?(\/\?spm_id_from=.*)?$/.test(OLD_URL)) {
- document.querySelector('.btn.next') &&
- document.querySelector('.btn.next').addEventListener('click', () => {
- setTimeout(() => {
- hideEvent();
- }, 250);
- });
- document.querySelector('.btn.prev') &&
- document.querySelector('.btn.prev').addEventListener('click', () => {
- setTimeout(() => {
- hideEvent();
- }, 250);
- });
- document.body.arrive(
- '.manga-panel .btn-change',
- {
- fireOnAttributesModification: true,
- onceOnly: true,
- existing: true,
- },
- item => {
- item.addEventListener('click', () => {
- setTimeout(() => {
- hideEvent();
- }, 1000);
- });
- }
- );
- document.body.arrive(
- '.manga-panel .tab-switch-item',
- {
- fireOnAttributesModification: true,
- onceOnly: true,
- existing: true,
- },
- item => {
- item.addEventListener('click', () => {
- setTimeout(() => {
- hideEvent();
- }, 1000);
- });
- }
- );
- }
- if (/live\.bilibili\.com\/all/.test(OLD_URL)) {
- document.body.arrive(
- '.content-panel h1.title > span',
- {
- fireOnAttributesModification: true,
- onceOnly: true,
- existing: true,
- },
- item => {
- item.addEventListener('click', () => {
- setTimeout(() => {
- hideEvent();
- }, 1000);
- });
- }
- );
- }
- });
- function displayDel(panelId, num) {
- if (document.getElementById(panelId)) {
- document.getElementById(panelId).textContent = ' (自动删除了 ' + num + ' 条通知)';
- } else {
- const delPanel = document.createElement('span');
- delPanel.id = panelId;
- delPanel.textContent = ' (自动删除了 ' + num + ' 条通知)';
- document.querySelector('.space-right-top .title').appendChild(delPanel);
- }
- }
- function decideText(
- textValue,
- isComment = false,
- isLive = false,
- isPic = false,
- sourceText = null,
- isMessageReply = false,
- dynamicVideo = null,
- dynamic = null,
- repost = null
- ) {
- let isDecide = false;
- let isDecideComment = false;
- let isDecideDynamic = false;
- let isDecideDynamicTitle = false;
- let isDecideDynamicContent = false;
- let isDecideDynamicRepost = false;
- if (bilibiliConfig.functionEnable) {
- if (textValue) {
- if (isComment) {
- if (isMessageReply) {
- if (bilibiliConfig.messageReplyEnable) {
- isDecideComment = true;
- }
- } else {
- isDecideComment = true;
- }
- } else if (isLive) {
- if (bilibiliConfig.liveEnable) {
- isDecide = true;
- }
- } else if (isPic) {
- if (bilibiliConfig.picEnable) {
- isDecide = true;
- }
- } else {
- isDecide = true;
- }
- } else {
- if (bilibiliConfig.dynamicVideo && dynamicVideo) {
- isDecideDynamic = true;
- isDecideDynamicTitle = true;
- }
- if (bilibiliConfig.dynamicContent && dynamic) {
- isDecideDynamic = true;
- isDecideDynamicContent = true;
- }
- if (bilibiliConfig.dynamicContent && repost) {
- isDecideDynamic = true;
- isDecideDynamicRepost = true;
- }
- }
- }
- if (isDecide) {
- if (bilibiliConfig.keywordEnable) {
- for (let k of bilibiliConfig.keywordArray) {
- if (k) {
- if (typeof k === 'string' && textValue.includes(k)) {
- return true;
- } else {
- try {
- if (textValue.match(k)) {
- return true;
- }
- } catch (e) {
- console.error('存在错误的正则表达式: ', e);
- }
- }
- }
- }
- }
- } else if (isDecideComment) {
- if (bilibiliConfig.commentKeywordEnable) {
- for (let i of bilibiliConfig.commentArray) {
- if (i) {
- if (typeof i === 'string') {
- if (textValue.includes(i)) {
- if (sourceText) {
- if (sourceText.includes(i)) {
- return true;
- } else if (/\[.*\]/i.test(i)) {
- return true;
- }
- } else {
- return true;
- }
- } else if (sourceText && /\[.*\]/i.test(i)) {
- if (sourceText.includes(i)) {
- return true;
- }
- }
- } else {
- try {
- if (textValue.match(i)) {
- return true;
- } else if (sourceText.match(i)) {
- return true;
- }
- } catch (e) {
- console.error('存在错误的正则表达式: ', e);
- }
- }
- }
- }
- }
- } else if (isDecideDynamic) {
- let dynamicStatus = false;
- if (isDecideDynamicTitle) {
- if (bilibiliConfig.keywordEnable) {
- for (let o of bilibiliConfig.keywordArray) {
- if (o) {
- if (typeof o === 'string' && dynamicVideo.includes(o)) {
- dynamicStatus = true;
- break;
- } else {
- try {
- if (dynamicVideo.match(o)) {
- dynamicStatus = true;
- break;
- }
- } catch (e) {
- console.error('存在错误的正则表达式: ', e);
- }
- }
- }
- }
- }
- }
- if (!dynamicStatus && dynamic.content && isDecideDynamicContent) {
- if (bilibiliConfig.commentKeywordEnable) {
- for (const q of bilibiliConfig.commentArray) {
- if (q) {
- if (typeof q === 'string') {
- if (dynamic.content.includes(q)) {
- if (dynamic.sourceContent) {
- if (dynamic.sourceContent.includes(q)) {
- dynamicStatus = true;
- break;
- } else if (/\[.*\]/i.test(q)) {
- dynamicStatus = true;
- break;
- }
- } else {
- dynamicStatus = true;
- break;
- }
- } else if (dynamic.sourceContent && /\[.*\]/i.test(q)) {
- if (dynamic.sourceContent.includes(q)) {
- dynamicStatus = true;
- break;
- }
- }
- } else {
- try {
- if (dynamic.content.match(q)) {
- dynamicStatus = true;
- break;
- } else if (dynamic.sourceContent.match(q)) {
- dynamicStatus = true;
- break;
- }
- } catch (e) {
- console.error('存在错误的正则表达式: ', e);
- }
- }
- }
- }
- }
- }
- if (!dynamicStatus && repost.content && isDecideDynamicRepost) {
- if (bilibiliConfig.commentKeywordEnable) {
- for (const r of bilibiliConfig.commentArray) {
- if (r) {
- if (typeof r === 'string') {
- if (repost.content.includes(r)) {
- if (repost.sourceContent) {
- if (repost.sourceContent.includes(r)) {
- dynamicStatus = true;
- break;
- } else if (/\[.*\]/i.test(r)) {
- dynamicStatus = true;
- break;
- }
- } else {
- dynamicStatus = true;
- break;
- }
- } else if (repost.sourceContent && /\[.*\]/i.test(r)) {
- if (repost.sourceContent.includes(r)) {
- dynamicStatus = true;
- break;
- }
- }
- } else {
- try {
- if (repost.content.match(r)) {
- dynamicStatus = true;
- break;
- } else if (repost.sourceContent.match(r)) {
- dynamicStatus = true;
- break;
- }
- } catch (e) {
- console.error('存在错误的正则表达式: ', e);
- }
- }
- }
- }
- }
- }
- return dynamicStatus;
- }
- return false;
- }
- function decideUsername(
- username,
- isComment = false,
- isLive = false,
- isPic = false,
- isMessageReply = false,
- trueLove = null,
- repostUser = null
- ) {
- let isDecide = false;
- if (bilibiliConfig.functionEnable && username) {
- if (isComment) {
- if (bilibiliConfig.commentEnable) {
- if (isMessageReply) {
- if (bilibiliConfig.messageReplyEnable) {
- isDecide = true;
- }
- } else {
- isDecide = true;
- }
- }
- } else if (isLive) {
- if (bilibiliConfig.liveEnable) {
- if (bilibiliConfig.usernameEnable) {
- isDecide = true;
- }
- }
- } else if (isPic) {
- if (bilibiliConfig.picEnable) {
- if (bilibiliConfig.usernameEnable) {
- isDecide = true;
- }
- }
- } else {
- if (bilibiliConfig.usernameEnable) {
- isDecide = true;
- }
- }
- }
- if (isDecide) {
- if (bilibiliConfig.usernameArray.includes(username)) {
- return true;
- }
- }
- if (bilibiliConfig.functionEnable) {
- if (bilibiliConfig.commentFans && trueLove) {
- if (bilibiliConfig.usernameArray.includes(trueLove)) {
- return true;
- }
- }
- if (bilibiliConfig.dynamicVideo && repostUser) {
- if (bilibiliConfig.usernameArray.includes(repostUser)) {
- return true;
- }
- }
- }
- return false;
- }
- function isWhitelist(username) {
- if (username && bilibiliConfig.functionEnable && bilibiliConfig.whitelistEnable) {
- if (bilibiliConfig.whitelistArray.includes(username)) {
- return true;
- }
- }
- return false;
- }
- function hideHandler(itemNode, username, textValue, method = 0, type = {}) {
- if (username) {
- if (typeof username === 'object') {
- username = username.textContent;
- }
- username = username.trim();
- }
- if (textValue) {
- if (typeof textValue === 'object') {
- textValue = textValue.textContent;
- }
- textValue = textValue.trim();
- }
- const isComment = type.comment ? true : false;
- const isMessageReply = type.messageReply ? true : false;
- const delButton = type.delButton ? type.delButton : null;
- const isLive = type.live ? true : false;
- const isPic = type.pic ? true : false;
- const trueLove = type.trueLove ? type.trueLove.trim() : null;
- const dynamic = type.dynamic != null && typeof type.dynamic === 'object' ? type.dynamic : null;
- const dynamicVideo = type.dynamicVideo ? type.dynamicVideo.trim() : null;
- const repost = type.repost != null && typeof type.repost === 'object' ? type.repost : null;
- const repostUser = type.repostUser ? type.repostUser.trim() : null;
- const sourceText = type.sourceText ? type.sourceText : null;
- let hideStatus = false;
- if (isWhitelist(username)) {
- hideStatus = false;
- } else if (decideUsername(username, isComment, isLive, isPic, isMessageReply, trueLove, repostUser)) {
- hideStatus = true;
- } else if (decideText(textValue, isComment, isLive, isPic, sourceText, isMessageReply, dynamicVideo, dynamic, repost)) {
- hideStatus = true;
- } else {
- hideStatus = false;
- }
- if (itemNode.constructor == Array) {
- for (let eleNode of itemNode) {
- if (eleNode) {
- Block_Obj.fn.hideOperation(eleNode, hideStatus, method);
- }
- }
- } else {
- Block_Obj.fn.hideOperation(itemNode, hideStatus, method);
- }
- if (hideStatus) {
- if (delButton) {
- if (bilibiliConfig.messageReplyDelEnable && !recordButton.includes(delButton)) {
- recordButton.push(delButton);
- delButton.click();
- console.info('%c自动删除通知:', 'color: purple;', '\n用户名:', username, '\n评论内容:', textValue);
- delNum++;
- displayDel('messageDelPanel', delNum);
- }
- }
- }
- }
- function extractEle(ele, selector) {
- let result = null;
- if (selector) {
- if (Array.isArray(selector)) {
- for (const e of selector) {
- if (ele.querySelector(e)) {
- result = ele.querySelector(e);
- break;
- }
- }
- } else {
- result = ele.querySelector(selector);
- }
- }
- return result;
- }
- function hideEvent() {
- handler.forEach(item => {
- const { c, index, user, text, method, type, userReg, url, comment, bv } = item;
- let status = false;
- if (url) {
- if (Array.isArray(url)) {
- for (let u of url) {
- if (OLD_URL.indexOf(u) !== -1) {
- status = true;
- break;
- }
- }
- } else {
- status = OLD_URL.indexOf(url) !== -1;
- }
- } else {
- status = OLD_URL.indexOf('www.bilibili.com') !== -1;
- }
- if (status) {
- const all = document.querySelectorAll(index);
- for (const ele of all) {
- if (c == 1) {
- hideHandler(ele, extractEle(ele, user).textContent.replace(userReg, ''));
- } else if (c == 2) {
- const bvNum = getBvNumber(ele.querySelector(bv).href);
- asyncUsernameHandle(bvNum, ele, extractEle(ele, text));
- } else {
- hideHandler(ele, extractEle(ele, user), extractEle(ele, text), method, type);
- }
- }
- if (comment) {
- hideComment();
- }
- }
- });
- if (OLD_URL.indexOf('www.bilibili.com') !== -1) {
- try {
- const carouselModulePanel = document.querySelector('.carousel-module .panel');
- if (carouselModulePanel) {
- const carouselModulePanelTitle = carouselModulePanel.querySelectorAll('ul.title a');
- const carouselModulePanelPic = carouselModulePanel.querySelectorAll('ul.pic li');
- const carouselModulePanelTrig = carouselModulePanel.querySelectorAll('ul.trig span');
- for (let panelIndex = 0; panelIndex < carouselModulePanelTitle.length; panelIndex++) {
- hideHandler(
- [carouselModulePanelTitle[panelIndex], carouselModulePanelPic[panelIndex], carouselModulePanelTrig[panelIndex]],
- null,
- carouselModulePanelTitle[panelIndex],
- 3
- );
- }
- }
- } catch (e) {
- console.error('bilibili_BLock: Variable carouselModulePanel is error.');
- console.error(e);
- }
- const rankItem = document.getElementsByClassName('rank-item');
- for (const rankItemEle of rankItem) {
- let textValue = '';
- if (rankItemEle.querySelector('p.ri-title')) {
- textValue = rankItemEle.querySelector('p.ri-title');
- }
- if (rankItemEle.querySelector('a.title')) {
- textValue = rankItemEle.querySelector('a.title');
- }
- if (rankItemEle.querySelector('.detail > a')) {
- hideHandler(rankItemEle, rankItemEle.querySelector('.detail > a'), textValue);
- } else if (rankItemEle.querySelector('a')) {
- const linkA = rankItemEle.querySelector('a');
- const bvNum = getBvNumber(linkA.href);
- asyncUsernameHandle(bvNum, rankItemEle, textValue);
- }
- }
- const recentHot = document.querySelectorAll('div#recent_hot li');
- for (const recentHotItem of recentHot) {
- const bvNum = getBvNumber(recentHotItem.querySelector('a').href);
- asyncUsernameHandle(bvNum, recentHotItem, recentHotItem.title);
- }
- const bilibiliPlayerRecommendVideo = document.getElementsByClassName('bilibili-player-recommend-video');
- for (const bilibiliPlayerRecommendVideoItem of bilibiliPlayerRecommendVideo) {
- const bvNum = getBvNumber(bilibiliPlayerRecommendVideoItem.href);
- asyncUsernameHandle(
- bvNum,
- bilibiliPlayerRecommendVideoItem,
- bilibiliPlayerRecommendVideoItem.querySelector('.bilibili-player-recommend-title')
- );
- }
- const bilibiliPlayerEndingPanelBoxRecommend = document.querySelectorAll('a.bilibili-player-ending-panel-box-recommend');
- for (const bilibiliPlayerEndingPanelBoxRecommendItem of bilibiliPlayerEndingPanelBoxRecommend) {
- let bvNum = '';
- try {
- bvNum = /(?:av|bv)(\w+)/i.exec(bilibiliPlayerEndingPanelBoxRecommendItem.getAttribute('data-bvid'))[1];
- } catch (e) {
- bvNum = null;
- }
- if (!bvNum) {
- try {
- bvNum = getBvNumber(bilibiliPlayerEndingPanelBoxRecommendItem.href);
- } catch (e) {
- bvNum = null;
- }
- }
- asyncUsernameHandle(
- bvNum,
- bilibiliPlayerEndingPanelBoxRecommendItem,
- bilibiliPlayerEndingPanelBoxRecommendItem.querySelector('.bilibili-player-ending-panel-box-recommend-cover-title')
- );
- }
- } else if (/(t|manga|space)\.bilibili\.com/.test(OLD_URL)) {
- const card = document.querySelectorAll('div.card');
- for (const cardItem of card) {
- const contentFull = cardItem.querySelector('.content-full');
- let sourceContent = null;
- let convertText = null;
- if (contentFull && !contentFull.closest('.repost')) {
- sourceContent = contentFull.textContent;
- if (bilibiliConfig.convertEmojiEnable) {
- convertText = getConvertText(contentFull.innerHTML);
- }
- }
- const title = cardItem.querySelector('.title');
- let titleText = null;
- if (title) {
- titleText = title.textContent;
- }
- let repostUser = cardItem.querySelector('.repost .username');
- repostUser = repostUser ? repostUser.textContent : null;
- let repostSourceText = null;
- let repostConvertText = null;
- const repostContent = cardItem.querySelector('.repost .content-full');
- if (repostContent) {
- repostSourceText = repostContent.textContent;
- if (bilibiliConfig.convertEmojiEnable) {
- repostConvertText = getConvertText(repostContent.innerHTML);
- }
- }
- if (bilibiliConfig.convertEmojiEnable) {
- hideHandler(cardItem, null, null, 0, {
- dynamicVideo: titleText,
- dynamic: {
- content: convertText,
- sourceContent: sourceContent,
- },
- repostUser,
- repost: {
- content: repostConvertText,
- sourceContent: repostSourceText,
- },
- });
- } else {
- hideHandler(cardItem, null, null, 0, {
- dynamicVideo: titleText,
- dynamic: {
- content: sourceContent,
- },
- repostUser,
- repost: {
- content: repostSourceText,
- },
- });
- }
- }
- hideComment();
- } else if (/message\.bilibili\.com\/#\/reply/.test(OLD_URL)) {
- const replyItem = document.getElementsByClassName('reply-item');
- for (const replyItemEle of replyItem) {
- let nextNode = null;
- if (replyItemEle.nextElementSibling) {
- if (replyItemEle.nextElementSibling.classList.contains('divider')) {
- nextNode = replyItemEle.nextElementSibling;
- }
- }
- const sourceText = replyItemEle.querySelector('.text').textContent;
- if (bilibiliConfig.convertEmojiEnable) {
- const convertText = replyItemEle.querySelector('.text span').innerHTML.replace(/<img.*alt="(.*)".*>/g, '$1');
- hideHandler([replyItemEle, nextNode], replyItemEle.querySelector('.name-field a'), convertText, 0, {
- comment: true,
- messageReply: true,
- sourceText: sourceText,
- delButton: replyItemEle.querySelector('.bl-button--primary'),
- });
- } else {
- hideHandler([replyItemEle, nextNode], replyItemEle.querySelector('.name-field a'), sourceText, 0, {
- comment: true,
- messageReply: true,
- delButton: replyItemEle.querySelector('.bl-button--primary'),
- });
- }
- }
- } else if (/live\.bilibili\.com\/\d+/.test(OLD_URL)) {
- const chatItems = document.querySelectorAll('#chat-items .chat-item');
- chatItems.forEach(item => {
- const fansMedalContent = item.querySelector('.fans-medal-content');
- hideHandler(item, null, null, 0, {
- trueLove: fansMedalContent ? fansMedalContent.textContent : null,
- });
- });
- }
- }
- function hideComment() {
- const commentList = document.querySelectorAll('.comment-list .list-item');
- for (const commentListItem of commentList) {
- const sourceText = commentListItem.querySelector('.con > p.text').textContent;
- let trueLove = commentListItem.querySelector('.true-love');
- trueLove = trueLove ? trueLove.firstChild.textContent : null;
- if (bilibiliConfig.convertEmojiEnable) {
- const convertText = getConvertText(commentListItem.querySelector('.con > p.text').innerHTML);
- hideHandler(commentListItem, commentListItem.querySelector('.con > .user a.name'), convertText, 0, {
- comment: true,
- sourceText: sourceText,
- trueLove,
- });
- } else {
- hideHandler(commentListItem, commentListItem.querySelector('.con > .user a.name'), sourceText, 0, {
- comment: true,
- trueLove,
- });
- }
- const commentReplyBtn = commentListItem.querySelector('.reply.btn-hover');
- if (bilibiliConfig.showBlockUserBtnEnable) {
- commentReplyBtn &&
- !commentListItem.querySelector('.bilibili_comment_user_block_button') &&
- commentReplyBtn.after(
- blockObj.createBlockBtn(
- commentListItem.querySelector('.con > .user a.name').textContent,
- 'usernameArray',
- 'bilibili_comment_user_block_button',
- 'span',
- '屏蔽',
- '屏蔽该用户'
- )
- );
- } else {
- commentListItem.querySelector('.bilibili_comment_user_block_button') &&
- commentListItem.querySelector('.bilibili_comment_user_block_button').remove();
- }
- if (bilibiliConfig.showBangBtnEnable) {
- const commentBtn = commentListItem.querySelector('.bilibili_comment_user_block_button') || commentReplyBtn;
- commentBtn &&
- !commentListItem.querySelector('.bilibili_comment_bang_button') &&
- commentBtn.after(
- blockObj.createBigBangBtn(
- sourceText,
- 'commentArray',
- 'bilibili_comment_bang_button',
- 'span',
- '爆炸',
- '拆分并选择文本内容进行屏蔽'
- )
- );
- } else {
- commentListItem.querySelector('.bilibili_comment_bang_button') &&
- commentListItem.querySelector('.bilibili_comment_bang_button').remove();
- }
- }
- const replyCommentList = document.querySelectorAll('.comment-list .reply-item');
- for (const replyCommentListItem of replyCommentList) {
- const replySourceText = replyCommentListItem.querySelector('.reply-con .text-con').textContent;
- if (bilibiliConfig.convertEmojiEnable) {
- const replyConvertText = getConvertText(replyCommentListItem.querySelector('.reply-con .text-con').innerHTML);
- hideHandler(replyCommentListItem, replyCommentListItem.querySelector('.reply-con .user a.name'), replyConvertText, 0, {
- comment: true,
- sourceText: replySourceText,
- });
- } else {
- hideHandler(replyCommentListItem, replyCommentListItem.querySelector('.reply-con .user a.name'), replySourceText, 0, {
- comment: true,
- });
- }
- const replyBtn = replyCommentListItem.querySelector('.reply.btn-hover');
- if (bilibiliConfig.showBlockUserBtnEnable) {
- replyBtn &&
- !replyCommentListItem.querySelector('.bilibili_reply_user_block_button') &&
- replyBtn.after(
- blockObj.createBlockBtn(
- replyCommentListItem.querySelector('.reply-con .user a.name').textContent,
- 'usernameArray',
- 'bilibili_reply_user_block_button',
- 'span',
- '屏蔽',
- '屏蔽该用户'
- )
- );
- } else {
- replyCommentListItem.querySelector('.bilibili_reply_user_block_button') &&
- replyCommentListItem.querySelector('.bilibili_reply_user_block_button').remove();
- }
- if (bilibiliConfig.showBangBtnEnable) {
- const pBtn = replyCommentListItem.querySelector('.bilibili_reply_user_block_button') || replyBtn;
- pBtn &&
- !replyCommentListItem.querySelector('.bilibili_reply_bang_button') &&
- pBtn.after(
- blockObj.createBigBangBtn(
- replySourceText,
- 'commentArray',
- 'bilibili_reply_bang_button',
- 'span',
- '爆炸',
- '拆分并选择文本内容进行屏蔽'
- )
- );
- } else {
- replyCommentListItem.querySelector('.bilibili_reply_bang_button') &&
- replyCommentListItem.querySelector('.bilibili_reply_bang_button').remove();
- }
- }
- }
- function getConvertText(text) {
- return text
- .replace(/<img.*?alt="(.*?)".*?>/g, '$1')
- .replace(/<a.*?>(.*?)<\/\s*a>/g, '$1')
- .replace(/ /g, ' ');
- }
- function asyncUsernameHandle(bvNum, mainEle, textValue, hideMethod = 0, typeInfo = {}) {
- let userName = '';
- if (bvNum) {
- let recordUser = false;
- infoRecord.forEach(item => {
- if (item.bv == bvNum) {
- userName = item.user;
- recordUser = true;
- }
- });
- if (recordUser) {
- hideHandler(mainEle, userName, textValue, hideMethod, typeInfo);
- } else {
- infoRecord.push({
- bv: bvNum,
- user: userName,
- time: dayjs().format('YYYY-MM-DD'),
- });
- const apiUrl = bvNum.match(/^\d+$/)
- ? 'https://api.bilibili.com/x/web-interface/view?aid='
- : 'https://api.bilibili.com/x/web-interface/view?bvid=';
- const xhr = new XMLHttpRequest();
- xhr.open('GET', apiUrl + bvNum, true);
- xhr.responseType = 'json';
- xhr.onload = () => {
- if (xhr.status == 200) {
- if (xhr.response.data && xhr.response.data.owner && xhr.response.data.owner['name']) {
- userName = xhr.response.data.owner['name'];
- }
- } else {
- sendStatus = false;
- console.info(apiUrl + bvNum + '\nresponse status: ' + xhr.status);
- }
- hideHandler(mainEle, userName, textValue, hideMethod, typeInfo);
- infoRecord.forEach(item => {
- if (item.bv == bvNum) {
- item.user = userName;
- }
- });
- Block_Obj.GM.setValue('infoRecord', infoRecord);
- };
- xhr.onerror = () => {
- console.info(apiUrl + bvNum + '\nerror.');
- hideHandler(mainEle, userName, textValue, hideMethod, typeInfo);
- };
- setTimeout(() => {
- sendStatus && xhr.send();
- }, INTERVAL_TIME * requestTotal);
- requestTotal++;
- }
- } else {
- hideHandler(mainEle, userName, textValue, hideMethod, typeInfo);
- }
- }
- function getBvNumber(video_link) {
- let bvNum = '';
- try {
- bvNum = /\/video\/(?:av|bv)(\w+)/i.exec(video_link)[1];
- } catch (e) {
- bvNum = null;
- }
- return bvNum;
- }
- })();