// ==UserScript==
// @name 哔哩哔哩屏蔽增强器
// @namespace http://tampermonkey.net/
// @license Apache-2.0
// @version 2.4
// @author byhgz
// @description 对B站视频或评论进行屏蔽,支持关键词模糊正则等,支持时长播放弹幕过滤等,如视频、评论、动态、直播间的评论等,详情可看下面支持的屏蔽类型
// @icon https://static.hdslb.com/images/favicon.ico
// @noframes
// @run-at document-start
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_addStyle
// @grant GM_unregisterMenuCommand
// @grant GM_registerMenuCommand
// @grant GM_openInTab
// @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://unpkg.com/element-ui/lib/index.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/dexie.min.js
// @require https://update.greasyfork.org/scripts/517928/gz_ui_css-v1.js
// @source https://gitee.com/hangexi/BiBiBSPUserVideoMonkeyScript
// homepage https://scriptcat.org/zh-CN/script-show-page/1029
// ==/UserScript==
"use strict";
(function (Vue, Dexie) {
'use strict';
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);
},
openInTab(url, options = {active: true, insert: true, setParent: true}) {
GM_openInTab(url, options);
}
};
class EventEmitter {
#regularEvents = {
events: {},
futures: {}
}
#callbackEvents = {
events: {},
callbackInterval: 1500
}
on(eventName, callback) {
const events = this.#regularEvents.events;
if (events[eventName]) {
events[eventName].push(callback);
return
}
events[eventName] = [];
events[eventName].push(callback);
const futureEvents = this.#regularEvents.futures;
if (futureEvents[eventName]) {
for (const futureEvent of futureEvents[eventName]) {
callback(...futureEvent);
}
delete futureEvents[eventName];
}
}
once(eventName, callback) {
const onceCallback = (...args) => {
callback(...args);
this.#removeCallback(eventName, onceCallback);
};
this.on(eventName, onceCallback);
}
handler(eventName, callback) {
const handlerEvents = this.#callbackEvents.events;
if (handlerEvents[eventName]) {
throw new Error('该事件名已经存在,请更换事件名')
}
handlerEvents[eventName] = callback;
}
invoke(eventName, ...data) {
return new Promise(resolve => {
const handlerEvents = this.#callbackEvents.events;
if (handlerEvents[eventName]) {
resolve(handlerEvents[eventName](...data));
return
}
const i1 = setInterval(() => {
if (handlerEvents[eventName]) {
clearInterval(i1);
resolve(handlerEvents[eventName](...data));
}
}, this.#callbackEvents.callbackInterval);
})
}
send(eventName, ...data) {
const ordinaryEvents = this.#regularEvents;
const events = ordinaryEvents.events;
const event = events[eventName];
if (event) {
for (const callback of event) {
callback(...data);
}
return;
}
const futures = ordinaryEvents.futures;
if (futures[eventName]) {
futures[eventName].push(data);
return;
}
futures[eventName] = [];
futures[eventName].push(data);
}
#removeCallback(eventName, callback) {
const events = this.#regularEvents.events;
if (events[eventName]) {
events[eventName] = events[eventName].filter(cb => cb !== callback);
}
const handlerEvents = this.#callbackEvents.events;
if (handlerEvents[eventName]) {
handlerEvents[eventName] = handlerEvents[eventName].filter(cb => cb !== callback);
}
}
off(eventName) {
const events = this.#regularEvents.events;
if (events[eventName]) {
delete events[eventName];
return true
}
const handlerEvents = this.#callbackEvents.events;
if (handlerEvents[eventName]) {
delete handlerEvents[eventName];
return true
}
return false
}
setInvokeInterval(interval) {
this.#callbackEvents.callbackInterval = interval;
}
getEvents() {
return {
regularEvents: this.#regularEvents,
callbackEvents: this.#callbackEvents
}
}
}
const eventEmitter = new EventEmitter();
const group_url = 'http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=tFU0xLt1uO5u5CXI2ktQRLh_XGAHBl7C&authKey=KAf4rICQYjfYUi66WelJAGhYtbJLILVWumOm%2BO9nM5fNaaVuF9Iiw3dJoPsVRUak&noverify=0&group_code=876295632';
const scriptCat_js_url = 'https://scriptcat.org/zh-CN/script-show-page/1029';
var globalValue = {
group_url,
scriptCat_js_url
};
gmUtil.addGMMenu('主面板', () => {
eventEmitter.send('主面板开关');
}, 'Q');
gmUtil.addGMMenu('脚本猫脚本更新页', () => {
gmUtil.openInTab(globalValue.scriptCat_js_url);
}, 'E');
gmUtil.addGMMenu('gf脚本更新页', () => {
gmUtil.openInTab('https://greasyfork.org/zh-CN/scripts/461382');
}, 'W');
gmUtil.addGMMenu('加入or反馈', () => {
gmUtil.openInTab(globalValue.group_url);
}, "T");
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或通过脚本信息底下联系方式联系作者解决`)) {
gmUtil.openInTab(globalValue.scriptCat_js_url);
gmUtil.openInTab(globalValue.group_url);
}
throw new Error(`外部库验证失败:${msg}`)
}
};
start();
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 isShowRightTopMainButSwitch = () => {
return gmUtil.getData("showRightTopMainButSwitch", false) === true;
};
const setShowRightTopMainButSwitch = (bool) => {
gmUtil.setData("showRightTopMainButSwitch", bool === true);
};
const isFirstFullDisplay = () => {
return gmUtil.getData('isFirstFullDisplay', true) === true
};
const setFirstFullDisplay = (bool) => {
gmUtil.setData('isFirstFullDisplay', bool === true);
};
const isHalfHiddenIntervalAfterInitialDisplay = () => {
return gmUtil.getData('is_half_hidden_interval_after_initial_display', true) === true
};
const setHalfHiddenIntervalAfterInitialDisplay = (bool) => {
gmUtil.setData('is_half_hidden_interval_after_initial_display', 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;
};
const isDelPlayerPageRightVideoList = () => {
return gmUtil.getData("isDelPlayerPageRightVideoList", false) === true
};
const bFuzzyAndRegularMatchingWordsToLowercase$1 = () => {
return gmUtil.getData("bFuzzyAndRegularMatchingWordsToLowercase", true) === true
};
const setFuzzyAndRegularMatchingWordsToLowercase = (bool) => {
gmUtil.setData("bFuzzyAndRegularMatchingWordsToLowercase", bool === true);
};
var localMKData = {
setBorderColor,
getBorderColor,
setOutputInformationFontColor,
getOutputInformationFontColor,
setHighlightInformationColor,
getHighlightInformationColor,
setBOnlyTheHomepageIsBlocked,
getBOnlyTheHomepageIsBlocked,
getAdaptationBAppCommerce,
setAdaptationBAppCommerce,
setDefaultColorInfo,
isCompatible_BEWLY_BEWLY,
setCompatible_BEWLY_BEWLY,
setDiscardOldCommentAreas,
isDiscardOldCommentAreas,
isShowRightTopMainButSwitch,
setShowRightTopMainButSwitch,
isFirstFullDisplay,
setFirstFullDisplay,
isHalfHiddenIntervalAfterInitialDisplay,
setHalfHiddenIntervalAfterInitialDisplay,
isDelPlayerPageRightVideoList,
bFuzzyAndRegularMatchingWordsToLowercase: bFuzzyAndRegularMatchingWordsToLowercase$1,
setFuzzyAndRegularMatchingWordsToLowercase
};
const panel_settings_vue = {
template: `
<div>
<el-card shadow="never">
<template #header>
<span>颜色设置</span>
</template>
<div class="el-horizontal-center">
选择器
<el-color-picker v-model="input_color"/>
</div>
<button gz_type @click="setBorderColorBut">设置边框色</button>
<button gz_type @click="setDefFontColorForOutputInformationBut">设置输出信息默认字体色</button>
<button gz_type @click="setTheFontColorForOutputInformationBut">设置输出信息高亮字体色</button>
<el-tooltip content="刷新页面生效">
<el-button @click="setDefInfoBut">恢复默认</el-button>
</el-tooltip>
</el-card>
<el-card shadow="never">
<template #header>
<span>外部主面板显隐按钮设置</span>
</template>
<el-switch v-model="showRightTopMainButSwitch" active-text="显示按钮"></el-switch>
<el-tooltip content="页面每次加载完之后是否完整展示按钮,否则半隐藏">
<el-switch v-model="isFirstFullDisplay" active-text="初次完整显示"></el-switch>
</el-tooltip>
<el-tooltip content="页面每次加载完之后如完整展示按钮时,间隔10秒后半隐藏处理">
<el-switch v-model="isHalfHiddenIntervalAfterInitialDisplay"
active-text="初次显示后间隔半隐藏"/>
</el-tooltip>
</el-card>
<el-card shadow="never">
<template #header>
<span>说明</span>
</template>
<div>按键盘tab键上的~键为展开关闭主面板</div>
</el-card>
<el-card shadow="never">
<template #header>
<span>devTools</span>
</template>
<el-input v-model.trim="devToolsInputVal" @keyup.enter.native="changeDevToolsInput"></el-input>
</el-card>
</div>`,
data() {
return {
input_color: null,
showRightTopMainButSwitch: localMKData.isShowRightTopMainButSwitch(),
isFirstFullDisplay: localMKData.isFirstFullDisplay(),
isHalfHiddenIntervalAfterInitialDisplay: localMKData.isHalfHiddenIntervalAfterInitialDisplay(),
devToolsInputVal: ''
}
},
methods: {
setBorderColorBut() {
this.$confirm('是否设置面板边框颜色', '提示').then(() => {
localMKData.setBorderColor(this.input_color);
this.$alert("已设置面板边框颜色,刷新生效");
});
},
setDefFontColorForOutputInformationBut() {
this.$confirm("是否设置输出信息默认字体颜色", "提示").then(() => {
localMKData.setOutputInformationFontColor(this.input_color);
this.$alert("已设置输出信息默认字体颜色,刷新生效");
});
},
setTheFontColorForOutputInformationBut() {
this.$confirm('是要设置输出信息高亮字体颜色吗?').then(() => {
localMKData.setHighlightInformationColor(this.input_color);
this.$alert("已设置输出信息高亮字体颜色,刷新生效");
});
},
setDefInfoBut() {
localMKData.setDefaultColorInfo();
this.$alert("已恢复默认颜色,刷新生效");
},
changeDevToolsInput() {
debugger
if (this.devToolsInputVal === 'show-dev') {
gmUtil.setData('dev-', true);
eventEmitter.send('debugger-dev-show', true);
this.devToolsInputVal = '';
}
if (this.devToolsInputVal === 'stop-dev') {
gmUtil.setData('open-dev', false);
eventEmitter.send('debugger-dev-show', false);
this.devToolsInputVal = '';
}
}
},
watch: {
showRightTopMainButSwitch(newVal) {
localMKData.setShowRightTopMainButSwitch(newVal);
eventEmitter.send('显隐主面板开关', newVal);
},
isFirstFullDisplay(newVal) {
localMKData.setFirstFullDisplay(newVal);
},
isHalfHiddenIntervalAfterInitialDisplay(newBool) {
localMKData.setHalfHiddenIntervalAfterInitialDisplay(newBool);
}
}
};
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黑名单(正则匹配)',
},
{
key: 'hotSearchKey',
name: '热搜关键词(模糊匹配)',
},
{
key: 'hotSearchKeyCanonical',
name: '热搜关键词(正则匹配)'
}
];
const otherKeyListData = [
{
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
}
];
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", []);
};
const getHotSearchKeyArr = () => {
return gmUtil.getData("hotSearchKey", []);
};
const getHotSearchKeyCanonicalArr = () => {
return gmUtil.getData("hotSearchKeyCanonical", []);
};
const clearKeyItem = (ruleKey) => {
gmUtil.delData(ruleKey);
};
var ruleKeyListData$1 = {
getNameArr,
getPreciseNameArr,
getNameCanonical,
getPreciseUidArr,
getPreciseUidWhiteArr,
getTitleArr,
getTitleCanonicalArr,
getCommentOnArr,
getCommentOnCanonicalArr,
getRuleKeyListData,
getPreciseTagArr,
getTagArr,
getTagCanonicalArr,
getPreciseFanCardArr,
getPrecisePartitionArr,
getVideoTagArr,
getPreciseVideoTagArr,
getVideoTagCanonicalArr,
getHotSearchKeyArr,
getHotSearchKeyCanonicalArr,
otherKeyListData,
clearKeyItem
};
const verificationInputValue = (ruleValue, type) => {
if (ruleValue === null) return {status: false, res: '内容不能为空'};
if (type === "precise_uid" || type === "precise_uid_white") {
ruleValue = parseInt(ruleValue);
if (isNaN(ruleValue)) {
return {
status: false,
res: '请输入数字!'
};
}
} else {
ruleValue.trim();
}
if (ruleValue === '') {
return {status: false, res: '内容不能为空'};
}
return {status: true, res: ruleValue};
};
const addRule = (ruleValue, type) => {
const verificationRes = verificationInputValue(ruleValue, type);
if (!verificationRes.status) {
return verificationRes
}
const arr = gmUtil.getData(type, []);
if (arr.includes(verificationRes.res)) {
return {status: false, res: '已存在此内容'};
}
arr.push(verificationRes.res);
gmUtil.setData(type, arr);
return {status: true, res: '添加成功'};
};
const showAddRuleInput = async (type) => {
let ruleValue;
try {
const {value} = await eventEmitter.invoke('el-prompt', '请输入要添加的规则内容', 'tip');
ruleValue = value;
} catch (e) {
return
}
const {res, status} = addRule(ruleValue, type);
eventEmitter.send('el-msg', res);
status && eventEmitter.send('刷新规则信息');
status && eventEmitter.send('通知屏蔽');
};
const delRule = (type, value) => {
const verificationRes = verificationInputValue(value, type);
if (!verificationRes.status) {
return verificationRes
}
const {res} = verificationRes;
const arr = gmUtil.getData(type, []);
const indexOf = arr.indexOf(res);
if (indexOf === -1) {
return {status: false, res: '不存在此内容'};
}
arr.splice(indexOf, 1);
gmUtil.setData(type, arr);
return {status: true, res: "移除成功"}
};
const showDelRuleInput = async (type) => {
let ruleValue;
try {
const {value} = await eventEmitter.invoke('el-prompt', '请输入要删除的规则内容', '删除指定规则');
ruleValue = value;
} catch (e) {
return
}
const {status, res} = delRule(type, ruleValue);
eventEmitter.send('el-msg', res);
status && eventEmitter.send('刷新规则信息');
};
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 (const key in parse) {
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, isTip = true) => {
const results = addRule(uid, "precise_uid");
if (isTip) {
eventEmitter.send('el-alert', results.res);
return null
}
return results;
};
const delRUlePreciseUid = (uid, isTip = true) => {
const results = delRule('precise_uid', uid);
if (isTip) {
eventEmitter.send('el-alert', results.res);
return null
}
return results
};
const addRulePreciseName = (name, tip = true) => {
const results = addRule(name, "precise_name");
if (tip) {
eventEmitter.send('el-msg', results.res);
}
return results;
};
const findRuleItemValue = (type, value) => {
return gmUtil.getData(type, []).find(item => item === value) || null
};
var ruleUtil = {
addRule,
showAddRuleInput,
showDelRuleInput,
getRuleContent,
overwriteImportRules,
appendImportRules,
overwriteImportRulesV1,
getNewRuleKeyList,
addRulePreciseUid,
addRulePreciseName,
delRUlePreciseUid,
findRuleItemValue
};
const rule_set_value_dialog = {
template: `
<div>
<el-dialog :visible="show" width="30%" title="修改单项规则值"
:close-on-click-modal="false" :modal="false">
{{ ruleName }}-{{ ruleType }}
<el-form>
<el-form-item label="要修改的值">
<el-input type="text" v-model="oldVal" clearable/>
</el-form-item>
<el-form-item label="修改后的值">
<el-input v-model="newVal" clearable/>
</el-form-item>
</el-form>
<template #footer class="dialog-footer">
<el-button @click="show=false">取消</el-button>
<el-button @click="okBut">确定</el-button>
</template>
</el-dialog>
</div>`,
data() {
return {
show: false,
ruleType: "",
ruleName: "",
oldVal: '',
newVal: ''
}
},
methods: {
okBut() {
let tempOldVal = this.oldVal.trim();
let tempNewVal = this.newVal.trim();
if (tempOldVal.length === 0 || tempNewVal.length === 0) {
this.$alert("请输入要修改的值或新值");
return
}
if (tempNewVal === tempOldVal) {
this.$alert("新值不能和旧值相同");
return;
}
const tempRuleType = this.ruleType;
if (tempRuleType === 'precise_uid' || tempRuleType === 'precise_uid_white') {
tempOldVal = parseInt(tempOldVal);
tempNewVal = parseInt(tempNewVal);
if (isNaN(tempOldVal) || isNaN(tempNewVal)) {
this.$alert("请输入整数数字");
return
}
}
if (!ruleUtil.findRuleItemValue(tempRuleType, tempOldVal)) {
this.$alert("要修改的值不存在");
return;
}
if (ruleUtil.findRuleItemValue(tempRuleType, tempNewVal)) {
this.$alert("新值已存在");
return;
}
const ruleArr = gmUtil.getData(tempRuleType, []);
const indexOf = ruleArr.indexOf(tempOldVal);
ruleArr[indexOf] = tempNewVal;
gmUtil.setData(tempRuleType, ruleArr);
this.$alert(`已将旧值【${tempOldVal}】修改成【${tempNewVal}】`);
this.show = false;
}
},
watch: {
show(newVal) {
if (newVal === false) this.oldVal = this.newVal = '';
}
},
created() {
eventEmitter.on('修改规则对话框', (type, name) => {
this.show = true;
this.ruleType = type;
this.ruleName = name;
});
}
};
const basic_rules_vue = {
components: {rule_set_value_dialog},
template: `
<div>
<el-card shadow="never">
<template #header>
<span>使用说明</span>
</template>
<div>1. 大部分情况下模糊匹配比精确匹配好用</div>
<div>2. 如果可以的话,请优先考虑根据uid精确屏蔽,而非使用用户名相关屏蔽,因用户名可以随意更改</div>
<div>如果用户要添加自己的正则匹配相关的规则时,建议先去该网址进行测试再添加,避免浪费时间
<el-link href="https://www.jyshare.com/front-end/854/" target="_blank"
type="primary">>>>正则表达式在线测试<<<
</el-link>
</div>
<div>
如果更新脚本之后规则全没了,请点击下面的【旧规则自动转新规则】按钮,进行转换,如不行请通过关于和问题反馈选项卡中的反馈渠道联系作者
</div>
</el-card>
<el-card>
<el-select v-model="selectVal" filterable>
<el-option v-for="item in ruleInfoArr" :value="item.type" :key="item.type" :label="item.name"></el-option>
</el-select>
<el-divider/>
<el-button-group>
<el-button @click="operationBut('add')">添加{{ selectText }}</el-button>
<el-button @click="operationBut('del')">移除{{ selectText }}</el-button>
<el-button @click="setRuleBut">修改{{ selectText }}</el-button>
<el-button @click="operationBut('find-item-all')">查询{{ selectText }}的内容</el-button>
</el-button-group>
<el-divider/>
<el-button-group>
<el-button @click="clearItemRuleBut" type="danger">清空{{ selectText }}项</el-button>
<el-button type="danger" @click="operationBut('del_all')">全部移除</el-button>
</el-button-group>
</el-card>
<rule_set_value_dialog/>
</div>`,
data() {
return {
selectVal: 'name',
selectText: "",
ruleActions: [
{
type: "uid",
name: "uid(精确)",
}
],
ruleKeyArr: [],
ruleInfoArr: [],
}
},
methods: {
setRuleBut() {
const type = this.selectVal;
const {name} = this.ruleInfoArr.find(item => item.type === type);
eventEmitter.send('修改规则对话框', type, name);
},
operationBut(model) {
const type = this.selectVal;
if (model === "add") {
ruleUtil.showAddRuleInput(type);
}
if (model === "del") {
ruleUtil.showDelRuleInput(type);
}
if (model === "del_all") {
this.$confirm('确定要删除所有规则吗?').then(() => {
for (let x of this.ruleKeyArr) {
gmUtil.delData(x);
}
this.$alert("删除全部规则成功");
eventEmitter.send('刷新规则信息');
});
}
if (model === 'find-item-all') {
const ruleData = gmUtil.getData(type, []);
eventEmitter.send('展示内容对话框', JSON.stringify(ruleData, null, 4));
}
},
clearItemRuleBut() {
const type = this.selectVal;
const find = this.ruleInfoArr.find(item => item.type === type);
this.$confirm(`是要清空${find.name}的规则内容吗?`, 'tip').then(() => {
ruleKeyListData$1.clearKeyItem(type);
this.$alert(`已清空${find.name}的规则内容`);
});
}
},
watch: {
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,
});
}
const find = this.ruleInfoArr.find(item => item.type === this.selectVal);
this.selectText = find.name;
}
};
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 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
};
var rule_export_import_vue = {
template: `
<div>
<el-card shadow="never">
<template #header>
<span>导出规则</span>
</template>
<button gz_type @click="ruleOutToFIleBut">导出到文件</button>
<button gz_type @click="outToInputBut">导出到编辑框</button>
<button gz_type @click="ruleOutToConsoleBut">导出到控制台</button>
</el-card>
<el-card shadow="never">
<template #header>
<el-row>
<el-col :span="12">
<div class="el-horizontal-left">导入规则</div>
</el-col>
<el-col :span="12">
<div class="el-horizontal-right">
<el-button v-for="item in ruleReference" @click="xtipAlertBut(item.content,item.title)">
{{ item.title }}
</el-button>
</div>
</el-col>
</el-row>
</template>
<div>规则内容请在下面编辑框中导入</div>
<div>旧版本的需要使用下面的v1旧版本导入规则</div>
<div>旧版本的只能覆盖导入</div>
<div>v1之后的版本可以选择覆盖和追加</div>
<div>旧规则转新规则,用于2.0之前版本升上来旧规则内容丢失问题</div>
<el-divider/>
<div>
<button gz_type @click="inputFIleRuleBut">读取外部规则文件</button>
<button gz_type @click="overwriteImportRulesBut">覆盖导入规则</button>
<button gz_type @click="appendImportRulesBut">追加导入规则</button>
<button gz_type @click="overwriteImportRulesV1But">v1旧版本覆盖导入规则</button>
<button gz_type @click="ruleOldToNewBut">旧规则自动转新规则</button>
</div>
<el-divider/>
<div>
<el-input autosize
:autosize="{ minRows: 10, maxRows: 50}"
type="textarea" v-model="ruleContentImport" placeholder="要导入的规则内容"></el-input>
</div>
</el-card>
<input ref="file" type="file" accept="application/json" @change="handleFileUpload"
style="display: none">
</div>`,
data() {
return {
ruleContentImport: "",
ruleReference: [
{
title: "旧版本规则参考",
content: ` {"用户名黑名单模式(精确匹配)":["账号已注销"],"BV号黑名单模式(精确匹配)":[],
"用户名黑名单模式(模糊匹配)":["bili_","_bili"],"用户uid黑名单模式(精确匹配)":[442010132,76525078,225219967,3493283164588093],
"用户uid白名单模式(精确匹配)":[344490740,1861980711],"标题黑名单模式(模糊匹配)":["激励计划","蚌不住","手游激励","游戏活动打卡"],
"标题黑名单模式(正则匹配)":["感觉.*不如","不要笑.*挑战"],"评论关键词黑名单模式(模糊匹配)":["感觉不如","差不多的了"],
"评论关键词黑名单模式(正则匹配)":["这不.+吗","玩.*的","不要笑.*挑战"],"粉丝牌黑名单模式(精确匹配)":[],
"专栏关键词内容黑名单模式(模糊匹配)":[],"动态关键词内容黑名单模式(模糊匹配)":["拼多多","京东红包","京东618红包","618活动"]}`
},
{
title: "新版本规则参考",
content: "待补充"
}
],
}
},
methods: {
overwriteImportRulesBut() {
this.$confirm('是否要覆盖导入规则?').then(() => {
const trim = this.ruleContentImport.trim();
debugger
if (ruleUtil.overwriteImportRules(this.ruleKeyArr, trim)) {
this.$alert('已覆盖导入成功!');
eventEmitter.send('刷新规则信息');
}
});
},
appendImportRulesBut() {
this.$confirm('是否要追加导入规则?').then(() => {
const trim = this.ruleContentImport.trim();
if (ruleUtil.appendImportRules(this.ruleKeyArr, trim)) {
this.$message('已追加导入成功!');
eventEmitter.send('刷新规则信息');
}
});
},
overwriteImportRulesV1But() {
this.$confirm('旧版本-是否导入规则?').then(() => {
const trim = this.ruleContentImport.trim();
if (ruleUtil.overwriteImportRulesV1(trim)) {
this.$message('已导入成功!');
eventEmitter.send('刷新规则信息');
}
});
},
xtipAlertBut(content, title) {
this.$alert(content, title);
},
ruleOldToNewBut() {
ruleConversion.oldToNewRule();
eventEmitter.send('刷新规则信息');
this.$message('已转换成功!');
},
handleFileUpload(event) {
defUtil.handleFileReader(event).then(data => {
const {content} = data;
try {
JSON.parse(content);
} catch (e) {
this.$message('文件内容有误');
return;
}
this.ruleContentImport = content;
this.$message('读取到内容,请按需覆盖或追加');
});
},
inputFIleRuleBut() {
this.$refs.file.click();
},
outToInputBut() {
this.ruleContentImport = ruleUtil.getRuleContent(2);
this.$message('已导出到输入框中');
},
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() {
console.log(ruleUtil.getRuleContent());
this.$message('已导出到控制台上,F12打开控制台查看');
},
},
};
var other_parameter_filter = {
template: `
<div>
<div style="display: flex">
<div style="width: 70vw">
<el-card>
<template #header>
<span>使用说明</span>
</template>
<ol>
<li>如设置时长相关单位为秒</li>
<li>如设置播放量和弹幕量相关单位为个</li>
<li>设置最小播放量则小于该值的视频会屏蔽</li>
<li>设置最大播放量则大于该值的视频会屏蔽</li>
<li>设置最小弹幕量则小于该值的视频会屏蔽</li>
<li>设置最大弹幕量则大于该值的视频会屏蔽</li>
<li>设置最小时长则小于该值的视频会屏蔽</li>
<li>设置最大时长则大于该值的视频会屏蔽</li>
<li>设置最小用户等级则小于该值的会屏蔽,低于该值的会屏蔽掉</li>
<li>设置最大用户等级则大于该值的会屏蔽,高于该值的会屏蔽掉</li>
<li>取消相关限制条件则不做限制处理</li>
<li>右侧信息关键条件-1则为未做任何限制处理</li>
<li>最后因为设置限制条件冲突或限制太多,视频未能限制的情况下,请按需设置限制条件</li>
</ol>
</el-card>
<input gz_type type="number" :min="inputMin" :max="inputMax" v-model="num">
<el-select v-model="selectValue" filterable>
<el-option :value="item.value" v-for="item in selectList" :label="item.name"></el-option>
</el-select>
<div>
<button @click="okVideoSelectBut" gz_type>设置</button>
<button @click="cancelBut" gz_type>取消</button>
<button gz_type @click="allCancelBut">全部取消</button>
</div>
</div>
<div>
<el-button @click="updateInfoBut">刷新</el-button>
<div v-for="item in selectList" style="padding: 5px">
{{ item.name }}{{ item.defVal }}
{{ item.name.includes('时长') ? '秒' : '' }}
</div>
</div>
</div>
</div>`,
data() {
return {
num: 0,
selectList: ruleKeyListData$1.otherKeyListData,
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.num > associatedVal && associatedVal !== -1) {
if (associatedFind.bLarge) {
this.$alert(`要设置的${find.name}值不能大于${associatedFind.name}的值`);
return
}
console.log('正常修改');
}
this.$alert(`已设置${find.name},值为${this.num}`);
gmUtil.setData(this.selectValue, this.num);
this.updateInfo();
},
cancelBut() {
gmUtil.setData(this.selectValue, -1);
const find = this.selectList.find(item => item.value === this.selectValue);
this.$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();
this.$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.num > 6) {
this.num = 6;
}
if (this.num < 3) {
this.num = 3;
}
} else {
this.inputMin = 0;
this.inputMax = '';
}
}
},
created() {
this.updateInfo();
}
};
var rule_information_vue = {
template: `
<div>
<h2>规则信息</h2>
<button gz_type @click="refreshInfoBut">刷新信息</button>
<div v-for="item in ruleInfoArr"
style="padding: 5px">
{{ item.name }}{{ item.len }}个
</div>
</div>`,
data() {
return {
ruleInfoArr: [],
}
},
methods: {
refreshInfoBut() {
for (let x of this.ruleInfoArr) {
x.len = gmUtil.getData(x.type, []).length;
}
this.$notify({
title: 'tip',
message: '刷新规则信息成功',
type: 'success',
});
},
},
created() {
for (let newRuleKeyListElement of ruleUtil.getNewRuleKeyList()) {
this.ruleInfoArr.push({
type: newRuleKeyListElement.key,
name: newRuleKeyListElement.name,
len: 0
});
}
this.refreshInfoBut();
eventEmitter.on('刷新规则信息', () => {
this.refreshInfoBut();
});
}
};
var conditional_processing_vue = {
template: `
<div>
<el-switch v-model="bOnlyTheHomepageIsBlocked" active-text="仅首页屏蔽生效屏蔽"/>
<el-tooltip content="模糊和正则匹配时,将匹配词转小写与规则值匹配。修改后刷新页面生效">
<el-switch v-model="bFuzzyAndRegularMatchingWordsToLowercase" active-text="模糊和正则匹配词转小写"></el-switch>
</el-tooltip>
</div>`,
data() {
return {
bOnlyTheHomepageIsBlocked: localMKData.getBOnlyTheHomepageIsBlocked(),
bFuzzyAndRegularMatchingWordsToLowercase: localMKData.bFuzzyAndRegularMatchingWordsToLowercase(),
}
},
methods: {},
watch: {
bOnlyTheHomepageIsBlocked(newVal) {
localMKData.setBOnlyTheHomepageIsBlocked(newVal);
},
bFuzzyAndRegularMatchingWordsToLowercase(newVal) {
localMKData.setFuzzyAndRegularMatchingWordsToLowercase(newVal);
}
},
created() {
}
};
var ruleManagementVue = {
components: {
rule_export_import_vue,
other_parameter_filter,
rule_information_vue,
conditional_processing_vue,
basic_rules_vue
},
template: `
<div>
<el-tabs type="border-card" tab-position="left">
<el-tab-pane label="基础规则">
<basic_rules_vue/>
</el-tab-pane>
<el-tab-pane label="其他规则">
<other_parameter_filter/>
</el-tab-pane>
<el-tab-pane label="高级规则">待补充</el-tab-pane>
<el-tab-pane label="导出导入">
<rule_export_import_vue/>
</el-tab-pane>
<el-tab-pane label="条件处理">
<conditional_processing_vue/>
</el-tab-pane>
<el-tab-pane label="规则信息">
<rule_information_vue/>
</el-tab-pane>
</el-tabs>
</div>`,
data() {
return {}
}
};
const compatible_setting_vue = {
template: `
<div>
<div>
<el-checkbox v-model="adaptationBAppRecommend">首页屏蔽适配Bilibili-Gate脚本(bilibili-app-recommend)
</el-checkbox>
</div>
<div>
<el-tooltip content="使用之后需刷新对应页面才可生效,勾选即评论区使用新版获取方式,不再使用旧版方式"
placement="top">
<el-checkbox v-model="discardOldCommentAreasV">弃用旧版评论区处理</el-checkbox>
</el-tooltip>
</div>
<div>
<el-checkbox v-model="compatible_BEWLY_BEWLY">兼容BewlyBewly插件</el-checkbox>
</div>
</div>`,
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({
videoInfos: 'bv,tags,userInfo,videoInfo',
});
const addVideoData = async (bv, data) => {
const {tags, userInfo, videoInfo} = data;
try {
await mk_db.videoInfos.add({
bv, tags, userInfo, videoInfo
});
} catch (e) {
console.log(`添加视频数据失败`, data, e);
return false
}
return true
};
const bulkImportVideoInfos = async (friendsData) => {
try {
const lastKeyItem = await mk_db.videoInfos.bulkPut(friendsData);
console.info('批量导入成功,最后一个插入的主键:', lastKeyItem);
return {state: true, lastKeyItem}
} catch (error) {
console.error('批量导入时出错:', error);
return {state: false, error}
}
};
const getVideoInfo = async () => {
return await mk_db.videoInfos.toArray()
};
const clearVideoInfosTable = async () => {
try {
await mk_db.videoInfos.clear();
return true
} catch (e) {
console.log('清除videoInfos表失败', e);
return false
}
};
var bvDexie = {
addVideoData,
clearVideoInfosTable,
bulkImportVideoInfos,
getVideoInfo
};
const cache_management_vue = {
template: `
<div>
<ol>
<li>每个域名中的缓存数据不同</li>
<li>仅仅支持导入json格式</li>
<li>下面导入默认追加模式</li>
</ol>
<div>当前域名:{{ hostname }}</div>
<button gz_type @click="outDbDataBut">导出当前域名的缓存数据</button>
<input ref="inputDemo" type="file" @change="handleFileUpload" accept="application/json"
style="display: none">
<button @click="inputFIleBut" gz_type>追加导入视频缓存数据</button>
<button gz_type @click="clearPageVideoCacheDataBut">清空当前域名的视频缓存数据</button>
</div>`,
data() {
return {
hostname: window.location.hostname
}
},
methods: {
outDbDataBut() {
bvDexie.getVideoInfo().then((data) => {
if (data.length === 0) {
this.$message('当前域名下没有缓存视频数据');
return
}
data = {
hostName: this.hostname,
size: data.length,
data: data
};
defUtil.fileDownload(JSON.stringify(data, null, 4), 'mk-db-videoInfos-cache.json');
this.$message('已导出当前域名的缓存数据');
console.log(data);
});
},
handleFileUpload(event) {
defUtil.handleFileReader(event).then(data => {
const {content} = data;
let parse;
try {
parse = JSON.parse(content);
} catch (e) {
this.$message('文件内容有误');
return;
}
const {hostName = null, videoInfos = []} = parse;
if (!hostName) {
this.$message('hostName字段不存在');
return;
}
if (!defUtil.isIterable(videoInfos)) {
this.$message('文件内容有误,非可迭代的数组!');
return;
}
if (videoInfos.length === 0) {
this.$message('tags数据为空');
return;
}
for (let item of videoInfos) {
if (!item['bv']) {
this.$message('bv字段不存在');
return;
}
if (!item['tags']) {
this.$message('tags字段不存在');
return;
}
if (!item['userInfo']) {
this.$message('userInfo字段不存在');
return;
}
if (!item['videoInfo']) {
this.$message('videoInfo字段不存在');
return;
}
}
bvDexie.bulkImportVideoInfos(videoInfos).then((bool) => {
if (bool) {
this.$message('导入成功');
} else {
this.$message('导入失败');
}
});
});
},
inputFIleBut() {
this.$refs.inputDemo.click();
},
clearPageVideoCacheDataBut() {
this.$confirm('是否清空当前域名下的tags数据').then(() => {
bvDexie.clearVideoInfosTable().then((bool) => {
if (bool) {
this.$message('已清空当前域名下的视频缓存数据');
} else {
this.$message('清空失败');
}
});
});
}
},
created() {
}
};
var donateLayoutVue = {
template: `
<div>
<el-card shadow="hover">
<template #header>
<span>零钱赞助</span>
</template>
<span>1元不嫌少,10元不嫌多,感谢支持!</span>
<el-divider/>
<span>生活不易,作者叹息</span>
<el-divider/>
<span>您的支持是我最大的更新动力</span>
</el-card>
<el-divider/>
<div class="el-vertical-center">
<el-avatar size="large"
src="//i0.hdslb.com/bfs/face/87e9c69a15f7d2b68294be165073c8e07a541e28.jpg@128w_128h_1c_1s.webp"></el-avatar>
</div>
<div class="el-vertical-center">
<el-button round type="primary" @click="showDialogBut">打赏点猫粮</el-button>
</div>
<el-dialog
center
:title="dialogIni.title"
:visible.sync="dialogIni.show">
<div class="el-vertical-center">
<el-image v-for="item in list"
:src="item.src"
style="height: 300px"
:preview-src-list="dialogIni.srcList"/>
</div>
</el-dialog>
</div>`,
data() {
return {
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"},
],
dialogIni: {
title: "打赏点猫粮",
show: false,
srcList: []
}
}
},
methods: {
showDialogBut() {
this.dialogIni.show = true;
}
},
created() {
this.dialogIni.srcList = this.list.map(x => x.src);
}
};
const outputInformationFontColor$1 = localMKData.getOutputInformationFontColor();
const highlightInformationColor$1 = localMKData.getHighlightInformationColor();
var outputInformationVue = {
template: `
<div>
<el-button type="info" @click="clearInfoBut">清空消息</el-button>
<div v-for="item in outputInfoArr" v-html="item"></div>
</div>`,
data() {
return {
outputInfoArr: [],
}
},
methods: {
clearInfoBut() {
this.$confirm('是否清空信息', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.outputInfoArr = [];
this.$message('已清空信息');
});
}
},
created() {
eventEmitter.on('打印信息', (content) => {
const liEL = document.createElement("li");
liEL.innerHTML = content;
this.outputInfoArr.push(liEL.innerHTML);
});
eventEmitter.on('屏蔽视频信息', (type, matching, videoData) => {
const toTimeString = defUtil.toTimeString();
const {name, uid, title, videoUrl} = videoData;
const info = `<b style="color: ${outputInformationFontColor$1}; " gz_bezel>
${toTimeString}-根据${type}-${matching ? `<b style="color: ${highlightInformationColor$1}">【${matching}】</b>` : ""}-屏蔽用户【${name}】uid=
<a href="https://space.bilibili.com/${uid}"
style="color: ${highlightInformationColor$1}"
target="_blank">【${uid}】</a>
标题【<a href="${videoUrl}" target="_blank" style="color: ${highlightInformationColor$1}">${title}</a>】
</b>`;
this.outputInfoArr.push(info);
});
eventEmitter.on('屏蔽评论信息', (type, matching, commentData) => {
const toTimeString = defUtil.toTimeString();
const {name, uid, content} = commentData;
this.outputInfoArr.push(`<b style="color: ${outputInformationFontColor$1}; " gz_bezel>
${toTimeString}-根据${type}-${matching ? `<b style="color: ${highlightInformationColor$1}">【${matching}】</b>` : ""}-屏蔽用户【${name}】uid=
<a href="https://space.bilibili.com/${uid}"
style="color: ${highlightInformationColor$1}"
target="_blank">【${uid}】</a>
评论【${content}】
</b>`);
});
eventEmitter.on('正则匹配时异常', (errorData) => {
const {msg, e} = errorData;
this.outputInfoArr.push(msg);
console.error(msg);
throw new Error(e)
});
}
};
const look_content_dialog_vue = {
template: `
<div>
<el-dialog
:fullscreen="true"
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<el-input autosize
type="textarea"
v-model="content"></el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
</div>`,
data() {
return {
dialogVisible: false,
content: ''
}
},
methods: {
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {
});
}
},
created() {
eventEmitter.on('展示内容对话框', (newContent) => {
this.content = newContent;
this.$message('已更新内容');
this.dialogVisible = true;
});
}
};
class ValueCache {
#mapCache = new Map();
set(key, value) {
this.#mapCache.set(key, value);
return value;
}
get(key, defaultValue = null) {
const newVar = this.#mapCache.get(key);
if (newVar) {
return newVar;
}
return defaultValue;
}
getAll() {
return this.#mapCache;
}
}
const valueCache = new ValueCache();
var video_zone = {
"动画": [
"MAD·AMV",
"MMD·3D",
"短片·手书",
"配音",
"手办·模玩",
"特摄",
"动漫杂谈"
],
"番剧": [
"资讯",
"官方延伸",
"完结动画"
],
"国创": [
"国产动画",
"国产原创相关",
"布袋戏",
"资讯"
],
"音乐": [
"原创音乐",
"翻唱",
"VOCALOID·UTAU",
"演奏",
"MV",
"音乐现场",
"音乐综合",
"乐评盘点",
"音乐教学"
],
"舞蹈": [
"宅舞",
"舞蹈综合",
"舞蹈教程",
"街舞",
"明星舞蹈",
"国风舞蹈"
],
"游戏": [
"单机游戏",
"电子竞技",
"手机游戏",
"网络游戏",
"桌游棋牌",
"GMV",
"音游"
],
"知识": [
"科学科普",
"社科·法律·心理(原社科人文、原趣味科普人文)",
"人文历史",
"财经商业",
"校园学习",
"职业职场",
"设计·创意",
"野生技术协会",
"演讲·公开课(已下线)",
"星海(已下线)"
],
"科技": [
"数码(原手机平板)",
"软件应用",
"计算机技术",
"科工机械 (原工业·工程·机械)",
"极客DIY",
"电脑装机(已下线)",
"摄影摄像(已下线)"
],
"运动": [
"篮球",
"足球",
"健身",
"竞技体育",
"运动文化"
],
"汽车": [
"汽车知识科普",
"赛车",
"改装玩车",
"新能源车",
"房车",
"摩托车",
"购车攻略",
"汽车生活",
"汽车文化(已下线)",
"汽车极客(已下线)"
],
"生活": [
"搞笑",
"出行",
"三农",
"家居房产",
"手工",
"绘画",
"日常",
"亲子",
"美食圈(重定向)",
"动物圈(重定向)",
"运动(重定向)",
"汽车(重定向)"
],
"美食": [
"美食制作(原[生活]->[美食圈])",
"美食侦探",
"美食测评",
"田园美食"
],
"动物圈": [
"喵星人",
"汪星人",
"动物二创",
"野生动物",
"小宠异宠"
],
"鬼畜": [
"鬼畜调教",
"音MAD",
"人力VOCALOID",
"鬼畜剧场"
],
"时尚": [
"美妆护肤",
"仿妆cos",
"穿搭",
"时尚潮流",
"健身(重定向)"
],
"资讯": [
"热点",
"环球",
"社会"
],
"广告": [],
"娱乐": [
"综艺",
"娱乐杂谈",
"粉丝创作",
"明星综合"
],
"影视": [
"影视杂谈",
"影视剪辑",
"小剧场",
"预告·资讯"
],
"纪录片": [
"人文·历史",
"科学·探索·自然",
"军事"
],
"电影": [
"华语电影",
"欧美电影",
"日本电影"
],
"电视剧": [
"国产剧"
]
};
const findKey = (itemKey) => {
for (let key in video_zone) {
const arr = video_zone[key];
if (arr.some((i) => i === itemKey)) return key;
}
return null;
};
var video_zoneData = {findKey};
const fetchGetVideoInfo = async (bvId) => {
const response = await fetch(`https://api.bilibili.com/x/web-interface/view/detail?bvid=${bvId}`);
const {code, data, message} = await response.json();
const defData = {state: false, msg: '默认失败信息'};
if (code !== 0) {
defData.msg = message;
return defData
}
defData.state = true;
defData.msg = '获取成功';
const {
View: {
staff,
tname,
tname_v2,
desc,
pubdate,
ctime,
copyright,
is_upower_exclusive,
duration,
stat: {
view,
danmaku,
reply,
favorite,
coin,
share
},
}, Card: {
follower,
like_num,
archive_count,
article_count, card: {
mid: uid,
name,
sex, level_info: {
current_level
},
pendant,
nameplate,
Official,
official_verify,
vip,
}
}, Tags,
participle
} = data;
const videoInfo = {
staff,
tname,
tname_v2,
desc,
pubdate,
ctime,
copyright,
is_upower_exclusive,
duration,
view,
danmaku,
reply,
favorite,
coin,
share,
participle,
};
const userInfo = {
follower,
like_num,
archive_count,
article_count,
Official,
official_verify,
vip,
uid,
name,
sex,
current_level,
pendant,
nameplate
};
const tags = [];
for (let tag of Tags) {
tags.push(tag['tag_name']);
}
tags.unshift(tname, tname_v2);
const findKey = video_zoneData.findKey(tname);
if (findKey) {
tags.unshift(findKey);
}
defData.data = {videoInfo, userInfo, tags};
return defData
};
var bFetch = {
fetchGetVideoInfo
};
const isDisableNetRequestsBvVideoInfo = () => {
return gmUtil.getData('isDisableNetRequestsBvVideoInfo', false)
};
const setDisableNetRequestsBvVideoInfo = (b) => {
gmUtil.setData('isDisableNetRequestsBvVideoInfo', b);
};
const bAfterLoadingThePageOpenMainPanel = () => {
return gmUtil.getData('bAfterLoadingThePageOpenMainPanel', false)
};
const setBAfterLoadingThePageOpenMainPanel = (b) => {
gmUtil.setData('bAfterLoadingThePageOpenMainPanel', b === true);
};
const debugger_management_vue = {
template: `
<div>
<ol>
<li>仅供测试</li>
</ol>
<el-card shadow="never">
<template #header><span>测试</span></template>
<el-button @click="demoBut">测试网络请求</el-button>
<el-button @click="demo1but">测试对话框</el-button>
<el-button @click="printValueCacheBut">打印valueCache值</el-button>
<el-button @click="printEventBut">打印事件中心值</el-button>
<el-divider/>
<el-switch v-model="isDisableNetRequestsBvVideoInfo" active-text="禁用根据bv号网络请求获取视频信息"/>
<el-switch v-model="bAfterLoadingThePageOpenMainPanel" active-text="加载完页面打开主面板"/>
</el-card>
</div>`,
data() {
return {
isDisableNetRequestsBvVideoInfo: isDisableNetRequestsBvVideoInfo(),
bAfterLoadingThePageOpenMainPanel: bAfterLoadingThePageOpenMainPanel()
}
},
methods: {
printValueCacheBut() {
console.log(valueCache.getAll());
},
demoBut() {
bFetch.fetchGetVideoInfo('BV152cWeXEhW').then(data => {
console.log(data);
debugger
});
},
demo1but() {
this.$alert('这是一段内容', '标题名称', {
confirmButtonText: '确定',
callback: action => {
this.$message({
type: 'info',
message: `action: ${action}`
});
}
});
},
printEventBut() {
console.log(eventEmitter.getEvents());
}
},
watch: {
isDisableNetRequestsBvVideoInfo(b) {
setDisableNetRequestsBvVideoInfo(b);
},
bAfterLoadingThePageOpenMainPanel(b) {
setBAfterLoadingThePageOpenMainPanel(b);
}
}
};
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;
};
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);
}
});
}
const findElement = async (selector, config = {}) => {
try {
const defConfig = {
doc: document,
interval: 1000,
timeout: -1,
};
config = {...defConfig, ...config};
const el = await findElementUntilFound(selector, config);
if (config.timeout === -1) {
return el
}
return {state: true, data: el}
} catch (e) {
return {state: false, data: e}
}
};
const findElements = async (selector, config = {}) => {
const defConfig = {doc: document, interval: 1000, timeout: -1};
config = {...defConfig, ...config};
try {
const elList = await findElementsUntilFound(selector, config);
if (config.timeout === -1) {
return elList
}
return {state: true, data: elList}
} catch (e) {
return {state: false, data: e}
}
};
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(Array.from(elements));
clearInterval(i1);
}
}, config.interval);
if (config.timeout > 0) {
setTimeout(() => {
clearInterval(i1);
reject(null); // 超时则返回 null
}, config.timeout);
}
});
}
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,
findElement,
findElements,
findElementUntilFound,
findElementsUntilFound,
findElementsAndBindEvents
};
const setTopInputPlaceholder = async () => {
if (localMKData.isCompatible_BEWLY_BEWLY()) {
return
}
const placeholder = valueCache.get('topInputPlaceholder');
if (placeholder === null) {
return
}
const targetInput = await elUtil.findElement('.nav-search-input');
targetInput.placeholder = placeholder;
eventEmitter.send('el-notification', {
title: "tip",
message: '已恢复顶部搜索框提示内容',
position: 'bottom-right',
});
};
const processTopInputContent = async () => {
if (localMKData.isCompatible_BEWLY_BEWLY()) {
return
}
if (!gmUtil.getData('isClearTopInputTipContent', false)) {
return;
}
const targetInput = await elUtil.findElement('.nav-search-input');
if (targetInput.placeholder === '') {
await defUtil.wait(1500);
await processTopInputContent();
return
}
valueCache.set('topInputPlaceholder', targetInput.placeholder);
targetInput.placeholder = '';
eventEmitter.send('el-msg', '清空了搜索框提示内容');
};
eventEmitter.on('执行清空顶部搜索框提示内容', () => {
processTopInputContent();
});
var topInput = {processTopInputContent, setTopInputPlaceholder};
const page_processing_vue = {
template: `
<div>
<el-card>
<template #header>
<span>搜索页</span>
</template>
<el-switch v-model="isRemoveSearchBottomContent"
active-text="屏蔽底部额外内容"/>
</el-card>
<el-card>
<template #header>
<span>播放页</span>
</template>
<el-switch v-model="isDelPlayerPageAd" active-text="屏蔽页面元素广告"/>
<el-switch v-model="isDelPlayerPageRightGameAd" active-text="屏蔽右侧游戏推荐"/>
<el-tooltip content="移除整个推荐列表,状态刷新生效">
<el-switch v-model="isDelPlayerPageRightVideoList" active-text="移除右侧推荐列表"/>
</el-tooltip>
<el-tooltip content="状态刷新生效">
<el-switch v-model="isDelBottomComment" active-text="移除评论区"/>
</el-tooltip>
</el-card>
<el-card>
<template #header>
<span>顶部搜索框</span>
</template>
<el-switch v-model="isClearTopInputTipContent" active-text="清空内容"/>
</el-card>
</div>`,
data() {
return {
isRemoveSearchBottomContent: gmUtil.getData('isRemoveSearchBottomContent', false),
isDelPlayerPageAd: gmUtil.getData('isDelPlayerPageAd', false),
isDelPlayerPageRightGameAd: gmUtil.getData('isDelPlayerPageRightGameAd', false),
isDelPlayerPageRightVideoList: localMKData.isDelPlayerPageRightVideoList(),
isDelBottomComment: gmUtil.getData('isDelBottomComment', false),
isClearTopInputTipContent: gmUtil.getData('isClearTopInputTipContent', false),
}
},
methods: {},
watch: {
isRemoveSearchBottomContent(b) {
gmUtil.setData('isRemoveSearchBottomContent', b);
},
isDelPlayerPageAd(b) {
gmUtil.setData('isDelPlayerPageAd', b);
},
isDelPlayerPageRightGameAd(b) {
gmUtil.setData('isDelPlayerPageRightGameAd', b);
},
isDelPlayerPageRightVideoList(b) {
gmUtil.setData('isDelPlayerPageRightVideoList', b);
},
isDelBottomComment(b) {
gmUtil.setData('isDelBottomComment', b);
},
isClearTopInputTipContent(b) {
gmUtil.setData('isClearTopInputTipContent', b);
if (b) {
eventEmitter.send('执行清空顶部搜索框提示内容');
return
}
topInput.setTopInputPlaceholder();
}
}
};
const about_and_feedback_vue = {
template: `
<div>
<el-card>
<template #header>
<span>作者b站</span>
</template>
<el-link target="_blank" href="https://space.bilibili.com/473239155" type="primary">b站传送门</el-link>
</el-card>
<el-card>
<template #header>
<span>交流群</span>
</template>
<el-link
:href='group_url' target="_blank" type="primary">====》Q群传送门《====
</el-link>
<el-tooltip content="点击查看群二维码">
<el-tag @click="lookImgBut">876295632</el-tag>
</el-tooltip>
</el-card>
<el-card>
<template #header>
<span>发布、更新、反馈地址</span>
</template>
<el-row>
<el-col :span="12">
<el-card>
<span>greasyfork</span>
<el-link target="_blank" type="primary" href="https://greasyfork.org/scripts/461382/">===》传送门《===
</el-link>
</el-card>
</el-col>
<el-col :span="12">
<el-card>
<span>脚本猫</span>
<el-link target="_blank" type="primary" :href="scriptCat_js_url">
===》传送门《===
</el-link>
</el-card>
</el-col>
</el-row>
</el-card>
<el-card>
<template #header>
<span>开源地址</span>
</template>
<el-row>
<el-col :span="12">
<el-card>
<span>gitee</span>
<el-link target="_blank" type="primary" href="https://gitee.com/hangexi/BiBiBSPUserVideoMonkeyScript"
>https://gitee.com/hangexi/BiBiBSPUserVideoMonkeyScript
</el-link>
</el-card>
</el-col>
<el-col :span="12">
<el-card>
<span>github</span>
<el-link target="_blank" type="primary" href="https://github.com/hgztask/BiBiBSPUserVideoMonkeyScript"
>https://github.com/hgztask/BiBiBSPUserVideoMonkeyScript
</el-link>
</el-card>
</el-col>
</el-row>
</el-card>
</div>`,
data() {
return {
group_url: globalValue.group_url,
scriptCat_js_url: globalValue.scriptCat_js_url
}
},
methods: {
lookImgBut() {
eventEmitter.send('显示图片对话框', {image: "https://www.mikuchase.ltd/img/qq_group_876295632.webp"});
}
},
created() {
}
};
const show_img_dialog_vue = {
template: `
<div>
<el-dialog
center
:title="title"
:modal="isModal"
:visible.sync="show">
<div class="el-vertical-center">
<el-image
:src="imgSrc" :preview-src-list="imgList"/>
</div>
</el-dialog>
</div>`,
data() {
return {
show: false,
title: "图片查看",
imgList: [],
imgSrc: '',
isModal: true
}
},
created() {
eventEmitter.on('显示图片对话框', ({image, title, images, isModal}) => {
this.imgSrc = image;
if (title) {
this.title = title;
}
if (images) {
this.imgList = images;
} else {
this.imgList = [image];
}
if (isModal) {
this.isModal = isModal;
}
this.show = true;
});
}
};
const sheet_dialog_vue = {
props: {
show: {
type: Boolean,
default: false
},
list: {
type: Array,
default: () => []
},
closeOnClickModal: {
type: Boolean,
default: true
},
title: {
type: String,
default: '选项'
},
clickItemClose: {
type: Boolean,
default: false
}
},
template: `
<div>
<el-dialog :visible="show" :title="title"
width="30%" center
:close-on-click-modal="closeOnClickModal"
@close="$emit('close')">
<div>
<el-row>
<el-col v-for="item in list" :key="item.label">
<el-button style="width: 100%" @click="handleClick(item)">项目{{ item.label }}</el-button>
</el-col>
</el-row>
</div>
</el-dialog>
</div>`,
data() {
return {
dialogShow: true,
list: []
}
},
methods: {
handleClick(item) {
if (this.clickItemClose) {
return;
}
this.$emit('options-click', item);
}
}
};
const mainLayoutEl = document.createElement('div');
if (document.head.querySelector('#element-ui-css') === null) {
const linkElement = document.createElement('link');
linkElement.rel = 'stylesheet';
linkElement.href = 'https://unpkg.com/element-ui/lib/theme-chalk/index.css';
linkElement.id = 'element-ui-css';
document.head.appendChild(linkElement);
console.log('挂载element-ui样式成功');
}
window.addEventListener('load', () => {
document.body.appendChild(mainLayoutEl);
new Vue({
el: mainLayoutEl,
template: `
<div>
<el-drawer style="position: fixed"
:visible.sync="drawer"
direction="ltr"
size="100%"
:modal="false"
:with-header="false">
<el-tabs type="border-card" v-model="tabsActiveName"
@tab-click="tabClick">
<el-tab-pane label="面板设置" name="面板设置" lazy>
<panel_settings_vue/>
</el-tab-pane>
<el-tab-pane label="规则管理" name="规则管理" lazy>
<rule_management_vue/>
</el-tab-pane>
<el-tab-pane label="兼容设置" name="兼容设置" lazy>
<compatible_setting_vue/>
</el-tab-pane>
<el-tab-pane label="缓存管理" name="缓存管理" lazy>
<cache_management_vue/>
</el-tab-pane>
<el-tab-pane label="页面处理" name="页面处理" lazy>
<page_processing_vue/>
</el-tab-pane>
<el-tab-pane label="输出信息" name="输出信息" lazy>
<output_information_vue/>
</el-tab-pane>
<el-tab-pane label="支持打赏" name="支持打赏" lazy>
<donate_layout_vue/>
</el-tab-pane>
<el-tab-pane label="关于和问题反馈" name="关于和问题反馈" lazy>
<about_and_feedback_vue/>
</el-tab-pane>
<el-tab-pane label="调试测试" name="调试测试" lazy v-if="debug_panel_show">
<div v-show="debug_panel_show">
<debugger_management_vue/>
</div>
</el-tab-pane>
</el-tabs>
</el-drawer>
<look_content_dialog_vue/>
<show_img_dialog_vue/>
<sheet_dialog_vue :show="sheet_dialog.show" :list="sheet_dialog.list" :title="sheet_dialog.title"
@close="handleClose"
:close-on-click-modal="sheet_dialog.closeOnClickModal" @options-click="handleOptionsClick"/>
</div>`,
components: {
output_information_vue: outputInformationVue,
donate_layout_vue: donateLayoutVue,
rule_management_vue: ruleManagementVue,
cache_management_vue,
panel_settings_vue,
compatible_setting_vue,
look_content_dialog_vue,
debugger_management_vue,
page_processing_vue,
about_and_feedback_vue,
show_img_dialog_vue,
sheet_dialog_vue
},
data() {
return {
drawer: false,
tabsActiveName: '规则管理',
debug_panel_show: gmUtil.getData('open-dev', false),
sheet_dialog: {
show: false,
list: [],
title: "",
optionsClick: null,
closeOnClickModal: true
}
}
},
methods: {
tabClick(tab) {
gmUtil.setData('mainTabsActiveName', tab.name);
},
handleClose() {
this.sheet_dialog.show = false;
},
handleOptionsClick(item) {
let tempBool;
const temp = this.sheet_dialog.optionsClick(item);
if (temp === undefined) {
tempBool = false;
} else {
tempBool = temp;
}
this.sheet_dialog.show = tempBool === true;
}
},
created() {
eventEmitter.on('主面板开关', () => {
const tempBool = this.drawer;
this.drawer = !tempBool;
});
eventEmitter.on('el-notification', (...options) => {
this.$notify(...options);
});
eventEmitter.on('el-msg', (...options) => {
this.$message(...options);
});
eventEmitter.on('el-alert', (...options) => {
this.$alert(...options);
});
eventEmitter.handler('el-confirm', (...options) => {
return this.$confirm(...options);
});
this.tabsActiveName = gmUtil.getData('mainTabsActiveName', '规则管理');
eventEmitter.on('debugger-dev-show', (bool) => {
debugger
this.debug_panel_show = bool;
if (bool) {
this.$alert('已开启测试调试面板', 'tip');
} else {
this.$alert('已关闭测试调试面板', 'tip');
}
});
eventEmitter.on('sheet-dialog', ({list, optionsClick, title = '选项', closeOnClickModal = false}) => {
this.sheet_dialog.show = true;
this.sheet_dialog.list = list;
this.sheet_dialog.title = title;
this.sheet_dialog.optionsClick = optionsClick;
this.sheet_dialog.closeOnClickModal = closeOnClickModal;
});
eventEmitter.handler('el-prompt', (...options) => {
return this.$prompt(...options)
});
if (bAfterLoadingThePageOpenMainPanel()) {
this.drawer = true;
}
}
});
});
var defCss = `
.el-vertical-center {
display: flex;
justify-content: center;
}
.el-horizontal-center {
display: flex;
align-items: center;
}
.el-horizontal-right {
display: flex;
justify-content: flex-end;
}
.el-horizontal-left {
display: flex;
justify-content: flex-start;
}
`;
gmUtil.addStyle(`
[gz_bezel]{
border:1px solid ${localMKData.getBorderColor()}
}
`);
gmUtil.addStyle(defCss);
const exactMatch = (ruleList, value) => {
if (ruleList === null || ruleList === undefined) return false;
if (!Array.isArray(ruleList)) return false
return ruleList.some(item => item === value);
};
const bFuzzyAndRegularMatchingWordsToLowercase = localMKData.bFuzzyAndRegularMatchingWordsToLowercase();
const regexMatch = (ruleList, value) => {
if (ruleList === null || ruleList === undefined) return null;
if (!Array.isArray(ruleList)) return null
if (bFuzzyAndRegularMatchingWordsToLowercase) {
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.send('正则匹配时异常', {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 outputInformationFontColor = localMKData.getOutputInformationFontColor();
const highlightInformationColor = localMKData.getHighlightInformationColor();
const getLiveRoomCommentInfoHtml = (type, matching, commentData) => {
const toTimeString = defUtil.toTimeString();
const {name, uid, content} = commentData;
return `<b style="color: ${outputInformationFontColor}; " gz_bezel>
${toTimeString}-根据${type}-${matching ? `<b style="color: ${highlightInformationColor}">【${matching}】</b>` : ""}-屏蔽用户【${name}】uid=
<a href="https://space.bilibili.com/${uid}"
style="color: ${highlightInformationColor}"
target="_blank">【${uid}】</a>
直播评论【${content}】
</b>`
};
const getDynamicContentInfoHtml = (type, matching, dynamicData) => {
const toTimeString = defUtil.toTimeString();
const {name, uid, content} = dynamicData;
return `<b style="color: ${outputInformationFontColor}; " gz_bezel>
${toTimeString}-根据${type}-${matching ? `<b style="color: ${highlightInformationColor}">【${matching}】</b>` : ""}-屏蔽用户【${name}】uid=
<a href="https://space.bilibili.com/${uid}"
style="color: ${highlightInformationColor}"
target="_blank">【${uid}】</a>
动态【${content}】
</b>`
};
const getLiveRoomInfoHtml = (type, matching, liveRoomData) => {
const toTimeString = defUtil.toTimeString();
const {name = null, uid = -1, title, liveUrl} = liveRoomData;
return `<b style="color: ${outputInformationFontColor};" gz_bezel>
${toTimeString}-根据${type}${matching ? `<b style="color: ${highlightInformationColor}">【${matching}】</b>` : ""}-屏蔽用户【${name === null ? '' : name}】${uid === -1 ? "" : `uid=
<a href="https://space.bilibili.com/${uid}"
style="color: ${highlightInformationColor}"
target="_blank">【${uid}】</a>`}
直播间标题【<a href="${liveUrl}" target="_blank" style="color: ${highlightInformationColor}">${title}</a>】
</b>`
};
var output_informationTab = {
getLiveRoomCommentInfoHtml,
getDynamicContentInfoHtml,
getLiveRoomInfoHtml
};
class VideoInfoCache {
#caches = [];
getCaches() {
return this.#caches;
}
getCount() {
return this.#caches.length;
}
addData(data) {
this.#caches.push(data);
}
is(bv) {
return this.#caches.some(item => item.bv === bv);
}
find(bv) {
const find = this.#caches.find(item => item.bv === bv);
if (find) {
return find
}
return null
}
async update() {
this.#caches = await bvDexie.getVideoInfo();
return this.getCaches();
}
}
const videoInfoCache = new VideoInfoCache();
class ElEventEmitter {
#elEvents = new Map()
addEvent(el, eventName, callback, repeated = false) {
const elEvents = this.#elEvents;
if (!elEvents.has(el)) {
elEvents.set(el, {events: [], attrs: []});
}
const {events, attrs} = elEvents.get(el);
if (!repeated) {
if (attrs.includes(eventName)) {
return
}
}
attrs.push(eventName);
events.push({eventName, callback});
el.setAttribute(`gz-event`, JSON.stringify(attrs));
el.addEventListener(eventName, callback);
}
hasEventName(el, eventName) {
const elEvents = this.#elEvents;
if (elEvents.has(el)) {
return true
}
const {attrs} = elEvents.get(el);
return attrs.includes(eventName)
}
}
const elEventEmitter = new ElEventEmitter();
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";
elEventEmitter.addEvent(explicitSubjectEl, "mouseout", () => buttonEL.style.display = "none");
elEventEmitter.addEvent(explicitSubjectEl, "mouseover", () => buttonEL.style.display = "");
}
insertionPositionEl.appendChild(buttonEL);
buttonEL.addEventListener("click", (event) => {
event.stopImmediatePropagation(); // 阻止事件冒泡和同一元素上的其他事件处理器
event.preventDefault(); // 阻止默认行为
const {uid, name} = data.data;
eventEmitter.send('sheet-dialog', {
title: "屏蔽选项",
list: [
{
label: `uid精确屏蔽-用户uid=${uid}-name=${name}`,
value: "uid"
}, {
label: `用户名精确屏蔽(不推荐)-用户name=${name}`,
value: 'name'
}
],
optionsClick: (item) => {
const {value} = item;
if (value === 'uid') {
if (uid === -1) {
eventEmitter.send('el-msg', "该页面数据不存在uid字段");
return;
}
const {status, res} = ruleUtil.addRulePreciseUid(uid, false);
if (status) {
data.maskingFunc();
}
eventEmitter.send('el-alert', res);
return;
}
if (!name) {
eventEmitter.send('el-alert', "该页面数据不存在name字段" + name);
return;
}
eventEmitter.invoke('el-confirm', '不推荐用户使用精确用户名来屏蔽,确定继续吗?').then(() => {
ruleUtil.addRulePreciseName(name);
});
}
});
});
};
eventEmitter.on('视频添加屏蔽按钮', (data) => {
addBlockButton$1(data, "gz_shielding_button", ["right"]);
});
eventEmitter.on('添加热门视频屏蔽按钮', (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 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 (name) {
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 shieldingOtherVideoParameter = async (videoData) => {
const {el, bv = '-1'} = videoData;
if (bv === '-1') return
if (videoInfoCache.getCount() === 0) {
await videoInfoCache.update();
}
const find = videoInfoCache.find(bv);
let result;
if (find === null) {
const {state, data, msg} = await bFetch.fetchGetVideoInfo(bv);
if (!state) {
console.warn('获取视频信息失败:' + msg);
return
}
result = data;
if (await bvDexie.addVideoData(bv, result)) {
await videoInfoCache.update();
console.log('mk-db-添加视频信息到数据库成功', result, videoData);
}
} else {
result = find;
}
const {tags = [], userInfo, videoInfo} = result;
let returnValue;
if (tags.length !== 0) {
returnValue = blockBasedVideoTag(tags);
if (returnValue.state) {
return returnValue
}
}
const currentLevel = userInfo?.current_level || -1;
returnValue = shieldingByLevel(currentLevel);
if (returnValue.state) {
return returnValue
}
};
const blockBasedVideoTag = (tags) => {
const preciseVideoTagArr = ruleKeyListData$1.getPreciseVideoTagArr();
const videoTagArr = ruleKeyListData$1.getVideoTagArr();
if (preciseVideoTagArr.length <= 0 && videoTagArr.length <= 0) {
return {state: false}
}
for (let tag of tags) {
if (ruleMatchingUtil.exactMatch(preciseVideoTagArr, tag)) {
return {state: true, type: "精确视频tag", matching: tag}
}
let fuzzyMatch = ruleMatchingUtil.fuzzyMatch(videoTagArr, tag);
if (fuzzyMatch) {
return {state: true, type: "模糊视频tag", matching: fuzzyMatch}
}
fuzzyMatch = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getVideoTagCanonicalArr(), tag);
if (fuzzyMatch) {
return {state: true, type: "正则视频tag", matching: fuzzyMatch}
}
}
return {state: false}
};
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";
}
eventEmitter.send('屏蔽视频信息', type, matching, videoData);
return true;
}
if (isDisableNetRequestsBvVideoInfo()) {
return state
}
shieldingOtherVideoParameter(videoData).then(res => {
if (!res) {
return
}
const {type, matching} = res;
if (method === "remove") {
el.remove();
} else {
el.style.display = "none";
}
eventEmitter.send('屏蔽视频信息', type, matching, 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) {
const infoHtml = output_informationTab.getDynamicContentInfoHtml(type, matching, dynamicData);
eventEmitter.send('打印信息', infoHtml);
}
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) {
return shieldingByLevel(level);
}
return {state: false};
};
const shieldingByLevel = (level) => {
const def = {state: false};
if (!level) {
return def
}
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 def
};
const shieldingCommentDecorated = (commentsData) => {
const {state, type, matching} = shieldingComment(commentsData);
if (state) {
commentsData.el?.remove();
eventEmitter.send('屏蔽评论信息', 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();
}
if (type) {
const infoHtml = output_informationTab.getLiveRoomCommentInfoHtml(type, matching, liveRoomContent);
eventEmitter.send('打印信息', infoHtml);
}
return state;
};
const shieldingComments = (commentsDataList) => {
for (let commentsData of commentsDataList) {
if (shieldingCommentDecorated(commentsData)) continue;
eventEmitter.send('评论添加屏蔽按钮', commentsData);
const {replies = []} = commentsData;
if (replies.length === 0) continue;
for (let reply of replies) {
if (shieldingCommentDecorated(reply)) continue;
eventEmitter.send('评论添加屏蔽按钮', 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();
const infoHtml = output_informationTab.getLiveRoomInfoHtml(type, matching, liveRoomData);
eventEmitter.send('打印信息', infoHtml);
}
return state;
};
const intervalExecutionStartShieldingVideoInert = (func, name = '') => {
let i1 = -1;
const start = () => {
if (i1 !== -1) {
return
}
console.log('开始执行屏蔽' + name);
i1 = setInterval(() => {
func();
console.log(`执行屏蔽${name}列表-定时器正在执行`);
}, 800);
};
const stop = () => {
if (i1 === -1) {
return
}
clearInterval(i1);
console.log(`已停止执行屏蔽${name}列表`);
i1 = -1;
};
return {start, stop}
};
var shielding = {
shieldingVideoDecorated,
shieldingDynamicDecorated,
shieldingCommentDecorated,
shieldingLiveRoomDecorated,
shieldingComments,
shieldingLiveRoomContentDecorated,
addLiveContentBlockButton,
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 = "已删除下载提示";
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 = "遍历换一换视频列表中检测到异常内容,已将该元素移除";
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();
console.warn("获取视频信息失败");
}
}
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 = "遍历换一换视频列表下面列表时检测到异常内容,已将该元素移除";
eventEmitter.send('打印信息', 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();
console.log("遍历视频列表中检测到异常内容,已将该元素移除;");
}
}
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;
}
eventEmitter.send('视频添加屏蔽按钮', {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;
}
eventEmitter.send('视频添加屏蔽按钮', {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;
}
eventEmitter.send('视频添加屏蔽按钮', {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.findElements('.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.findElement('.live-condition');
if (elEventEmitter.hasEventName(el, 'click')) return
elEventEmitter.addEvent(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.findElement('.vui_pagenation--btns');
if (elEventEmitter.hasEventName(el, 'click')) return
elEventEmitter.addEvent(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.findElement('.room-order');
if (elEventEmitter.hasEventName(el, 'click')) return
elEventEmitter.addEvent(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.findElement('.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.findElement('.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.findElements(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();
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;
}
eventEmitter.send('视频添加屏蔽按钮', {data: videoData, maskingFunc: startShieldingCSVideoList});
}
};
const startShieldingOtherVideoList = async () => {
const list = await getOtherVideoList();
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue;
}
eventEmitter.send('视频添加屏蔽按钮', {data: videoData, maskingFunc: startShieldingOtherVideoList});
}
};
const getTwTabActiveItem = async () => {
const twoTabActiveItem = await elUtil.findElement('.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.findElement('.vui_tabs--nav-item.vui_tabs--nav-item-active', {interval: 200});
const topTabActiveItemLabel = topTabActiveItem.textContent.trim();
console.log(topTabActiveItemLabel);
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 res;
try {
res = await elUtil.findElement('.user-list.search-all-list', {interval: 50, timeout: 4000});
} catch (e) {
return
}
let el;
if (!res.state) {
return
}
el = res.data;
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();
eventEmitter.send('打印信息', `根据精确uid匹配到用户${name}-【${uid}】`);
return
}
let fuzzyMatch = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getNameArr(), name);
if (fuzzyMatch) {
el.remove();
eventEmitter.send('打印信息', `根据模糊用户名【${fuzzyMatch}】匹配到用户${name}-【${uid}】`);
return
}
fuzzyMatch = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getNameCanonical(), name);
if (fuzzyMatch) {
el.remove();
eventEmitter.send('打印信息', `根据正则用户名【${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);
}
};
const delFooterContent = () => {
if (!gmUtil.getData('isRemoveSearchBottomContent', false)) {
return
}
elUtil.findElement('#biliMainFooter').then(el => {
el.remove();
eventEmitter.send('打印信息', '已删除底部内容');
});
};
var searchModel = {
isSearch,
searchTopTabsIWrapperInstallListener,
startShieldingVideoList: startShieldingVideoList$6,
currentlyActivatedOptions,
delFooterContent
};
const isVideoPlayPage = (url = window.location.href) => {
return url.includes("www.bilibili.com/video");
};
const selectUserBlocking = async () => {
const {state} = await elUtil.findElement('.header.can-pointer', {timeout: 1800});
if (state) {
const elList = document.querySelectorAll('.container>.membersinfo-upcard-wrap>.membersinfo-upcard');
const list = [];
for (const el of elList) {
const userUrl = el.querySelector('.avatar').href;
const uid = elUtil.getUrlUID(userUrl);
const name = el.querySelector('.staff-name').textContent.trim();
list.push({
label: `用户-name=${name}-uid=${uid}`,
uid
});
}
eventEmitter.send('sheet-dialog', {
title: '选择要屏蔽的用户(uid精确)',
list,
optionsClick: (item) => {
ruleUtil.addRulePreciseUid(item.uid);
return true
}
});
} else {
const el = document.querySelector('.up-info-container');
const nameEl = el.querySelector('.up-info--right a.up-name');
const name = nameEl.textContent.trim();
const userUrl = nameEl.href;
const uid = elUtil.getUrlUID(userUrl);
console.log('点击了屏蔽按钮', name, userUrl, uid);
eventEmitter.invoke('el-confirm', `用户uid=${uid}-name=${name}`, 'uid精确屏蔽方式').then(() => {
if (uid === -1) {
eventEmitter.send('el-msg', "该页面数据不存在uid字段");
return;
}
ruleUtil.addRulePreciseUid(uid);
});
}
};
const getGetTheVideoListOnTheRight$1 = async () => {
await elUtil.findElementUntilFound(".video-page-card-small .b-img img");
delAd();
delGameAd();
const elList = await elUtil.findElements(".rec-list>.video-page-card-small", {interval: 1000});
const nextPlayEl = document.querySelector('.next-play>.video-page-card-small');
if (nextPlayEl) {
elList.push(nextPlayEl);
}
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>(.*)<svg/s)?.[1].trim();
nPlayCount = sFormatUtil.toPlayCountOrBulletChat(nPlayCount);
let nBulletChat = playInfo.match(/class="dm".+<\/svg>(.+)$/s)?.[1].trim();
nBulletChat = sFormatUtil.toPlayCountOrBulletChat(nBulletChat);
let nDuration = el.querySelector('.duration')?.textContent.trim();
nDuration = sFormatUtil.timeStringToSeconds(nDuration);
list.push({
title,
userUrl,
name,
uid,
bv,
nPlayCount,
nBulletChat,
nDuration,
el,
videoUrl,
insertionPositionEl: el.querySelector(".playinfo"),
explicitSubjectEl: elInfo
});
} catch (e) {
console.error("获取右侧视频列表失败:", e);
}
}
return list;
};
const startShieldingVideoList$5 = () => {
if (localMKData.isDelPlayerPageRightVideoList()) {
return
}
getGetTheVideoListOnTheRight$1().then((videoList) => {
for (let videoData of videoList) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue;
}
eventEmitter.send('视频添加屏蔽按钮', {data: videoData, maskingFunc: startShieldingVideoList$5});
}
});
};
const findTheExpandButtonForTheListOnTheRightAndBindTheEvent$2 = () => {
setTimeout(() => {
elUtil.findElementUntilFound(".rec-footer", {interval: 2000}).then((el) => {
console.log("找到右侧视频列表的展开按钮", el);
el.addEventListener("click", () => {
startShieldingVideoList$5();
});
});
}, 3000);
};
const getPlayerVideoList = async () => {
const elList = await elUtil.findElements('.bpx-player-ending-related>.bpx-player-ending-related-item');
const data = {list: [], cancelEl: null};
for (const el of elList) {
const title = el.querySelector('.bpx-player-ending-related-item-title')?.textContent.trim();
const cancelEl = el.querySelector('.bpx-player-ending-related-item-cancel');
if (cancelEl) {
data.cancelEl = cancelEl;
}
data.list.push({
title,
el
});
}
return data
};
const setVideoPlayerEnded = async () => {
const videoEl = await elUtil.findElement('#bilibili-player video');
const funcStart = async () => {
const res = await getPlayerVideoList();
for (let {el, title} of res.list) {
let matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getTitleArr(), title);
if (matching !== null) {
eventEmitter.send('打印信息', `根据-模糊标题-【${matching}】-屏蔽视频:${title}`);
el.remove();
continue
}
matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getTitleCanonicalArr(), title);
if (matching !== null) {
eventEmitter.send('打印信息', `根据-正则标题-【${matching}】-屏蔽视频:${title}`);
el.remove();
}
}
};
videoEl.addEventListener('ended', () => {
console.log('视频播放结束');
funcStart();
});
};
const delAd = () => {
if (!gmUtil.getData('isDelPlayerPageAd', false)) {
return
}
elUtil.findElements('[class|=ad],#slide_ad').then(elList => {
for (const el of elList) {
el.style.display = 'none';
}
eventEmitter.send('打印信息', '隐藏了播放页的页面广告');
});
};
const delRightVideoList = () => {
if (!localMKData.isDelPlayerPageRightVideoList()) {
return
}
elUtil.findElement('.recommend-list-v1').then(el => {
el?.remove();
eventEmitter.send('打印信息', '屏蔽了播放页的右侧推荐列表');
});
};
const delGameAd = () => {
if (!gmUtil.getData('isDelPlayerPageRightGameAd', false)) {
return
}
elUtil.findElement('.video-page-game-card-small', {timeout: 10000}).then(({state, data}) => {
if (!state) {
eventEmitter.send('打印信息', '没有找到播放页的右侧游戏推荐');
return
}
data?.remove();
eventEmitter.send('打印信息', '屏蔽了游戏推荐');
});
};
const delBottomCommentApp = () => {
if (!gmUtil.getData('isDelBottomComment', false)) {
return
}
elUtil.findElement('#commentapp').then(el => {
el?.remove();
eventEmitter.send('打印信息', '移除了页面底部的评论区');
});
};
const delElManagement = () => {
if (localMKData.isDelPlayerPageRightVideoList()) {
delAd();
}
delRightVideoList();
delBottomCommentApp();
};
var videoPlayModel = {
isVideoPlayPage,
startShieldingVideoList: startShieldingVideoList$5,
findTheExpandButtonForTheListOnTheRightAndBindTheEvent: findTheExpandButtonForTheListOnTheRightAndBindTheEvent$2,
selectUserBlocking,
setVideoPlayerEnded,
delElManagement
};
const getPlayCountAndBulletChatAndDuration = (el) => {
const playInfo = el.querySelector('.playinfo').innerHTML.trim();
let nPlayCount = playInfo.match(/<\/svg>(.*)<svg/s)?.[1].trim();
nPlayCount = sFormatUtil.toPlayCountOrBulletChat(nPlayCount);
let nBulletChat = playInfo.match(/class="dm-icon".+<\/svg>(.+)$/s)?.[1].trim();
nBulletChat = sFormatUtil.toPlayCountOrBulletChat(nBulletChat);
let nDuration = el.querySelector('.duration')?.textContent.trim();
nDuration = sFormatUtil.timeStringToSeconds(nDuration);
return {
nPlayCount, nBulletChat, nDuration
}
};
const getRightVideoDataList$1=(elList)=>{
const list = [];
for (let el of elList) {
const title = el.querySelector(".title").textContent.trim();
const userInfoEl = el.querySelector(".upname");
const name = userInfoEl.querySelector(".name").textContent.trim();
const userUrl = userInfoEl.href;
const uid = elUtil.getUrlUID(userUrl);
const videoUrl = el.querySelector(".info>a").href;
const bv = elUtil.getUrlBV(videoUrl);
list.push({
...getPlayCountAndBulletChatAndDuration(el), ...{
title,
name,
userUrl,
videoUrl,
uid,
bv,
el,
insertionPositionEl: el.querySelector(".playinfo"),
explicitSubjectEl: el.querySelector(".info")
}
});
}
return list;
};
var generalFuc = {getRightVideoDataList: getRightVideoDataList$1};
const iscCollectionVideoPlayPage = (url) => {
return url.includes("www.bilibili.com/list/ml")
};
const getGetTheVideoListOnTheRight = async () => {
const elList = await elUtil.findElementsUntilFound(".recommend-list-container>.video-card");
return generalFuc.getRightVideoDataList(elList);
};
const startShieldingVideoList$4 = () => {
getGetTheVideoListOnTheRight().then((videoList) => {
const css = {right: "123px"};
for (let videoData of videoList) {
if (shielding.shieldingVideoDecorated(videoData)) continue;
videoData.css = css;
eventEmitter.send('视频添加屏蔽按钮', {data: videoData, maskingFunc: startShieldingVideoList$4});
}
});
};
const findTheExpandButtonForTheListOnTheRightAndBindTheEvent$1 = () => {
setTimeout(() => {
elUtil.findElementUntilFound(".rec-footer", {interval: 2000}).then((el) => {
el.addEventListener("click", () => {
startShieldingVideoList$4();
});
});
}, 3000);
};
var collectionVideoPlayPageModel = {
iscCollectionVideoPlayPage,
startShieldingVideoList: startShieldingVideoList$4,
findTheExpandButtonForTheListOnTheRightAndBindTheEvent: findTheExpandButtonForTheListOnTheRightAndBindTheEvent$1
};
const addEventListenerUrlChange = (callback) => {
let oldUrl = window.location.href;
setInterval(() => {
const newUrl = window.location.href;
if (oldUrl === newUrl) return;
oldUrl = newUrl;
const title = document.title;
callback(newUrl, oldUrl, title);
}, 1000);
};
const addEventListenerNetwork = (callback) => {
new PerformanceObserver(() => {
const entries = performance.getEntriesByType('resource');
const windowUrl = window.location.href;
const winTitle = document.title;
for (let entry of entries) {
const url = entry.name;
const initiatorType = entry.initiatorType;
if (initiatorType === "img" || initiatorType === "css" || initiatorType === "link" || initiatorType === "beacon") {
continue;
}
callback(url, windowUrl,winTitle, initiatorType);
}
performance.clearResourceTimings();//清除资源时间
}).observe({entryTypes: ['resource']});
};
function watchElementListLengthWithInterval(selector, callback, config={}) {
const defConfig = {};
config = {...defConfig, ...config};
let previousLength = -1;
const timer = setInterval(() => {
if (previousLength === -1) {
previousLength = document.querySelectorAll(selector).length;
return
}
const currentElements = document.querySelectorAll(selector);
const currentLength = currentElements.length;
if (currentLength !== previousLength) {
previousLength = currentLength;
callback({
action: currentLength > previousLength ? 'add' : 'del',
elements: currentElements,
length: currentLength
}
);
}
},
config.interval
);
return stop = () => {
clearInterval(timer);
};
}
var watch = {
addEventListenerUrlChange,
addEventListenerNetwork,
watchElementListLengthWithInterval
};
const isLiveRoom = (url) => {
return url.search('/live.bilibili.com/\\d+') !== -1;
};
const getChatItems = async () => {
const elList = await elUtil.findElementsUntilFound("#chat-items>div");
if (elList.length >= 200) {
for (let i = 0; i < 100; i++) {
elList[i]?.remove();
}
console.log("弹幕列表超过200,已删除前100条");
}
const list = [];
for (let el of elList) {
if (el.className === "chat-item convention-msg border-box") {
continue;
}
if (el.className === "chat-item misc-msg guard-buy") {
continue;
}
const name = el.getAttribute("data-uname");
if (name === null) {
continue;
}
const uid = el.getAttribute("data-uid");
const content = el.getAttribute("data-danmaku");
const timeStamp = el.getAttribute("data-timestamp");
const fansMedalEl = el.querySelector(".fans-medal-content");
const fansMedal = fansMedalEl === null ? null : fansMedalEl.textContent.trim();
list.push({
name,
uid,
content,
timeStamp,
fansMedal,
el,
insertionPositionEl: el,
explicitSubjectEl: el
});
}
return list;
};
const startShieldingLiveChatContents = async () => {
const commentsDataList = await getChatItems();
for (let commentsData of commentsDataList) {
if (shielding.shieldingLiveRoomContentDecorated(commentsData)) {
continue;
}
shielding.addLiveContentBlockButton({data: commentsData, maskingFunc: startShieldingLiveChatContents});
}
};
const addWatchLiveRoomChatItemsListener = () => {
const throttle = defUtil.throttle(startShieldingLiveChatContents, 1000);
watch.watchElementListLengthWithInterval("#chat-items>div", throttle);
};
var liveRoomModel = {
isLiveRoom,
addWatchLiveRoomChatItemsListener
};
const isVideoPlayWatchLaterPage = (url) => {
return url.startsWith("https://www.bilibili.com/list/watchlater")
};
const getRightVideoDataList = async () => {
const elList = await elUtil.findElementsUntilFound(".recommend-video-card.video-card");
return generalFuc.getRightVideoDataList(elList);
};
const startShieldingVideoList$3 = async () => {
const videoList = await getRightVideoDataList();
const css = {right: "123px"};
for (let videoData of videoList) {
videoData.css = css;
if (shielding.shieldingVideoDecorated(videoData)) continue;
eventEmitter.send('视频添加屏蔽按钮', {data: videoData, maskingFunc: startShieldingVideoList$3});
}
};
const startDebounceShieldingVideoList = defUtil.debounce(startShieldingVideoList$3, 1000);
const findTheExpandButtonForTheListOnTheRightAndBindTheEvent = () => {
elUtil.findElementsAndBindEvents(".rec-footer", startDebounceShieldingVideoList);
};
var videoPlayWatchLater = {
isVideoPlayWatchLaterPage,
startDebounceShieldingVideoList,
findTheExpandButtonForTheListOnTheRightAndBindTheEvent
};
const getBewlyEl = async () => {
let el = await elUtil.findElementUntilFound('#bewly', {interval: 500});
return el.shadowRoot;
};
const isBEWLYPage = (url) => {
return url.includes('www.bilibili.com/?page=') ||
url === 'https://www.bilibili.com/'
|| url.startsWith('https://www.bilibili.com/?spm_id_from=')
};
const getVideoList = async () => {
const beEl = await getBewlyEl();
const elList = await elUtil.findElementsUntilFound('.video-card.group', {doc: beEl});
const list = [];
for (let el of elList) {
const parentElement = el.parentElement.parentElement;
const title = el.querySelector('.keep-two-lines>a[title]').textContent.trim();
const userUrlEl = el.querySelector('.channel-name');
const userUrl = userUrlEl.href;
const uid = elUtil.getUrlUID(userUrl);
const name = userUrlEl.textContent.trim();
const playInfoEl = el.querySelector('[flex="~ items-center gap-1 wrap"]>div');
let playCount = playInfoEl.querySelector('span:first-child')?.textContent.trim() || null;
playCount = sFormatUtil.toPlayCountOrBulletChat(playCount);
let bulletChat = playInfoEl.querySelector('span:last-of-type')?.textContent.trim() || null;
if (playInfoEl.querySelectorAll('span').length < 2) {
bulletChat = -1;
} else {
bulletChat = sFormatUtil.toPlayCountOrBulletChat(bulletChat);
}
let nDuration = el.querySelector('[class*="group-hover:opacity-0"]')?.textContent.trim() || null;
nDuration = sFormatUtil.timeStringToSeconds(nDuration);
const videoUrl = el.querySelector('[href*="https://www.bilibili.com/video"]')?.href;
const bv=elUtil.getUrlBV(videoUrl);
const insertionPositionEl = el.querySelector('[class="group/desc"]');
list.push({
title,
name,
uid,
bv,
userUrl,
videoUrl,
playCount,
bulletChat,
nDuration,
el: parentElement,
insertionPositionEl,
explicitSubjectEl: parentElement
});
}
return list
};
const getRightTabs = async () => {
const beEl = await getBewlyEl();
const els = await elUtil.findElementsUntilFound(".dock-content-inner>.b-tooltip-wrapper", {doc: beEl});
const list = [];
for (let el of els) {
const label = el.querySelector('.b-tooltip').textContent.trim();
const active = !!el.querySelector('.dock-item.group.active');
list.push({label, active, el});
}
return list;
};
const getHistoryVideoDataList = async () => {
const beEL = await getBewlyEl();
const elList = await elUtil.findElementsUntilFound("a.group[flex][cursor-pointer]", {doc: beEL});
const list = [];
for (let el of elList) {
const titleEl = el.querySelector('h3.keep-two-lines');
const videoUrlEl = titleEl.parentElement;
const userEl = videoUrlEl.nextElementSibling;
const videoUrl = videoUrlEl.href;
const bv=elUtil.getUrlBV(videoUrl);
const userUrl = userEl.href;
const uid = elUtil.getUrlUID(userUrl);
const name = userEl.textContent.trim();
const title = titleEl?.textContent.trim();
const tempTime = el.querySelector('div[pos][rounded-8]')?.textContent.trim().split(/[\t\r\f\n\s]*/g).join("");
const match = tempTime?.match(/\/(.*)/);
let nDuration = match?.[1];
nDuration = sFormatUtil.timeStringToSeconds(nDuration);
list.push({
title,
userUrl,
name,
uid,
videoUrl,
nDuration,
bv,
el,
insertionPositionEl: videoUrlEl.parentElement,
explicitSubjectEl: el
});
}
return list
};
const startShieldingHistoryVideoList = async () => {
const list = await getHistoryVideoDataList();
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue
}
eventEmitter.send('视频添加屏蔽按钮', {data: videoData, maskingFunc: startShieldingHistoryVideoList});
}
};
const startShieldingVideoList$2 = async () => {
const list = await getVideoList();
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue
}
eventEmitter.send('视频添加屏蔽按钮', {data: videoData, maskingFunc: startShieldingVideoList$2});
}
};
const intervalExecutionStartShieldingVideo$2 = () => {
const res = shielding.intervalExecutionStartShieldingVideoInert(startShieldingVideoList$2, '视频');
return () => {
return res
}
};
const intervalExecutionStartShieldingHistoryVideo = () => {
const res = shielding.intervalExecutionStartShieldingVideoInert(startShieldingHistoryVideoList, '历史记录');
return () => {
return res
}
};
const startShieldingVideo$1 = intervalExecutionStartShieldingVideo$2();
const startShieldingHistoryVideo = intervalExecutionStartShieldingHistoryVideo();
const rightTabsInsertListener = () => {
getRightTabs().then(list => {
for (let {el, label, active} of list) {
el.addEventListener('click', () => {
console.log('右侧选项卡栏点击了' + label, active);
if (label === '首页') {
homeTopTabsInsertListener();
startShieldingVideo$1().start();
} else {
startShieldingVideo$1().stop();
}
if (label === '观看历史') {
startShieldingHistoryVideo().start();
} else {
startShieldingHistoryVideo().stop();
}
}
);
}
}
);
};
const getHomeTopTabs = async () => {
const beEl = await getBewlyEl();
const els = beEl.querySelectorAll('.home-tabs-inside>[data-overlayscrollbars-contents]>button');
const list = [];
for (let el of els) {
const label = el.textContent.trim();
const active = el.classList.contains('tab-activated');
list.push({label, active, el});
}
if (list.some(tab => tab.active === true)) {
return list
}
return await getHomeTopTabs()
};
const excludeTabNames = ['正在关注', '订阅剧集', '直播'];
const excludeRankingLeftTabNames = ['番剧', '综艺', '电视剧', '纪录片', '中国动画'];
const homeTopTabsInsertListener = () => {
getHomeTopTabs().then(list => {
for (let {el, label} of list) {
el.addEventListener('click', () => {
console.log('点击了' + label);
if (excludeTabNames.includes(label)) {
startShieldingVideo$1().stop();
return
}
if (label === '排行') {
rankingLeftTabsInsertListener();
}
startShieldingVideo$1().start();
});
}
});
};
const getRankingLeftTabs = async () => {
const beEl = await getBewlyEl();
const elList = await elUtil.findElementsUntilFound('ul[flex="~ col gap-2"]>li', {doc: beEl});
const list = [];
for (let el of elList) {
const label = el.textContent.trim();
list.push({label, el});
}
return list
};
const rankingLeftTabsInsertListener = () => {
getRankingLeftTabs().then(list => {
for (let {el, label} of list) {
el.addEventListener('click', () => {
console.log('点击了' + label);
if (excludeRankingLeftTabNames.includes(label)) {
startShieldingVideo$1().stop();
return
}
startShieldingVideo$1().start();
});
}
});
};
const installBEWLStyle = () => {
getBewlyEl().then(el => {
gz_ui_css.addStyle(el, el);
});
};
const searchBoxInsertListener = async () => {
const beEl = await getBewlyEl();
const input = await elUtil.findElementUntilFound('[placeholder="搜索观看历史"]', {doc: beEl});
input.addEventListener('keydown', (event) => {
if (event.key === 'Enter' || event.keyCode === 13) {
console.log('回车键被按下');
if (input['value'].length === 0) return
setTimeout(startShieldingHistoryVideoList, 1500);
}
});
};
const startRun$1 = async (url) => {
const parseUrl = defUtil.parseUrl(url);
const {page} = parseUrl.queryParams;
installBEWLStyle();
if (page === 'Home' ||
url.startsWith('https://www.bilibili.com/?spm_id_from=') ||
url === 'https://www.bilibili.com/'
) {
startShieldingVideo$1().start();
homeTopTabsInsertListener();
}
if (page === 'History') {
startShieldingHistoryVideo().start();
searchBoxInsertListener();
}
rightTabsInsertListener();
};
var compatibleBewlyBewly = {
startRun: startRun$1,
isBEWLYPage,
};
const isNewHistoryPage = (url) => {
return url.includes('://www.bilibili.com/history')
};
const getDuration = (str) => {
if (str === null) {
return -1
}
if (str.includes('已看完') || str === '') {
return -1
} else {
const match = str?.match(/\/(.*)/);
if (match) {
return sFormatUtil.timeStringToSeconds(match[1]);
}
}
return -1
};
const getVideoDataList$3 = async () => {
const elList = await elUtil.findElementsUntilFound('.section-cards.grid-mode>div');
const list = [];
for (let el of elList) {
const titleEl = el.querySelector('.bili-video-card__title');
const title = titleEl.textContent.trim();
const videoUrl = titleEl.firstElementChild.href||null;
if (videoUrl?.includes('live.bilibili.com')) {
continue
}
const bv=elUtil.getUrlBV(videoUrl);
const userEl = el.querySelector('.bili-video-card__author');
const cardTag = el.querySelector('.bili-cover-card__tag')?.textContent.trim() || null;
const name = userEl.textContent.trim();
const userUrl = userEl.href;
const uid = elUtil.getUrlUID(userUrl);
let nDuration = -1;
if (cardTag !== '专栏') {
nDuration = el.querySelector('.bili-cover-card__stat')?.textContent.trim() || null;
nDuration = getDuration(nDuration);
}
const tempEL = el.querySelector('.bili-video-card__details');
list.push({
title,
videoUrl,
name,
userUrl,
nDuration,
uid,
el,
bv,
insertionPositionEl: tempEL,
explicitSubjectEl: tempEL
});
}
return list
};
const startShieldingVideoList$1 = async () => {
const list = await getVideoDataList$3();
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue;
}
shielding.addBlockButton({data: videoData, maskingFunc: startShieldingVideoList$1}, "gz_shielding_button");
}
};
const intervalExecutionStartShieldingVideo$1 = () => {
const res = shielding.intervalExecutionStartShieldingVideoInert(startShieldingVideoList$1, '历史记录项');
return () => {
return res
}
};
const executionStartShieldingVideo = intervalExecutionStartShieldingVideo$1();
const getTopFilterLabel = async () => {
const el = await elUtil.findElementUntilFound('.radio-filter>.radio-filter__item--active');
return el.textContent?.trim()
};
const topFilterInsertListener = () => {
elUtil.findElementUntilFound('.radio-filter').then((el => {
el.addEventListener('click', (e) => {
const target = e.target;
const label = target.textContent?.trim();
console.log(`点击了${label}`);
if (label === '直播') {
executionStartShieldingVideo().stop();
return
}
executionStartShieldingVideo().start();
});
}));
};
const startRun = () => {
getTopFilterLabel().then(label => {
if (label === '直播') {
return
}
executionStartShieldingVideo().start();
});
topFilterInsertListener();
};
var newHistory = {
isNewHistoryPage,
intervalExecutionStartShieldingVideo: intervalExecutionStartShieldingVideo$1,
startRun
};
const startShieldingHotList = async () => {
const elList = await elUtil.findElements(".trendings-col>.trending-item",
{interval: 2000});
console.log("检查热搜关键词中...");
const hotSearchKeyArr = ruleKeyListData$1.getHotSearchKeyArr();
const hotSearchKeyCanonicalArr = ruleKeyListData$1.getHotSearchKeyCanonicalArr();
for (let el of elList) {
const label = el.textContent.trim();
let match = ruleMatchingUtil.fuzzyMatch(hotSearchKeyArr, label);
if (match) {
el.remove();
eventEmitter.send('打印信息', `根据模糊热搜关键词-【${match}】-屏蔽-${label}`);
continue;
}
match = ruleMatchingUtil.regexMatch(hotSearchKeyCanonicalArr, label);
if (match) {
eventEmitter.send('打印信息', `根据正则热搜关键词-【${match}】-屏蔽-${label}`);
el.remove();
}
}
};
var hotSearch = {
startShieldingHotList
};
const isMessagePage = (url = window.location.href) => {
return url.includes("message.bilibili.com");
};
const modifyTopItemsZIndex = () => {
elUtil.findElement('#home_nav').then(el => {
el.style.zIndex = 1000;
eventEmitter.send('打印信息', '已修改顶部的z-index值为1');
});
};
var messagePage = {
isMessagePage,
modifyTopItemsZIndex,
};
const isSpacePage = (url = window.location.href) => {
return url.startsWith('https://space.bilibili.com/')
};
const isPersonalHomepage = async () => {
const keyStr = 'isPersonalHomepage';
const cache = valueCache.get(keyStr);
if (cache) {
return cache
}
const {
state: newState,
data: newData
} = await elUtil.findElements('.nav-tab__item .nav-tab__item-text', {timeout: 2500});
if (newState) {
const bool = newData.some(el => el.textContent.trim() === '设置');
valueCache.set('space_version', 'new');
return valueCache.set(keyStr, bool);
}
let {state} = await elUtil.findElement('.n-tab-links>.n-btn.n-setting>.n-text', {timeout: 1500});
valueCache.set('space_version', 'old');
return valueCache.set(keyStr, state);
};
const getUserInfo = async () => {
const spaceUserInfo = valueCache.get('space_userInfo');
if (spaceUserInfo) {
return spaceUserInfo
}
await isPersonalHomepage();
const nameData = {};
nameData.uid = elUtil.getUrlUID(window.location.href);
if (valueCache.get('space_version', 'new') === 'new') {
nameData.name = await elUtil.findElement('.nickname').then(el => el.textContent.trim());
} else {
nameData.name = await elUtil.findElement('#h-name').then(el => el.textContent.trim());
}
if (!nameData.name) {
const title = document.title;
nameData.name = title.match(/(.+)的个人空间/)[1];
}
valueCache.set('space_userInfo', nameData);
return nameData
};
var space = {
isPersonalHomepage,
isSpacePage,
getUserInfo
};
const bOnlyTheHomepageIsBlocked$2 = localMKData.getBOnlyTheHomepageIsBlocked();
const staticRoute = (title, url) => {
console.log("静态路由", title, url);
topInput.processTopInputContent();
if (bOnlyTheHomepageIsBlocked$2) return;
hotSearch.startShieldingHotList();
eventEmitter.send('通知屏蔽');
if (compatibleBewlyBewly.isBEWLYPage(url)) {
if (localMKData.isCompatible_BEWLY_BEWLY()) {
compatibleBewlyBewly.startRun(url);
return;
}
}
if (bilibiliHome.isHome(url, title)) {
if (localMKData.isCompatible_BEWLY_BEWLY()) {
return;
}
bilibiliHome.scrollMouseUpAndDown().then(() => bilibiliHome.startDebounceShieldingChangeVideoList());
bilibiliHome.startClearExcessContentList();
bilibiliHome.deDesktopDownloadTipEl();
}
if (searchModel.isSearch(url)) {
searchModel.searchTopTabsIWrapperInstallListener();
searchModel.startShieldingVideoList();
searchModel.currentlyActivatedOptions();
searchLive.installStyle();
searchModel.delFooterContent();
}
if (videoPlayModel.isVideoPlayPage(url)) {
elUtil.findElement('.v-modal').then(() => {
const styleEl = document.createElement('style');
styleEl.innerHTML = `.v-modal {
z-index: auto !important;
}`;
document.head.appendChild(styleEl);
});
videoPlayModel.findTheExpandButtonForTheListOnTheRightAndBindTheEvent();
videoPlayModel.setVideoPlayerEnded();
videoPlayModel.delElManagement();
}
if (collectionVideoPlayPageModel.iscCollectionVideoPlayPage(url)) {
collectionVideoPlayPageModel.findTheExpandButtonForTheListOnTheRightAndBindTheEvent();
}
if (liveRoomModel.isLiveRoom(url)) {
liveRoomModel.addWatchLiveRoomChatItemsListener();
}
if (videoPlayWatchLater.isVideoPlayWatchLaterPage(url)) {
videoPlayWatchLater.findTheExpandButtonForTheListOnTheRightAndBindTheEvent();
}
if (newHistory.isNewHistoryPage(url)) {
newHistory.startRun();
}
if (messagePage.isMessagePage(url)) {
messagePage.modifyTopItemsZIndex();
}
if (space.isSpacePage()) {
space.getUserInfo().then(userInfo => {
console.info('userInfo', userInfo);
});
}
};
const dynamicRouting = (title, url) => {
console.log("动态路由", title, url);
if (bOnlyTheHomepageIsBlocked$2) return;
eventEmitter.send('通知屏蔽');
};
var router = {
staticRoute,
dynamicRouting
};
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
};
eventEmitter.on('评论添加屏蔽按钮', (commentsData) => {
shielding.addBlockButton({
data: commentsData,
maskingFunc: startShieldingComments
}, "gz_shielding_comment_button");
});
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 () => {
if (videoPlayModel.isVideoPlayPage() && gmUtil.getData('isDelBottomComment', false)) {
return
}
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 getVideDataList = async (isWeekly = false) => {
const css = isWeekly ? ".video-list>.video-card" : ".card-list>.video-card";
const elList = await elUtil.findElementsUntilFound(css);
const list = [];
for (let el of elList) {
const videoCardInfoEl = el.querySelector(".video-card__info");
const title = videoCardInfoEl.querySelector(".video-name").title.trim();
const name = videoCardInfoEl.querySelector(".up-name__text").title;
const videoUrl = el.querySelector('.video-card__content>a')?.href || null;
const bv = elUtil.getUrlBV(videoUrl);
let nPlayCount = el.querySelector('.play-text').textContent.trim();
nPlayCount = sFormatUtil.toPlayCountOrBulletChat(nPlayCount);
let nBulletChat = el.querySelector('.like-text').textContent.trim();
nBulletChat = sFormatUtil.toPlayCountOrBulletChat(nBulletChat);
list.push({
el,
title,
name,
uid: -1,
videoUrl,
bv,
nPlayCount,
nBulletChat,
nDuration: -1,
insertionPositionEl: videoCardInfoEl.querySelector("div"),
explicitSubjectEl: videoCardInfoEl
});
}
return list;
};
const startShieldingVideoList = async (isWeekly = false) => {
const list = await getVideDataList(isWeekly);
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue;
}
eventEmitter.send('添加热门视频屏蔽按钮', {data: videoData, maskingFunc: startShieldingVideoList});
}
};
var popularAll = {
startShieldingVideoList
};
const isDynamicPage = (url) => {
return url.search("space.bilibili.com/\\d+/dynamic") !== -1;
};
const getDataList = async () => {
const elList = await elUtil.findElementsUntilFound(".bili-dyn-list__items>.bili-dyn-list__item");
const list = [];
for (let el of elList) {
const videoCardEl = el.querySelector(".bili-dyn-card-video__title");
const name = el.querySelector(".bili-dyn-title").textContent.trim();
const tagEl = el.querySelector(".bili-dyn-topic__text");
const data = {el, name};
if (tagEl !== null) {
data.tag = tagEl.textContent.trim();
}
data.judgmentVideo = videoCardEl !== null;
if (data.judgmentVideo) {
data.title = videoCardEl.textContent.trim();
} else {
const contentTitleEL = el.querySelector(".dyn-card-opus>.dyn-card-opus__title");
const contentTitle = contentTitleEL === null ? "" : contentTitleEL.textContent.trim();
const contentElBody = el.querySelector(".bili-rich-text").textContent.trim();
data.content = contentTitle + contentElBody;
}
list.push(data);
}
return list;
};
const startShieldingDynamicContent = async () => {
const personalHomepage = space.isPersonalHomepage();
if (personalHomepage) return;
const list = await getDataList();
for (let dynamicContent of list) {
shielding.shieldingDynamicDecorated(dynamicContent);
}
};
const startThrottleShieldingDynamicContent = defUtil.throttle(startShieldingDynamicContent, 2000);
var dynamic = {
isDynamicPage,
startThrottleShieldingDynamicContent
};
const isLiveSection = (url) => {
return url.includes("live.bilibili.com/p/eden/area-tags")
};
const getRoomCardDataList = async () => {
const elList = await elUtil.findElementsUntilFound("#room-card-list>div");
const list = [];
for (let el of elList) {
const liveUrl = el.querySelector("#card").href;
const name = el.querySelector(".Item_nickName_KO2QE").textContent.trim();
const title = el.querySelector(".Item_roomTitle_ax3eD").textContent.trim();
const partition = el.querySelector(".Item_area-name_PXDG4")?.textContent.trim() || null;
const popularity = el.querySelector(".Item_onlineCount_FmOW6").textContent.trim();
list.push({liveUrl, name, title, partition, popularity, el});
}
return list;
};
const startShieldingLiveRoom$1 = async () => {
const liveList = await getRoomCardDataList();
for (let liveData of liveList) {
shielding.shieldingLiveRoomDecorated(liveData);
}
};
var liveSectionModel = {
isLiveSection,
startShieldingLiveRoom: startShieldingLiveRoom$1
};
const isLiveHomePage = (url) => {
return url.includes("https://live.bilibili.com/?spm_id_from=333.1007.0.0") ||
url === "https://live.bilibili.com/"
};
const getTopLiveRoomDataList = async () => {
const verification = await elUtil.findElementUntilFound(".v-top>.aside-item .t-left.aside-item-tips.p-absolute.w-100.border-box");
if (verification.textContent.trim() === "--") {
return await getTopLiveRoomDataList();
}
const elList = await elUtil.findElementsUntilFound(".v-top>.aside-item", {interval: 2000});
const list = [];
for (let el of elList) {
const classList = el.classList;
const active = classList.contains("active");
const title = el.getAttribute("title");
const {up_id: uid, room_id} = JSON.parse(el.getAttribute("data-report"));
const liveUrl = `https://live.bilibili.com/${room_id}`;
list.push({title, uid, active, liveUrl, el});
}
return list;
};
const getLiveRoomDataList = async () => {
const elList = await elUtil.findElementsUntilFound(".room-card-wrapper.p-relative.dp-i-block");
const list = [];
for (let el of elList) {
const cardEl = el.querySelector(".room-card-ctnr.p-relative.w-100");
const cardData = JSON.parse(cardEl.getAttribute("data-bl-report-click") || "");
const {up_id: uid, room_id} = cardData.msg;
const liveUrl = `https://live.bilibili.com/${room_id}`;
const name = el.querySelector(".room-anchor>span").textContent.trim();
const title = el.querySelector(".room-title.card-text").textContent.trim();
const partition = el.querySelector(".area-name").textContent.trim();
const popularity = el.querySelector(".room-anchor .v-middle").textContent.trim();
list.push({name, title, partition, popularity, liveUrl, uid, el});
}
return list;
};
const startShieldingLiveRoom = async () => {
const list = await getLiveRoomDataList();
for (let liveData of list) {
shielding.shieldingLiveRoomDecorated(liveData);
}
};
const startShieldingTopLiveRoom = async () => {
const list = await getTopLiveRoomDataList();
for (let liveData of list) {
shielding.shieldingLiveRoomDecorated(liveData);
}
};
var liveHome = {
isLiveHomePage,
startShieldingLiveRoom,
startShieldingTopLiveRoom
};
const isPartition = (url) => {
return url.includes('www.bilibili.com/v/');
};
const getHotVideoDayList = async () => {
const elList = await elUtil.findElementsUntilFound('.bili-rank-list-video__item');
const list = [];
for (let el of elList) {
let videoUrlEl = el.querySelector('a.rank-video-card');
const titleEl = el.querySelector('.rank-video-card__info--tit');
const videoUrl = videoUrlEl.href;
const title = titleEl.textContent.trim();
const bv = elUtil.getUrlBV(videoUrl);
list.push({
title, videoUrl, bv, el
});
}
return list
};
const getVideoDataList$2 = async () => {
const elList = await elUtil.findElementsUntilFound('.bili-video-card');
const list = [];
const oneTitleEl = elList[0].querySelector('.bili-video-card__info--tit>a');
if (oneTitleEl === null) {
await defUtil.wait();
return await getVideoDataList$2()
}
for (let el of elList) {
const titleEl = el.querySelector('.bili-video-card__info--tit>a');
if (titleEl === null) {
continue
}
const userEl = el.querySelector('a.bili-video-card__info--owner');
const playAndDmu = el.querySelectorAll('.bili-video-card__stats--item>span');
let nDuration = el.querySelector('.bili-video-card__stats__duration')?.textContent.trim();
let nPlayCount = playAndDmu[0]?.textContent.trim();
nPlayCount = sFormatUtil.toPlayCountOrBulletChat(nPlayCount);
let nBulletChat = playAndDmu[1]?.textContent.trim();
nBulletChat = sFormatUtil.toPlayCountOrBulletChat(nBulletChat);
nDuration = sFormatUtil.toPlayCountOrBulletChat(nDuration);
const title = titleEl.textContent.trim();
const videoUrl = titleEl.href;
const userUrl = userEl.href;
const name = userEl
.querySelector('.bili-video-card__info--author')
?.textContent.trim() || null;
const uid = elUtil.getUrlUID(userUrl);
const bv = elUtil.getUrlBV(videoUrl);
list.push({
name, title, uid, bv, userUrl, videoUrl, el,
nPlayCount, nBulletChat, nDuration,
explicitSubjectEl: el.querySelector('.bili-video-card__info'),
insertionPositionEl: el.querySelector('.bili-video-card__info--bottom')
});
}
return list
};
const shieldingVideoList = async () => {
const list = await getVideoDataList$2();
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue
}
eventEmitter.send('视频添加屏蔽按钮', {data: videoData, maskingFunc: shieldingVideoList});
}
};
const startShieldingHotVideoDayList = async () => {
const list = await getHotVideoDayList();
for (let videoData of list) {
shielding.shieldingVideoDecorated(videoData);
}
};
const startIntervalShieldingVideoList = () => {
setInterval(async () => {
await shieldingVideoList();
}, 1500);
};
var partition = {
isPartition,
startIntervalShieldingVideoList,
startShieldingHotVideoDayList
};
const bOnlyTheHomepageIsBlocked$1 = localMKData.getBOnlyTheHomepageIsBlocked();
const compatible_BEWLY_BEWLY = localMKData.isCompatible_BEWLY_BEWLY();
const observeNetwork = (url, windowUrl, winTitle, initiatorType) => {
if (!url.includes('api')) {
return;
}
if (bOnlyTheHomepageIsBlocked$1) {
if (!bilibiliHome.isHome(windowUrl, winTitle)) {
return;
}
}
if (url.startsWith("https://api.bilibili.com/x/web-interface/wbi/index/top/feed/rcmd?web_location=")) {
if (compatible_BEWLY_BEWLY) {
return;
}
bilibiliHome.startDebounceShieldingChangeVideoList();
bilibiliHome.startDebounceShieldingHomeVideoList();
console.log("检测到首页加载了换一换视频列表和其下面的视频列表");
return;
}
if (url.startsWith("https://api.bilibili.com/x/v2/reply/wbi/main?oid=")) {
console.log("检测到评论区楼主评论加载了");
commentSectionModel.startShieldingComments();
return;
}
if (url.startsWith("https://api.bilibili.com/x/v2/reply/reply?oid=")) {
console.log("检测到评论区楼主层中的子层评论列表加载了");
commentSectionModel.startShieldingComments();
}
if (url.startsWith("https://api.bilibili.com/x/web-interface/popular?ps=")) {
popularAll.startShieldingVideoList();
}
if (url.startsWith("https://api.bilibili.com/x/web-interface/popular/series/one?number=")) {
popularAll.startShieldingVideoList(true);
}
if (url.startsWith("https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?offset=")) {
console.log("检测到用户动态加载了");
dynamic.startThrottleShieldingDynamicContent();
}
if (url.startsWith("https://api.live.bilibili.com/xlive/web-interface/v1/second/getList?platform=web&parent_area_id=")) {
console.log("检测到直播间加载了分区下的房间列表");
liveSectionModel.startShieldingLiveRoom();
}
if (url.startsWith("https://api.live.bilibili.com/xlive/web-interface/v1/index/getList?platform=web")) {
console.log("检测到直播间加载了推荐房间列表");
liveHome.startShieldingLiveRoom();
}
if (url.startsWith('https://api.bilibili.com/x/web-interface/ranking/region?day=')) {
console.log("检测到专区热门排行榜加载了");
partition.startShieldingHotVideoDayList();
}
};
var observeNetwork$1 = {
observeNetwork
};
const shielding_user_vue = {
template: `
<div>
<el-dropdown v-if="shieldingModelShow"
@command="dropdownEvent">
<el-button round>
屏蔽操作<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu v-slot="dropdown">
<el-dropdown-item command="屏蔽uid"
v-if="shieldingUseUIDrButShow">屏蔽(uid)
</el-dropdown-item>
<el-dropdown-item command="移除屏蔽uid"
v-if="removedShieldingUIDrButShow">移除屏蔽(uid)
</el-dropdown-item>
<el-dropdown-item command="选择用户屏蔽" v-if="selectUserBlockingButShow">选择用户屏蔽</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>`,
data() {
return {
shieldingModelShow: true,
shieldingUseUIDrButShow: false,
removedShieldingUIDrButShow: false,
selectUserBlockingButShow: false,
uid: -1
}
},
methods: {
async dropdownEvent(item) {
if (item === '屏蔽uid') {
const {name, uid} = await space.getUserInfo();
this.$confirm(`是否屏蔽当前用户【${name}】uid=【${uid}】`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const {status, res} = ruleUtil.addRulePreciseUid(uid, false);
this.$alert(res);
if (status) {
this.shieldingUseUIDrButShow = false;
this.removedShieldingUIDrButShow = true;
}
});
return
}
if (item === '移除屏蔽uid') {
const {uid} = await space.getUserInfo();
ruleUtil.delRUlePreciseUid(uid);
return
}
if (item === '选择用户屏蔽') {
await videoPlayModel.selectUserBlocking();
return
}
this.$message('未知选项');
}
},
async created() {
if (videoPlayModel.isVideoPlayPage()) {
this.selectUserBlockingButShow = true;
}
if (space.isSpacePage()) {
this.urlUID = elUtil.getUrlUID(window.location.href);
if (ruleKeyListData$1.getPreciseUidArr().includes(this.urlUID)) {
this.shieldingModelShow = true;
this.removedShieldingUIDrButShow = true;
await this.$alert('当前用户为已标记uid黑名单', '提示');
return;
}
if (await space.isPersonalHomepage()) {
this.shieldingModelShow = false;
return;
}
this.shieldingModelShow = true;
this.shieldingUseUIDrButShow = true;
}
}
};
const addLayout = () => {
const div = document.createElement('div');
const divStyle = div.style;
divStyle.position = 'fixed';
divStyle.zIndex = '9000';
divStyle.right = "0";
divStyle.top = '13%';
divStyle.transition = 'transform 0.5s';
if (!localMKData.isFirstFullDisplay()) {
divStyle.transform = 'translateX(80%)';
} else {
if (localMKData.isHalfHiddenIntervalAfterInitialDisplay()) {
setTimeout(() => {
divStyle.transform = 'translateX(80%)';
eventEmitter.send('el-msg', '自动隐藏外部主面板显隐按钮');
}, 8000);
}
}
const vueDiv = document.createElement('div');
div.appendChild(vueDiv);
document.body.appendChild(div);
const config = {
components: {
shielding_user_vue,
},
el: vueDiv,
template: `
<div v-show="panelShow" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
<div>
<el-button round @click="showBut">主面板</el-button>
</div>
<shielding_user_vue/>
</div>`,
data() {
return {
panelShow: localMKData.isShowRightTopMainButSwitch(),
}
},
methods: {
showBut() {
eventEmitter.send('主面板开关');
},
handleMouseEnter() {
divStyle.transform = "translateX(0)";
},
handleMouseLeave() {
divStyle.transform = 'translateX(80%)';
}
},
created() {
eventEmitter.on('显隐主面板开关', (bool) => {
this.panelShow = bool;
});
}
};
new Vue(config);
};
var rightFloatingLayoutVue = {
addLayout
};
const generalUrl=[
"popular/rank/all",
"popular/rank/douga",
"popular/rank/music",
"popular/rank/dance",
"popular/rank/game",
"popular/rank/knowledge",
"popular/rank/tech",
"popular/rank/sports",
"popular/rank/car",
"popular/rank/life",
"popular/rank/food",
"popular/rank/animal",
"popular/rank/kichiku",
"popular/rank/fashion",
"popular/rank/ent",
"popular/rank/cinephile",
"popular/rank/origin",
"popular/rank/rookie"
];
const isPopularHistory = (url) => {
return url.includes("popular/history")
};
const isPopularAllPage = (url) => {
return url.includes("www.bilibili.com/v/popular/all");
};
const isPopularWeeklyPage = (url) => {
return url.includes("www.bilibili.com/v/popular/weekly");
};
const isGeneralPopularRank=(url)=>{
return generalUrl.some(itemUrl => url.includes(itemUrl));
};
const getVideoDataList$1 = async () => {
const elList = await elUtil.findElementsUntilFound(".rank-list>li");
const list = [];
for (let el of elList) {
const title = el.querySelector(".title").textContent.trim();
const userUrl = el.querySelector(".detail>a").href;
const uid = elUtil.getUrlUID(userUrl);
const name = el.querySelector(".up-name").textContent.trim();
const detailStateEls = el.querySelectorAll('.detail-state>.data-box');
let nPlayCount = detailStateEls[0].textContent.trim();
nPlayCount = sFormatUtil.toPlayCountOrBulletChat(nPlayCount);
let nBulletChat = detailStateEls[1].textContent.trim();
nBulletChat = sFormatUtil.toPlayCountOrBulletChat(nBulletChat);
const videoUrl = el.querySelector('.img>a')?.href || null;
const bv = elUtil.getUrlBV(videoUrl);
list.push({
title,
userUrl,
uid,
name,
videoUrl,
bv,
nPlayCount,
nBulletChat,
nDuration: -1,
el,
insertionPositionEl: el.querySelector(".detail-state"),
explicitSubjectEl: el.querySelector(".info")
});
}
return list;
};
const startShieldingRankVideoList = async () => {
const list = await getVideoDataList$1();
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue;
}
eventEmitter.send('添加热门视频屏蔽按钮', {data: videoData, maskingFunc: startShieldingRankVideoList});
}
};
var popular = {
isPopularHistory,
isPopularAllPage,
isGeneralPopularRank,
isPopularWeeklyPage,
startShieldingRankVideoList,
};
const isOldHistory = (url) => {
return url.includes('https://www.bilibili.com/account/history')
};
const getVideoDataList = async () => {
const elList = await elUtil.findElementsUntilFound('#history_list>.history-record');
const list = [];
for (let el of elList) {
const labelEL = el.querySelector('.cover-contain>.label');
if (labelEL !== null) {
const label = labelEL.textContent.trim();
console.log(`排除${label}`);
continue
}
const titleEl = el.querySelector('.title');
const userEl = el.querySelector('.w-info>span>a');
const title = titleEl.textContent.trim();
const videoUrl = titleEl.href;
const bv = elUtil.getUrlBV(videoUrl);
const name = userEl.textContent.trim();
const userUrl = userEl.href;
const uid = elUtil.getUrlUID(userUrl);
list.push({
title,
videoUrl,
name,
userUrl,
uid,
el,
bv,
explicitSubjectEl: el.querySelector('.r-txt'),
insertionPositionEl: el.querySelector('.subtitle')
});
}
return list
};
const startShieldingVideo = async () => {
console.log('开始屏蔽旧版历史记录视频列表');
const list = await getVideoDataList();
const css = {right: "45px"};
for (let videoData of list) {
if (shielding.shieldingVideoDecorated(videoData)) {
continue;
}
videoData.css = css;
eventEmitter.send('视频添加屏蔽按钮', {data: videoData, maskingFunc: startShieldingVideo});
}
console.log('屏蔽旧版历史记录视频列表完成');
};
const intervalExecutionStartShieldingVideo = () => {
setInterval(startShieldingVideo, 2000);
};
var oldHistory = {
isOldHistory,
intervalExecutionStartShieldingVideo
};
const bOnlyTheHomepageIsBlocked = localMKData.getBOnlyTheHomepageIsBlocked();
const compatibleBEWLYBEWLY = localMKData.isCompatible_BEWLY_BEWLY();
const adaptationBAppCommerce = localMKData.getAdaptationBAppCommerce();
eventEmitter.on('通知屏蔽', () => {
const url = window.location.href;
const title = document.title;
if (bOnlyTheHomepageIsBlocked) return;
if (searchModel.isSearch(url)) {
searchModel.startShieldingVideoList();
}
if (bilibiliHome.isHome(url, title)) {
if (compatibleBEWLYBEWLY) {
return;
}
if (adaptationBAppCommerce) {
bilibiliHome.startIntervalShieldingGateVideoList();
}
bilibiliHome.startDebounceShieldingHomeVideoList();
}
if (videoPlayModel.isVideoPlayPage(url)) {
videoPlayModel.startShieldingVideoList();
}
if (collectionVideoPlayPageModel.iscCollectionVideoPlayPage(url)) {
collectionVideoPlayPageModel.startShieldingVideoList();
}
if (popular.isPopularAllPage(url) || popular.isPopularHistory(url)) {
popularAll.startShieldingVideoList();
}
if (popular.isPopularWeeklyPage(url)) {
popularAll.startShieldingVideoList(true);
}
if (popular.isGeneralPopularRank(url)) {
popular.startShieldingRankVideoList();
}
if (topicDetail.isTopicDetailPage(url)) {
topicDetail.startShielding();
}
if (dynamic.isDynamicPage(url)) {
dynamic.startThrottleShieldingDynamicContent();
}
if (videoPlayWatchLater.isVideoPlayWatchLaterPage(url)) {
videoPlayWatchLater.startDebounceShieldingVideoList();
}
if (liveSectionModel.isLiveSection(url)) {
liveSectionModel.startShieldingLiveRoom();
}
if (liveHome.isLiveHomePage(url)) {
liveHome.startShieldingLiveRoom();
liveHome.startShieldingTopLiveRoom();
}
if (oldHistory.isOldHistory(url)) {
oldHistory.intervalExecutionStartShieldingVideo();
}
if (partition.isPartition(url)) {
partition.startIntervalShieldingVideoList();
}
});
window.addEventListener('load', () => {
console.log('页面加载完成');
rightFloatingLayoutVue.addLayout();
router.staticRoute(document.title, window.location.href);
watch.addEventListenerUrlChange((newUrl, oldUrl, title) => {
router.dynamicRouting(title, newUrl);
});
});
watch.addEventListenerNetwork((url, windowUrl, winTitle, initiatorType) => {
observeNetwork$1.observeNetwork(url, windowUrl, winTitle, initiatorType);
});
document.addEventListener('keydown', function (event) {
if (event.key === "`") {
eventEmitter.send('主面板开关');
}
});
})(Vue, Dexie);