Greasy Fork

Greasy Fork is available in English.

仙家军成分查询Helper

用于标记仙家军和动态转发仙以及使用仙话术的b站用户。可能存在误伤,请注意辨别。标记仅供参考,不建议直接作为“依据”使用。

当前为 2023-12-11 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         仙家军成分查询Helper
// @namespace    www.bilibili.com
// @version      1.6.0
// @description  用于标记仙家军和动态转发仙以及使用仙话术的b站用户。可能存在误伤,请注意辨别。标记仅供参考,不建议直接作为“依据”使用。
// @author       Darknights
// @match        https://*.bilibili.com/*
// @match        https://*.biligame.com/detail/?id=*
// @exclude      https://message.bilibili.com/*
// @exclude      https://manga.bilibili.com/*
// @exclude      https://www.bilibili.com/correspond/*
// @exclude      https://www.bilibili.com/page-proxy/*
// @exclude      https://live.bilibili.com/*
// @exclude      https://search.bilibili.com/*
// @icon         https://static.hdslb.com/images/favicon.ico
// @connect      bilibili.com
// @connect      biligame.com
// @connect      fastly.jsdelivr.net
// @connect      raw.githubusercontent.com
// @grant        GM_xmlhttpRequest
// @grant        GM_info
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @license      MIT
// @run-at       document-end
// ==/UserScript==

'use strict';

// 以下为网络名单
let xianList;
let xianFavList;
let xianWordList;
let xianLeakList;
let ignoreList;
let aidList;

//以下为本地名单,请在脚本编辑器-存储区自行添加,关键词列表均为字符串形式,注意要转义反斜杠
// 大部分为仙,少数可能有误判
const localXianList = GM_getValue("localXianList", []);

// 转发者常见仙的,包含且不限于一些up主/被仙缠上的人等等
const localXianFavList = GM_getValue("localXianFavList", []);

// 无视官号和无关号的动态,防止匹配到关键词浪费标签
const localIgnoreList = GM_getValue("localIgnoreList", []);

// 仙可能会用的词汇
const localXianWordList = GM_getValue("localXianWordList", []);

// 被开盒者隐私信息,需要特殊处理故与关键词列表区分
const localXianLeakList = GM_getValue("localXianLeakList", []);

// 辅助,因为有些正则匹配返回值为空
const localAidList = GM_getValue("localAidList", []);

const recordMap = new Map();
const uidSet = new Set();

const xianTag = ["仙", "#11DD77"];
const localXianTag = ["仙(本地)", "#11DD77"];

const xianRepostTag = ["转发仙:", "#1E971E"];
const localXianRepostTag = ["转发仙(本地):", "#1E971E"];

const favRepostTag = ["转发:", "#2C9EFF"];
const localFavRepostTag = ["转发(本地):", "#2C9EFF"];

const xianWordTag = ["命中:", "#04AEAB"];
const localXianWordTag = ["命中(本地):", "#04AEAB"];

const apiTag = ["出错,点此消除", "#FF3434"];

const refreshTag = ["然后点此🔄", "#FF7B00"];

const newVerTag = ["*已有新版本*", "#990CD0"];

const BLOG_URL = "https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?&host_mid=";

const BILI_URL = "https://t.bilibili.com/";

const SCRIPT_URL = "http://greasyfork.icu/zh-CN/scripts/467197";

const PRIVATE_TIPS = "*已隐藏,注意可能是无关话题被匹配*";

const XIAN_MATCH_TIPS = "*仙或其拥护者,可能存在误判,请注意辨别*";

const NEW_VERSION_TIPS = "*点击跳转安装页,更多功能尽在新版本*";


const CheckType = {
    Profile: 0,
    Comment: 1,
    At: 2,
    Reference: 3,
    Repo: 4,
    Follow: 5,
    GameComment: 6
}

const urlSourceDic = {
    githubusercontent: "https://raw.githubusercontent.com/Darknights1750/XianLists/main/xianLists.json",
    jsdelivr: "https://fastly.jsdelivr.net/gh/Darknights1750/XianLists@main/xianLists.json"
}

const statusDic = {
    0: "脚本已暂停⚠️",
    1: "脚本运行中✅"
}


let updateTime;
let onlineVersion;
let isLatestVersion = false;
let clearAllMenuId;
let urlSourceMenuId;
let statusMenuId;


