哔哩哔哩屏蔽增强器

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

// ==UserScript==
// @name        哔哩哔哩屏蔽增强器
// @namespace   http://tampermonkey.net/
// @license     Apache-2.0
// @version     2.0
// @author      byhgz
// @description 对B站视频或评论进行屏蔽,支持关键词模糊正则等,支持时长播放弹幕过滤等,如视频、评论、动态、直播间的评论等,详情可看下面支持的屏蔽类型
// @icon        https://static.hdslb.com/images/favicon.ico
// @noframes
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_deleteValue
// @grant       GM_addStyle
// @grant       GM_unregisterMenuCommand
// @grant       GM_registerMenuCommand
// @exclude     *://message.bilibili.com/pages/nav/header_sync
// @exclude     *://message.bilibili.com/pages/nav/index_new_pc_sync
// @exclude     *://live.bilibili.com/blackboard/dropdown-menu.html
// @exclude     *://live.bilibili.com/p/html/live-web-mng/*
// @exclude     *://www.bilibili.com/correspond/*
// @match       *://search.bilibili.com/*
// @match       *://www.bilibili.com/v/food/*
// @match       *://message.bilibili.com/*
// @match       *://www.bilibili.com/read/*
// @match       *://www.bilibili.com/v/topic/detail/?topic_id=*
// @match       *://www.bilibili.com/v/kichiku/*
// @match       *://t.bilibili.com/*
// @match       *://space.bilibili.com/*
// @match       *://www.bilibili.com/video/*
// @match       *://live.bilibili.com/?spm_id_from=*
// @match       *://live.bilibili.com/p/eden/area-tags?*
// @match       *://live.bilibili.com/*
// @match       *://www.bilibili.com/opus/*
// @match       *://www.bilibili.com/*
// @require     https://cdn.jsdelivr.net/npm/vue@2
// @require     https://update.greasyfork.org/scripts/517928/gz_ui_css-v1.js
// @require     https://update.greasyfork.org/scripts/521941/about_and_feedback_components.js
// @require     https://greasyfork.org/scripts/462234-message/code/Message.js
// @require     https://update.greasyfork.org/scripts/449512/Xtiper.js
// @require     https://update.greasyfork.org/scripts/516282/Drawer_gz%E9%A1%B5%E9%9D%A2%E4%BE%A7%E8%BE%B9%E6%8A%BD%E5%B1%89%E7%BB%84%E4%BB%B6.js
// @require     https://update.greasyfork.org/scripts/517538/DynamicTabs_gz.js
// ==/UserScript==
"use strict";
(function (Vue) {
    '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);
        },
    };
    const setBorderColor = (color) => {
        gmUtil.setData("borderColor", color);
    };
    const defBorderColor="rgb(0, 243, 255)";
    const getBorderColor = () => {
        return gmUtil.getData("borderColor", defBorderColor)
    };
    const setOutputInformationFontColor = (color) => {
        gmUtil.setData("output_information_font_color", color);
    };
    const defOutputInformationFontColor="rgb(119,128,248)";
    const getOutputInformationFontColor = () => {
        return gmUtil.getData("output_information_font_color", defOutputInformationFontColor)
    };
    const setHighlightInformationColor = (color) => {
        gmUtil.setData("highlight_information_color", color);
    };
    const defHighlightInformationColor="rgb(234, 93, 93)";
    const getHighlightInformationColor = () => {
        return gmUtil.getData("highlight_information_color", defHighlightInformationColor);
    };
    const setDefaultColorInfo=()=>{
        setBorderColor(defBorderColor);
        setOutputInformationFontColor(defOutputInformationFontColor);
        setHighlightInformationColor(defHighlightInformationColor);
    };
    const setBOnlyTheHomepageIsBlocked = (bool) => {
        gmUtil.setData("bOnlyTheHomepageIsBlocked", bool === true);
    };
    const getBOnlyTheHomepageIsBlocked = () => {
        return gmUtil.getData("bOnlyTheHomepageIsBlocked", false);
    };
    const getAdaptationBAppCommerce = () => {
        return gmUtil.getData("adaptation-b-app-recommend", false) === true;
    };
    const setAdaptationBAppCommerce = (bool) => {
        gmUtil.setData("adaptation-b-app-recommend", bool === true);
    };
    const isHideMainButSwitch=()=>{
        return gmUtil.getData("hideMainButSwitch", false) === true;
    };
    const setHideMainButSwitch=(bool)=>{
        gmUtil.setData("hideMainButSwitch", bool === true);
    };
    const isCompatible_BEWLY_BEWLY=()=>{
        return gmUtil.getData("compatible_BEWLY_BEWLY", false) === true;
    };
    const setCompatible_BEWLY_BEWLY=(bool)=>{
        gmUtil.setData("compatible_BEWLY_BEWLY", bool === true);
    };
    var localMKData = {
        setBorderColor,
        getBorderColor,
        setOutputInformationFontColor,
        getOutputInformationFontColor,
        setHighlightInformationColor,
        getHighlightInformationColor,
        setBOnlyTheHomepageIsBlocked,
        getBOnlyTheHomepageIsBlocked,
        getAdaptationBAppCommerce,
        setAdaptationBAppCommerce,
        setDefaultColorInfo,
        isHideMainButSwitch,
        setHideMainButSwitch,
        isCompatible_BEWLY_BEWLY,
        setCompatible_BEWLY_BEWLY
    };
    const mainDrawer = new Drawer_gz({
        show: false,
        height: "50vh",
        headerShow: false,
        title: "屏蔽器主面板",
        direction: "top",
        externalButtonText: "屏蔽器",
        externalButtonWidth: "80px",
        externalButtonShow: !localMKData.isHideMainButSwitch(),
        zIndex: 9000,
        drawerBorder: `1px solid ${localMKData.getBorderColor()}`,
        bodyHtml: `<div id="shield"></div>`,
    });
    const options = {
        styles: `
                .my-custom-tab-button {
                    font-size: 16px;
                }
                .my-custom-tab-content {
                    background-color: #f9f9f9;
                }
            `,
        classes: {
            tabButton: 'my-custom-tab-button',
            tabButtonActive: 'my-custom-tab-button-active',
            tabContent: 'my-custom-tab-content',
            tabContentActive: 'my-custom-tab-content-active'
        },
        backgroundColor: '#eee',
        borderColor: '#ddd',
        textColor: '#333',
        fontWeight: 'bold',
        activeBackgroundColor: '#0056b3',
        activeTextColor: '#fff',
        contentBorderColor: '#bbb',
        contentBackgroundColor: '#ffffff',
        onTabClick: (id, title, content) => {
            const tab = tabsConfig.find(item => item.title === title);
            const height = tab.height;
            mainDrawer.setHeight(height ? height : '50vh');
        },
    };
    const tabsConfig = [
        {
            id: 'tab01',
            title: '面板设置',
            content: '<div id="panel_settings_vue"></div>',
            height: "23vh",
        },
        {
            id: 'tab02',
            title: '规则管理',
            content: '<div id="rule_management_vue"></div>',
            height: "96vh"
        },
        {
            id: 'tab03',
            title: '其他参数过滤',
            content: `<div id="other_parameter_filter"></div>`,
        },
        {
            id:'id04',
            title: '兼容设置',
            content: `<div id="compatible_setting"></div>`,
        },
        {
            id: 'tab05',
            title: '输出信息',
            content: `<div id="output_information">
<button gz_type>清空消息</button>
<ol class="info">
</ol>
</div>`,
            height: "96vh"
        },
        {
            id: 'tab06',
            title: '支持打赏',
            content: '<div id="station_b_shield_donate"></div>',
            height: "80vh"
        },
        {
            id: 'tab07',
            title: '关于和问题反馈',
            content: `<div id="station_b_shield_problem_feedback"></div>`,
            height: '53vh'
        }
    ];
    new DynamicTabs_gz('#shield', tabsConfig,
        options
    );
    const returnVue$4 = () => {
        return new Vue({
            template: `
          <div>
            <div>
              选色器:<input type="color" v-model="input_color">
            </div>
            <button gz_type @click="setBorderColorBut">设置边框色</button>
            <button gz_type @click="setDefFontColorForOutputInformationBut">设置输出信息默认字体色</button>
            <button gz_type @click="setTheFontColorForOutputInformationBut">设置输出信息高亮字体色</button>
            <button title="刷新页面生效" gz_type @click="setDefInfoBut">恢复默认</button>
            <hr>
            <label>
              <input type="checkbox" v-model="hideMainButSwitch">隐藏主面板开关按钮
            </label>
            <hr>
            <div>
              <h4>说明</h4>
              <ol>
                <li>按键盘tab键上的~键为展开关闭主面板</li>
              </ol>
            </div>
          </div>`,
            el: '#shield #panel_settings_vue',
            data() {
                return {
                    input_color: "",
                    hideMainButSwitch: localMKData.isHideMainButSwitch()
                }
            },
            methods: {
                setBorderColorBut() {
                    console.log(this.input_color);
                    xtip.confirm("是要否设置面板边框颜色吗?", {
                        icon: "a",
                        btn1: () => {
                            localMKData.setBorderColor(this.input_color);
                            xtip.alert("已设置面板边框颜色,刷新生效");
                        }
                    });
                },
                setDefFontColorForOutputInformationBut() {
                    xtip.confirm("是要否设置输出信息默认字体颜色吗?", {
                        icon: "a",
                        btn1: () => {
                            localMKData.setOutputInformationFontColor(this.input_color);
                            xtip.alert("已设置输出信息默认字体颜色,刷新生效");
                        }
                    });
                },
                setTheFontColorForOutputInformationBut() {
                    xtip.confirm("是要否设置输出信息高亮字体颜色吗?", {
                        icon: "a",
                        btn1: () => {
                            localMKData.setHighlightInformationColor(this.input_color);
                            xtip.alert("已设置输出信息高亮字体颜色,刷新生效");
                        }
                    });
                },
                setDefInfoBut() {
                    localMKData.setDefaultColorInfo();
                    xtip.alert("已恢复默认颜色,刷新生效");
                }
            },
            watch: {
                hideMainButSwitch(newVal) {
                    localMKData.setHideMainButSwitch(newVal);
                    mainDrawer.externalButtonShow(!newVal);
                }
            }
        });
    };
    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 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
        };
    };
    var defUtil = {
        wait,
        fileDownload,
        toTimeString,
        smoothScroll,
        debounce,
        debounceAsync,
        throttle,
        throttleAsync,
        parseUrl
    };
    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: "直播分区黑名单(精确匹配)"
        }
    ];
    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", []);
    };
    var ruleKeyListData$1 = {
        getNameArr,
        getPreciseNameArr,
        getNameCanonical,
        getPreciseUidArr,
        getPreciseUidWhiteArr,
        getTitleArr,
        getTitleCanonicalArr,
        getCommentOnArr,
        getCommentOnCanonicalArr,
        getRuleKeyListData,
        getPreciseTagArr,
        getTagArr,
        getTagCanonicalArr,
        getPreciseFanCardArr,
        getPrecisePartitionArr
    };
    const verificationInputValue = (ruleValue, type) => {
        if (ruleValue === null) return null;
        if (type === "precise_uid" || type === "precise_uid_white") {
            ruleValue = parseInt(ruleValue);
            if (isNaN(ruleValue)) {
                Qmsg.info('请输入数字!');
                return null;
            }
        } else {
            ruleValue.trim();
        }
        if (ruleValue === '') {
            Qmsg.info('内容为空');
            return null;
        }
        return ruleValue;
    };
    const addRule = (ruleValue, type) => {
        const inputValue = verificationInputValue(ruleValue, type);
        return new Promise((resolve, reject) => {
                if (inputValue === null) {
                    reject('取消添加');
                    return;
                }
                const arr = gmUtil.getData(type, []);
                if (arr.includes(inputValue)) {
                    reject('已存在此内容');
                    return;
                }
                arr.push(inputValue);
                gmUtil.setData(type, arr);
                resolve('添加成功');
            }
        )
    };
    const showAddRuleInput = (type) => {
        const ruleValue = window.prompt('请输入要添加的规则内容', '');
        return addRule(ruleValue, type);
    };
    const showDelRuleInput = (type) => {
        let prompt = window.prompt('请输入要移除的规则内容', '');
        const inputValue = verificationInputValue(prompt, type);
        return new Promise((resolve, reject) => {
            if (inputValue === null) {
                reject('取消添加');
                return;
            }
            const arr = gmUtil.getData(type, []);
            const indexOf = arr.indexOf(inputValue);
            if (indexOf === -1) {
                reject('不存在此内容');
                return;
            }
            arr.splice(indexOf, 1);
            gmUtil.setData(type, arr);
            resolve('移除成功');
        })
    };
    const showSetRuleInput = (type) => {
        let prompt = window.prompt('请输入要修改的规则内容', '');
        const inputValue = verificationInputValue(prompt, type);
        return new Promise((resolve, reject) => {
            if (inputValue === null) return;
            const arr = gmUtil.getData(type, []);
            const indexOf = arr.indexOf(inputValue);
            if (indexOf === -1) {
                reject('不存在此内容');
                return;
            }
            prompt = window.prompt('请输入要修改的内容', '');
            const newInputValue = verificationInputValue(prompt, type);
            if (newInputValue === null) return;
            if (arr.includes(newInputValue)) {
                reject('已存在要修改过后的值内容');
                return;
            }
            arr[indexOf] = newInputValue;
            gmUtil.setData(type, arr);
            resolve('修改成功');
        })
    };
    const getRuleContent = (space = 0) => {
        const ruleMap = {};
        for (let ruleKeyListDatum of ruleKeyListData$1.getRuleKeyListData()) {
            const key = ruleKeyListDatum.key;
            ruleMap[key] = gmUtil.getData(key, []);
        }
        return JSON.stringify(ruleMap, null, space);
    };
    const verificationRuleMap = (keyArr, content) => {
        let parse;
        try {
            parse = JSON.parse(content);
        } catch (e) {
            alert('规则内容有误');
            return false;
        }
        const newRule = {};
        for (let key of keyArr) {
            if (!Array.isArray(parse[key])) {
                continue;
            }
            if (parse[key].length === 0) {
                continue;
            }
            newRule[key] = parse[key];
        }
        if (Object.keys(newRule).length === 0) {
            alert('规则内容为空');
            return false;
        }
        return newRule;
    };
    const overwriteImportRules = (keyArr, content) => {
        const map = verificationRuleMap(keyArr, content);
        if (map === false) return false;
        for (let key of Object.keys(map)) {
            gmUtil.setData(key, map[key]);
        }
        return true;
    };
    const appendImportRules = (keyArr, content) => {
        const map = verificationRuleMap(keyArr, content);
        if (map === false) return false;
        for (let key of Object.keys(map)) {
            const arr = gmUtil.getData(key, []);
            for (let item of map[key]) {
                if (!arr.includes(item)) {
                    arr.push(item);
                }
            }
            gmUtil.setData(key, arr);
        }
        return true;
    };
    const getNewRuleKeyList = () => {
        return ruleKeyListData$1.getRuleKeyListData();
    };
    const overwriteImportRulesV1 = (content) => {
        let parse;
        try {
            parse = JSON.parse(content);
        } catch (e) {
            alert('规则内容有误');
            return false;
        }
        for (let ruleKeyListDatum of ruleKeyListData$1.getRuleKeyListData()) {
            const name = ruleKeyListDatum.oldName;
            const jsonRuleList = parse[name];
            if (!jsonRuleList) {
                continue;
            }
            if (jsonRuleList.length === 0) {
                continue;
            }
            gmUtil.setData(ruleKeyListDatum.key, jsonRuleList);
        }
        return true;
    };
    var ruleUtil = {
        addRule,
        showAddRuleInput,
        showDelRuleInput,
        showSetRuleInput,
        getRuleContent,
        overwriteImportRules,
        appendImportRules,
        overwriteImportRulesV1,
        getNewRuleKeyList,
    };
    const returnVue$3 = () => {
        return new Vue({
            template: `
          <div style="display: flex">
            <div style="width: 84%;" gz_bezel>
              <h4>使用说明</h4>
              <ol>
                <li>脚本中会对要匹配的内容进行去除空格和转成小写,比如有个内容是【不 要 笑 挑 战
                  ChallEnGE】,会被识别称为【不要笑挑战challenge】
                </li>
                <li>在上述一点的情况下,模糊匹配和正则匹配的方式时不用考虑要匹配的内容中大写问题</li>
                <li>大部分情况下模糊匹配比精确匹配好用</li>
                <li>如果用户要添加自己的正则匹配相关的规则时,建议先去该网址进行测试再添加,避免浪费时间
                  <a href="https://www.jyshare.com/front-end/854/" target="_blank">>>>正则表达式在线测试<<<</a>
                </li>
              </ol>
              <div>
<!--                <h3>指定类型批量添加</h3>-->
<!--                <span>指定类型批量添加,每个规则空格分割</span>-->
<!--                <textarea-->
<!--                    style="width: 100%"-->
<!--                    cols="30" rows="5" placeholder="匹配添加内容时规则内容" v-model="inputVal"/>-->
              </div>
              <div>
                <label>
                  <input type="checkbox" v-model="bOnlyTheHomepageIsBlocked">仅首页屏蔽生效屏蔽
                </label>
              </div>
              <div>
                <select v-model="selectVal">
                  <option v-for="item in ruleInfoArr" :value="item.type">{{ item.name }}</option>
                </select>
                《====可点击切换条件
              </div>
              <button gz_type @click="operationBut('add')">添加{{ selectText }}</button>
              <button gz_type @click="operationBut('del')">移除{{ selectText }}</button>
              <button gz_type="info" @click="operationBut('del_all')">全部移除</button>
              <button gz_type @click="operationBut('set')">移除{{ selectText }}</button>
              <div>
                <h2>导出规则</h2>
                <button gz_type @click="ruleOutToFIleBut">导出到文件</button>
                <button gz_type>导出到编辑框</button>
                <button gz_type @click="ruleOutToConsoleBut">导出到控制台</button>
              </div>
              <hr>
              <div>
                <h2>导入规则</h2>
                <div style="display: flex;justify-content:space-between;">
                  <ol>
                    <li>规则内容请在下面编辑框中导入</li>
                    <li>旧版本的需要使用下面的v1旧版本导入规则</li>
                    <li>旧版本的只能覆盖导入</li>
                    <li>v1之后的版本可以选择覆盖和追加</li>
                  </ol>
                  <ol>
                    <li v-for="item in ruleReference">
                      <button gz_type='info' @click="xtipAlertBut(item.content,item.title)">
                        {{ item.title }}
                      </button>
                    </li>
                  </ol>
                </div>
                <button gz_type @click="overwriteImportRulesBut">覆盖导入规则</button>
                <button gz_type @click="appendImportRulesBut">追加导入规则</button>
                <button gz_type @click="overwriteImportRulesV1But">v1旧版本覆盖导入规则</button>
                <div>
                  <textarea cols="30" rows="10" placeholder="要导入的规则内容" style="width: 100%"
                            v-model="ruleContentImport"></textarea>
                </div>
              </div>
            </div>
            <div style="width: 15%;" gz_bezel>
              <h2>规则信息</h2>
              <button gz_type @click="refreshInfoBut">刷新信息</button>
              <div v-for="item in ruleInfoArr">{{ item.name }}
                <button gz_type>{{ item.len }}</button>
                个
              </div>
            </div>
          </div>`,
            el: '#shield #rule_management_vue',
            data() {
                return {
                    selectVal: 'name',
                    selectText: "",
                    ruleContentImport: "",
                    ruleActions: [
                        {
                            type: "uid",
                            name: "uid(精确)",
                        }
                    ],
                    ruleKeyArr: [],
                    ruleInfoArr: [],
                    ruleReference: [
                        {
                            title: "旧版本规则参考",
                            content: ` {"用户名黑名单模式(精确匹配)":["账号已注销"],"BV号黑名单模式(精确匹配)":[],
                        "用户名黑名单模式(模糊匹配)":["bili_","_bili"],"用户uid黑名单模式(精确匹配)":[442010132,76525078,225219967,3493283164588093],
                        "用户uid白名单模式(精确匹配)":[344490740,1861980711],"标题黑名单模式(模糊匹配)":["激励计划","蚌不住","手游激励","游戏活动打卡"],
                        "标题黑名单模式(正则匹配)":["感觉.*不如","不要笑.*挑战"],"评论关键词黑名单模式(模糊匹配)":["感觉不如","差不多的了"],
                        "评论关键词黑名单模式(正则匹配)":["这不.+吗","玩.*的","不要笑.*挑战"],"粉丝牌黑名单模式(精确匹配)":[],
                        "专栏关键词内容黑名单模式(模糊匹配)":[],"动态关键词内容黑名单模式(模糊匹配)":["拼多多","京东红包","京东618红包","618活动"]}`
                        },
                        {
                            title: "新版本规则参考",
                            content: "待补充"
                        }
                    ],
                    bOnlyTheHomepageIsBlocked: localMKData.getBOnlyTheHomepageIsBlocked()
                }
            },
            methods: {
                operationBut(model) {
                    debugger
                    const type = this.selectVal;
                    if (model === "add") {
                        ruleUtil.showAddRuleInput(type).then((msg) => {
                            this.refreshInfoBut();
                            alert(msg);
                        }).catch(errMsg => {
                            Qmsg.info(errMsg);
                        });
                    }
                    if (model === "del") {
                        ruleUtil.showDelRuleInput(type).then((msg) => {
                            this.refreshInfoBut();
                            alert(msg);
                        }).catch(errMsg => {
                            Qmsg.info(errMsg);
                        });
                    }
                    if (model === "set") {
                        ruleUtil.showSetRuleInput(type).then((msg) => {
                            this.refreshInfoBut();
                            alert(msg);
                        }).catch(errMsg => {
                            Qmsg.info(errMsg);
                        });
                    }
                    if (model === "del_all") {
                        if (!window.confirm("确定要删除所有规则吗?")) {
                            Qmsg.info('取消删除全部操作');
                            return;
                        }
                        for (let x of this.ruleKeyArr) {
                            gmUtil.delData(x);
                        }
                        alert("删除全部规则成功");
                        this.refreshInfoBut();
                    }
                },
                ruleOutToFIleBut() {
                    const ruleContent = ruleUtil.getRuleContent(4);
                    let fileName = "b站屏蔽器规则-" + defUtil.toTimeString();
                    const s = prompt("保存为", fileName);
                    if (s === null) return;
                    if (!(s.includes(" ") || s === "" || s.length === 0)) fileName = s;
                    defUtil.fileDownload(ruleContent, fileName + ".json");
                },
                ruleOutToConsoleBut() {
                    xtip.msg('已导出到控制台上!', {icon: 's'});
                    console.log(ruleUtil.getRuleContent());
                },
                refreshInfoBut() {
                    for (let x of this.ruleInfoArr) {
                        x.len = gmUtil.getData(x.type, []).length;
                    }
                    Qmsg.info('已刷新规则信息');
                },
                overwriteImportRulesBut() {
                    const trim = this.ruleContentImport.trim();
                    if (ruleUtil.overwriteImportRules(this.ruleKeyArr, trim)) {
                        xtip.msg('已导入成功!', {icon: 's'});
                        this.refreshInfoBut();
                    }
                },
                appendImportRulesBut() {
                    const trim = this.ruleContentImport.trim();
                    if (ruleUtil.appendImportRules(this.ruleKeyArr, trim)) {
                        xtip.msg('已导入成功!', {icon: 's'});
                        this.refreshInfoBut();
                    }
                },
                overwriteImportRulesV1But() {
                    const trim = this.ruleContentImport.trim();
                    if (ruleUtil.overwriteImportRulesV1(trim)) {
                        xtip.msg('已导入成功!', {icon: 's'});
                        this.refreshInfoBut();
                    }
                },
                xtipAlertBut(content, title) {
                    xtip.alert(content,
                        {title: title});
                }
            },
            watch: {
                bOnlyTheHomepageIsBlocked(newVal) {
                    localMKData.setBOnlyTheHomepageIsBlocked(newVal);
                },
                selectVal(newVal) {
                    console.log(newVal);
                    const find = this.ruleInfoArr.find(item => item.type === newVal);
                    this.selectText = find.name;
                }
            },
            created() {
                for (let newRuleKeyListElement of ruleUtil.getNewRuleKeyList()) {
                    this.ruleKeyArr.push(newRuleKeyListElement.key);
                    this.ruleInfoArr.push({
                        type: newRuleKeyListElement.key,
                        name: newRuleKeyListElement.name,
                        len: 0
                    });
                }
                const find = this.ruleInfoArr.find(item => item.type === this.selectVal);
                this.selectText = find.name;
                this.refreshInfoBut();
            }
        });
    };
    const returnVue$2 = () => {
        return new Vue({
            el: "#station_b_shield_donate",
            template: `<div>
          <div style="border: 3px solid #000;">
            <div style="display: flex;align-items: center;">
              <h2>零钱赞助</h2>
              <ul>
                <li>1元不嫌少,10元不嫌多哦!感谢支持!</li>
                <li>生活不易,作者叹息</li>
                <li>您的支持是我最大的更新动力</li>
              </ul>
            </div>
            <hr>
            <div style="display: flex;justify-content: center;">
              <div v-for="item in list" :title="item.name"><img :src="item.src" :alt="item.alt"
                                                                style="max-height: 500px;">
                <span style="display: flex;justify-content: center;">{{ item.name }}</span>
              </div>
            </div>
            <hr>
            <h1 style=" display: flex; justify-content: center;">打赏点猫粮</h1>
          </div>
        </div>`,
            data: {
                list: [
                    {
                        name: "支付宝赞助",
                        alt: "支付宝支持",
                        src: "https://www.mikuchase.ltd/img/paymentCodeZFB.webp"
                    },
                    {name: "微信赞助", alt: "微信支持", src: "https://www.mikuchase.ltd/img/paymentCodeWX.webp"},
                    {name: "QQ赞助", alt: "QQ支持", src: "https://www.mikuchase.ltd/img/paymentCodeQQ.webp"},
                ]
            }
        });
    };
    const returnVue$1 = () => {
        return new Vue({
            el: '#other_parameter_filter',
            template: `
          <div style="display: flex">
            <div style="width: 70vw">
              <div>
                <h2>使用说明</h2>
                <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>
              </div>
              <input 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>
              <button @click="updateInfoBut">刷新</button>
              <div v-for="item in selectList">
                {{ item.name }}
                <button gz_type>{{ item.defVal }}</button>
                {{ item.name.includes('时长') ? '秒' : '' }}
              </div>
            </div>
          </div>`,
            data() {
                return {
                    index: 0,
                    selectList: [
                        {
                            name: '最小播放量',
                            value: 'nMinimumPlay',
                            associated: 'nMaximumPlayback',
                            defVal: -1
                        },
                        {
                            name: '最大播放量',
                            value: 'nMaximumPlayback',
                            associated: 'nMinimumPlay',
                            bLarge: true,
                            defVal: -1
                        },
                        {
                            name: '最小弹幕数',
                            value: 'nMinimumBarrage',
                            associated: 'nMaximumBarrage',
                            defVal: -1
                        },
                        {
                            name: '最大弹幕数',
                            value: 'nMaximumBarrage',
                            associated: 'nMinimumBarrage',
                            bLarge: true,
                            defVal: -1
                        },
                        {
                            name: '最小时长',
                            value: 'nMinimumDuration',
                            associated: 'nMaximumDuration',
                            defVal: -1
                        },
                        {
                            name: '最大时长',
                            value: 'nMaximumDuration',
                            associated: 'nMinimumDuration',
                            bLarge: true,
                            defVal: -1
                        },
                        {
                            name: '评论区最小用户等级过滤',
                            value: 'nMinimumLevel',
                            associated: 'nMaximumLevel',
                            defVal: -1
                        },
                        {
                            name: '评论区最大用户等级过滤',
                            value: 'nMaximumLevel',
                            associated: 'nMinimumLevel',
                            bLarge: true,
                            defVal: -1
                        }
                    ],
                    selectValue: 'nMinimumPlay',
                    inputMax: '',
                    inputMin: '0'
                }
            },
            methods: {
                okVideoSelectBut() {
                    const find = this.selectList.find(item => item.value === this.selectValue);
                    const associatedVal = gmUtil.getData(find.associated, -1);
                    const associatedFind = this.selectList.find(item => item.value === find.associated);
                    if (this.index > associatedVal && associatedVal !== -1) {
                        if (associatedFind.bLarge) {
                            xtip.alert(`要设置的${find.name}值不能大于${associatedFind.name}的值`);
                            return
                        }
                        console.log('正常修改');
                    }
                    xtip.alert(`已设置${find.name},值为${this.index}`);
                    gmUtil.setData(this.selectValue, this.index);
                    this.updateInfo();
                },
                cancelBut() {
                    gmUtil.setData(this.selectValue, -1);
                    const find = this.selectList.find(item => item.value === this.selectValue);
                    xtip.alert(`已取消${find.name}的限制`);
                    this.updateInfo();
                },
                allCancelBut() {
                    for (let item of this.selectList) {
                        gmUtil.setData(item.value, -1);
                    }
                    this.updateInfo();
                },
                updateInfo() {
                    for (let item of this.selectList) {
                        item.defVal = gmUtil.getData(item.value, -1);
                    }
                },
                updateInfoBut() {
                    this.updateInfo();
                    xtip.alert('已刷新');
                },
            },
            watch: {
                selectValue(newVal) {
                    const find = this.selectList.find(item => item.value === newVal);
                    if (find.name.includes('用户等级')) {
                        this.inputMin = 3;
                        this.inputMax = 6;
                        if (this.index > 6) {
                            this.index = 6;
                        }
                        if (this.index < 3) {
                            this.index = 3;
                        }
                    } else {
                        this.inputMin = 0;
                        this.inputMax = '';
                    }
                }
            },
            created() {
                this.updateInfo();
            }
        })
    };
    const returnVue = () => {
        return new Vue({
            el: "#shield #compatible_setting",
            template: `
          <div>
            <div>
              <label>
                <input type="checkbox" v-model="adaptationBAppRecommend">首页屏蔽适配Bilibili-Gate脚本(bilibili-app-recommend)
              </label>
            </div>
            <div>
              <label>
                <input type="checkbox" v-model="compatible_BEWLY_BEWLY">兼容BewlyBewly插件
              </label>
            </div>
          </div>`,
            data() {
                return {
                    adaptationBAppRecommend: localMKData.getAdaptationBAppCommerce(),
                    compatible_BEWLY_BEWLY: localMKData.isCompatible_BEWLY_BEWLY()
                }
            },
            watch:{
                adaptationBAppRecommend(newVal) {
                    localMKData.setAdaptationBAppCommerce(newVal);
                },
                compatible_BEWLY_BEWLY(newVal) {
                    localMKData.setCompatible_BEWLY_BEWLY(newVal);
                },
            }
        })
    };
    document.querySelector("#output_information button")?.addEventListener("click", () => {
        olEL.innerHTML = "";
        alert("已清空消息");
    });
    const olEL = document.querySelector("#output_information>.info");
    const addInfo = (content) => {
        const liEL = document.createElement("li");
        liEL.innerHTML = content;
        olEL.appendChild(liEL);
    };
    const outputInformationFontColor = localMKData.getOutputInformationFontColor();
    const highlightInformationColor = localMKData.getHighlightInformationColor();
    const getVideoInfoHtml = (type, matching, videoData) => {
        const toTimeString = defUtil.toTimeString();
        const {name, uid, title, videoUrl} = videoData;
        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>
            标题【<a href="${videoUrl}" target="_blank" style="color: ${highlightInformationColor}">${title}</a>】
            </b>`
    };
    const getCommentInfoHtml = (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 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 = {
        addInfo,
        getVideoInfoHtml,
        getCommentInfoHtml,
        getLiveRoomCommentInfoHtml,
        getDynamicContentInfoHtml,
        getLiveRoomInfoHtml
    };
    returnVue$4();
    returnVue$3();
    returnVue$2();
    returnVue$1();
    returnVue();
    installAboutAndFeedbackComponentsVue('#station_b_shield_problem_feedback',
        {
            title: 'B站屏蔽增强器',
            gfFeedbackUrl: 'https://greasyfork.org/zh-CN/scripts/461382'
        }
    );
    gmUtil.addStyle(`
[gz_bezel]{
border:1px solid ${localMKData.getBorderColor()}
}
`);
    const getUrlUID = (url) => {
        const isDoYouHaveAnyParameters = url.indexOf('?');
        const lastIndexOf = url.lastIndexOf("/");
        let uid;
        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 eventRegistry = new Map();
    function addEventListenerWithTracking(element, eventName, handler) {
        if (!eventRegistry.has(element)) {
            eventRegistry.set(element, new Map());
        }
        const elementEvents = eventRegistry.get(element);
        if (!elementEvents.has(eventName)) {
            elementEvents.set(eventName, new Set());
        }
        elementEvents.get(eventName).add(handler);
        element.addEventListener(eventName, handler);
    }
    function findElementUntilFound(selector, config = {}) {
        const defConfig = {doc: document, interval: 1000};
        config = {...defConfig, ...config};
        return new Promise((resolve) => {
            const i1 = setInterval(() => {
                const element = config.doc.querySelector(selector);
                if (element) {
                    resolve(element);
                    clearInterval(i1);
                }
            }, config.interval);
        });
    }
    function findElementsUntilFound(selector, config = {}) {
        const defConfig = {doc: document, interval: 1000};
        config = {...defConfig, ...config};
        return new Promise((resolve) => {
            function attemptToFind() {
                const elements = config.doc.querySelectorAll(selector);
                if (elements.length > 0) {
                    resolve(elements);
                } else {
                    setTimeout(attemptToFind, config.interval);
                }
            }
            attemptToFind();
        });
    }
    function findElementWithTimeout(selector, config = {}) {
        const defConfig = {
            doc: document,
            interval: 1000,
            timeout: 60000
        };
        config = {...defConfig, ...config};
        return new Promise((resolve) => {
            let intervalId;
            function attemptToFind() {
                const element = config.doc.querySelector(selector);
                if (element) {
                    clearInterval(intervalId);
                    resolve({
                        state: true,
                        msg: "已找到元素",
                        el: element
                    });
                }
            }
            intervalId = setInterval(attemptToFind, config.interval);
            const timeout = setTimeout(() => {
                clearInterval(intervalId);
                resolve({
                    state: false,
                    msg: "已超时:" + config.timeout
                }); // 超时后提示信息
                clearTimeout(timeout);
            }, config.timeout);
            attemptToFind(); // 立即尝试一次
        });
    }
    function findElementsWithTimeout(selector, config = {}) {
        const defConfig = {
            doc: document,
            interval: 1000,
            timeout: 60000
        };
        config = {...defConfig, ...config};
        return new Promise((resolve, reject) => {
            let timer;
            let intervalId;
            function attemptToFind() {
                const elements = config.doc.querySelectorAll(selector);
                if (elements.length > 0) {
                    clearTimeout(timer);
                    clearInterval(intervalId);
                    resolve(elements);
                }
            }
            intervalId = setInterval(attemptToFind, config.interval);
            timer = setTimeout(() => {
                clearInterval(intervalId);
                reject(null); // 超时后返回 null
            }, config.timeout);
            attemptToFind(); // 立即尝试一次
        });
    }
    const findElementsAndBindEvents = (css, callback, config = {}) => {
        config = {
            ...{
                interval: 2000,
                timeOut: 3000
            }, config
        };
        setTimeout(() => {
            findElementUntilFound(css, {interval: config.interval}).then((el) => {
                el.addEventListener("click", () => {
                    callback();
                });
            });
        }, config.timeOut);
    };
    var elUtil = {
        getUrlUID,
        addEventListenerWithTracking,
        findElementUntilFound,
        findElementWithTimeout,
        findElementsUntilFound,
        findElementsWithTimeout,
        findElementsAndBindEvents
    };
    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 => value.search(item) !== -1);
        return find===undefined ? null : find;
    };
    const fuzzyMatch = (ruleList, value) => {
        if (ruleList === null || ruleList === undefined) return null;
        if (!Array.isArray(ruleList)) return null
        const find = ruleList.find(item => value.includes(item));
        return find === undefined ? null : find;
    };
    var ruleMatchingUtil = {
        exactMatch,
        regexMatch,
        fuzzyMatch
    };
    const  Tip = {
        success(text, config) {
            Qmsg.success(text, config);
        },
        successBottomRight(text) {
            this.success(text, {position: "bottomright"});
        },
        videoBlock(text) {//屏蔽了视频的提示
            this.success(text, {position: "bottomright"});
        },
        info(text, config) {
            Qmsg.info(text, config);
        },
        infoBottomRight(text) {
            this.info(text, {position: "bottomright"});
        },
        error(text, config) {
            Qmsg.error(text, config);
        },
        errorBottomRight(text) {
            this.error(text, {position: "bottomright"});
        },
        warning(text, config) {
            Qmsg.warning(text, config);
        },
        config(cfg) {//设置全局Tip配置
            Qmsg.config(cfg);
        },
        loading(text, config) {
            return Qmsg.loading(text, config);
        },
        close(loading) {
            try {
                loading.close();
            } catch (e) {
                console.error(e);
                this.error("loading关闭失败!");
            }
        },
        printLn(content) {
            Util.printElement("#outputInfo", `<dd>${content}</dd>`);
        },
        printVideo(color, content, name, uid, title, videoHref) {
            Util.printElement("#outputInfo", `
        <dd><b
            style="color: ${color}; ">${Util.toTimeString()}${content}屏蔽用户【${name}】uid=<a href="https://space.bilibili.com/${uid}" target="_blank">【${uid}】</a>标题【<a href="${videoHref}" target="_blank">${title}</a>】</b>
        </dd>`);
        },
        printCommentOn(color, content, name, uid, primaryContent) {
            Util.printElement("#outputInfo", `
        <dd>
        <b  style="color: ${color}; ">${Util.toTimeString()}${content} 屏蔽用户【${name}】uid=<a href="https://space.bilibili.com/${uid}" target="_blank">【${uid}】</a>
   原言论=【${primaryContent}】</b>
</dd>`);
        }
    };
    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();
                data.videoUrl = el.querySelector(".bili-dyn-card-video").href;
                data.insertionPositionEl = el.querySelector(".bili-dyn-content__orig");
                data.explicitSubjectEl = data.insertionPositionEl;
            } else {
                const dynTitle = el.querySelector(".dyn-card-opus__title");
                const contentTitle = dynTitle === null ? "" : dynTitle.textContent.trim();
                const contentBody = el.querySelector(".bili-rich-text>div").textContent.trim();
                data.insertionPositionEl = el.querySelector(".dyn-card-opus");
                data.explicitSubjectEl = data.insertionPositionEl;
                data.content = contentTitle + contentBody;
            }
            list.push(data);
        }
        return list;
    };
    const __shieldingVideo = (videoData) => {
        if (shielding.shieldingVideoDecorated(videoData)) {
            return;
        }
        shielding.addTopicDetailVideoBlockButton({data: videoData, maskingFunc: startShielding});
    };
    const __shieldingDynamic = (dynamicData) => {
        if (shielding.shieldingCommentDecorated(dynamicData)) {
            return;
        }
        shielding.addTopicDetailContentsBlockButton({data: dynamicData, maskingFunc: startShielding});
    };
    const startShielding = async () => {
        const list = await getDataList$1();
        const css = {width: "100%"};
        for (let data of list) {
            data.css = css;
            if (data.judgmentVideo) {
                __shieldingVideo(data);
            } else {
                __shieldingDynamic(data);
            }
        }
    };
    var topicDetail = {
        isTopicDetailPage,
        startShielding
    };
    const getUrlUserLevel = (src) => {
        const levelMath = src?.match(/level_(.+)\.svg/) || null;
        let level = -1;
        if (levelMath !== null) {
            const levelRow = levelMath[1];
            if (levelRow === 'h') {
                level = 7;
            } else {
                level = parseInt(levelRow);
            }
        }
        return level;
    };
    const getOldUserLevel = (iEl) => {
        let level = -1;
        const levelCLassName = iEl.classList[1];
        if (levelCLassName === 'level-hardcore') {
            level = 7;
        } else {
            const levelMatch = levelCLassName.match(/level-(.+)/)?.[1] || '';
            level = parseInt(levelMatch);
        }
        return level
    };
    const getCommentSectionList = async () => {
        const commentApp = await elUtil.findElementUntilFound("bili-comments",
            {interval: 500});
        const comments = await elUtil.findElementsUntilFound("#feed>bili-comment-thread-renderer",
            {doc: commentApp.shadowRoot, interval: 500});
        const commentsData = [];
        let isLoaded = false;
        for (let el of comments) {
            const theOPEl = el.shadowRoot.getElementById("comment").shadowRoot;
            const theOPUserInfo = theOPEl.querySelector("bili-comment-user-info")
                .shadowRoot.getElementById("info");
            const userNameEl = theOPUserInfo.querySelector("#user-name>a");
            const userLevelSrc = theOPUserInfo.querySelector('#user-level>img')?.src || null;
            const level = getUrlUserLevel(userLevelSrc);
            isLoaded = theOPEl.querySelector("#content>bili-rich-text")
                .shadowRoot.querySelector("#contents>*") !== null;
            if (!isLoaded) {
                break;
            }
            const theOPContentEl = theOPEl.querySelector("#content>bili-rich-text")
                .shadowRoot.querySelector("#contents");
            const theOPContent = theOPContentEl.textContent.trim();
            const userName = userNameEl.textContent.trim();
            const userUrl = userNameEl.href;
            const uid = elUtil.getUrlUID(userUrl);
            const replies = [];
            commentsData.push({
                name: userName,
                userUrl,
                uid,
                level,
                content: theOPContent,
                replies,
                el,
                insertionPositionEl: theOPUserInfo,
                explicitSubjectEl: theOPEl.querySelector("#body")
            });
            const inTheBuildingEls = el.shadowRoot.querySelector("bili-comment-replies-renderer")
                .shadowRoot.querySelectorAll("bili-comment-reply-renderer");
            for (let inTheBuildingEl of inTheBuildingEls) {
                const inTheContentEl = inTheBuildingEl.shadowRoot;
                const inTheBuildingUserInfo = inTheContentEl.querySelector("bili-comment-user-info")
                    .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 inTheBuildingContent = inTheContentEl.querySelector("bili-rich-text")
                    .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: inTheContentEl
                });
            }
        }
        if (!isLoaded) {
            await defUtil.wait(500);
            return getCommentSectionList()
        }
        return commentsData;
    };
    const getOldCommentSectionList = async () => {
        const results = await elUtil.findElementsWithTimeout(".reply-list>.reply-item");
        if (results === null) {
            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);
                replies.push({
                    name: userName,
                    userUrl,
                    uid,
                    level,
                    content: subContent,
                    el: inTheBuildingEl,
                    insertionPositionEl: subUserInfoEl,
                    explicitSubjectEl: inTheBuildingEl
                });
            }
        }
        debugger
        return commentsData;
    };
    const startShieldingComments = async () => {
        let list;
        const href = window.location.href;
        if (href.includes("https://space.bilibili.com/") || topicDetail.isTopicDetailPage(href)) {
            list = await getOldCommentSectionList();
        } else {
            list = await getCommentSectionList();
        }
        shielding.shieldingComments(list);
    };
    var commentSectionModel = {
        startShieldingComments
    };
    const addBlockButton = (data, tagCss, position = []) => {
        const {insertionPositionEl, explicitSubjectEl, css} = data.data;
        if (insertionPositionEl.querySelector("." + tagCss)) return;
        const buttonEL = document.createElement("button");
        buttonEL.setAttribute("gz_type", "");
        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];
            }
        }
        buttonEL.style.display = "none";
        elUtil.addEventListenerWithTracking(explicitSubjectEl, "mouseover", () => buttonEL.style.display = "block");
        elUtil.addEventListenerWithTracking(explicitSubjectEl, "mouseout", () => buttonEL.style.display = "none");
        insertionPositionEl.appendChild(buttonEL);
        buttonEL.addEventListener("click", (event) => {
            event.stopImmediatePropagation(); // 阻止事件冒泡和同一元素上的其他事件处理器
            event.preventDefault(); // 阻止默认行为
            const tempData = data.data;
            console.log("该选项数据:", data);
            xtip.sheet({
                btn: ['uid精确屏蔽(推荐)', '用户名精确屏蔽(不推荐)'],
                btn1: () => {
                    const tipContent = `uid精确屏蔽\n
用户${tempData.name}\n
uid:${tempData.uid}`;
                    xtip.confirm(tipContent, {
                        title: "添加规则",
                        icon: "a",
                        btn1: () => {
                            if (tempData.uid === -1) {
                                Tip.error("该页面数据不存在uid字段");
                                return;
                            }
                            ruleUtil.addRule(tempData.uid, "precise_uid").then(msg => {
                                xtip.alert(msg, {icon: 's'});
                                data.maskingFunc();
                            }).catch(msg => {
                                xtip.alert(msg, {icon: 'e'});
                            });
                        }
                    });
                },
                btn2: () => {
                    xtip.msg('暂未开放.');
                },
            });
        });
    };
    const addVideoBlockButton$1 = (data) => {
        addBlockButton(data, "gz_shielding_button", ["right"]);
    };
    const addPopularVideoBlockButton = (data) => {
        addBlockButton(data, "gz_shielding_button", ["right", "bottom"]);
    };
    const addTopicDetailVideoBlockButton = (data) => {
        addBlockButton(data, "gz_shielding_button");
    };
    const addTopicDetailContentsBlockButton = (data) => {
        const position = data.data.position;
        const loop = position !== undefined;
        addBlockButton(data, "gz_shielding_topic_detail_button", loop ? position : []);
    };
    const addCommentBlockButton = (commentsData) => {
        const data = {
            data: commentsData,
            maskingFunc: commentSectionModel.startShieldingComments
        };
        addBlockButton(data, "gz_shielding_comment_button");
    };
    const addLiveContentBlockButton = (commentsData) => {
        addBlockButton(commentsData, "gz_shielding_live_danmaku_button");
    };
    const shieldingVideo = (videoData) => {
        const {
            title, uid = -1,
            name, nDuration = -1,
            nBulletChat = -1, nPlayCount = -1
        } = videoData;
        if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseUidWhiteArr(), uid)) {
            return {state: false};
        }
        if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseUidArr(), uid)) {
            return {state: true, type: "精确匹配uid"};
        }
        let matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getTitleArr(), title);
        if (matching !== null) {
            return {state: true, type: "模糊匹配标题", matching};
        }
        matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getTitleCanonicalArr(), title);
        if (matching !== null) {
            return {state: true, type: "正则匹配标题", matching};
        }
        if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseNameArr(), name)) {
            return {state: true, type: "精确匹配用户名"};
        }
        matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getNameArr(), name);
        if (matching !== null) {
            return {state: true, type: "模糊匹配用户名", matching};
        }
        matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getNameCanonical(), name);
        if (matching !== null) {
            return {state: true, type: "正则用户名", matching};
        }
        if (nDuration !== -1) {
            const min = gmUtil.getData('nMinimumDuration', -1);
            if (min > nDuration) {
                return {state: true, type: '最小时长', matching: min}
            }
            const max = gmUtil.getData('nMaximumDuration', -1);
            if (max > nDuration) {
                return {state: true, type: '最大时长', matching: max}
            }
        }
        if (nBulletChat !== -1) {
            const min = gmUtil.getData('nMinimumBarrage', -1);
            if (min > nBulletChat) {
                return {state: true, type: '最小弹幕数', matching: min}
            }
            const max = gmUtil.getData('nMaximumBarrage', -1);
            if (max > nBulletChat) {
                return {state: true, type: '最大弹幕数', matching: max}
            }
        }
        if (nPlayCount !== -1) {
            const min = gmUtil.getData('nMinimumPlay', -1);
            if (min > nPlayCount) {
                return {state: true, type: '最小播放量', matching: min}
            }
            const max = gmUtil.getData('nMaximumPlayback', -1);
            if (max > nPlayCount) {
                return {state: true, type: '最大播放量', matching: max}
            }
        }
        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";
            }
            Tip.successBottomRight("屏蔽了视频");
            const videoInfoHtml = output_informationTab.getVideoInfoHtml(type, matching, videoData);
            output_informationTab.addInfo(videoInfoHtml);
        }
        return state;
    };
    const shieldingDynamic = (dynamicData) => {
        const {
            content = null,
            el,
            title = null,
            tag = null
        } = dynamicData;
        let matching = null;
        if (content !== null) {
            matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getCommentOnArr(), content);
            if (matching !== null) {
                el?.remove();
                return {state: true, type: "评论模糊内容", matching};
            }
            matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getCommentOnCanonicalArr(), content);
            if (matching !== null) {
                el?.remove();
                return {state: true, type: "评论正则内容", matching};
            }
        }
        if (title !== null) {
            matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getTitleArr(), title);
            if (matching !== null) {
                el?.remove();
                return {state: true, type: "模糊标题", matching};
            }
            matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getTitleCanonicalArr(), title);
            if (matching !== null) {
                el?.remove();
                return {state: true, type: "正则标题", matching};
            }
        }
        if (tag !== null) {
            if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseTagArr(), tag)) {
                el?.remove();
                return {state: true, type: "精确tag"};
            }
            matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getTagArr(), tag);
            if (matching !== null) {
                el?.remove();
                return {state: true, type: "模糊tag", matching};
            }
            matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getTagCanonicalArr(), tag);
            if (matching !== null) {
                el?.remove();
                return {state: true, type: "正则tag", matching};
            }
        }
        return {state: false}
    };
    const shieldingDynamicDecorated = (dynamicData) => {
        const {state, type, matching} = shieldingDynamic(dynamicData);
        if (state) {
            Tip.successBottomRight("屏蔽了视频");
            output_informationTab.addInfo(output_informationTab.getDynamicContentInfoHtml(type, matching, dynamicData));
        }
        return state;
    };
    const shieldingComment = (commentsData) => {
        const {content, uid, name, level = -1} = commentsData;
        if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseUidWhiteArr(), uid)) {
            return {state: false};
        }
        if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseUidArr(), uid)) {
            return {state: true, type: "精确匹配uid"};
        }
        if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseNameArr(), name)) {
            return {state: true, type: "精确用户名"};
        }
        let matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getNameArr(), name);
        if (matching !== null) {
            return {state: true, type: "模糊匹配用户名", matching};
        }
        matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getNameCanonical(), name);
        if (matching !== null) {
            return {state: true, type: "正则用户名", matching};
        }
        matching = ruleMatchingUtil.fuzzyMatch(ruleKeyListData$1.getCommentOnArr(), content);
        if (matching !== null) {
            return {state: true, type: "模糊评论内容", matching};
        }
        matching = ruleMatchingUtil.regexMatch(ruleKeyListData$1.getCommentOnCanonicalArr(), content);
        if (matching !== null) {
            return {state: true, type: "正则评论内容", matching};
        }
        if (level !== -1) {
            const min = gmUtil.getData('nMinimumLevel', -1);
            if (min > level) {
                return {state: true, type: "评论区最小用户等级过滤", matching: min};
            }
            const max = gmUtil.getData('nMaximumLevel', -1);
            if (max > level) {
                return {state: true, type: "评论区最大用户等级过滤", matching: max};
            }
        }
        return {state: false};
    };
    const shieldingCommentDecorated = (commentsData) => {
        const {state, type, matching} = shieldingComment(commentsData);
        if (state) {
            commentsData.el?.remove();
            Tip.successBottomRight("屏蔽了评论");
            output_informationTab.addInfo(output_informationTab.getCommentInfoHtml(type, matching, commentsData));
        }
        return state;
    };
    const shieldingLiveRoomContentDecorated = (liveRoomContent) => {
        let {state, type, matching} = shieldingComment(liveRoomContent);
        const {el, fansMedal} = liveRoomContent;
        if (fansMedal !== null) {
            if (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPreciseFanCardArr(), fansMedal)) {
                el?.remove();
                state = true;
                type = "精确粉丝牌";
            }
        }
        if (state) {
            el?.remove();
            Tip.successBottomRight("屏蔽了直播间评论");
        }
        if (type) {
            output_informationTab.addInfo(output_informationTab.getLiveRoomCommentInfoHtml(type, matching, liveRoomContent));
        }
        return state;
    };
    const shieldingComments = (commentsDataList) => {
        for (let commentsData of commentsDataList) {
            if (shieldingCommentDecorated(commentsData)) continue;
            addCommentBlockButton(commentsData);
            const {replies = []} = commentsData;
            if (replies.length === 0) continue;
            for (let reply of replies) {
                if (shieldingCommentDecorated(reply)) continue;
                addCommentBlockButton(reply);
            }
        }
    };
    const shieldingLiveRoom = (liveRoomData) => {
        const {name = null, 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 !== null) {
            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 (ruleMatchingUtil.exactMatch(ruleKeyListData$1.getPrecisePartitionArr(), partition)) {
            return {state: true, type: "精确直播分区"};
        }
        return {state: false};
    };
    const shieldingLiveRoomDecorated = (liveRoomData) => {
        const {state, type, matching = null} = shieldingLiveRoom(liveRoomData);
        if (state) {
            liveRoomData.el?.remove();
            Tip.successBottomRight("屏蔽了直播间");
            output_informationTab.addInfo(output_informationTab.getLiveRoomInfoHtml(type, matching, liveRoomData));
        }
        return state;
    };
    var shielding = {
        shieldingVideoDecorated,
        shieldingDynamicDecorated,
        shieldingCommentDecorated,
        shieldingLiveRoomDecorated,
        shieldingComments,
        addVideoBlockButton: addVideoBlockButton$1,
        addCommentBlockButton,
        shieldingLiveRoomContentDecorated,
        addLiveContentBlockButton,
        addPopularVideoBlockButton,
        addTopicDetailVideoBlockButton,
        addTopicDetailContentsBlockButton,
        addBlockButton
    };
    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 === 'https://www.bilibili.com/?spm_id_from=333.1007.0.0'
    };
    const adaptationBAppCommerce$1 = localMKData.getAdaptationBAppCommerce();
    const deDesktopDownloadTipEl = async () => {
        const el = await elUtil.findElementUntilFound(".desktop-download-tip");
        el?.remove();
        const log = "已删除下载提示";
        Tip.infoBottomRight(log);
        console.log(log, el);
    };
    const getChangeTheVideoElList = async () => {
        const elList = await elUtil.findElementsUntilFound(".container.is-version8>.feed-card");
        const list = [];
        for (let el of elList) {
            try {
                const tempData = getVideoData(el);
                const {userUrl} = tempData;
                const videoUrl = el.querySelector(".bili-video-card__info--tit>a").href;
                if (!userUrl.includes("//space.bilibili.com/")) {
                    el?.remove();
                    const log = "遍历换一换视频列表中检测到异常内容,已将该元素移除";
                    Tip.infoBottomRight(log);
                    console.log(log, el);
                    continue;
                }
                list.push({
                    ...tempData, ...{
                        videoUrl,
                        el,
                        insertionPositionEl: el.querySelector(".bili-video-card__info--bottom"),
                        explicitSubjectEl: el.querySelector(".bili-video-card__info")
                    }
                });
            } catch (e) {
                el.remove();
                Qmsg.error("获取视频信息失败");
            }
        }
        return list
    };
    const getVideoData = (el) => {
        const title = el.querySelector(".bili-video-card__info--tit").title;
        const name = el.querySelector(".bili-video-card__info--author").textContent.trim();
        let nPlayCount = el.querySelector('.bili-video-card__stats--text')?.textContent.trim();
        nPlayCount = sFormatUtil.toPlayCountOrBulletChat(nPlayCount);
        let nBulletChat = el.querySelector('.bili-video-card__stats--text')?.textContent.trim();
        nBulletChat = sFormatUtil.toPlayCountOrBulletChat(nBulletChat);
        let nDuration = el.querySelector('.bili-video-card__stats__duration')?.textContent.trim();
        nDuration = sFormatUtil.timeStringToSeconds(nDuration);
        const userUrl = el.querySelector(".bili-video-card__info--owner").getAttribute("href");
        const uid = elUtil.getUrlUID(userUrl);
        return {
            title,
            name,
            uid,
            nPlayCount,
            nBulletChat,
            nDuration,
            userUrl
        }
    };
    const getHomeVideoELList = async () => {
        const elList = await elUtil.findElementsUntilFound(".container.is-version8>.bili-video-card");
        let list = [];
        for (let el of elList) {
            try {
                const tempData = getVideoData(el);
                const {userUrl} = tempData;
                if (!userUrl.includes("//space.bilibili.com/")) {
                    el?.remove();
                    const log = "遍历换一换视频列表下面列表时检测到异常内容,已将该元素移除";
                    Tip.infoBottomRight(log);
                    console.log(log, el);
                    continue;
                }
                list.push({
                    ...tempData, ...{
                        videoUrl: el.querySelector(".bili-video-card__info--tit>a").href,
                        el,
                        insertionPositionEl: el.querySelector(".bili-video-card__info--bottom"),
                        explicitSubjectEl: el.querySelector(".bili-video-card__info")
                    }
                });
            } catch (e) {
                el?.remove();
                Tip.infoBottomRight("遍历视频列表中检测到异常内容,已将该元素移除;");
            }
        }
        return list;
    };
    const getGateActivatedTab = async () => {
        const el = await elUtil.findElementUntilFound(".ant-radio-group>.ant-radio-button-wrapper-checked .css-1k4kcw8");
        return el?.textContent.trim();
    };
    const getGateDataList = async () => {
        const elList = await elUtil.findElementsUntilFound(".bilibili-gate-video-grid>[data-bvid].bili-video-card");
        const list = [];
        for (let el of elList) {
            const tempData = getVideoData(el);
            const videoUrl = el.querySelector("a.css-feo88y").href;
            const insertionPositionEl = el.querySelector(".bili-video-card__info--owner");
            list.push({
                ...tempData, ...{
                    videoUrl,
                    el,
                    insertionPositionEl,
                    explicitSubjectEl: el
                }
            });
        }
        return list;
    };
    const startShieldingGateVideoList = async () => {
        const list = await getGateDataList();
        for (let videoData of list) {
            if (shielding.shieldingVideoDecorated(videoData, "hide")) {
                continue;
            }
            shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingGateVideoList});
        }
    };
    const startIntervalShieldingGateVideoList = () => {
        const throttle = defUtil.throttle(startShieldingGateVideoList, 2000);
        setInterval(async () => {
            await getGateActivatedTab();
            throttle();
        }, 1500);
    };
    const startClearExcessContentList = () => {
        if (adaptationBAppCommerce$1) return;
        setInterval(() => {
            const otherElList = document.querySelectorAll(".floor-single-card");
            const liveList = document.querySelectorAll(".bili-live-card");
            const elList = [...otherElList, ...liveList];
            for (let el of elList) {
                el?.remove();
            }
        }, 1000);
        console.log("已启动每秒清理首页视频列表中多余的内容");
    };
    const startShieldingChangeVideoList = async () => {
        const list = await getChangeTheVideoElList();
        for (let videoData of list) {
            if (shielding.shieldingVideoDecorated(videoData)) {
                continue;
            }
            shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingChangeVideoList});
        }
    };
    const startDebounceShieldingChangeVideoList = defUtil.debounce(startShieldingChangeVideoList, 200);
    const startShieldingHomeVideoList = async () => {
        const homeVideoELList = await getHomeVideoELList();
        for (const videoData of homeVideoELList) {
            if (shielding.shieldingVideoDecorated(videoData)) {
                continue;
            }
            shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingHomeVideoList});
        }
    };
    const startDebounceShieldingHomeVideoList = defUtil.debounce(startShieldingHomeVideoList, 500);
    const scrollMouseUpAndDown = async () => {
        if (adaptationBAppCommerce$1) return;
        await defUtil.smoothScroll(false, 100);
        return defUtil.smoothScroll(true, 600);
    };
    var bilibiliHome = {
        isHome,
        startClearExcessContentList,
        startDebounceShieldingChangeVideoList,
        startDebounceShieldingHomeVideoList,
        scrollMouseUpAndDown,
        deDesktopDownloadTipEl,
        startIntervalShieldingGateVideoList
    };
    const isSearch = (url) => {
        return url.includes("search.bilibili.com")
    };
    const getVideoList$1 = async (css) => {
        const elList = await elUtil.findElementsWithTimeout(css);
        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");
            let userUrl;
            try {
                userUrl = userEl.getAttribute("href");
            } catch (e) {
                console.error(e);
            }
            if (!userUrl.includes("//space.bilibili.com/")) {
                el?.remove();
                Tip.infoBottomRight("移除了非视频内容");
                console.log("移除了非视频内容", userUrl, el);
                continue;
            }
            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,
                nPlayCount,
                nBulletChat,
                nDuration,
                el,
                videoUrl: el.querySelector(".bili-video-card__info--right>a").href,
                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 startShieldingVideoList$5 = () => {
        getTabComprehensiveSortedVideoList().then(list => {
            for (let videoData of list) {
                if (shielding.shieldingVideoDecorated(videoData)) {
                    continue;
                }
                shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingVideoList$5});
            }
            console.log("搜索页综合选项卡中的综合排序视频列表已处理完成");
        });
        getOtherVideoList().then(list => {
            for (let videoData of list) {
                if (shielding.shieldingVideoDecorated(videoData)) {
                    continue;
                }
                shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingVideoList$5});
            }
        });
    };
    const startDebounceShieldingVideoList$1 = defUtil.debounce(startShieldingVideoList$5, 500);
    var searchModel = {
        isSearch,
        startDebounceShieldingVideoList: startDebounceShieldingVideoList$1
    };
    const isVideoPlayPage = (url) => {
        return url.includes("www.bilibili.com/video");
    };
    const getGetTheVideoListOnTheRight$1 = async () => {
        await elUtil.findElementUntilFound(".video-page-card-small .b-img img");
        const elList = await elUtil.findElementsUntilFound(".video-page-card-small", {interval: 50});
        const list = [];
        for (let el of elList) {
            try {
                const elInfo = el.querySelector(".info");
                const title = elInfo.querySelector(".title").title;
                const name = elInfo.querySelector(".upname .name").textContent.trim();
                const userUrl = elInfo.querySelector(".upname>a").href;
                const uid = elUtil.getUrlUID(userUrl);
                const playInfo = el.querySelector('.playinfo').innerHTML.trim();
                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,
                    nPlayCount,
                    nBulletChat,
                    nDuration,
                    el,
                    videoUrl: el.querySelector(".info>a").href,
                    insertionPositionEl: el.querySelector(".playinfo"),
                    explicitSubjectEl: elInfo
                });
            } catch (e) {
                console.error("获取右侧视频列表失败:", e);
            }
        }
        return list;
    };
    const startShieldingVideoList$4 = () => {
        getGetTheVideoListOnTheRight$1().then((videoList) => {
            for (let videoData of videoList) {
                if (shielding.shieldingVideoDecorated(videoData)) {
                    continue;
                }
                shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingVideoList$4});
            }
        });
    };
    const findTheExpandButtonForTheListOnTheRightAndBindTheEvent$2 = () => {
        setTimeout(() => {
            elUtil.findElementUntilFound(".rec-footer", {interval: 2000}).then((el) => {
                console.log("找到右侧视频列表的展开按钮");
                console.log(el);
                el.addEventListener("click", () => {
                    startShieldingVideoList$4();
                });
            });
        }, 3000);
    };
    var videoPlayModel = {
        isVideoPlayPage,
        startShieldingVideoList: startShieldingVideoList$4,
        findTheExpandButtonForTheListOnTheRightAndBindTheEvent: findTheExpandButtonForTheListOnTheRightAndBindTheEvent$2,
    };
    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
        }
    };
    var generalFuc = {getPlayCountAndBulletChatAndDuration};
    const iscCollectionVideoPlayPage = (url) => {
        return url.includes("www.bilibili.com/list/ml")
    };
    const getGetTheVideoListOnTheRight = async () => {
        const elList = await elUtil.findElementsUntilFound(".recommend-list-container>.video-card");
        const list = [];
        for (let el of elList) {
            const title = el.querySelector(".title").title;
            const name = el.querySelector(".name").textContent.trim();
            const userUrl = el.querySelector(".upname").href;
            const uid = elUtil.getUrlUID(userUrl);
            list.push({
                ...generalFuc.getPlayCountAndBulletChatAndDuration(el), ...{
                    title,
                    name,
                    userUrl,
                    videoUrl: el.querySelector(".info>a").href,
                    uid,
                    el,
                    insertionPositionEl: el.querySelector(".playinfo"),
                    explicitSubjectEl: el.querySelector(".info")
                }
            });
        }
        return list;
    };
    const startShieldingVideoList$3 = () => {
        getGetTheVideoListOnTheRight().then((videoList) => {
            const css = {right: "123px"};
            for (let videoData of videoList) {
                if (shielding.shieldingVideoDecorated(videoData)) continue;
                videoData.css = css;
                shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingVideoList$3});
            }
        });
    };
    const findTheExpandButtonForTheListOnTheRightAndBindTheEvent$1 = () => {
        setTimeout(() => {
            elUtil.findElementUntilFound(".rec-footer", {interval: 2000}).then((el) => {
                el.addEventListener("click", () => {
                    startShieldingVideoList$3();
                });
            });
        }, 3000);
    };
    var collectionVideoPlayPageModel = {
        iscCollectionVideoPlayPage,
        startShieldingVideoList: startShieldingVideoList$3,
        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;
            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,
                nPlayCount,
                nBulletChat,
                nDuration: -1,
                insertionPositionEl: videoCardInfoEl.querySelector("div"),
                explicitSubjectEl: videoCardInfoEl
            });
        }
        return list;
    };
    const startShieldingVideoList$2 = async (isWeekly = false) => {
        const list = await getVideDataList(isWeekly);
        for (let videoData of list) {
            if (shielding.shieldingVideoDecorated(videoData)) {
                continue;
            }
            shielding.addPopularVideoBlockButton({data: videoData, maskingFunc: startShieldingVideoList$2});
        }
    };
    var popularAll = {
        startShieldingVideoList: startShieldingVideoList$2
    };
    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 = 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);
            list.push({
                title,
                userUrl,
                uid,
                name,
                nPlayCount,
                nBulletChat,
                nDuration: -1,
                el,
                insertionPositionEl: el.querySelector(".detail-state"),
                explicitSubjectEl: el.querySelector(".info")
            });
        }
        return list;
    };
    const startShieldingRankVideoList = async () => {
        const list = await getVideoDataList();
        for (let videoData of list) {
            if (shielding.shieldingVideoDecorated(videoData)) {
                continue;
            }
            shielding.addPopularVideoBlockButton({data: videoData, maskingFunc: startShieldingRankVideoList});
        }
    };
    var popular = {
        isPopularHistory,
        isPopularAllPage,
        isGeneralPopularRank,
        isPopularWeeklyPage,
        startShieldingRankVideoList,
    };
    const cacheData = {
        isPersonalHomepage: null,
    };
    const isPersonalHomepage = async () => {
        if (cacheData.isPersonalHomepage !== null) {
            return cacheData.isPersonalHomepage;
        }
        const {state} = await elUtil.findElementWithTimeout(".h-action", {timeout: 2000, interval: 200});
        const res = !state;
        cacheData.isPersonalHomepage = res;
        return res;
    };
    const isThrottleAsyncPersonalHomepage = defUtil.throttleAsync(isPersonalHomepage,2000);
    var space = {
        isThrottleAsyncPersonalHomepage,
    };
    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 = await space.isThrottleAsyncPersonalHomepage();
        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");
        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);
            list.push({
                ...generalFuc.getPlayCountAndBulletChatAndDuration(el), ...{
                    title,
                    name,
                    userUrl,
                    videoUrl: el.querySelector(".info>a").href,
                    uid,
                    el,
                    insertionPositionEl: el.querySelector(".playinfo"),
                    explicitSubjectEl: el.querySelector(".info")
                }
            });
        }
        return list;
    };
    const startShieldingVideoList$1 = async () => {
        const videoList = await getRightVideoDataList();
        const css = {right: "123px"};
        for (let videoData of videoList) {
            videoData.css = css;
            if (shielding.shieldingVideoDecorated(videoData)) continue;
            shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingVideoList$1});
        }
    };
    const startDebounceShieldingVideoList = defUtil.debounce(startShieldingVideoList$1, 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/?spm_id_from=333.788.0.0&page=');
    };
    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 || null;
            const insertionPositionEl = el.querySelector('[class="group/desc"]');
            list.push({
                title,
                name,
                uid,
                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 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,
                el,
                insertionPositionEl: videoUrlEl.parentElement,
                explicitSubjectEl: el
            });
        }
        return list
    };
    const intervalExecutionStartShieldingVideoInert = (func, name = '') => {
        let i1 = -1;
        const start = () => {
            if (i1 !== -1) {
                return
            }
            console.log('开始执行屏蔽' + name);
            i1 = setInterval(() => {
                func();
                console.log(`执行屏蔽${name}列表-定时器正在执行`);
            }, 1500);
        };
        const stop = () => {
            if (i1 === -1) {
                return
            }
            clearInterval(i1);
            console.log(`已停止执行屏蔽${name}列表`);
            i1 = -1;
        };
        return {start, stop}
    };
    const startShieldingHistoryVideoList = async () => {
        const list = await getHistoryVideoDataList();
        for (let videoData of list) {
            if (shielding.shieldingVideoDecorated(videoData)) {
                continue
            }
            shielding.addVideoBlockButton({data: videoData, maskingFunc: startShieldingHistoryVideoList});
        }
    };
    const startShieldingVideoList = async () => {
        const list = await getVideoList();
        for (let videoData of list) {
            if (shielding.shieldingVideoDecorated(videoData)) {
                continue
            }
            addVideoBlockButton({data: videoData, maskingFunc: startShieldingVideoList});
        }
    };
    const intervalExecutionStartShieldingVideo = () => {
        const res = intervalExecutionStartShieldingVideoInert(startShieldingVideoList, '视频');
        return () => {
            return res
        }
    };
    const intervalExecutionStartShieldingHistoryVideo = () => {
        const res = intervalExecutionStartShieldingVideoInert(startShieldingHistoryVideoList, '历史记录');
        return () => {
            return res
        }
    };
    const startShieldingVideo = intervalExecutionStartShieldingVideo();
    const startShieldingHistoryVideo = intervalExecutionStartShieldingHistoryVideo();
    const rightTabsInsertListener = () => {
        getRightTabs().then(list => {
                for (let {el, label, active} of list) {
                    el.addEventListener('click', () => {
                            console.log('右侧选项卡栏点击了' + label, active);
                            if (label === '首页') {
                                debugger
                                homeTopTabsInsertListener();
                                startShieldingVideo().start();
                            } else {
                                startShieldingVideo().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().stop();
                        return
                    }
                    if (label === '排行') {
                        rankingLeftTabsInsertListener();
                    }
                    startShieldingVideo().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().stop();
                        return
                    }
                    startShieldingVideo().start();
                });
            }
        });
    };
    const addVideoBlockButton = (data) => {
        shielding.addBlockButton(data, "gz_shielding_button", ["right", 'bottom']);
    };
    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 = async (parseUrl) => {
        const {page} = parseUrl.queryParams;
        installBEWLStyle();
        if (page === 'Home') {
            startShieldingVideo().start();
            homeTopTabsInsertListener();
        }
        if (page === 'History') {
            startShieldingHistoryVideo().start();
            searchBoxInsertListener();
        }
        rightTabsInsertListener();
    };
    var compatibleBewlyBewly = {
        startRun,
        isBEWLYPage,
    };
    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);
        if (compatible_BEWLY_BEWLY$1 && compatibleBewlyBewly.isBEWLYPage(url)) {
            const parseUrl = defUtil.parseUrl(url);
            compatibleBewlyBewly.startRun(parseUrl);
            return;
        }
        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.startDebounceShieldingVideoList();
        }
        if (videoPlayModel.isVideoPlayPage(url)) {
            videoPlayModel.startShieldingVideoList();
            videoPlayModel.findTheExpandButtonForTheListOnTheRightAndBindTheEvent();
        }
        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();
        }
    };
    const dynamicRouting = (title, url) => {
        console.log("动态路由", title, url);
        if (bOnlyTheHomepageIsBlocked$1) return;
        if (searchModel.isSearch(url)) {
            searchModel.startDebounceShieldingVideoList();
        }
        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
    };
    const bOnlyTheHomepageIsBlocked = localMKData.getBOnlyTheHomepageIsBlocked();
    const compatible_BEWLY_BEWLY = localMKData.isCompatible_BEWLY_BEWLY();
    const observeNetwork = (url, windowUrl,winTitle, initiatorType) => {
        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();
        }
    };
    var observeNetwork$1 = {
        observeNetwork
    };
    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 === "`") {
            mainDrawer.showDrawer();
        }
    });
})(Vue);