@shenzi#soushuba_tid_tmp

搜书吧 缓存tid

// ==UserScript==
// @name         @shenzi#soushuba_tid_tmp
// @name:zh-CN   @神紫#小说网站 搜书吧 缓存tid
// @namespace    http://tampermonkey.net/
// @version      1.0.6
// @description  搜书吧 缓存tid
// @author       神紫
// @match        *://vsdf.n.rkggs5f4e5asf.com/*
// @match        *://v.asf.nupt4j5yt4.com/*
// @match        *://s.dg.b4yh4tyj46.com/*
// @match        *://p6.36.nu6kiu4yuk5.com/*
// @match        *://u0.k1.2ijtyj454.com/*
// @match        *://52n.mf.56sdfwef45.com/*
// @match        *://62df.th.9ef56erg.com/*
// @match        *://upq.asd6.sa5f6dff3f12.com/*
// @match        *://q1.v.agrth45tge.com/*
// @match        *://b6d.vb.2bhrg1e54.com/*
// @match        *://cc96.c3.c3sdefwewer.com/*
// @match        *://33ty.hk.sdvs4df4e5f4.com/*
// @match        *://nhg.69.tj55tg4y5asd.com/*
// @match        *://gdr.6d9g.b172gf1r5g.com/*
// @match        *://g9dr.bnm.9vdrg4er5.com/*
// @match        *://sxsy77.com/*
// @match        *://sxsy122.com/*
// @match        *://sxsy19.com/*
// @match        *://404ba.com/*
// @match        *://404zu.com/*
// @match        *://404zu.net/*
// @match        *://404zu.org/*
// @match        *://404ku.com/*
// @icon         https://b6d.vb.2bhrg1e54.com/favicon.ico
// @icon         https://sxsy19.com/favicon.ico
// @icon         https://404ku.com/favicon.ico
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// @grant        GM_setClipboard
// @grant        GM_registerMenuCommand
// @license      MIT
// ==/UserScript==