const commandClearAll = function () {
    Array.prototype.slice.call(document.getElementsByClassName('xian')).forEach((item) => {
        item.remove()
    })
    Array.prototype.slice.call(document.getElementsByClassName('xian-fail')).forEach((item) => {
        item.remove()
    })
}

const commandUrlSource = function () {
    GM_unregisterMenuCommand(urlSourceMenuId);
    if ("jsdelivr" === GM_getValue("urlSource", "jsdelivr")) {
        GM_setValue("urlSource", "githubusercontent");
    } else {
        GM_setValue("urlSource", "jsdelivr");
    }
    urlSourceMenuId = GM_registerMenuCommand("切换数据源(刷新生效)|当前" + GM_getValue("urlSource", "jsdelivr"), commandUrlSource);
}

const commandStatus = function () {
    GM_unregisterMenuCommand(statusMenuId);
    if (1 === GM_getValue("status", 1)) {
        GM_setValue("status", 0);
    } else {
        GM_setValue("status", 1);
    }
    statusMenuId = GM_registerMenuCommand("暂停/启动脚本|当前" + statusDic[GM_getValue("status", 1)], commandStatus);
}

const initSettings = function () {
    // 0:不开启,1:开启
    if (null === GM_getValue("timeInterval", null)) GM_setValue("timeInterval", 2500); // 标签处理间隔时间 单位:ms
    if (null === GM_getValue("testLog", null)) GM_setValue("testLog", 0); // 是否开启调试日志
    if (null === GM_getValue("previewLength", null)) GM_setValue("previewLength", 60); // 文本预览长度
    if (null === GM_getValue("usingCheckProfile", null)) GM_setValue("usingCheckProfile", 1); // 是否监测个人主页UID
    if (null === GM_getValue("usingCheckComments", null)) GM_setValue("usingCheckComments", 1); // 是否监测评论区
    if (null === GM_getValue("usingCheckRepos", null)) GM_setValue("usingCheckRepos", 1); // 是否监测转发区
    if (null === GM_getValue("usingCheckReferences", null)) GM_setValue("usingCheckReferences", 1); // 是否监测动态被转发者
    if (null === GM_getValue("usingCheckAts", null)) GM_setValue("usingCheckAts", 1); // 是否监测@他人
    if (null === GM_getValue("usingCheckFollows", null)) GM_setValue("usingCheckFollows", 1); // 是否监测关注/粉丝列表
    if (null === GM_getValue("usingCheckGameComments", null)) GM_setValue("usingCheckGameComments", 1); // 是否监测游戏评价区
    if (null === GM_getValue("localXianList", null)) GM_setValue("localXianList", []);
    if (null === GM_getValue("localXianFavList", null)) GM_setValue("localXianFavList", []);
    if (null === GM_getValue("localIgnoreList", null)) GM_setValue("localIgnoreList", []);
    if (null === GM_getValue("localXianWordList", null)) GM_setValue("localXianWordList", []);
    if (null === GM_getValue("localXianLeakList", null)) GM_setValue("localXianLeakList", []);
    if (null === GM_getValue("localAidList", null)) GM_setValue("localAidList", []);
    clearAllMenuId = GM_registerMenuCommand("清空本页所有标签", commandClearAll);
    urlSourceMenuId = GM_registerMenuCommand("切换数据源(刷新生效)|当前" + GM_getValue("urlSource", "jsdelivr"), commandUrlSource);
    statusMenuId = GM_registerMenuCommand("暂停/启动脚本|当前" + statusDic[GM_getValue("status", 1)], commandStatus);
}


const log = function (message) {
    return GM_getValue("testLog", 0) ? console.log(message) : null;
};

const spawnHtml = function (data, text) {
    return `<a class="xian" style='color: ${data[1]} !important' title='${text}' target='_blank'>&lt;${data[0]}&gt;</a>`;
}

const spawnApiHtml = function (data) {
    return `<a class="xian-fail" style='color: ${data[1]} !important' href='https://space.bilibili.com/208259/dynamic' target='_blank'>&lt;${data[0]}&gt;</a>`;
}

const spawnRefreshHtml = function (data) {
    return `<a class="xian-fail" style='color: ${data[1]} !important' target='_blank' onclick='refreshTags()'>&lt;${data[0]}&gt;</a>`;
}

