Sleazy Fork is available in English.

dzmm-helper

自用辅助脚本,只适用于电脑浏览器

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

Advertisement:

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

Advertisement:

// ==UserScript==
// @name         dzmm-helper
// @namespace    oninashi
// @version      1.5.4
// @author       oninashi
// @description  自用辅助脚本,只适用于电脑浏览器
// @license      MIT
// @icon         https://www.dzmm.ai/favicon.ico
// @match        https://www.dzmm.ai/*
// @match        https://www.dzmm.io/*
// @match        https://www.duskpine.top/*
// @match        https://www.aiaptx.com/*
// @match        https://www.fendal.top/*
// @match        https://www.aikda.com/*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_openInTab
// @grant        GM_setValue
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// ==/UserScript==

(function() {
  "use strict";

  const d = new Set(); const importCSS = async (e) => { d.has(e) || (d.add(e), ((t) => { typeof GM_addStyle == "function" ? GM_addStyle(t) : (document.head || document.documentElement).appendChild(document.createElement("style")).append(t); })(e)); };

  var _GM_getValue = (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  var _GM_openInTab = (() => typeof GM_openInTab != "undefined" ? GM_openInTab : void 0)();
  var _GM_setValue = (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  var _GM_xmlhttpRequest = (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
  var _unsafeWindow = (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
  const lsObj = {
    setItem: (key, value) => {
      localStorage.setItem(key, JSON.stringify(value));
    },
    getItem: (key, def = "") => {
      const item = localStorage.getItem(key);
      if (item) {
        return JSON.parse(item);
      }
      return def;
    },
  };
  const _locHref = () => location.href;
  const $n = (selector) => {
    return document.querySelector(selector);
  };
  const $na = (selector) => {
    return document.querySelectorAll(selector);
  };
  const gm_config_def = {
    isDef: true,
    every_config: {
      baseURL: "http://127.0.0.1:8083",
      name: "name",
      password: "password",
      switchOn: false,
    },
  };
  const gob = {
    $body: document.body,
    gm_config: null,
    pageObserver: null,
    staticTimestamp: Math.floor(Date.now() / 1e3),
    get latestTimestamp() {
      return Math.floor(Date.now() / 1e3);
    },
    get locHref() {
      return _locHref();
    },
    get bolWidthChanged() {
      return $n("div.width-adjusted") !== null;
    },
    get $$header() {
      return $na("header");
    },
    init() {
      this.gm_config = _GM_getValue("config", gm_config_def);
      if (this.gm_config.isDef) {
        _GM_setValue("config", Object.assign({}, gm_config_def, { isDef: false }));
      }
    },
    _checkImgUrl: (url) => url.startsWith("/api/draw/image/"),
    _getUUID: (url) => {
      const parts = decodeURIComponent(url).split("/");
      return parts[parts.length - 1].split("?")[0];
    },
    _getImgUrl: (url) => {
      const uuid = gob._getUUID(url);
      const rslUrl = `${location.origin}/draw/${uuid}`;
      return rslUrl;
    },
    _markImg: ($img, classNames, delay = 1e3) => {
      setTimeout(() => {
        $img.classList.add(...classNames, "dzmm-image");
        if ($img.classList.contains("opacity-0")) {
          gob._markImg($img, classNames, delay);
          return;
        }
      }, delay);
    },
    _getImages: () => {
      const $$imgs = $na("div.group img");
      const $$Images = [];
      $$imgs.forEach(($img) => {
        const src = $img.getAttribute("src");
        if (src && gob._checkImgUrl(src)) {
          $img.dataset.uuid = gob._getUUID(src);
          $$Images.push($img);
        }
      });
      return $$Images;
    },
    _getMultiToolBar() {
      let $button = Array.from($na("button")).find(($btn) => $btn.textContent === "退出选择");
      if ($button) {
        return $button.parentNode;
      }
      const $div = $n("div.border-b");
      if (!$div) {
        return null;
      }
      $button = Array.from($div.querySelectorAll("button")).find(($btn) => $btn.textContent === "取消");
      if ($button) {
        return $div;
      }
      return null;
    },
    _isHistoryPage() {
      return this.locHref.includes("draw/generate/history");
    },
    _isHistoryGallery() {
      return this.locHref.includes("draw/generate/history?sub=gallery");
    },
    _isGeneratePage() {
      return this.locHref.endsWith("draw/generate/create");
    },
    _isDrawPage() {
      return /\/draw\/[a-f0-9-]{36}$/.test(this.locHref);
    },
    _isCharEdt() {
      return this.locHref.includes("/studio/character-creation");
    },
    _cleanClickEvents($el) {
      $el.onclick = (e) => {
        e.stopPropagation();
      };
      $el.oncontextmenu = (e) => {
        e.stopPropagation();
      };
    },
    _delayRun(fn, delay = 1e3) {
      setTimeout(() => {
        fn();
      }, delay);
    },
    disablePageObserve() {
      if (this.pageObserver) {
        this.pageObserver.disconnect();
        this.pageObserver = null;
      }
    },
    enablePageObserve(callback) {
      if (this.pageObserver) {
        return;
      }
      this.pageObserver = new MutationObserver((mr, mo) => callback(mr, mo));
      this.pageObserver.observe(this.$body, {
        childList: true,
        subtree: true,
      });
    },
  };
  gob.init();
  const LS_PUBLIC = "dzmm_listPublic";
  const storePublic = {
    galleries: {},
    load() {
      const galleries = lsObj.getItem(LS_PUBLIC, {});
      if (Object.keys(galleries).length > 0) {
        this.galleries = galleries;
      }
    },
    save() {
      lsObj.setItem(LS_PUBLIC, this.galleries);
    },
    parseGalleries(res) {
      const data = JSON.parse(res);
      if (data.result?.data?.json) {
        const galleries = data.result.data.json;
        if (Array.isArray(galleries)) {
          galleries.forEach((gallery) => {
            const { id, title, images } = gallery;
            this.galleries[id] = { id, title, images };
          });
          this.save();
        }
      }
    },
    addGallery(gallery) {
      this.galleries[gallery.id] = { id: gallery.id, title: gallery.title, images: gallery.images };
      this.save();
    },
    isPublic($img) {
      const uuid = $img.getAttribute("data-uuid");
      if (!uuid) return;
      Object.values(this.galleries).forEach((gallery) => {
        gallery.images.forEach((image) => {
          if (image.endsWith(uuid)) {
            gob._markImg($img, ["public"]);
          }
        });
      });
    },
  };
  storePublic.load();
  const gmWindow = _unsafeWindow ?? window;
  const reFetchHandler = (requestUrl, response) => {
    const interceptConfigs = [
      {
        pattern: /\/api\/trpc\/user.getGalleries\?input=/,
        handler: async (text) => {
          storePublic.parseGalleries(text);
        },
      },
    ];
    interceptConfigs.forEach(async (config) => {
      if (config.pattern.test(requestUrl)) {
        try {
          const text = await response.clone().text();
          await config.handler(text);
        }
        catch (err) {
          console.error("拦截处理出错,回退原始 response:", err);
        }
      }
    });
  };
  const originalFetch = gmWindow.fetch.bind(gmWindow);
  const reFetch = async (input, init) => {
    const response = await originalFetch(input, init);
    const requestUrl = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
    reFetchHandler(requestUrl, response);
    return response;
  };
  gmWindow.fetch = reFetch;
  const styleCss = "div.group:has(.dzmm-image){--orange: #f97316;--green: #10b981;border-width:2px}div.group:has(.submitted){border-top-color:var(--green)}div.group:has(.cur-downloaded){border-right-color:var(--green)}div.group:has(.public){border-bottom-color:var(--green)}div.group:has(.downloaded){border-left-color:var(--green)}div.group:has(.un-downloaded){border-left-color:hsl(var(--primary));border-top-color:hsl(var(--primary));border-right-color:hsl(var(--primary))}div.group:has(.dzmm-art):hover .dzmm-art{flex-wrap:wrap!important}div.group:has(.dzmm-art):hover .dzmm-art>span{min-width:48%}.dzmm-art-input.short{width:6.3rem}.z-55{z-index:55}.z-60{z-index:60}.z-65{z-index:65}.z-75{z-index:75}.dzmm-drop-panel{position:fixed;top:0;right:0;bottom:0;height:100vh;width:25vw;background:color-mix(in srgb,hsl(var(--card)) 85%,#000 15%);border-left:1px solid hsl(var(--border));box-shadow:-12px 0 24px #00000040;display:flex;flex-direction:column;pointer-events:auto;transition:all .22s ease}.dzmm-drop-panel-zone{flex:1;border-bottom:1px dashed hsl(var(--border));display:flex;flex-direction:column;justify-content:center;align-items:center;gap:6px}.dzmm-drop-panel-zone h4{margin:0;font-size:16px;line-height:1.2}.dzmm-drop-panel-zone p{margin:0;font-size:13px;opacity:.8}.dzmm-drop-panel.mini{bottom:auto;width:0;height:0}.dzmm-drop-panel.mini .dzmm-drop-panel-zone{display:none}";
  importCSS(styleCss);
  const fnAddElementToNav = (newElement) => {
    const $nav = $n("nav.h-full div.hidden");
    if (!$n(".dzmm-nav-divider")) {
      const $span = document.createElement("span");
      $span.classList.add("px-1", "py-2", "text-muted-foreground");
      $span.classList.add("dzmm-nav-divider");
      $span.textContent = "|";
      $nav?.insertAdjacentElement("beforeend", $span);
    }
    newElement.classList.add("px-3", "py-2", "text-muted-foreground", "hover:text-foreground");
    if ($nav) {
      $nav?.insertAdjacentElement("beforeend", newElement);
      $nav.classList.add("dzmm-nav-added");
    }
  };
  const fnAddGalleryLink = () => {
    const clsName = "dzmm-gallery-link";
    if ($n(`.${clsName}`)) return;
    const $画廊链接 = document.createElement("a");
    $画廊链接.classList.add(clsName);
    $画廊链接.href = "/draw";
    $画廊链接.textContent = "画廊";
    fnAddElementToNav($画廊链接);
  };
  const fnAddGenerateLink = (target = "nav") => {
    const clsName = "dzmm-generate-link" + target;
    if ($n(`.${clsName}`)) return;
    const $创作链接 = document.createElement("a");
    $创作链接.classList.add(clsName);
    $创作链接.href = "/draw/generate/create";
    $创作链接.textContent = "创作";
    fnAddElementToNav($创作链接);
  };
  const fnAddHistoryLink = () => {
    const clsName = "dzmm-history-link";
    if ($n(`.${clsName}`)) return;
    const $历史链接 = document.createElement("a");
    $历史链接.classList.add(clsName);
    $历史链接.href = "/draw/generate/history";
    $历史链接.textContent = "我的作品";
    fnAddElementToNav($历史链接);
  };
  const fnReplaceButtonWithLink = ($container, btnText, href) => {
    if (!$container) return;
    const done = $container.dataset.done === "true";
    if (done) return;
    $container.dataset.done = "true";
    const $btn = Array.from($container.querySelectorAll("button")).find((btn) => btn.textContent === btnText);
    if (!$btn) return;
    const $link = document.createElement("a");
    $link.href = href;
    $link.className = $btn.className;
    $link.innerHTML = $btn.innerHTML;
    $link.target = "_blank";
    $btn.replaceWith($link);
  };
  const fnConvertButtonToLink = () => {
    let $container = $n("div.relative.items-center.overflow-x-auto");
    fnReplaceButtonWithLink($container, "画廊", "/draw");
    $container = $n(".mb-4 .max-w-full");
    fnReplaceButtonWithLink($container, "画廊", "/draw/generate/history?sub=gallery");
  };
  const LS_ART = "dzmm_listArt";
  const storeArt = {
    arts: [],
    load() {
      const gmArts = _GM_getValue(LS_ART, []);
      const lsArts = lsObj.getItem(LS_ART, []);
      const arts = [...new Set([...gmArts, ...lsArts])];
      if (arts.length > 0) {
        this.arts = arts;
      }
    },
    save() {
      lsObj.setItem(LS_ART, this.arts);
      _GM_setValue(LS_ART, this.arts);
    },
    add(artName) {
      if (!this.arts.includes(artName)) {
        this.arts.push(artName);
        this.save();
      }
    },
    remove(artName) {
      const idx = this.arts.indexOf(artName);
      if (idx !== -1) {
        this.arts.splice(idx, 1);
        this.save();
      }
    },
    artsCheck(text, cb) {
      const lowerText = text.toLowerCase();
      const found = this.arts.filter((artName) => lowerText.includes(artName.toLowerCase()));
      cb(found);
    },
  };
  storeArt.load();
  class HttpRequest {
    constructor() {
    }

    get(url, headers = {}) {
      return this.request({
        method: "GET",
        url,
        headers,
      });
    }

    post(url, data = {}, headers = {}) {
      const formData = new FormData();
      for (const key in data) {
        formData.append(key, data[key]);
      }
      return this.request({
        method: "POST",
        url,
        data: formData,
        headers,
      });
    }

    request(options) {
      return new Promise((resolve, reject) => {
        const requestOptions = Object.assign({}, options);
        requestOptions.onload = function(res) {
          resolve(res);
        };
        requestOptions.onerror = function(error) {
          reject(error);
        };
        _GM_xmlhttpRequest(requestOptions);
      });
    }
  }
  const http = new HttpRequest();
  const DOWNLOAD_URL_TEMPLATE = "{baseURL}/?search={uuid}&json=1&path_column=1";
  const LS_DL = "dzmm_listDownload";
  const storeDownload = {
    dls: [],
    get switchOn() {
      return !!gob.gm_config?.every_config?.switchOn;
    },
    load() {
      const lsDls = lsObj.getItem(LS_DL, []);
      if (lsDls.length > 0) {
        this.dls = lsDls;
      }
    },
    lsCacheCheck(dlInfo) {
      const lsTime = dlInfo.lsTime;
      const now = gob.staticTimestamp;
      const isValid = now - lsTime < 3600 * 4;
      return isValid;
    },
    lsWatchCheck(dlInfo) {
      const now = gob.staticTimestamp;
      if (dlInfo && dlInfo.watchUntil && now < dlInfo.watchUntil) {
        return true;
      }
      return false;
    },
    lsWatchSet(uuid, watchDuration = 180) {
      const dlInfo = this.lsGet(uuid);
      if (dlInfo) {
        const now = gob.staticTimestamp;
        dlInfo.watchUntil = now + watchDuration;
        this.lsSet(dlInfo);
      }
    },
    lsDLCheck(uuid) {
      const dlInfo = this.lsGet(uuid);
      if (dlInfo) {
        return dlInfo.downloaded;
      }
      return false;
    },
    lsGet(uuid) {
      const dlInfo = this.dls.find((dl) => dl.uuid === uuid) || null;
      if (dlInfo && !this.lsCacheCheck(dlInfo)) {
        return null;
      }
      return dlInfo;
    },
    lsSet(dlInfo) {
      const existingIndex = this.dls.findIndex((dl) => dl.uuid === dlInfo.uuid);
      if (existingIndex >= 0) {
        this.dls[existingIndex] = dlInfo;
      }
      else {
        this.dls.push(dlInfo);
      }
      lsObj.setItem(LS_DL, this.dls);
    },
    lsDel(uuid) {
      this.dls = this.dls.filter((dl) => dl.uuid !== uuid);
      lsObj.setItem(LS_DL, this.dls);
    },
    isDL($img, forceCheck = false) {
      const uuid = $img.dataset.uuid;
      const dlInfo = this.lsGet(uuid);
      if (dlInfo === null || this.lsWatchCheck(dlInfo) || forceCheck) {
        $img.classList.remove("downloaded", "un-downloaded");
        const payload = {
          uuid,
          lsTime: gob.staticTimestamp,
          downloaded: false,
        };
        if (this.lsWatchCheck(dlInfo)) {
          payload.watchUntil = dlInfo.watchUntil;
        }
        if (storeDownload.switchOn) {
          storeDownload.checkDownload(uuid).then((data) => {
            if (data.totalResults > 0) {
              payload.downloaded = true;
            }
          }).finally(() => {
            storeDownload.lsSet(payload);
            gob._markImg($img, payload.downloaded ? ["downloaded"] : ["un-downloaded"]);
          });
        }
      }
      else {
        gob._markImg($img, dlInfo.downloaded ? ["downloaded"] : ["un-downloaded"]);
      }
    },
    getDefaultResult() {
      return {
        totalResults: 0,
        results: [],
      };
    },
    getQueryUrl(uuid) {
      const baseURL = gob.gm_config?.every_config?.baseURL?.trim();
      if (!baseURL) {
        return "";
      }
      return DOWNLOAD_URL_TEMPLATE.replace("{baseURL}", baseURL).replace("{uuid}", encodeURIComponent(uuid));
    },
    getHeaders() {
      const name = gob.gm_config?.every_config?.name?.trim() || "";
      const password = gob.gm_config?.every_config?.password?.trim() || "";
      if (!name && !password) {
        return {};
      }
      return {
        Authorization: "Basic " + btoa(`${name}:${password}`),
      };
    },
    async checkDownload(uuid) {
      const tplRlt = this.getDefaultResult();
      const url = this.getQueryUrl(uuid);
      if (!url) {
        console.error("everything API 查询失败,未配置 baseURL");
        return tplRlt;
      }
      try {
        const res = await http.get(url, this.getHeaders());
        if (res.status === 200) {
          const data = JSON.parse(res.responseText);
          return data || tplRlt;
        }
        console.error("everything API 查询失败,状态码", res.status);
      }
      catch (error) {
        console.error("查询 everything API 失败", error);
      }
      return tplRlt;
    },
  };
  storeDownload.load();
  const insertPreviewContainer = (clsName) => {
    let $fixedDiv = $n(`.${clsName}`);
    if (!$fixedDiv) {
      $fixedDiv = document.createElement("div");
      $fixedDiv.className = `rounded-lg bg-card fixed bottom-1 z-75 p-1.5 ${clsName} hidden`;
      $fixedDiv.innerHTML = "<div class=\"image-preview h-full\"></div>";
      document.body.appendChild($fixedDiv);
    }
    $fixedDiv.style.maxWidth = "40vw";
    return $fixedDiv;
  };
  const fnShowImgIndex = ($img, act = "show") => {
    if (!$img) {
      return;
    }
    const i = parseInt($img.dataset.index);
    const recordIndex = $img.dataset.recordIndex;
    const clsName = `dzmm-img-index-${i}`;
    const $imgIndex = $n(`.${clsName}`);
    if (act === "show") {
      if ($imgIndex) return;
      const $span = document.createElement("span");
      $span.className = "absolute bottom-1 right-1 text-xs bg-black/50 rounded-full px-1 py-1 transition-opacity";
      $span.classList.add(clsName);
      $span.textContent = String(i + 1) + (recordIndex ? ` (${recordIndex})` : "");
      $img.insertAdjacentElement("afterend", $span);
    }
    else {
      if ($imgIndex) {
        $imgIndex.classList.add("opacity-0");
        setTimeout(() => {
          $imgIndex.remove();
        }, 500);
      }
    }
  };
  const fnFindBadge = ($el) => {
    const $elParent = $el.parentElement;
    if (!$elParent) return null;
    const $greenBg = $elParent.querySelector(".text-green-700");
    if ($greenBg) {
      return $greenBg;
    }
    else {
      return fnFindBadge($elParent);
    }
  };
  const fnBadgeHandle = ($img) => {
    const $greenBg = fnFindBadge($img);
    if ($greenBg) {
      $greenBg.classList.add("dark:text-orange-400", "text-orange-700");
      $greenBg.classList.remove("dark:text-green-400", "text-green-700");
      gob._cleanClickEvents($greenBg);
    }
    const detUrl = gob._getImgUrl($img.src);
    if ($greenBg && detUrl) {
      const tmpHtml = $greenBg.innerHTML;
      const tmpCls = $greenBg.className;
      $greenBg.className = "";
      $greenBg.innerHTML = `<a href="${detUrl}" target="_blank" class="${tmpCls}">${tmpHtml}</a>`;
    }
  };
  const fnPromptHandle = ($img, isList = false) => {
    let textPrompt = "";
    if (isList) {
      const $itemCenter = $img.closest(".items-stretch");
      const $promptWrap = $itemCenter?.querySelector(".self-stretch");
      if ($promptWrap) {
        const $prompt = $promptWrap.querySelector(".text-sm.line-clamp-2");
        $prompt?.classList.remove("line-clamp-2");
        $prompt?.classList.add("dzmm-prompt");
        const actBar = $promptWrap.querySelector("div.mt-1.justify-between");
        if (actBar) {
          actBar.classList.remove("justify-between", "items-end");
          actBar.classList.add("items-center");
        }
        $promptWrap.classList.add("cursor-default");
        $promptWrap.onclick = (e) => {
          if (e.target.tagName === "BUTTON") return;
          e.stopPropagation();
          e.preventDefault();
        };
      }
    }
    else {
      const $divGroup = $img.closest("div.group");
      const $promptWrap = $divGroup?.querySelector("div.px-3");
      if ($promptWrap && $img.dataset.index) {
        gob._cleanClickEvents($promptWrap);
        const $prompt = $promptWrap.querySelector("p.text-sm");
        $prompt?.classList.add("dzmm-prompt");
        textPrompt = $prompt?.textContent?.trim() || "";
        storeArt.artsCheck(textPrompt, (found) => {
          if (found.length > 0) {
            let $artFound;
            if ($promptWrap.querySelector(".text-xs")) {
              $artFound = $promptWrap.querySelector(".flex-nowrap");
              $artFound?.classList.add("dzmm-art");
            }
            else {
              $prompt?.insertAdjacentHTML("afterend", "<p class=\"dzmm-art flex gap-1\" data-art=\"found\"></p>");
              $artFound = $promptWrap.querySelector(".dzmm-art");
            }
            found.forEach((art) => {
              $artFound?.insertAdjacentHTML("beforeend", `<span class="text-xs px-2 py-0.5 rounded-full dark:bg-pink-900/40 dark:text-pink-200" data-art="${art}">${art}</span>`);
            });
          }
        });
      }
      if ($divGroup) {
        $divGroup.style.aspectRatio = "0.75/1.2";
      }
    }
  };
  const fnCountUndownloaded = (imgs) => {
    const $navUL = $n("nav[role=\"navigation\"] ul");
    if (!$navUL) return;
    let count = 0;
    imgs.forEach(($img) => {
      if ($img && $img.classList.contains("un-downloaded")) {
        count++;
      }
    });
    let $countSpan = $navUL.querySelector(".dzmm-undownload-count");
    if (!$countSpan) {
      $countSpan = document.createElement("li");
      $countSpan.className = "dzmm-undownload-count text-sm text-muted-foreground px-2";
      $navUL.appendChild($countSpan);
    }
    count === 0 ? $countSpan.classList.add("hidden") : $countSpan.classList.remove("hidden");
    const lstCount = $countSpan.dataset.count || "0";
    if (lstCount === String(count)) return;
    $countSpan.dataset.count = String(count);
    $countSpan.textContent = `未下载: ${count}`;
  };
  class PreviewEngine {
    getImages;
    $fixedDiv;
    clsName = "";
    isList = false;
    imageHandlers = [];
    finalizeHandlers = [];
    hasRegisteredDefaults = false;
    init({ getImages, clsName }) {
      this.getImages = getImages;
      this.$fixedDiv = insertPreviewContainer(clsName);
      this.clsName = clsName;
      this.isList = $na(".space-y-3").length > 0;
      this.regDefaults();
      return this;
    }

    regImage(apply, name = "image-handler") {
      this.imageHandlers.push({ name, apply });
      return this;
    }

    regFinalize(apply, name = "finalize-handler") {
      this.finalizeHandlers.push({ name, apply });
      return this;
    }

    regDefaults() {
      if (this.hasRegisteredDefaults) return this;
      this.regImage(($img, i) => {
        $img.dataset.index = i.toString();
      }, "set-index");
      this.regImage(($img) => {
        storePublic.isPublic($img);
      }, "public-mark");
      storeDownload.switchOn && this.regImage(($img) => {
        storeDownload.isDL($img);
      }, "download-mark");
      this.regImage(($img, _i, ctx) => {
        fnPromptHandle($img, ctx.isListMode);
      }, "prompt-enhance");
      this.regImage(($img, _i, ctx) => {
        if (!ctx.isListMode) {
          $img.draggable = true;
        }
      }, "set-draggable");
      this.regImage(($img) => {
        fnBadgeHandle($img);
      }, "badge-enhance");
      this.regImage(($img, _i, ctx) => {
        if ($img.dataset.event === "set") return;
        $img.dataset.event = "set";
        $img.addEventListener("mouseenter", (e) => {
          clearTimeout(ctx.hideTimer);
          fnShowImgIndex($img);
          const $preview = $n(`.${ctx.clsName} .image-preview`);
          $preview.innerHTML = `<img src="${$img.src}" class="h-full" />`;
          ctx.$fixedDiv?.appendChild($preview);
          ctx.$fixedDiv.classList.remove("hidden");
          const isLeft = ctx.isListMode || e.clientX < window.innerWidth / 2;
          if (isLeft) {
            ctx.$fixedDiv.classList.add("right-1");
            ctx.$fixedDiv.classList.remove("left-1");
          }
          else {
            ctx.$fixedDiv.classList.add("left-1");
            ctx.$fixedDiv.classList.remove("right-1");
          }
          const aspectRatio = $img.naturalWidth / $img.naturalHeight;
          if (aspectRatio >= 1) {
            ctx.$fixedDiv.classList.remove("top-1");
            $preview.querySelector("img")?.classList.remove("h-full");
          }
          else {
            ctx.$fixedDiv.classList.add("top-1");
            $preview.querySelector("img")?.classList.add("h-full");
          }
        });
        $img.addEventListener("mouseout", () => {
          ctx.removePreview();
          setTimeout(() => {
            fnShowImgIndex($img, "hide");
          }, 1e3);
        });
      }, "hover-preview");
      this.regFinalize((ctx) => {
        if (!storeDownload.switchOn) return;
        gob._delayRun(() => {
          fnCountUndownloaded(ctx.imgs);
        }, 1700);
      }, "undownload-count");
      this.regFinalize((ctx) => {
        if (ctx.$fixedDiv.dataset.event === "set") return;
        ctx.$fixedDiv.addEventListener("mousemove", () => {
          clearTimeout(ctx.hideTimer);
        });
        ctx.$fixedDiv.addEventListener("mouseleave", () => {
          ctx.removePreview();
        });
        ctx.$fixedDiv.dataset.event = "set";
      }, "bind-fixed-div-events");
      this.hasRegisteredDefaults = true;
      return this;
    }

    run() {
      if (!this.getImages || !this.$fixedDiv || !this.clsName) {
        return this;
      }
      const imgs = Array.from(this.getImages());
      if (imgs.length === 0) return this;
      const ctx = {
        imgs,
        $fixedDiv: this.$fixedDiv,
        clsName: this.clsName,
        isListMode: this.isList,
        hideTimer: void 0,
        removePreview: () => {
          ctx.hideTimer = setTimeout(() => {
            ctx.$fixedDiv.classList.add("hidden");
          }, 50);
        },
      };
      imgs.forEach(($img, i) => {
        this.imageHandlers.forEach((handler) => handler.apply($img, i, ctx));
      });
      this.finalizeHandlers.forEach((handler) => handler.apply(ctx));
      return this;
    }
  }
  const fnAddImagePreview = () => {
    const isTargetPage = (gob._isHistoryPage() || gob._isGeneratePage()) && !gob._isHistoryGallery();
    if (!isTargetPage) {
      return;
    }
    const clsName = "dzmm-fixed-preview";
    const runPreview = () => {
      const previewEngine = new PreviewEngine();
      previewEngine.init({
        getImages: gob._getImages,
        clsName,
      }).run();
    };
    runPreview();
  };
  const 自动获取数量 = 48;
  const oDL = {
    markDL: ($img) => {
      gob._markImg($img, ["downloaded"]);
    },
    removeDL: ($img) => {
      gob._markImg($img, ["un-downloaded"]);
      $img.classList.remove("downloaded");
    },
    isDL: ($img) => {
      const uuid = $img.dataset.uuid;
      return $img.classList.contains("downloaded") || storeDownload.lsDLCheck(uuid);
    },
  };
  const fnGetPickBtn = ($img) => {
    const rlt = {
      $pickBtn: null,
      isPicked: false,
    };
    const $group = $img.closest("div.group");
    if (!$group) {
      return rlt;
    }
    const $btn = $group.querySelector("div.right-2.z-10 div");
    if ($btn) {
      rlt.$pickBtn = $btn;
      rlt.isPicked = $btn.classList.contains("bg-primary");
    }
    return rlt;
  };
  const fnClearPick = () => {
    const $$imgs = gob._getImages();
    $$imgs.forEach(($img) => {
      const { $pickBtn, isPicked } = fnGetPickBtn($img);
      if ($pickBtn && isPicked) {
        $pickBtn.click();
      }
    });
  };
  const fnGetPickImages = () => {
    const $$imgs = gob._getImages();
    const $$pickImgs = [];
    const $toolBar = gob._getMultiToolBar();
    if ($toolBar) {
      $$imgs.forEach(($img) => {
        const { $pickBtn, isPicked } = fnGetPickBtn($img);
        if ($pickBtn && isPicked) {
          $$pickImgs.push($img);
        }
      });
    }
    else {
      for (let i = 0; i < Math.min(自动获取数量, $$imgs.length); i++) {
        $$pickImgs.push($$imgs[i]);
      }
    }
    return $$pickImgs;
  };
  const _getImagesWrapper = (isEvenClick) => {
    const $$imgs = gob._getImages();
    let $$imgsFiltered = [];
    $$imgsFiltered = $$imgsFiltered.length > 0 ? $$imgsFiltered : $$imgs.filter(($img) => !oDL.isDL($img));
    if (isEvenClick && $$imgsFiltered.length > 0) {
      return $$imgsFiltered;
    }
    return $$imgs;
  };
  const fnAutoPick = ($toolBar, callback) => {
    const clickCount = parseInt($toolBar.dataset.dzmmClickCount || "0", 10);
    $toolBar.dataset.dzmmClickCount = (clickCount + 1).toString();
    const $$imgs = _getImagesWrapper(clickCount % 2 === 0);
    let pickCount = 0;
    const pickStart = parseInt($toolBar.dataset.dzmmPickStart || gob.$body.dataset.dzmmPickStart || "0", 10);
    const uuids = [];
    $$imgs.forEach(($img, index) => {
      const { $pickBtn, isPicked } = fnGetPickBtn($img);
      if (!$pickBtn) {
        return;
      }
      if (index >= pickStart && pickCount < 自动获取数量) {
        if (!isPicked) {
          $pickBtn.click();
        }
        pickCount++;
        const uuid = $img.dataset.uuid;
        uuid && uuids.push(uuid);
      }
      else {
        if (isPicked) {
          $pickBtn.click();
        }
      }
      if (pickCount === 1) {
        $img.scrollIntoView({ behavior: "smooth", block: "center" });
      }
    });
    uuids.length > 0 && storeDownload.switchOn && storeDownload.checkDownload(uuids.join("|")).then((data) => {
      for (let i = 0; i < uuids.length; i++) {
        const uuid = uuids[i];
        const $img = $n(`img[data-uuid="${uuid}"]`);
        if (!$img) {
          console.log(`UUID ${uuid} 对应的图片元素未找到,无法标记下载状态`);
          continue;
        }
        const rlt = data.results.find((item) => item.name.includes(uuid));
        let watchDuration = 0;
        if (rlt) {
          watchDuration = 30;
          oDL.markDL($img);
        }
        else {
          watchDuration = 180;
          oDL.removeDL($img);
        }
        storeDownload.lsWatchSet(uuid, watchDuration);
      }
    });
    let nextStart = pickStart + 自动获取数量;
    if (nextStart >= $$imgs.length) {
      nextStart = 0;
    }
    $toolBar.dataset.dzmmPickStart = nextStart.toString();
    gob.$body.dataset.dzmmPickStart = pickStart.toString();
    if (callback) {
      callback();
    }
  };
  const fnCopyUUIDs = () => {
    const $autoPickBtn = $n("button.dzmm-auto-pick-btn");
    if ($autoPickBtn) {
      const originalText = $autoPickBtn.textContent;
      $autoPickBtn.textContent = "UUID 已复制";
      setTimeout(() => {
        $autoPickBtn.textContent = originalText;
      }, 2e3);
    }
    setTimeout(async () => {
      const $$pickImgs = fnGetPickImages();
      const uuids = $$pickImgs.map(($img) => $img.dataset.uuid || "").sort((a, b) => a.localeCompare(b)).join("|");
      await navigator.clipboard.writeText(uuids);
    }, 500);
  };
  const fnAddBatchBtn = () => {
    const $toolBar = gob._getMultiToolBar();
    if (!$toolBar || $toolBar.dataset.dzmmPickInit === "1") {
      return;
    }
    const $downloadBtn = Array.from($toolBar.querySelectorAll("button")).find((btn) => btn.innerText.includes("下载"));
    if (!$downloadBtn) {
      return;
    }
    const $copyUUIDBtn = document.createElement("button");
    $copyUUIDBtn.className = $downloadBtn.className;
    $copyUUIDBtn.classList.add("dzmm-copy-uuid-btn");
    $copyUUIDBtn.innerText = "复制 UUID";
    $copyUUIDBtn.onclick = () => {
      fnCopyUUIDs();
    };
    $downloadBtn.insertAdjacentElement("beforebegin", $copyUUIDBtn);
    const $autoPickBtn = document.createElement("button");
    $autoPickBtn.className = $downloadBtn.className;
    $autoPickBtn.classList.add("dzmm-auto-pick-btn");
    $autoPickBtn.innerText = "批量选择";
    $autoPickBtn.onclick = () => {
      fnClearPick();
      gob._delayRun(() => {
        fnAutoPick($toolBar, fnCopyUUIDs);
      }, 300);
    };
    $downloadBtn.insertAdjacentElement("beforebegin", $autoPickBtn);
    $toolBar.dataset.dzmmPickInit = "1";
  };
  const fnAddStoreArt = () => {
    if (!gob._isHistoryPage() && !gob._isGeneratePage() && !gob._isDrawPage()) {
      return;
    }
    const clsName = "dzmm-art-input";
    if ($n(`.${clsName}`)) return;
    let $subNav = $n("div.relative.items-center.overflow-x-auto");
    if (!$subNav) {
      const $h3 = $n("div.items-center > h3.font-medium");
      if (!$h3) return;
      $subNav = document.createElement("div");
      $subNav.classList.add("flex-1", "flex", "gap-1", "ml-1");
      $h3.insertAdjacentElement("afterend", $subNav);
    }
    if (!$subNav) return;
    const $nav = $n(".dzmm-nav-added");
    const $btn = document.createElement("button");
    $btn.classList.add(clsName);
    $btn.classList.add("dzmm-store-art-btn", "px-2", "py-1.5", "text-sm", "text-muted-foreground", "hover:text-foreground", "rounded-md", "border", "border-input", "hover:bg-accent");
    $btn.textContent = "保存画师";
    const $input = document.createElement("input");
    $input.type = "text";
    $input.placeholder = "输入画师名称并回车";
    $input.classList.add("dzmm-art-input", "text-sm", "bg-muted", "rounded-full", "w-0", "transition-[width]", "duration-500", "ease-swift");
    $subNav.insertAdjacentElement("beforeend", $input);
    $subNav.insertAdjacentElement("beforeend", $btn);
    const observer = new IntersectionObserver((changes) => {
      changes.forEach((change) => {
        change.intersectionRatio <= 0 ? $nav?.insertAdjacentElement("beforeend", $input) : $btn?.insertAdjacentElement("beforebegin", $input);
        change.intersectionRatio <= 0 && _ToggleInput("short");
      });
    });
    observer.observe($btn);
    const fnSubmitArt = () => {
      const artName = $input.value.trim().replace(/\s+/g, "_").toLocaleLowerCase();
      if (!artName) {
        $input.placeholder = "画师名称不能为空";
        return;
      }
      storeArt.add(artName);
      const btnText = $btn.textContent || "保存画师";
      $btn.textContent = "已保存: " + artName;
      gob._delayRun(() => {
        $btn.textContent = btnText;
      }, 2e3);
      $input.value = "";
    };
    let t = null;
    const _ToggleInput = (to, focus = false) => {
      if (to === "show" || to === "short") {
        if (t) {
          clearTimeout(t);
          t = null;
        }
        $input.classList.add("w-48", "px-2", "py-1.5");
      }
      if (to === "show") {
        $input.classList.remove("short");
        focus && $input.focus();
      }
      if (to === "short") {
        t = setTimeout(() => {
          $input.classList.add("short");
          $input.blur();
        }, 1e3);
      }
    };
    [$n("header"), $subNav.parentElement].forEach(($parent) => {
      $parent?.addEventListener("mouseenter", () => {
        if ($parent.querySelector(`.${clsName}`)) {
          _ToggleInput("show", true);
        }
      });
      $parent?.addEventListener("mouseleave", () => {
        if ($parent.querySelector(`.${clsName}`)) {
          _ToggleInput("short");
        }
      });
    });
    $btn.addEventListener("click", () => {
      fnSubmitArt();
    });
    $input.addEventListener("keydown", (e) => {
      if (e.key === "Enter") {
        fnSubmitArt();
      }
    });
  };
  const fnParseSoloGallery = () => {
    if (!gob.locHref.includes("/gallery/")) {
      return;
    }
    const galleryId = gob.locHref.split("/gallery/")[1].split("?")[0];
    const $myGallerySpan = Array.from($na(".justify-between .text-xs")).find((el) => el.textContent?.includes("我的画廊"));
    if (!$myGallerySpan || $myGallerySpan.dataset.uuid === galleryId) {
      return;
    }
    $myGallerySpan.dataset.uuid = galleryId;
    const images = Array.from($na(".swiper-slide img")).map(($img) => {
      const src = $img.getAttribute("src");
      return src || "";
    });
    storePublic.addGallery({
      id: galleryId,
      title: "unknown",
      images,
    });
  };
  const fnAddPromptExt2 = ($h3Parent, $p) => {
    const $copyBtn = $h3Parent?.querySelector("button.rounded");
    if (!$copyBtn) return;
    const uuid = gob._getUUID(gob.locHref);
    let $dlBtn = $h3Parent?.querySelector(".dzmm-download-prompt-btn");
    if (!$dlBtn) {
      $dlBtn = document.createElement("button");
      $dlBtn.classList.add("dzmm-download-prompt-btn", "p-1.5", "rounded", "hover:bg-muted", "transition-all", "duration-200");
      $dlBtn.textContent = "下载提示词";
      $copyBtn.insertAdjacentElement("beforebegin", $dlBtn);
    }
    $dlBtn.onclick = () => {
      const promptText = $p.textContent?.trim() || "";
      if (!promptText) return;
      const blob = new Blob([promptText], { type: "text/plain;charset=utf-8" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = `${uuid}.txt`;
      a.click();
      URL.revokeObjectURL(url);
    };
  };
  const fnAddPromptExt = () => {
    const $h3提示词 = Array.from($na("h3")).find((el) => {
      return el.textContent?.includes("绘画提示词");
    });
    if (!$h3提示词) return;
    const $h3Parent = $h3提示词.parentElement;
    const $p = $h3Parent?.nextElementSibling;
    const fnChangePrompt = ($p2) => {
      $p2.classList.add("dzmm-sys-prompt");
      $p2.classList.add("hidden");
      const $$a = $p2.querySelectorAll("a");
      let promptText = "";
      if ($$a.length > 0) {
        $$a.forEach(($a) => {
          const linkText = $a.textContent?.trim() || "";
          promptText += linkText + ", ";
        });
      }
      else {
        promptText = $p2.textContent?.trim() || "";
      }
      let $newPromptP = $n(".dzmm-new-prompt");
      if ($newPromptP) {
        $newPromptP.textContent = promptText;
      }
      else {
        $newPromptP = document.createElement("p");
        $newPromptP.textContent = promptText;
        $newPromptP.classList.add("dzmm-new-prompt", "rounded-md", "bg-muted/60", "p-3", "leading-relaxed", "text-foreground/80");
        $h3Parent?.insertAdjacentElement("afterend", $newPromptP);
      }
      fnAddPromptExt2($h3Parent, $newPromptP);
    };
    if ($p && $p.tagName === "DIV") {
      fnChangePrompt($p);
      const observer = new MutationObserver(() => {
        fnChangePrompt($p);
      });
      observer.observe($p, { childList: true, subtree: true });
    }
  };
  const dropPanel = {
    PANEL_ID: "dzmm-drop-panel",
    $panel: null,
    $dragImg: null,
    t: null,
    hasImageFiles(event) {
      const files = event.dataTransfer?.files;
      if (!files || files.length === 0) {
        return false;
      }
      return Array.from(files).some((file) => file.type.startsWith("image/"));
    },
    ensure() {
      if (this.$panel) {
        return this.$panel;
      }
      let $panel = document.getElementById(this.PANEL_ID);
      $panel = document.createElement("div");
      $panel.className = "dzmm-drop-panel rounded-md z-55 mini";
      $panel.id = this.PANEL_ID;
      $panel.innerHTML = `
    <div class="dzmm-drop-panel-zone" data-zone="top">
        <h4>管理在线图片</h4>
        <p>根据 UUID 查看图片记录</p>
    </div>
    <div class="dzmm-drop-panel-zone" data-zone="bottom">
        <h4>页面内的图片处理</h4>
        <p>检查图片是否下载(需要配置 everything API)</p>
    </div>
`;
      document.body.appendChild($panel);
      this.$panel = $panel;
      return $panel;
    },
    getDropZone(event) {
      const $panel = this.$panel;
      if (!$panel) {
        return "top";
      }
      const rect = $panel.getBoundingClientRect();
      const isTop = event.clientY < rect.top + rect.height / 2;
      return isTop ? "top" : "bottom";
    },
  };
  const fnAddDropPanel = () => {
    if (document.body.dataset.dzmmDropPanelInit === "1") {
      return;
    }
    const $panel = dropPanel.ensure();
    document.body.addEventListener("dragstart", (event) => {
      const $target = event.target;
      dropPanel.$dragImg = $target instanceof HTMLImageElement ? $target : null;
    });
    document.body.addEventListener("dragend", () => {
      dropPanel.$dragImg = null;
    });
    const togglePanel = (to, delay = 300) => {
      dropPanel.t && clearTimeout(dropPanel.t);
      const bolToMini = to === "hide";
      $panel.classList.toggle("mini", bolToMini);
      dropPanel.t = setTimeout(() => {
        togglePanel("hide");
      }, delay);
      setTimeout(() => {
        $panel.dataset.state = to;
      }, delay);
    };
    document.body.addEventListener("dragenter", (event) => {
      event.preventDefault();
      togglePanel("show");
    });
    $panel.addEventListener("dragover", (event) => {
      event.preventDefault();
      togglePanel("show", 5e3);
    });
    $panel.addEventListener("dragleave", (event) => {
      if ($panel.dataset.state !== "show") {
        return;
      }
      const nextTarget = event.relatedTarget;
      if (!nextTarget || !$panel.contains(nextTarget)) {
        togglePanel("hide");
      }
    });
    $panel.addEventListener("drop", (event) => {
      event.preventDefault();
      const zone = dropPanel.getDropZone(event);
      if (zone === "top") {
        if (!dropPanel.hasImageFiles(event)) {
          return;
        }
        const files = Array.from(event.dataTransfer?.files || []).filter((file) => file.type.startsWith("image/"));
        const host = location.origin;
        const name = files[0].name.replace(/^.+@|\.png/g, "");
        _GM_openInTab(host + "/draw/" + name, false);
      }
      if (storeDownload.switchOn && zone === "bottom") {
        const $img = dropPanel.$dragImg;
        if ($img && $img.dataset.uuid) {
          storeDownload.isDL($img, true);
        }
      }
      dropPanel.$dragImg = null;
      togglePanel("hide");
    });
    document.body.dataset.dzmmDropPanelInit = "1";
  };
  const fnAddNavLinks = () => {
    fnAddGalleryLink();
    fnAddGenerateLink();
    fnAddHistoryLink();
    fnConvertButtonToLink();
    gob._delayRun(() => {
      if (gob.$$header.length >= 2) {
        Array.from(gob.$$header).forEach(($header) => {
          if (!$header.querySelector(".dzmm-nav-added")) {
            $header.remove();
          }
        });
      }
    });
  };
  const fnSetContainer = () => {
    if (gob.bolWidthChanged) {
      return;
    }
    setTimeout(() => {
      const $container = $n(".min-h-screen div.container");
      if (!$container) {
        return;
      }
      $container.className = "w-full space-y-2 flex-1 container max-w-6xl mx-auto p-4";
      const $grid = $container.querySelector(".grid.md\\:grid-cols-3");
      if (!$grid) {
        return;
      }
      $grid?.classList.add("lg:grid-cols-6", "width-adjusted");
    }, 1e3);
  };
  const fnInitLitePage = () => {
    fnAddNavLinks();
    fnSetContainer();
    fnAddImagePreview();
    fnAddStoreArt();
    fnAddPromptExt();
    fnAddBatchBtn();
    fnAddDropPanel();
    fnParseSoloGallery();
  };
  const mountLitePage = () => {
    console.log("lite page mounted");
    gob.enablePageObserve(() => {
      fnInitLitePage();
    });
  };
  mountLitePage();
})();