福利吧小助手

一个用于增强福利吧功能的油猴脚本,提供链接提取、界面美化、编解码等功能。

// ==UserScript==
// @name               福利吧小助手
// @namespace          https://greasyfork.org/zh-CN/users/860681-aoguai
// @version            1.0.1
// @description        一个用于增强福利吧功能的油猴脚本,提供链接提取、界面美化、编解码等功能。
// @author             aoguai
// @include           *://fulibus.net/*
// @include           *://fuliba20[0-9][0-9].net/*
// @include           *://fuliba[0-9][0-9].net/*
// @include           *://f.uliba.net/*
// @include           *://*.wnflb20[0-9][0-9].com/*
// @include           *://*.wnflb[0-9][0-9].com/*
// @include           *://*.wnflb2023.com/*
// @include           *://fuliba2025.net/
// @include           /www.wnflb\d*.com/
// @require            https://gcore.jsdelivr.net/npm/arrive@2.4.1/minified/arrive.min.js
// @require            https://cdn.jsdelivr.net/npm/crypto-js@4.1.1/crypto-js.min.js
// @require            https://greasyfork.org/scripts/403716-gm-config-cn/code/GM_config_CN.js
// @connect            pan.baidu.com
// @connect            keyfc.net
// @connect            fuliba123.com
// @grant              GM_info
// @grant              GM_setClipboard
// @grant              GM_getValue
// @grant              GM_setValue
// @grant              GM_registerMenuCommand
// @grant              GM_xmlhttpRequest
// @grant              GM_addStyle
// @run-at             document-start
// @noframes
// @license            GNU General Public License v3.0 or later
// ==/UserScript==
(function () {
  'use strict';
  if (typeof GM_config == 'undefined') {
    console.error(
      '福利吧小助手:\nGM_config 库文件加载失败,脚本无法正常工作,请尝试刷新网页以重新加载。',
    );
  } else if (typeof document.arrive == 'undefined') {
    console.error(
      '福利吧小助手:\narrive 库文件加载失败,脚本可能无法正常工作,请尝试刷新网页以重新加载。',
    );
  } else if (typeof CryptoJS == 'undefined') {
    console.warn(
      '福利吧小助手:\nCryptoJS 库文件加载失败,BASE64 编解码功能无法使用。',
    );
  } else {
    console.debug('福利吧小助手:\n脚本工作环境正常。');
  }
  const icon = {
    settings:
      'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/settings.svg)',
    codeGray:
      'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/code_gray.svg)',
    codeBlue:
      'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/code_blue.svg)',
    modeNight:
      'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/mode_night.svg)',
    modeDay:
      'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/mode_day.svg)',
    signatureAdd:
      'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/signature_add.svg)',
    signatureMinus:
      'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/signature_minus.svg)',
    collapsedYes: 'static/image/common/collapsed_yes.gif',
    collapsedNo: 'static/image/common/collapsed_no.gif',
  };
  const style = {
    // 设置面板样式
    settings: `
    #myGoodBoyConfig {
      --primary-color: #4A90E2;
      --text-color: #333;
      --border-color: #E5E5E5;
      --hover-color: #2D74C4;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    }

    #myGoodBoyConfig input, 
    #myGoodBoyConfig button {
      cursor: pointer;
      transition: all 0.2s ease;
    }

    #myGoodBoyConfig button:hover {
      background: var(--hover-color);
    }

    #myGoodBoyConfig input[type="checkbox"] {
      width: 18px;
      height: 18px;
    }

    #myGoodBoyConfig .reset_holder {
      float: left;
      position: relative;
      bottom: -3vh;
    }

    #myGoodBoyConfig .section_header {
      padding: 12px;
      background: var(--primary-color);
      border-radius: 4px;
    }

    #myGoodBoyConfig .section_header a {
      color: #FFF;
      text-decoration: none;
      font-weight: 500;
      transition: color 0.2s;
    }

    #myGoodBoyConfig .section_header a:hover {
      color: #E5E5E5;
    }
  `,

    // 代码面板样式
    codePanel: `
    #myCodePanel {
      --panel-width: 600px;
      --panel-height: 430px;
      --border-radius: 8px;
      
      width: var(--panel-width) !important;
      height: var(--panel-height) !important;
      border-radius: var(--border-radius);
      box-shadow: 0 2px 12px rgba(0,0,0,0.15);
    }

    #myCodePanel input,
    #myCodePanel button {
      cursor: pointer;
      transition: all 0.2s;
    }

    #myCodePanel button {
      padding: 6px 12px;
      border-radius: 4px;
      border: 1px solid var(--border-color);
    }

    #myCodePanel button:hover {
      background: var(--hover-color);
      color: white;
    }

    #myCodePanel .reset_holder {
      float: left;
      position: relative;
      bottom: -1vh;
    }

    #myCodePanel .nav-tabs {
      text-align: center;
      border-bottom: 1px solid var(--border-color);
    }

    #myCodePanel .nav-tabs > div {
      padding: 8px 20px;
      transition: background-color 0.2s;
    }

    #myCodePanel #myCodePanel_saveBtn {
      display: none;
    }

    #myCodePanel #myCodePanel_resetLink {
      text-decoration: underline;
      color: var(--primary-color);
    }

    #myCodePanel textarea {
      width: 96%;
      padding: 8px;
      border-radius: 4px;
      border: 1px solid var(--border-color);
      resize: vertical;
    }
  `,

    // 夜间模式样式
    night: `
    html, body, .bm, .bdl, .bdl dt, .bdl dd.bdl_a a, .tb .a a, .pn, .fl .bm_h, .ct2_a, .ct3_a, .t_table, table.plhin {
      background-color: #282A36 !important;
      background-blend-mode: multiply;
    }
    .bdl dl.a, .tl .th, .tl .ts th, .tl .ts td, .pg a, .pg strong, .pgb a, .pg label, .bml .bm_h, #scrolltop a, .bmn, .bm_h, td.pls, .ad td.plc, div.exfm, .tb a, .tb_h, .ttp li.a a, div.uo a, input#addsubmit_btn, #gh .bm .bm_h, .jump_bdl li, .newthread tr th, .newthread tr td, .tl .threadpre td, .tl .threadpre:hover td, .nfl .f_c, #myCodePanel {
      background-color: #282A36 !important;
    }
    #nv, .card_gender_0, .card .o a, .tbn li.a, #p_btn a, #p_btn i {
      background: #40444D !important;
    }
    #toptb, .tedt .bar, .edt .bar, .edt .bbar, #post_extra_tb label.a, #extcreditmenu.a, #g_upmine.a, .tl #forumnewshow, .jump_bdl .a a, .jump_bdl .a a:hover, .psth, .pl .quote, .pm_tac, .pm .c, .pml .hover, #uhd, #flw_header .bar, .ttp a, .ttp strong, .bmw .bm_h, .GzList ul li a, .m_c, .m_c .o, .dt th, .section_header_holder p, #fx_checkin_menu,#fx_checkin_menub, .pl .blockcode ol li:hover {
        background-color: #40444D !important;
    }
    #nv li a:hover, #nv li.hover a, #nv li.hover a:hover, #nv > a {
      background: #1A1A1A !important;
      background-blend-mode: multiply;
    }
    .p_pop, .p_pof, .sllt, .tl #forumnewshow a:hover, #autopbn:hover, .pgbtn a:hover, #hiddenpoststip {
      background-color: #1A1A1A !important;
    }
    #threadlist > div > table > tbody > tr:hover > *, #threadlist > div > form > table > tbody > tr:not(.threadpre):hover > *, div.tl > form > table > tbody > tr:hover > * {
      background-color: #1A1A1A !important;
    }
    .p_pop a:hover {
      background: #3D3D3D !important;
    }
    a, #um, #um a, body, input, button, select, textarea, .xi2, .xi2 a, .pg a, .pg strong, .pgb a, .pg label, .jump_bdl a, div#forum_rules_37 font {
      color: #C0C0C0 !important;
    }
    .tps a, .chart em {
      color: #666 !important;
    }
    .GzList ul li a {
      color: #000 !important !important;
    }
    .tedt .pt, .px, .pt, .ps, select, input,
    #myCodePanel textarea, #myCodePanel button
    {
      background-color: #38383D !important;
    }
    .pl .blockcode {
      background: #38383D !important;
    }
    ul.cl.nav li a, ul.cl.nav li a:hover {
      background-repeat: no-repeat !important;
      background-position: 50% 5px !important;
    }
    #fastpostsmilie_88_td, #fx_checkin_topb, #hd h2 a,#newspecial, #newspecialtmp, #post_reply, #post_replytmp, .ico_fall, .ico_increase, .o img, fieldset legend, div.ac1 {
      mix-blend-mode: multiply;
    }
    .p_pop a, .tl #forumnewshow a {
      filter: brightness(.7);
    }
    #category_36 tbody td p>a, .bm_c tbody h2>a, .common font, .fl .bm_h h2 a, .tl th a, .xw0.xi1, .y.xg1 font {
      mix-blend-mode: color-dodge;
    }
    .ignore_notice {
      right: -3px !important;
      top: -53px !important;
    }
    .tps a:hover {
      background-color: #C0C0C0 !important;
    }
    `,

    // 基础样式
    basic: `
    .my_good_boy_div_float {
      position: absolute;
      max-width: 430px;
      padding: 16px 20px;
      margin-left: 962px;
      margin-top: -170px;
      border: 2px solid #CDCDCD;
      border-radius: 8px;
      background: white;
      box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    }

    .my_good_boy_div_basic {
      margin-top: 16px;
    }

    .my_good_boy_p {
      color: #FF4D4F;
      font-size: 15px;
      margin: 8px 0;
    }

    .my_good_boy_p_float {
      margin-left: 0 !important;
    }

    .my_good_boy_li {
      list-style-type: disc;
      white-space: nowrap;
      margin: 8px 0;
    }

    .my_good_boy_a {
      display: inline;
      font-size: 15px;
      white-space: nowrap;
      color: var(--primary-color);
      text-decoration: none;
      transition: color 0.2s;
    }

    .my_good_boy_a:hover {
      color: var(--hover-color);
    }

    .my_good_boy_a_copy {
      display: inline-block;
      font-size: 15px;
      margin-left: 20px;
      text-decoration: underline;
      cursor: pointer;
    }

    .a_copy_completed {
      color: #FF6600 !important;
      animation: fadeIn 0.3s;
    }

    .link_faild {
      color: #999 !important;
      text-decoration: line-through !important;
    }

    .show_more_link {
      text-decoration: underline;
      color: var(--primary-color);
      cursor: pointer;
    }

    #settingsIcon {
      display: block;
      float: right;
      cursor: pointer;
      margin-top: 5px;
      width: 23px;
      height: 18px;
      background-image: ${icon.settings};
      background-repeat: no-repeat;
      background-size: 16px auto;
      background-position: center;
      transition: transform 0.2s;
    }

    #settingsIcon:hover {
      transform: rotate(45deg);
    }

    .expand_box,
    .expand_box_h {
      bottom: 0;
      height: 60px;
      position: fixed;
      right: -6vw;
      transition: all 0.3s ease;
      width: 12vw;
      z-index: 999;
    }

    .expand_box_h {
      height: 120px;
    }

    .show_expand_box {
      right: 0;
      width: 6vw;
    }

    #myCodeSpan,
    #myNightSpan,
    #myNightSpan_2 {
      background-repeat: no-repeat;
      background-size: 32px auto;
      background-position: center;
      border-radius: 50%;
      color: #FFF;
      cursor: pointer;
      display: block;
      height: 38px;
      width: 38px;
      position: absolute;
      right: 1vw;
      transition: all 0.3s ease;
    }

    #myCodeSpan {
      background-image: ${icon.codeGray};
      background-color: #787878;
      bottom: 10px;
    }

    #myCodeSpan:hover {
      box-shadow: 0 0 10px rgba(0,255,0,0.5);
      background-image: ${icon.codeBlue};
      transform: scale(1.1);
    }

    #myNightSpan,
    #myNightSpan_2 {
      background-color: #00A1D6;
    }

    #myNightSpan {
      bottom: 10px;
    }

    #myNightSpan_2 {
      bottom: 60px;
    }

    #myNightSpan:hover,
    #myNightSpan_2:hover {
      box-shadow: 0 0 10px rgba(0,255,0,0.5);
      transform: scale(1.1);
    }

    .signature_switch_div {
      width: 16px;
      height: 16px;
      display: block;
      position: relative;
      top: -5px;
      cursor: pointer;
      background-image: ${icon.signatureMinus};
      background-size: 16px auto;
      background-repeat: no-repeat;
      background-position: center;
      transition: all 0.2s;
    }

    .signature_switch_div:hover {
      transform: scale(1.1);
    }

    .signature_switch_close {
      background-image: ${icon.signatureAdd};
    }

    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }
  `,
  };

  // 定义网站地址常量
  const SITE_URLS = {
    HOME: '',
    FORUM: '',
  };
  const reg = {
    url: /^[\S\s]*?(magnet:\?xt=urn:btih:(?:[a-z0-9]{40}|[a-z0-9]{32})|ftp:\/\/\S*|ed2k:\/\/\S*|thunder:\/\/\S*|flashget:\/\/\S*|qqdl:\/\/\S*|xfplay:\/\/\S*|https?:\/\/[\w零一二三四五六七八九壹贰叁肆伍陆柒捌玖-]*\.?[\w零一二三四五六七八九壹贰叁肆伍陆柒捌玖-]+\.+\w+\S*)/i,
    download:
      /^[\S\s]*?(magnet:\?xt=urn:btih:(?:[a-z0-9]{40}|[a-z0-9]{32})|ed2k:\/\/\S*|thunder:\/\/\S*)/i,
    www: /^[\S\s]*?(www\.[\w-]+\.[a-z]+[\w#=%+?/-]*)/i,
    baidupan: /^https?:\/\/pan\.baidu\.com\/s(?:hare)?\/[\w=?&-]+$/i,
    baidupanIncludeCode:
      /^https?:\/\/pan\.baidu\.com\/s(?:hare)?\/[\w=?#&-]+$/i,
    code: /(?:提取)+[^a-z0-9解压]*([a-z0-9]{4})[^a-z0-9]*/i,
    baidupanCode:
      /^(?:(?:下载)?链接\S+\s+)?(?:[^解压]+\s+)?[^a-z0-9解压]*([a-z0-9]{4})[^a-z0-9]*(?:app)?[^a-z0-9]*$/i,
    singleCharCode: /^[a-z0-9]$/i,
    missingHeaderBaidupan:
      /^[\S\s]*?[^/\w-]?((?<!xunlei\.com\/)s(?:hare)?\/[\w=?-]{10,50})/i,
    missingHeaderBaidupanTest: /^([\w=?-]{15,50})\s+[a-z0-9]{4}$/i,
    pan: /^[\S\s]*?(pan\.(?:baidu|xunlei|lanzou)\.com\/?s?(?:hare)?\/[\w=?&-]+)/i,
    hash: /(?:[^a-z0-9]|^)([a-z0-9]{40}|[a-z0-9]{32})(?:&dn=.*|[^a-z0-9]|$)/i,
    md5: /(?:md5[^a-z0-9]+|sha1[^a-z0-9]+)/i,
    core: /^.*?((?:富强|民主|文明|和谐|自由|平等|公正|法治|爱国|敬业|诚信|友善){10,}).*?$/i,
    baijia:
      /^.*?([赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻福水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳唐罗薛伍余米贝姚孟顾尹江钟]{10,}).*?$/i,
    foyu: /^.*?((?:佛曰:|如是我闻:)\S{10,}).*?$/i,
    prefixLinkMagnet: /^https?:\/\/www\.wnflb\d*\.com\/magnet:\?xt=.*$/i,
    prefixLinkMagnetReplace: /^https?:\/\/www\.wnflb\d*\.com\//i,
    prefixCode:
      /^https?:\/\/www\.wnflb\d*\.com\/(\w+-\w+$|chrome-extension:\/\/)/i,
    prefixHash: /^https?:\/\/www\.wnflb\d*\.com\/([a-z0-9]{40}|[a-z0-9]{32})$/i,
    prefixUrl:
      /^https?:\/\/www\.wnflb\d*\.com\/(www\..*$|.*\.(?:com|net|cn|org|site|info|edu|gov)$)/i,
    redircdn: /^https?:\/\/to\.redircdn\.com\/\?(.*)&z$/i,
    prefixReplace: /^https?:\/\/www\.wnflb\d*\.com\//i,
    baseImage: /^https?:\/\/(data:)/i,
  };
  const filterReg = [
    /^https?:\/\/pan\.baidu\.com\/(?:s|share|mbox)?\/[\w#?%=/&-]*[^\w#?%=/&-]+/i,
    /^https?:\/\/www\.52pojie\.cn\/?#?$/i,
    /^https?:\/\/www\.52pojie\.cn\/(?:forum|home|misc)\.php\?/i,
    /^https?:\/\/www\.52pojie\.cn\/(?:forum|thread)-\d+-\d+(?:-\d+)?\.html$/i,
    /^https?:\/\/www\.wnflb\d*\.com\/?$/i,
    /^https?:\/\/www\.wnflb\d*\.com\/(?:home|forum)\.php\?/i,
    /^https?:\/\/www\.wnflb\d*\.com\/(?:thread|forum)-\d+-\d+(?:-\d+)?\.html$/i,
    /^https?:\/\/www\.imdb\.com\/title\//i,
    /^https?:\/\/movie\.douban\.com\/(?:subject|celebrity)/i,
    /^https?:\/\/photo\.weibo\.com\//i,
    /^https?:\/\/s\.weibo\.com\/weibo\?q=/i,
    /^https?:\/\/baike\.(?:so|baidu|sogou)\.com/i,
    /^https?:\/\/app\.bilibili\.com/i,
    /^https?:\/\/bbs\.zhiyoo\.com\/(?:forum|gforum)-\d+-\d+\.html/i,
    /^https?:\/\/www\.3dmgame\.com\/tag\//i,
    /^https?:\/\/www\.3dmgame\.com\/games\/[^/]*\/?$/i,
    /^https?:\/\/www\.tv432\.com\/search\.php\?searchword=/i,
    /^https?:\/\/www\.viidii\.info\/\?/i,
    /^https?:\/\/www\.daybox\.net\/image\//i,
    /^https?:\/\/www\.yidianzixun\.com\/channel\//i,
    /^https?:\/\/[\w-]*\.?sina\.com\.cn\/?/i,
    /^https?:\/\/(?:www|post)\.smzdm\.com\/(?:fenlei|p)\//i,
    /^https?:\/\/laod\.cn\/tag\//i,
    /^https?:\/\/www\.smmimg\.com\/i\//i,
  ];
  const ELEMENTS_TO_REMOVE = [
    '.topbar',
    '.breadcrumbs',
    '.branding',
    '#focusslide',
    '.sidebar',
    '.post-copyright',
    '.shares',
    '.action.action-rewards',
    '.title.excerpts-title .more',
  ];

  const KEEP_KEYWORDS = [
    'RSS',
    '联系TG',
    '联系邮箱',
    '百家姓暗号',
    '核心价值观',
    '加密解密工具',
    '地址发布',
    '搜索',
  ];

  const BLOCK_KEYWORDS = [
    '内裤',
    '邀请码',
    '购物',
    '淘宝',
    'taobao',
    '手机卡',
    '流量卡',
    '网赚',
  ];
  const coreValues = '富强民主文明和谐自由平等公正法治爱国敬业诚信友善';
  const baijiaValues = new Map([
    ['赵', '0'],
    ['钱', '1'],
    ['孙', '2'],
    ['李', '3'],
    ['周', '4'],
    ['吴', '5'],
    ['郑', '6'],
    ['王', '7'],
    ['冯', '8'],
    ['陈', '9'],
    ['褚', 'a'],
    ['卫', 'b'],
    ['蒋', 'c'],
    ['沈', 'd'],
    ['韩', 'e'],
    ['杨', 'f'],
    ['朱', 'g'],
    ['秦', 'h'],
    ['尤', 'i'],
    ['许', 'j'],
    ['何', 'k'],
    ['吕', 'l'],
    ['施', 'm'],
    ['张', 'n'],
    ['孔', 'o'],
    ['曹', 'p'],
    ['严', 'q'],
    ['华', 'r'],
    ['金', 's'],
    ['魏', 't'],
    ['陶', 'u'],
    ['姜', 'v'],
    ['戚', 'w'],
    ['谢', 'x'],
    ['邹', 'y'],
    ['喻', 'z'],
    ['福', 'A'],
    ['水', 'B'],
    ['窦', 'C'],
    ['章', 'D'],
    ['云', 'E'],
    ['苏', 'F'],
    ['潘', 'G'],
    ['葛', 'H'],
    ['奚', 'I'],
    ['范', 'J'],
    ['彭', 'K'],
    ['郎', 'L'],
    ['鲁', 'M'],
    ['韦', 'N'],
    ['昌', 'O'],
    ['马', 'P'],
    ['苗', 'Q'],
    ['凤', 'R'],
    ['花', 'S'],
    ['方', 'T'],
    ['俞', 'U'],
    ['任', 'V'],
    ['袁', 'W'],
    ['柳', 'X'],
    ['唐', 'Y'],
    ['罗', 'Z'],
    ['薛', '.'],
    ['伍', '-'],
    ['余', '_'],
    ['米', '+'],
    ['贝', '='],
    ['姚', '/'],
    ['孟', '?'],
    ['顾', '#'],
    ['尹', '%'],
    ['江', '&'],
    ['钟', '*'],
    ['高', ':'],
    ['田', '|'],
  ]);

  // 创建反向映射,用于编码
  const reverseMap = new Map(
    Array.from(baijiaValues.entries()).map(([k, v]) => [v, k]),
  );

  // 预编译正则表达式
  const MAGNET_PREFIX_REGEX = /^magnet:\?xt=urn:btih:/;
  const TRIM_REGEX = /^\s+|\s+$/g;
  const HTTP_PROTOCOL_REGEX = /^https?\/\//i;
  const URL_PROTOCOL_REGEX = /^(https?:\/\/|ed2k:\/\/)/;

  // 常量配置
  const CONFIG = {
    DEFAULT_ACCESS_NUM: 90,
    MAX_ACCESS_NUM: 90,
    LEVEL_ACCESS_MAP: {
      '-1': 0,
      '0': 5,
    },
  };

  // 获取最新地址并设置常量
  function initSiteUrls() {
    return new Promise((resolve, reject) => {
      GM_xmlhttpRequest({
        method: 'GET',
        url: 'https://fuliba123.com/',
        timeout: 10000,
        onload: function (response) {
          if (response.status === 200) {
            try {
              const parser = new DOMParser();
              const doc = parser.parseFromString(
                response.responseText,
                'text/html',
              );
              // 获取所有链接元素
              const linkElements = doc.querySelectorAll('a.card.no-c');
              // 遍历链接元素设置常量
              linkElements.forEach((element) => {
                const titleElement = element.querySelector('strong');
                if (titleElement) {
                  const title = titleElement.textContent.trim();
                  const url = element.href || element.getAttribute('data-url');
                  if (title === '福利吧') {
                    SITE_URLS.HOME = url;
                    // 添加首页地址到 @match
                    addMatchPattern(url);
                  } else if (title === '福利吧论坛') {
                    SITE_URLS.FORUM = url;
                    // 添加论坛地址到 @match
                    addMatchPattern(url);
                  }
                }
              });
              if (SITE_URLS.HOME && SITE_URLS.FORUM) {
                console.debug('福利吧小助手:\n网站地址初始化成功');
                console.debug('首页地址:', SITE_URLS.HOME);
                console.debug('论坛地址:', SITE_URLS.FORUM);
                resolve(SITE_URLS);
              } else {
                reject(new Error('未找到所需的链接'));
              }
            } catch (error) {
              reject(error);
            }
          } else {
            reject(new Error(`请求失败,状态码:${response.status}`));
          }
        },
        onerror: function (error) {
          reject(new Error('网络请求错误:' + error));
        },
        ontimeout: function () {
          reject(new Error('请求超时'));
        },
      });
    });
  }

  // 添加新的 match pattern
  function addMatchPattern(url) {
    try {
      const urlObj = new URL(url);
      const hostname = urlObj.hostname;

      // 构建 include pattern
      const patterns = [
        `*://${hostname}/*`,
        `*://*.${hostname}/*`,
        `/${hostname.replace(/\./g, '\\.')}/`, // 添加正则表达式形式的匹配
      ];

      // 获取当前脚本的元数据
      const metadata = GM_info.script;

      // 添加新的 @include (如果不存在)
      patterns.forEach((pattern) => {
        if (!metadata.includes || !metadata.includes.includes(pattern)) {
          // 如果 includes 数组不存在则创建它
          if (!metadata.includes) {
            metadata.includes = [];
          }
          metadata.includes.push(pattern);
          console.debug('福利吧小助手:\n添加新的 include pattern:', pattern);
        }
      });
    } catch (error) {
      console.warn('福利吧小助手:\n添加 include pattern 失败:', error);
    }
  }

  const status = {
    nightEnable: GM_config.getValue('nightEnable', false),
    collapsedGwwzEnable: GM_config.getValue('collapsedGwwzEnable', false),
    accessNum: GM_config.getValue('accessNumber', 90),
    nightStyleDom: null,
    checkDate: GM_config.getValue('checkDate', '2000-1-1'),
    oldUrl: location.href,
    timer1: null,
    timer2: null,
    timer3: null,
    timer4: null,
  };
  class Good_Boy {
    constructor(config, linkArray = []) {
      this.config = config;
      this.floatEnable = this.isMobilePage()
        ? false
        : config.get('displayPosition') == '右侧';
      this.linkArray = linkArray;
      this.totalCount = linkArray.length;
      this.currentCount = 0;
      this.showMoreStatus = false;
      this.insertUlStatus = false;
      this.ulNode = document.createElement('ul');
    }
    insertLinkItem(linkArray = []) {
      this.linkArray = this.linkArray.concat(linkArray);
      this.totalCount = this.linkArray.length;
      const maxLinkNumber = this.config.get('maxLinkNumber');
      for (
        let i = this.currentCount;
        i < this.totalCount && i < maxLinkNumber;
        i++
      ) {
        const tempA = this.createLink(this.linkArray[i]);
        tempA && this.ulNode.appendChild(tempA);
      }
      this.currentCount = Math.min(this.totalCount, maxLinkNumber);
      if (maxLinkNumber > -1 && this.totalCount > maxLinkNumber) {
        const message = `[共提取到 ${this.totalCount} 个链接,仅显示前 ${maxLinkNumber} 个]:`;
        const pElement = this.ulNode.getElementsByTagName('p')[0];
        pElement && (pElement.textContent = message);
        if (!this.showMoreStatus) {
          this.ulNode.appendChild(this.showMoreLink());
          this.showMoreStatus = true;
        }
      } else {
        const message = `[共提取到 ${this.totalCount} 个链接]:`;
        const pElement = this.ulNode.getElementsByTagName('p')[0];
        pElement && (pElement.textContent = message);
      }
    }
    isMobilePage() {
      return /android|webos|iphone|ipod|blackberry/i.test(navigator.userAgent);
    }
    getCutLinkText(linkText) {
      if (this.isMobilePage()) {
        return linkText.length >= 35
          ? linkText.slice(0, 15) + ' ... ' + linkText.slice(-10)
          : linkText;
      } else if (this.floatEnable) {
        return linkText.length >= 50
          ? linkText.slice(0, 25) + ' ... ' + linkText.slice(-15)
          : linkText;
      }
      return linkText.length >= 80
        ? linkText.slice(0, 45) + ' ... ' + linkText.slice(-25)
        : linkText;
    }
    managePrefixCode(inputLink) {
      const { prefixCode, prefixHash, prefixReplace, prefixUrl, redircdn } =
        reg;
      if (prefixCode.test(inputLink)) {
        return inputLink.replace(prefixReplace, '');
      } else if (prefixHash.test(inputLink)) {
        return inputLink.replace(prefixReplace, 'magnet:?xt=urn:btih:');
      } else if (prefixUrl.test(inputLink)) {
        return inputLink.replace(prefixReplace, 'http://');
      } else if (redircdn.test(inputLink)) {
        return inputLink.replace(redircdn, '$1').replace('______', '.');
      }
      return inputLink;
    }
    createLink(linkHref) {
      const { baidupanIncludeCode } = reg;
      if (linkHref.length > 2000) {
        return null;
      }
      const linkLi = document.createElement('li');
      linkLi.className = 'my_good_boy_li';
      const linkA = document.createElement('a');
      linkA.title = '点击访问';
      linkHref = this.managePrefixCode(linkHref);
      linkA.className = 'my_good_boy_a';
      linkA.href = encodeURI(linkHref);
      linkA.target = '_blank';
      linkA.textContent = this.getCutLinkText(linkHref);
      linkA.style.color = this.config.get('linkColor');
      linkLi.appendChild(linkA);
      if (this.config.get('copyEnable')) {
        const copyA = document.createElement('a');
        copyA.className = 'my_good_boy_a_copy';
        copyA.title = '复制链接';
        copyA.href = 'javascript:;';
        copyA.target = '_self';
        copyA.textContent = '复制';
        copyA.style.color = this.config.get('linkColor');
        copyA.addEventListener('click', function () {
          GM_setClipboard(linkHref, 'text');
          this.classList.add('a_copy_completed');
          this.title = '复制成功';
          status.timer1 && clearTimeout(status.timer1);
          status.timer1 = setTimeout(() => {
            this.classList.remove('a_copy_completed');
            this.title = '复制链接';
          }, 2000);
        });
        linkLi.appendChild(copyA);
        if (
          baidupanIncludeCode.test(linkHref) &&
          /(?:#|\?pwd=)[a-z0-9]{4}$/i.test(linkHref)
        ) {
          const codeValue = /#([a-z0-9]{4})$/i.exec(linkHref)[1];
          const codeCopyA = document.createElement('a');
          codeCopyA.className = 'my_good_boy_a_copy';
          codeCopyA.title = '复制提取码';
          codeCopyA.href = 'javascript:;';
          codeCopyA.target = '_self';
          codeCopyA.textContent = '复制提取码';
          codeCopyA.style.color = this.config.get('linkColor');
          codeCopyA.addEventListener('click', function () {
            GM_setClipboard(codeValue, 'text');
            this.classList.add('a_copy_completed');
            this.title = '复制成功';
            status.timer2 && clearTimeout(status.timer2);
            status.timer2 = setTimeout(() => {
              this.classList.remove('a_copy_completed');
              this.title = '复制提取码';
            }, 2000);
          });
          linkLi.appendChild(codeCopyA);
        }
      }
      this.config.get('checkEnable') &&
        baidupanIncludeCode.test(linkHref) &&
        this.checkBaidupan(linkHref, linkA);
      return linkLi;
    }
    showMoreLink() {
      const linkLi = document.createElement('li');
      linkLi.className = 'my_good_boy_li';
      const linkA = document.createElement('a');
      linkA.className = 'my_good_boy_a show_more_link';
      linkA.href = 'javascript:;';
      linkA.title = '显示全部提取链接';
      linkA.textContent = '显示全部';
      linkA.target = '_self';
      linkA.style.color = this.config.get('linkColor');
      linkA.addEventListener(
        'click',
        () => {
          this.ulNode.removeChild(linkLi);
          for (; this.currentCount < this.totalCount; this.currentCount++) {
            const tempA = this.createLink(this.linkArray[this.currentCount]);
            tempA && this.ulNode.appendChild(tempA);
          }
          this.ulNode.getElementsByTagName('p')[0].textContent =
            '[共提取到 ' + this.totalCount + ' 个链接]:';
          this.showMoreStatus = false;
        },
        false,
      );
      linkLi.appendChild(linkA);
      return linkLi;
    }
    createGoodBoyFrame(container, linkArray = []) {
      if (this.insertUlStatus) {
        this.insertLinkItem(linkArray);
      } else {
        const goodBoyDiv = document.createElement('div');
        goodBoyDiv.className = this.floatEnable
          ? 'my_good_boy_div_float'
          : 'my_good_boy_div_basic';
        const goodBoyP = document.createElement('p');
        goodBoyP.className = this.floatEnable
          ? 'my_good_boy_p my_good_boy_p_float'
          : 'my_good_boy_p';
        this.ulNode.appendChild(goodBoyP);
        this.insertLinkItem(linkArray);
        goodBoyDiv.appendChild(this.ulNode);
        container.appendChild(goodBoyDiv);
        this.insertUlStatus = true;
      }
    }
    createGoodBoyElement(container, linkObj, textObj, nodeTextArray) {
      const backLinkArray = this.autoEvent(
        container,
        linkObj.linkObjArray,
        linkObj.baiduObjArray,
        linkObj.linksArray,
        textObj.hideTextArray,
        textObj.showTextArray,
        nodeTextArray,
      );
      backLinkArray.length > 0 &&
        this.createGoodBoyFrame(container, backLinkArray);
    }
    managePrefix(inputLinkArray) {
      const { prefixLinkMagnet, prefixLinkMagnetReplace } = reg;
      const returnLinkArray = [];
      inputLinkArray.forEach((item) => {
        returnLinkArray.push(
          prefixLinkMagnet.test(item)
            ? item.replace(prefixLinkMagnetReplace, '')
            : item,
        );
      });
      return returnLinkArray;
    }
    pickUpMagnet(item) {
      const { url, download, hash, md5 } = reg;
      let tempLink = '';
      const item1 = item.replace(/[^a-z0-9:=?/\\.&%|-]/gi, '');
      if (download.test(item1)) {
        tempLink = download.exec(item1)[1];
      } else {
        const item2 = item.replace(/[^a-z0-9:=?/\\.,,。|\s+-]/gi, '');
        if (!md5.test(item2) && hash.test(item2) && !url.test(item2)) {
          const tempHash = hash.exec(item2)[1];
          if (!/^(?:[a-z]+|[0-9]+)$/i.test(tempHash)) {
            tempLink = 'magnet:?xt=urn:btih:' + tempHash;
          }
        }
      }
      return tempLink;
    }
    manageText(textArray) {
      const {
        url,
        download,
        www,
        missingHeaderBaidupan,
        missingHeaderBaidupanTest,
        pan,
        hash,
        md5,
      } = reg;
      const tempArray = [];
      textArray.forEach((item) => {
        let tempLink = '';
        if (pan.test(item)) {
          tempLink = 'https://' + pan.exec(item)[1];
        } else if (/magnet:|ed2k:|thunder:/i.test(item)) {
          if (download.test(item)) {
            tempLink = download.exec(item)[1];
          }
        } else if (url.test(item)) {
          tempLink = url.exec(item)[1];
        } else if (www.test(item)) {
          tempLink = 'http://' + www.exec(item)[1];
        } else if (missingHeaderBaidupan.test(item)) {
          const linkMissValue = missingHeaderBaidupan.exec(item)[1];
          tempLink = /^\//i.test(linkMissValue)
            ? 'https://pan.baidu.com' + linkMissValue
            : 'https://pan.baidu.com/' + linkMissValue;
        } else if (missingHeaderBaidupanTest.test(item)) {
          tempLink =
            'https://pan.baidu.com/s/' +
            missingHeaderBaidupanTest.exec(item)[1];
        } else if (!md5.test(item) && hash.test(item)) {
          tempLink = 'magnet:?xt=urn:btih:' + hash.exec(item)[1];
        } else if (item.length > 32) {
          tempLink = this.pickUpMagnet(item);
        }
        filterLink(tempLink) && tempArray.push(tempLink);
      });
      return this.managePrefix(tempArray);
    }
    decodeLink(inputLinkArray) {
      const { url } = reg;
      inputLinkArray.forEach((item, index) => {
        if (url.test(item)) {
          inputLinkArray[index] = decodeURI(item);
        }
      });
      return inputLinkArray;
    }
    pickUpBaidupanCode(textArray) {
      const { code, baidupanCode, singleCharCode } = reg;
      const codeArray = [];
      const charArray = [];
      textArray.forEach((item) => {
        let tempValue = '';
        if (code.test(item)) {
          tempValue = code.exec(item)[1];
        } else if (baidupanCode.test(item)) {
          tempValue = baidupanCode.exec(item)[1];
        } else if (singleCharCode.test(item)) {
          charArray.push(item);
        }
        if (
          tempValue &&
          !/\d{4}/i.test(tempValue) &&
          codeArray.indexOf(tempValue) === -1
        ) {
          codeArray.push(tempValue);
        }
      });
      while (charArray.length > 0 && charArray.length % 4 === 0) {
        const tempCode = charArray.splice(0, 4);
        const charValue = tempCode.join('');
        if (!/\d{4}/i.test(charValue) && codeArray.indexOf(charValue) === -1) {
          codeArray.push(charValue);
        }
      }
      return codeArray;
    }
    manageRepeatArray(inputLinkArray) {
      const outputLinkArray = [];
      for (let i = 0, l = inputLinkArray.length; i < l; i++) {
        for (let j = i + 1; j < l; j++) {
          if (
            getPureLink(inputLinkArray[i]) === getPureLink(inputLinkArray[j])
          ) {
            ++i;
            j = i;
          }
        }
        outputLinkArray.push(inputLinkArray[i]);
      }
      return outputLinkArray;
    }
    splitWrap(textArray) {
      let tempArray = [];
      textArray.forEach((text) => {
        if (text) {
          tempArray = tempArray.concat(text.split('\n').filter((v) => v));
        }
      });
      return tempArray;
    }
    autoEvent(
      container,
      linkObjArray,
      baiduObjArray,
      _linksArray,
      hideTextArray,
      showTextArray,
      nodeTextArray,
    ) {
      const { url, baidupan, hash, md5 } = reg;
      const linkArray = [];
      const linkTextArray = [];
      linkObjArray.forEach((item) => {
        linkArray.push(item.eleValue);
        linkTextArray.push(item.eleContainer);
      });
      if (hideTextArray.length > 0) {
        hideTextArray = this.splitWrap(hideTextArray);
      }
      if (showTextArray.length > 0) {
        showTextArray = this.splitWrap(showTextArray);
      }
      if (nodeTextArray.length > 0) {
        nodeTextArray = this.splitWrap(nodeTextArray);
      }
      const concatTextArray = this.manageRepeatArray(
        this.decodeLink(hideTextArray),
      );
      let concatLinkArray = this.manageRepeatArray(
        this.decodeLink(this.manageText(linkArray.concat(concatTextArray))),
      );
      const generalTextArray = showTextArray.concat(
        nodeTextArray.concat(linkTextArray),
      );
      const indexA = [];
      const codeB = this.pickUpBaidupanCode(concatTextArray);
      let codeC = [];
      if (codeB.length > 0) {
        for (let j = 0; j < concatLinkArray.length; j++) {
          if (baidupan.test(concatLinkArray[j])) {
            indexA.push(j);
          }
        }
        if (codeB.length === indexA.length) {
          for (let k = 0; k < indexA.length; k++) {
            if (!/\?pwd=/.test(concatLinkArray[indexA[k]])) {
              concatLinkArray[indexA[k]] += '?pwd=' + codeB[k];
            }
          }
        } else if (codeB.length === baiduObjArray.length) {
          for (let l = 0; l < baiduObjArray.length; l++) {
            if (!/\?pwd=/.test(baiduObjArray[l].ele.href)) {
              baiduObjArray[l].ele.textContent =
                baiduObjArray[l].eleContainer + '?pwd=' + codeB[l];
              baiduObjArray[l].ele.href =
                baiduObjArray[l].eleValue + '?pwd=' + codeB[l];
            }
          }
        }
      } else {
        codeC = this.pickUpBaidupanCode(generalTextArray);
        if (codeC.length > 0) {
          for (let j = 0; j < concatLinkArray.length; j++) {
            if (baidupan.test(concatLinkArray[j])) {
              indexA.push(j);
            }
          }
          if (codeC.length === indexA.length) {
            for (let k = 0; k < indexA.length; k++) {
              concatLinkArray[indexA[k]] += '?pwd=' + codeC[k];
            }
          } else if (codeC.length === baiduObjArray.length) {
            for (let l = 0; l < baiduObjArray.length; l++) {
              baiduObjArray[l].ele.textContent =
                baiduObjArray[l].eleContainer + '?pwd=' + codeC[l];
              baiduObjArray[l].ele.href =
                baiduObjArray[l].eleValue + '?pwd=' + codeC[l];
            }
          }
        }
      }
      let hashArray = [];
      generalTextArray.forEach((item) => {
        if (!url.test(item)) {
          if (!md5.test(item) && hash.test(item)) {
            hashArray.push('magnet:?xt=urn:btih:' + hash.exec(item)[1]);
          } else if (item.length > 32) {
            let temp_link = this.pickUpMagnet(item);
            temp_link && hashArray.push(temp_link);
          }
        }
      });
      hashArray = this.decodeLink(hashArray);
      concatLinkArray = this.manageRepeatArray(
        concatLinkArray.concat(hashArray),
      );
      if (this.config.get('checkEnable')) {
        for (let p of baiduObjArray) {
          this.checkBaidupan(p.eleValue, p.ele);
        }
      }
      const hideCodeTextArray = this.decodeCoreValues(
        container,
        hideTextArray.concat(generalTextArray),
      );
      if (hideCodeTextArray.length > 0) {
        hideCodeTextArray.forEach((item, index) => {
          if (!url.test(item)) {
            if (!md5.test(item) && hash.test(item)) {
              hideCodeTextArray[index] =
                'magnet:?xt=urn:btih:' + hash.exec(item)[1];
            } else if (item.length > 32) {
              const tempLink = this.pickUpMagnet(item);
              if (tempLink) {
                hideCodeTextArray[index] = tempLink;
              }
            }
          }
        });
        concatLinkArray = this.manageRepeatArray(
          concatLinkArray.concat(hideCodeTextArray),
        );
      }
      concatLinkArray = concatLinkArray
        .map((item) => {
          if (generalTextArray.includes(item)) {
            return null;
          }
          return item;
        })
        .filter((v) => v);
      return concatLinkArray;
    }
    foyuPromise(encoded) {
      return new Promise(function (resolve, _reject) {
        GM_xmlhttpRequest({
          method: 'POST',
          url: 'https://keyfc.net/bbs/tools/tudou.aspx',
          data: 'orignalMsg=' + encoded.replace(/\s/g, '') + '&action=Decode',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
          },
          onload: function (res) {
            if (res.status == 200 && res.readyState == 4) {
              resolve(
                res.responseText.replace(/^<\/Message><\/BUDDHIST>$/g, ''),
              );
            } else {
              console.warn('福利吧小助手:\n自动解码出错!');
              resolve('');
            }
          },
          onerror: function () {
            console.error('福利吧小助手:\n网络链接出错!');
            resolve('');
          },
        });
      });
    }
    async foyuDecode(container, encoded) {
      await this.foyuPromise(encoded).then((data) => {
        data && this.createGoodBoyFrame(container, [data]);
      });
    }
    decodeCoreValues(container, textArray) {
      const { core, baijia, foyu } = reg;
      const decodeArray = [];
      textArray.forEach((item) => {
        if (core.test(item)) {
          decodeArray.push(coreValuesDecode(core.exec(item)[1]));
        } else if (baijia.test(item)) {
          decodeArray.push(baijiaDecode(baijia.exec(item)[1]));
        } else if (foyu.test(item)) {
          this.foyuDecode(container, foyu.exec(item)[1]);
        }
      });
      return decodeArray;
    }
    checkBaidupan(linkValue, linkDom) {
      GM_xmlhttpRequest({
        url: linkValue,
        method: 'GET',
        headers: {
          'Content-type': 'application/x-www-form-urlencoded',
        },
        onload: function (res) {
          if (res.status === 200) {
            if (
              res.responseText.indexOf('此链接分享内容可能因为涉及侵权') !==
                -1 ||
              res.responseText.indexOf('你所访问的页面不存在了') !== -1 ||
              res.responseText.indexOf('分享的文件已经被取消了') !== -1
            ) {
              linkDom.classList.add('link_faild');
              linkDom.title = '链接资源已经失效!';
            } else {
              linkDom.title = '链接资源正常。';
            }
          } else {
            console.warn('福利吧小助手:\n请求返回状态码异常:', res.status);
          }
        },
        onerror: function (err) {
          console.warn('福利吧小助手:\n网络连接失败。\n', linkValue, err);
        },
        ontimeout: function () {
          console.warn('福利吧小助手:\n请求超时。\n', linkValue);
        },
      });
    }
  }
  function randBin() {
    return Math.random() >= 0.5;
  }
  function str2Utf8(str) {
    const ENCODED_CHARS = /[A-Za-z0-9\-_.!~*'()]/g;
    return Array.from(str)
      .map((char) => {
        if (ENCODED_CHARS.test(char)) {
          ENCODED_CHARS.lastIndex = 0;
          return char.codePointAt(0).toString(16);
        }
        const code = char.charCodeAt(0);
        if (code < 128) {
          return code.toString(16).padStart(2, '0');
        }
        if (code < 2048) {
          return (
            ((code >> 6) | 0xc0).toString(16) +
            ((code & 0x3f) | 0x80).toString(16)
          );
        }
        return (
          ((code >> 12) | 0xe0).toString(16) +
          (((code >> 6) & 0x3f) | 0x80).toString(16) +
          ((code & 0x3f) | 0x80).toString(16)
        );
      })
      .join('')
      .toUpperCase();
  }
  function hex2Duo(hexs) {
    const duo = new Array(hexs.length * 2);
    let index = 0;
    const len = hexs.length;
    for (let i = 0; i < len; i++) {
      const n =
        hexs[i] >= 'a'
          ? hexs.charCodeAt(i) - 87
          : hexs[i] >= 'A'
            ? hexs.charCodeAt(i) - 55
            : hexs.charCodeAt(i) - 48;
      if (n < 10) {
        duo[index++] = n;
      } else {
        if (randBin()) {
          duo[index++] = 10;
          duo[index++] = n - 10;
        } else {
          duo[index++] = 11;
          duo[index++] = n - 6;
        }
      }
    }
    return duo.slice(0, index);
  }
  function utf82Str(utfs) {
    const len = utfs.length * 2;
    const arr = new Array(len);
    for (let i = 0, j = 0; i < utfs.length; i++) {
      arr[j++] = '%';
      arr[j++] = utfs[i];
    }
    return decodeURIComponent(arr.join(''));
  }
  function duo2Hex(duo) {
    const l = duo.length;
    const result = new Array(l);
    let pos = 0;
    for (let i = 0; i < l; i++) {
      const curr = duo[i];
      if (curr < 10) {
        result[pos++] = curr.toString(16).toUpperCase();
      } else if (curr === 10) {
        result[pos++] = (duo[++i] + 10).toString(16).toUpperCase();
      } else {
        result[pos++] = (duo[++i] + 6).toString(16).toUpperCase();
      }
    }
    return result.slice(0, pos).join('');
  }
  function duo2Values(duo) {
    return duo.map((d) => coreValues[2 * d] + coreValues[2 * d + 1]).join('');
  }
  function coreValuesEncode(str) {
    return duo2Values(hex2Duo(str2Utf8(str)));
  }
  function coreValuesDecode(encoded) {
    const duo = [];
    for (let c of encoded) {
      let i = coreValues.indexOf(c);
      if (i === -1) {
        continue;
      } else if (i & 1) {
        continue;
      } else {
        duo.push(i >> 1);
      }
    }
    const hexs = duo2Hex(duo);
    let str;
    try {
      str = utf82Str(hexs);
    } catch (e) {
      throw e;
    }
    return str;
  }
  function isFloat(str) {
    return str == '右侧';
  }
  function baijiaEncode(str) {
    const cleaned = str.replace(TRIM_REGEX, '');
    const value = cleaned.replace(MAGNET_PREFIX_REGEX, '');
    return Array.from(value)
      .map((char) => reverseMap.get(char) || '')
      .join('');
  }
  function baijiaDecode(encoded) {
    const decoded = Array.from(encoded)
      .map((char) => baijiaValues.get(char) || '')
      .join('');
    if (HTTP_PROTOCOL_REGEX.test(decoded)) {
      return decoded.replace(/^(https?)/, '$1:');
    }
    if (URL_PROTOCOL_REGEX.test(decoded)) {
      return decoded;
    }
    return `magnet:?xt=urn:btih:${decoded}`;
  }
  function convertChineseNumber(textString) {
    return textString.replace(
      /[零一二三四五六七八九壹贰叁肆伍陆柒捌玖]/gi,
      (arg0) => {
        let index = '零一二三四五六七八九'.indexOf(arg0);
        if (index === -1) {
          index = '壹贰叁肆伍陆柒捌玖'.indexOf(arg0) + 1;
        }
        return index;
      },
    );
  }
  function filterLink(inputLink) {
    let status = true;
    if (inputLink) {
      for (let i in filterReg) {
        if (filterReg[i].test(inputLink)) {
          status = false;
          break;
        }
      }
    } else {
      status = false;
    }
    return status;
  }
  function getPureLink(inputLink, depthBoolean) {
    const { baidupanIncludeCode } = reg;
    let outputLink = inputLink;
    if (depthBoolean) {
      if (baidupanIncludeCode.test(outputLink)) {
        if (/#[a-z0-9]{4}$/i.test(outputLink)) {
          outputLink = outputLink.replace(/#[a-z0-9]{4}$/i, '');
        }
      } else if (
        /^https?:\/\/www\.bilibili\.com\/video\/av\d+\?from=search/i.test(
          outputLink,
        )
      ) {
        outputLink = outputLink.replace(/\?from=search.*/, '');
      }
    }
    let returnLink = outputLink
      .replace(
        /(^(?:\s+)?(?:\[url\])?(?:\s+)?(?:https?:\/\/)?|(?:\/+)?(?:\s+)?(?:\[\/url\])?$|%C2%A0$)/gi,
        '',
      )
      .replace(/%C2%A0/gi, '%20');
    try {
      returnLink = decodeURI(returnLink);
    } catch (e) {
      console.warn('福利吧小助手:\n出现编码转换错误。', outputLink);
      console.warn(e);
      returnLink = outputLink
        .replace(
          /(^(?:\s+)?(?:\[url\])?(?:\s+)?(?:https?:\/\/)?|(?:\/+)?(?:\s+)?(?:\[\/url\])?$|%C2%A0$)/gi,
          '',
        )
        .replace(/%C2%A0/gi, '%20');
    }
    return returnLink;
  }
  function contrastTextAndLink(textValue, linkValue) {
    let sta = true;
    textValue = getPureLink(textValue, true);
    linkValue = getPureLink(linkValue, true);
    if (/\s...\s/i.test(textValue)) {
      sta = false;
    } else if (textValue === linkValue) {
      sta = false;
    }
    return sta;
  }
  function findLink(container) {
    const { baidupan } = reg;
    const linkA = container.getElementsByTagName('a');
    const tempObj = {
      linkObjArray: [],
      baiduObjArray: [],
      linksArray: [],
    };
    const tempBaiduArray = [];
    for (let i = 0; i < linkA.length; i++) {
      if (linkA[i].closest('div.aimg_tip')) {
        continue;
      }
      const tempLink = linkA[i].href;
      if (filterLink(tempLink)) {
        const tempImg = linkA[i].querySelectorAll('img');
        if (
          tempImg.length === 0 ||
          (tempImg.length > 0 &&
            tempImg[0].src !== tempLink &&
            tempImg[0].getAttribute('file') !== tempLink)
        ) {
          const tempText = linkA[i].innerText.replace(/^\s+|\s+$/gi, '');
          if (contrastTextAndLink(tempText, tempLink)) {
            const linkObj = {
              eleValue: tempLink,
              eleContainer: tempText,
              ele: linkA[i],
            };
            tempObj.linkObjArray.push(linkObj);
          } else if (baidupan.test(tempLink)) {
            const baiduObj = {
              eleValue: tempLink,
              eleContainer: tempText,
              ele: linkA[i],
            };
            if (tempBaiduArray.indexOf(tempLink) === -1) {
              tempBaiduArray.push(tempLink);
              tempObj.baiduObjArray.push(baiduObj);
            }
          }
        }
        tempObj.linksArray.indexOf(tempLink) === -1 &&
          tempObj.linksArray.push(tempLink);
      }
    }
    return tempObj;
  }
  // 定义常量,提高可读性和性能
  const GRAY_THRESHOLD = 192;
  const OPACITY_THRESHOLD = 0.2;
  const GRAY_COEFFICIENTS = {
    R: 0.299,
    G: 0.587,
    B: 0.114,
  };
  function judgeColor(color) {
    // 使用一个正则表达式同时匹配 rgb 和 rgba
    const matches = color.match(
      /rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d*\.?\d+))?\)/i,
    );
    if (!matches) return false;
    const [, r, g, b, a = 1] = matches.map((val) => +val);
    // 如果是 rgba 且透明度低于阈值,直接返回
    if (a <= OPACITY_THRESHOLD) return true;
    // 计算灰度值
    const grayLevel =
      r * GRAY_COEFFICIENTS.R +
      g * GRAY_COEFFICIENTS.G +
      b * GRAY_COEFFICIENTS.B;
    return grayLevel > GRAY_THRESHOLD;
  }
  // 优化后的 rgb 转 rgba 函数
  function rgb2Rgba(colorString) {
    const matches = colorString.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/i);
    if (!matches) return colorString;
    const [, r, g, b] = matches;
    return `rgba(${r}, ${g}, ${b}, 1)`;
  }
  function display_Text(container, newTextColor, newTextBackgroundColor) {
    const { url } = reg;
    const textFont = container.getElementsByTagName('font');
    const tempObj = {
      hideTextArray: [],
      showTextArray: [],
    };
    for (let i = 0; i < textFont.length; i++) {
      if (
        textFont[i].closest('.quote') ||
        textFont[i].getElementsByClassName('aimg_tip').length !== 0
      ) {
        continue;
      }
      const tempText = textFont[i].innerText.replace(/^\s+|\s+$/gi, '');
      if (!/^\s*$/i.test(tempText)) {
        const textColor = window.getComputedStyle(textFont[i]).color;
        const textBackgroundColor = window.getComputedStyle(
          textFont[i],
        ).backgroundColor;
        if (judgeColor(textColor) && judgeColor(textBackgroundColor)) {
          textFont[i].style.color = newTextColor;
          tempObj.hideTextArray.push(tempText);
        } else if (rgb2Rgba(textBackgroundColor) === rgb2Rgba(textColor)) {
          textFont[i].style.backgroundColor = newTextBackgroundColor;
          textFont[i].style.color = newTextColor;
          tempObj.hideTextArray.push(tempText);
        } else if (!judgeColor(textBackgroundColor) && !judgeColor(textColor)) {
          textFont[i].style.backgroundColor = newTextBackgroundColor;
          textFont[i].style.color = newTextColor;
          tempObj.hideTextArray.push(tempText);
        } else if (
          textFont[i].childNodes.length === 1 &&
          textFont[i].childNodes[0].nodeType === 3
        ) {
          if (GM_config.get('extractEnable')) {
            if (url.test(tempText)) {
              textFont[i].innerHTML = textFont[i].innerHTML.replace(
                url,
                (_arg0, arg1) => {
                  return (
                    '<a href="' +
                    convertChineseNumber(arg1) +
                    '" title="点击访问" target="_blank">' +
                    convertChineseNumber(arg1) +
                    '</a>'
                  );
                },
              );
            }
          }
          !tempObj.showTextArray.includes(tempText) &&
            tempObj.showTextArray.push(tempText);
        } else if (textFont[i].childNodes.length > 1) {
          const tFont = textFont[i].childNodes;
          for (let child_index in tFont) {
            analysisText(tFont[child_index]);
          }
          !tempObj.showTextArray.includes(tempText) &&
            tempObj.showTextArray.push(tempText);
        }
      }
    }
    const tempTable = container.getElementsByTagName('table');
    for (let j = 0; j < tempTable.length; j++) {
      if (
        !judgeColor(tempTable[j].style.backgroundColor) &&
        !judgeColor(tempTable[j].style.color)
      ) {
        tempTable[j].style.backgroundColor = newTextBackgroundColor;
      } else if (
        judgeColor(tempTable[j].style.color) &&
        judgeColor(tempTable[j].style.backgroundColor)
      ) {
        tempTable[j].style.color = newTextColor;
      }
    }
    return tempObj;
  }
  function text2A(node) {
    const { url } = reg;
    const tempSpan = document.createElement('span');
    tempSpan.innerHTML = node.nodeValue.replace(url, (arg0, arg1) => {
      if (arg1.length > 2000) {
        return arg0;
      }
      return arg0.replace(
        arg1,
        '<a href="' +
          convertChineseNumber(arg1) +
          '" title="点击访问" target="_blank">' +
          convertChineseNumber(arg1) +
          '</a>',
      );
    });
    node.parentNode.replaceChild(tempSpan, node);
  }
  function analysisText(domPoint) {
    const { url } = reg;
    const nodeList = domPoint.childNodes;
    const nodeTextArray = [];
    for (let i in nodeList) {
      if (nodeList[i].nodeType === 3) {
        const tempText = nodeList[i].nodeValue.replace(/^\s+|\s+$/gi, '');
        if (!/^\s*$/i.test(tempText)) {
          if (GM_config.get('extractEnable')) {
            if (url.test(tempText)) {
              text2A(nodeList[i]);
            }
          }
          nodeTextArray.push(tempText);
        }
      } else if (
        nodeList[i].nodeType === 1 &&
        !nodeList[i].className.includes('quote') &&
        !nodeList[i].className.includes('pstatus') &&
        !nodeList[i].className.includes('aimg_tip') &&
        !nodeList[i].className.includes('blockcode') &&
        nodeList[i].nodeName !== 'FONT' &&
        nodeList[i].nodeName !== 'A' &&
        nodeList[i].nodeName !== 'SCRIPT' &&
        nodeList[i].childNodes.length > 0
      ) {
        const recursiveArray = analysisText(nodeList[i]);
        for (let j in recursiveArray) {
          nodeTextArray.push(recursiveArray[j]);
        }
      }
    }
    return nodeTextArray;
  }
  function isMobilePage() {
    return /android|webos|iphone|ipod|blackberry/i.test(navigator.userAgent);
  }
  function getNowDate() {
    const now = new Date();
    return now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate();
  }
  function getUpdateTime(unixTime) {
    if (!unixTime) return '';
    const formatter = new Intl.DateTimeFormat('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      hour12: false,
    });
    return ` (更新时间: ${formatter.format(new Date(unixTime)).replace(/\//g, '-')})`;
  }
  // 用户权限相关的纯函数
  function calculateUserAccess(level) {
    if (level in CONFIG.LEVEL_ACCESS_MAP) {
      return CONFIG.LEVEL_ACCESS_MAP[level];
    }
    return level >= 1 && level <= 8 ? level * 10 : CONFIG.DEFAULT_ACCESS_NUM;
  }
  // 样式处理相关的纯函数
  function getPostStyle(type, color = '') {
    const styles = {
      blocked:
        'color: #999; font-weight: bold; text-decoration-line: line-through; text-decoration-color: #000000;',
      restricted: 'color: #999; font-weight: bold;',
      highlighted: `font-weight: bold; color: ${color};`,
    };
    return styles[type] || '';
  }
  // 数字提取工具函数
  function extractNumber(text) {
    if (!text) return 0;
    return Number(text.replace('+', ''));
  }
  // 获取最大点赞数
  function getMaxAgreeCount(fontElements) {
    return Array.from(fontElements)
      .map((el) => extractNumber(el.textContent))
      .reduce((max, current) => Math.max(max, current), 0);
  }
  function highlightPost() {
    // 确保DOM已经加载
    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', () => initHighlight());
    } else {
      initHighlight();
    }
  }
  // 初始化高亮功能
  function initHighlight() {
    try {
      updateUserAccessLevel();
      initializePostHighlighting();
    } catch (error) {
      console.warn('福利吧小助手:\n执行出错:', error.message);
    }
  }
  // 更新用户访问权限
  function updateUserAccessLevel() {
    try {
      const upMineElement = document.getElementById('g_upmine');
      if (!upMineElement) return;
      const levelMatch = /LV\.(-?[0-9])/.exec(upMineElement.textContent);
      if (!levelMatch) return;
      const newAccessNum = calculateUserAccess(levelMatch[1]);
      if (status.accessNum !== newAccessNum) {
        status.accessNum = newAccessNum;
        GM_config.setValue('accessNumber', newAccessNum);
      }
    } catch (error) {
      console.warn(
        '福利吧小助手:\n识别用户阅读权限出错,将使用存储中记录的用户阅读权限。',
      );
    }
    console.debug('福利吧小助手:\n用户阅读权限:', status.accessNum);
  }
  // 初始化帖子高亮
  function initializePostHighlighting() {
    // 缓存选择器字符串,避免重复创建字符串
    const THREADLIST_SELECTOR = '#threadlisttableid';
    // 立即检查目标元素
    const threadlist = document.querySelector(THREADLIST_SELECTOR);
    if (threadlist) {
      processThreadList(threadlist);
      return;
    }
    // 创建单个共享的 MutationObserver 配置对象
    const observerConfig = {
      childList: true,
      subtree: true,
    };
    // 使用函数声明提升性能,避免在回调中重复创建函数
    function threadlistCallback(mutations, obs) {
      const threadlist = document.querySelector(THREADLIST_SELECTOR);
      if (threadlist) {
        processThreadList(threadlist);
        obs.disconnect();
      }
    }
    function bodyCallback(mutations, obs) {
      if (document.body) {
        obs.disconnect();
        const observer = new MutationObserver(threadlistCallback);
        observer.observe(document.body, observerConfig);
      }
    }
    // 主逻辑
    if (document.body) {
      const observer = new MutationObserver(threadlistCallback);
      observer.observe(document.body, observerConfig);
    } else {
      const bodyObserver = new MutationObserver(bodyCallback);
      bodyObserver.observe(document.documentElement, {
        childList: true,
      });
    }
  }
  // 处理帖子列表
  function processThreadList(tbody) {
    const items = tbody.querySelectorAll('.common, .new, .lock');
    items.forEach(processPostItem);
  }
  // 处理单个帖子
  function processPostItem(item) {
    const titleElement = item.querySelector('.xst');
    if (!titleElement) return;
    // 如果已经是加粗样式,跳过处理
    if (titleElement.style.fontWeight === '700') return;
    const readNum = extractNumber(item.querySelector('.xw1')?.textContent);
    // 处理阅读权限
    if (readNum > CONFIG.MAX_ACCESS_NUM) {
      titleElement.setAttribute('style', getPostStyle('blocked'));
      return;
    }
    if (readNum > status.accessNum) {
      titleElement.setAttribute('style', getPostStyle('restricted'));
      return;
    }
    // 处理点赞数
    const agreeNum = getMaxAgreeCount(item.querySelectorAll('font'));
    if (agreeNum >= GM_config.get('agreeThreshold')) {
      titleElement.setAttribute(
        'style',
        getPostStyle('highlighted', GM_config.get('agreeColor')),
      );
      return;
    }
    // 处理回复数
    const replyNum = extractNumber(
      item.parentNode.querySelector('td.num a')?.textContent,
    );
    if (replyNum >= GM_config.get('replyTHreshold')) {
      titleElement.setAttribute(
        'style',
        getPostStyle('highlighted', GM_config.get('replyColor')),
      );
    }
  }
  function createSettingsIcon() {
    const iconSpan = document.createElement('span');
    iconSpan.id = 'settingsIcon';
    iconSpan.title = '打开福利吧小助手设置';
    iconSpan.addEventListener('click', () => {
      GM_config.open();
    });
    return iconSpan;
  }
  function operateCode(inputId, outputId, callback, waitStr = '') {
    const str = document.getElementById(inputId).value;
    if (str) {
      document.getElementById(outputId).value = waitStr;
      const result = callback(str, outputId);
      if (result) {
        document.getElementById(outputId).value = result;
      }
    }
  }
  function copyCode(copyBtn, resultId) {
    const copyStr = document.getElementById(resultId).value;
    if (copyStr) {
      GM_setClipboard(copyStr, 'text');
      copyBtn.title = '复制成功';
      copyBtn.classList.add('a_copy_completed');
      status.timer3 && clearTimeout(status.timer3);
      status.timer3 = setTimeout(() => {
        copyBtn.classList.remove('a_copy_completed');
        copyBtn.title = '将输出的结果复制到剪贴板中';
      }, 2000);
    }
  }
  function createSwitchSpan(keyValue, domArray) {
    const switchSpan = document.createElement('span');
    switchSpan.className = 'o';
    const switchImg = document.createElement('img');
    switchImg.id = keyValue + '_user_img';
    switchImg.title = '收起/展开';
    switchImg.alt = '收起/展开';
    if (status[keyValue]) {
      domArray.forEach(function (item) {
        item.classList.add('collapsed_hide');
      });
      switchImg.src = icon.collapsedYes;
    } else {
      switchImg.src = icon.collapsedNo;
    }
    switchImg.addEventListener('click', () => {
      if (status[keyValue]) {
        domArray.forEach((item) => {
          item.classList.remove('collapsed_hide');
        });
        switchImg.src = icon.collapsedNo;
        status[keyValue] = false;
      } else {
        domArray.forEach((item) => {
          item.classList.add('collapsed_hide');
        });
        switchImg.src = icon.collapsedYes;
        status[keyValue] = true;
      }
      GM_config.setValue(keyValue, status[keyValue]);
    });
    switchSpan.appendChild(switchImg);
    return switchSpan;
  }
  function createSignatureSwitch(signature, switchStatus = true) {
    const switchDiv = document.createElement('div');
    switchDiv.className = 'signature_switch_div';
    if (switchStatus) {
      switchDiv.title = '收起';
    } else {
      switchDiv.title = '展开';
      switchDiv.classList.add('signature_switch_close');
      signature.classList.add('signature_hide');
    }
    switchDiv.addEventListener(
      'click',
      () => {
        if (switchStatus) {
          switchStatus = false;
          switchDiv.title = '展开';
          switchDiv.classList.add('signature_switch_close');
          signature.classList.add('signature_hide');
        } else {
          switchStatus = true;
          switchDiv.title = '收起';
          switchDiv.classList.remove('signature_switch_close');
          signature.classList.remove('signature_hide');
        }
      },
      false,
    );
    return switchDiv;
  }
  function mobileInit() {
    const { checkDate, oldUrl } = status;
    if (GM_config.get('highlightEnable')) {
      if (
        oldUrl.indexOf('mod=forumdisplay') !== -1 ||
        /forum-\d+-\d+\.html/i.test(oldUrl)
      ) {
        document.body.arrive(
          '.threadlist li',
          { fireOnAttributesModification: true, existing: true },
          function () {
            let replyNum = this.querySelector(
              'span.num.icon.iconfont',
            ).textContent;
            if (replyNum) {
              replyNum = Number(/\d+/.exec(replyNum)[0]);
              if (replyNum >= GM_config.get('replyTHreshold')) {
                this.querySelector('div.thread-item-sub').setAttribute(
                  'style',
                  'font-weight: bold; color: ' +
                    GM_config.get('replyColor') +
                    ';',
                );
              }
            }
          },
        );
      }
    }
    if (
      oldUrl.indexOf('mod=viewthread') !== -1 ||
      /thread-\d+-\d+(?:-\d+)?\.html/i.test(oldUrl)
    ) {
      const phoneBackgroundColor = window.getComputedStyle(
        document.body,
      ).backgroundColor;
      const messageDom = document.querySelectorAll('.message');
      for (let messageEle of messageDom) {
        const textObj = display_Text(
          messageEle,
          GM_config.get('textColor'),
          phoneBackgroundColor,
        );
        const textArray = analysisText(messageEle);
        const linkObj = findLink(messageEle);
        const goodBoyObj = new Good_Boy(GM_config);
        goodBoyObj.createGoodBoyElement(
          messageEle,
          linkObj,
          textObj,
          textArray,
        );
      }
    }
    if (GM_config.get('autoCheckInEnable')) {
      document.body.arrive(
        '.bg > a',
        { onceOnly: true, existing: true },
        function (item) {
          if (item.textContent === '签到领奖') {
            const nowDate = getNowDate();
            if (nowDate !== checkDate) {
              GM_config.setValue('checkEnable', nowDate);
              setTimeout(() => {
                item.click();
              }, 2000);
              console.info('福利吧小助手:\n完成自动签到。');
            }
          }
        },
      );
    }
  }
  function pcInit() {
    const { baseImage } = reg;
    const { oldUrl } = status;
    if (
      oldUrl.indexOf('mod=forumdisplay') !== -1 ||
      /forum-\d+-\d+\.html/i.test(oldUrl)
    ) {
      if (oldUrl.indexOf('fid=37') !== -1 || /forum-37-/i.test(oldUrl)) {
        document.arrive(
          'div.bm_h.cl',
          {
            fireOnAttributesModification: true,
            onceOnly: true,
            existing: true,
          },
          function () {
            if (this.querySelectorAll('span.y').length === 0) {
              const themeArray = [];
              themeArray.push(this.nextElementSibling);
              this.insertBefore(
                createSwitchSpan('collapsedGwwzEnable', themeArray),
                this.childNodes[0],
              );
            }
          },
        );
      }
      GM_config.get('highlightEnable') && highlightPost();
      if (GM_config.get('visitedEnable')) {
        const visitedStyle =
          '.tl th a.s.xst:visited, .tl td.fn a:visited { color: ' +
          GM_config.get('visitedColor') +
          ' !important; }';
        GM_addStyle(visitedStyle);
        console.debug('福利吧小助手:\n完成注入自定义己访问帖子的样式。');
      }
    }
    if (
      oldUrl.indexOf('mod=viewthread') !== -1 ||
      /thread-\d+-\d+(?:-\d+)?\.html/i.test(oldUrl)
    ) {
      document.addEventListener(
        'DOMContentLoaded',
        () => {
          const tFImg = document.querySelectorAll('td.t_f img');
          for (let imgEle of tFImg) {
            let baseSrc = imgEle.getAttribute('file');
            if (baseImage.test(baseSrc)) {
              baseSrc = baseSrc.replace(baseImage, '$1');
              imgEle.setAttribute('file', baseSrc);
              imgEle.src = baseSrc;
            }
          }
          const zoomImg = document.querySelectorAll('.t_f img.zoom');
          for (let zoomEle of zoomImg) {
            zoomEle.removeAttribute('height');
          }
          const htmlBackgroundColor = window.getComputedStyle(
            document.body,
          ).backgroundColor;
          const tFDom = document.querySelectorAll('td.t_f');
          for (let domEle of tFDom) {
            const goodBoyObj = new Good_Boy(GM_config);
            if (isFloat(GM_config.get('displayPosition'))) {
              const favatarBtn = domEle
                .closest('table.plhin')
                .querySelector('div.favatar');
              const textObj = display_Text(
                domEle,
                GM_config.get('textColor'),
                htmlBackgroundColor,
              );
              const textArray = analysisText(domEle);
              const linkObj = findLink(domEle);
              goodBoyObj.createGoodBoyElement(
                favatarBtn,
                linkObj,
                textObj,
                textArray,
              );
            } else {
              const mainBtn =
                domEle.closest('div.pcb').querySelector('div.t_fsz') ||
                domEle.closest('div.pcb').querySelector('div.pcbs');
              const textObj = display_Text(
                domEle,
                GM_config.get('textColor'),
                htmlBackgroundColor,
              );
              const textArray = analysisText(domEle);
              const linkObj = findLink(domEle);
              goodBoyObj.createGoodBoyElement(
                mainBtn,
                linkObj,
                textObj,
                textArray,
              );
            }
          }
          const signA = document.querySelectorAll('div.sign a');
          for (let signEle of signA) {
            if (/member\.php\?mod=logging&action=logout/i.test(signEle.href)) {
              signEle.style.display = 'none';
            }
          }
          if (GM_config.get('signatureEnable')) {
            const sign = document.querySelectorAll('div.sign');
            const signStatus = GM_config.get('signatureSwitch') == '展开';
            for (let signItem of sign) {
              signItem.insertAdjacentElement(
                'beforebegin',
                createSignatureSwitch(signItem, signStatus),
              );
            }
          }
        },
        false,
      );
    }
    if (GM_config.get('autoCheckInEnable')) {
      document.arrive(
        '#fx_checkin_topb',
        { fireOnAttributesModification: true, onceOnly: true, existing: true },
        function () {
          if (this.getElementsByTagName('img')[0].alt !== '已签到') {
            if (typeof fx_checkin === 'function') {
              this.click();
            } else {
              setTimeout(() => {
                this.click();
              }, 2000);
            }
            console.info('福利吧小助手:\n自动签到完成。');
          }
        },
      );
    }
    if (GM_config.get('codeEnable') || GM_config.get('nightBtnEnable')) {
      document.addEventListener('DOMContentLoaded', function () {
        const expandBox = document.createElement('div');
        expandBox.className = 'expand_box';
        if (GM_config.get('codeEnable') && GM_config.get('nightBtnEnable')) {
          expandBox.className = 'expand_box_h';
        }
        expandBox.onmouseenter = function () {
          this.classList.add('show_expand_box');
        };
        expandBox.onmouseleave = function () {
          this.classList.remove('show_expand_box');
        };
        if (GM_config.get('codeEnable')) {
          // 创建和初始化面板的函数
          const createCodePanel = () => {
            // 使用 DocumentFragment 减少DOM重排
            const fragment = document.createDocumentFragment();
            const codeFrame = document.createElement('div');
            fragment.appendChild(codeFrame);
            // 提取共用的field配置
            const createTextField = (label, section = null) => ({
              label: label,
              section: section,
              type: 'textarea',
              labelPos: 'above',
              placeholder: '请输入内容',
              default: '',
              save: false,
            });
            const createButtonField = (label, title, clickHandler) => ({
              label: label,
              title: title,
              type: 'button',
              click: clickHandler,
            });
            // 创建编解码处理器工厂
            const createCodeHandler =
              (inputId, outputId, processor, processingMsg) => () =>
                operateCode(inputId, outputId, processor, processingMsg);
            // 提取重复的URL配置
            const links = {
              baijia: `${SITE_URLS.HOME}/anhao.html`,
              coreValues: 'https://github.com/sym233/core-values-encoder',
              yflc: 'http://keyfc.net/bbs/tools/tudoucode.aspx',
            };
            // 优化与佛论禅的网络请求处理
            const createYflcProcessor = (action) => (str, resultId) => {
              const handleResponse = (res) => {
                const outputEl = document.getElementById(resultId);
                if (res.status === 200 && res.readyState === 4) {
                  outputEl.value = res.responseText.replace(
                    /^<BUDDHIST><Message><!\[CDATA\[|\]\]><\/Message><\/BUDDHIST>$/g,
                    '',
                  );
                } else {
                  outputEl.value = `${action}出现错误!`;
                }
              };
              GM_xmlhttpRequest({
                method: 'POST',
                url: 'https://keyfc.net/bbs/tools/tudou.aspx',
                data: `orignalMsg=${action === '编码' ? encodeURIComponent(str) : str.replace(/\s/g, '')}&action=${action}`,
                headers: {
                  'Content-Type': 'application/x-www-form-urlencoded',
                },
                onload: handleResponse,
                onerror: () =>
                  (document.getElementById(resultId).value = '网络连接出错!'),
              });
              return false;
            };
            // 配置面板
            const codePanel = new GM_configStruct({
              id: 'myCodePanel',
              title: '编解码工具',
              isTabs: true,
              skin: 'tab',
              frame: codeFrame,
              css: style.codePanel,
              fields: {
                // 百家姓
                bjxInput: {
                  ...createTextField('输入:', [
                    '百家姓',
                    GM_config.create('a', {
                      textContent: '百家姓编码原示例地址',
                      title: '点击跳转到百家姓编码示例',
                      target: '_blank',
                      href: links.baijia,
                    }),
                  ]),
                },
                bjxEncodeBtn: createButtonField(
                  '编码 >>>',
                  '使用"百家姓"进行编码',
                  createCodeHandler(
                    'myCodePanel_field_bjxInput',
                    'myCodePanel_field_bjxOutput',
                    baijiaEncode,
                    '编码中...',
                  ),
                ),
                bjxDecodeBtn: createButtonField(
                  '解码 >>>',
                  '对"百家姓"的编码进行解码',
                  createCodeHandler(
                    'myCodePanel_field_bjxInput',
                    'myCodePanel_field_bjxOutput',
                    baijiaDecode,
                    '解码中...',
                  ),
                ),
                bjxOutput: createTextField('输出:'),
                bjxCopyBtn: createButtonField(
                  '复制结果',
                  '将输出的结果复制到剪贴板中',
                  function () {
                    copyCode(this, 'myCodePanel_field_bjxOutput');
                  },
                ),
                // 社会主义核心价值观
                coreValuesInput: {
                  ...createTextField('输入:', [
                    '社会主义核心价值观',
                    GM_config.create('a', {
                      textContent: '社会主义核心价值观编码项目地址',
                      title: '点击跳转到社会主义核心价值观编码项目',
                      target: '_blank',
                      href: links.coreValues,
                    }),
                  ]),
                },
                coreValuesEncodeBtn: createButtonField(
                  '编码 >>>',
                  '使用"社会主义核心价值观"进行编码',
                  createCodeHandler(
                    'myCodePanel_field_coreValuesInput',
                    'myCodePanel_field_coreValuesOutput',
                    coreValuesEncode,
                    '编码中...',
                  ),
                ),
                coreValuesDecodeBtn: createButtonField(
                  '解码 >>>',
                  '对"社会主义核心价值观"的编码进行解码',
                  createCodeHandler(
                    'myCodePanel_field_coreValuesInput',
                    'myCodePanel_field_coreValuesOutput',
                    coreValuesDecode,
                    '解码中...',
                  ),
                ),
                coreValuesOutput: createTextField('输出:'),
                coreValuesCopyBtn: createButtonField(
                  '复制结果',
                  '将输出的结果复制到剪贴板中',
                  function () {
                    copyCode(this, 'myCodePanel_field_coreValuesOutput');
                  },
                ),
                // 与佛论禅
                yflcInput: {
                  ...createTextField('输入:', [
                    '与佛论禅',
                    GM_config.create('a', {
                      textContent: '与佛论禅编码原工具地址',
                      title: '点击跳转到与佛论禅编码工具',
                      target: '_blank',
                      href: links.yflc,
                    }),
                  ]),
                },
                yflcEncodeBtn: createButtonField(
                  '编码 >>>',
                  '使用"与佛论禅"进行编码',
                  createCodeHandler(
                    'myCodePanel_field_yflcInput',
                    'myCodePanel_field_yflcOutput',
                    createYflcProcessor('编码'),
                    '联网进行编码中...',
                  ),
                ),
                yflcDecodeBtn: createButtonField(
                  '解码 >>>',
                  '对"与佛论禅"的编码进行解码',
                  createCodeHandler(
                    'myCodePanel_field_yflcInput',
                    'myCodePanel_field_yflcOutput',
                    createYflcProcessor('解码'),
                    '联网进行解码中...',
                  ),
                ),
                yflcOutput: createTextField('输出:'),
                yflcCopyBtn: createButtonField(
                  '复制结果',
                  '将输出的结果复制到剪贴板中',
                  function () {
                    copyCode(this, 'myCodePanel_field_yflcOutput');
                  },
                ),
                // BASE64
                base64Input: {
                  ...createTextField('输入:', [
                    'BASE64',
                    GM_config.create('a', {
                      textContent: 'crypto-js 项目地址',
                      title: '点击跳转到 crypto-js 项目',
                      target: '_blank',
                      href: 'https://github.com/brix/crypto-js',
                    }),
                  ]),
                },
                base64EncodeBtn: createButtonField(
                  '编码 >>>',
                  '使用"BASE64"进行编码',
                  createCodeHandler(
                    'myCodePanel_field_base64Input',
                    'myCodePanel_field_base64Output',
                    (str) => {
                      if (!window.CryptoJS) return 'crypto-js 库文件不存在!';
                      const words = CryptoJS.enc.Utf8.parse(str);
                      return CryptoJS.enc.Base64.stringify(words);
                    },
                    '编码中...',
                  ),
                ),
                base64DecodeBtn: createButtonField(
                  '解码 >>>',
                  '对"BASE64"的编码进行解码',
                  createCodeHandler(
                    'myCodePanel_field_base64Input',
                    'myCodePanel_field_base64Output',
                    (str) => {
                      if (!window.CryptoJS) return 'crypto-js 库文件不存在!';
                      const words = CryptoJS.enc.Base64.parse(str);
                      return words.toString(CryptoJS.enc.Utf8);
                    },
                    '解码中...',
                  ),
                ),
                base64Output: createTextField('输出:'),
                base64CopyBtn: createButtonField(
                  '复制结果',
                  '将输出的结果复制到剪贴板中',
                  function () {
                    copyCode(this, 'myCodePanel_field_base64Output');
                  },
                ),
              },
              events: {
                open: function (doc) {
                  const config = this;
                  const closeBtn = doc.getElementById(config.id + '_closeBtn');
                  const resetLink = doc.getElementById(
                    config.id + '_resetLink',
                  );
                  if (closeBtn) closeBtn.title = '关闭面板';
                  if (resetLink) {
                    resetLink.textContent = '清空内容';
                    resetLink.title = '清空所有内容';
                  }
                },
              },
            });
            // 创建打开面板的按钮
            const codeSpan = document.createElement('span');
            codeSpan.id = 'myCodeSpan';
            codeSpan.title = '打开编解码工具';
            codeSpan.addEventListener('click', () => codePanel.open(), {
              passive: true,
            });
            // 一次性添加所有DOM元素
            document.body.appendChild(fragment);
            expandBox.appendChild(codeSpan);
            return codePanel;
          };
          // 初始化面板
          createCodePanel();
        }
        if (GM_config.get('nightBtnEnable')) {
          const nightBtnSpan = document.createElement('span');
          nightBtnSpan.id = 'myNightSpan';
          if (GM_config.get('codeEnable')) {
            nightBtnSpan.id = 'myNightSpan_2';
          }
          if (status.nightEnable) {
            nightBtnSpan.style.backgroundImage = icon.modeNight;
            nightBtnSpan.title = '切换到日间模式';
          } else {
            nightBtnSpan.style.backgroundImage = icon.modeDay;
            nightBtnSpan.title = '切换到夜间模式';
          }
          nightBtnSpan.addEventListener(
            'click',
            () => {
              if (status.nightEnable) {
                status.nightStyleDom &&
                  status.nightStyleDom.parentNode.removeChild(
                    status.nightStyleDom,
                  );
                status.nightEnable = false;
                GM_config.setValue('nightEnable', status.nightEnable);
                nightBtnSpan.title = '切换到夜间模式';
                nightBtnSpan.style.backgroundImage = icon.modeDay;
              } else {
                status.nightStyleDom = GM_addStyle(style.night);
                status.nightEnable = true;
                GM_config.setValue('nightEnable', status.nightEnable);
                nightBtnSpan.title = '切换到日间模式';
                nightBtnSpan.style.backgroundImage = icon.modeNight;
              }
            },
            false,
          );
          expandBox.appendChild(nightBtnSpan);
        }
        document.body.appendChild(expandBox);
      });
    }
    document.arrive(
      '#sslct',
      { fireOnAttributesModification: true, onceOnly: true, existing: true },
      (item) => {
        item.after(createSettingsIcon());
      },
    );
    document.arrive(
      '.site-nav.site-navbar',
      { fireOnAttributesModification: true, onceOnly: true, existing: true },
      (nav) => {
        // 在搜索按钮前插入设置图标
        const searchLi = nav.querySelector('.navto-search');
        if (searchLi) {
          nav.insertBefore(createSettingsIcon(), searchLi);
        } else {
          nav.appendChild(createSettingsIcon());
        }
      },
    );
  }
  function aInit() {
    try {
      GM_registerMenuCommand('福利吧小助手 - 设置', () => {
        GM_config.open();
      });
    } catch (e) {
      console.error('福利吧小助手:\n在扩展中注册菜单项出错!');
      console.error(e);
    }
    GM_addStyle(style.basic);
    if (isMobilePage()) {
      console.info('福利吧小助手:\n当前页面为移动端页面。');
      document.addEventListener('DOMContentLoaded', () => {
        mobileInit();
      });
    } else {
      if (document.head) {
        if (document.head.querySelector('title')) {
          if (status.nightEnable) {
            status.nightStyleDom = GM_addStyle(style.night);
          }
          pcInit();
        } else {
          document.addEventListener('DOMContentLoaded', function () {
            console.warn('福利吧小助手:\n网页加载失败。即将自动刷新重载。');
            status.timer4 && clearTimeout(status.timer4);
            status.timer4 = setTimeout(() => {
              location.reload();
            }, 2000);
          });
        }
      } else {
        if (status.nightEnable) {
          status.nightStyleDom = GM_addStyle(style.night);
        }
        pcInit();
      }
    }
    if (
      location.hostname.includes('fulibus.net') ||
      location.hostname.includes('fuliba') ||
      location.hostname.includes('f.uliba.net')
    ) {
      // 简化首页
      removeElements();
      adjustStyles();
      simplifyNavigation();
      removePromotions();
      // 处理正文内容
      document.addEventListener('DOMContentLoaded', () => {
        processText();
      });
    }
  }
  // 移除多余元素
  function removeElements() {
    ELEMENTS_TO_REMOVE.forEach((selector) => {
      const element = document.querySelector(selector);
      element?.parentNode.removeChild(element);
    });
  }
  // 调整样式
  function adjustStyles() {
    const header = document.querySelector('.header');
    if (header) header.style.padding = '20px 0';
    const content = document.querySelector('.content');
    if (content) content.style.marginRight = '0';
  }
  // 优化导航栏
  function simplifyNavigation() {
    const nav = document.querySelector('ul.site-nav.site-navbar');
    if (!nav) return;
    function shouldKeepSpecific(element) {
      const text = element.textContent.trim();
      return KEEP_KEYWORDS.some((keyword) => text.includes(keyword));
    }
    function shouldBlock(element) {
      const text = element.textContent.toLowerCase();
      const link = element.querySelector('a')?.href.toLowerCase() || '';
      return BLOCK_KEYWORDS.some(
        (keyword) =>
          text.includes(keyword.toLowerCase()) ||
          link.includes(keyword.toLowerCase()),
      );
    }
    function shouldKeep(element) {
      const text = element.textContent;
      const isSearch = element.classList.contains('navto-search');
      const isSpecificItem = shouldKeepSpecific(element);
      return (
        isSpecificItem ||
        isSearch ||
        ((text.includes('福') || text.includes('关于')) &&
          !shouldBlock(element))
      );
    }
    function processNavItems(parent) {
      Array.from(parent.children).forEach((item) => {
        if (item.tagName.toLowerCase() === 'li') {
          const subMenu = item.querySelector('.sub-menu');
          if (subMenu) {
            processNavItems(subMenu);
          }
          // 如果子菜单为空且父项不是特定保留项,则删除父项
          if (
            subMenu &&
            subMenu.children.length === 0 &&
            !shouldKeepSpecific(item)
          ) {
            item.remove();
          }
          // 如果不应保留,则删除
          else if (!shouldKeep(item)) {
            item.remove();
          }
        }
      });
    }
    processNavItems(nav);
  }
  // 移除推广内容
  function removePromotions() {
    const content = document.querySelector('.content');
    if (!content) return;
    Array.from(content.querySelectorAll('article')).forEach((article) => {
      const likeCount = parseInt(
        article.querySelector('.post-like span')?.textContent,
      );
      if (likeCount > 100) article.remove();
    });
  }
  // 处理正文内容
  function processText() {
    const paragraphs = document.querySelectorAll('p');
    paragraphs.forEach((p) => {
      const text = p.innerText;
      // 处理百家姓编码
      const surnameMatches = findSurnameEncoding(text);
      if (surnameMatches.length > 0) {
        let newText = text;
        surnameMatches.forEach((match) => {
          const decoded = processSurnameEncoding(match);
          if (decoded) {
            // 创建新的链接元素
            const link = document.createElement('a');
            link.href = decoded;
            link.textContent = decoded;
            link.target = '_blank';
            link.className = 'my_good_boy_a'; // 使用原有的链接样式类
            // 替换原文本
            newText = newText.replace(match, '');
            p.innerHTML = newText;
            p.appendChild(document.createElement('br'));
            p.appendChild(link);
            // 添加复制按钮
            if (GM_config.get('copyEnable')) {
              const copyBtn = document.createElement('a');
              copyBtn.className = 'my_good_boy_a_copy';
              copyBtn.title = '复制链接';
              copyBtn.href = 'javascript:;';
              copyBtn.textContent = '复制';
              copyBtn.addEventListener('click', function () {
                GM_setClipboard(decoded, 'text');
                this.classList.add('a_copy_completed');
                this.title = '复制成功';
                status.timer1 && clearTimeout(status.timer1);
                status.timer1 = setTimeout(() => {
                  this.classList.remove('a_copy_completed');
                  this.title = '复制链接';
                }, 2000);
              });
              p.appendChild(copyBtn);
            }
          }
        });
      }
      // 处理YouTube链接
      if (text.includes('watch?v=')) {
        const videoId = text.split('?v=')[1]?.split(/[\s&]/)[0];
        if (videoId) {
          const link = document.createElement('a');
          link.href = `https://www.youtube.com/watch?v=${videoId}`;
          link.textContent = '油管链接';
          link.target = '_blank';
          link.className = 'my_good_boy_a';
          p.appendChild(link);
        }
      }
    });
  }
  // 查找百家姓编码
  function findSurnameEncoding(text) {
    // 使用原有的 reg.baijia 正则表达式
    const matches = reg.baijia.exec(text);
    return matches ? [matches[1]] : [];
  }
  // 处理百家姓编码
  function processSurnameEncoding(encodedText) {
    try {
      // 使用原有的 baijiaDecode 函数解码
      const decoded = baijiaDecode(encodedText);
      // 验证解码结果是否是有效的链接
      if (isValidDecodedLink(decoded)) {
        return decoded;
      }
      return null;
    } catch (e) {
      console.warn('福利吧小助手:\n百家姓解码出错:', e);
      return null;
    }
  }
  // 验证解码结果
  function isValidDecodedLink(decoded) {
    // 验证是否是磁力链接
    if (decoded.startsWith('magnet:?xt=urn:btih:')) {
      const hash = decoded.replace('magnet:?xt=urn:btih:', '');
      return /^[a-fA-F0-9]{40}$/i.test(hash);
    }
    // 验证是否是http/https链接
    if (decoded.startsWith('http://') || decoded.startsWith('https://')) {
      try {
        new URL(decoded);
        return true;
      } catch (e) {
        return false;
      }
    }
    // 验证是否是其他支持的协议链接
    const supportedProtocols = [
      'ed2k://',
      'thunder://',
      'flashget://',
      'qqdl://',
      'xfplay://',
      'ftp://',
    ];
    return supportedProtocols.some((protocol) => decoded.startsWith(protocol));
  }
  GM_config.init({
    id: 'myGoodBoyConfig',
    title: GM_config.create('a', {
      textContent: '福利吧小助手-设置 ver.' + GM_info.script.version,
      title: '点击跳转到脚本页面' + getUpdateTime(GM_info.script.lastModified),
      target: '_blank',
      href: 'https://sleazyfork.org/zh-CN/scripts/381494',
    }),
    skin: 'tab',
    css: style.settings,
    frameStyle: {
      width: '400px',
      height: '720px',
    },
    fields: {
      autoCheckInEnable: {
        label: '自动签到',
        title: '进入论坛后自动点击签到按钮',
        labelPos: 'right',
        type: 'checkbox',
        default: true,
        section: GM_config.create('a', {
          textContent: '作者: aoguai',
          title: '点击反馈问题',
          target: '_blank',
          href:
            location.origin +
            '/home.php?mod=spacecp&ac=pm&op=showmsg&touid=90713',
        }),
      },
      nightBtnEnable: {
        label: '显示切换夜间模式的悬浮按钮',
        title: '将鼠标移至网页右下角弹出 (仅支持电脑端页面)',
        labelPos: 'right',
        type: 'checkbox',
        default: true,
      },
      codeEnable: {
        label: '显示编解码工具的悬浮按钮',
        title: '将鼠标移至网页右下角弹出 (仅支持电脑端页面)',
        labelPos: 'right',
        type: 'checkbox',
        default: false,
      },
      copyEnable: {
        label: '显示复制按钮',
        title: '在所提取链接后显示复制按钮',
        labelPos: 'right',
        type: 'checkbox',
        default: true,
      },
      extractEnable: {
        label: '识别文字中的网址并转换为超链接',
        title: '将帖子中网址文字转换为可点击访问的超链接',
        labelPos: 'right',
        type: 'checkbox',
        default: true,
      },
      checkEnable: {
        label: '自动检测百度网盘链接有效性',
        title: '检测并标记出已经失效的百度网盘链接',
        labelPos: 'right',
        type: 'checkbox',
        default: false,
      },
      displayPosition: {
        label: '自定义提取链接的显示位置: ',
        title: '指定所提取链接的显示位置 (仅支持电脑端页面)',
        labelPos: 'left',
        type: 'select',
        options: ['底部', '右侧'],
        default: '底部',
      },
      maxLinkNumber: {
        label: '所提取链接的最大显示数量: ',
        title: '每个楼层所提取链接的默认最大显示数量值 (-1 表示无限制)',
        labelPos: 'left',
        type: 'int',
        size: 18,
        default: 5,
      },
      linkColor: {
        label: '自定义提取链接的文字颜色: ',
        title: '设定所提取链接显示的文字颜色',
        labelPos: 'left',
        type: 'text',
        size: 18,
        default: '#369',
      },
      textColor: {
        label: '自定义隐藏文字的高亮颜色: ',
        title: '设定将隐藏文字高亮的颜色',
        labelPos: 'left',
        type: 'text',
        size: 18,
        default: '#FF33CC',
      },
      signatureEnable: {
        label: '显示签名档折叠图标',
        title: '在签名档的左上方显示一个折叠图标',
        labelPos: 'right',
        type: 'checkbox',
        default: true,
        line: 'start',
      },
      signatureSwitch: {
        label: '签名档的默认折叠状态: ',
        title: '自定义签名档默认的折叠状态',
        labelPos: 'left',
        type: 'select',
        options: ['展开', '收起'],
        default: '展开',
        line: 'end',
      },
      highlightEnable: {
        label: '启用热帖高亮功能',
        title: '在帖子列表页面开启热帖高亮 (移动端页面只支持回复高亮)',
        labelPos: 'right',
        type: 'checkbox',
        default: true,
        line: 'start',
      },
      agreeThreshold: {
        label: '按分享值高亮的阈值: ',
        title: '分享值>=阈值时高亮',
        labelPos: 'left',
        type: 'unsigned int',
        size: 18,
        default: 20,
      },
      agreeColor: {
        label: '按分享值高亮的颜色: ',
        title: '优化级高',
        labelPos: 'left',
        type: 'text',
        size: 18,
        default: '#EE1B2E',
      },
      replyTHreshold: {
        label: '按回复数高亮的阈值: ',
        title: '回复数>=阈值时高亮',
        labelPos: 'left',
        type: 'unsigned int',
        size: 18,
        default: 50,
      },
      replyColor: {
        label: '按回复数高亮的颜色: ',
        title: '优化级低',
        labelPos: 'left',
        type: 'text',
        size: 18,
        default: '#2B65B7',
        line: 'end',
      },
      visitedEnable: {
        label: '标记已打开过的帖子',
        title: '允许将已打开过的帖子设置成自定义的颜色',
        labelPos: 'right',
        type: 'checkbox',
        default: false,
        line: 'start',
      },
      visitedColor: {
        label: '自定义已打开过的帖子的颜色',
        title: '优先级最高',
        labelPos: 'left',
        type: 'text',
        size: 18,
        default: '#666',
        line: 'end',
      },
    },
    events: {
      init: async () => {
        console.debug('福利吧小助手:\n配置信息读取完成。');
        try {
          // 等待获取网站地址
          await initSiteUrls();
          // 继续执行其他初始化
          aInit();
        } catch (error) {
          console.error('福利吧小助手:\n获取网站地址失败:', error);
          // 即使获取地址失败也继续执行其他初始化
          aInit();
        }
      },
      save: () => {
        location.reload();
      },
    },
  });
})();