const spawnHtmlWithRef = function (data, word, link, text) {
    return `<a class="xian" style='color: ${data[1]} !important' href='${link}' title='${text}' target='_blank'>&lt;${data[0]}${word}&gt;</a>`;
}

// 检测是不是新版
const isNew = function () {
    if (location.host === 'space.bilibili.com') {
        return true;
    }
    if (document.getElementsByClassName('item goback').length > 0) {
        return true;
    }
    if (document.getElementsByClassName('app-v1').length > 0) {
        return true;
    }
    if (document.getElementsByClassName('opus-detail').length > 0) {
        return true;
    }
    if (document.getElementsByClassName('bgc').length > 0) {
        return true;
    }
    return false;
};

const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay));

const getXianListOnline = function () {
    return new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
            method: "GET",
            url: urlSourceDic[GM_getValue("urlSource", "jsdelivr")],
            data: '',
            headers: {
                'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
            },
            onload: res => {
                if (res.status === 200) {
                    resolve(JSON.parse(res.responseText));
                } else {
                    resolve(JSON.parse('{"xianList":[],"xianFavList":[],"xianWordList":[]}'));
                }
            }
        });
    });
}

const createScriptFun = function () {
    let refreshTagsScript = document.createElement('script');
    refreshTagsScript.innerText = `const refreshTags=function(){Array.prototype.slice.call(document.getElementsByClassName('xian-fail')).forEach((item)=>{item.remove()})}`;
    document.head.appendChild(refreshTagsScript);
}

const compareVersions = function (curVer, netArr) {
    var curArr = curVer.split('.');
    var netArr = netArr.split('.');
    for (var i = 0; i < Math.max(curArr.length, netArr.length); i++) {
        var curNum = parseInt(curArr[i] || 0);
        var netNum = parseInt(netArr[i] || 0);

        if (curNum < netNum) {
            return 1;
        }
        if (curNum > netNum + 10 || !/^\d+$/.test(curNum) || !/^\d+$/.test(netNum)) {
            return 2;
        }
        if (curNum > netNum) {
            return -1;
        }
    }
    return 0;
}

const fillLists = async function () {
    let json = await getXianListOnline();
    xianList = json.xianList;
    xianFavList = json.xianFavList;
    ignoreList = [...localIgnoreList, ...json.ignoreList];
    xianWordList = json.xianWordList.map((item) => new RegExp(item));
    xianLeakList = json.xianLeakList.map((item) => new RegExp(item));
    aidList = json.aidList.map((item) => new RegExp(item));
    aidList = [...aidList, ...localAidList];
    updateTime = json.updateTime;
    onlineVersion = json.version;
}

