// ==UserScript==
// @name 哔哩哔哩屏蔽增强器
// @namespace http://tampermonkey.net/
// @license Apache-2.0
// @version 2.2
// @author byhgz
// @description 对B站视频或评论进行屏蔽,支持关键词模糊正则等,支持时长播放弹幕过滤等,如视频、评论、动态、直播间的评论等,详情可看下面支持的屏蔽类型
// @icon https://static.hdslb.com/images/favicon.ico
// @noframes
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_addStyle
// @grant GM_unregisterMenuCommand
// @grant GM_registerMenuCommand
// @exclude *://message.bilibili.com/pages/nav/header_sync
// @exclude *://message.bilibili.com/pages/nav/index_new_pc_sync
// @exclude *://live.bilibili.com/blackboard/dropdown-menu.html
// @exclude *://live.bilibili.com/p/html/live-web-mng/*
// @exclude *://www.bilibili.com/correspond/*
// @match *://search.bilibili.com/*
// @match *://www.bilibili.com/v/food/*
// @match *://message.bilibili.com/*
// @match *://www.bilibili.com/read/*
// @match *://www.bilibili.com/v/topic/detail/?topic_id=*
// @match *://www.bilibili.com/v/kichiku/*
// @match *://t.bilibili.com/*
// @match *://space.bilibili.com/*
// @match *://www.bilibili.com/video/*
// @match *://live.bilibili.com/?spm_id_from=*
// @match *://live.bilibili.com/p/eden/area-tags?*
// @match *://live.bilibili.com/*
// @match *://www.bilibili.com/opus/*
// @match *://www.bilibili.com/*
// @require https://cdn.jsdelivr.net/npm/vue@2
// @require https://cdn.jsdelivr.net/npm/dexie@4.0.10/dist/dexie.min.js
// @require https://update.greasyfork.org/scripts/517928/gz_ui_css-v1.js
// @require https://update.greasyfork.org/scripts/521941/about_and_feedback_components.js
// @require https://greasyfork.org/scripts/462234-message/code/Message.js
// @require https://update.greasyfork.org/scripts/449512/Xtiper.js
// @require https://update.greasyfork.org/scripts/516282/Drawer_gz%E9%A1%B5%E9%9D%A2%E4%BE%A7%E8%BE%B9%E6%8A%BD%E5%B1%89%E7%BB%84%E4%BB%B6.js
// @require https://update.greasyfork.org/scripts/517538/DynamicTabs_gz.js
// ==/UserScript==
"use strict";
(function (Vue, Dexie) {
'use strict';
const start = () => {
let loop = false;
let msg;
if (!Vue) {
loop = true;
msg = 'Vue is not defined,Vue未定义,请检查是否引入了Vue';
}
if (!Dexie) {
loop = true;
msg = 'Dexie is not defined,Dexie未定义,请检查是否引入了Dexie';
}
if (loop) {
if (confirm('外部库验证失败:' + msg+`\n请联系作者核查问题\n可通过点击确定按钮跳转到脚本主页。
\n脚本主页信息中,有相关解决文档
\n或通过脚本信息底下联系方式联系作者解决`)) {
window.location.href = 'https://greasyfork.org/zh-CN/scripts/461382';
}
throw new Error(`外部库验证失败:${msg}`)
}
};
start();
var gmUtil = {
setData(key, content) {
GM_setValue(key, content);
},
getData(key, defaultValue) {
return GM_getValue(key, defaultValue);
},
delData(key) {
if (!this.isData(key)) {
return false;
}
GM_deleteValue(key);
return true;
},
isData(key) {
return this.getData(key) !== undefined;
},
addStyle(style) {
GM_addStyle(style);
},
addGMMenu(text, func, shortcutKey = null) {
return GM_registerMenuCommand(text, func, shortcutKey);
},
};
const setBorderColor = (color) => {
gmUtil.setData("borderColor", color);
};
const defBorderColor = "rgb(0, 243, 255)";
const getBorderColor = () => {
return gmUtil.getData("borderColor", defBorderColor)
};
const setOutputInformationFontColor = (color) => {
gmUtil.setData("output_information_font_color", color);
};
const defOutputInformationFontColor = "rgb(119,128,248)";
const getOutputInformationFontColor = () => {
return gmUtil.getData("output_information_font_color", defOutputInformationFontColor)
};
const setHighlightInformationColor = (color) => {
gmUtil.setData("highlight_information_color", color);
};
const defHighlightInformationColor = "rgb(234, 93, 93)";
const getHighlightInformationColor = () => {
return gmUtil.getData("highlight_information_color", defHighlightInformationColor);
};
const setDefaultColorInfo = () => {
setBorderColor(defBorderColor);
setOutputInformationFontColor(defOutputInformationFontColor);
setHighlightInformationColor(defHighlightInformationColor);
};
const setBOnlyTheHomepageIsBlocked = (bool) => {
gmUtil.setData("bOnlyTheHomepageIsBlocked", bool === true);
};
const getBOnlyTheHomepageIsBlocked = () => {
return gmUtil.getData("bOnlyTheHomepageIsBlocked", false);
};
const getAdaptationBAppCommerce = () => {
return gmUtil.getData("adaptation-b-app-recommend", false) === true;
};
const setAdaptationBAppCommerce = (bool) => {
gmUtil.setData("adaptation-b-app-recommend", bool === true);
};
const isHideMainButSwitch = () => {
return gmUtil.getData("hideMainButSwitch", false) === true;
};
const setHideMainButSwitch = (bool) => {
gmUtil.setData("hideMainButSwitch", bool === true);
};
const isHideRightTopMainButSwitch = () => {
return gmUtil.getData("hideRightTopMainButSwitch", true) === true;
};
const setHideRightTopMainButSwitch = (bool) => {
gmUtil.setData("hideRightTopMainButSwitch", bool === true);
};
const isCompatible_BEWLY_BEWLY = () => {
return gmUtil.getData("compatible_BEWLY_BEWLY", false) === true;
};
const setCompatible_BEWLY_BEWLY = (bool) => {
gmUtil.setData("compatible_BEWLY_BEWLY", bool === true);
};
const setDiscardOldCommentAreas = (bool) => {
gmUtil.setData("discardOldCommentAreas", bool === true);
};
const isDiscardOldCommentAreas = () => {
return gmUtil.getData("discardOldCommentAreas", false) === true;
};
var localMKData = {
setBorderColor,
getBorderColor,
setOutputInformationFontColor,
getOutputInformationFontColor,
setHighlightInformationColor,
getHighlightInformationColor,
setBOnlyTheHomepageIsBlocked,
getBOnlyTheHomepageIsBlocked,
getAdaptationBAppCommerce,
setAdaptationBAppCommerce,
setDefaultColorInfo,
isHideMainButSwitch,
setHideMainButSwitch,
isCompatible_BEWLY_BEWLY,
setCompatible_BEWLY_BEWLY,
setDiscardOldCommentAreas,
isDiscardOldCommentAreas,
isHideRightTopMainButSwitch,
setHideRightTopMainButSwitch
};
const mainDrawer = new Drawer_gz({
show: false,
height: "50vh",
headerShow: false,
title: "屏蔽器主面板",
direction: "top",
externalButtonText: "屏蔽器",
externalButtonWidth: "80px",
externalButtonShow: !localMKData.isHideMainButSwitch(),
zIndex: 9000,
drawerBorder: `1px solid ${localMKData.getBorderColor()}`,
bodyHtml: `
`,
});
const options = {
styles: `
.my-custom-tab-button {
font-size: 16px;
}
.my-custom-tab-content {
background-color: #f9f9f9;
}
`,
classes: {
tabButton: 'my-custom-tab-button',
tabButtonActive: 'my-custom-tab-button-active',
tabContent: 'my-custom-tab-content',
tabContentActive: 'my-custom-tab-content-active'
},
backgroundColor: '#eee',
borderColor: '#ddd',
textColor: '#333',
fontWeight: 'bold',
activeBackgroundColor: '#0056b3',
activeTextColor: '#fff',
contentBorderColor: '#bbb',
contentBackgroundColor: '#ffffff',
onTabClick: (id, title, content) => {
const tab = tabsConfig.find(item => item.title === title);
const height = tab.height;
mainDrawer.setHeight(height ? height : '50vh');
},
};
const tabsConfig = [
{
id: 'tab01',
title: '面板设置',
content: '',
height: "25vh",
},
{
id: 'tab02',
title: '规则管理',
content: '',
height: "96vh"
},
{
id: 'tab03',
title: '其他参数过滤',
content: ``,
height: '60vh'
},
{
id:'id04',
title: '兼容设置',
content: ``,
},
{
id: 'tab05',
title: '缓存tags管理',
content: '',
},
{
id: 'tab06',
title: '输出信息',
content: ``,
height: "96vh"
},
{
id: 'tab07',
title: '支持打赏',
content: '',
height: "80vh"
},
{
id: 'tab08',
title: '关于和问题反馈',
content: ``,
height: '53vh'
}
];
new DynamicTabs_gz('#shield', tabsConfig,
options
);
class EventEmitter {
constructor() {
this.events = {};
this.handlers = {};
}
on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
}
once(eventName, callback) {
const onceCallback = (...args) => {
callback(...args);
this.off(eventName, onceCallback);
};
this.on(eventName, onceCallback);
}
emit(eventName, data) {
if (!this.events[eventName]) {
throw new Error(`没有为注册的事件侦听器 "${eventName}"`);
}
this.events[eventName].forEach(callback => {
try {
callback(data);
} catch (error) {
console.error(`事件侦听器中发生错误 "${eventName}":`, error);
}
});
}
off(eventName, callback) {
if (this.events[eventName]) {
this.events[eventName] = this.events[eventName].filter(cb => cb !== callback);
}
}
removeAllListeners(eventName) {
if (eventName) {
delete this.events[eventName];
delete this.handlers[eventName];
} else {
this.events = {};
this.handlers = {};
}
}
listenerCount(eventName) {
return this.events[eventName] ? this.events[eventName].length : 0;
}
handle(eventName, handler) {
this.handlers[eventName] = handler;
}
invoke(eventName, data) {
if (this.handlers[eventName]) {
return this.handlers[eventName](data);
}
return null;
}
}
const eventEmitter = new EventEmitter();
const returnVue$5 = () => {
return new Vue({
template: `
`,
el: '#shield #panel_settings_vue',
data() {
return {
input_color: "",
hideMainButSwitch: localMKData.isHideMainButSwitch(),
hideRightTopMainButSwitch: localMKData.isHideRightTopMainButSwitch()
}
},
methods: {
setBorderColorBut() {
xtip.confirm("是要否设置面板边框颜色吗?", {
icon: "a",
btn1: () => {
localMKData.setBorderColor(this.input_color);
xtip.alert("已设置面板边框颜色,刷新生效");
}
});
},
setDefFontColorForOutputInformationBut() {
xtip.confirm("是要否设置输出信息默认字体颜色吗?", {
icon: "a",
btn1: () => {
localMKData.setOutputInformationFontColor(this.input_color);
xtip.alert("已设置输出信息默认字体颜色,刷新生效");
}
});
},
setTheFontColorForOutputInformationBut() {
xtip.confirm("是要否设置输出信息高亮字体颜色吗?", {
icon: "a",
btn1: () => {
localMKData.setHighlightInformationColor(this.input_color);
xtip.alert("已设置输出信息高亮字体颜色,刷新生效");
}
});
},
setDefInfoBut() {
localMKData.setDefaultColorInfo();
xtip.alert("已恢复默认颜色,刷新生效");
}
},
watch: {
hideMainButSwitch(newVal) {
localMKData.setHideMainButSwitch(newVal);
mainDrawer.externalButtonShow(!newVal);
},
hideRightTopMainButSwitch(newVal) {
localMKData.setHideRightTopMainButSwitch(newVal);
eventEmitter.emit('右上角开关按钮显隐', newVal);
}
}
});
};
const wait = (milliseconds = 1000) => {
return new Promise(resolve => setTimeout(resolve, milliseconds));
};
const fileDownload = (content, fileName) => {
const element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(content));
element.setAttribute('download', fileName);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
};
const handleFileReader = (event) => {
return new Promise((resolve, reject) => {
const file = event.target.files[0];
if (!file) {
reject('未读取到文件');
return;
}
let reader = new FileReader();
reader.onload = (e) => {
const fileContent = e.target.result;
resolve({file, content: fileContent});
reader = null;
};
reader.readAsText(file);
});
};
const isIterable = (obj) => {
return obj != null && typeof obj[Symbol.iterator] === 'function';
};
const toTimeString = () => {
return new Date().toLocaleString();
};
function smoothScroll(toTop = false, duration = 1000) {
return new Promise((resolve) => {
const start = window.scrollY;
const end = toTop ? 0 : document.documentElement.scrollHeight - window.innerHeight;
const change = end - start;
const startTime = performance.now();
function animateScroll(currentTime) {
const elapsedTime = currentTime - startTime;
const progress = Math.min(elapsedTime / duration, 1);
const easeInOutQuad = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress;
window.scrollTo(0, start + change * easeInOutQuad);
if (progress < 1) {
requestAnimationFrame(animateScroll);
} else {
resolve();
}
}
requestAnimationFrame(animateScroll);
});
}
function debounce(func, wait = 1000) {
let timeout;
return function (...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
function debounceAsync(asyncFunc, wait = 1000) {
let timeout;
let pendingPromise;
return async function (...args) {
const context = this;
if (pendingPromise) {
clearTimeout(timeout);
await pendingPromise;
}
pendingPromise = new Promise((resolve) => {
timeout = setTimeout(() => {
pendingPromise = null; // 清除引用
resolve(asyncFunc.apply(context, args));
}, wait);
});
return pendingPromise;
};
}
function throttle(func, limit) {
let inThrottle;
return function (...args) {
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
function throttleAsync(asyncFunc, limit) {
let isThrottled = false;
let pendingArgs = null;
let pendingContext = null;
let timeoutId;
let pendingPromiseResolve;
const throttled = async function (...args) {
const context = this;
if (isThrottled) {
return new Promise((resolve) => {
pendingArgs = args;
pendingContext = context;
pendingPromiseResolve = resolve;
});
}
isThrottled = true;
try {
return await asyncFunc.apply(context, args);
} finally {
timeoutId = setTimeout(() => {
isThrottled = false;
if (pendingArgs) {
throttled.apply(pendingContext, pendingArgs).then(pendingPromiseResolve);
pendingArgs = null;
pendingContext = null;
pendingPromiseResolve = null;
}
}, limit);
}
};
throttled.cancel = () => {
clearTimeout(timeoutId);
isThrottled = false;
pendingArgs = null;
pendingContext = null;
pendingPromiseResolve = null;
};
return throttled;
}
const parseUrl = (urlString) => {
const url = new URL(urlString);
const pathSegments = url.pathname.split('/').filter(segment => segment !== '');
const searchParams = new URLSearchParams(url.search.slice(1));
const queryParams = {};
for (const [key, value] of searchParams.entries()) {
queryParams[key] = value;
}
return {
protocol: url.protocol,
hostname: url.hostname,
port: url.port,
pathname: url.pathname,
pathSegments,
search: url.search,
queryParams,
hash: url.hash
};
};
const getLocalStorage = (key, isList = false, defaultValue = null) => {
const item = localStorage.getItem(key);
if (item === null) {
return defaultValue
}
if (isList) {
try {
return JSON.parse(item)
} catch (e) {
console.error(`读取localStorage时尝试转换${key}的值失败`, e);
return defaultValue
}
}
return item
};
var defUtil = {
wait,
fileDownload,
toTimeString,
smoothScroll,
debounce,
debounceAsync,
throttle,
throttleAsync,
parseUrl,
handleFileReader,
isIterable,
getLocalStorage
};
const ruleKeyListData = [
{
key: "name",
name: "用户名黑名单(模糊匹配)",
oldKey: "userNameKeyArr",
oldName: "用户名黑名单模式(模糊匹配)"
},
{
key: "precise_name",
name: "用户名黑名单(精确匹配)",
oldKey: "userNameArr",
oldName: "用户名黑名单模式(精确匹配)"
}, {
key: "nameCanonical",
name: "用户名黑名单(正则匹配)"
},
{
key: "precise_uid",
name: "用户uid黑名单(精确匹配)",
oldKey: "userUIDArr",
oldName: "用户uid黑名单模式(精确匹配)"
},
{
key: "precise_uid_white",
name: "用户uid白名单(精确匹配)",
oldKey: "userWhiteUIDArr",
oldName: "用户uid白名单模式(精确匹配)"
}, {
key: "title",
name: "标题黑名单(模糊匹配)",
oldKey: "titleKeyArr",
oldName: "标题黑名单模式(模糊匹配)"
}, {
key: "titleCanonical",
name: "标题黑名单(正则匹配)",
oldKey: "titleKeyCanonicalArr",
oldName: "标题黑名单模式(正则匹配)"
}, {
key: "commentOn",
name: "评论关键词黑名单(模糊匹配)",
oldKey: "commentOnKeyArr",
oldName: "评论关键词黑名单模式(模糊匹配)"
}, {
key: "commentOnCanonical",
name: "评论关键词黑名单(正则匹配)",
oldKey: "contentOnKeyCanonicalArr",
oldName: "评论关键词黑名单模式(正则匹配)"
}, {
key: "contentOn",
name: "评论内容黑名单(模糊匹配)",
oldKey: "contentOnKeyArr",
oldName: "评论内容黑名单模式(模糊匹配)"
}, {
key: "precise_fanCard",
name: "粉丝牌黑名单(精确匹配)",
oldKey: "fanCardArr",
oldName: "粉丝牌黑名单模式(精确匹配)"
}, {
key: "dynamic",
name: "动态关键词黑名单(模糊匹配)",
oldKey: "dynamicArr",
oldName: "动态关键词内容黑名单模式(模糊匹配)"
}, {
key: "precise_tag",
name: "话题tag标签黑名单(精确匹配)",
}
, {
key: "tag",
name: "话题tag标签黑名单(模糊匹配)",
}, {
key: "tagCanonical",
name: "话题tag标签黑名单(正则匹配)"
}, {
key: "precise_partition",
name: "直播分区黑名单(精确匹配)"
}, {
key: 'videoTag',
name: '视频tag黑名单(模糊匹配)',
}, {
key: 'precise_videoTag',
name: '视频tag黑名单(精确匹配)',
}, {
key: 'videoTagCanonical',
name: '视频tag黑名单(正则匹配)',
}
];
const getRuleKeyListData = () => {
return ruleKeyListData;
};
const getNameArr = () => {
return gmUtil.getData("name", []);
};
const getPreciseNameArr = () => {
return gmUtil.getData("precise_name", []);
};
const getNameCanonical = () => {
return gmUtil.getData("nameCanonical", []);
};
const getPreciseUidArr = () => {
return gmUtil.getData("precise_uid", []);
};
const getPreciseUidWhiteArr = () => {
return gmUtil.getData("precise_uid_white", []);
};
const getTitleArr = () => {
return gmUtil.getData("title", []);
};
const getTitleCanonicalArr = () => {
return gmUtil.getData("titleCanonical", []);
};
const getCommentOnArr = () => {
return gmUtil.getData("commentOn", []);
};
const getCommentOnCanonicalArr = () => {
return gmUtil.getData("commentOnCanonical", []);
};
const getPreciseTagArr = () => {
return gmUtil.getData("precise_tag", []);
};
const getTagArr = () => {
return gmUtil.getData("tag", []);
};
const getTagCanonicalArr = () => {
return gmUtil.getData("tagCanonical", []);
};
const getPreciseFanCardArr = () => {
return gmUtil.getData("precise_fanCard", []);
};
const getPrecisePartitionArr = () => {
return gmUtil.getData("precise_partition", []);
};
const getVideoTagArr = () => {
return gmUtil.getData("videoTag", []);
};
const getPreciseVideoTagArr = () => {
return gmUtil.getData("precise_videoTag", []);
};
const getVideoTagCanonicalArr = () => {
return gmUtil.getData("videoTagCanonical", []);
};
var ruleKeyListData$1 = {
getNameArr,
getPreciseNameArr,
getNameCanonical,
getPreciseUidArr,
getPreciseUidWhiteArr,
getTitleArr,
getTitleCanonicalArr,
getCommentOnArr,
getCommentOnCanonicalArr,
getRuleKeyListData,
getPreciseTagArr,
getTagArr,
getTagCanonicalArr,
getPreciseFanCardArr,
getPrecisePartitionArr,
getVideoTagArr,
getPreciseVideoTagArr,
getVideoTagCanonicalArr
};
const verificationInputValue = (ruleValue, type) => {
if (ruleValue === null) return null;
if (type === "precise_uid" || type === "precise_uid_white") {
ruleValue = parseInt(ruleValue);
if (isNaN(ruleValue)) {
Qmsg.info('请输入数字!');
return null;
}
} else {
ruleValue.trim();
}
if (ruleValue === '') {
Qmsg.info('内容为空');
return null;
}
return ruleValue;
};
const addRule = (ruleValue, type) => {
const inputValue = verificationInputValue(ruleValue, type);
return new Promise((resolve, reject) => {
if (inputValue === null) {
reject('取消添加');
return;
}
const arr = gmUtil.getData(type, []);
if (arr.includes(inputValue)) {
reject('已存在此内容');
return;
}
arr.push(inputValue);
gmUtil.setData(type, arr);
resolve('添加成功');
}
)
};
const showAddRuleInput = (type) => {
const ruleValue = window.prompt('请输入要添加的规则内容', '');
return addRule(ruleValue, type);
};
const showDelRuleInput = (type) => {
let prompt = window.prompt('请输入要移除的规则内容', '');
const inputValue = verificationInputValue(prompt, type);
return new Promise((resolve, reject) => {
if (inputValue === null) {
reject('取消添加');
return;
}
const arr = gmUtil.getData(type, []);
const indexOf = arr.indexOf(inputValue);
if (indexOf === -1) {
reject('不存在此内容');
return;
}
arr.splice(indexOf, 1);
gmUtil.setData(type, arr);
resolve('移除成功');
})
};
const showSetRuleInput = (type) => {
let prompt = window.prompt('请输入要修改的规则内容', '');
const inputValue = verificationInputValue(prompt, type);
return new Promise((resolve, reject) => {
if (inputValue === null) return;
const arr = gmUtil.getData(type, []);
const indexOf = arr.indexOf(inputValue);
if (indexOf === -1) {
reject('不存在此内容');
return;
}
prompt = window.prompt('请输入要修改的内容', '');
const newInputValue = verificationInputValue(prompt, type);
if (newInputValue === null) return;
if (arr.includes(newInputValue)) {
reject('已存在要修改过后的值内容');
return;
}
arr[indexOf] = newInputValue;
gmUtil.setData(type, arr);
resolve('修改成功');
})
};
const getRuleContent = (space = 0) => {
const ruleMap = {};
for (let ruleKeyListDatum of ruleKeyListData$1.getRuleKeyListData()) {
const key = ruleKeyListDatum.key;
ruleMap[key] = gmUtil.getData(key, []);
}
return JSON.stringify(ruleMap, null, space);
};
const verificationRuleMap = (keyArr, content) => {
let parse;
try {
parse = JSON.parse(content);
} catch (e) {
alert('规则内容有误');
return false;
}
const newRule = {};
for (let key of keyArr) {
if (!Array.isArray(parse[key])) {
continue;
}
if (parse[key].length === 0) {
continue;
}
newRule[key] = parse[key];
}
if (Object.keys(newRule).length === 0) {
alert('规则内容为空');
return false;
}
return newRule;
};
const overwriteImportRules = (keyArr, content) => {
const map = verificationRuleMap(keyArr, content);
if (map === false) return false;
for (let key of Object.keys(map)) {
gmUtil.setData(key, map[key]);
}
return true;
};
const appendImportRules = (keyArr, content) => {
const map = verificationRuleMap(keyArr, content);
if (map === false) return false;
for (let key of Object.keys(map)) {
const arr = gmUtil.getData(key, []);
for (let item of map[key]) {
if (!arr.includes(item)) {
arr.push(item);
}
}
gmUtil.setData(key, arr);
}
return true;
};
const getNewRuleKeyList = () => {
return ruleKeyListData$1.getRuleKeyListData();
};
const overwriteImportRulesV1 = (content) => {
let parse;
try {
parse = JSON.parse(content);
} catch (e) {
alert('规则内容有误');
return false;
}
for (let ruleKeyListDatum of ruleKeyListData$1.getRuleKeyListData()) {
const name = ruleKeyListDatum.oldName;
const jsonRuleList = parse[name];
if (!jsonRuleList) {
continue;
}
if (jsonRuleList.length === 0) {
continue;
}
gmUtil.setData(ruleKeyListDatum.key, jsonRuleList);
}
return true;
};
const addRulePreciseUid = (uid) => {
return addRule(uid, "precise_uid").then(msg => {
xtip.msg(msg, {icon: 's'});
}).catch(msg => {
xtip.msg(msg, {icon: 'e'});
})
};
const addRulePreciseName= (name) => {
return addRule(name, "precise_name").then(msg => {
xtip.msg(msg, {icon: 's'});
}).catch(msg => {
xtip.msg(msg, {icon: 'e'});
})
};
var ruleUtil = {
addRule,
showAddRuleInput,
showDelRuleInput,
showSetRuleInput,
getRuleContent,
overwriteImportRules,
appendImportRules,
overwriteImportRulesV1,
getNewRuleKeyList,
addRulePreciseUid,
addRulePreciseName
};
const oldToNewRule = () => {
const listData = ruleKeyListData$1.getRuleKeyListData().filter(item => item.oldKey);
for (let data of listData) {
const oldKeyDataArr = gmUtil.getData(data.oldKey, []);
if (oldKeyDataArr.length === 0) {
continue
}
const newKeyDataArr = gmUtil.getData(data.key, []);
if (newKeyDataArr.length === 0) {
gmUtil.setData(data.key, oldKeyDataArr);
gmUtil.delData(data.oldKey);
continue
}
for (let v of oldKeyDataArr) {
const isExist = newKeyDataArr.find(item => item === v);
if (!isExist) {
newKeyDataArr.push(v);
}
}
gmUtil.setData(data.key, newKeyDataArr);
}
};
var ruleConversion = {
oldToNewRule
};
const returnVue$4 = () => {
return new Vue({
template: `
使用说明
- 脚本中会对要匹配的内容进行去除空格和转成小写,比如有个内容是【不 要 笑 挑 战
ChallEnGE】,会被识别称为【不要笑挑战challenge】
- 在上述一点的情况下,模糊匹配和正则匹配的方式时不用考虑要匹配的内容中大写问题
- 大部分情况下模糊匹配比精确匹配好用
- 如果用户要添加自己的正则匹配相关的规则时,建议先去该网址进行测试再添加,避免浪费时间
>>>正则表达式在线测试<<<
-
如果更新脚本之后规则全吗,没了请点击下面的【旧规则自动转新规则】按钮,进行转换,如不行请通过关于和问题反馈选项卡中的反馈渠道联系作者
《====可点击切换条件
导出规则
规则信息
{{ item.name }}{{ item.len }}个
`,
el: '#shield #rule_management_vue',
data() {
return {
selectVal: 'name',
selectText: "",
ruleContentImport: "",
ruleActions: [
{
type: "uid",
name: "uid(精确)",
}
],
ruleKeyArr: [],
ruleInfoArr: [],
ruleReference: [
{
title: "旧版本规则参考",
content: ` {"用户名黑名单模式(精确匹配)":["账号已注销"],"BV号黑名单模式(精确匹配)":[],
"用户名黑名单模式(模糊匹配)":["bili_","_bili"],"用户uid黑名单模式(精确匹配)":[442010132,76525078,225219967,3493283164588093],
"用户uid白名单模式(精确匹配)":[344490740,1861980711],"标题黑名单模式(模糊匹配)":["激励计划","蚌不住","手游激励","游戏活动打卡"],
"标题黑名单模式(正则匹配)":["感觉.*不如","不要笑.*挑战"],"评论关键词黑名单模式(模糊匹配)":["感觉不如","差不多的了"],
"评论关键词黑名单模式(正则匹配)":["这不.+吗","玩.*的","不要笑.*挑战"],"粉丝牌黑名单模式(精确匹配)":[],
"专栏关键词内容黑名单模式(模糊匹配)":[],"动态关键词内容黑名单模式(模糊匹配)":["拼多多","京东红包","京东618红包","618活动"]}`
},
{
title: "新版本规则参考",
content: "待补充"
}
],
bOnlyTheHomepageIsBlocked: localMKData.getBOnlyTheHomepageIsBlocked()
}
},
methods: {
operationBut(model) {
const type = this.selectVal;
if (model === "add") {
ruleUtil.showAddRuleInput(type).then((msg) => {
this.refreshInfoBut();
alert(msg);
}).catch(errMsg => {
Qmsg.info(errMsg);
});
}
if (model === "del") {
ruleUtil.showDelRuleInput(type).then((msg) => {
this.refreshInfoBut();
alert(msg);
}).catch(errMsg => {
Qmsg.info(errMsg);
});
}
if (model === "set") {
ruleUtil.showSetRuleInput(type).then((msg) => {
this.refreshInfoBut();
alert(msg);
}).catch(errMsg => {
Qmsg.info(errMsg);
});
}
if (model === "del_all") {
if (!window.confirm("确定要删除所有规则吗?")) {
Qmsg.info('取消删除全部操作');
return;
}
for (let x of this.ruleKeyArr) {
gmUtil.delData(x);
}
alert("删除全部规则成功");
this.refreshInfoBut();
}
},
ruleOutToFIleBut() {
const ruleContent = ruleUtil.getRuleContent(4);
let fileName = "b站屏蔽器规则-" + defUtil.toTimeString();
const s = prompt("保存为", fileName);
if (s === null) return;
if (!(s.includes(" ") || s === "" || s.length === 0)) fileName = s;
defUtil.fileDownload(ruleContent, fileName + ".json");
},
ruleOutToConsoleBut() {
xtip.msg('已导出到控制台上!', {icon: 's'});
console.log(ruleUtil.getRuleContent());
},
refreshInfoBut() {
for (let x of this.ruleInfoArr) {
x.len = gmUtil.getData(x.type, []).length;
}
Qmsg.info('已刷新规则信息');
},
overwriteImportRulesBut() {
xtip.confirm('是否要覆盖导入规则?', {
icon: 'a',
btn1: () => {
const trim = this.ruleContentImport.trim();
if (ruleUtil.overwriteImportRules(this.ruleKeyArr, trim)) {
xtip.msg('已覆盖导入成功!', {icon: 's'});
this.refreshInfoBut();
}
}
});
},
appendImportRulesBut() {
xtip.confirm('是否要追加导入规则?', {
icon: 'a',
btn1: () => {
const trim = this.ruleContentImport.trim();
if (ruleUtil.appendImportRules(this.ruleKeyArr, trim)) {
xtip.msg('已追加导入成功!', {icon: 's'});
this.refreshInfoBut();
}
}
});
},
overwriteImportRulesV1But() {
xtip.confirm('旧版本-是否导入规则?', {
icon: 'a',
btn1: () => {
const trim = this.ruleContentImport.trim();
if (ruleUtil.overwriteImportRulesV1(trim)) {
xtip.msg('已导入成功!', {icon: 's'});
this.refreshInfoBut();
}
}
});
},
xtipAlertBut(content, title) {
xtip.alert(content,
{title: title});
},
ruleOldToNewBut() {
ruleConversion.oldToNewRule();
this.refreshInfoBut();
xtip.msg('已转换成功!', {icon: 's'});
},
outToInputBut() {
this.ruleContentImport = ruleUtil.getRuleContent(2);
xtip.msg('已导出到输入框!', {icon: 's'});
},
handleFileUpload(event) {
defUtil.handleFileReader(event).then(data => {
const {content} = data;
try {
JSON.parse(content);
} catch (e) {
xtip.msg('文件内容有误', {icon: 'e'});
return;
}
this.ruleContentImport = content;
xtip.msg('读取到内容,请按需覆盖或追加', {icon: 's'});
});
},
inputFIleRuleBut() {
this.$refs.file.click();
}
},
watch: {
bOnlyTheHomepageIsBlocked(newVal) {
localMKData.setBOnlyTheHomepageIsBlocked(newVal);
},
selectVal(newVal) {
console.log(newVal);
const find = this.ruleInfoArr.find(item => item.type === newVal);
this.selectText = find.name;
}
},
created() {
for (let newRuleKeyListElement of ruleUtil.getNewRuleKeyList()) {
this.ruleKeyArr.push(newRuleKeyListElement.key);
this.ruleInfoArr.push({
type: newRuleKeyListElement.key,
name: newRuleKeyListElement.name,
len: 0
});
}
const find = this.ruleInfoArr.find(item => item.type === this.selectVal);
this.selectText = find.name;
this.refreshInfoBut();
}
});
};
const returnVue$3 = () => {
return new Vue({
el: "#station_b_shield_donate",
template: `
零钱赞助
- 1元不嫌少,10元不嫌多哦!感谢支持!
- 生活不易,作者叹息
- 您的支持是我最大的更新动力
{{ item.name }}
打赏点猫粮
`,
data: {
list: [
{
name: "支付宝赞助",
alt: "支付宝支持",
src: "https://www.mikuchase.ltd/img/paymentCodeZFB.webp"
},
{name: "微信赞助", alt: "微信支持", src: "https://www.mikuchase.ltd/img/paymentCodeWX.webp"},
{name: "QQ赞助", alt: "QQ支持", src: "https://www.mikuchase.ltd/img/paymentCodeQQ.webp"},
]
}
});
};
const returnVue$2 = () => {
return new Vue({
el: '#other_parameter_filter',
template: `
{{ item.name }}{{ item.defVal }}
{{ item.name.includes('时长') ? '秒' : '' }}
`,
data() {
return {
index: 0,
selectList: [
{
name: '最小播放量',
value: 'nMinimumPlay',
associated: 'nMaximumPlayback',
defVal: -1
},
{
name: '最大播放量',
value: 'nMaximumPlayback',
associated: 'nMinimumPlay',
bLarge: true,
defVal: -1
},
{
name: '最小弹幕数',
value: 'nMinimumBarrage',
associated: 'nMaximumBarrage',
defVal: -1
},
{
name: '最大弹幕数',
value: 'nMaximumBarrage',
associated: 'nMinimumBarrage',
bLarge: true,
defVal: -1
},
{
name: '最小时长',
value: 'nMinimumDuration',
associated: 'nMaximumDuration',
defVal: -1
},
{
name: '最大时长',
value: 'nMaximumDuration',
associated: 'nMinimumDuration',
bLarge: true,
defVal: -1
},
{
name: '评论区最小用户等级过滤',
value: 'nMinimumLevel',
associated: 'nMaximumLevel',
defVal: -1
},
{
name: '评论区最大用户等级过滤',
value: 'nMaximumLevel',
associated: 'nMinimumLevel',
bLarge: true,
defVal: -1
}
],
selectValue: 'nMinimumPlay',
inputMax: '',
inputMin: '0'
}
},
methods: {
okVideoSelectBut() {
const find = this.selectList.find(item => item.value === this.selectValue);
const associatedVal = gmUtil.getData(find.associated, -1);
const associatedFind = this.selectList.find(item => item.value === find.associated);
if (this.index > associatedVal && associatedVal !== -1) {
if (associatedFind.bLarge) {
xtip.alert(`要设置的${find.name}值不能大于${associatedFind.name}的值`);
return
}
console.log('正常修改');
}
xtip.alert(`已设置${find.name},值为${this.index}`);
gmUtil.setData(this.selectValue, this.index);
this.updateInfo();
},
cancelBut() {
gmUtil.setData(this.selectValue, -1);
const find = this.selectList.find(item => item.value === this.selectValue);
xtip.alert(`已取消${find.name}的限制`);
this.updateInfo();
},
allCancelBut() {
for (let item of this.selectList) {
gmUtil.setData(item.value, -1);
}
this.updateInfo();
},
updateInfo() {
for (let item of this.selectList) {
item.defVal = gmUtil.getData(item.value, -1);
}
},
updateInfoBut() {
this.updateInfo();
xtip.alert('已刷新');
},
},
watch: {
selectValue(newVal) {
const find = this.selectList.find(item => item.value === newVal);
if (find.name.includes('用户等级')) {
this.inputMin = 3;
this.inputMax = 6;
if (this.index > 6) {
this.index = 6;
}
if (this.index < 3) {
this.index = 3;
}
} else {
this.inputMin = 0;
this.inputMax = '';
}
}
},
created() {
this.updateInfo();
}
})
};
const returnVue$1 = () => {
return new Vue({
el: "#shield #compatible_setting",
template: `
`,
data() {
return {
adaptationBAppRecommend: localMKData.getAdaptationBAppCommerce(),
compatible_BEWLY_BEWLY: localMKData.isCompatible_BEWLY_BEWLY(),
discardOldCommentAreasV:localMKData.isDiscardOldCommentAreas()
}
},
watch:{
adaptationBAppRecommend(newVal) {
localMKData.setAdaptationBAppCommerce(newVal);
},
compatible_BEWLY_BEWLY(newVal) {
localMKData.setCompatible_BEWLY_BEWLY(newVal);
},
discardOldCommentAreasV(newVal) {
localMKData.setDiscardOldCommentAreas(newVal);
}
}
})
};
const mk_db = new Dexie('mk-db');
mk_db.version(1).stores({
tags: 'bv,title,name'
});
const localData = [];
const updateLocalData = async () => {
localData.splice(0, localData.length, ...await mk_db.tags.toArray());
};
updateLocalData().then(r => {
console.log('初始化视频tags表临时缓存');
});
const findBv = async (bv) => {
const find = localData.find(item => item.bv === bv);
if (find === undefined) {
return false
}
return find
};
const addTagsData = async (data) => {
const {title, bv, name, tags} = data;
try {
await mk_db.tags.add({
bv,
title,
name,
tags
});
} catch (e) {
console.log(`添加视频tags失败`, data, e);
return false
}
return true
};
const bulkImportTags = async (friendsData) => {
try {
const lastKeyItem = await mk_db.tags.bulkPut(friendsData);
console.log('批量导入成功,最后一个插入的主键:', lastKeyItem);
return {state: true, lastKeyItem}
} catch (error) {
console.error('批量导入时出错:', error);
return {state: false, error}
}
};
const getVideoAllTags = async () => {
return await mk_db.tags.toArray()
};
const getTagsCount = async () => {
try {
const count = await mk_db.tags.count();
return {state: true, count}
} catch (e) {
return {state: false, count: -1, error: e}
}
};
const clearTagsTable = async () => {
try {
await mk_db.tags.clear();
return true
} catch (e) {
console.log('清除tags表失败', e);
return false
}
};
var bvDexie = {
addTagsData,
getVideoAllTags,
findBv,
updateLocalData,
getTagsCount,
clearTagsTable,
bulkImportTags
};
const returnVue = () => {
return new Vue({
el: "#cache_tags_management_vue",
template: `
`,
data() {
return {
hostname: window.location.hostname
}
},
methods: {
outTagsDataBut() {
bvDexie.getVideoAllTags().then((data) => {
data = {
hostName: this.hostname,
size: data.length,
tags: data
};
defUtil.fileDownload(JSON.stringify(data,null,4), 'mk-db-tags.json');
xtip.msg('已导出当前域名的tags缓存数据', 'success');
console.log(data);
});
},
handleFileUpload(event) {
defUtil.handleFileReader(event).then(data => {
const {content} = data;
let parse;
try {
parse = JSON.parse(content);
} catch (e) {
xtip.msg('文件内容有误', {icon: 'e'});
return;
}
const {hostName = null, tags = []} = parse;
if (!hostName) {
xtip.msg('hostName字段不存在', {icon: 'e'});
return;
}
if (!defUtil.isIterable(tags)) {
xtip.msg('文件内容有误,非可迭代的数组!', {icon: 'e'});
return;
}
if (tags.length === 0) {
xtip.msg('tags数据为空', {icon: 'e'});
return;
}
for (let item of tags) {
if (!item['name']) {
xtip.msg('name字段不存在', {icon: 'e'});
return;
}
if (!item['title']) {
xtip.msg('title字段不存在', {icon: 'e'});
return;
}
if (!item['bv']) {
xtip.msg('bv字段不存在', {icon: 'e'});
return;
}
if (!item['tags']) {
xtip.msg('tags字段不存在', {icon: 'e'});
return;
}
}
bvDexie.bulkImportTags(tags).then((bool) => {
if (bool) {
xtip.msg('导入成功', 'success');
} else {
xtip.msg('导入失败', 'error');
}
});
});
},
inputFIleBut() {
this.$refs.inputDemo.click();
},
clearPageTagsDataBut() {
xtip.confirm('是否清空当前域名下的tags数据', {
icon: 'a',
btn1: () => {
bvDexie.clearTagsTable().then((bool) => {
if (bool) {
xtip.msg('已清空当前域名下的tags数据', 'success');
} else {
xtip.msg('清空失败', 'error');
}
});
}
});
}
},
created() {
}
})
};
document.querySelector("#output_information button")?.addEventListener("click", () => {
olEL.innerHTML = "";
alert("已清空消息");
});
const olEL = document.querySelector("#output_information>.info");
const addInfo = (content) => {
const liEL = document.createElement("li");
liEL.innerHTML = content;
olEL.appendChild(liEL);
};
const outputInformationFontColor = localMKData.getOutputInformationFontColor();
const highlightInformationColor = localMKData.getHighlightInformationColor();
eventEmitter.on('正则匹配时异常', (errorData) => {
const {msg, e} = errorData;
addInfo(msg);
console.log(msg);
throw new Error(e)
});
const getVideoInfoHtml = (type, matching, videoData) => {
const toTimeString = defUtil.toTimeString();
const {name, uid, title, videoUrl} = videoData;
return `
${toTimeString}-根据${type}-${matching ? `【${matching}】` : ""}-屏蔽用户【${name}】uid=
【${uid}】
标题【${title}】
`
};
const getCommentInfoHtml = (type, matching, commentData) => {
const toTimeString = defUtil.toTimeString();
const {name, uid, content} = commentData;
return `
${toTimeString}-根据${type}-${matching ? `【${matching}】` : ""}-屏蔽用户【${name}】uid=
【${uid}】
评论【${content}】
`
};
const getLiveRoomCommentInfoHtml = (type, matching, commentData) => {
const toTimeString = defUtil.toTimeString();
const {name, uid, content} = commentData;
return `
${toTimeString}-根据${type}-${matching ? `【${matching}】` : ""}-屏蔽用户【${name}】uid=
【${uid}】
直播评论【${content}】
`
};
const getDynamicContentInfoHtml = (type, matching, dynamicData) => {
const toTimeString = defUtil.toTimeString();
const {name, uid, content} = dynamicData;
return `
${toTimeString}-根据${type}-${matching ? `【${matching}】` : ""}-屏蔽用户【${name}】uid=
【${uid}】
动态【${content}】
`
};
const getLiveRoomInfoHtml = (type, matching, liveRoomData) => {
const toTimeString = defUtil.toTimeString();
const {name = null, uid = -1, title, liveUrl} = liveRoomData;
return `
${toTimeString}-根据${type}${matching ? `【${matching}】` : ""}-屏蔽用户【${name === null ? '' : name}】${uid === -1 ? "" : `uid=
【${uid}】`}
直播间标题【${title}】
`
};
var output_informationTab = {
addInfo,
getVideoInfoHtml,
getCommentInfoHtml,
getLiveRoomCommentInfoHtml,
getDynamicContentInfoHtml,
getLiveRoomInfoHtml
};
var css$1 = `button {
position: fixed;
right: 5%;
top: 13%;
width: 60px;
height: 60px;
border-radius: 50%;
border-width: 0;
cursor: pointer;
background: #0056b3;
}
`;
const addLayout = () => {
const div = document.createElement('div');
div.style.position = 'fixed';
div.style.zIndex = '9001';
div.style.display = localMKData.isHideRightTopMainButSwitch() ? 'none' : '';
const but = document.createElement('button');
but.textContent = '屏蔽器';
const shadowRoot = div.attachShadow({mode: 'open'});
const styleElement = document.createElement('style');
styleElement.textContent = css$1;
shadowRoot.appendChild(but);
shadowRoot.appendChild(styleElement);
document.querySelector('body').appendChild(div);
but.addEventListener('click', () => mainDrawer.showDrawer());
eventEmitter.on('右上角开关按钮显隐', (loop) => {
div.style.display = !loop ? '' : 'none';
});
};
var externalHoverSwitchPanelButton = {
addLayout
};
returnVue$5();
returnVue$4();
returnVue$3();
returnVue$2();
returnVue$1();
returnVue();
installAboutAndFeedbackComponentsVue('#station_b_shield_problem_feedback',
{
title: 'B站屏蔽增强器',
gfFeedbackUrl: 'https://greasyfork.org/zh-CN/scripts/461382'
}
);
gmUtil.addStyle(`
[gz_bezel]{
border:1px solid ${localMKData.getBorderColor()}
}
`);
externalHoverSwitchPanelButton.addLayout();
const getUrlUID = (url) => {
let uid;
if (url.startsWith('http')) {
const parseUrl = defUtil.parseUrl(url);
uid = parseUrl.pathSegments[0]?.trim();
return parseInt(uid)
}
const isDoYouHaveAnyParameters = url.indexOf('?');
const lastIndexOf = url.lastIndexOf("/");
if (isDoYouHaveAnyParameters === -1) {
if (url.endsWith('/')) {
const nTheIndexOfTheLastSecondOccurrenceOfTheSlash = url.lastIndexOf('/', url.length - 2);
uid = url.substring(nTheIndexOfTheLastSecondOccurrenceOfTheSlash + 1, url.length - 1);
} else {
uid = url.substring(lastIndexOf + 1);
}
} else {
uid = url.substring(lastIndexOf + 1, isDoYouHaveAnyParameters);
}
return parseInt(uid);
};
const getUrlBV = (url) => {
let match = url.match(/video\/(.+)\//);
if (match === null) {
match = url.match(/video\/(.+)\?/);
}
if (match === null) {
match=url.match(/video\/(.+)/);
}
return match?.[1]?.trim() || null;
};
const eventRegistry = new Map();
function addEventListenerWithTracking(element, eventName, handler) {
if (!element) {
console.error(element);
throw new Error('错误的元素!')
}
if (!eventRegistry.has(element)) {
eventRegistry.set(element, {events: [], attrs: []});
}
const {events, attrs} = eventRegistry.get(element);
if (attrs.includes(eventName)) {
return
}
attrs.push(eventName);
events.push({eventName, handler});
element.setAttribute(`event-${eventName}`, eventName);
element.addEventListener(eventName, handler);
}
function hasEventListener(element, eventName) {
const elementEvents = eventRegistry.get(element);
if (!elementEvents) {
return false
}
const attr = element.getAttribute(`event-${eventName}`);
if (attr) {
return true
}
const {events} = elementEvents;
return events.some(item => item === eventName);
}
function findElementUntilFound(selector, config = {}) {
const defConfig = {
doc: document,
interval: 1000,
timeout: -1,
};
config = {...defConfig, ...config};
return new Promise((resolve, reject) => {
const i1 = setInterval(() => {
const element = config.doc.querySelector(selector);
if (element) {
resolve(element);
clearInterval(i1);
}
}, config.interval);
if (config.timeout > 0) {
setTimeout(() => {
clearInterval(i1);
reject(null); // 超时则返回 null
}, config.timeout);
}
});
}
function findElementsUntilFound(selector, config = {}) {
const defConfig = {doc: document, interval: 1000, timeout: -1};
config = {...defConfig, ...config};
return new Promise((resolve, reject) => {
const i1 = setInterval(() => {
const elements = config.doc.querySelectorAll(selector);
if (elements.length > 0) {
resolve(elements);
clearInterval(i1);
}
}, config.interval);
if (config.timeout > 0) {
setTimeout(() => {
clearInterval(i1);
reject(null); // 超时则返回 null
}, config.timeout);
}
});
}
function findElementWithTimeout(selector, config = {}) {
const defConfig = {
doc: document,
interval: 1000,
timeout: 60000
};
config = {...defConfig, ...config};
return new Promise((resolve) => {
let intervalId;
function attemptToFind() {
const element = config.doc.querySelector(selector);
if (element) {
clearInterval(intervalId);
resolve({
state: true,
msg: "已找到元素",
el: element
});
}
}
intervalId = setInterval(attemptToFind, config.interval);
const timeout = setTimeout(() => {
clearInterval(intervalId);
resolve({
state: false,
msg: "已超时:" + config.timeout
}); // 超时后提示信息
clearTimeout(timeout);
}, config.timeout);
attemptToFind(); // 立即尝试一次
});
}
const findElementsAndBindEvents = (css, callback, config = {}) => {
config = {
...{
interval: 2000,
timeOut: 3000
}, config
};
setTimeout(() => {
findElementUntilFound(css, {interval: config.interval}).then((el) => {
el.addEventListener("click", () => {
callback();
});
});
}, config.timeOut);
};
var elUtil = {
getUrlUID,
getUrlBV,
addEventListenerWithTracking,
findElementUntilFound,
findElementWithTimeout,
findElementsUntilFound,
findElementsAndBindEvents,
hasEventListener
};
const exactMatch = (ruleList, value) => {
if (ruleList === null || ruleList === undefined) return false;
if (!Array.isArray(ruleList)) return false
return ruleList.some(item => item === value);
};
const regexMatch = (ruleList, value) => {
if (ruleList === null || ruleList === undefined) return null;
if (!Array.isArray(ruleList)) return null
value = value.toLowerCase();
value = value.split(/[\t\r\f\n\s]*/g).join("");
const find = ruleList.find(item => {
try {
return value.search(item) !== -1;
} catch (e) {
const msg = `正则匹配失败,请检查规则列表中的正则表达式是否正确,错误信息:${e.message}`;
eventEmitter.emit('正则匹配时异常', {e, msg});
return false;
}
});
return find === undefined ? null : find;
};
const fuzzyMatch = (ruleList, value) => {
if (ruleList === null || ruleList === undefined||value===null) return null;
if (!Array.isArray(ruleList)) return null
const find = ruleList.find(item => value.toLowerCase().includes(item));
return find === undefined ? null : find;
};
var ruleMatchingUtil = {
exactMatch,
regexMatch,
fuzzyMatch
};
const Tip = {
success(text, config) {
Qmsg.success(text, config);
},
successBottomRight(text) {
this.success(text, {position: "bottomright"});
},
videoBlock(text) {//屏蔽了视频的提示
this.success(text, {position: "bottomright"});
},
info(text, config) {
Qmsg.info(text, config);
},
infoBottomRight(text) {
this.info(text, {position: "bottomright"});
},
error(text, config) {
Qmsg.error(text, config);
},
errorBottomRight(text) {
this.error(text, {position: "bottomright"});
},
warning(text, config) {
Qmsg.warning(text, config);
},
config(cfg) {//设置全局Tip配置
Qmsg.config(cfg);
},
loading(text, config) {
return Qmsg.loading(text, config);
},
close(loading) {
try {
loading.close();
} catch (e) {
console.error(e);
this.error("loading关闭失败!");
}
},
printLn(content) {
Util.printElement("#outputInfo", `${content}`);
},
printVideo(color, content, name, uid, title, videoHref) {
Util.printElement("#outputInfo", `
${Util.toTimeString()}${content}屏蔽用户【${name}】uid=【${uid}】标题【${title}】
`);
},
printCommentOn(color, content, name, uid, primaryContent) {
Util.printElement("#outputInfo", `
${Util.toTimeString()}${content} 屏蔽用户【${name}】uid=【${uid}】
原言论=【${primaryContent}】
`);
}
};
const isTopicDetailPage = (url) => {
return url.includes("//www.bilibili.com/v/topic/detail/")
};
const getDataList$1 = async () => {
const elList = await elUtil.findElementsUntilFound(".list__topic-card");
const list = [];
for (let el of elList) {
const name = el.querySelector(".bili-dyn-title").textContent.trim();
const uidEl = el.querySelector(".bili-dyn-item__following");
const uid = parseInt(uidEl.getAttribute("data-mid"));
const judgmentEl = el.querySelector(".bili-dyn-card-video__title");
const data = {name, uid, el, judgmentVideo: judgmentEl !== null};
if (judgmentEl !== null) {
data.title = judgmentEl.textContent.trim();
const videoUrl = el.querySelector(".bili-dyn-card-video").href;
data.videoUrl = videoUrl;
data.bv = elUtil.getUrlBV(videoUrl);
data.insertionPositionEl = el.querySelector(".bili-dyn-content__orig");
data.explicitSubjectEl = data.insertionPositionEl;
} else {
const dynTitle = el.querySelector(".dyn-card-opus__title");
const contentTitle = dynTitle === null ? "" : dynTitle.textContent.trim();
const contentBody = el.querySelector(".bili-rich-text>div").textContent.trim();
data.insertionPositionEl = el.querySelector(".dyn-card-opus");
data.explicitSubjectEl = data.insertionPositionEl;
data.content = contentTitle + contentBody;
}
list.push(data);
}
return list;
};
const __shieldingVideo = (videoData) => {
if (shielding.shieldingVideoDecorated(videoData)) {
return;
}
shielding.addTopicDetailVideoBlockButton({data: videoData, maskingFunc: startShielding});
};
const __shieldingDynamic = (dynamicData) => {
if (shielding.shieldingCommentDecorated(dynamicData)) {
return;
}
shielding.addTopicDetailContentsBlockButton({data: dynamicData, maskingFunc: startShielding});
};
const startShielding = async () => {
const list = await getDataList$1();
const css = {width: "100%"};
for (let data of list) {
data.css = css;
if (data.judgmentVideo) {
__shieldingVideo(data);
} else {
__shieldingDynamic(data);
}
}
};
var topicDetail = {
isTopicDetailPage,
startShielding
};
const getUrlUserLevel = (src) => {
const levelMath = src?.match(/level_(.+)\.svg/) || null;
let level = -1;
if (levelMath !== null) {
const levelRow = levelMath[1];
if (levelRow === 'h') {
level = 7;
} else {
level = parseInt(levelRow);
}
}
return level;
};
const getOldUserLevel = (iEl) => {
let level = -1;
const levelCLassName = iEl.classList[1];
if (levelCLassName === 'level-hardcore') {
level = 7;
} else {
const levelMatch = levelCLassName.match(/level-(.+)/)?.[1] || '';
level = parseInt(levelMatch);
}
return level
};
const getCommentSectionList = async () => {
const commentApp = await elUtil.findElementUntilFound("bili-comments",
{interval: 500});
const comments = await elUtil.findElementsUntilFound("#feed>bili-comment-thread-renderer",
{doc: commentApp.shadowRoot, interval: 500});
const commentsData = [];
let isLoaded = false;
for (let el of comments) {
const theOPEl = el.shadowRoot.getElementById("comment").shadowRoot;
const theOPUserInfo = theOPEl.querySelector("bili-comment-user-info")
.shadowRoot.getElementById("info");
const userNameEl = theOPUserInfo.querySelector("#user-name>a");
const userLevelSrc = theOPUserInfo.querySelector('#user-level>img')?.src || null;
const level = getUrlUserLevel(userLevelSrc);
isLoaded = theOPEl.querySelector("#content>bili-rich-text")
.shadowRoot.querySelector("#contents>*") !== null;
if (!isLoaded) {
break;
}
const theOPContentEl = theOPEl.querySelector("#content>bili-rich-text")
.shadowRoot.querySelector("#contents");
const theOPContent = theOPContentEl.textContent.trim();
const userName = userNameEl.textContent.trim();
const userUrl = userNameEl.href;
const uid = elUtil.getUrlUID(userUrl);
const replies = [];
commentsData.push({
name: userName,
userUrl,
uid,
level,
content: theOPContent,
replies,
el,
insertionPositionEl: theOPUserInfo,
explicitSubjectEl: theOPEl.querySelector("#body")
});
const inTheBuildingEls = el.shadowRoot.querySelector("bili-comment-replies-renderer")
.shadowRoot.querySelectorAll("bili-comment-reply-renderer");
for (let inTheBuildingEl of inTheBuildingEls) {
const inTheContentEl = inTheBuildingEl.shadowRoot;
const biliCommentUserInfo = inTheContentEl.querySelector("bili-comment-user-info");
biliCommentUserInfo.style.display = 'block';
const inTheBuildingUserInfo = biliCommentUserInfo.shadowRoot.getElementById("info");
const inTheBuildingUserNameEl = inTheBuildingUserInfo.querySelector("#user-name>a");
const inTheBuildingUserName = inTheBuildingUserNameEl.textContent.trim();
const inTheBuildingUserUrl = inTheBuildingUserNameEl.href;
const inTheBuildingUid = elUtil.getUrlUID(inTheBuildingUserUrl);
const biliRichTextEL = inTheContentEl.querySelector("bili-rich-text");
const inTheBuildingContent = biliRichTextEL.shadowRoot.getElementById("contents").textContent.trim();
const userLevelSrc = inTheBuildingUserInfo.querySelector('#user-level>img')?.src || null;
const level = getUrlUserLevel(userLevelSrc);
replies.push({
name: inTheBuildingUserName,
userUrl: inTheBuildingUserUrl,
uid: inTheBuildingUid,
level,
content: inTheBuildingContent,
el: inTheBuildingEl,
insertionPositionEl: inTheBuildingUserInfo,
explicitSubjectEl: inTheBuildingEl
});
}
}
if (!isLoaded) {
await defUtil.wait(500);
return getCommentSectionList()
}
return commentsData;
};
const getOldCommentSectionList = async () => {
let results;
try {
results = await elUtil.findElementsUntilFound(".reply-list>.reply-item", {timeout: 5000});
} catch (e) {
return []
}
const commentsData = [];
for (let el of results) {
const theOPEl = el.querySelector(".root-reply-container");
const theOPUserInfoEl = theOPEl.querySelector(".user-name");
const userName = theOPUserInfoEl.textContent.trim();
const uid = parseInt(theOPUserInfoEl.getAttribute("data-user-id"));
const userUrl = `https://space.bilibili.com/${uid}`;
const theOPContent = theOPEl.querySelector(".reply-content").textContent.trim();
const userInfoEl = el.querySelector(".user-info");
const iEl = userInfoEl.querySelector('i');
const level = getOldUserLevel(iEl);
const replies = [];
commentsData.push({
name: userName,
userUrl,
uid,
content: theOPContent,
level,
replies,
el,
insertionPositionEl: userInfoEl,
explicitSubjectEl: el.querySelector(".content-warp")
});
const inTheBuildingEls = el.querySelectorAll(".sub-reply-container>.sub-reply-list>.sub-reply-item");
for (let inTheBuildingEl of inTheBuildingEls) {
const subUserNameEl = inTheBuildingEl.querySelector(".sub-user-name");
const uid = parseInt(subUserNameEl.getAttribute("data-user-id"));
const userName = subUserNameEl.textContent.trim();
const userUrl = `https://space.bilibili.com/${uid}`;
const subContent = inTheBuildingEl.querySelector(".reply-content").textContent.trim();
const subUserInfoEl = inTheBuildingEl.querySelector(".sub-user-info");
const iEl = subUserInfoEl.querySelector('i');
const level = getOldUserLevel(iEl);
const replyContentContainerEl = inTheBuildingEl.querySelector('span.reply-content-container');
replyContentContainerEl.style.display = 'block';
replies.push({
name: userName,
userUrl,
uid,
level,
content: subContent,
el: inTheBuildingEl,
insertionPositionEl: subUserInfoEl,
explicitSubjectEl: inTheBuildingEl
});
}
}
return commentsData;
};
const startShieldingComments = async () => {
let list;
const href = window.location.href;
if (localMKData.isDiscardOldCommentAreas()) {
list = await getCommentSectionList();
} else if (href.includes("https://space.bilibili.com/") || topicDetail.isTopicDetailPage(href)) {
list = await getOldCommentSectionList();
} else {
list = await getCommentSectionList();
}
shielding.shieldingComments(list);
};
var commentSectionModel = {
startShieldingComments
};
const getVideoTags = async (bv) => {
const response = await fetch(`https://api.bilibili.com/x/web-interface/view/detail/tag?bvid=${bv}`);
const videoTagData = {bv, state: false, tags: []};
if (!response.ok) {
videoTagData.msgData = {msg: 'fetch网络请求失败:获取视频tag失败', response};
return videoTagData
}
let responseJson;
try {
responseJson = await response.json();
} catch (e) {
videoTagData.msgData = {msg: '获取视频tag异常:转换json内容失败', e};
return videoTagData
}
const {code, data} = responseJson;
if (code !== 0) {
videoTagData.msgData = {msg: '获取视频tag失败', responseJson};
return videoTagData
}
try {
for (let datum of data) {
videoTagData.tags.push(datum['tag_name']);
}
} catch (e) {
videoTagData.msgData = {msg: '获取视频tag异常:遍历读取data数据时失败', e};
return videoTagData
}
videoTagData.state = true;
videoTagData.msgData = {msg: '获取视频tag成功'};
return videoTagData
};
const getVideoTagsPackaging = async (videoData) => {
const {bv, title, name} = videoData;
const find = await bvDexie.findBv(bv);
if (find) {
return {state: true, data: {bv, name, title, tags: find.tags}}
}
const videoTagData = await getVideoTags(bv);
if (!videoTagData.state) {
console.error(videoTagData.msgData.msg, videoTagData.msgData);
return {state: false, data: videoTagData}
}
const {tags} = videoTagData;
const bool = await bvDexie.addTagsData({bv, title, name, tags});
if (bool) {
await bvDexie.updateLocalData();
console.log('mk-db-tags-添加数据成功', videoTagData, videoData);
} else {
console.error('mk-db-tags-添加数据失败', videoTagData, videoData);
}
return {state: true, data: {bv, name, title, tags}}
};
var bFetch = {
getVideoTagsPackaging
};
const addBlockButton$1 = (data, tagCss = '', position = []) => {
const {insertionPositionEl, explicitSubjectEl, css} = data.data;
if (tagCss !== '') {
if (insertionPositionEl.querySelector("." + tagCss)) return;
}
const buttonEL = document.createElement("button");
buttonEL.setAttribute("gz_type", "");
if (tagCss !== '') {
buttonEL.className = tagCss;
}
buttonEL.textContent = "屏蔽";
if (position.length !== 0) {
buttonEL.style.position = "absolute";
}
if (position.includes("right")) {
buttonEL.style.right = "0";
}
if (position.includes("bottom")) {
buttonEL.style.bottom = "0";
}
if (css !== undefined) {
for (let key of Object.keys(css)) {
buttonEL.style[key] = css[key];
}
}
if (explicitSubjectEl) {
buttonEL.style.display = "none";
elUtil.addEventListenerWithTracking(explicitSubjectEl, "mouseout", () => buttonEL.style.display = "none");
elUtil.addEventListenerWithTracking(explicitSubjectEl, "mouseover", () => buttonEL.style.display = "");
}
insertionPositionEl.appendChild(buttonEL);
buttonEL.addEventListener("click", (event) => {
event.stopImmediatePropagation(); // 阻止事件冒泡和同一元素上的其他事件处理器
event.preventDefault(); // 阻止默认行为
const {uid, name} = data.data;
console.log("该选项数据:", data);
xtip.sheet({
btn: [`uid精确屏蔽-用户uid=${uid}-name=${name}`, `用户名精确屏蔽(不推荐)-用户name=${name}`],
btn1: () => {
if (uid === -1) {
Tip.error("该页面数据不存在uid字段");
return;
}
ruleUtil.addRule(uid, "precise_uid").then(msg => {
xtip.msg(msg);
data.maskingFunc();
}).catch(msg => {
xtip.alert(msg, {icon: 'e'});
});
},
btn2: () => {
if (!name) {
alert("该页面数据不存在name字段" + name);
return;
}
if (!window.confirm('不推荐用户使用精确用户名来屏蔽,确定继续吗?')) return
ruleUtil.addRulePreciseName(name);
},
});
});
};
const addVideoBlockButton$1 = (data) => {
addBlockButton$1(data, "gz_shielding_button", ["right"]);
};
const addPopularVideoBlockButton = (data) => {
addBlockButton$1(data, "gz_shielding_button", ["right", "bottom"]);
};
const addTopicDetailVideoBlockButton = (data) => {
addBlockButton$1(data, "gz_shielding_button");
};
const addTopicDetailContentsBlockButton = (data) => {
const position = data.data.position;
const loop = position !== undefined;
addBlockButton$1(data, "gz_shielding_topic_detail_button", loop ? position : []);
};
const addCommentBlockButton = (commentsData) => {
const data = {
data: commentsData,
maskingFunc: commentSectionModel.startShieldingComments
};
addBlockButton$1(data, "gz_shielding_comment_button");
};
const addLiveContentBlockButton = (commentsData) => {
addBlockButton$1(commentsData, "gz_shielding_live_danmaku_button");
};
const shieldingVideo = (videoData) => {
const {
title, uid = -1,
name, nDuration = -1,
nBulletChat = -1, nPlayCount = -1
} = videoData;
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseUidWhiteArr(), uid)) {
return {state: false};
}
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseUidArr(), uid)) {
return {state: true, type: "精确匹配uid"};
}
let matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getTitleArr(), title);
if (matching !== null) {
return {state: true, type: "模糊匹配标题", matching};
}
matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getTitleCanonicalArr(), title);
if (matching !== null) {
return {state: true, type: "正则匹配标题", matching};
}
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseNameArr(), name)) {
return {state: true, type: "精确匹配用户名"};
}
matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getNameArr(), name);
if (matching !== null) {
return {state: true, type: "模糊匹配用户名", matching};
}
matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getNameCanonical(), name);
if (matching !== null) {
return {state: true, type: "正则用户名", matching};
}
if (nDuration !== -1) {
const min = gmUtil.getData('nMinimumDuration', -1);
if (min > nDuration && min !== -1) {
return {state: true, type: '最小时长', matching: min}
}
const max = gmUtil.getData('nMaximumDuration', -1);
if (max < nDuration && max !== -1) {
return {state: true, type: '最大时长', matching: max}
}
}
if (nBulletChat !== -1) {
const min = gmUtil.getData('nMinimumBarrage', -1);
if (min > nBulletChat && min !== -1) {
return {state: true, type: '最小弹幕数', matching: min}
}
const max = gmUtil.getData('nMaximumBarrage', -1);
if (max < nBulletChat && max !== -1) {
return {state: true, type: '最大弹幕数', matching: max}
}
}
if (nPlayCount !== -1) {
const min = gmUtil.getData('nMinimumPlay', -1);
if (min > nPlayCount && min !== -1) {
return {state: true, type: '最小播放量', matching: min}
}
const max = gmUtil.getData('nMaximumPlayback', -1);
if (max < nPlayCount && max !== -1) {
return {state: true, type: '最大播放量', matching: max}
}
}
return {state: false};
};
const blockBasedVideoTag = async (videoData) => {
const {el, bv = '-1'} = videoData;
if (bv === '-1') {
return
}
const preciseVideoTagArr = ruleKeyListData$1.getPreciseVideoTagArr();
const videoTagArr = ruleKeyListData$1.getVideoTagArr();
if (preciseVideoTagArr.length <= 0 && videoTagArr.length <= 0) {
return
}
const tagsData = await bFetch.getVideoTagsPackaging(videoData);
const {state, data} = tagsData;
if (!state) {
console.log('错误:', data);
return
}
const {tags = []} = data;
for (let tag of tags) {
if (ruleMatchingUtil.exactMatch(preciseVideoTagArr, tag)) {
el?.remove();
Tip.successBottomRight("屏蔽了视频");
output_informationTab.addInfo(output_informationTab.getVideoInfoHtml("精确tag", tag, videoData));
return
}
let fuzzyMatch = ruleMatchingUtil.fuzzyMatch(videoTagArr, tag);
if (fuzzyMatch) {
el?.remove();
Tip.successBottomRight("屏蔽了视频");
output_informationTab.addInfo(output_informationTab.getVideoInfoHtml("模糊tag", fuzzyMatch, videoData));
return
}
fuzzyMatch = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getVideoTagCanonicalArr(), tag);
if (fuzzyMatch) {
el?.remove();
Tip.successBottomRight("屏蔽了视频");
output_informationTab.addInfo(output_informationTab.getVideoInfoHtml("正则tag", fuzzyMatch, videoData));
return
}
}
};
const shieldingVideoDecorated = (videoData, method = "remove") => {
const {el} = videoData;
if (el.style.display === "none") {
return true
}
const {state, type, matching = null} = shieldingVideo(videoData);
if (state) {
if (method === "remove") {
el?.remove();
} else {
el.style.display = "none";
}
Tip.successBottomRight("屏蔽了视频");
const videoInfoHtml = output_informationTab.getVideoInfoHtml(type, matching, videoData);
output_informationTab.addInfo(videoInfoHtml);
return true;
}
blockBasedVideoTag(videoData);
return state;
};
const shieldingDynamic = (dynamicData) => {
const {
content = null,
el,
title = null,
tag = null
} = dynamicData;
let matching = null;
if (content !== null) {
matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getCommentOnArr(), content);
if (matching !== null) {
el?.remove();
return {state: true, type: "评论模糊内容", matching};
}
matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getCommentOnCanonicalArr(), content);
if (matching !== null) {
el?.remove();
return {state: true, type: "评论正则内容", matching};
}
}
if (title !== null) {
matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getTitleArr(), title);
if (matching !== null) {
el?.remove();
return {state: true, type: "模糊标题", matching};
}
matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getTitleCanonicalArr(), title);
if (matching !== null) {
el?.remove();
return {state: true, type: "正则标题", matching};
}
}
if (tag !== null) {
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseTagArr(), tag)) {
el?.remove();
return {state: true, type: "精确tag"};
}
matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getTagArr(), tag);
if (matching !== null) {
el?.remove();
return {state: true, type: "模糊tag", matching};
}
matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getTagCanonicalArr(), tag);
if (matching !== null) {
el?.remove();
return {state: true, type: "正则tag", matching};
}
}
return {state: false}
};
const shieldingDynamicDecorated = (dynamicData) => {
const {state, type, matching} = shieldingDynamic(dynamicData);
if (state) {
Tip.successBottomRight("屏蔽了视频");
output_informationTab.addInfo(output_informationTab.getDynamicContentInfoHtml(type, matching, dynamicData));
}
return state;
};
const shieldingComment = (commentsData) => {
const {content, uid, name, level = -1} = commentsData;
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseUidWhiteArr(), uid)) {
return {state: false};
}
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseUidArr(), uid)) {
return {state: true, type: "精确匹配uid"};
}
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseNameArr(), name)) {
return {state: true, type: "精确用户名"};
}
let matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getNameArr(), name);
if (matching !== null) {
return {state: true, type: "模糊匹配用户名", matching};
}
matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getNameCanonical(), name);
if (matching !== null) {
return {state: true, type: "正则用户名", matching};
}
matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getCommentOnArr(), content);
if (matching !== null) {
return {state: true, type: "模糊评论内容", matching};
}
matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getCommentOnCanonicalArr(), content);
if (matching !== null) {
return {state: true, type: "正则评论内容", matching};
}
if (level !== -1) {
const min = gmUtil.getData('nMinimumLevel', -1);
if (min > level) {
return {state: true, type: "评论区最小用户等级过滤", matching: min};
}
const max = gmUtil.getData('nMaximumLevel', -1);
if (max > level) {
return {state: true, type: "评论区最大用户等级过滤", matching: max};
}
}
return {state: false};
};
const shieldingCommentDecorated = (commentsData) => {
const {state, type, matching} = shieldingComment(commentsData);
if (state) {
commentsData.el?.remove();
Tip.successBottomRight("屏蔽了评论");
output_informationTab.addInfo(output_informationTab.getCommentInfoHtml(type, matching, commentsData));
}
return state;
};
const shieldingLiveRoomContentDecorated = (liveRoomContent) => {
let {state, type, matching} = shieldingComment(liveRoomContent);
const {el, fansMedal} = liveRoomContent;
if (fansMedal !== null) {
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseFanCardArr(), fansMedal)) {
el?.remove();
state = true;
type = "精确粉丝牌";
}
}
if (state) {
el?.remove();
Tip.successBottomRight("屏蔽了直播间评论");
}
if (type) {
output_informationTab.addInfo(output_informationTab.getLiveRoomCommentInfoHtml(type, matching, liveRoomContent));
}
return state;
};
const shieldingComments = (commentsDataList) => {
for (let commentsData of commentsDataList) {
if (shieldingCommentDecorated(commentsData)) continue;
addCommentBlockButton(commentsData);
const {replies = []} = commentsData;
if (replies.length === 0) continue;
for (let reply of replies) {
if (shieldingCommentDecorated(reply)) continue;
addCommentBlockButton(reply);
}
}
};
const shieldingLiveRoom = (liveRoomData) => {
const {name, title, partition, uid = -1} = liveRoomData;
if (uid !== -1) {
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseUidWhiteArr(), uid)) {
return {state: false};
}
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseUidArr(), uid)) {
return {state: true, type: "精确用户uid"};
}
}
let matching;
if (name) {
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseNameArr(), name)) {
return {state: true, type: "精确用户名"};
}
matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getNameArr(), name);
if (matching) {
return {state: true, type: "模糊用户名", matching};
}
}
matching = ruleMatchingUtil.exactMatch(ruleKeyListData$1.getTitleArr(), title);
if (matching) {
return {state: true, type: "模糊标题", matching};
}
matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getTitleCanonicalArr(), title);
if (matching) {
return {state: true, type: "正则标题", matching};
}
if (partition) {
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPrecisePartitionArr(), partition)) {
return {state: true, type: "精确直播分区"};
}
}
return {state: false};
};
const shieldingLiveRoomDecorated = (liveRoomData) => {
const {state, type, matching = null} = shieldingLiveRoom(liveRoomData);
if (state) {
liveRoomData.el?.remove();
Tip.successBottomRight("屏蔽了直播间");
output_informationTab.addInfo(output_informationTab.getLiveRoomInfoHtml(type, matching, liveRoomData));
}
return state;
};
const intervalExecutionStartShieldingVideoInert = (func, name = '') => {
let i1 = -1;
const start = () => {
if (i1 !== -1) {
return
}
console.log('开始执行屏蔽' + name);
i1 = setInterval(() => {
func();
console.log(`执行屏蔽${name}列表-定时器正在执行`);
}, 1500);
};
const stop = () => {
if (i1 === -1) {
return
}
clearInterval(i1);
console.log(`已停止执行屏蔽${name}列表`);
i1 = -1;
};
return {start, stop}
};
var shielding = {
shieldingVideoDecorated,
shieldingDynamicDecorated,
shieldingCommentDecorated,
shieldingLiveRoomDecorated,
shieldingComments,
addVideoBlockButton: addVideoBlockButton$1,
addCommentBlockButton,
shieldingLiveRoomContentDecorated,
addLiveContentBlockButton,
addPopularVideoBlockButton,
addTopicDetailVideoBlockButton,
addTopicDetailContentsBlockButton,
intervalExecutionStartShieldingVideoInert,
addBlockButton: addBlockButton$1
};
const toPlayCountOrBulletChat = (str) => {
if (!str) {
return -1
}
str = str.split(/[\t\r\f\n\s]*/g).join("");
const replace = str.replace(/[^\d.]/g, '');
if (str.endsWith('万') || str.endsWith('万次') || str.endsWith('万弹幕')) {
return parseFloat(replace) * 10000;
}
if (str.endsWith('次') || str.endsWith('弹幕')) {
return parseInt(replace);
}
return parseInt(str)
};
const timeStringToSeconds = (timeStr) => {
if (!timeStr) {
return -1
}
const parts = timeStr.split(':');
switch (parts.length) {
case 1: // 只有秒
return Number(parts[0]);
case 2: // 分钟和秒
return Number(parts[0]) * 60 + Number(parts[1]);
case 3: // 小时、分钟和秒
return Number(parts[0]) * 3600 + Number(parts[1]) * 60 + Number(parts[2]);
default:
throw new Error('Invalid time format');
}
};
var sFormatUtil = {
toPlayCountOrBulletChat,
timeStringToSeconds
};
const isHome = (url, title) => {
if (title !== "哔哩哔哩 (゜-゜)つロ 干杯~-bilibili") {
return false
}
if (url === 'https://www.bilibili.com/') {
return true
}
return url.includes('https://www.bilibili.com/?spm_id_from=')
};
const adaptationBAppCommerce$1 = localMKData.getAdaptationBAppCommerce();
const deDesktopDownloadTipEl = async () => {
const el = await elUtil.findElementUntilFound(".desktop-download-tip");
el?.remove();
const log = "已删除下载提示";
Tip.infoBottomRight(log);
console.log(log, el);
};
const getChangeTheVideoElList = async () => {
const elList = await elUtil.findElementsUntilFound(".container.is-version8>.feed-card");
const list = [];
for (let el of elList) {
try {
const tempData = getVideoData(el);
const {userUrl} = tempData;
const videoUrl = el.querySelector(".bili-video-card__info--tit>a")?.href || null;
if (!userUrl.includes("//space.bilibili.com/")) {
el?.remove();
const log = "遍历换一换视频列表中检测到异常内容,已将该元素移除";
Tip.infoBottomRight(log);
console.log(log, el);
continue;
}
const items = {
...tempData, ...{
videoUrl,
el,
insertionPositionEl: el.querySelector(".bili-video-card__info--bottom"),
explicitSubjectEl: el.querySelector(".bili-video-card__info")
}
};
if (videoUrl?.includes('www.bilibili.com/video')) {
items.bv = elUtil.getUrlBV(videoUrl);
}
list.push(items);
} catch (e) {
el.remove();
Qmsg.error("获取视频信息失败");
}
}
return list
};
const getVideoData = (el) => {
const title = el.querySelector(".bili-video-card__info--tit").title;
const name = el.querySelector(".bili-video-card__info--author").textContent.trim();
let nPlayCount = el.querySelector('.bili-video-card__stats--text')?.textContent.trim();
nPlayCount = sFormatUtil.toPlayCountOrBulletChat(nPlayCount);
let nBulletChat = el.querySelector('.bili-video-card__stats--text')?.textContent.trim();
nBulletChat = sFormatUtil.toPlayCountOrBulletChat(nBulletChat);
let nDuration = el.querySelector('.bili-video-card__stats__duration')?.textContent.trim();
nDuration = sFormatUtil.timeStringToSeconds(nDuration);
const userUrl = el.querySelector(".bili-video-card__info--owner").getAttribute("href");
const uid = elUtil.getUrlUID(userUrl);
return {
title,
name,
uid,
nPlayCount,
nBulletChat,
nDuration,
userUrl
}
};
const getHomeVideoELList = async () => {
const elList = await elUtil.findElementsUntilFound(".container.is-version8>.bili-video-card");
let list = [];
for (let el of elList) {
try {
const tempData = getVideoData(el);
const {userUrl} = tempData;
if (!userUrl.includes("//space.bilibili.com/")) {
el?.remove();
const log = "遍历换一换视频列表下面列表时检测到异常内容,已将该元素移除";
Tip.infoBottomRight(log);
console.log(log, el);
continue;
}
const videoUrl = el.querySelector(".bili-video-card__info--tit>a")?.href;
const items = {
...tempData, ...{
videoUrl,
el,
insertionPositionEl: el.querySelector(".bili-video-card__info--bottom"),
explicitSubjectEl: el.querySelector(".bili-video-card__info")
}
};
if (videoUrl?.includes('www.bilibili.com/video')) {
items.bv = elUtil.getUrlBV(videoUrl);
}
list.push(items);
} catch (e) {
el?.remove();
Tip.infoBottomRight("遍历视频列表中检测到异常内容,已将该元素移除;");
}
}
return list;
};
const getGateActivatedTab = async () => {
const el = await elUtil.findElementUntilFound(".ant-radio-group>.ant-radio-button-wrapper-checked .css-1k4kcw8");
return el?.textContent.trim();
};
const getGateDataList = async () => {
const elList = await elUtil.findElementsUntilFound(".bilibili-gate-video-grid>[data-bvid].bili-video-card");
const list = [];
for (let el of elList) {
const tempData = getVideoData(el);
const videoUrl = el.querySelector("a.css-feo88y")?.href;
const bv = elUtil.getUrlBV(videoUrl);
const insertionPositionEl = el.querySelector(".bili-video-card__info--owner");
list.push({
...tempData, ...{
videoUrl,
el,
bv,
insertionPositionEl,
explicitSubjectEl: el
}
});
}
return list;
};
const startShieldingGateVideoList = async () => {
const list = await getGateDataList();
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData, "hide")) {
continue;
}
shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingGateVideoList});
}
};
const startIntervalShieldingGateVideoList = () => {
const throttle = defUtil.throttle(startShieldingGateVideoList, 2000);
setInterval(async () => {
await getGateActivatedTab();
throttle();
}, 1500);
};
const startClearExcessContentList = () => {
if (adaptationBAppCommerce$1) return;
setInterval(() => {
const otherElList = document.querySelectorAll(".floor-single-card");
const liveList = document.querySelectorAll(".bili-live-card");
const elList = [...otherElList, ...liveList];
for (let el of elList) {
el?.remove();
}
}, 1000);
console.log("已启动每秒清理首页视频列表中多余的内容");
};
const startShieldingChangeVideoList = async () => {
const list = await getChangeTheVideoElList();
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue;
}
shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingChangeVideoList});
}
};
const startDebounceShieldingChangeVideoList = defUtil.debounce(startShieldingChangeVideoList, 200);
const startShieldingHomeVideoList = async () => {
const homeVideoELList = await getHomeVideoELList();
for (const videoData of homeVideoELList) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue;
}
shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingHomeVideoList});
}
};
const startDebounceShieldingHomeVideoList = defUtil.debounce(startShieldingHomeVideoList, 500);
const scrollMouseUpAndDown = async () => {
if (adaptationBAppCommerce$1) return;
await defUtil.smoothScroll(false, 100);
return defUtil.smoothScroll(true, 600);
};
var bilibiliHome = {
isHome,
startClearExcessContentList,
startDebounceShieldingChangeVideoList,
startDebounceShieldingHomeVideoList,
scrollMouseUpAndDown,
deDesktopDownloadTipEl,
startIntervalShieldingGateVideoList
};
var css = `.to_hide_xl {
display: block !important;
}
`;
const installStyle = () => {
const styleElement = document.createElement('style');
styleElement.textContent = css;
document.head.appendChild(styleElement);
};
const getLiveRoomList = async () => {
const elList = await elUtil.findElementsUntilFound('.live-room-cards>.video-list-item');
const list = [];
for (let el of elList) {
const titleAEl = el.querySelector('.bili-live-card__info--tit>a');
const titleEl = el.querySelector('.bili-live-card__info--tit>a>span');
const userEl = el.querySelector('.bili-live-card__info--uname');
const liveUrl = titleAEl.href;
const title = titleEl.textContent.trim();
const userUrl = userEl.href;
const uid = elUtil.getUrlUID(userUrl);
const name = userEl.textContent.trim();
list.push({
title,
liveUrl,
name,
userUrl,
uid,
el,
explicitSubjectEl: el.querySelector('.bili-live-card__info'),
insertionPositionEl: userEl
});
}
return list
};
const addBlockButton = (data) => {
shielding.addBlockButton(data, '', ['right']);
};
const startShieldingLiveRoomList = async () => {
const list = await getLiveRoomList();
for (let liveData of list) {
if (shielding.shieldingLiveRoomDecorated(liveData)) {
continue
}
addBlockButton({data: liveData, maskingFunc: startShieldingLiveRoomList});
}
};
const InstallLiveTopTabsListener = async () => {
const el = await elUtil.findElementUntilFound('.live-condition');
if (elUtil.hasEventListener(el, 'click')) return
elUtil.addEventListenerWithTracking(el, 'click', async (event) => {
const target = event.target;
const label = target.textContent.trim();
if (label === '主播') {
return
}
await startShieldingLiveRoomList();
InstallBottomPagingListener();
installTopRoomOrderListener();
});
console.log("直播顶部选项卡安装监听器已安装");
};
const InstallBottomPagingListener = async () => {
const el = await elUtil.findElementUntilFound('.vui_pagenation--btns');
if (elUtil.hasEventListener(el, 'click')) return
elUtil.addEventListenerWithTracking(el, 'click', async (event) => {
const target = event.target;
if (target.tagName !== 'BUTTON') {
return
}
await startShieldingLiveRoomList();
installTopRoomOrderListener();
});
console.log("底部分页安装监听器已安装");
};
const installTopRoomOrderListener = async () => {
const el = await elUtil.findElementUntilFound('.room-order');
if (elUtil.hasEventListener(el, 'click')) return
elUtil.addEventListenerWithTracking(el, 'click', async (event) => {
const target = event.target;
console.log('顶部房间排序监听器触发了', target.textContent.trim(), target);
await startShieldingLiveRoomList();
InstallBottomPagingListener();
installTopRoomOrderListener();
});
console.log('顶部房间排序监听器已安装');
};
var searchLive = {
InstallLiveTopTabsListener,
installStyle,
startShieldingLiveRoomList,
InstallBottomPagingListener,
installTopRoomOrderListener
};
const isSearch = (url) => {
return url.includes("search.bilibili.com")
};
const currentlyActivatedOptions = async () => {
const el = await elUtil.findElementUntilFound('.vui_tabs--nav-item-active .vui_tabs--nav-text');
const label = el.textContent.trim();
if (label === '直播') {
await searchLive.startShieldingLiveRoomList();
searchLive.InstallLiveTopTabsListener();
searchLive.InstallBottomPagingListener();
elUtil.findElementUntilFound('.live-condition>.vui_button--active').then(activeEl => {
if (activeEl.textContent.trim() !== '主播') {
searchLive.installTopRoomOrderListener();
}
});
}
};
const searchTopTabsIWrapperInstallListener = async () => {
const tempTabs = ['番剧', '影视', '用户'];
const el = await elUtil.findElementUntilFound('.vui_tabs--navbar>ul');
el.addEventListener("click", async (event) => {
const eventTarget = event.target;
if (eventTarget.className !== 'vui_tabs--nav-text') {
return
}
const tabName = eventTarget.textContent.trim();
if (tempTabs.includes(tabName)) {
return
}
if (tabName === '直播') {
searchLive.installTopRoomOrderListener();
return
}
console.log("搜索页顶部选项卡监听器触发了", tabName);
});
console.log("搜索页顶部选项卡安装监听器已安装");
};
const getVideoList$1 = async (css) => {
const elList = await elUtil.findElementsUntilFound(css, {interval: 200});
const list = [];
for (let el of elList) {
const title = el.querySelector(".bili-video-card__info--tit").title;
const userEl = el.querySelector(".bili-video-card__info--owner");
if (userEl === null) {
console.log("获取不到该视频卡片的用户地址,", el);
el?.remove();
continue
}
const userUrl = userEl.getAttribute("href");
if (!userUrl.includes("//space.bilibili.com/")) {
el?.remove();
Tip.infoBottomRight("移除了非视频内容");
console.log("移除了非视频内容", userUrl, el);
continue;
}
const videoUrl = el.querySelector(".bili-video-card__info--right>a")?.href;
if (videoUrl?.includes('live.bilibili.com/')) {
continue
}
const bv = elUtil.getUrlBV(videoUrl);
const uid = elUtil.getUrlUID(userUrl);
const name = userEl.querySelector(".bili-video-card__info--author").textContent.trim();
const bili_video_card__stats_item = el.querySelectorAll('.bili-video-card__stats--item');
let nPlayCount = bili_video_card__stats_item[0]?.textContent.trim();
nPlayCount = sFormatUtil.toPlayCountOrBulletChat(nPlayCount);
let nBulletChat = bili_video_card__stats_item[1]?.textContent.trim();
nBulletChat = sFormatUtil.toPlayCountOrBulletChat(nBulletChat);
let nDuration = el.querySelector('.bili-video-card__stats__duration')?.textContent.trim();
nDuration = sFormatUtil.timeStringToSeconds(nDuration);
list.push({
title,
userUrl,
name,
uid,
bv,
nPlayCount,
nBulletChat,
nDuration,
el,
videoUrl,
insertionPositionEl: el.querySelector(".bili-video-card__info--bottom"),
explicitSubjectEl: el.querySelector(".bili-video-card__info")
});
}
return list;
};
const getTabComprehensiveSortedVideoList = () => {
return getVideoList$1(".video.i_wrapper.search-all-list>.video-list>div");
};
const getOtherVideoList = () => {
return getVideoList$1(".search-page.search-page-video>.video-list.row>div");
};
const startShieldingCSVideoList = async () => {
const list = await getTabComprehensiveSortedVideoList();
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue;
}
shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingCSVideoList});
}
};
const startShieldingOtherVideoList = async () => {
const list = await getOtherVideoList();
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue;
}
shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingOtherVideoList});
}
};
const getTwTabActiveItem = async () => {
const twoTabActiveItem = await elUtil.findElementUntilFound('.vui_button.vui_button--tab.vui_button--active.mr_sm', {interval: 200});
const twoTabActiveItemLabel = twoTabActiveItem.textContent.trim();
return {el: twoTabActiveItemLabel, label: twoTabActiveItemLabel}
};
const startShieldingVideoList$6 = async () => {
const topTabActiveItem = await elUtil.findElementUntilFound('.vui_tabs--nav-item.vui_tabs--nav-item-active', {interval: 200});
const topTabActiveItemLabel = topTabActiveItem.textContent.trim();
if (topTabActiveItemLabel !== '综合') {
await startShieldingOtherVideoList();
return
}
const {label} = await getTwTabActiveItem();
if (label !== '综合排序') {
await startShieldingOtherVideoList();
return
}
const parseUrl = defUtil.parseUrl(window.location.href);
if (parseUrl.queryParams['page']) {
await startShieldingOtherVideoList();
} else {
await startShieldingCSVideoList();
processingExactSearchVideoCardContent();
}
};
const processingExactSearchVideoCardContent = async () => {
let el;
try {
el = await elUtil.findElementUntilFound('.user-list.search-all-list', {interval: 50, timeout: 4000});
} catch (e) {
return
}
const infoCardEl = el.querySelector('.info-card');
const userNameEl = infoCardEl.querySelector('.user-name');
const name = userNameEl.textContent.trim();
const userUrl = userNameEl.href;
const uid = elUtil.getUrlUID(userUrl);
if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseUidArr(), uid)) {
el.remove();
Tip.successBottomRight('屏蔽到用户');
output_informationTab.addInfo(`根据精确uid匹配到用户${name}-【${uid}】`);
return
}
let fuzzyMatch = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getNameArr(), name);
if (fuzzyMatch) {
el.remove();
Tip.infoBottomRight('屏蔽到用户');
output_informationTab.addInfo(`根据模糊用户名【${fuzzyMatch}】匹配到用户${name}-【${uid}】`);
return
}
fuzzyMatch = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getNameCanonical(), name);
if (fuzzyMatch) {
el.remove();
Tip.infoBottomRight('屏蔽到用户');
output_informationTab.addInfo(`根据正则用户名【${fuzzyMatch}】匹配到用户${name}-【${uid}】`);
return
}
const insertionPositionEl = el.querySelector('.info-card.flex_start');
shielding.addBlockButton({
data: {
name,
uid,
insertionPositionEl,
}
});
const videoElList = el.querySelectorAll('.video-list>.video-list-item');
const list = [];
for (let videoEl of videoElList) {
const titleEl = videoEl.querySelector('.bili-video-card__info--right>a');
const videoUrl = titleEl.href;
const bv = elUtil.getUrlBV(videoUrl);
const title = titleEl.textContent.trim();
let nDuration = videoEl.querySelector('.bili-video-card__stats__duration')?.textContent.trim();
nDuration = sFormatUtil.timeStringToSeconds(nDuration);
let nPlayCount = videoEl.querySelector('.bili-video-card__stats--item>span')?.textContent.trim();
nPlayCount = sFormatUtil.toPlayCountOrBulletChat(nPlayCount);
list.push({
title,
userUrl,
name,
uid,
bv,
nPlayCount,
nDuration,
el: videoEl,
videoUrl
});
}
for (let videoData of list) {
shielding.shieldingVideoDecorated(videoData);
}
};
var searchModel = {
isSearch,
searchTopTabsIWrapperInstallListener,
startShieldingVideoList: startShieldingVideoList$6,
currentlyActivatedOptions
};
const getData = (key,defValue=null) => {
const el = document.querySelector('#mk_data');
if (el === null) {
return defValue
}
const text = el.textContent.trim();
const parse = JSON.parse(text);
if (parse[key]) {
return parse[key]
}
return defValue
};
const addData = (key, value) => {
const el = document.querySelector('#mk_data');
if (el === null) {
const mk_data = document.createElement('div');
mk_data.id = 'mk_data';
mk_data.style.display = 'none';
document.head.appendChild(mk_data);
mk_data.textContent = JSON.stringify({[key]: value});
return
}
const txt = el.textContent.trim();
const parse = JSON.parse(txt);
parse[key] = value;
el.textContent = JSON.stringify(parse);
};
const setData = (key, value) => {
addData(key, value);
};
var elData = {
addData,
getData,
setData
};
const isVideoPlayPage = (url) => {
return url.includes("www.bilibili.com/video");
};
const installSingleUserCreatorButton = async () => {
const el = await elUtil.findElementUntilFound('.up-info-container');
const installPositionEl = el.querySelector('.up-info--right');
const butEl = document.createElement("button");
butEl.setAttribute("gz_type", "");
butEl.textContent = "屏蔽";
butEl.style.width = "100%";
butEl.style.display = 'none';
const nameEl = installPositionEl.querySelector('a.up-name');
butEl.addEventListener('click', () => {
const name = nameEl.textContent.trim();
const userUrl = nameEl.href;
const uid = elUtil.getUrlUID(userUrl);
console.log('点击了屏蔽按钮', name, userUrl, uid);
xtip.confirm(`用户uid=${uid}-name=${name}`, {
title: "uid精确屏蔽方式", icon: "a",
btn1: () => {
if (uid === -1) {
Tip.error("该页面数据不存在uid字段");
return;
}
ruleUtil.addRulePreciseUid(uid);
}
});
});
elUtil.addEventListenerWithTracking(installPositionEl, 'mouseover', () => butEl.style.display = '');
elUtil.addEventListenerWithTracking(installPositionEl, 'mouseout', () => butEl.style.display = 'none');
installPositionEl.appendChild(butEl);
Tip.infoBottomRight(`单作者添加屏蔽按钮成功`);
};
const creationTeamInsertsShieldButton = async () => {
const elList = await elUtil.findElementsUntilFound('.container>.membersinfo-upcard-wrap>.membersinfo-upcard');
for (let item of elList) {
const butEL = document.createElement('button');
butEL.className = "gz_button gz_demo";
butEL.textContent = "屏蔽";
butEL.style.display = 'none';
const userUrl = item.querySelector('.avatar').href;
const uid = elUtil.getUrlUID(userUrl);
const name = item.querySelector('.staff-name').textContent.trim();
butEL.addEventListener('click', () => {
xtip.confirm(`uid=${uid}-name=${name}`, {
title: "uid精确屏蔽方式", icon: "a",
btn1: () => {
if (uid === -1) {
Tip.error("该页面数据不存在uid字段");
return;
}
ruleUtil.addRulePreciseUid(uid);
}
});
});
item.appendChild(butEL);
elUtil.addEventListenerWithTracking(item, 'mouseover', () => butEL.style.display = '');
elUtil.addEventListenerWithTracking(item, 'mouseout', () => butEL.style.display = 'none');
}
Tip.infoBottomRight(`创作团队添加屏蔽按钮成功`);
};
const execAuthorAddBlockButton = () => {
elUtil.findElementWithTimeout('.header.can-pointer', {timeout: 4000}).then(res => {
if (res.state) {
creationTeamInsertsShieldButton();
elData.setData('isSingleAuthor', false);
return
}
if (elData.getData('isSingleAuthor', false)) {
return;
}
elData.setData('isSingleAuthor', true);
installSingleUserCreatorButton();
});
};
const getGetTheVideoListOnTheRight$1 = async () => {
await elUtil.findElementUntilFound(".video-page-card-small .b-img img");
const elList = await elUtil.findElementsUntilFound(".video-page-card-small", {interval: 50});
const list = [];
for (let el of elList) {
try {
const elInfo = el.querySelector(".info");
const title = elInfo.querySelector(".title").title;
const name = elInfo.querySelector(".upname .name").textContent.trim();
const userUrl = elInfo.querySelector(".upname>a").href;
const uid = elUtil.getUrlUID(userUrl);
const playInfo = el.querySelector('.playinfo').innerHTML.trim();
const videoUrl = el.querySelector(".info>a").href;
const bv = elUtil.getUrlBV(videoUrl);
let nPlayCount = playInfo.match(/<\/svg>(.*)