"use strict";
(function () {
    class DecimalBase64To {
        static base64Code = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/";
        static decToB64(decimal) {
            if (decimal === 0)
                return this.base64Code[0];
            const base64Arr = [];
            while (decimal > 0) {
                const remainder = decimal % 64;
                base64Arr.push(this.base64Code[remainder]);
                decimal = Math.floor((decimal - remainder) / 64);
            }
            return base64Arr.reverse().join("");
        }
        static b64ToDec(base64) {
            let decimal = 0;
            for (let i = 0; i < base64.length; i++) {
                const value = this.base64Code.indexOf(base64[i]);
                if (value === -1)
                    return NaN;
                decimal = decimal * 64 + value;
            }
            return decimal;
        }
    }
    class DataTmp {
        data_key;
        max_exist_time_get_data_tmp;
        black_flag;
        last_time_get_data_tmp = -1;
        data = "";
        constructor(data_key, black_flag = "|", max_exist_time_get_data_tmp = 30 * 1000) {
            this.data_key = data_key;
            this.black_flag = black_flag;
            this.max_exist_time_get_data_tmp = max_exist_time_get_data_tmp;
        }
        init() {
            this.data = GM_getValue(this.data_key, this.black_flag);
            this.last_time_get_data_tmp = Date.now();
        }
        _add(value) { this.data += `${value}${this.black_flag}`; }
        _del(value) { this.data = this.data.replace(`${this.black_flag}${value}${this.black_flag}`, this.black_flag); }
        _save() { GM_setValue(this.data_key, this.data); }
        exist(value) { return this.data.indexOf(`${this.black_flag}${value}${this.black_flag}`) !== -1; }
        init_tmp() { if (Date.now() - this.last_time_get_data_tmp >= this.max_exist_time_get_data_tmp) {
            this.init();
        } }
        add_unsave(value) {
            this.init_tmp();
            this._add(value);
        }
        add_save(value) {
            this.init();
            if (!this.exist(value)) {
                this._add(value);
                this._save();
            }
        }
        del_save(value) {
            this.init();
            if (this.exist(value)) {
                this._del(value);
                this._save();
            }
        }
        load(values) {
            this.init();
            let updated = false;
            for (const value of values) {
                if (!this.exist(value)) {
                    if (!updated)
                        updated = true;
                    this._add(value);
                }
            }
            if (updated) {
                this._save();
            }
        }
        dumps_fmt_dump(dumps) { return dumps.split(this.black_flag).map(dt => dt.trim()).filter(dt => dt.length !== 0); }
        fmt_data() { this.init(); return this.dumps_fmt_dump(this.data); }
        dump() { return this.fmt_data(); }
        dumps() { this.init(); return this.data; }
        optimize_sorted() {
            const dts = this.fmt_data();
            if (dts.length === 0)
                return;
            const data = dts.sort().join(this.black_flag);
            GM_setValue(this.data_key, `${this.black_flag}${data}${this.black_flag}`);
        }
    }
    class ImExData {
        static im_init = false;
        static im_open;
        static dm_init = false;
        static dm_open;
        static dts_exp_fail(dts) {
            const fails = [];
            dts.forEach((dat) => { if (isNaN(DecimalBase64To.b64ToDec(dat))) {
                fails.push(dat);
            } });
            return fails;
        }
        static load_im_dm_style() {
            const style = document.createElement("style");
            style.innerText = `
#confirm-dialog {
  border: none;
  border-radius: 8px;
  padding: 20px;
  min-width: 20em;
  width: 30em;
  max-width: 80%;
}

#confirm-dialog[data-state="init"] #confirm-content { border-color: #1f1f1f; }
#confirm-dialog[data-state="succeed"] #confirm-content { border-color: #7fff00; }
#confirm-dialog[data-state="fail"] #confirm-content { border-color: #ff0000; }

#confirm-content {
  min-width: 97%;
  max-width: 97%;
  min-height: 10em;
  height: 20em;
  max-height: 80vh;
}

#confirm-error { color: #ff0000; font-weight: bold; }
`;
            document.body.appendChild(style);
        }
        static load_im_element(data_key, data_ban_key, black_flag) {
            const confirmDialog = document.createElement("dialog");
            const confirmContent = document.createElement("textarea");
            const confirmError = document.createElement("p");
            const confirmPaste = document.createElement("button");
            const confirmSubmit = document.createElement("button");
            const confirmClose = document.createElement("button");
            confirmContent.placeholder = "请输入要导入的数据";
            confirmPaste.innerText = "导入剪切板的数据";
            confirmSubmit.innerText = "确定";
            confirmClose.innerText = "取消";
            confirmDialog.id = "confirm-dialog";
            confirmContent.id = "confirm-content";
            confirmError.id = "confirm-error";
            confirmPaste.id = "confirm-paste";
            confirmSubmit.id = "confirm-submit";
            confirmClose.id = "confirm-close";
            function msgOut(state, errorinfo, content) { confirmDialog.dataset.state = state; confirmError.innerText = errorinfo; confirmContent.value = content; }
            function initOut() { msgOut("init", "", ""); }
            function infoOut(content) { msgOut("succeed", "", content); }
            function errorOut(errorinfo, content = "") { msgOut("fail", errorinfo, content); }
            const initObj = () => {
                option_dbpack = null;
                initOut();
            };
            this.im_open = () => {
                confirmDialog.showModal();
                initObj();
            };
            const checkdata = () => {
                const importedData = confirmContent.value.trim();
                if (importedData.length === 0)
                    return errorOut("无数据");
                let idbpack;
                try {
                    idbpack = this.im_dbpack(importedData, this.allowKeys, black_flag);
                }
                catch (e) {
                    return errorOut(e.message);
                }
                let dt = new DataTmp(data_key, black_flag);
                const i10 = this.allowKeyCore in idbpack;
                const i20 = this.allowKeyBan in idbpack;
                const importedCoreData = i10 ? dt.dumps_fmt_dump(idbpack[this.allowKeyCore]) : [];
                const importedBanData = i20 ? dt.dumps_fmt_dump(idbpack[this.allowKeyBan]) : [];
                dt = null;
                const fails = this.dts_exp_fail(importedCoreData);
                if (fails.length !== 0)
                    return errorOut("↑↑↑❌浏览数据加载出错❌↑↑↑", importedCoreData.join(black_flag));
                const failBans = this.dts_exp_fail(importedBanData);
                if (failBans.length !== 0)
                    return errorOut("↑↑↑❌封禁数据加载出错❌↑↑↑", importedBanData.join(black_flag));
                option_dbpack = idbpack;
                if (!i10)
                    return infoOut(`封禁数据:\n${importedBanData.join(black_flag)}`);
                if (!i20)
                    return infoOut(`浏览数据:\n${importedCoreData.join(black_flag)}`);
                return infoOut(`浏览数据:\n${importedCoreData.join(black_flag)}\n${`${'-'.repeat(10)}\n`.repeat(3)}封禁数据:\n${importedBanData.join(black_flag)}`);
            };
            let option_dbpack;
            confirmContent.addEventListener("change", checkdata);
            confirmPaste.addEventListener("click", () => {
                navigator.clipboard.readText()
                    .then((text) => { confirmContent.value = text; checkdata(); })
                    .catch((err) => { alert(`无法从剪切板读取数据: ${err}`); });
            });
            confirmSubmit.addEventListener("click", () => {
                if (confirmDialog.dataset?.state !== "succeed")
                    return;
                if (option_dbpack === null)
                    return;
                let dt = new DataTmp(data_key, black_flag);
                const i10 = this.allowKeyCore in option_dbpack;
                const i20 = this.allowKeyBan in option_dbpack;
                const importedCoreData = i10 ? dt.dumps_fmt_dump(option_dbpack[this.allowKeyCore]) : [];
                const importedBanData = i20 ? dt.dumps_fmt_dump(option_dbpack[this.allowKeyBan]) : [];
                if (i10)
                    dt.load(importedCoreData);
                if (i20)
                    new DataTmp(data_ban_key, black_flag).load(importedBanData);
                dt = null;
                initObj();
                confirmDialog.close();
            });
            confirmClose.addEventListener("click", () => {
                if (confirmDialog === null)
                    return;
                initObj();
                confirmDialog.close();
            });
            confirmDialog.appendChild(confirmContent);
            confirmDialog.appendChild(confirmError);
            confirmDialog.appendChild(confirmPaste);
            confirmDialog.appendChild(confirmSubmit);
            confirmDialog.appendChild(confirmClose);
            document.body.appendChild(confirmDialog);
        }
        static add_dm_options(select, options, currOption) {
            const optionEls = [];
            for (const option of options) {
                if (option === currOption)
                    continue;
                const thisOption = option;
                const optionEl = document.createElement("option");
                optionEl.className = "option-other-web";
                optionEl.value = optionEl.innerText = thisOption;
                select.appendChild(optionEl);
                optionEls.push(optionEl);
            }
            return optionEls;
        }
        static remove_dm_options(select, options) {
            for (const option of options) {
                select.removeChild(option);
            }
            options.splice(0, options.length);
        }
        static load_dm_element(ksDt, ksBanDt, data_key, data_ban_key, black_flag) {
            const confirmDialog = document.createElement("dialog");
            const confirmTitle = document.createElement("select");
            const confirmOptionVoid = document.createElement("option");
            const confirmContent = document.createElement("textarea");
            const confirmError = document.createElement("p");
            const confirmSubmit = document.createElement("button");
            const confirmClose = document.createElement("button");
            confirmOptionVoid.innerText = "请选择网站";
            confirmOptionVoid.value = "null";
            confirmOptionVoid.selected = true;
            confirmContent.readOnly = true;
            confirmContent.placeholder = "请选择上方‘其他网站的数据’,\n以便装以‘该网站’的数据到‘本网站’。";
            confirmSubmit.innerText = "确定";
            confirmClose.innerText = "取消";
            confirmDialog.id = "confirm-dialog";
            confirmTitle.id = "confirm-selects";
            confirmContent.id = "confirm-content";
            confirmError.id = "confirm-error";
            confirmSubmit.id = "confirm-submit";
            confirmClose.id = "confirm-close";
            function msgOut(state, errorinfo, content) { confirmDialog.dataset.state = state; confirmError.innerText = errorinfo; confirmContent.value = content; }
            function initOut() { msgOut("init", "", ""); }
            function infoOut(content) { msgOut("succeed", "", content); }
            function errorOut(errorinfo, content = "") { msgOut("fail", errorinfo, content); }
            const initObj = () => {
                optionHt = null;
                if (options !== null)
                    this.remove_dm_options(confirmTitle, options);
                initOut();
                confirmOptionVoid.selected = true;
            };
            this.dm_open = () => {
                confirmDialog.showModal();
                initObj();
                options = this.add_dm_options(confirmTitle, ksDt.read_fmt_hts(), all_tid_dt.unfmt_host(data_key));
            };
            let optionHt;
            let options = null;
            confirmTitle.addEventListener("change", () => {
                const { selectedOptions } = confirmTitle;
                if (selectedOptions.length === 0)
                    return errorOut("异常程式-无选择");
                else if (selectedOptions.length > 1)
                    return errorOut("异常程式-多重选择");
                const selectedOption = selectedOptions[0];
                const optionHt2 = selectedOption.value;
                const importedData = new DataTmp(ksDt.fmt_key(optionHt2), black_flag).dump();
                const importedBanData = new DataTmp(ksBanDt.fmt_key(optionHt2), black_flag).dump();
                const i10 = importedData.length === 0;
                const i20 = importedBanData.length === 0;
                if (i10 && i20)
                    return errorOut("网站数据为空");
                const fails = this.dts_exp_fail(importedData);
                if (fails.length !== 0)
                    return errorOut("↑↑↑❌浏览数据加载出错❌↑↑↑", importedData.join(black_flag));
                const failBans = this.dts_exp_fail(importedBanData);
                if (failBans.length !== 0)
                    return errorOut("↑↑↑❌封禁数据加载出错❌↑↑↑", importedBanData.join(black_flag));
                optionHt = optionHt2;
                if (i10)
                    return infoOut(`封禁数据:\n${importedBanData.join(black_flag)}`);
                if (i20)
                    return infoOut(`浏览数据:\n${importedData.join(black_flag)}`);
                return infoOut(`浏览数据:\n${importedData.join(black_flag)}\n${`${'-'.repeat(10)}\n`.repeat(3)}封禁数据:\n${importedBanData.join(black_flag)}`);
            });
            confirmSubmit.addEventListener("click", () => {
                if (confirmDialog.dataset?.state !== "succeed")
                    return;
                if (optionHt === null)
                    return;
                const data_key2 = ksDt.fmt_key(optionHt);
                const data_ban_key2 = ksBanDt.fmt_key(optionHt);
                const dump_key2 = new DataTmp(data_key2, black_flag).dump();
                const dump_ban_key2 = new DataTmp(data_ban_key2, black_flag).dump();
                if (dump_key2.length !== 0)
                    new DataTmp(data_key, black_flag).load(dump_key2);
                if (dump_ban_key2.length !== 0)
                    new DataTmp(data_ban_key, black_flag).load(dump_ban_key2);
                ksDt.delete_key(data_key2);
                ksBanDt.delete_key(data_ban_key2);
                initObj();
                confirmDialog.close();
            });
            confirmClose.addEventListener("click", () => {
                if (confirmDialog === null)
                    return;
                initObj();
                confirmDialog.close();
            });
            confirmTitle.appendChild(confirmOptionVoid);
            confirmDialog.appendChild(confirmTitle);
            confirmDialog.appendChild(confirmContent);
            confirmDialog.appendChild(confirmError);
            confirmDialog.appendChild(confirmSubmit);
            confirmDialog.appendChild(confirmClose);
            document.body.appendChild(confirmDialog);
        }
        static optimize_sorted_base(ksDt, black_flag) {
            const keys = ksDt.read_keys();
            for (const key of keys) {
                let dt = new DataTmp(key, black_flag);
                dt.optimize_sorted();
                dt = null;
            }
        }
        static ex_dbpack_start(k, black_flag) { return `${k}${black_flag.repeat(2)}>>${k}>>>${black_flag.repeat(2)}`; }
        static ex_dbpack_end(k, black_flag) { return `${black_flag.repeat(2)}<<${k}<<<${black_flag.repeat(2)}`; }
        static ex_dbpack_split(black_flag) { return `${black_flag.repeat(2)}<>><><${black_flag.repeat(2)}`; }
        static allowKeyCore = "core";
        static allowKeyBan = "ban";
        static allowKeys = [this.allowKeyCore, this.allowKeyBan];
        static im_dbpack(dbpack, keys, black_flag) {
            const dbpacks = dbpack.split(this.ex_dbpack_split(black_flag));
            const eobj = {};
            for (const dbpack of dbpacks) {
                const [k] = dbpack.split(black_flag, 1);
                if (k in eobj)
                    throw new Error("数据key值重复");
                if (!keys.includes(k))
                    throw new Error(`${k}[k]不属于keys: ${JSON.stringify(keys)}`);
                const dbpack_start = this.ex_dbpack_start(k, black_flag);
                if (!dbpack.startsWith(dbpack_start))
                    throw new Error(`${dbpack_start}这个头部数据未能匹配到这个数据:${dbpack}`);
                const dbpack_end = this.ex_dbpack_end(k, black_flag);
                if (!dbpack.endsWith(dbpack_end))
                    throw new Error(`${dbpack_end}这个尾部数据未能匹配到这个数据:${dbpack}`);
                eobj[k] = dbpack.substring(dbpack_start.length, dbpack.length - dbpack_end.length);
            }
            return eobj;
        }
        static ex_dbpack(mp, black_flag) { return mp.map(([k, v]) => `${this.ex_dbpack_start(k, black_flag)}${v}${this.ex_dbpack_end(k, black_flag)}`).join(this.ex_dbpack_split(black_flag)); }
        static im(data_key, data_ban_key, black_flag) {
            if (!this.im_init) {
                this.im_init = true;
                if (!this.dm_init)
                    this.load_im_dm_style();
                this.load_im_element(data_key, data_ban_key, black_flag);
            }
            this.im_open?.();
        }
        static ex(data_key, data_ban_key, black_flag) {
            const dbpack = this.ex_dbpack([
                [this.allowKeyCore, new DataTmp(data_key, black_flag).dumps()],
                [this.allowKeyBan, new DataTmp(data_ban_key, black_flag).dumps()],
            ], black_flag);
            if (dbpack === "") {
                alert("写入剪贴板失败: tid数据为空");
            }
            else {
                try {
                    GM_setClipboard(dbpack);
                    alert("写入剪贴板成功!");
                }
                catch (error) {
                    alert("写入剪贴板失败: " + error);
                }
            }
        }
        static data_migration(ksDt, ksBanDt, data_key, data_ban_key, black_flag) {
            if (!this.dm_init) {
                this.dm_init = true;
                if (!this.im_init)
                    this.load_im_dm_style();
                this.load_dm_element(ksDt, ksBanDt, data_key, data_ban_key, black_flag);
            }
            this.dm_open?.();
        }
        static optimize_sorted(ksDt, ksBanDt, black_flag) {
            this.optimize_sorted_base(ksDt, black_flag);
            this.optimize_sorted_base(ksBanDt, black_flag);
        }
    }
    class KeysDt {
        mkey;
        constructor(mkey) { this.mkey = `#${mkey}`; }
        unfmt_host(key) { return key.substring(0, key.length - this.mkey.length); }
        fmt_key(host) { return `${host}${this.mkey}`; }
        check_key(key) { return key.endsWith(this.mkey); }
        delete_key(key) { this.check_key(key) ? GM_deleteValue(key) : undefined; }
        read_keys() { return GM_listValues().filter((key) => this.check_key(key)); }
        read_fmt_hts() { return this.read_keys().map((key) => this.unfmt_host(key)); }
    }
    function rCodeE(rCode, min = 4, max = 6) {
        const rcl = rCode.length;
        const rl = Math.floor(Math.random() * (max - min + 1)) + min;
        return new Array(rl).fill("")
            .map(() => rCode[Math.floor(Math.random() * rcl)])
            .join("");
    }
    function reset_gmdata(key, handle) {
        const rf = rCodeE(".0123456789");
        let userInput = prompt(`您正在进行一个危险的操作[${handle}],请输入这段字符串=> ${rf} <=以确保该操作是由您本人的发动的!`);
        if (userInput === null) {
            alert("❌操作已取消。❌");
        }
        else if (userInput === rf) {
            alert(`✔️输入正确,请确认此消息(Enter),操作[${handle}]将会运行。✔️`);
            GM_deleteValue(key);
        }
        else {
            alert("❌输入错误,操作已取消。❌");
        }
    }
    const all_tid_dt = new KeysDt("tid_datas");
    const all_tid_ban_dt = new KeysDt("tid_ban_datas");
    const tid_tmp_key = all_tid_dt.fmt_key(window.location.host);
    const tid_ban_tmp_key = all_tid_ban_dt.fmt_key(window.location.host);
    const tid_split = "|";
    GM_registerMenuCommand("重置tid浏览数据", () => reset_gmdata(tid_tmp_key, "重置tid浏览数据"));
    GM_registerMenuCommand("重置tid封禁数据", () => reset_gmdata(tid_ban_tmp_key, "重置tid封禁数据"));
    GM_registerMenuCommand("导出tid数据到剪切板", () => ImExData.ex(tid_tmp_key, tid_ban_tmp_key, tid_split));
    GM_registerMenuCommand("导入tid数据从剪切板", () => ImExData.im(tid_tmp_key, tid_ban_tmp_key, tid_split));
    GM_registerMenuCommand("迁移tid数据从缓存中", () => ImExData.data_migration(all_tid_dt, all_tid_ban_dt, tid_tmp_key, tid_ban_tmp_key, tid_split));
    GM_registerMenuCommand("tid数据顺序优化", () => ImExData.optimize_sorted(all_tid_dt, all_tid_ban_dt, tid_split));
    let ApplicationNames;
    (function (ApplicationNames) {
        ApplicationNames["soushuba"] = "\u641C\u4E66\u5427";
        ApplicationNames["sxsy"] = "\u5C1A\u9999\u4E66\u82D1";
        ApplicationNames["ba404"] = "404\u5427 - \u7F51\u7EDC\u5C0F\u8BF4\u4EA4\u6D41\u8BBA\u575B | 404\u7EC4 | 404KU | 404\u4E66\u5427";
    })(ApplicationNames || (ApplicationNames = {}));
    function getApplicationName() {
        const applicationNameMeta = document.querySelector('meta[name="application-name"]');
        if (applicationNameMeta === null)
            return null;
        let applicationName = applicationNameMeta.getAttribute('content');
        if (applicationName === null)
            return null;
        applicationName = applicationName.trim();
        const appName = Object.values(ApplicationNames).find(name => name.split("|").map(name => name.trim()).includes(applicationName));
        return appName ? appName : null;
    }
    function load_tid_style() {
        const style = document.createElement("style");
        style.innerHTML = `
#threadlisttableid tr[data-fidxexist="hide"] { display: none; }

#delform tr[data-banstate="init"][data-fidxexist="exist"]:hover td,
#delform tr[data-banstate="init"][data-fidxexist="exist"]:hover th,
#threadlisttableid tr[data-banstate="init"][data-fidxexist="exist"]:hover td,
#threadlisttableid tr[data-banstate="init"][data-fidxexist="exist"]:hover th { background: #0096fa; }

#delform tr[data-banstate="init"][data-fidxexist="exist"] th > a,
#threadlisttableid tr[data-banstate="init"][data-fidxexist="exist"] a.s.xst,
#threadlist ul li[data-banstate="init"][data-fidxexist="exist"] h3 a { color: snow; background: #0096fa; }

#threadlist ul li[data-fidxexist="exist"] h3 a strong font { color: snow; background: red; }

#delform tr[data-banstate="init"] td.icn,
#delform tr[data-banstate="ban"],
#threadlisttableid tr[data-banstate="init"] td.icn,
#threadlisttableid tr[data-banstate="ban"],
#threadlist ul li[data-banstate="init"] h3 span.uv,
#threadlist ul li[data-banstate="ban"] { position: relative; }

#delform tr[data-banstate="init"] td.icn:after,
#delform tr[data-banstate="ban"]:after,
#threadlisttableid tr[data-banstate="init"] td.icn:after,
#threadlisttableid tr[data-banstate="ban"]:after,
#threadlist ul li[data-banstate="init"] h3 span.uv:after,
#threadlist ul li[data-banstate="ban"]:after {
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 65001;
  width: 100%;
  height: 100%;
  cursor: pointer;
  pointer-events: all;
}

#delform tr[data-banstate="init"] td.icn:after:active,
#threadlisttableid tr[data-banstate="init"] td.icn:after:active,
#threadlist ul li[data-banstate="init"] h3 span.uv:after:active {
  text-shadow: 2px 2px 6px black;
}

#delform tr[data-banstate="init"] td.icn:after,
#threadlisttableid tr[data-banstate="init"] td.icn:after,
#threadlist ul li[data-banstate="init"] h3 span.uv:after {
  content: "❌";
  background-color: #ffffff;
}
#delform tr[data-banstate="init"] td.icn:after,
#threadlisttableid tr[data-banstate="init"] td.icn:after {
  font-size: 1.5em;
}
#threadlist ul li[data-banstate="init"] h3 span.uv:after {
  font-size: 1.2em;
  top: 2.0em;
}
#delform tr[data-banstate="ban"] td.by,
#threadlisttableid tr[data-banstate="ban"] td.by { display: none; }
#delform tr[data-banstate="ban"]:after,
#threadlisttableid tr[data-banstate="ban"]:after,
#threadlist ul li[data-banstate="ban"]:after {
  content: "UI屏蔽中,点击解除屏蔽";
  background-color: rgba(255, 0, 0, 0.5);
  font-size: 2.0em;
  color: aliceblue;
  font-weight: bold;
  letter-spacing: 0.3em;
}
`;
        document.head.appendChild(style);
    }
    function load_replycoins_style() {
        const style = document.createElement("style");
        style.innerHTML = `
.post-btn-time {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.3em;
}
.post-btn-time .time-u30,
.post-btn-time .time-u45,
.post-btn-time .time-u60 {
  background: #0096fa;
}
.post-btn-time.run .time-u30,
.post-btn-time.run .time-u45,
.post-btn-time.run .time-u60 {
  background: red;
}
.post-btn-time.run.u30 .time-u30,
.post-btn-time.run.u45 .time-u30,
.post-btn-time.run.u45 .time-u45,
.post-btn-time.run.u60 .time-u30,
.post-btn-time.run.u60 .time-u45,
.post-btn-time.run.u60 .time-u60 {
  background: green;
}
.post-btn {
  font-size: 1.2em;
  font-weight: bold;
  background: #0096fa;
  color: azure;
  border: 0;
  border-radius: 0.3em;
  padding: 0.3em 0.6em;
  cursor: pointer;
}`;
        document.head.appendChild(style);
    }
    function keyJump() {
        function pageJump(className) {
            const elements = document.getElementsByClassName(className);
            if (elements.length === 0)
                return;
            const element = elements[0];
            if (!(element instanceof HTMLAnchorElement))
                return;
            element.click();
        }
        document.body.addEventListener("keydown", ({ altKey, ctrlKey, key, shiftKey }) => {
            if (!ctrlKey && !shiftKey && !altKey) {
                if (key === "ArrowLeft" || key === "a") {
                    pageJump("prev");
                }
                else if (key === "ArrowRight" || key === "d") {
                    pageJump("nxt");
                }
            }
        });
    }
    function keyJump404(urlSearch) {
        function pageJump(add) {
            const page = urlSearch.get("page");
            const next_page = (page === null ? 1 : parseInt(page, 10)) + add;
            urlSearch.set("page", next_page.toString(10));
            window.location.search = urlSearch.toString();
        }
        document.body.addEventListener("keydown", ({ altKey, ctrlKey, key, shiftKey }) => {
            if (!ctrlKey && !shiftKey && !altKey) {
                if (key === "ArrowLeft" || key === "a") {
                    pageJump(-1);
                }
                else if (key === "ArrowRight" || key === "d") {
                    pageJump(1);
                }
            }
        });
    }
    function keyJumpHome() {
        function pageJump(className) {
            const elements = document.getElementsByClassName(className);
            if (elements.length === 0)
                return;
            const element = elements[0];
            if (!(element instanceof HTMLAnchorElement))
                return;
            element.click();
        }
        function pageJumpX(className) {
            const spanf = document.getElementsByClassName(className);
            if (spanf.length === 0)
                return;
            const span = spanf[0];
            if (!(span instanceof HTMLSpanElement))
                return;
            const af = span.getElementsByTagName("a");
            if (af.length === 0)
                return;
            const a = af[0];
            a.click();
        }
        document.body.addEventListener("keydown", ({ altKey, ctrlKey, key, shiftKey }) => {
            if (!ctrlKey && !shiftKey && !altKey) {
                if (key === "ArrowLeft" || key === "a") {
                    pageJumpX("pgb");
                }
                else if (key === "ArrowRight" || key === "d") {
                    pageJump("nxt");
                }
            }
        });
    }
    function newthread_mark_a4(element, tid_s10, dt, banDt) {
        const tid_i10 = parseInt(tid_s10, 10);
        if (isNaN(tid_i10) || !isFinite(tid_i10))
            return;
        const tid_b64 = DecimalBase64To.decToB64(tid_i10);
        const dataset = element.dataset;
        dataset.tid = tid_b64;
        dataset.fidxexist = dt.exist(tid_b64) ? "exist" : "init";
        dataset.banstate = banDt.exist(tid_b64) ? "ban" : "init";
    }
    function newthread_mark_a3(element, a0, dt, banDt) {
        const { href } = a0;
        if (href.trim().length === 0)
            return;
        const m = href.match(tid_pattern_a2);
        if (m === null)
            return;
        const tid = DecimalBase64To.decToB64(parseInt(m[0], 10));
        const dataset = element.dataset;
        dataset.tid = tid;
        dataset.fidxexist = dt.exist(tid) ? "exist" : "init";
        dataset.banstate = banDt.exist(tid) ? "ban" : "init";
    }
    function target_find_a(target) {
        if (target === null)
            return null;
        if (!(target instanceof Element))
            return null;
        if (target instanceof HTMLAnchorElement)
            return target;
        const a = target.closest("a");
        if (a === null)
            return undefined;
        return a;
    }
    function newthread_mark_forumdisplay(tbody, dt, banDt, soushuba_remove_guanggao = false) {
        const trf = tbody.getElementsByTagName("tr");
        if (trf.length === 0)
            return;
        const tr = trf[0];
        const thf = tr.getElementsByTagName("th");
        if (thf.length === 0)
            return;
        const th = thf[0];
        const af = th.getElementsByTagName("a");
        if (af.length === 0)
            return;
        const { id: cid } = af[0];
        if (cid.trim().length === 0)
            return;
        const m = cid.match(tid_from_id_pattern);
        if (m === null) {
            if (soushuba_remove_guanggao) {
                if (cid.match(tid_bad_from_id_pattern) === null)
                    return;
                tr.dataset.fidxexist = "hide";
                return;
            }
            else {
                return;
            }
        }
        const tid_s10 = m.groups?.tid;
        if (tid_s10 === undefined)
            return;
        newthread_mark_a4(tr, tid_s10, dt, banDt);
    }
    function newthread_mark_home(tr, dt, banDt) {
        const icnf = tr.getElementsByClassName("icn");
        if (icnf.length === 0)
            return;
        const icn = icnf[0];
        if (!(icn instanceof HTMLTableCellElement))
            return;
        const af = icn.getElementsByTagName("a");
        if (af.length === 0)
            return;
        const { href } = af[0];
        if (href.length === 0)
            return;
        const m = href.match(tid_from_url_pattern);
        if (m === null)
            return;
        const tid_s10 = m.groups?.tid;
        if (tid_s10 === undefined)
            return;
        newthread_mark_a4(tr, tid_s10, dt, banDt);
    }
    function newthread_mark_search(li, dt, banDt) {
        const h3f = li.getElementsByTagName("h3");
        if (h3f.length === 0)
            return;
        const h3 = h3f[0];
        const af = h3.getElementsByTagName("a");
        if (af.length === 0)
            return;
        const a0 = af[0];
        newthread_mark_a3(li, a0, dt, banDt);
        const span = document.createElement("span");
        span.className = "uv";
        h3.insertAdjacentElement("afterbegin", span);
    }
    function newthread_mark_listen_forumdisplay(xbody, dt, banDt) {
        let BUTTONS;
        (function (BUTTONS) {
            BUTTONS[BUTTONS["LEFT"] = 0] = "LEFT";
            BUTTONS[BUTTONS["CENTER"] = 1] = "CENTER";
        })(BUTTONS || (BUTTONS = {}));
        function click(xbody, target, button, dt, banDt) {
            let ex_handle = true;
            let ban_handle = true;
            const a = target_find_a(target);
            if (a === null)
                throw new Error("target不是标签HTMLElement的子集。");
            if (a === undefined) {
                if (button === BUTTONS.CENTER) {
                    throw new Error("target父元素a未查询到 && target不是元素a。");
                }
                else {
                    ex_handle = false;
                }
            }
            else {
                if (!xbody.contains(a))
                    throw new Error("xbody并不包含子元素a。");
            }
            const tr = target.closest("tr");
            if (tr === null)
                throw new Error("target父元素tr未查询到。");
            if (!xbody.contains(tr))
                throw new Error("xbody并不包含子元素tr。");
            const dataset = tr.dataset;
            const tid = dataset?.tid;
            if (tid === undefined)
                throw new Error("元素tr的dataset的tid属性并不存在。");
            const banstate = dataset?.banstate;
            if (banstate === undefined)
                throw new Error("元素tr的dataset的banstate属性并不存在。");
            const fidxexist = dataset?.fidxexist;
            if (fidxexist === undefined)
                throw new Error("元素tr的dataset的fidxexist属性并不存在。");
            if (ex_handle) {
                const { href } = a;
                if (tid_find.test(href)) {
                    dataset.fidxexist = "exist";
                    dt.add_unsave(tid);
                    return;
                }
            }
            if (ban_handle) {
                if (banstate === "init") {
                    const td = target.closest("td");
                    if (td === null)
                        return;
                    if (!td.classList.contains("icn"))
                        return;
                    if (isNaN(DecimalBase64To.b64ToDec(tid)))
                        return;
                    if (!banDt.exist(tid))
                        banDt.add_save(tid);
                    dataset.banstate = "ban";
                    return;
                }
                else if (banstate === "ban") {
                    if (isNaN(DecimalBase64To.b64ToDec(tid)))
                        return;
                    if (banDt.exist(tid))
                        banDt.del_save(tid);
                    dataset.banstate = "init";
                    return;
                }
                else {
                    throw new Error("程式错误。");
                }
            }
        }
        xbody.addEventListener("mousedown", ({ target, button }) => {
            let fbutton;
            if (button === 0) {
                fbutton = BUTTONS.LEFT;
            }
            else if (button === 1) {
                fbutton = BUTTONS.CENTER;
            }
            else {
                return;
            }
            try {
                return click(xbody, target, fbutton, dt, banDt);
            }
            catch (err) {
            }
        });
    }
    function forumdisplay(soushuba_remove_guanggao = false) {
        const dt = new DataTmp(tid_tmp_key, tid_split);
        dt.init();
        const banDt = new DataTmp(tid_ban_tmp_key, tid_split);
        banDt.init();
        load_tid_style();
        const threadlisttableid = document.getElementById("threadlisttableid");
        if (threadlisttableid === null)
            return;
        if (!(threadlisttableid instanceof HTMLTableElement))
            return;
        const xbody = threadlisttableid;
        const tbodys = xbody.getElementsByTagName("tbody");
        for (const tbody of tbodys) {
            newthread_mark_forumdisplay(tbody, dt, banDt, soushuba_remove_guanggao);
        }
        newthread_mark_listen_forumdisplay(xbody, dt, banDt);
        const observer = new MutationObserver(function (mutations, observer) {
            for (const mutation of mutations) {
                if (mutation.type !== "childList")
                    return;
                const { addedNodes } = mutation;
                if (addedNodes.length === 0)
                    continue;
                for (const addedNode of addedNodes) {
                    if (!(addedNode instanceof HTMLTableSectionElement))
                        continue;
                    newthread_mark_forumdisplay(addedNode, dt, banDt);
                }
            }
        });
        const config = {
            attributes: false,
            characterData: false,
            childList: true,
            subtree: false,
        };
        observer.observe(xbody, config);
    }
    function homephp() {
        const dt = new DataTmp(tid_tmp_key, tid_split);
        dt.init();
        const banDt = new DataTmp(tid_ban_tmp_key, tid_split);
        banDt.init();
        load_tid_style();
        const delform = document.getElementById("delform");
        if (delform === null)
            return;
        if (!(delform instanceof HTMLFormElement))
            return;
        let tablef = delform.getElementsByTagName("table");
        if (tablef.length === 0)
            return;
        const table = tablef[0];
        let tbodyf = table.getElementsByTagName("tbody");
        if (tbodyf.length === 0)
            return;
        const tbody = tbodyf[0];
        const xbody = tbody;
        const trs = xbody.getElementsByTagName("tr");
        for (const tr of trs) {
            newthread_mark_home(tr, dt, banDt);
        }
        newthread_mark_listen_forumdisplay(xbody, dt, banDt);
    }
    function searchphp() {
        const dt = new DataTmp(tid_tmp_key, tid_split);
        dt.init();
        const banDt = new DataTmp(tid_ban_tmp_key, tid_split);
        banDt.init();
        load_tid_style();
        const threadlist = document.getElementById("threadlist");
        if (threadlist === null)
            return;
        if (!(threadlist instanceof HTMLDivElement))
            return;
        const ulf = threadlist.getElementsByTagName("ul");
        if (ulf.length === 0)
            return;
        const ul = ulf[0];
        const xbody = ul;
        const lis = xbody.getElementsByTagName("li");
        for (const li of lis) {
            newthread_mark_search(li, dt, banDt);
        }
        function click_a(a) {
            const li = a.closest("li[data-banstate] h3");
            if (li === null)
                return "li error";
            const dataset = li.dataset;
            if (dataset?.fidxexist === undefined)
                return "li error";
            const tid = dataset?.tid;
            if (tid === undefined)
                return "li error";
            const href = a.href;
            if (!tid_find.test(href))
                return "href is null";
            dataset.fidxexist = "exist";
            dt.add_unsave(tid);
            return "final";
        }
        function run_a(target) {
            const a = target_find_a(target);
            return a === null ? "element is null" : a === undefined ? "element unfind a" : click_a(a);
        }
        function run_ban(target, li) {
            const dataset = li.dataset;
            const banstate = dataset?.banstate;
            if (banstate === "init") {
                const span = target.closest("li[data-banstate] h3 span.uv");
                if (span === null)
                    return;
                const tid = dataset?.tid;
                if (tid === undefined)
                    return;
                if (isNaN(DecimalBase64To.b64ToDec(tid)))
                    return;
                if (!banDt.exist(tid))
                    banDt.add_save(tid);
                dataset.banstate = "ban";
                return;
            }
            else if (banstate === "ban") {
                const tid = dataset?.tid;
                if (tid === undefined)
                    return;
                if (isNaN(DecimalBase64To.b64ToDec(tid)))
                    return;
                if (banDt.exist(tid))
                    banDt.del_save(tid);
                dataset.banstate = "init";
                return;
            }
        }
        xbody.addEventListener("mousedown", ({ target, button }) => {
            if (button === 0) {
                const res1 = run_a(target);
                if (res1 === "final")
                    return;
                if (res1 === "element is null")
                    return;
                let li;
                if (res1 === "element unfind a") {
                    li = target.closest("li[data-banstate]");
                    if (li === null)
                        return null;
                }
                else if (res1 === "li error") {
                    return;
                }
                else if (res1 === "href is null") {
                    li = target.closest("li[data-banstate]");
                    if (li === null)
                        return null;
                }
                else {
                    return;
                }
                li.closest("li[data-banstate]");
                run_ban(target, li);
            }
            else if (button === 1) {
                run_a(target);
            }
        });
    }
    function viewthread(get_tid) {
        if (get_tid === null || get_tid === undefined)
            return;
        const tid_b10 = parseInt(get_tid, 10);
        if (isNaN(tid_b10) || !isFinite(tid_b10))
            return;
        const tid_b64 = DecimalBase64To.decToB64(tid_b10);
        let dt = new DataTmp(tid_tmp_key, tid_split);
        dt.add_save(tid_b64);
        dt = null;
    }
    function viewthread_replycoins() {
        const fastpostsubmit = document.getElementById("fastpostsubmit");
        if (fastpostsubmit === null || !(fastpostsubmit instanceof HTMLButtonElement))
            throw new Error("fastpostsubmit");
        const fastpostmessage = document.getElementById("fastpostmessage");
        if (fastpostmessage === null || !(fastpostmessage instanceof HTMLTextAreaElement))
            throw new Error("fastpostmessage");
        const pgses = document.getElementsByClassName("pgs");
        if (pgses.length !== 2)
            throw new Error("pgs");
        const pgs1 = pgses[0];
        if (!(pgs1 instanceof HTMLDivElement))
            throw new Error("pgs1");
        const pgs2 = pgses[1];
        if (!(pgs2 instanceof HTMLDivElement))
            throw new Error("pgs2");
        load_replycoins_style();
        function initElement(top) {
            const div = document.createElement("div");
            const pbtn = document.createElement("button");
            const timer = document.createElement("span");
            const time = document.createElement("span");
            const time30u = document.createElement("span");
            const time45u = document.createElement("span");
            const time60u = document.createElement("span");
            pbtn.className = "post-btn";
            pbtn.innerHTML = "快速回复(CTRL+D)";
            timer.className = "post-btn-timer";
            timer.innerHTML = "时间(s): ";
            time.className = "post-btn-time";
            time.innerHTML = "未启动";
            time30u.className = "time-u30";
            time30u.innerHTML = "30s↑";
            time45u.className = "time-u45";
            time45u.innerHTML = "45s↑";
            time60u.className = "time-u60";
            time60u.innerHTML = "60s↑";
            div.className = "post-btn-time";
            div.appendChild(pbtn);
            div.appendChild(timer);
            div.appendChild(time);
            div.appendChild(time30u);
            div.appendChild(time45u);
            div.appendChild(time60u);
            top.appendChild(div);
            function run() {
                const { classList } = div;
                if (classList.contains("run")) {
                    if (classList.contains("u30")) {
                        classList.remove("u30");
                    }
                    else if (classList.contains("u45")) {
                        classList.remove("u45");
                    }
                    else if (classList.contains("u60")) {
                        classList.remove("u60");
                    }
                }
                else {
                    classList.add("run");
                }
            }
            function update(s) {
                time.innerHTML = s.toString(10);
                if (s === 30) {
                    div.classList.add("u30");
                }
                else if (s === 45) {
                    div.classList.remove("u30");
                    div.classList.add("u45");
                }
                else if (s === 60) {
                    div.classList.remove("u45");
                    div.classList.add("u60");
                }
            }
            return [pbtn, update, run];
        }
        const [pbtn1, update1, run1] = initElement(pgs1);
        const [pbtn2, update2, run2] = initElement(pgs2);
        function choice(...array) {
            const randomIndex = Math.floor(Math.random() * array.length);
            return array[randomIndex];
        }
        function linkc(...array) {
            return array.join("");
        }
        const values = [
            () => linkc(choice("👍🏻", "👍", "⭐️", "(* ̄▽ ̄)b", ""), choice("感谢", "谢谢"), choice("👍🏻", "👍", "⭐️", "(* ̄▽ ̄)b", ""), choice("楼主", "lz", "大佬", "dl"), choice(linkc(choice("的", ""), "分享"), linkc("分享", choice("的", ""), choice("帖子", "文件", "书"))), choice("👍🏻", "👍", "⭐️", "(* ̄▽ ̄)b", "  !  !  !", "")),
        ];
        function postdata(fastpostmessage, fastpostsubmit) {
            fastpostmessage.value = choice(...values)();
            fastpostsubmit.click();
            startTimeCount();
        }
        window.addEventListener("keypress", (ev) => {
            const { key, ctrlKey, shiftKey, altKey } = ev;
            if (ctrlKey && !shiftKey && !altKey) {
                if (key === "d") {
                    ev.preventDefault();
                    ev.stopPropagation();
                }
            }
        });
        window.addEventListener("keydown", (ev) => {
            const { key, ctrlKey, shiftKey, altKey } = ev;
            if (ctrlKey && !shiftKey && !altKey) {
                if (key === "d") {
                    postdata(fastpostmessage, fastpostsubmit);
                    ev.preventDefault();
                    ev.stopPropagation();
                }
            }
        });
        pbtn1.addEventListener("click", () => {
            postdata(fastpostmessage, fastpostsubmit);
        });
        pbtn2.addEventListener("click", () => {
            postdata(fastpostmessage, fastpostsubmit);
        });
        let timer;
        function startTimeCount() {
            if (timer !== undefined) {
                clearInterval(timer);
                timer = undefined;
            }
            let countdownTime = 0;
            run1();
            run2();
            const updateCountdown = () => {
                countdownTime++;
                update1(countdownTime);
                update2(countdownTime);
            };
            timer = setInterval(updateCountdown, 1000);
        }
    }
    const { pathname: pn, search } = window.location;
    const tid_pattern_a2 = /(?<=(?:^|\/)thread-)[1-9]\d*(?=-[1-9]\d*-[1-9]\d*[.]html)|(?<=[?&]tid=)[1-9]\d*(?=&|$)/;
    const tid_from_url_pattern = /[?&]tid=(?<tid>[1-9]\d*)(?:&|$)/;
    const tid_from_id_pattern = /^content_(?<tid>[1-9]\d*)$/;
    const tid_bad_from_id_pattern = /^content_adver&aid=[1-9]\d*$/;
    const tid_find = /(^|\/)thread-[1-9]\d*-[1-9]\d*-[1-9]\d*[.]html|[?&]tid=[1-9]\d*(&|$)/;
    const tid_forumdisplay2_pattern = /^\/forum-\d+-\d+[.]html$/;
    const tid_viewthread2t_pattern = /^\/thread-(?<tid>\d+)-\d+-\d+[.]html$/;
    let m;
    if (pn === "/forum.php") {
        const urlSearch = new URLSearchParams(search);
        const mod = urlSearch.get("mod");
        if (mod === null) {
            return;
        }
        else if (mod === "viewthread") {
            const applicationName = getApplicationName();
            if (applicationName === ApplicationNames.soushuba || applicationName === ApplicationNames.sxsy || applicationName === ApplicationNames.ba404) {
                const get_tid = urlSearch.get("tid");
                viewthread(get_tid);
                viewthread_replycoins();
            }
        }
        else if (mod === "forumdisplay") {
            const applicationName = getApplicationName();
            if (applicationName === ApplicationNames.soushuba) {
                forumdisplay(true);
                keyJump();
            }
            else if (applicationName === ApplicationNames.sxsy) {
                forumdisplay();
                keyJump();
            }
            else if (applicationName === ApplicationNames.ba404) {
                forumdisplay();
                keyJump404(urlSearch);
            }
        }
    }
    else if (pn === "/search.php") {
        const urlSearch = new URLSearchParams(search);
        const mod = urlSearch.get("mod");
        if (mod === null) {
            return;
        }
        else if (mod === "forum") {
            searchphp();
            keyJump();
        }
    }
    else if (pn === "/home.php") {
        const urlSearch = new URLSearchParams(search);
        const mod = urlSearch.get("mod");
        if (mod === null) {
            return;
        }
        else if (mod === "space") {
            const do_ = urlSearch.get("do");
            if (do_ === null)
                return;
            const uid = urlSearch.get("uid");
            if (uid === null)
                return;
            homephp();
            keyJumpHome();
        }
    }
    else if (tid_forumdisplay2_pattern.test(pn)) {
        const applicationName = getApplicationName();
        if (applicationName === ApplicationNames.ba404) {
            forumdisplay();
            keyJump();
        }
    }
    else if ((m = pn.match(tid_viewthread2t_pattern)) !== null) {
        const applicationName = getApplicationName();
        if (applicationName === ApplicationNames.ba404) {
            const get_tid = m.groups?.tid;
            viewthread(get_tid);
            viewthread_replycoins();
        }
    }
})();