const runHelper = function () {

    /* Functions */
    const isBlank = function (str) {
        if (!str || /^\s*$/.test(str)) {
            return true;
        }
        return false;
    }

    const getUid = function (htmlEntity, checkType) {
        if (checkType === CheckType.Profile) {
            return window.location.href.match(/(?<=space\.bilibili\.com\/)\d+/)[0];
        }
        if (checkType === CheckType.Comment) {
            return isNew() ? htmlEntity.dataset.userId : htmlEntity.children[0].href.replace(/[^\d]/g, "");
        }
        if (checkType === CheckType.Repo) {
            return htmlEntity._profile.uid;
        }
        if (checkType === CheckType.At) {
            return htmlEntity.dataset.oid ? htmlEntity.dataset.oid : htmlEntity.dataset.userId;
        }
        if (checkType === CheckType.Reference) {
            return htmlEntity._profile.uid;
        }
        if (checkType === CheckType.Follow) {
            return htmlEntity.parentElement.href.replace(/[^\d]/g, "");
        }
        if (checkType === CheckType.GameComment) {
            return htmlEntity.href.replace(/[^\d]/g, "");
        }
    }

    const getName = function (htmlEntity, checkType) {
        if (checkType === CheckType.Profile) {
            return htmlEntity.innerText;
        }
        if (checkType === CheckType.Comment) {
            return isNew() ? htmlEntity.innerText : htmlEntity.children[0].innerText;
        }
        if (checkType === CheckType.Repo) {
            return htmlEntity.innerText;
        }
        if (checkType === CheckType.At) {
            return htmlEntity.innerText.replace(/@/g, "");
        }
        if (checkType === CheckType.Reference) {
            return htmlEntity.innerText;
        }
        if (checkType === CheckType.Follow) {
            return htmlEntity.innerText;
        }
        if (checkType === CheckType.GameComment) {
            return htmlEntity.innerText;
        }
    }

    const getCommentList = function () {
        if (isNew()) {
            const lst = new Set();
            for (let c of document.getElementsByClassName('user-name')) {
                lst.add(c);
            }
            for (let c of document.getElementsByClassName('sub-user-name')) {
                lst.add(c);
            }
            return Array.from(lst);
        } else {
            return document.getElementsByClassName('user');
        }
    }

    const getRepoList = function () {
        return document.getElementsByClassName('bili-dyn-forward-item__uname');
    }

    const getReferenceList = function () {
        return document.getElementsByClassName('dyn-orig-author__name');
    }

    const getFollowList = function () {
        return Array.from(document.getElementsByClassName('fans-name'));
    }

    const getGameCommentList = function () {
        return Array.from(document.querySelectorAll("a.user-name"));
    }

    const getAtList = function () {
        const lst = new Set();
        for (let c of document.getElementsByClassName('jump-link user')) {
            lst.add(c);
        }
        for (let c of document.getElementsByClassName('bili-rich-text-module at')) {
            lst.add(c);
        }
        return Array.from(lst);
    }

    const spliceText = function (moduleDynamic) {
        let fullTextArr = [];
        if (moduleDynamic.topic != null && !isBlank(moduleDynamic.topic.name)) {
            fullTextArr.push(moduleDynamic.topic.name);
        }
        if (moduleDynamic.desc != null && !isBlank(moduleDynamic.desc.text)) {
            fullTextArr.push(moduleDynamic.desc.text);
        }
        if (moduleDynamic.major != null) {
            if (moduleDynamic.major.archive != null) {
                if (!isBlank(moduleDynamic.major.archive.title)) {
                    fullTextArr.push(moduleDynamic.major.archive.title);
                }
                if (!isBlank(moduleDynamic.major.archive.desc)) {
                    fullTextArr.push(moduleDynamic.major.archive.desc);
                }
            }
            if (moduleDynamic.major.article != null) {
                if (!isBlank(moduleDynamic.major.article.title)) {
                    fullTextArr.push(moduleDynamic.major.article.title);
                }
                if (!isBlank(moduleDynamic.major.article.desc)) {
                    fullTextArr.push(moduleDynamic.major.article.desc);
                }
            }
            if (moduleDynamic.major.live != null && !isBlank(moduleDynamic.major.live.title)) {
                fullTextArr.push(moduleDynamic.major.live.title);
            }
        }
        if (moduleDynamic.additional != null && moduleDynamic.additional.ugc != null && !isBlank(moduleDynamic.additional.ugc.title)) {
            fullTextArr.push(moduleDynamic.additional.ugc.title);
        }
        return fullTextArr.join('//');
    }

    const previewText = function (text, index, len) {
        const left = Math.max(0, index - len);
        const right = Math.min(text.length, index + len);
        let textPart = '';
        if (left > 0) {
            textPart += '...';
        }
        textPart += text.substring(left, right).replace(/\n|\r/g, '').trim();
        if (right < text.length) {
            textPart += '...';
        }
        return textPart;
    }

    const findRepost = function (items, ownId, isFav, isLocal) {
        const usingList = isLocal ? (isFav ? localXianFavList : localXianList) : (isFav ? xianFavList : xianList);
        for (let i = 0; i < items.length; i++) {
            const item = items[i];
            for (const key in item) {
                if (key === 'orig') {
                    const origId = String(item.orig.modules.module_author.mid);
                    if (origId === ownId) {
                        return null;
                    }
                    if (usingList.indexOf(origId) > -1) {
                        const origName = String(item.orig.modules.module_author.name);
                        const ownFullText = spliceText(item.modules.module_dynamic);
                        const origFullText = spliceText(item.orig.modules.module_dynamic);
                        const ownTextPart = previewText(ownFullText, 0, GM_getValue("previewLength", 60));
                        const origTextPart = previewText(origFullText, 0, GM_getValue("previewLength", 60));
                        const bothTextPart = `${ownTextPart}//@${origName}:${origTextPart}`;
                        return [origId, origName, String(item.id_str), bothTextPart];
                    }
                }
            }
        }
        return null;
    }

    const hear = function (text, name, isLocal) {
        if (isBlank(text) || ignoreList.indexOf(name) > -1) {
            return null;
        }
        const usingWordList = isLocal ? localXianWordList : xianWordList;
        const usingLeakList = isLocal ? localXianLeakList : xianLeakList;
        for (const word of usingWordList) {
            const matchRes = text.match(word);
            if (matchRes != null) {
                let matchStr = matchRes[0];
                let matchIndex = matchRes.index;
                if (matchStr === '') {
                    for (const aidWord of aidList) {
                        const matchAid = text.match(aidWord);
                        if (matchAid != null) {
                            matchStr = matchAid[0];
                            matchIndex = matchAid.index;
                            break;
                        }
                    }
                }
                matchStr = matchStr.replace(/\n|\r/g, '').trim();
                return [matchStr, matchIndex + matchStr.length / 2];
            }
        }
        for (const word of usingLeakList) {
            const matchRes = text.match(word);
            if (matchRes != null) {
                return ['可能是盒隐私', -1];
            }
        }
        return null;
    }

    /**
     * 查找关键词
     * @param {} items 动态列表
     * @returns [关键词,动态id,动态片段]
     */
    const findWord = function (items, ownName, matchedDynamicList, isLocal) {
        for (let i = 0; i < items.length; i++) {
            const item = items[i];
            if (matchedDynamicList.indexOf(String(item.id_str)) > -1) {
                continue;
            }
            let origName;
            let ownFullText = spliceText(item.modules.module_dynamic);
            let origFullText;
            let ownTextPart;
            let origTextPart;
            let returnWord; // 关键词
            let returnPart; // 预览文本
            for (const key in item) {
                if (key === 'orig') {
                    origName = String(item.orig.modules.module_author.name);
                    origFullText = spliceText(item.orig.modules.module_dynamic);
                    break;
                }
            }
            const ownMatch = hear(ownFullText, ownName, isLocal);
            const origMatch = hear(origFullText, origName, isLocal);
            if (ownMatch == null && origMatch == null) {
                continue;
            }
            if (ownMatch == null) {
                returnWord = '🔁' + origMatch[0];
            } else {
                returnWord = ownMatch[0];
            }
            const ownIndex = ownMatch ? ownMatch[1] : 0;
            const origIndex = origMatch ? origMatch[1] : 0;
            ownTextPart = ownIndex < 0 ? PRIVATE_TIPS : previewText(ownFullText, ownIndex, GM_getValue("previewLength", 60) / 2);
            returnPart = ownTextPart;
            if (!isBlank(origName)) {
                origTextPart = origIndex < 0 ? PRIVATE_TIPS : previewText(origFullText, origIndex, GM_getValue("previewLength", 60) / 2);
                returnPart = ownTextPart + `//@${origName}:${origTextPart}`;
            }
            return [returnWord, String(item.id_str), returnPart];
        }
        return null;
    }

    //检查记录
    const findRecord = async function (uid, name) {
        let oldTag;
        if (recordMap.has(uid)) {
            oldTag = recordMap.get(uid);
            uidSet.delete(uid);
            if (oldTag) {
                log(`[xian-helper]>>Record:${name}@UID-${uid}>>find>>${oldTag.replaceAll(/<\/?a.*?>/g, "").replaceAll(/&gt;&lt;/g, "、").replaceAll(/&.t;/g, "")}`);
            }
        } else if (uidSet.has(uid)) {
            await sleep(500);
            oldTag = findRecord(uid, name);
        } else {
            uidSet.add(uid);
        }
        return oldTag;
    }

    const checkEntity = async function (htmlEntity, checkType) {
        if (htmlEntity.innerHTML.indexOf(`<span class="xian`) === -1) {
            let xianSpan = document.createElement('span');
            xianSpan.className = 'xian';
            htmlEntity.appendChild(xianSpan);
            if (compareVersions(GM_info.script.version, onlineVersion) > 0) {
                htmlEntity.innerHTML += spawnHtmlWithRef(newVerTag, '', SCRIPT_URL, NEW_VERSION_TIPS);
            }
            const uid = String(getUid(htmlEntity, checkType));
            if (isBlank(uid)) {
                return;
            }
            const name = getName(htmlEntity, checkType).trim();
            if (ignoreList.indexOf(name) > -1) {
                return;
            }
            let oldTag = await findRecord(uid, name);

            if (oldTag != null) {
                htmlEntity.innerHTML += oldTag;
            } else {
                GM_xmlhttpRequest({
                    method: "get",
                    url: BLOG_URL + uid,
                    data: '',
                    headers: {
                        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
                    },
                    onload: res => {
                        if (res.status === 200) {
                            let newTag = '';
                            if (xianList.indexOf(uid) > -1) {
                                log(`[xian-helper]>>Find Target:${name}@UID-${uid}>>${checkType}`);
                                newTag += spawnHtml(xianTag, XIAN_MATCH_TIPS);
                            }
                            if (localXianList.indexOf(uid) > -1) {
                                log(`[xian-helper]>>Find Local Target:${name}@UID-${uid}>>${checkType}`);
                                newTag += spawnHtml(localXianTag, XIAN_MATCH_TIPS);
                            }
                            const dynamicJson = JSON.parse(res.response).data;
                            if (dynamicJson) {
                                if (dynamicJson.items) {
                                    let matchedDynamicList = [];
                                    const repostMatch = findRepost(dynamicJson.items, uid, false, false);
                                    if (repostMatch != null) {
                                        matchedDynamicList.push(repostMatch[2]);
                                        log(`[xian-helper]>>Find Repost:${name}@UID-${uid}>>repost>>${repostMatch[1]}@UID-${repostMatch[0]}>>${checkType}`);
                                        const fixedText = repostMatch[1].length > 12 ? repostMatch[1].slice(0, 9) + '...' : repostMatch[1];
                                        newTag += spawnHtmlWithRef(xianRepostTag, fixedText, BILI_URL + repostMatch[2], repostMatch[3]);
                                    } else {
                                        const localRepostMatch = findRepost(dynamicJson.items, uid, false, true);
                                        if (localRepostMatch != null) {
                                            matchedDynamicList.push(repostMatch[2]);
                                            log(`[xian-helper]>>Find Local Repost:${name}@UID-${uid}>>repost>>${repostMatch[1]}@UID-${repostMatch[0]}>>${checkType}`);
                                            const fixedText = repostMatch[1].length > 12 ? repostMatch[1].slice(0, 9) + '...' : repostMatch[1];
                                            newTag += spawnHtmlWithRef(localXianRepostTag, fixedText, BILI_URL + repostMatch[2], repostMatch[3]);
                                        }
                                    }
                                    const favRepostMatch = findRepost(dynamicJson.items, uid, true, false);
                                    if (favRepostMatch != null) {
                                        matchedDynamicList.push(favRepostMatch[2]);
                                        log(`[xian-helper]>>Find Fav:${name}@UID-${uid}>>repost>>${favRepostMatch[1]}@UID-${favRepostMatch[0]}>>${checkType}`);
                                        const fixedText = favRepostMatch[1].length > 12 ? favRepostMatch[1].slice(0, 9) + '...' : favRepostMatch[1];
                                        newTag += spawnHtmlWithRef(favRepostTag, fixedText, BILI_URL + favRepostMatch[2], favRepostMatch[3]);
                                    } else {
                                        const localFavRepostMatch = findRepost(dynamicJson.items, uid, true, true);
                                        if (localFavRepostMatch != null) {
                                            matchedDynamicList.push(favRepostMatch[2]);
                                            log(`[xian-helper]>>Find Local Fav:${name}@UID-${uid}>>repost>>${favRepostMatch[1]}@UID-${favRepostMatch[0]}>>${checkType}`);
                                            const fixedText = favRepostMatch[1].length > 12 ? favRepostMatch[1].slice(0, 9) + '...' : favRepostMatch[1];
                                            newTag += spawnHtmlWithRef(localFavRepostTag, fixedText, BILI_URL + favRepostMatch[2], favRepostMatch[3]);
                                        }
                                    }
                                    const wordMatch = findWord(dynamicJson.items, name, matchedDynamicList, false);
                                    if (wordMatch != null) {
                                        log(`[xian-helper]>>Find Word:${name}@UID-${uid}>>say>>${wordMatch[0]}>>${checkType}`);
                                        const fixedText = wordMatch[0].length > 12 ? wordMatch[0].slice(0, 9) + '...' : wordMatch[0];
                                        newTag += spawnHtmlWithRef(xianWordTag, fixedText, BILI_URL + wordMatch[1], wordMatch[2]);
                                    } else {
                                        const localWordMatch = findWord(dynamicJson.items, name, matchedDynamicList, true);
                                        if (localWordMatch != null) {
                                            log(`[xian-helper]>>Find Local Word:${name}@UID-${uid}>>say>>${wordMatch[0]}>>${checkType}`);
                                            const fixedText = wordMatch[0].length > 12 ? wordMatch[0].slice(0, 9) + '...' : wordMatch[0];
                                            newTag += spawnHtmlWithRef(localXianWordTag, fixedText, BILI_URL + wordMatch[1], wordMatch[2]);
                                        }
                                    }
                                }
                                htmlEntity.innerHTML += newTag;
                                recordMap.set(uid, newTag);
                            } else {
                                xianSpan.className = 'xian-fail';
                                htmlEntity.innerHTML += spawnApiHtml(apiTag);
                                htmlEntity.innerHTML += spawnRefreshHtml(refreshTag);
                                uidSet.delete(uid);
                                log('[xian-helper]仙家军成分查询Helper get dynamic fail...');
                                log(htmlEntity);
                                log(res);
                            }
                        } else {
                            xianSpan.className = 'xian-fail';
                            log('[xian-helper]仙家军成分查询Helper request fail...');
                            log(htmlEntity);
                            log(res);
                        }
                    },
                });
            }
        }
    }

    const checkComments = function () {
        const commentlist = getCommentList();
        if (commentlist != null && commentlist.length > 0) {
            commentlist.forEach(htmlEntity => {
                checkEntity(htmlEntity, CheckType.Comment);
            });
        }
    }

    const checkRepos = function () {
        const repolist = getRepoList();
        if (repolist != null && repolist.length > 0) {
            repolist.forEach(htmlEntity => {
                checkEntity(htmlEntity, CheckType.Repo);
            });
        }
    }

    const checkAts = function () {
        const atList = getAtList();
        if (atList != null && atList.length > 0) {
            atList.forEach(htmlEntity => {
                checkEntity(htmlEntity, CheckType.At);
            });

        }
    }

    const checkReferences = function () {
        const referenceList = getReferenceList();
        if (referenceList != null && referenceList.length > 0) {
            referenceList.forEach(htmlEntity => {
                checkEntity(htmlEntity, CheckType.Reference);
            });
        }
    }

    const checkFollows = function () {
        const followList = getFollowList();
        if (followList != null && followList.length > 0) {
            followList.forEach(htmlEntity => {
                checkEntity(htmlEntity, CheckType.Follow);
            });
        }
    }

    const checkProfile = async function () {
        let htmlEntity = document.getElementById('h-name');
        if (htmlEntity != null) {
            checkEntity(htmlEntity, CheckType.Profile);
        }
    }

    const checkGameComments = async function () {
        const gameCommentList = getGameCommentList();
        if (gameCommentList != null && gameCommentList.length > 0) {
            gameCommentList.forEach(htmlEntity => {
                checkEntity(htmlEntity, CheckType.GameComment);
            });
        }
    }

    log(`[xian-helper]仙家军成分查询Helper,启动!
[xian-helper]>>isNew: ${isNew()}
[xian-helper]>>Loading: ${window.location.href}
[xian-helper]>>urlSource: ${GM_getValue("urlSource", "jsdelivr")}
[xian-helper]>>List update time: ${updateTime}
`)

    setInterval(() => {
        if (GM_getValue("status", 1)) {
            if (location.host === "www.biligame.com") {
                if (GM_getValue("usingCheckGameComments", 1)) {
                    checkGameComments();
                }
            } else {
                if (GM_getValue("usingCheckComments", 1)) {
                    checkComments();
                }
                if (GM_getValue("usingCheckRepos", 1)) {
                    checkRepos();
                }
                if (GM_getValue("usingCheckReferences", 1)) {
                    checkReferences();
                }
                if (GM_getValue("usingCheckAts", 1)) {
                    checkAts();
                }
                if (location.host === "space.bilibili.com") {
                    if (GM_getValue("usingCheckProfile", 1)) {
                        checkProfile();
                    }
                    if (GM_getValue("usingCheckFollows", 1)) {
                        checkFollows();
                    }
                }
            }
        }
    }, GM_getValue("timeInterval", 2500));
}

const start = async function () {
    initSettings();
    createScriptFun();
    await fillLists();
    runHelper();
}

start();