Greasy Fork

Greasy Fork is available in English.

哔哩哔哩屏蔽增强器

对B站视频或评论进行屏蔽,支持关键词模糊正则等,支持时长播放弹幕过滤等,如视频、评论、动态、直播间的评论等,详情可看下面支持的屏蔽类型

当前为 2025-02-08 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        哔哩哔哩屏蔽增强器
// @namespace   http://tampermonkey.net/
// @license     Apache-2.0
// @version     2.3
// @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.icu/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('http://greasyfork.icu/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
    };
    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,
    };
    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 null;
        if (type === "precise_uid" || type === "precise_uid_white") {
            ruleValue = parseInt(ruleValue);
            if (isNaN(ruleValue)) {
                Qmsg.info('请输入数字!');
                return null;
            }
        } else {
            ruleValue.trim();
        }
        if (ruleValue === '') {
            Qmsg.info('内容为空');
            return null;
        }
        return ruleValue;
    };
    const addRule = (ruleValue, type) => {
        const inputValue = verificationInputValue(ruleValue, type);
        return new Promise((resolve, reject) => {
                if (inputValue === null) {
                    reject('取消添加');
                    return;
                }
                const arr = gmUtil.getData(type, []);
                if (arr.includes(inputValue)) {
                    reject('已存在此内容');
                    return;
                }
                arr.push(inputValue);
                gmUtil.setData(type, arr);
                resolve('添加成功');
            }
        )
    };
    const showAddRuleInput = (type) => {
        const ruleValue = window.prompt('请输入要添加的规则内容', '');
        return addRule(ruleValue, type);
    };
    const showDelRuleInput = (type) => {
        let prompt = window.prompt('请输入要移除的规则内容', '');
        const inputValue = verificationInputValue(prompt, type);
        return new Promise((resolve, reject) => {
            if (inputValue === null) {
                reject('取消添加');
                return;
            }
            const arr = gmUtil.getData(type, []);
            const indexOf = arr.indexOf(inputValue);
            if (indexOf === -1) {
                reject('不存在此内容');
                return;
            }
            arr.splice(indexOf, 1);
            gmUtil.setData(type, arr);
            resolve('移除成功');
        })
    };
    const showSetRuleInput = (type) => {
        let prompt = window.prompt('请输入要修改的规则内容', '');
        const inputValue = verificationInputValue(prompt, type);
        return new Promise((resolve, reject) => {
            if (inputValue === null) return;
            const arr = gmUtil.getData(type, []);
            const indexOf = arr.indexOf(inputValue);
            if (indexOf === -1) {
                reject('不存在此内容');
                return;
            }
            prompt = window.prompt('请输入要修改的内容', '');
            const newInputValue = verificationInputValue(prompt, type);
            if (newInputValue === null) return;
            if (arr.includes(newInputValue)) {
                reject('已存在要修改过后的值内容');
                return;
            }
            arr[indexOf] = newInputValue;
            gmUtil.setData(type, arr);
            resolve('修改成功');
        })
    };
    const getRuleContent = (space = 0) => {
        const ruleMap = {};
        for (let ruleKeyListDatum of ruleKeyListData$1.getRuleKeyListData()) {
            const key = ruleKeyListDatum.key;
            ruleMap[key] = gmUtil.getData(key, []);
        }
        return JSON.stringify(ruleMap, null, space);
    };
    const verificationRuleMap = (keyArr, content) => {
        let parse;
        try {
            parse = JSON.parse(content);
        } catch (e) {
            alert('规则内容有误');
            return false;
        }
        const newRule = {};
        for (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) => {
        return addRule(uid, "precise_uid").then(msg => {
            eventEmitter.send('el-msg', msg);
        }).catch(msg => {
            eventEmitter.send('el-msg', msg);
        })
    };
    const addRulePreciseName = (name) => {
        return addRule(name, "precise_name").then(msg => {
            eventEmitter.send('el-msg', msg);
        }).catch(msg => {
            eventEmitter.send('el-msg', msg);
        })
    };
    var ruleUtil = {
        addRule,
        showAddRuleInput,
        showDelRuleInput,
        showSetRuleInput,
        getRuleContent,
        overwriteImportRules,
        appendImportRules,
        overwriteImportRulesV1,
        getNewRuleKeyList,
        addRulePreciseUid,
        addRulePreciseName
    };
    const basic_rules_vue = {
        template: `
      <div>
      <el-card shadow="never">
        <template #header>
          <span>使用说明</span>
        </template>
        <div>脚本中会对要匹配的内容进行去除空格和转成小写,比如有个内容是【不 要 笑 挑 战
          ChallEnGE】,会被识别称为【不要笑挑战challenge】
        </div>
        <div>在上述一点的情况下,模糊匹配和正则匹配的方式时不用考虑要匹配的内容中大写问题</div>
        <div>大部分情况下模糊匹配比精确匹配好用</div>
        <div>如果用户要添加自己的正则匹配相关的规则时,建议先去该网址进行测试再添加,避免浪费时间
          <el-link href="https://www.jyshare.com/front-end/854/" target="_blank"
                   type="primary">>>>正则表达式在线测试<<<
          </el-link>
        </div>
        <div>
          如果更新脚本之后规则全没了,请点击下面的【旧规则自动转新规则】按钮,进行转换,如不行请通过关于和问题反馈选项卡中的反馈渠道联系作者
        </div>
      </el-card>
      <div>
        <select v-model="selectVal">
          <option v-for="item in ruleInfoArr" :value="item.type">{{ item.name }}</option>
        </select>
        《====可点击切换条件
      </div>
      <el-divider/>
      <el-button-group>
        <el-button @click="operationBut('add')">添加{{ selectText }}</el-button>
        <el-button @click="operationBut('del')">移除{{ selectText }}</el-button>
        <el-button @click="operationBut('set')">修改{{ 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>
      </div>`,
        data() {
            return {
                selectVal: 'name',
                selectText: "",
                ruleActions: [
                    {
                        type: "uid",
                        name: "uid(精确)",
                    }
                ],
                ruleKeyArr: [],
                ruleInfoArr: [],
            }
        },
        methods: {
            operationBut(model) {
                const type = this.selectVal;
                if (model === "add") {
                    ruleUtil.showAddRuleInput(type).then((msg) => {
                        eventEmitter.send('刷新规则信息');
                        alert(msg);
                    }).catch(errMsg => {
                        Qmsg.info(errMsg);
                    });
                }
                if (model === "del") {
                    ruleUtil.showDelRuleInput(type).then((msg) => {
                        eventEmitter.send('刷新规则信息');
                        alert(msg);
                    }).catch(errMsg => {
                        Qmsg.info(errMsg);
                    });
                }
                if (model === "set") {
                    ruleUtil.showSetRuleInput(type).then((msg) => {
                        eventEmitter.send('刷新规则信息');
                        alert(msg);
                    }).catch(errMsg => {
                        Qmsg.info(errMsg);
                    });
                }
                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="index">
          <select v-model="selectValue">
            <option :value="item.value" v-for="item in selectList">{{ item.name }}</option>
          </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 {
                index: 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.index > associatedVal && associatedVal !== -1) {
                    if (associatedFind.bLarge) {
                        this.$alert(`要设置的${find.name}值不能大于${associatedFind.name}的值`);
                        return
                    }
                    console.log('正常修改');
                }
                this.$alert(`已设置${find.name},值为${this.index}`);
                gmUtil.setData(this.selectValue, this.index);
                this.updateInfo();
            },
            cancelBut() {
                gmUtil.setData(this.selectValue, -1);
                const find = this.selectList.find(item => item.value === this.selectValue);
                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.index > 6) {
                        this.index = 6;
                    }
                    if (this.index < 3) {
                        this.index = 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 active-text="模糊和正则匹配词转小写"></el-switch>
      </el-tooltip>
      </div>`,
        data() {
            return {
                bOnlyTheHomepageIsBlocked: localMKData.getBOnlyTheHomepageIsBlocked()
            }
        },
        methods: {},
        watch: {
            bOnlyTheHomepageIsBlocked(newVal) {
                localMKData.setBOnlyTheHomepageIsBlocked(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="http://greasyfork.icu/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;
                });
                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 regexMatch = (ruleList, value) => {
        if (ruleList === null || ruleList === undefined) return null;
        if (!Array.isArray(ruleList)) return null
        value = value.toLowerCase();
        value = value.split(/[\t\r\f\n\s]*/g).join("");
        const find = ruleList.find(item => {
            try {
                return value.search(item) !== -1;
            } catch (e) {
                const msg = `正则匹配失败,请检查规则列表中的正则表达式是否正确,错误信息:${e.message}`;
                eventEmitter.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;
                        }
                        ruleUtil.addRule(uid, "precise_uid").then(msg => {
                            eventEmitter.send('el-msg', msg);
                            data.maskingFunc();
                        }).catch((msg) => {
                            eventEmitter.send('el-alert', msg);
                        });
                        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;
            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();
                Qmsg.error("获取视频信息失败");
            }
        }
        return list
    };
    const getVideoData = (el) => {
        const title = el.querySelector(".bili-video-card__info--tit").title;
        const name = el.querySelector(".bili-video-card__info--author").textContent.trim();
        let nPlayCount = el.querySelector('.bili-video-card__stats--text')?.textContent.trim();
        nPlayCount = sFormatUtil.toPlayCountOrBulletChat(nPlayCount);
        let nBulletChat = el.querySelector('.bili-video-card__stats--text')?.textContent.trim();
        nBulletChat = sFormatUtil.toPlayCountOrBulletChat(nBulletChat);
        let nDuration = el.querySelector('.bili-video-card__stats__duration')?.textContent.trim();
        nDuration = sFormatUtil.timeStringToSeconds(nDuration);
        const userUrl = el.querySelector(".bili-video-card__info--owner").getAttribute("href");
        const uid = elUtil.getUrlUID(userUrl);
        return {
            title,
            name,
            uid,
            nPlayCount,
            nBulletChat,
            nDuration,
            userUrl
        }
    };
    const getHomeVideoELList = async () => {
        const elList = await elUtil.findElementsUntilFound(".container.is-version8>.bili-video-card");
        let list = [];
        for (let el of elList) {
            try {
                const tempData = getVideoData(el);
                const {userUrl} = tempData;
                if (!userUrl.includes("//space.bilibili.com/")) {
                    el?.remove();
                    const log = "遍历换一换视频列表下面列表时检测到异常内容,已将该元素移除";
                   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();
        console.log(list);
        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 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$3 = async (isWeekly = false) => {
        const list = await getVideDataList(isWeekly);
        for (let videoData of list) {
            if (shielding.shieldingVideoDecorated(videoData)) {
                continue;
            }
            eventEmitter.send('添加热门视频屏蔽按钮', {data: videoData, maskingFunc: startShieldingVideoList$3});
        }
    };
    var popularAll = {
        startShieldingVideoList: startShieldingVideoList$3
    };
    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$3 = 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$3();
        for (let videoData of list) {
            if (shielding.shieldingVideoDecorated(videoData)) {
                continue;
            }
            eventEmitter.send('添加热门视频屏蔽按钮', {data: videoData, maskingFunc: startShieldingRankVideoList});
        }
    };
    var popular = {
        isPopularHistory,
        isPopularAllPage,
        isGeneralPopularRank,
        isPopularWeeklyPage,
        startShieldingRankVideoList,
    };
    const isTopicDetailPage = (url) => {
        return url.includes("//www.bilibili.com/v/topic/detail/")
    };
    const getDataList$1 = async () => {
        const elList = await elUtil.findElementsUntilFound(".list__topic-card");
        const list = [];
        for (let el of elList) {
            const name = el.querySelector(".bili-dyn-title").textContent.trim();
            const uidEl = el.querySelector(".bili-dyn-item__following");
            const uid = parseInt(uidEl.getAttribute("data-mid"));
            const judgmentEl = el.querySelector(".bili-dyn-card-video__title");
            const data = {name, uid, el, judgmentVideo: judgmentEl !== null};
            if (judgmentEl !== null) {
                data.title = judgmentEl.textContent.trim();
                const videoUrl = el.querySelector(".bili-dyn-card-video").href;
                data.videoUrl = videoUrl;
                data.bv = elUtil.getUrlBV(videoUrl);
                data.insertionPositionEl = el.querySelector(".bili-dyn-content__orig");
                data.explicitSubjectEl = data.insertionPositionEl;
            } else {
                const dynTitle = el.querySelector(".dyn-card-opus__title");
                const contentTitle = dynTitle === null ? "" : dynTitle.textContent.trim();
                const contentBody = el.querySelector(".bili-rich-text>div").textContent.trim();
                data.insertionPositionEl = el.querySelector(".dyn-card-opus");
                data.explicitSubjectEl = data.insertionPositionEl;
                data.content = contentTitle + contentBody;
            }
            list.push(data);
        }
        return list;
    };
    const __shieldingVideo = (videoData) => {
        if (shielding.shieldingVideoDecorated(videoData)) {
            return;
        }
        shielding.addTopicDetailVideoBlockButton({data: videoData, maskingFunc: startShielding});
    };
    const __shieldingDynamic = (dynamicData) => {
        if (shielding.shieldingCommentDecorated(dynamicData)) {
            return;
        }
        shielding.addTopicDetailContentsBlockButton({data: dynamicData, maskingFunc: startShielding});
    };
    const startShielding = async () => {
        const list = await getDataList$1();
        const css = {width: "100%"};
        for (let data of list) {
            data.css = css;
            if (data.judgmentVideo) {
                __shieldingVideo(data);
            } else {
                __shieldingDynamic(data);
            }
        }
    };
    var topicDetail = {
        isTopicDetailPage,
        startShielding
    };
    const 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 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 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$2 = 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$2});
        }
    };
    const startDebounceShieldingVideoList = defUtil.debounce(startShieldingVideoList$2, 1000);
    const findTheExpandButtonForTheListOnTheRightAndBindTheEvent = () => {
        elUtil.findElementsAndBindEvents(".rec-footer", startDebounceShieldingVideoList);
    };
    var videoPlayWatchLater = {
        isVideoPlayWatchLaterPage,
        startDebounceShieldingVideoList,
        findTheExpandButtonForTheListOnTheRightAndBindTheEvent
    };
    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 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$1 = async () => {
        const list = await getVideoList();
        for (let videoData of list) {
            if (shielding.shieldingVideoDecorated(videoData)) {
                continue
            }
            eventEmitter.send('视频添加屏蔽按钮', {data: videoData, maskingFunc: startShieldingVideoList$1});
        }
    };
    const intervalExecutionStartShieldingVideo$2 = () => {
        const res = shielding.intervalExecutionStartShieldingVideoInert(startShieldingVideoList$1, '视频');
        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=')) {
            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$2 = 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 = async () => {
        const list = await getVideoDataList$2();
        for (let videoData of list) {
            if (shielding.shieldingVideoDecorated(videoData)) {
                continue;
            }
            shielding.addBlockButton({data: videoData, maskingFunc: startShieldingVideoList}, "gz_shielding_button");
        }
    };
    const intervalExecutionStartShieldingVideo$1 = () => {
        const res = shielding.intervalExecutionStartShieldingVideoInert(startShieldingVideoList, '历史记录项');
        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 isOldHistory = (url) => {
        return url.includes('https://www.bilibili.com/account/history')
    };
    const getVideoDataList$1 = 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$1();
        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 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 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 = 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()
        }
        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();
        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 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 bOnlyTheHomepageIsBlocked$1 = localMKData.getBOnlyTheHomepageIsBlocked();
    const adaptationBAppCommerce = localMKData.getAdaptationBAppCommerce();
    const compatible_BEWLY_BEWLY$1 = localMKData.isCompatible_BEWLY_BEWLY();
    const staticRoute = (title, url) => {
        console.log("静态路由", title, url);
        topInput.processTopInputContent();
        if (compatible_BEWLY_BEWLY$1 && compatibleBewlyBewly.isBEWLYPage(url)) {
            compatibleBewlyBewly.startRun(url);
            return;
        }
        hotSearch.startShieldingHotList();
        if (bilibiliHome.isHome(url, title)) {
            if (compatible_BEWLY_BEWLY$1) {
                return;
            }
            if (adaptationBAppCommerce) {
                bilibiliHome.startIntervalShieldingGateVideoList();
            }
            bilibiliHome.scrollMouseUpAndDown().then(() => bilibiliHome.startDebounceShieldingChangeVideoList());
            bilibiliHome.startClearExcessContentList();
            bilibiliHome.deDesktopDownloadTipEl();
            bilibiliHome.startDebounceShieldingHomeVideoList();
        }
        if (bOnlyTheHomepageIsBlocked$1) return;
        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.startShieldingVideoList();
            videoPlayModel.findTheExpandButtonForTheListOnTheRightAndBindTheEvent();
            videoPlayModel.setVideoPlayerEnded();
            videoPlayModel.delElManagement();
        }
        if (collectionVideoPlayPageModel.iscCollectionVideoPlayPage(url)) {
            collectionVideoPlayPageModel.startShieldingVideoList();
            collectionVideoPlayPageModel.findTheExpandButtonForTheListOnTheRightAndBindTheEvent();
        }
        if (liveRoomModel.isLiveRoom(url)) {
            liveRoomModel.addWatchLiveRoomChatItemsListener();
        }
        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();
            videoPlayWatchLater.findTheExpandButtonForTheListOnTheRightAndBindTheEvent();
        }
        if (liveSectionModel.isLiveSection(url)) {
            liveSectionModel.startShieldingLiveRoom();
        }
        if (liveHome.isLiveHomePage(url)) {
            liveHome.startShieldingLiveRoom();
            liveHome.startShieldingTopLiveRoom();
        }
        if (newHistory.isNewHistoryPage(url)) {
            newHistory.startRun();
        }
        if (oldHistory.isOldHistory(url)) {
            oldHistory.intervalExecutionStartShieldingVideo();
        }
        if (partition.isPartition(url)) {
            partition.startIntervalShieldingVideoList();
        }
        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$1) return;
        if (searchModel.isSearch(url)) {
            searchModel.startShieldingVideoList();
        }
        if (videoPlayModel.isVideoPlayPage(url)) {
            videoPlayModel.startShieldingVideoList();
        }
        if (popular.isPopularAllPage(url) || popular.isPopularHistory(url)) {
            popularAll.startShieldingVideoList();
        }
        if (popular.isPopularWeeklyPage(url)) {
            popularAll.startShieldingVideoList(true);
        }
        if (popular.isGeneralPopularRank(url)) {
            popular.startShieldingRankVideoList();
        }
        if (dynamic.isDynamicPage(url)) {
            dynamic.startThrottleShieldingDynamicContent();
        }
    };
    var router = {
        staticRoute,
        dynamicRouting
    };
    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 bOnlyTheHomepageIsBlocked = localMKData.getBOnlyTheHomepageIsBlocked();
    const compatible_BEWLY_BEWLY = localMKData.isCompatible_BEWLY_BEWLY();
    const observeNetwork = (url, windowUrl, winTitle, initiatorType) => {
        if (!url.includes('api')) {
            return;
        }
        if (bOnlyTheHomepageIsBlocked) {
            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(() => {
                        ruleUtil.addRulePreciseUid(uid);
                    });
                    return
                }
                if (item === '移除屏蔽uid') {
                    this.$message('暂未完善');
                    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
    };
    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);