哔哩哔哩 - 屏蔽指定内容

实现可分别按用户名、关键字或正则表达式对视频(或直播间/相薄)和评论(或回复)进行屏蔽; 将鼠标移至网页右下角弹出悬浮按钮

// ==UserScript==
// @name         哔哩哔哩 - 屏蔽指定内容
// @namespace    biliblockorder
// @version      4.9.2
// @description  实现可分别按用户名、关键字或正则表达式对视频(或直播间/相薄)和评论(或回复)进行屏蔽; 将鼠标移至网页右下角弹出悬浮按钮
// @author       Harald
// @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/[email protected]/minified/arrive.min.js
// @require      https://update.gf.qytechs.cn/scripts/407543/963893/Block_Obj.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/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
// ==/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;
      }
      .video-card,
      .reply-btn {
          margin-right: 0px !important;
      }
      .bilibili_comment_bang_button,
      .bilibili_comment_user_block_button {
          display: inline-block;
          padding: 0px 5px;
          border-radius: 4px;
          cursor: pointer;
      }
      .bilibili_reply_bang_button,
      .bilibili_reply_user_block_button{
          margin-left: 10px;
      }
      .bilibili_comment_bang_button:hover,
      .bilibili_comment_user_block_button:hover {
          color: #00a1d6;
          background-color: #e5e9ef;
      }
      .bilibili_reply_bang_button:hover,
      .bilibili_reply_user_block_button:hover{
          color: var(--brand_blue);
      }
  `;
  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-small, .video-page-operator-card-small',
      user: '.upname .name',
      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-list > div',
      user: '.bili-video-card__info--author',
      text: 'h3',
      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: 'whitelistArray',
      ori: 'whitelistRegArray',
    },
    {
      key: 'usernameArray',
      ori: 'usernameRegArray',
    },
    {
      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 && 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) {
      for (let k of bilibiliConfig.usernameArray) {
        if (k) {
          if (typeof k === 'string' && username.includes(k)) {
            return true;
          } else {
            try {
              if (username.match(k)) {
                return true;
              }
            } catch (e) {
              console.error('存在错误的正则表达式: ', e);
            }
          }
        }
      }
    }
    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) {
      for (let k of bilibiliConfig.whitelistArray) {
        if (k) {
          if (typeof k === 'string' && username.includes(k)) {
            return true;
          } else {
            try {
              if (username.match(k)) {
                return true;
              }
            } catch (e) {
              console.error('存在错误的正则表达式: ', e);
            }
          }
        }
      }
    }
    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('.reply-list .reply-item');
    for (const commentListItem of commentList) {
      const sourceText = commentListItem.querySelector('.root-reply > .reply-content').textContent;
      let trueLove = commentListItem.querySelector('.true-love');
      trueLove = trueLove ? trueLove.firstChild.textContent : null;
      if (bilibiliConfig.convertEmojiEnable) {
        const convertText = getConvertText(commentListItem.querySelector('.root-reply > .reply-content').innerHTML);
        hideHandler(commentListItem, commentListItem.querySelector('.user-info > .user-name'), convertText, 0, {
          comment: true,
          sourceText: sourceText,
          trueLove,
        });
      } else {
        hideHandler(commentListItem, commentListItem.querySelector('.user-info > .user-name'), sourceText, 0, {
          comment: true,
          trueLove,
        });
      }
      const commentReplyBtn = commentListItem.querySelector('.reply-btn');
      if (bilibiliConfig.showBlockUserBtnEnable) {
        commentReplyBtn &&
          !commentListItem.querySelector('.bilibili_comment_user_block_button') &&
          commentReplyBtn.after(
            blockObj.createBlockBtn(
              commentListItem.querySelector('.user-info > .user-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('.sub-reply-list > .sub-reply-item');
    for (const replyCommentListItem of replyCommentList) {
      const replySourceText = replyCommentListItem.querySelector('.sub-reply-content > .reply-content').textContent;
      if (bilibiliConfig.convertEmojiEnable) {
        const replyConvertText = getConvertText(replyCommentListItem.querySelector('.sub-reply-content > .reply-content').innerHTML);
        hideHandler(replyCommentListItem, replyCommentListItem.querySelector('.sub-user-info > .sub-user-name'), replyConvertText, 0, {
          comment: true,
          sourceText: replySourceText,
        });
      } else {
        hideHandler(replyCommentListItem, replyCommentListItem.querySelector('.sub-user-info > .sub-user-name'), replySourceText, 0, {
          comment: true,
        });
      }
      const replyBtn = replyCommentListItem.querySelector('.sub-reply-btn');
      if (bilibiliConfig.showBlockUserBtnEnable) {
        replyBtn &&
          !replyCommentListItem.querySelector('.bilibili_reply_user_block_button') &&
          replyBtn.after(
            blockObj.createBlockBtn(
              replyCommentListItem.querySelector('.sub-user-info > .sub-user-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 class="emoji-.+?alt="(.+?)".*?>/g, '$1')
      .replace(/<a class="jump-link normal" href="(.+?)".*?>/g, '$1')
      .replace(/&nbsp;/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;
  }
})();

QingJ © 2025

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