ニコニコ動画 引用コメントツール

dアニメストア ニコニコ支店の引用コメント関連のツール

当前为 2022-11-26 提交的版本,查看 最新版本

// ==UserScript==
// @name         ニコニコ動画 引用コメントツール
// @namespace    https://midra.me
// @version      2.0.2
// @description  dアニメストア ニコニコ支店の引用コメント関連のツール
// @author       Midra
// @license      MIT
// @match        https://www.nicovideo.jp/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=nicovideo.jp
// @run-at       document-start
// @noframes
// @grant        unsafeWindow
// @grant        GM_addStyle
// @grant        GM.addStyle
// @grant        GM_getValue
// @grant        GM.getValue
// @grant        GM_setValue
// @grant        GM.setValue
// @grant        GM_deleteValue
// @grant        GM.deleteValue
// @grant        GM_registerMenuCommand
// @grant        GM_xmlhttpRequest
// @connect      nicovideo.jp
// ==/UserScript==

"use strict";
(() => {
  var __defProp = Object.defineProperty;
  var __export = (target, all) => {
    for (var name in all)
      __defProp(target, name, { get: all[name], enumerable: true });
  };
  var __accessCheck = (obj, member, msg) => {
    if (!member.has(obj))
      throw TypeError("Cannot " + msg);
  };
  var __privateGet = (obj, member, getter) => {
    __accessCheck(obj, member, "read from private field");
    return getter ? getter.call(obj) : member.get(obj);
  };
  var __privateAdd = (obj, member, value) => {
    if (member.has(obj))
      throw TypeError("Cannot add the same private member more than once");
    member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
  };
  var __privateSet = (obj, member, value, setter) => {
    __accessCheck(obj, member, "write to private field");
    setter ? setter.call(obj, value) : member.set(obj, value);
    return value;
  };

  // src/window.ts
  var globalWindow;
  try {
    globalWindow = unsafeWindow;
  } catch {
    try {
      const elem = document.createElement("div");
      elem.setAttribute("onclick", "return window");
      const result = elem.onclick(null);
      globalWindow = result !== void 0 ? result : window;
    } catch {
      globalWindow = window;
    }
  }
  var origFetch = globalWindow.fetch;

  // ../../UserScript/Library/MidConfig/src/extensionAPI.ts
  var isChromeExtension = () => Boolean(window["ECT:isChromeExtension"]);
  var generateUID = () => `${Array.from(Array(10)).map(() => "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[Math.random() * 62 | 0]).join("")}_${Date.now()}`;
  var StorageAPI = {
    get(keys) {
      return new Promise(async (resolve, reject) => {
        if (isChromeExtension()) {
          try {
            const uid = generateUID();
            const onMessage = ({ data }) => {
              if (data.type === "MIDEXT:storage:get:return" && data.uid === uid) {
                window.removeEventListener("message", onMessage);
                data.error ? reject() : resolve(data.value);
              }
            };
            window.addEventListener("message", onMessage);
            window.postMessage({
              type: "MIDEXT:storage:get",
              keys,
              uid
            });
            setTimeout(() => {
              window.removeEventListener("message", onMessage);
              reject();
            }, 2500);
          } catch (e) {
            reject(e);
          }
        } else {
          let getValue = null;
          try {
            getValue = GM_getValue;
          } catch {
            try {
              getValue = GM.getValue;
            } catch {
            }
          }
          try {
            const items = {};
            for (const key of Array.isArray(keys) ? keys : [keys]) {
              if (typeof getValue === "function") {
                items[key] = getValue(key);
                if (items[key] instanceof Promise) {
                  items[key] = await items[key];
                }
              } else {
                const localItem = localStorage.getItem(key);
                items[key] = localItem !== null ? JSON.parse(localItem) : void 0;
              }
            }
            if (Array.isArray(keys)) {
              resolve(items);
            } else {
              resolve(items[keys]);
            }
          } catch (e) {
            reject(e);
          }
        }
      });
    },
    set(key, value) {
      return new Promise(async (resolve, reject) => {
        if (isChromeExtension()) {
          try {
            const uid = generateUID();
            const onMessage = ({ data }) => {
              if (data.type === "MIDEXT:storage:set:return" && data.uid === uid) {
                window.removeEventListener("message", onMessage);
                data.error ? reject() : resolve();
              }
            };
            window.addEventListener("message", onMessage);
            window.postMessage({
              type: "MIDEXT:storage:set",
              key,
              value,
              uid
            });
            setTimeout(() => {
              window.removeEventListener("message", onMessage);
              reject();
            }, 2500);
          } catch (e) {
            reject(e);
          }
        } else {
          let setValue = null;
          try {
            setValue = GM_setValue;
          } catch {
            try {
              setValue = GM.setValue;
            } catch {
            }
          }
          try {
            if (typeof setValue === "function") {
              const result = setValue(key, value);
              if (result instanceof Promise) {
                await result;
              }
            } else {
              localStorage.setItem(key, value);
            }
            resolve();
          } catch (e) {
            reject(e);
          }
        }
      });
    },
    remove(keys) {
      return new Promise(async (resolve, reject) => {
        if (isChromeExtension()) {
          try {
            const uid = generateUID();
            const onMessage = ({ data }) => {
              if (data.type === "MIDEXT:storage:remove:return" && data.uid === uid) {
                window.removeEventListener("message", onMessage);
                data.error ? reject() : resolve();
              }
            };
            window.addEventListener("message", onMessage);
            window.postMessage({
              type: "MIDEXT:storage:remove",
              keys,
              uid
            });
            setTimeout(() => {
              window.removeEventListener("message", onMessage);
              reject();
            }, 2500);
          } catch (e) {
            reject(e);
          }
        } else {
          let deleteValue = null;
          try {
            deleteValue = GM_deleteValue;
          } catch {
            try {
              deleteValue = GM.deleteValue;
            } catch {
            }
          }
          try {
            for (const key of Array.isArray(keys) ? keys : [keys]) {
              if (typeof deleteValue === "function") {
                const result = deleteValue(key);
                if (result instanceof Promise) {
                  await result;
                }
              } else {
                localStorage.removeItem(key);
              }
            }
            resolve();
          } catch (e) {
            reject(e);
          }
        }
      });
    }
  };
  var FetchAPI = (input, init) => {
    return new Promise(async (resolve, reject) => {
      if (isChromeExtension()) {
        try {
          const uid = generateUID();
          const onMessage = ({ data }) => {
            if (data.type === "MIDEXT:fetch:return" && data.uid === uid) {
              window.removeEventListener("message", onMessage);
              data.error ? reject() : resolve(data.response);
            }
          };
          window.addEventListener("message", onMessage);
          window.postMessage({
            type: "MIDEXT:fetch",
            input,
            init,
            uid
          });
          setTimeout(() => {
            window.removeEventListener("message", onMessage);
            reject();
          }, 5e3);
        } catch (e) {
          reject(e);
        }
      } else {
        try {
          if (typeof GM_xmlhttpRequest === "function") {
            GM_xmlhttpRequest({
              method: init?.method || "GET",
              url: input,
              headers: init?.headers,
              onload: (e) => {
                if (e.readyState === XMLHttpRequest.DONE) {
                  const headers = {};
                  e.responseHeaders.trim().split(/[\r\n]+/).forEach((line) => {
                    const parts = line.split(": ");
                    const header = parts.shift();
                    const value = parts.join(": ");
                    headers[header] = value;
                  });
                  resolve(new Response(e.responseText, {
                    status: e.status,
                    statusText: e.statusText,
                    headers
                  }));
                } else {
                  reject(e);
                }
              },
              onerror: (e) => reject(e)
            });
          } else {
            throw new Error();
          }
        } catch {
          reject();
        }
      }
    });
  };

  // src/constants.ts
  var ECT_ID = "extra-comment-tools";
  var DANIME_CHANNEL_ID = "ch2632720";
  var WATCH_V3_API = "https://www.nicovideo.jp/api/watch/v3";
  var THREADS_API = "https://nvcomment.nicovideo.jp/v1/threads";
  var CHANNEL_VIDEO_DANIME_LINKS_API = "https://public-api.ch.nicovideo.jp/v1/user/channelVideoDAnimeLinks";
  var SEARCH_V2_API = "https://api.search.nicovideo.jp/api/v2/snapshot/video/contents/search";
  var NICORU_KEYS_API = " https://nvapi.nicovideo.jp/v1/comment/keys/nicoru";
  var STYLE = `
#midconfig-wrapper {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  background-color: #00000080;
  z-index: 9999999;
}
.midconfig-panel {
  width: 550px;
  height: 450px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
`;

  // src/apis/getVideoData.ts
  var getVideoData = async (videoId) => {
    if (videoId === void 0) {
      throw new Error("[ECT] ERROR: videoId is undefined");
    }
    try {
      const requestQuery = {
        actionTrackId: `${Array.from(Array(10)).map(() => "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[Math.random() * 62 | 0]).join("")}_${Date.now()}`
      };
      const res = await origFetch(`${WATCH_V3_API}/${videoId}?${new URLSearchParams(requestQuery)}`, {
        method: "GET",
        headers: {
          "x-client-os-type": "others",
          "x-frontend-id": "6",
          "x-frontend-version": "0"
        }
      });
      if (res.ok) {
        const json = await res.json();
        if (json.data !== void 0) {
          return json.data;
        }
      }
    } catch (e) {
      throw new Error(e);
    }
    throw new Error("[ECT] ERROR: getVideoData");
  };
  var getVideoData_default = getVideoData;

  // src/apis/getThreads.ts
  var getThreads = async (videoData) => {
    if (videoData === void 0) {
      throw new Error("[ECT] ERROR: videoData is undefined");
    }
    try {
      const res = await origFetch(THREADS_API, {
        method: "POST",
        headers: {
          "x-client-os-type": "others",
          "x-frontend-id": "6",
          "x-frontend-version": "0"
        },
        body: JSON.stringify({
          additionals: {},
          params: videoData.comment?.nvComment?.params || {},
          threadKey: videoData.comment?.nvComment?.threadKey
        })
      });
      if (res.ok) {
        const json = await res.json();
        if (json?.data !== void 0) {
          return json.data.threads;
        }
      }
    } catch (e) {
      throw new Error(e);
    }
    throw new Error("[ECT] ERROR: getThreads");
  };
  var getThreads_default = getThreads;

  // src/apis/getLinkedVideoId.ts
  var getLinkedVideoId = async (videoId) => {
    if (videoId === void 0) {
      throw new Error("[ECT] ERROR: videoId is undefined");
    }
    try {
      const requestQuery = {
        videoId,
        _frontendId: "6"
      };
      const res = await origFetch(`${CHANNEL_VIDEO_DANIME_LINKS_API}?${new URLSearchParams(requestQuery)}`);
      if (res.ok) {
        const json = await res.json();
        if (json.data !== void 0) {
          return json.data.items[0].linkedVideoId;
        }
      }
    } catch (e) {
      throw new Error(e);
    }
    throw new Error("[ECT] ERROR: getLinkedVideoId");
  };
  var getLinkedVideoId_default = getLinkedVideoId;

  // src/apis/getNicoruKey.ts
  var getNicoruKey = async (threadId, fork) => {
    if (threadId === void 0 || fork === void 0) {
      throw new Error("[ECT] ERROR: threadId or fork is undefined");
    }
    try {
      const requestQuery = {
        threadId,
        fork
      };
      const res = await origFetch(`${NICORU_KEYS_API}?${new URLSearchParams(requestQuery)}`, {
        method: "GET",
        headers: {
          "x-frontend-id": "6",
          "x-frontend-version": "0"
        },
        credentials: "include"
      });
      if (res.ok) {
        const json = await res.json();
        if (json.data !== void 0) {
          return json.data.nicoruKey;
        }
      }
    } catch (e) {
      throw new Error(e);
    }
    throw new Error("[ECT] ERROR: getNicoruKey");
  };
  var getNicoruKey_default = getNicoruKey;

  // src/utils/migrationConfig.ts
  var migrationConfig = async (config) => {
    const json = config.getJSON();
    if (!isChromeExtension()) {
      if (json.version <= 1) {
        if (!Boolean(await StorageAPI.get(`midconfig-${ECT_ID}`))) {
          const oldConfigKeys = [
            "extraMain",
            "extraEasy",
            "extraMainFromDanime",
            "forcedExtra",
            "showAddedCommentCount",
            "showExtraViewCount",
            "deleteExtra",
            "deleteEasy",
            "kawaiiPct",
            "www.nicovideo.jp"
          ];
          const oldConfig = await StorageAPI.get(oldConfigKeys);
          const general = json.data["general"];
          general["mergeExtraMain"].value = oldConfig["extraMain"];
          general["mergeExtraEasy"].value = oldConfig["extraEasy"];
          general["mergeExtraFromDanime"].value = oldConfig["extraMainFromDanime"];
          general["forcedExtra"].value = oldConfig["forcedExtra"];
          general["deleteExtra"].value = oldConfig["deleteExtra"];
          general["deleteEasy"].value = oldConfig["deleteEasy"];
          general["showMergedCommentCount"].value = oldConfig["showAddedCommentCount"];
          general["showExtraViewCount"].value = oldConfig["showExtraViewCount"];
          general["showKawaiiPct"].value = oldConfig["kawaiiPct"];
          Object.keys(general).forEach((key) => {
            general[key].checked = general[key].value;
          });
          config.setJSON(json);
          await config.save();
          await StorageAPI.remove(oldConfigKeys);
        }
      }
    }
  };
  var migrationConfig_default = migrationConfig;

  // src/utils/injectStyle.ts
  var injectStyle = (css) => {
    const style = document.createElement("style");
    style.textContent = css;
    document.head.appendChild(style);
  };
  var injectStyle_default = injectStyle;

  // src/utils/generateDocumentByHTML.ts
  var generateDocumentByHTML = (html) => {
    const elem = document.createElement("html");
    elem.insertAdjacentHTML("beforeend", html);
    return elem;
  };
  var generateDocumentByHTML_default = generateDocumentByHTML;

  // src/utils/generateElementByHTML.ts
  var generateElementByHTML = (html) => {
    const elem = document.createElement("div");
    elem.insertAdjacentHTML("beforeend", html);
    return elem.firstElementChild;
  };
  var generateElementByHTML_default = generateElementByHTML;

  // src/utils/filterObject.ts
  var filterObject = (obj) => {
    if (obj !== null && obj !== void 0 && typeof obj === "object" && !Array.isArray(obj)) {
      Object.keys(obj).forEach((key) => {
        if (obj[key] === null || obj[key] === void 0) {
          delete obj[key];
        } else {
          filterObject(obj[key]);
        }
      });
    }
  };
  var filterObject_default = filterObject;

  // src/utils/convertToRoman.ts
  var convertToRoman = (num) => {
    const decimal = [1e3, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
    const romanNumeral = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"];
    let result = "";
    decimal.forEach((val, idx) => {
      while (val <= num) {
        result += romanNumeral[idx];
        num -= val;
      }
    });
    return result || num.toString();
  };
  var convertToRoman_default = convertToRoman;

  // src/utils/fixRomanNum.ts
  var fixRomanNum = (str) => {
    const ronamNum = [null, "\u2170", "\u2171", "\u2172", "\u2173", "\u2174", "\u2175", "\u2176", "\u2177", "\u2178", "\u2179", "\u217A", "\u217B"];
    return str.replace(/[ⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹⅺⅻ]/, (char) => {
      const idx = ronamNum.indexOf(char);
      return idx !== -1 ? convertToRoman_default(Number(idx)).toLowerCase() : char;
    });
  };
  var fixRomanNum_default = fixRomanNum;

  // src/utils/normalizeText.ts
  var normalizeText = (text) => {
    text = text.toLowerCase();
    text = fixRomanNum_default(text);
    text = text.replace(/[-−\(\)()「」「」『』【】[]〈〉《》〔〕{}{}\[\]]/g, " ");
    text = text.replace(/[a-z0-9]/g, (s) => String.fromCharCode(s.charCodeAt(0) - 65248));
    text = text.replace(/./g, (s) => ({
      "\u301C": "~",
      "\uFF1F": "?",
      "\uFF01": "!",
      "\u201D": '"',
      "\u2019": "'",
      "\xB4": "'",
      "\uFF40": "`",
      "\uFF1A": ":",
      "\uFF0C": ",",
      "\uFF0E": ".",
      "\u30FB": "\uFF65",
      "\uFF0F": "/",
      "\uFF03": "#",
      "\uFF04": "$",
      "\uFF05": "%",
      "\uFF06": "&",
      "\uFF1D": "=",
      "\uFF20": "@"
    })[s] || s);
    text = text.replace(/\s+/g, " ").trim();
    return text;
  };
  var normalizeText_default = normalizeText;

  // src/utils/numberToKansuji.ts
  var numberToKansuji = (num) => {
    let result = "";
    if (typeof num === "number" && 0 < num && num < 1e5) {
      const kansujiA = ["", "\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D", "\u4E03", "\u516B", "\u4E5D"];
      const kansujiB = ["", "\u5341", "\u767E", "\u5343", "\u4E07"];
      const numAry = Array.from(num.toString()).map((v) => Number(v));
      numAry.reverse().forEach((n, idx, ary) => {
        if (n === 0) {
          return;
        } else if (idx === 0) {
          result = `${kansujiA[n]}${result}`;
        } else if (n === 1) {
          if (3 <= idx && 5 <= ary.length) {
            result = `${kansujiA[n]}${kansujiB[idx]}${result}`;
          } else {
            result = `${kansujiB[idx]}${result}`;
          }
        } else {
          result = `${kansujiA[n]}${kansujiB[idx]}${result}`;
        }
      });
    }
    return result !== "" ? result : null;
  };
  var numberToKansuji_default = numberToKansuji;

  // src/utils/kansujiToNumber.ts
  var kansujiToNumber = (kansuji) => {
    let result = 0;
    if (typeof kansuji === "string") {
      const kansujiA = ["", "\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D", "\u4E03", "\u516B", "\u4E5D"];
      const kansujiB = ["", "\u5341", "\u767E", "\u5343", "\u4E07"];
      const numberB = [1, 10, 100, 1e3, 1e4];
      let isKansuji = false;
      const kansujiAry = Array.from(kansuji);
      kansujiAry.forEach((char) => {
        isKansuji || (isKansuji = Boolean([...kansujiA, ...kansujiB].find((v) => v === char)));
      });
      if (isKansuji) {
        kansujiAry.forEach((char, idx, ary) => {
          if (char === null) {
            return;
          }
          const idxA = kansujiA.findIndex((v) => v === char);
          const idxB = kansujiB.findIndex((v) => v === char);
          if (idxA !== -1) {
            if (idx + 1 < kansujiAry.length) {
              const nextIdxB = kansujiB.findIndex((v) => v === ary[idx + 1]);
              if (nextIdxB !== -1) {
                result += idxA * numberB[nextIdxB];
                ary[idx + 1] = null;
              }
            } else {
              result += idxA;
            }
          }
          if (idxB !== -1) {
            if (idx + 1 < kansujiAry.length) {
              const nextIdxB = kansujiB.findIndex((v) => v === ary[idx + 1]);
              if (nextIdxB !== -1) {
                result += numberB[idxB] * numberB[nextIdxB];
                ary[idx + 1] = null;
              } else {
                result += numberB[idxB];
              }
            } else {
              result += numberB[idxB];
            }
          }
        });
      }
    }
    return 0 < result ? result : null;
  };
  var kansujiToNumber_default = kansujiToNumber;

  // src/utils/optimizeEpisodeNumberForSearch.ts
  var optimizeEpisodeNumberForSearch = (title) => {
    const splitedTitle = title.split(" ");
    if (splitedTitle.length === 3) {
      const num = Number(splitedTitle[1]);
      if (Number.isFinite(num)) {
        splitedTitle[1] = `${num}\u8A71`;
        title = splitedTitle.join(" ");
      }
    }
    title = title.replace(/第?(\d+|[一二三四五六七八九十百千万]+)話|episode(\d+)|#(\d+)/g, (_, p1, p2, p3) => {
      let num = Number(p1 || p2 || p3);
      if (Number.isNaN(num)) {
        num = kansujiToNumber_default(p1);
      }
      if (num < 10) {
        const zeroPadding = ("00" + num).slice(-2);
        return ` ${num} OR ${zeroPadding} OR ${numberToKansuji_default(num)} `;
      } else {
        return ` ${num} OR ${numberToKansuji_default(num)} `;
      }
    });
    title = title.replace(/\s+/g, " ").trim();
    return title;
  };
  var optimizeEpisodeNumberForSearch_default = optimizeEpisodeNumberForSearch;

  // src/utils/optimizeTitleForSearch.ts
  var optimizeTitleForSearch = (title) => {
    if (typeof title === "string") {
      title = normalizeText_default(title);
      title = optimizeEpisodeNumberForSearch_default(title);
      title = title.replace(/\s+/g, " ").trim();
      return title;
    } else {
      return "";
    }
  };
  var optimizeTitleForSearch_default = optimizeTitleForSearch;

  // src/utils/normalizeEpisodeNumber.ts
  var normalizeEpisodeNumber = (str) => {
    return str.replace(/第?(\d+|[一二三四五六七八九十百千万]+)話|episode(\d+)|#(\d+)|\s(\d+)\s/g, (_, p1, p2, p3, p4) => {
      const num = Number(p1 || p2 || p3 || p4);
      if (Number.isFinite(num)) {
        return num.toString();
      } else {
        return kansujiToNumber_default(p1).toString();
      }
    });
  };
  var normalizeEpisodeNumber_default = normalizeEpisodeNumber;

  // src/utils/isEqualTitle.ts
  var isEqualTitle = (titleA, titleB) => {
    let result = false;
    if (typeof titleA === "string" && titleA !== "" && typeof titleB === "string" && titleB !== "") {
      result = titleA === titleB;
      if (!result) {
        titleA = normalizeText_default(titleA);
        titleA = normalizeEpisodeNumber_default(titleA);
        titleA = titleA.replace(/\s+/g, "").trim();
        titleB = normalizeText_default(titleB);
        titleB = normalizeEpisodeNumber_default(titleB);
        titleB = titleB.replace(/\s+/g, "").trim();
        result = titleA === titleB;
      }
    }
    return result;
  };
  var isEqualTitle_default = isEqualTitle;

  // src/apis/searchVideo.ts
  var searchVideo = async (query) => {
    if (query === void 0) {
      throw new Error("[ECT] ERROR: query is undefined");
    }
    try {
      const requestQuery = {
        q: query.q,
        targets: query.targets.join(),
        fields: query.fields?.join() || ["contentId", "title", "channelId", "lengthSeconds", "tags"].join(),
        _sort: query._sort || "+startTime",
        _offset: query._offset,
        _limit: query._limit || "5",
        _context: "ect"
      };
      if (query.filters !== void 0) {
        Object.entries(query.filters).forEach((val) => {
          if (Array.isArray(val[1]) && val[1].length === 2) {
            requestQuery[`filters[${val[0]}][gte]`] = val[1][0];
            requestQuery[`filters[${val[0]}][lte]`] = val[1][1];
          } else {
            requestQuery[`filters[${val[0]}][0]`] = val[1];
          }
        });
      }
      filterObject_default(requestQuery);
      const res = await FetchAPI(`${SEARCH_V2_API}?${new URLSearchParams(requestQuery)}`, {
        method: "GET",
        headers: {
          "User-Agent": "ECT/1.0"
        }
      });
      if (res.ok) {
        let json;
        if (res instanceof Response) {
          json = await res.json();
        } else {
          json = res.json;
        }
        if (json?.data !== void 0) {
          return json.data;
        }
      }
    } catch (e) {
      throw new Error(e);
    }
    throw new Error("[ECT] ERROR: search");
  };
  var searchVideo_default = searchVideo;

  // ../../UserScript/Library/MidConfig/src/types.ts
  var isConfigItemData = (data) => {
    if (data != null && typeof data === "object" && !Array.isArray(data)) {
      return Object.keys(data).length === 3 && data.hasOwnProperty("checked") && data.hasOwnProperty("value") && data.hasOwnProperty("default");
    }
    return false;
  };
  var isConfigJsonData = (data) => {
    if (data != null && typeof data === "object" && !Array.isArray(data)) {
      return Object.keys(data).length === 2 && data.hasOwnProperty("version") && data.hasOwnProperty("data");
    }
    return false;
  };

  // ../../UserScript/Library/MidConfig/src/constants.ts
  var SVG_CHECKMARK = '<svg class="midconfig-svg-checkmark" width="16" height="16" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M9.86 17.997a1.002 1.002 0 0 1-.73-.32l-4.86-5.17a1.001 1.001 0 0 1 1.46-1.37l4.12 4.39 8.41-9.2a1 1 0 1 1 1.48 1.34l-9.14 10a1.002 1.002 0 0 1-.73.33h-.01Z"></path></svg>';
  var SVG_ARROW_DOWN = '<svg class="midconfig-svg-arrow-down" width="30" height="30" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 16.001a1 1 0 0 1-.64-.23l-6-5a1.001 1.001 0 0 1 1.28-1.54l5.36 4.48 5.36-4.32a1 1 0 0 1 1.41.15 1 1 0 0 1-.14 1.46l-6 4.83a1 1 0 0 1-.63.17Z"></path></svg>';
  var STYLE2 = '#midconfig{display:flex;flex-direction:column;flex-wrap:nowrap;justify-content:space-between;width:100%;height:100%;border-radius:10px;background-color:var(--back1);border:1px solid var(--text3);box-shadow:1px 1px 10px -2px var(--text3);overflow:hidden}#midconfig{--accent1: #2389ff;--accent2: #238aff26;--accent-text: #fff;--back1: #fff;--text1: #3c3c3c;--text2: #8a8a8a;--text3: #e0e0e0;--red1: #ff3456;--red2: #ff345626}#midconfig[theme=dark]{--accent1: #298cff;--accent2: #298cff36;--accent-text: #fff;--back1: #333;--text1: #f1f1f1;--text2: #a0a0a0;--text3: #505050}@media(prefers-color-scheme: dark){#midconfig[theme=auto]{--accent1: #298cff;--accent2: #298cff36;--accent-text: #fff;--back1: #333;--text1: #f1f1f1;--text2: #a0a0a0;--text3: #505050}}#midconfig #midconfig,#midconfig *,#midconfig ::after,#midconfig ::before{transition:150ms ease-in-out}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container>input[type=text],#midconfig .midconfig-select-container>select{padding:0 10px;border:1px solid var(--text3);border-radius:8px;background-color:rgba(0,0,0,0)}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-label-container>label>span,#midconfig .midconfig-main>.midconfig-page-item .midconfig-group>.midconfig-group-header>span,#midconfig .midconfig-tab>.midconfig-tab-item,#midconfig .midconfig-button,#midconfig .midconfig-select-container>select{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}#midconfig ::-webkit-scrollbar{width:7px}#midconfig ::-webkit-scrollbar-track{background-color:rgba(0,0,0,0);margin:1px 0}#midconfig ::-webkit-scrollbar-thumb{background-color:var(--text2);border-radius:3px;border-right:1px solid rgba(0,0,0,0);border-left:1px solid rgba(0,0,0,0);background-clip:padding-box}#midconfig *{scrollbar-width:thin;scrollbar-color:var(--text2) rgba(0,0,0,0)}#midconfig,#midconfig *,#midconfig ::after,#midconfig ::before{margin:0;padding:0;box-sizing:border-box;font-family:-apple-system,sans-serif;font-size:14px;font-weight:400;color:var(--text1)}#midconfig :not(input){-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#midconfig svg{display:inline-block;fill:var(--text2);pointer-events:none}#midconfig input{-webkit-appearance:none;-moz-appearance:none;appearance:none}#midconfig input[type=checkbox]{display:none}#midconfig input[type=checkbox]+label{cursor:pointer}#midconfig input[type=checkbox]+label>svg.midconfig-svg-checkmark{width:16px;height:16px;min-width:16px;min-height:16px;margin:2px;border:2px solid var(--text3);border-radius:4px;fill:rgba(0,0,0,0);transition-property:background-color,border}#midconfig input[type=checkbox]:checked+label>svg.midconfig-svg-checkmark{background-color:var(--accent1);border:none;fill:var(--accent-text)}#midconfig .midconfig-select-container{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;position:relative}#midconfig .midconfig-select-container>select{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:100%}#midconfig .midconfig-select-container>select:focus{outline:none}#midconfig .midconfig-select-container>svg.midconfig-svg-arrow-down{position:absolute;top:3px;right:3px;width:24px;height:24px;min-width:24px;min-height:24px}#midconfig .midconfig-button-container{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;width:100%}#midconfig .midconfig-button-container__disable>.midconfig-button,#midconfig .midconfig-button-container.midconfig-button-empty>.midconfig-button{opacity:.25;pointer-events:none}#midconfig .midconfig-button{display:inline-block;width:inherit;height:30px;line-height:30px;text-align:center;background-color:var(--back1);border-radius:8px;cursor:pointer}#midconfig .midconfig-button:hover{filter:opacity(0.7)}#midconfig .midconfig-button:hover:active{filter:opacity(0.5)}#midconfig .midconfig-button--solid{color:var(--accent1)}#midconfig .midconfig-button--outline{line-height:28px;color:var(--accent1);border:1px solid var(--accent1)}#midconfig .midconfig-button--outline:hover{color:var(--accent-text);background-color:var(--accent1);filter:none}#midconfig .midconfig-button--outline:hover:active{filter:opacity(0.7)}#midconfig .midconfig-button--fill-alpha{color:var(--accent1);background-color:var(--accent2)}#midconfig .midconfig-button--fill{color:var(--accent-text);background-color:var(--accent1)}#midconfig .midconfig-button--solid-red{color:var(--red1)}#midconfig .midconfig-button--outline-red{line-height:28px;color:var(--red1);border:1px solid var(--red1)}#midconfig .midconfig-button--outline-red:hover{color:#fff;background-color:var(--red1);filter:none}#midconfig .midconfig-button--outline-red:hover:active{filter:opacity(0.7)}#midconfig .midconfig-button--fill-alpha-red{color:var(--red1);background-color:var(--red2)}#midconfig .midconfig-button--fill-red{color:#fff;background-color:var(--red1)}#midconfig>*{width:100%}#midconfig .midconfig-tab{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;gap:5px;padding:5px 5px 0;border-bottom:1px solid var(--text3)}#midconfig .midconfig-tab>.midconfig-tab-item{display:inline-block;width:inherit;height:30px;line-height:30px;padding:0 0 5px;text-align:center;color:var(--text2);cursor:pointer;box-sizing:content-box}#midconfig .midconfig-tab>.midconfig-tab-item::after{content:"";display:block;position:relative;top:1px;width:100%;height:4px;background-color:var(--accent1);border-radius:2px;opacity:0}#midconfig .midconfig-tab>.midconfig-tab-item__selected{font-weight:600;color:var(--accent1)}#midconfig .midconfig-tab>.midconfig-tab-item__selected::after{opacity:1}#midconfig .midconfig-main{height:100%;padding:10px 8px 10px 10px;overflow-y:scroll}#midconfig .midconfig-main>.midconfig-page-item{display:none}#midconfig .midconfig-main>.midconfig-page-item__selected{display:flex;flex-direction:column;flex-wrap:nowrap;gap:5px}#midconfig .midconfig-main>.midconfig-page-item .midconfig-group>.midconfig-group-header{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;justify-content:space-between;height:30px}#midconfig .midconfig-main>.midconfig-page-item .midconfig-group>.midconfig-group-header>svg.midconfig-svg-arrow-down{width:30px;height:inherit;max-width:30px;max-height:30px;min-width:30px;min-height:30px;transform:scale(-1, -1)}#midconfig .midconfig-main>.midconfig-page-item .midconfig-group>.midconfig-group-items{display:flex;flex-direction:column;flex-wrap:nowrap;gap:5px}#midconfig .midconfig-main>.midconfig-page-item .midconfig-group>.midconfig-group-items>.midconfig-item>.midconfig-label-container{padding-left:15px}#midconfig .midconfig-main>.midconfig-page-item .midconfig-group.midconfig-accordion>.midconfig-group-header{cursor:pointer}#midconfig .midconfig-main>.midconfig-page-item .midconfig-group.midconfig-accordion__close>.midconfig-group-header>svg.midconfig-svg-arrow-down{transform:scale(1, 1)}#midconfig .midconfig-main>.midconfig-page-item .midconfig-group.midconfig-accordion__close>.midconfig-group-items{display:none}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:5px;height:30px;overflow:hidden}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item:not(.midconfig-item-checkbox)>*{width:50%;overflow:hidden}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>*{width:100%;height:inherit}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>*>*{width:100%;height:inherit}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-label-container>label{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;gap:5px}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;gap:5px}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container>input[type=text]:focus{outline:none;border-color:var(--accent1)}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container>input[type=color]{width:30px;height:30px;min-width:30px;min-height:30px;border:none;border-radius:50%;overflow:hidden;cursor:pointer}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container>input[type=color]::-webkit-color-swatch-wrapper{padding:0}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container>input[type=color]::-moz-color-swatch-wrapper{padding:0}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container>input[type=color]::-webkit-color-swatch{border:1px solid var(--text3);border-radius:50%}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container>input[type=color]::-moz-color-swatch{border:1px solid var(--text3);border-radius:50%}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container>input[type=range]{width:65%;height:6px;background:linear-gradient(90deg, var(--accent1) var(--range-progress, 0), var(--text3) var(--range-progress, 0));border-radius:3px;transition:none}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container>input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:12px;height:12px;background-color:var(--accent1);border-radius:6px;border:none;cursor:ew-resize}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container>input[type=range]::-moz-range-thumb{-moz-appearance:none;appearance:none;width:12px;height:12px;background-color:var(--accent1);border-radius:6px;border:none;cursor:ew-resize}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item>.midconfig-input-container>input[type=range]+input[type=text]{width:35%;padding:0;text-align:center}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item.midconfig-button-container>.midconfig-label-container{width:100%}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item.midconfig-button-container>.midconfig-button{max-width:120px;min-width:90px}#midconfig .midconfig-main>.midconfig-page-item .midconfig-item__disable>.midconfig-input-container{opacity:.25;pointer-events:none}#midconfig .midconfig-main>.midconfig-page-item .midconfig-divider{display:block;width:100%;height:1px;background-color:var(--text3);margin:2px 0}#midconfig .midconfig-bottom{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;gap:5px;padding:5px;border-top:1px solid var(--text3)}';

  // ../../UserScript/Library/MidConfig/src/Items/index.ts
  var Items_exports = {};
  __export(Items_exports, {
    Button: () => Button_default,
    ButtonEmpty: () => ButtonEmpty_default,
    CheckBox: () => CheckBox_default,
    Color: () => Color_default,
    Divider: () => Divider_default,
    Group: () => Group_default,
    Item: () => Item_default,
    Range: () => Range_default,
    Select: () => Select_default,
    Text: () => Text_default
  });

  // ../../UserScript/Library/MidConfig/src/utils/generateUID.ts
  var generateUID2 = (len = 10) => {
    const str = `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`;
    return `${Array.from(Array(len)).map(() => str[Math.random() * str.length | 0]).join("")}-${Date.now()}`;
  };
  var generateUID_default = generateUID2;

  // ../../UserScript/Library/MidConfig/src/utils/fullWidthToHalfWidth.ts
  var fullWidthToHalfWidth = (str) => {
    return str.replace("\uFF03", "#").replace(/[a-z0-9]/g, (s) => String.fromCharCode(s.charCodeAt(0) - 65248));
  };
  var fullWidthToHalfWidth_default = fullWidthToHalfWidth;

  // ../../UserScript/Library/MidConfig/src/utils/setTextWithTitle.ts
  var setTextWithTitle = (elem, text) => {
    elem.textContent = text;
    elem.addEventListener("mouseover", ({ target }) => {
      if (target instanceof HTMLElement) {
        if (0 < target.scrollWidth - target.offsetWidth) {
          target.title = target.textContent || "";
        } else {
          target.title = "";
        }
      }
    });
  };
  var setTextWithTitle_default = setTextWithTitle;

  // ../../UserScript/Library/MidConfig/src/utils/isColorCode.ts
  var isColorCode = (hex) => {
    return /^#?[a-fA-F0-9]{6}$/.test(hex);
  };
  var isColorCode_default = isColorCode;

  // ../../UserScript/Library/MidConfig/src/utils/defineCustomElement.ts
  var defineCustomElement = (name, constructor) => {
    if (customElements.constructor.prototype.get.call(customElements, "midconfig-panel") === void 0) {
      customElements.constructor.prototype.define.call(customElements, name, constructor);
    }
  };
  var defineCustomElement_default = defineCustomElement;

  // ../../UserScript/Library/MidConfig/src/Items/Item.ts
  var _initData, _uid, _value, _labalContainer, _inputContainer, _inputCheckbox;
  var _Item = class extends HTMLElement {
    constructor(initData) {
      super();
      __privateAdd(this, _initData, void 0);
      __privateAdd(this, _uid, void 0);
      __privateAdd(this, _value, void 0);
      __privateAdd(this, _labalContainer, void 0);
      __privateAdd(this, _inputContainer, void 0);
      __privateAdd(this, _inputCheckbox, null);
      __privateSet(this, _initData, initData);
      __privateSet(this, _uid, `midconfig-${generateUID_default()}`);
      __privateSet(this, _value, initData.default);
      this.classList.add(_Item.NAME);
      this.classList.add(this.tagName.toLowerCase());
      __privateSet(this, _labalContainer, document.createElement("div"));
      __privateGet(this, _labalContainer).classList.add("midconfig-label-container");
      const label = document.createElement("label");
      const span = document.createElement("span");
      setTextWithTitle_default(span, initData.label);
      label.appendChild(span);
      __privateGet(this, _labalContainer).insertAdjacentElement("beforeend", label);
      if (initData.withCheckBox === true) {
        label.setAttribute("for", __privateGet(this, _uid));
        label.insertAdjacentHTML("afterbegin", SVG_CHECKMARK);
        __privateSet(this, _inputCheckbox, document.createElement("input"));
        __privateGet(this, _inputCheckbox).type = "checkbox";
        __privateGet(this, _inputCheckbox).id = __privateGet(this, _uid);
        __privateGet(this, _inputCheckbox).checked = Boolean(initData.checked);
        if (!this.checked) {
          this.classList.add(`${_Item.NAME}__disable`);
        }
        __privateGet(this, _inputCheckbox).addEventListener("change", () => {
          if (this.checked) {
            this.classList.remove(`${_Item.NAME}__disable`);
          } else {
            this.classList.add(`${_Item.NAME}__disable`);
          }
          if (typeof __privateGet(this, _initData).onChange === "function") {
            __privateGet(this, _initData).onChange({
              target: this,
              id: __privateGet(this, _initData).id,
              value: null,
              checked: this.checked
            });
          }
        });
        __privateGet(this, _labalContainer).insertAdjacentElement("afterbegin", __privateGet(this, _inputCheckbox));
      }
      __privateSet(this, _inputContainer, document.createElement("div"));
      __privateGet(this, _inputContainer).classList.add("midconfig-input-container");
      this.appendChild(__privateGet(this, _labalContainer));
      this.appendChild(__privateGet(this, _inputContainer));
    }
    get initData() {
      return __privateGet(this, _initData);
    }
    get uid() {
      return __privateGet(this, _uid);
    }
    get value() {
      return __privateGet(this, _value);
    }
    get checked() {
      if (__privateGet(this, _inputCheckbox) !== null) {
        return __privateGet(this, _inputCheckbox).checked;
      } else {
        return null;
      }
    }
    get labalContainer() {
      return __privateGet(this, _labalContainer);
    }
    get inputContainer() {
      return __privateGet(this, _inputContainer);
    }
    get inputCheckbox() {
      return __privateGet(this, _inputCheckbox);
    }
    set checked(data) {
      if (typeof data === "boolean" && __privateGet(this, _inputCheckbox) !== null) {
        if (data === __privateGet(this, _inputCheckbox).checked) {
          return;
        }
        __privateGet(this, _inputCheckbox).checked = data;
        if (this.checked) {
          this.classList.remove(`${_Item.NAME}__disable`);
        } else {
          this.classList.add(`${_Item.NAME}__disable`);
        }
        if (typeof __privateGet(this, _initData).onChange === "function") {
          __privateGet(this, _initData).onChange({
            target: this,
            id: __privateGet(this, _initData).id,
            value: null,
            checked: this.checked
          });
        }
      }
    }
    set _value(data) {
      if (typeof data === "string" || typeof data === "number" || typeof data === "boolean") {
        if (data === __privateGet(this, _value)) {
          return;
        }
        __privateSet(this, _value, data);
        if (typeof __privateGet(this, _initData).onChange === "function") {
          __privateGet(this, _initData).onChange({
            target: this,
            id: __privateGet(this, _initData).id,
            value: __privateGet(this, _value),
            checked: this.checked
          });
        }
      }
    }
    getValue() {
      return this.value;
    }
    setValue(data) {
      if (typeof data === "string" || typeof data === "number" || typeof data === "boolean") {
        this._value = data;
      }
    }
    getData() {
      return {
        checked: this.checked,
        value: this.value,
        default: __privateGet(this, _initData).default
      };
    }
    setData(data) {
      this.setValue(data.value);
      this.checked = data.checked;
    }
    reset() {
      this.setValue(__privateGet(this, _initData).default);
      this.checked = Boolean(__privateGet(this, _initData).checked);
    }
  };
  var Item = _Item;
  _initData = new WeakMap();
  _uid = new WeakMap();
  _value = new WeakMap();
  _labalContainer = new WeakMap();
  _inputContainer = new WeakMap();
  _inputCheckbox = new WeakMap();
  Item.NAME = "midconfig-item";
  defineCustomElement_default(Item.NAME, Item);
  var Item_default = Item;

  // ../../UserScript/Library/MidConfig/src/Items/Text.ts
  var _inputText;
  var Text = class extends Item_default {
    constructor(initData, option) {
      super(initData);
      __privateAdd(this, _inputText, void 0);
      __privateSet(this, _inputText, document.createElement("input"));
      __privateGet(this, _inputText).type = "text";
      __privateGet(this, _inputText).value = initData.default;
      __privateGet(this, _inputText).spellcheck = false;
      __privateGet(this, _inputText).setAttribute("autocorrect", "off");
      if (typeof option?.maxlength === "number") {
        __privateGet(this, _inputText).maxLength = option.maxlength;
      }
      if (typeof option?.minlength === "number") {
        __privateGet(this, _inputText).minLength = option.minlength;
      }
      if (typeof option?.placeholder === "string") {
        __privateGet(this, _inputText).placeholder = option.placeholder;
      } else {
        __privateGet(this, _inputText).placeholder = initData.default;
      }
      __privateGet(this, _inputText).addEventListener("change", () => {
        this.setValue(__privateGet(this, _inputText).value);
      });
      this.inputContainer.appendChild(__privateGet(this, _inputText));
    }
    setValue(data) {
      if (typeof data === "number") {
        data = data.toString();
      }
      if (typeof data === "string") {
        data = data.trim();
        __privateGet(this, _inputText).value = data;
        this._value = data;
      }
    }
  };
  _inputText = new WeakMap();
  defineCustomElement_default("midconfig-item-text", Text);
  var Text_default = Text;

  // ../../UserScript/Library/MidConfig/src/Items/CheckBox.ts
  var CheckBox = class extends Item_default {
    constructor(initData) {
      initData.withCheckBox = true;
      initData.checked || (initData.checked = initData.default);
      super(initData);
      this.inputContainer.remove();
    }
    get value() {
      return Boolean(this.inputCheckbox?.checked);
    }
    setValue(data) {
      if (typeof data === "boolean" && this.inputCheckbox !== null) {
        this.inputCheckbox.checked = data;
        this._value = data;
      }
    }
  };
  defineCustomElement_default("midconfig-item-checkbox", CheckBox);
  var CheckBox_default = CheckBox;

  // ../../UserScript/Library/MidConfig/src/Items/Color.ts
  var _inputColor, _inputText2;
  var Color = class extends Item_default {
    constructor(initData, option) {
      super(initData);
      __privateAdd(this, _inputColor, void 0);
      __privateAdd(this, _inputText2, void 0);
      initData.default = initData.default.toUpperCase();
      __privateSet(this, _inputColor, document.createElement("input"));
      __privateGet(this, _inputColor).type = "color";
      __privateGet(this, _inputColor).value = initData.default;
      __privateSet(this, _inputText2, document.createElement("input"));
      __privateGet(this, _inputText2).type = "text";
      __privateGet(this, _inputText2).value = initData.default;
      __privateGet(this, _inputText2).spellcheck = false;
      __privateGet(this, _inputText2).setAttribute("autocorrect", "off");
      __privateGet(this, _inputText2).maxLength = 7;
      __privateGet(this, _inputText2).minLength = 6;
      if (typeof option?.placeholder === "string") {
        __privateGet(this, _inputText2).placeholder = option.placeholder;
      } else {
        __privateGet(this, _inputText2).placeholder = initData.default;
      }
      const changeHandler = ({ target }) => {
        if (target instanceof HTMLInputElement) {
          if (target.value === "") {
            target.value = this.initData.default;
          }
          target.value = fullWidthToHalfWidth_default(target.value);
          this.setValue(target.value);
        }
      };
      __privateGet(this, _inputColor).addEventListener("change", changeHandler);
      __privateGet(this, _inputText2).addEventListener("change", changeHandler);
      this.inputContainer.appendChild(__privateGet(this, _inputColor));
      this.inputContainer.appendChild(__privateGet(this, _inputText2));
    }
    setValue(data) {
      if (typeof data === "string") {
        data = data.trim().toUpperCase();
        if (!isColorCode_default(data)) {
          data = this.initData.default;
        }
        if (!data.startsWith("#")) {
          data = `#${data}`;
        }
        __privateGet(this, _inputColor).value = data;
        __privateGet(this, _inputText2).value = data;
        this._value = data;
      }
    }
  };
  _inputColor = new WeakMap();
  _inputText2 = new WeakMap();
  defineCustomElement_default("midconfig-item-color", Color);
  var Color_default = Color;

  // ../../UserScript/Library/MidConfig/src/Items/Range.ts
  var _inputRange, _inputText3;
  var Range = class extends Item_default {
    constructor(initData, option) {
      super(initData);
      __privateAdd(this, _inputRange, void 0);
      __privateAdd(this, _inputText3, void 0);
      __privateSet(this, _inputRange, document.createElement("input"));
      __privateGet(this, _inputRange).type = "range";
      __privateGet(this, _inputRange).value = initData.default.toString();
      __privateGet(this, _inputRange).max = option.max.toString();
      __privateGet(this, _inputRange).min = option.min.toString();
      __privateGet(this, _inputRange).step = option.step.toString();
      __privateGet(this, _inputRange).style.setProperty(
        "--range-progress",
        `${(initData.default - option.min) / (option.max - option.min) * 100}%`
      );
      __privateSet(this, _inputText3, document.createElement("input"));
      __privateGet(this, _inputText3).type = "text";
      __privateGet(this, _inputText3).value = initData.default.toString();
      __privateGet(this, _inputText3).spellcheck = false;
      __privateGet(this, _inputText3).setAttribute("autocorrect", "off");
      __privateGet(this, _inputText3).maxLength = (option.max + option.step).toString().length;
      if (typeof option.placeholder === "string") {
        __privateGet(this, _inputText3).placeholder = option.placeholder;
      } else {
        __privateGet(this, _inputText3).placeholder = initData.default.toString();
      }
      __privateGet(this, _inputRange).addEventListener("input", () => {
        __privateGet(this, _inputRange).style.setProperty(
          "--range-progress",
          `${(Number(__privateGet(this, _inputRange).value) - Number(__privateGet(this, _inputRange).min)) / (Number(__privateGet(this, _inputRange).max) - Number(__privateGet(this, _inputRange).min)) * 100}%`
        );
        __privateGet(this, _inputText3).value = __privateGet(this, _inputRange).value;
      });
      const changeHandler = ({ target }) => {
        if (target instanceof HTMLInputElement) {
          if (target.value === "") {
            target.value = this.initData.default;
          }
          target.value = fullWidthToHalfWidth_default(target.value);
          this.setValue(target.value);
        }
      };
      __privateGet(this, _inputRange).addEventListener("change", changeHandler);
      __privateGet(this, _inputText3).addEventListener("change", changeHandler);
      this.inputContainer.appendChild(__privateGet(this, _inputRange));
      this.inputContainer.appendChild(__privateGet(this, _inputText3));
    }
    setValue(data) {
      if (typeof data === "string") {
        data = Number(data);
      }
      if (Number.isNaN(data)) {
        data = this.initData.default;
      }
      if (typeof data === "number" && data <= Number(__privateGet(this, _inputRange).max) && Number(__privateGet(this, _inputRange).min) <= data) {
        __privateGet(this, _inputRange).value = data.toString();
        __privateGet(this, _inputText3).value = data.toString();
        __privateGet(this, _inputRange).style.setProperty(
          "--range-progress",
          `${(Number(__privateGet(this, _inputRange).value) - Number(__privateGet(this, _inputRange).min)) / (Number(__privateGet(this, _inputRange).max) - Number(__privateGet(this, _inputRange).min)) * 100}%`
        );
        this._value = data;
      }
    }
  };
  _inputRange = new WeakMap();
  _inputText3 = new WeakMap();
  defineCustomElement_default("midconfig-item-range", Range);
  var Range_default = Range;

  // ../../UserScript/Library/MidConfig/src/Items/Select.ts
  var _select, _options;
  var Select = class extends Item_default {
    constructor(initData, options) {
      super(initData);
      __privateAdd(this, _select, void 0);
      __privateAdd(this, _options, []);
      const selectContainer = document.createElement("div");
      selectContainer.classList.add("midconfig-select-container");
      __privateSet(this, _select, document.createElement("select"));
      for (const { text, value } of options) {
        const option = document.createElement("option");
        option.text = text;
        option.value = value;
        if (value === initData.default) {
          option.selected = true;
        }
        __privateGet(this, _select).appendChild(option);
        __privateGet(this, _options).push(option);
      }
      __privateGet(this, _select).addEventListener("change", () => {
        this.setValue(__privateGet(this, _select).value);
      });
      selectContainer.appendChild(__privateGet(this, _select));
      selectContainer.insertAdjacentHTML("beforeend", SVG_ARROW_DOWN);
      this.inputContainer.appendChild(selectContainer);
    }
    setValue(data) {
      if (typeof data === "string") {
        data = data.trim();
        const targetOption = __privateGet(this, _options).find((v) => v.value === data);
        if (targetOption !== void 0) {
          targetOption.selected = true;
          this._value = data;
        }
      }
    }
  };
  _select = new WeakMap();
  _options = new WeakMap();
  defineCustomElement_default("midconfig-item-select", Select);
  var Select_default = Select;

  // ../../UserScript/Library/MidConfig/src/Items/Button.ts
  var _initData2, _disable, _labalContainer2;
  var _Button = class extends HTMLElement {
    constructor(initData) {
      super();
      __privateAdd(this, _initData2, void 0);
      __privateAdd(this, _disable, void 0);
      __privateAdd(this, _labalContainer2, null);
      __privateSet(this, _initData2, initData);
      this.disable = Boolean(initData.disable);
      this.classList.add("midconfig-item");
      this.classList.add(this.tagName.toLowerCase());
      if (typeof initData.label === "string") {
        __privateSet(this, _labalContainer2, document.createElement("div"));
        __privateGet(this, _labalContainer2).classList.add("midconfig-label-container");
        const label = document.createElement("label");
        const span = document.createElement("span");
        setTextWithTitle_default(span, initData.label);
        label.appendChild(span);
        __privateGet(this, _labalContainer2).appendChild(label);
        this.appendChild(__privateGet(this, _labalContainer2));
      }
      const button = document.createElement("div");
      button.classList.add("midconfig-button");
      button.classList.add(`midconfig-button--${initData.type}`);
      setTextWithTitle_default(button, initData.text);
      button.addEventListener("click", async () => {
        await __privateGet(this, _initData2).onClick(__privateGet(this, _initData2).id);
      });
      this.appendChild(button);
    }
    get initData() {
      return __privateGet(this, _initData2);
    }
    get disable() {
      return __privateGet(this, _disable);
    }
    get labalContainer() {
      return __privateGet(this, _labalContainer2);
    }
    set disable(v) {
      __privateSet(this, _disable, Boolean(v));
      if (__privateGet(this, _disable)) {
        this.classList.add(`${_Button.NAME}__disable`);
      } else {
        this.classList.remove(`${_Button.NAME}__disable`);
      }
    }
  };
  var Button = _Button;
  _initData2 = new WeakMap();
  _disable = new WeakMap();
  _labalContainer2 = new WeakMap();
  Button.NAME = "midconfig-button-container";
  defineCustomElement_default(Button.NAME, Button);
  var Button_default = Button;

  // ../../UserScript/Library/MidConfig/src/Items/ButtonEmpty.ts
  var ButtonEmpty = class extends Button_default {
    constructor() {
      super({
        id: "",
        text: "",
        type: "solid",
        onClick: () => null
      });
      this.classList.add("midconfig-button-container");
    }
  };
  ButtonEmpty.NAME = "midconfig-button-empty";
  defineCustomElement_default(ButtonEmpty.NAME, ButtonEmpty);
  var ButtonEmpty_default = ButtonEmpty;

  // ../../UserScript/Library/MidConfig/src/Items/Divider.ts
  var Divider = class extends HTMLElement {
    constructor() {
      super();
      this.classList.add(this.tagName.toLowerCase());
    }
  };
  Divider.NAME = "midconfig-divider";
  defineCustomElement_default(Divider.NAME, Divider);
  var Divider_default = Divider;

  // ../../UserScript/Library/MidConfig/src/Items/Group.ts
  var _initData3, _isOpen;
  var _Group = class extends HTMLElement {
    constructor(initData) {
      super();
      __privateAdd(this, _initData3, void 0);
      __privateAdd(this, _isOpen, void 0);
      __privateSet(this, _initData3, initData);
      __privateSet(this, _isOpen, Boolean(initData.isAccordionOpen));
      this.classList.add(_Group.NAME);
      const header = document.createElement("div");
      header.classList.add(`${_Group.NAME}-header`);
      const span = document.createElement("span");
      setTextWithTitle_default(span, initData.label);
      header.appendChild(span);
      const items = document.createElement("div");
      items.classList.add(`${_Group.NAME}-items`);
      for (const item of initData.items) {
        items.appendChild(item);
      }
      if (initData.isAccordion) {
        this.classList.add("midconfig-accordion");
        if (!__privateGet(this, _isOpen)) {
          this.classList.add("midconfig-accordion__close");
        }
        header.insertAdjacentHTML("beforeend", SVG_ARROW_DOWN);
        header.addEventListener("click", () => __privateGet(this, _isOpen) ? this.close() : this.open());
      }
      this.appendChild(header);
      this.appendChild(items);
    }
    get initData() {
      return __privateGet(this, _initData3);
    }
    get isOpen() {
      return __privateGet(this, _isOpen);
    }
    open() {
      __privateSet(this, _isOpen, true);
      this.classList.remove("midconfig-accordion__close");
    }
    close() {
      __privateSet(this, _isOpen, false);
      this.classList.add("midconfig-accordion__close");
    }
    getData() {
      const data = {};
      __privateGet(this, _initData3).items.forEach((item) => {
        if (item instanceof Item_default) {
          data[item.initData.id] = item.getData();
        }
      });
      return data;
    }
    setData(values) {
      Object.keys(values).forEach((id) => {
        __privateGet(this, _initData3).items.forEach((item) => {
          if (item instanceof Item_default && item.initData.id === id) {
            item.setData(values[id]);
          }
        });
      });
    }
    reset() {
      __privateGet(this, _initData3).items.forEach((v) => v instanceof Item_default && v.reset());
    }
  };
  var Group = _Group;
  _initData3 = new WeakMap();
  _isOpen = new WeakMap();
  Group.NAME = "midconfig-group";
  defineCustomElement_default(Group.NAME, Group);
  var Group_default = Group;

  // ../../UserScript/Library/MidConfig/src/index.ts
  var _initData4, _shadowInner, _tab, _main, _bottom;
  var _Panel = class extends HTMLElement {
    constructor(initData, isDev) {
      super();
      __privateAdd(this, _initData4, void 0);
      __privateAdd(this, _shadowInner, null);
      __privateAdd(this, _tab, void 0);
      __privateAdd(this, _main, void 0);
      __privateAdd(this, _bottom, void 0);
      __privateSet(this, _initData4, initData);
      this.classList.add(_Panel.NAME);
      __privateSet(this, _tab, document.createElement("div"));
      __privateGet(this, _tab).classList.add("midconfig-tab");
      __privateSet(this, _main, document.createElement("div"));
      __privateGet(this, _main).classList.add("midconfig-main");
      __privateSet(this, _bottom, document.createElement("div"));
      __privateGet(this, _bottom).classList.add("midconfig-bottom");
      initData.tabs.forEach((tab, idx) => {
        const tabItem = document.createElement("div");
        tabItem.classList.add("midconfig-tab-item");
        setTextWithTitle_default(tabItem, tab.label);
        const pageItem = document.createElement("div");
        pageItem.classList.add("midconfig-page-item");
        tab.child.forEach((item) => pageItem.appendChild(item));
        if (idx === 0) {
          tabItem.classList.add("midconfig-tab-item__selected");
          pageItem.classList.add("midconfig-page-item__selected");
        }
        tabItem.addEventListener("click", () => {
          Array.from(__privateGet(this, _tab).children).forEach((item) => {
            item.classList.remove("midconfig-tab-item__selected");
          });
          tabItem.classList.add("midconfig-tab-item__selected");
          Array.from(__privateGet(this, _main).children).forEach((page) => {
            page.classList.remove("midconfig-page-item__selected");
          });
          pageItem.classList.add("midconfig-page-item__selected");
        });
        __privateGet(this, _tab).appendChild(tabItem);
        __privateGet(this, _main).appendChild(pageItem);
      });
      initData.buttons.forEach((button) => {
        delete button.initData.label;
        button.labalContainer?.remove();
        __privateGet(this, _bottom).appendChild(button);
      });
      if (!Boolean(isDev)) {
        __privateSet(this, _shadowInner, document.createElement("div"));
        __privateGet(this, _shadowInner).id = "midconfig";
        __privateGet(this, _shadowInner).appendChild(__privateGet(this, _tab));
        __privateGet(this, _shadowInner).appendChild(__privateGet(this, _main));
        __privateGet(this, _shadowInner).appendChild(__privateGet(this, _bottom));
        const shadow = this.attachShadow({ mode: "closed" });
        shadow.appendChild(__privateGet(this, _shadowInner));
        const style = document.createElement("style");
        style.textContent = STYLE2;
        shadow.appendChild(style);
      } else {
        this.id = "midconfig";
        this.appendChild(__privateGet(this, _tab));
        this.appendChild(__privateGet(this, _main));
        this.appendChild(__privateGet(this, _bottom));
        _Panel.addStyle(STYLE2);
      }
      this.style.display = isDev ? "flex" : "block";
      this.setTheme(initData.theme);
    }
    get initData() {
      return __privateGet(this, _initData4);
    }
    get key() {
      return `midconfig-${__privateGet(this, _initData4).id}`;
    }
    async init() {
      await this.load();
    }
    getValue(key, json) {
      let result = void 0;
      const parsedKey = key.split(">").map((v) => v.trim());
      if (parsedKey.length < 2 || 3 < parsedKey.length) {
        return;
      }
      const data = isConfigJsonData(json) ? json.data : this.getJSON().data;
      Object.keys(data).forEach((tabId) => {
        if (tabId !== parsedKey[0]) {
          return;
        }
        const tab = data[tabId];
        Object.keys(tab).forEach((itemId) => {
          if (itemId !== parsedKey[1]) {
            return;
          }
          const item = tab[itemId];
          if (isConfigItemData(item)) {
            result = item;
          } else {
            Object.keys(item).forEach((id) => {
              if (id !== parsedKey[2]) {
                return;
              }
              const groupItem = item[id];
              if (isConfigItemData(groupItem)) {
                result = groupItem;
              }
            });
          }
        });
      });
      return result;
    }
    getJSON() {
      const json = {
        version: __privateGet(this, _initData4).version,
        data: {}
      };
      __privateGet(this, _initData4).tabs.forEach((tab) => {
        var _a, _b;
        (_a = json.data)[_b = tab.id] || (_a[_b] = {});
        tab.child.forEach((item) => {
          if (item instanceof Item_default || item instanceof Group_default) {
            json.data[tab.id][item.initData.id] = item.getData();
          }
        });
      });
      return json;
    }
    setJSON(json) {
      if (!isConfigJsonData(json)) {
        return false;
      }
      try {
        Object.keys(json.data).forEach((tabId) => {
          const targetTab = __privateGet(this, _initData4).tabs.filter((v) => v.id === tabId);
          targetTab.forEach((tab) => {
            Object.keys(json.data[tabId]).forEach((itemId) => {
              const data = json.data[tabId][itemId];
              const targetItem = tab.child.filter((item) => {
                if (item instanceof Item_default || item instanceof Group_default) {
                  return item.initData.id === itemId;
                }
              });
              targetItem.forEach((item) => {
                if (isConfigItemData(data)) {
                  if (item instanceof Item_default) {
                    item.setData(data);
                  }
                } else {
                  if (item instanceof Group_default) {
                    item.setData(data);
                  }
                }
              });
            });
          });
        });
        return true;
      } catch (e) {
        console.error(e);
      }
      return false;
    }
    async save() {
      try {
        const value = this.getJSON();
        await StorageAPI.set(this.key, value);
      } catch (e) {
        console.error(e);
      }
    }
    async load() {
      try {
        const value = await StorageAPI.get(this.key);
        if (isConfigJsonData(value)) {
          this.setJSON(value);
        }
      } catch (e) {
        console.error(e);
      }
    }
    async reset() {
      __privateGet(this, _initData4).tabs.forEach((tab) => {
        tab.child.forEach((item) => {
          if (item instanceof Item_default || item instanceof Group_default) {
            item.reset();
          }
        });
      });
      await StorageAPI.remove(this.key);
    }
    export() {
      const value = JSON.stringify(this.getJSON());
      window.prompt("\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8", value);
    }
    setTheme(theme = "auto") {
      if (["auto", "light", "dark"].includes(theme)) {
        (__privateGet(this, _shadowInner) || this).setAttribute("theme", theme);
      }
    }
    static addStyle(style) {
      let GMAddStyle = null;
      try {
        GMAddStyle || (GMAddStyle = GM_addStyle);
      } catch {
      }
      try {
        GMAddStyle || (GMAddStyle = GM && GM.addStyle);
      } catch {
      }
      try {
        if (typeof GMAddStyle === "function") {
          GMAddStyle(style);
        } else {
          const styleElem = document.createElement("style");
          styleElem.textContent = style;
          document.head.appendChild(styleElem);
        }
      } catch (e) {
        console.error(e);
      }
    }
  };
  var Panel = _Panel;
  _initData4 = new WeakMap();
  _shadowInner = new WeakMap();
  _tab = new WeakMap();
  _main = new WeakMap();
  _bottom = new WeakMap();
  Panel.NAME = "midconfig-panel";
  defineCustomElement_default(Panel.NAME, Panel);

  // src/config.ts
  var midconfig = new Panel({
    id: ECT_ID,
    version: 1,
    theme: "light",
    tabs: [
      {
        id: "general",
        label: "\u5168\u822C",
        child: [
          new Items_exports.CheckBox({
            id: "mergeExtraMain",
            label: "\u300C\u5F15\u7528\u30B3\u30E1\u30F3\u30C8\u300D\u3092\u300C\u30C1\u30E3\u30F3\u30CD\u30EB\u30B3\u30E1\u30F3\u30C8\u300D\u306B\u7D71\u5408",
            default: true
          }),
          new Items_exports.CheckBox({
            id: "mergeExtraEasy",
            label: "\u300C\u5F15\u7528\u304B\u3093\u305F\u3093\u30B3\u30E1\u30F3\u30C8\u300D\u3092\u300C\u304B\u3093\u305F\u3093\u30B3\u30E1\u30F3\u30C8\u300D\u306B\u7D71\u5408",
            default: true
          }),
          new Items_exports.Divider(),
          new Items_exports.CheckBox({
            id: "mergeExtraFromDanime",
            label: "\u300Cd\u30A2\u30CB\u30E1\u30B9\u30C8\u30A2 \u30CB\u30B3\u30CB\u30B3\u652F\u5E97\u300D\u306E\u30B3\u30E1\u30F3\u30C8\u3092\u5F15\u7528\u30FB\u7D71\u5408",
            default: false
          }),
          new Items_exports.CheckBox({
            id: "forcedExtra",
            label: "\u30B3\u30E1\u30F3\u30C8\u3092\u5F37\u5236\u7684\u306B\u5F15\u7528\u30FB\u7D71\u5408",
            default: false
          }),
          new Items_exports.Divider(),
          new Items_exports.CheckBox({
            id: "deleteExtra",
            label: "\u300C\u5F15\u7528\u30B3\u30E1\u30F3\u30C8\u300D\u3068\u300C\u5F15\u7528\u304B\u3093\u305F\u3093\u30B3\u30E1\u30F3\u30C8\u300D\u3092\u975E\u8868\u793A",
            default: false
          }),
          new Items_exports.CheckBox({
            id: "deleteEasy",
            label: "\u300C\u304B\u3093\u305F\u3093\u30B3\u30E1\u30F3\u30C8\u300D\u3068\u300C\u5F15\u7528\u304B\u3093\u305F\u3093\u30B3\u30E1\u30F3\u30C8\u300D\u3092\u975E\u8868\u793A",
            default: false
          }),
          new Items_exports.Divider(),
          new Items_exports.CheckBox({
            id: "showMergedCommentCount",
            label: "\u7D71\u5408\u3057\u305F\u30B3\u30E1\u30F3\u30C8\u306E\u6570\u3092\u30B3\u30E1\u30F3\u30C8\u6570\u6A2A\u306B\u8868\u793A",
            default: true
          }),
          new Items_exports.CheckBox({
            id: "showExtraViewCount",
            label: "\u5F15\u7528\u3057\u305F\u52D5\u753B\u306E\u518D\u751F\u6570\u3092\u518D\u751F\u6570\u6A2A\u306B\u8868\u793A",
            default: false
          }),
          new Items_exports.CheckBox({
            id: "showKawaiiPct",
            label: "\u30B3\u30E1\u30F3\u30C8\u306E\u300C\u304B\u308F\u3044\u3044\u300D\u7387\u3092\u8868\u793A",
            default: false
          })
        ]
      },
      {
        id: "other",
        label: "\u305D\u306E\u4ED6",
        child: [
          new Items_exports.Button({
            id: "import",
            type: "solid",
            label: "\u8A2D\u5B9A\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B",
            text: "\u30A4\u30F3\u30DD\u30FC\u30C8",
            onClick: async () => {
              const value = window.prompt("\u30A4\u30F3\u30DD\u30FC\u30C8");
              if (value) {
                let result = false;
                try {
                  result = midconfig.setJSON(JSON.parse(value));
                } catch (e) {
                  console.error(e);
                }
                window.alert(result ? "\u30A4\u30F3\u30DD\u30FC\u30C8\u3057\u307E\u3057\u305F" : "\u30A4\u30F3\u30DD\u30FC\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
              }
            }
          }),
          new Items_exports.Button({
            id: "export",
            type: "solid",
            label: "\u8A2D\u5B9A\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3059\u308B",
            text: "\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8",
            onClick: async () => {
              window.prompt("\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8", JSON.stringify(midconfig.getJSON()));
            }
          }),
          new Items_exports.Button({
            id: "reset",
            type: "outline-red",
            label: "\u8A2D\u5B9A\u3092\u30EA\u30BB\u30C3\u30C8\u3059\u308B",
            text: "\u30EA\u30BB\u30C3\u30C8",
            onClick: async () => {
              if (window.confirm("\u30EA\u30BB\u30C3\u30C8\u3057\u307E\u3059\u304B\uFF1F")) {
                await midconfig.reset();
              }
            }
          })
        ]
      }
    ],
    buttons: [
      new Items_exports.Button({
        id: "cancel",
        text: "\u30AD\u30E3\u30F3\u30BB\u30EB",
        type: "solid",
        onClick: async () => {
          closeConfig();
        }
      }),
      new Items_exports.ButtonEmpty(),
      new Items_exports.ButtonEmpty(),
      new Items_exports.Button({
        id: "save",
        text: "\u4FDD\u5B58",
        type: "fill",
        onClick: async () => {
          await midconfig.save();
          if (window.confirm("\u8A2D\u5B9A\u3092\u53CD\u6620\u3055\u305B\u308B\u306B\u306F\u30DA\u30FC\u30B8\u3092\u518D\u8AAD\u307F\u8FBC\u307F\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n\u518D\u8AAD\u307F\u8FBC\u307F\u3057\u307E\u3059\u304B\uFF1F")) {
            location.reload();
          }
        }
      })
    ]
  });
  var openConfig = () => {
    if (document.getElementById("midconfig-wrapper") === null) {
      const wrapper = document.createElement("div");
      wrapper.id = "midconfig-wrapper";
      wrapper.appendChild(midconfig);
      wrapper.addEventListener("click", ({ target }) => {
        if (target instanceof HTMLElement && target.id === "midconfig-wrapper") {
          closeConfig();
        }
      });
      document.body.appendChild(wrapper);
    }
  };
  var closeConfig = () => {
    document.getElementById("midconfig-wrapper")?.remove();
  };
  var getConfig = () => {
    const json = midconfig.getJSON();
    return {
      mergeExtraMain: json.data["general"]["mergeExtraMain"].value,
      mergeExtraEasy: json.data["general"]["mergeExtraEasy"].value,
      mergeExtraFromDanime: json.data["general"]["mergeExtraFromDanime"].value,
      forcedExtra: json.data["general"]["forcedExtra"].value,
      deleteExtra: json.data["general"]["deleteExtra"].value,
      deleteEasy: json.data["general"]["deleteEasy"].value,
      showMergedCommentCount: json.data["general"]["showMergedCommentCount"].value,
      showExtraViewCount: json.data["general"]["showExtraViewCount"].value,
      showKawaiiPct: json.data["general"]["showKawaiiPct"].value
    };
  };
  document.addEventListener("ECT:openConfig", openConfig);
  document.addEventListener("ECT:closeConfig", closeConfig);

  // src/index.ts
  if (!isChromeExtension()) {
    window["ECT:isUserScript"] = true;
  }
  (async () => {
    injectStyle_default(STYLE);
    await midconfig.init();
    await migrationConfig_default(midconfig);
    const config = getConfig();
    console.log("[ECT] config:", config);
    try {
      if (typeof GM_registerMenuCommand === "function") {
        GM_registerMenuCommand("\u8A2D\u5B9A", openConfig);
      }
    } catch {
      try {
        if (typeof GM.registerMenuCommand === "function") {
          GM.registerMenuCommand("\u8A2D\u5B9A", openConfig);
        }
      } catch {
      }
    }
    if (!location.pathname.startsWith("/watch/"))
      return;
    const ECT = {
      get videoId() {
        return location.pathname.split("/")[2];
      },
      getChannnelThreadsData(videoData) {
        return videoData?.comment?.threads?.filter((thread) => {
          return {
            "main": "community",
            "easy": "easy"
          }[thread.forkLabel] === thread.label;
        }) || [];
      },
      getExtraThreadsData(videoData) {
        return videoData?.comment?.threads?.filter((thread) => {
          return {
            "main": "extra-community",
            "easy": "extra-easy"
          }[thread.forkLabel] === thread.label;
        }) || [];
      },
      async getLinkedVideo(videoId) {
        try {
          const linkedVideoId = await getLinkedVideoId_default(videoId);
          const linkedVideoData = await getVideoData_default(linkedVideoId);
          const linkedVideoThreads = await getThreads_default(linkedVideoData);
          return {
            videoData: linkedVideoData,
            threads: linkedVideoThreads
          };
        } catch (e) {
        }
      },
      async getIdenticalVideo(videoData) {
        if (videoData === void 0 || videoData.video === void 0) {
          throw new Error("[ECT] ERROR: videoData is undefined");
        }
        try {
          const searchTitle = optimizeTitleForSearch_default(videoData.video.title);
          const duration = videoData.video.duration;
          console.log("[ECT] search title:", searchTitle);
          let searchResult;
          let filteredResult;
          try {
            const query = {
              targets: ["title"],
              filters: {
                "categoryTags": "\u30A2\u30CB\u30E1",
                "genre.keyword": "\u30A2\u30CB\u30E1",
                "lengthSeconds": Number.isFinite(duration) ? [duration - 2, duration + 2] : void 0
              }
            };
            searchResult = await searchVideo_default({
              q: searchTitle,
              ...query
            });
            console.log("[ECT] search result 1:", searchResult);
            if (Array.isArray(searchResult) && searchResult.length <= 1) {
              searchResult = await searchVideo_default({
                q: videoData.video.title,
                ...query
              });
              console.log("[ECT] search result 2:", searchResult);
            }
            if (Array.isArray(searchResult) && 0 < searchResult.length) {
              filteredResult = searchResult.filter((val) => isEqualTitle_default(val.title, videoData.video.title) && val.contentId !== videoData.video.id);
            }
          } catch (e) {
          }
          if (!Array.isArray(filteredResult) || filteredResult[0] === void 0) {
            try {
              const res = await origFetch(`https://www.nicovideo.jp/search/${encodeURIComponent(searchTitle)}?genre=anime&sort=f&order=a`);
              const elem = generateDocumentByHTML_default(await res.text());
              searchResult = Array.from(elem.querySelectorAll('.item[data-video-item][data-video-id^="so"]')).filter((item) => {
                const videoLength = item.getElementsByClassName("videoLength")[0].textContent.trim().split(":");
                const videoDuration = videoLength.length === 2 ? Number(videoLength[0]) * 60 + Number(videoLength[1]) : 0;
                return Math.abs(videoDuration - duration) <= 2;
              }).map((item) => ({
                contentId: item.dataset.videoId,
                title: item.querySelector(".itemTitle > a")?.title?.trim()
              }));
              console.log("[ECT] search result 3:", searchResult);
              if (Array.isArray(searchResult) && 0 < searchResult.length) {
                filteredResult = searchResult.filter((val) => isEqualTitle_default(val.title, videoData.video.title) && val.contentId !== videoData.video.id);
              }
            } catch (e) {
            }
          }
          console.log("[ECT] search result (filtered):", filteredResult);
          if (Array.isArray(filteredResult) && filteredResult[0] !== void 0) {
            const identicalVideoData = await getVideoData_default(filteredResult[0].contentId);
            if (identicalVideoData?.channel?.isOfficialAnime) {
              const identicalVideoThreads = await getThreads_default(identicalVideoData);
              return {
                videoData: identicalVideoData,
                threads: identicalVideoThreads
              };
            }
          }
        } catch (e) {
        }
      }
    };
    let origExtraThreadsOldNums = null;
    let origExtraThreads = null;
    globalWindow.fetch = new Proxy(globalWindow.fetch, {
      apply: async function(target, thisArg, argArray) {
        if (argArray[1]?.method?.toUpperCase() === "POST") {
          if (argArray[0].startsWith(THREADS_API) && argArray[0].endsWith("/nicorus") && origExtraThreadsOldNums !== null && origExtraThreads !== null) {
            try {
              const splitedUrl = argArray[0].split("/");
              const body = typeof argArray[1]?.body === "string" ? JSON.parse(argArray[1].body) : null;
              if (body !== null) {
                const oldNums = origExtraThreadsOldNums[`${splitedUrl[5]}-${body.fork}`];
                const oldNo = oldNums[body.no];
                body.no = oldNo || body.no;
                let isExtraComment = false;
                for (const thread of origExtraThreads) {
                  if (!isExtraComment && thread.fork === body.fork) {
                    if (oldNo !== void 0) {
                      isExtraComment = Boolean(thread.comments?.find((cmt) => cmt.no === oldNo && cmt.body === body.content));
                      if (isExtraComment) {
                        splitedUrl[5] = thread.id;
                        body.videoId = thread.videoId;
                        body.nicoruKey = await getNicoruKey_default(splitedUrl[5], body.fork);
                      }
                    }
                  }
                }
                argArray[0] = splitedUrl.join("/");
                argArray[1].body = JSON.stringify(body);
              }
            } catch (e) {
            }
          }
        }
        let promise;
        try {
          promise = Reflect.apply(target, thisArg, argArray);
        } catch {
          promise = new Promise((resolve) => resolve(Response.error()));
        }
        if (argArray[1]?.method?.toUpperCase() === "POST") {
          if (argArray[0] === THREADS_API) {
            let videoData;
            let extraVideoData;
            let linkedVideo;
            let identicalVideo;
            let extraThreadsData = [];
            let channelThreadsData = [];
            origExtraThreads = null;
            origExtraThreadsOldNums = null;
            try {
              document.getElementsByClassName("FormattedNumber-mergedComment")[0]?.remove();
              document.getElementsByClassName("FormattedNumber-extraView")[0]?.remove();
              console.log("[ECT] %cfetch start%c", "color:white;background-color:blue;", "");
              videoData = await getVideoData_default(ECT.videoId);
              if (!videoData?.channel?.isOfficialAnime) {
                return promise;
              }
              console.log("[ECT] videoData:", videoData);
              if (videoData.channel.id === DANIME_CHANNEL_ID) {
                extraThreadsData = ECT.getExtraThreadsData(videoData);
                if (extraThreadsData.length !== 0) {
                  extraVideoData = await getVideoData_default(extraThreadsData[0].videoId);
                }
              } else if (!config["deleteExtra"] && config["mergeExtraFromDanime"]) {
                linkedVideo = await ECT.getLinkedVideo(ECT.videoId);
                if (linkedVideo !== void 0 && Math.abs(videoData.video.duration - linkedVideo.videoData.video.duration) <= 2) {
                  extraThreadsData = ECT.getChannnelThreadsData(linkedVideo.videoData);
                  if (extraThreadsData.length !== 0) {
                    extraVideoData = linkedVideo.videoData;
                  }
                }
              }
              console.log("[ECT] linkedVideo:", linkedVideo);
              if (!config["deleteExtra"] && config["forcedExtra"] && extraThreadsData.length === 0 && (videoData.channel.id === DANIME_CHANNEL_ID || config["mergeExtraFromDanime"])) {
                identicalVideo = await ECT.getIdenticalVideo(videoData);
                if (identicalVideo !== void 0) {
                  extraThreadsData = ECT.getChannnelThreadsData(identicalVideo.videoData);
                  if (extraThreadsData.length !== 0) {
                    extraVideoData = identicalVideo.videoData;
                  }
                }
              }
              console.log("[ECT] identicalVideo:", identicalVideo);
              console.log("[ECT] extraThreadsData:", extraThreadsData);
              channelThreadsData = ECT.getChannnelThreadsData(videoData);
              console.log("[ECT] channelThreadsData:", channelThreadsData);
              console.log("[ECT] extraVideoData:", extraVideoData);
            } catch (e) {
            }
            const response = await promise;
            try {
              const json = await response.json();
              console.log("[ECT] json:", json);
              let jsonThreads = json.data?.threads;
              if (Boolean(jsonThreads?.length)) {
                let mergedCommentCount = 0;
                for (const extraThreadData of extraThreadsData) {
                  try {
                    const extraThreadIdx = jsonThreads.findIndex((thread) => extraThreadData.id.toString() === thread.id && extraThreadData.forkLabel === thread.fork);
                    if (config["deleteExtra"] && extraThreadIdx !== -1) {
                      delete jsonThreads[extraThreadIdx];
                    } else {
                      const targetThreadData = channelThreadsData.find((channelThread) => extraThreadData.forkLabel === channelThread.forkLabel && extraThreadData.label.indexOf(channelThread.label) !== -1);
                      if (targetThreadData === void 0) {
                        continue;
                      }
                      const targetThreadIdx = jsonThreads.findIndex((thread) => targetThreadData.id.toString() === thread.id && targetThreadData.forkLabel === thread.fork);
                      if (targetThreadIdx === -1) {
                        continue;
                      }
                      if (config["mergeExtraMain"] && extraThreadData.forkLabel === "main" || config["mergeExtraEasy"] && extraThreadData.forkLabel === "easy" && !config["deleteEasy"] || config["forcedExtra"] && identicalVideo !== void 0) {
                        let extraThread;
                        if (extraThreadIdx !== -1) {
                          extraThread = jsonThreads[extraThreadIdx];
                          delete jsonThreads[extraThreadIdx];
                        } else {
                          extraThread = (linkedVideo || identicalVideo)?.threads?.find((thread) => extraThreadData.id.toString() === thread.id && extraThreadData.forkLabel === thread.fork);
                        }
                        if (extraThread == null) {
                          continue;
                        }
                        origExtraThreads || (origExtraThreads = []);
                        origExtraThreads.push(JSON.parse(JSON.stringify({
                          videoId: extraThreadData.videoId,
                          ...extraThread
                        })));
                        mergedCommentCount += extraThread.commentCount;
                        jsonThreads[targetThreadIdx].comments.push(...extraThread.comments);
                        jsonThreads[targetThreadIdx].comments.sort((a, b) => {
                          return new Date(a.postedAt).getTime() - new Date(b.postedAt).getTime();
                        });
                        const oldNo = [];
                        jsonThreads[targetThreadIdx].comments.forEach((v, i) => {
                          oldNo[i + 1] = v.no;
                          v.no = i + 1;
                        });
                        origExtraThreadsOldNums || (origExtraThreadsOldNums = {});
                        origExtraThreadsOldNums[`${targetThreadData.id}-${targetThreadData.forkLabel}`] = oldNo;
                        jsonThreads[targetThreadIdx].commentCount += extraThread.commentCount;
                      }
                    }
                    jsonThreads = jsonThreads.filter(Boolean);
                  } catch (e) {
                  }
                }
                if (config["deleteEasy"]) {
                  jsonThreads = jsonThreads.filter((v) => v.fork !== "easy");
                }
                if (config["showMergedCommentCount"] && mergedCommentCount !== 0) {
                  setTimeout((cnt) => {
                    const counter = document.querySelector(".CommentCountMeta-counter > .FormattedNumber");
                    counter?.insertAdjacentHTML(
                      "afterend",
                      `<span class="FormattedNumber-mergedComment">&nbsp;(+${cnt.toLocaleString()})</span>`
                    );
                  }, 0, mergedCommentCount);
                }
                console.log(`[ECT] \u7D71\u5408\u3057\u305F\u5F15\u7528\u30B3\u30E1\u30F3\u30C8\u6570: ${mergedCommentCount}`);
              }
              if (config["showExtraViewCount"] && Boolean(extraVideoData?.video?.count?.view)) {
                setTimeout((cnt) => {
                  const counter = document.querySelector(".VideoViewCountMeta-counter > .FormattedNumber");
                  counter?.insertAdjacentHTML(
                    "afterend",
                    `<span class="FormattedNumber-extraView">&nbsp;(+${cnt.toLocaleString()})</span>`
                  );
                }, 0, extraVideoData.video.count.view);
              }
              if (config["showKawaiiPct"]) {
                let cmtCnt = 0;
                let kawaiiCnt = 0;
                for (const thread of jsonThreads) {
                  cmtCnt += thread.comments.length;
                  kawaiiCnt += thread.comments.filter((v) => /かわいい/.test(v.body)).length;
                }
                const kawaiiPct = Math.round(kawaiiCnt / cmtCnt * 10 * 100) / 10;
                if (0 < kawaiiPct) {
                  setTimeout((pct) => {
                    try {
                      const kawaiiPctElem = document.querySelector(".KawaiiPctMeta") || document.querySelector(".CommentCountMeta")?.cloneNode(true);
                      if (kawaiiPctElem instanceof HTMLElement) {
                        kawaiiPctElem.classList.add("KawaiiPctMeta");
                        kawaiiPctElem.querySelector(".CommentCountMeta-title").textContent = "\u304B\u308F\u3044\u3044\u7387";
                        kawaiiPctElem.querySelector(".CommentCountMeta-counter").textContent = `${pct}%`;
                        document.querySelector(".CommentCountMeta").insertAdjacentElement("afterend", kawaiiPctElem);
                      }
                    } catch (e) {
                    }
                  }, 0, kawaiiPct);
                }
              }
              if (jsonThreads !== void 0) {
                json.data.threads = jsonThreads;
              }
              return new Response(JSON.stringify(json), {
                status: response.status,
                statusText: response.statusText,
                headers: response.headers
              });
            } catch (e) {
            }
          }
        }
        return promise;
      }
    });
    const obs_opt = {
      childList: true,
      subtree: true
    };
    const obs = new MutationObserver((mutationRecord) => {
      for (const { addedNodes } of mutationRecord) {
        for (const added of addedNodes) {
          if (added instanceof HTMLElement && added.classList.contains("ContextMenu-wrapper")) {
            obs.disconnect();
            const menuContainer = added.getElementsByClassName("VideoContextMenuContainer")[0];
            if (menuContainer instanceof HTMLElement) {
              const ectOptionBtn = generateElementByHTML_default(
                `
              <div class="VideoContextMenu-group">
                <div class="ContextMenuItem">\u5F15\u7528\u30B3\u30E1\u30F3\u30C8\u30C4\u30FC\u30EB \u8A2D\u5B9A</div>
              </div>
              `
              );
              ectOptionBtn.firstElementChild.addEventListener("click", openConfig);
              menuContainer.appendChild(ectOptionBtn);
            }
            obs.observe(document.body, obs_opt);
          }
        }
      }
    });
    obs.observe(document.body, obs_opt);
  })();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址