// ==UserScript==
// @name         Bilibili【哔哩哔哩】 用户成分标签
// @namespace    lycoris
// @version      2.6.0
// @description  根据 Bilibili 用户近期动态、粉丝勋章内容检测成分添加自定义标签,按规则屏蔽评论
// @author       Lyzoris
// @supportURL   https://github.com/lyzoris/Bilibili-UserComponentTag
// @compatible   chrome 80 or later
// @compatible   edge 80 or later
// @match        https://www.bilibili.com
// @match        https://www.bilibili.com/video/*
// @match        https://www.bilibili.com/opus/*
// @match        https://t.bilibili.com/*
// @match        https://space.bilibili.com/*
// @match        https://www.bilibili.com/bangumi/play/*
// @match        https://www.bilibili.com/read/*
// @icon         https://static.hdslb.com/images/favicon.ico
// @connect      bilibili.com
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue 
// @grant        GM_listValues
// @grant        GM_setClipboard
// @require      https://greasyfork.org/scripts/448895-elementgetter%E5%BA%93/code/ElementGetter%E5%BA%93.js?version=1106656
// @license MIT
// @run-at document-end
// @downloadURL none
// ==/UserScript==
(function () {
    "use surict";
    const elmGetter = new ElementGetter();
    const Cookie = document.cookie
    const goOldVideo = Cookie.match(/(?<=go_old_video=)[-\d]{1,2}/)
    let isNew = true
    if(Cookie && goOldVideo){
        isNew = goOldVideo[0] === '-1'
    }
    let Page = '';
    const webType = { '^https:\/\/www.bilibili.com[\/]$': 'Main', 'https:\/\/(t|space).bilibili.com': 'Dynamic', 'https:\/\/www.bilibili.com\/video': 'Video' };
    Object.keys(webType).map(urlReg => { if (RegExp(urlReg).test(location.href)) {
        Page = webType[urlReg];
    } });
    const ApiUrl = {
        blog: 'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?&host_mid=',
        concerns: 'https://api.bilibili.com/x/relation/followings?vmid=',
        medal: 'https://api.live.bilibili.com/xlive/web-ucenter/user/MedalWall?target_id='
    };
    const childTagReg = new RegExp(/^(\[.*?\])(\[.*?\])*(\[.*?\])$/);
    const tagClassHide = {
        true: '.tag-class {display:none;}',
        false: '.tag-class {display:block;}'
    };
    const Style_tagClassHide = elmGetter.create(``);
    const ScriptStyle_STR = `
    
    `;
    const ScriptBody_STR = `
    
`;
    const ScriptBody = elmGetter.create(ScriptBody_STR);
    const ScriptStyle = elmGetter.create(ScriptStyle_STR);
    const Head = document.head || document.querySelector('head');
    const Body = document.body || document.querySelector('body');
    Head.appendChild(ScriptStyle);
    Head.appendChild(Style_tagClassHide);
    Body.appendChild(ScriptBody);
    const scriptHide = ScriptBody.querySelector('.script-hide');
    const scriptMain = ScriptBody.querySelector('.script-main');
    const topNav = ScriptBody.querySelectorAll('.topnav-option');
    const scriptBar = ScriptBody.querySelectorAll('.scriptBar');
    const inputFields = ScriptBody.querySelectorAll('.input-tag');
    let tagClass_hide = ScriptBody.querySelector('#tagClass-hide');
    let tag_merge = ScriptBody.querySelector('#tag-merge');
    let detect_repost = ScriptBody.querySelector('#detect-repost');
    let detect_concerns = ScriptBody.querySelector('#detect-concerns');
    let detect_medal = ScriptBody.querySelector('#detect-medal');
    let detection_mode = ScriptBody.querySelector('#detectionMode-input');
    let link_delete = ScriptBody.querySelector('#link-delete');
    let close_comment = ScriptBody.querySelector('#close-comment');
    let import_area = ScriptBody.querySelector('#import-area');
    let tag_name = ScriptBody.querySelector('#input-tagname');
    let tag_text = ScriptBody.querySelector('#input-tagtext');
    let tag_reg = ScriptBody.querySelector('#input-tagreg');
    let tag_color = ScriptBody.querySelector('#input-tagcolor');
    let add_tag = ScriptBody.querySelector('#add-tag');
    let import_tag = ScriptBody.querySelector('#import-tag');
    let export_tag = ScriptBody.querySelector('#export-tag');
    let taglist = ScriptBody.querySelector('.tagbar-taglist');
    let tag_hide = ScriptBody.querySelector('#tag-hide');
    let add_comment = ScriptBody.querySelector('#add-comment-reg');
    let comment_reg = ScriptBody.querySelector('#input-comment-reg');
    let commentlist = ScriptBody.querySelector('.tagbar-commentlist');
    let dynamic_btn = ScriptBody.querySelector('#dynamic-btn');
    let script_like = ScriptBody.querySelector('.script-like');
    let reg_ruler = ScriptBody.querySelector('#reg-ruler');
    let block_user = ScriptBody.querySelector('#block-user');
    let block_comment = ScriptBody.querySelector('#block-comment');
    let block_dynamic = ScriptBody.querySelector('#block-dynamic');
    let block_video = ScriptBody.querySelector('#block-video');
    inputFields.forEach(e => {
        e.onkeyup = (event) => {
            let index = Number(event.target?.getAttribute('index'));
            if (['Enter', 'ArrowDown'].includes(event.key)) {
                index = index == 2 ? 0 : index + 1;
            } else if (event.key == 'ArrowUp') {
                index = index == 0 ? 2 : index - 1;
            }
            inputFields[index].focus();
        };
    });
    scriptHide.onclick = () => {
        if (scriptMain.style.display === 'block') {
            scriptMain.style.display = 'none';
            scriptHide.classList.remove('tagbar-active');
        } else {
            scriptMain.style.display = 'block';
            scriptHide.classList.add('tagbar-active');
        }
    };
    topNav.forEach(btn => {
        btn.onclick = () => {
            topNav.forEach(i => { i.classList.remove('topnav-active'); });
            btn.classList.add('topnav-active');
            scriptBar.forEach(i => { i.style.display = 'none'; });
            scriptBar[Number(btn.getAttribute('index'))].style.display = 'flex';
        };
    });
    reg_ruler.onclick = (event) => {
        event.altKey && window.open('https://gitee.com/thinkyoung/learn_regex');
    };
    block_user.onclick = () => {
        BlockOption.User = block_user.checked;
        GM_setValue('BlockOption', BlockOption);
    };
    block_video.onclick = () => {
        BlockOption.Video = block_video.checked;
        GM_setValue('BlockOption', BlockOption);
        if (block_video.checked && Page === 'Main') {
            mainPageBlock();
        }
    };
    block_dynamic.onclick = () => {
        BlockOption.Dynamic = block_dynamic.checked;
        GM_setValue('BlockOption', BlockOption);
        if (block_dynamic.checked && Page === 'Dynamic') {
            dynamicPageBlock();
        }
    };
    block_comment.onclick = () => {
        BlockOption.Comment = block_comment.checked;
        GM_setValue('BlockOption', BlockOption);
    };
    detection_mode.onclick = () => {
        AutoDetect = detection_mode.checked;
        GM_setValue('AutoDetect', AutoDetect);
    };
    dynamic_btn.onclick = () => {
        script_like.style.display = dynamic_btn.checked ? 'block' : 'none';
        GM_setValue('DynamicLike', dynamic_btn.checked);
    };
    script_like.onclick = dynamicBatchLike;
    tagClass_hide.onclick = () => {
        Style_tagClassHide.innerHTML = tagClassHide[String(tagClass_hide.checked)];
        GM_setValue('TagClassHide', tagClass_hide.checked);
    };
    detect_repost.onclick = () => {
        DetectOption.Repost = detect_repost.checked;
        GM_setValue('DetectOption', DetectOption);
    };
    detect_concerns.onclick = () => {
        DetectOption.Concerns = detect_concerns.checked;
        GM_setValue('DetectOption', DetectOption);
    };
    detect_medal.onclick = () => {
        DetectOption.Medal = detect_medal.checked;
        GM_setValue('DetectOption', DetectOption);
    };
    tag_merge.onclick = () => {
        tagMerge = tag_merge.checked;
        GM_setValue('TagMerge', tagMerge);
    };
    link_delete.onclick = () => { GM_setValue('NoJump', link_delete.checked); };
    close_comment.onclick = () => {
        closeComment();
        GM_setValue('CloseComment', close_comment.checked);
    };
    add_tag.onclick = () => {
        if (tag_name.value && tag_text.value && tag_reg.value) {
            if (!/[\n\r"'{}、]/.test(tag_reg.value)) {
                addTag({
                    tag: tag_name.value,
                    text: tag_text.value,
                    reg: tag_reg.value,
                    color: tag_color.value,
                    hide: tag_hide.checked
                });
                tag_name.value = '';
                tag_text.value = '';
                tag_reg.value = '';
                tag_hide.checked = false;
            } else {
                alert(`标签规则不应该包含‘ “ 、" ' { } \\n \\r等字符`);
            }
        } else {
            alert('请将标签信息补充完整');
        }
    };
    add_comment.onclick = () => {
        if (comment_reg.value) {
            addKeyWord(comment_reg.value);
            comment_reg.value = '';
        } else {
            alert('请将关键词正则信息补充完整');
        }
    };
    function exportDataToClipboard() {
        let exportData = {};
        let key_storage = GM_listValues();
        key_storage.forEach(i => {
            exportData[i] = GM_getValue(i, null);
        });
        GM_setClipboard(JSON.stringify(exportData));
        alert('已导出标签数据到剪切板!');
    }
    function importDataToTemperMonkey() {
        if (import_area.value) {
            try {
                let importData = JSON.parse(import_area.value);
                Object.keys(importData).forEach(i => { GM_setValue(i, importData[i]); });
            }
            catch (e) {
                alert('导入配置出错,请检查配置项');
                return;
            }
            import_area.value = '';
            configInit();
        } else {
            alert('配置为空!请先在输入框粘贴配置并检查无误后点击【导入配置】');
        }
    }
    export_tag.onclick = exportDataToClipboard;
    import_tag.onclick = importDataToTemperMonkey;
    function addKeyWord(reg_text) {
        if (!keyword.includes(reg_text)) {
            let new_tag = insertTag(commentlist, reg_text);
            let keyword_index = Object.keys(temp_keyword).length;
            temp_keyword[keyword_index] = reg_text;
            keyword.push(reg_text);
            GM_setValue('Keyword', keyword);
            function deleteTag() {
                commentlist.removeChild(new_tag);
                delete temp_keyword[keyword_index];
                keyword = [];
                Object.keys(temp_keyword).map((key) => keyword.push(temp_keyword[key]));
                GM_setValue('Keyword', keyword);
            }
            new_tag.children[0].onclick = deleteTag;
            new_tag.children[1].ondblclick = () => {
                comment_reg.value = reg_text;
                deleteTag();
            };
        }
    }
    function addTag(tag_dic) {
        let new_tag = insertTag(taglist, tag_dic);
        let tag_index = Object.keys(tag).length;
        tag[tag_index] = tag_dic;
        tagList.push(tag, tag_index);
        function deleteTag() {
            taglist.removeChild(new_tag);
            delete tag[tag_index];
            let tag_temp = { ...tag };
            tag = {};
            Object.values(tag_temp).forEach((value, i) => { tag[i] = value; });
            tagList.pop(tag);
        }
        new_tag.children[0].onclick = deleteTag;
        new_tag.children[1].ondblclick = () => {
            tag_name.value = tag_dic.tag;
            tag_text.value = tag_dic.text;
            tag_reg.value = tag_dic.reg;
            tag_color.value = tag_dic.color;
            tag_hide.checked = tag_dic.hide;
            deleteTag();
        };
    }
    function insertTag(parentNode, tagInfo) {
        let title = '';
        let text = '';
        let color = '#1d1d1dbd';
        let border = 'none';
        if (typeof (tagInfo) === 'object') {
            if (childTagReg.test(tagInfo.reg)) {
                border = 'solid 1px #4fc3f7';
                title = `分类:${tagInfo.tag} (合并标签)
子标签:${tagInfo.reg}
隐藏评论:${tagInfo.hide}
请放在待合并标签后`;
            } else {
                title = `分类:${tagInfo.tag}
规则:${tagInfo.reg}
隐藏评论:${tagInfo.hide}`;
            }
            text = tagInfo.text;
            color = tagInfo.color;
        } else {
            text = tagInfo;
        }
        let new_tag = elmGetter.create(``);
        parentNode.appendChild(new_tag);
        return new_tag;
    }
    function measureTextWidth(fontSize, text) {
        let fontFamily = 'PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif';
        let canvas = document.createElement('canvas');
        let context = canvas.getContext('2d');
        context.font = `${fontSize} ${fontFamily}`;
        let result = context.measureText(text);
        return result.width > 18 ? Math.ceil(result.width) : 18;
    }
    class Tag {
        constructor(tag_dic) {
            this.child_tag = [];
            this.tag_class = this.str2tagID(tag_dic.tag, 'class');
            this.text = tag_dic.text;
            this.tag_id = this.str2tagID(this.text, 'id');
            this.reg = Tag.multiReg(tag_dic.reg);
            this.hide = tag_dic.hide;
            this.tag_width = measureTextWidth('15px', tag_dic.tag);
            this.width = measureTextWidth('15px', this.text);
            this.list = new Set();
            this.nolist = new Set();
            this.childTag(tag_dic);
            this.tag_childNode = this.createElement(``);
            this.tagNode = this.createElement(``);
        }
        createElement(dom_str) {
            return dom_str;
        }
        childTag(tag_dic) {
            if (childTagReg.test(tag_dic.reg)) {
                this.child_tag = tag_dic.reg.match(/(?<=\[)(.*?)(?=\])/g);
                let regs = [];
                tagList.list.filter(i => { if (this.child_tag.includes(i.text)) {
                    return i;
                } }).forEach(e => {
                    let new_reg = String(e.reg).match(/\((.*?)\){1,2}/g);
                    if (new_reg) {
                        regs.splice(0, 0, ...new_reg);
                    } else {
                        regs.push(`(?=.*(${String(e.reg).replace(/\//g, '')}))`);
                    }
                });
                this.reg = new RegExp(`^${regs.join('')}.*`);
            }
        }
        str2tagID(str, state) {
            let hex = '';
            for (let i = 0; i < str.length; i++) {
                hex += str.charCodeAt(i).toString(32);
            }
            return 'tag-' + state + '-' + hex;
        }
        static multiReg(query) {
            let regStr = query.indexOf('&') !== -1 ? `^${query.split('&').map(q => `(?=.*${q})`).join('')}.*` : query;
            return new RegExp(regStr);
        }
        checkUserTag(pid, userNode, replyNode) {
            if (this.list.has(pid)) {
                this.hide && removeUserComment(replyNode);
                if (!userNode.querySelector('.' + this.tag_id)) {
                    this.addUserTag(userNode);
                }
            }
        }
        detectNewUserTag(pid, userNode, replyNode, userInfo) {
            if (this.reg.test(userInfo)) {
                this.hide && removeUserComment(replyNode);
                if (!userNode.querySelector('.' + this.tag_id) && !this.list.has(pid) && !this.nolist.has(pid)) {
                    this.addUserTag(userNode);
                }
                this.combineChildTag(pid, userNode);
                this.list.add(pid);
            } else {
                this.nolist.add(pid);
            }
        }
        addUserTag(userNode) {
            if (userNode.querySelector('.' + this.tag_class) && tagMerge) {
                userNode.querySelector('.' + this.tag_class).innerHTML += this.tag_childNode;
            } else {
                userNode.innerHTML += this.tagNode;
            }
        }
        combineChildTag(pid, userNode) {
            if (this.child_tag.length != 0) {
                tagList.list.forEach(e => {
                    if (this.child_tag.includes(e.text)) {
                        let child_tag = userNode.querySelector('.' + e.tag_id)?.parentNode;
                        child_tag && userNode.removeChild(child_tag);
                        e.list.delete(pid);
                        e.nolist.add(pid);
                    }
                });
            }
        }
    }
    class TagList {
        constructor() {
            this.list = [];
        }
        push(tag, index) {
            this.list.push(new Tag(tag[index]));
            GM_setValue('Tag', tag);
        }
        pop(tag) {
            this.list = [];
            Object.values(tag).map(i => this.list.push(new Tag(i)));
            GM_setValue('Tag', tag);
        }
        checkUserInfo(pid, userNode, commentNode) {
            this.list.map(i => i.checkUserTag(pid, userNode, commentNode));
            if (DetectOption.Medal && this.isChecked(pid)) {
                this.addMedalWall(pid, userNode);
            }
        }
        isChecked(pid) {
            let tag0 = this.list[0];
            return (tag0.list.has(pid) || tag0.nolist.has(pid)) ? true : false;
        }
        detectNewUserInfo(pid, userNode, commentNode) {
            let p = [];
            const p1 = (resolve) => { Requests(ApiUrl.blog + pid, (data) => { resolve(data); }, 'blog'); };
            const p2 = (resolve) => { Requests(ApiUrl.medal + pid, (data) => { resolve(data); }, 'medal'); };
            const p3 = (resolve) => { Requests(`${ApiUrl.concerns}${pid}&pn=1&ps=50`, (data) => { resolve(data); }, 'concerns'); };
            if (DetectOption.Concerns && DetectOption.Medal) {
                p = [p1, p2, p3];
            } else if (DetectOption.Concerns && !DetectOption.Medal) {
                p = [p1, p3];
            } else if (!DetectOption.Concerns && DetectOption.Medal) {
                p = [p1, p2];
            } else {
                p = [p1];
            }
            Promise.all(p.map(i => new Promise(i))).then((result) => {
                this.list.map(i => i.detectNewUserTag(pid, userNode, commentNode, result.join('')));
                if (DetectOption.Medal && MedalShow) {
                    this.getMedalData(pid, userNode, result[1]);
                }
            });
        }
        getMedalData(pid, userNode, data) {
            let medal_list = JSON.parse(data).list;
            if (medal_list.length != 0) {
                let medalInfo = [];
                medal_list.forEach((e) => {
                    medalInfo.push({
                        targetName: e.target_name,
                        link: e.link,
                        medalName: e.medal_info.medal_name,
                        level: e.medal_info.level,
                        color: { start: '#' + e.medal_info.medal_color_start.toString(16).padStart(6, '0'),
                            end: '#' + e.medal_info.medal_color_end.toString(16).padStart(6, '0'),
                            border: '#' + e.medal_info.medal_color_border.toString(16).padStart(6, '0')
                        }
                    });
                });
                MedalDict[pid] = medalInfo;
                this.addMedalWall(pid, userNode);
            }
        }
        addMedalWall(pid, userNode) {
            if (userNode.querySelector('.medalTag')) {
                return;
            }
            RunOnce(() => {
                window.addEventListener('click', (event) => {
                    let e = event || window.event;
                    let targetClass = e.target?.classList;
                    if (!targetClass.contains('medal-font')) {
                        document.querySelectorAll('.medal-table').forEach(e => {
                            e.style.display = 'none';
                        });
                    }
                });
            });
            let medal = MedalDict[pid];
            if (medal) {
                let medal_list = '';
                medal.forEach((e) => {
                    medal_list += `
                    `;
                });
                let medalInner = `
                `;
                userNode.innerHTML += medalInner;
                let medalBtn = userNode.querySelector('.medalTag');
                let table = userNode.querySelector('.medal-table');
                medalBtn.onclick = () => {
                    let disp = table.style.display;
                    table.style.left = medalBtn.offsetLeft + 50 + 'px';
                    table.style.display = disp === 'block' ? 'none' : 'block';
                };
            }
        }
    }
    let RunOnce = function FunctionRunOnlyOnce(func) {
        func.apply(arguments);
        RunOnce = () => { };
    };
    function Requests(requestUrl, func, state) {
        GM_xmlhttpRequest({
            method: "get",
            url: requestUrl,
            data: '',
            headers: {
                'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, Concerns Gecko) Chrome/104.0.0.0 Safari/537.36'
            },
            onload: function (res) {
                if (res.status === 200) {
                    let data;
                    if (state === 'blog') {
                        let data_list = [];
                        let data_json = JSON.parse(res.response)?.data?.items || [];
                        if (data_json.length > 0) {
                            data_json.map((i) => {
                                let zhuanf_text = i?.modules?.module_dynamic?.desc?.text || '';
                                let origin_text = i?.orig?.modules?.module_dynamic?.desc?.text || '';
                                if (zhuanf_text) {
                                    if (!DetectOption.Repost) {
                                        data_list.push({ 'text': zhuanf_text });
                                    } else {
                                        data_list.push({ 'text': zhuanf_text, 'orig_text': origin_text });
                                    }
                                }
                            });
                        }
                        data = JSON.stringify(data_list).replace(/\[.{1,12}\]/g, '');
                    } else if (state === 'concerns') {
                        let data_list = [];
                        let data_json = JSON.parse(res.response)?.data?.list || [];
                        data_json.length > 0 && data_json.map((i) => { data_list.push(i?.uname); });
                        data = data_list.join(' ');
                    } else {
                        data = JSON.stringify(JSON.parse(res.response)?.data || []);
                    }
                    func(data);
                } else {
                    console.log('加载用户信息失败');
                    console.log(res);
                }
            },
        });
    }
    function getUserID(userNode) {
        if (isNew) {
            return userNode?.querySelector('.user-name,.sub-user-name')?.dataset?.userId || userNode?.querySelector('.name')?.dataset?.usercardMid;
        } else {
            return userNode?.querySelector('.name')?.dataset?.usercardMid || userNode.children[0].href.replace(/[^\d]/g, "");
        }
    }
    function deleteJumpLink(comment) {
        if (link_delete.checked) {
            let jump_word = comment?.querySelectorAll('.jump-link.search-word');
            if (jump_word) {
                for (let link of jump_word) {
                    link.outerHTML = link.innerText;
                }
            }
        }
    }
    function closeComment() {
        if (close_comment.checked) {
            elmGetter.each('div.bottom-page.paging-box-big.center', document, (reply) => {
                let close_btn = elmGetter.create('');
                reply.parentNode.insertBefore(close_btn, reply);
                close_btn.onclick = () => {
                    let comment_btn = reply?.parentNode?.parentNode?.parentNode?.parentNode?.querySelector('.bili-dyn-action.comment.active');
                    comment_btn.click();
                    comment_btn.scrollIntoView({ behavior: 'instant', block: 'center' });
                };
                if (!close_comment.checked) {
                    return false;
                }
            });
        }
    }
    function dynamicBatchLike() {
        let likebtns = document.querySelectorAll('div.like:not(.active)');
        let likebtnsiter = likebtns.entries();
        let clicktimer = setInterval(() => {
            let nextele = likebtnsiter.next();
            if (nextele.done) {
                clearInterval(clicktimer);
                return;
            }
            nextele.value[1].click();
        }, 600);
    }
    function mainPageBlock() {
        if (keyword.length === 0) {
            return;
        }
        elmGetter.each('.bili-video-card.is-rcmd', document, (reply) => {
            let author = reply?.querySelector('.bili-video-card__info--owner');
            let authorName = author.innerText;
            let authorHref = author?.href?.match(/(?<=https:\/\/space.bilibili.com\/)\d+$/);
            let authorID = authorHref ? authorHref[0] : '';
            let title = (reply?.querySelector('.bili-video-card__info--tit')).title;
            for (let reg of keyword) {
                if (RegExp(reg).test(title)) {
                    reply?.parentNode?.removeChild(reply);
                    console.log(`已屏蔽视频 %c${title}  %c关键词:%c${reg}`, 'color: #67d0ff;', 'color: #30aa35;', 'color: #f44336; font-weight: bolder');
                    return;
                }
            }
            if (blackList.has(authorID) || blackList.has(authorName)) {
                reply?.parentNode?.removeChild(reply);
                console.log(`已屏蔽视频 %c${title}  %c作者ID: %c${authorID}`, 'color: #67d0ff;', 'color: #30aa35;', 'color: #f44336; font-weight: bolder');
            }
            if (!BlockOption.Video) {
                return false;
            }
        });
    }
    function dynamicPageBlock() {
        elmGetter.each('.bili-dyn-list__item', document, (reply) => {
            let content = reply?.querySelector('.bili-rich-text__content')?.innerText || '';
            let title = reply?.querySelector('.bili-dyn-card-video__title.bili-ellipsis')?.innerText || '';
            let desc = reply?.querySelector('.bili-dyn-card-video__desc.bili-ellipsis')?.innerText || '';
            let all_content = content + title + desc;
            for (let reg of keyword) {
                if (RegExp(reg).test(all_content)) {
                    reply?.parentNode?.removeChild(reply);
                    console.log(`已屏蔽动态 %c${content}  %c关键词:%c${reg}`, 'color: #67d0ff;', 'color: #30aa35;', 'color: #f44336; font-weight: bolder');
                    return;
                }
            }
            if (!BlockOption.Dynamic) {
                return false;
            }
        });
    }
    function userCommentBlock(userID, reply, comment) {
        if (!BlockOption.Comment) {
            return;
        }
        let commentText = comment?.innerText;
        if (blackList.has(userID)) {
            removeUserComment(reply);
            console.log(`已屏蔽评论 %c${commentText}  %c用户ID: %c${userID}`, 'color: #67d0ff;', 'color: #30aa35;', 'color: #f44336; font-weight: bolder');
            return true;
        }
        if (keyword.length > 0 && commentText) {
            for (let reg of keyword) {
                if (RegExp(reg).test(commentText)) {
                    removeUserComment(reply);
                    console.log(`已屏蔽评论 %c${commentText}  %c关键词:%c${reg}`, 'color: #67d0ff;', 'color: #30aa35;', 'color: #f44336; font-weight: bolder');
                    return true;
                }
            }
        }
        if (BlockOption.User) {
            let blockBtn = elmGetter.create('屏蔽');
            let replyInfo = reply?.querySelector('.reply-info,.sub-reply-info,.info');
            blockBtn.onclick = () => {
                blackList.add(userID);
                GM_setValue('BlackList', Array.from(blackList));
                console.log(`已屏蔽用户: %cID: %c${userID}`, 'color: #f44336; font-weight: bolder', 'color: #f44336; font-weight: bolder');
                replyInfo.removeChild(blockBtn);
                removeUserComment(reply);
            };
            replyInfo.insertBefore(blockBtn, replyInfo.childNodes[replyInfo.childNodes.length - 1]);
        }
        return false;
    }
    function removeUserComment(reply) {
        if (reply.getAttribute('class') === 'content-warp') {
            reply.parentNode?.parentNode?.parentNode?.removeChild(reply.parentNode?.parentNode);
        } else {
            reply.parentNode?.removeChild(reply);
        }
    }
    function detectUserTag(userID, userInfo, reply) {
        function detect(userID, userInfo, reply) {
            if (tagList.list.length == 0) {
                return;
            }
            tagList.checkUserInfo(userID, userInfo, reply);
            if (tagList.isChecked(userID)) {
                return;
            }
            tagList.detectNewUserInfo(userID, userInfo, reply);
        }
        if (!AutoDetect && !tagList.isChecked(userID)) {
            let searchBtn = elmGetter.create('检测
');
            searchBtn.onclick = () => {
                detect(userID, userInfo, reply);
                userInfo.removeChild(searchBtn);
            };
            userInfo.insertBefore(searchBtn, userInfo.childNodes[2]);
            return;
        }
        detect(userID, userInfo, reply);
    }
    function tagInsertObserver() {
        elmGetter.each('.sub-reply-item,.content-warp,.list-item.reply-wrap,.reply-item.reply-wrap', document, (reply) => {
            let userInfo = reply?.querySelector('div.user-info:not(.section),.sub-user-info,div.user');
            let comment = reply?.querySelector('span.reply-content,p.text,span.text-con');
            let userID = getUserID(userInfo);
            if (userID) {
                if (userCommentBlock(userID, reply, comment)) {
                    return;
                }
                deleteJumpLink(comment);
                detectUserTag(userID, userInfo, reply);
            }
        });
    }
    function hideOption(option) {
        if (option.Medal) {
            MedalShow = false;
        }
        if (option.Comment) {
            close_comment.checked = false;
            close_comment.parentNode.style.display = 'none';
        }
        if (option.Like) {
            dynamic_btn.checked = false;
            dynamic_btn.parentNode.style.display = 'none';
            script_like.style.display = 'none';
        }
        if (option.Link) {
            link_delete.checked = false;
            link_delete.parentNode.style.display = 'none';
        }
    }
    function configInit() {
        let all_data = GM_listValues();
        if (all_data.includes('SearchTag')) {
            GM_setValue('AutoDetect', GM_getValue('SearchTag', false));
            GM_deleteValue('SearchTag');
        }
        if (all_data.includes('TagNameHide')) {
            GM_setValue('TagClassHide', GM_getValue('TagNameHide', false));
            GM_deleteValue('TagNameHide');
        }
        all_data.includes('RefreshTime') && GM_deleteValue('RefreshTime');
        all_data.includes('BlockUser') && GM_deleteValue('BlockUser');
        all_data.includes('DetectConcerns') && GM_deleteValue('DetectConcerns');
        all_data.includes('DetectMedal') && GM_deleteValue('DetectMedal');
        all_data.includes('DetectRepost') && GM_deleteValue('DetectRepost');
        all_data.includes('TagSize') && GM_deleteValue('TagSize');
        tagClass_hide.checked = GM_getValue('TagClassHide', false);
        Style_tagClassHide.innerHTML = tagClassHide[String(tagClass_hide.checked)];
        AutoDetect = GM_getValue('AutoDetect', false);
        detection_mode.checked = AutoDetect;
        DetectOption = GM_getValue('DetectOption', { Repost: false, Concerns: false, Medal: false });
        ({ Repost: detect_repost.checked, Concerns: detect_concerns.checked, Medal: detect_medal.checked } = DetectOption);
        BlockOption = GM_getValue('BlockOption', { User: false, Comment: false, Dynamic: false, Video: false });
        ({ User: block_user.checked, Comment: block_comment.checked, Dynamic: block_dynamic.checked, Video: block_video.checked } = BlockOption);
        blackList = new Set(GM_getValue('BlackList', []));
        tagMerge = GM_getValue('TagMerge', false);
        tag_merge.checked = tagMerge;
        link_delete.checked = GM_getValue('NoJump', false);
        close_comment.checked = GM_getValue('CloseComment', false);
        dynamic_btn.checked = GM_getValue('DynamicLike', false);
        script_like.style.display = dynamic_btn.checked ? 'block' : 'none';
        GM_getValue('Keyword', []).map((key) => addKeyWord(key));
        Object.values(GM_getValue('Tag', {})).map((i) => { addTag(i); });
    }
    const tagList = new TagList();
    const temp_keyword = {};
    const MedalDict = {};
    let tag = {};
    let keyword = [];
    let tagMerge = false;
    let MedalShow = false;
    let AutoDetect = false;
    let DetectOption = { Repost: false, Concerns: false, Medal: false };
    let BlockOption = { User: false, Comment: false, Dynamic: false, Video: false };
    let blackList = new Set();
    configInit();
    switch (Page) {
        case 'Main':
            mainPageBlock();
            hideOption({ Medal: true, Comment: true, Like: true, Link: true });
            break;
        case 'Dynamic':
            dynamicPageBlock();
            tagInsertObserver();
            closeComment();
            hideOption({ Medal: true, Comment: false, Like: false, Link: true });
            break;
        case 'Video':
            tagInsertObserver();
            hideOption({ Medal: false, Comment: true, Like: true, Link: false });
            break;
        default:
            tagInsertObserver();
            hideOption({ Medal: true, Comment: true, Like: true, Link: false });
    }
})();