dzmm-helper

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

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         dzmm-helper
// @namespace    oninashi
// @version      1.1.0
// @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/*
// @grant        GM_addStyle
// @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 _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 gob = {
    $body: document.body,
    pageObserver: null,
    get locHref() {
      return _locHref();
    },
    get bolWidthChanged() {
      return $n("div.width-adjusted") !== null;
    },
    get $$header() {
      return $na("header");
    },
    _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;
    },
    _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,
      });
    },
  };
  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();
        }
      }
    },
    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 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 = _unsafeWindow.fetch.bind(_unsafeWindow);
  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;
  };
  _unsafeWindow.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 img.downloaded{opacity:.8;filter:brightness(.9)}div.group:has(.dzmm-art):hover .dzmm-art{flex-wrap:wrap!important}div.group:has(.dzmm-art):hover .dzmm-art>span{min-width:48%}.z-55{z-index:55}.z-60{z-index:60}.z-65{z-index:65}.z-75{z-index:75}";
  importCSS(styleCss);
  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 _isListMode = () => {
    return $na(".space-y-3").length > 0;
  };
  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) => {
    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");
      }
      if ($divGroup) {
        $divGroup.style.aspectRatio = "0.75/1.2";
      }
    }
  };
  const bindImagePreviewEvents = (getImages, $fixedDiv, clsName) => {
    const imgs = getImages();
    if (imgs.length === 0) return;
    const fistImg = imgs[0];
    const lstImgUrl = $fixedDiv.dataset.url || "";
    if (fistImg.src === lstImgUrl && fistImg.dataset.event === "set") {
      return;
    }
    $fixedDiv.dataset.url = fistImg.src;
    let t;
    const fnRemovePreview = () => {
      t = setTimeout(() => {
        $fixedDiv.classList.add("hidden");
      }, 50);
    };
    const isListMode = _isListMode();
    imgs.forEach(($img, i) => {
      $img.dataset.index = i.toString();
      if ($img.dataset.event === "set") return;
      $img.dataset.event = "set";
      if (!isListMode) {
        $img.draggable = true;
      }
      fnPromptHandle($img, isListMode);
      fnBadgeHandle($img);
      storePublic.isPublic($img);
      $img.addEventListener("mouseenter", (e) => {
        clearTimeout(t);
        fnShowImgIndex($img);
        const $preview = $n(`.${clsName} .image-preview`);
        $preview.innerHTML = `<img src="${$img.src}" class="h-full" />`;
        $fixedDiv?.appendChild($preview);
        $fixedDiv.classList.remove("hidden");
        const isLeft = isListMode || e.clientX < window.innerWidth / 2;
        if (isLeft) {
          $fixedDiv.classList.add("right-1");
          $fixedDiv.classList.remove("left-1");
        }
        else {
          $fixedDiv.classList.add("left-1");
          $fixedDiv.classList.remove("right-1");
        }
        const aspectRatio = $img.naturalWidth / $img.naturalHeight;
        if (aspectRatio >= 1) {
          $fixedDiv.classList.remove("top-1");
          $preview.querySelector("img")?.classList.remove("h-full");
        }
        else {
          $fixedDiv.classList.add("top-1");
          $preview.querySelector("img")?.classList.add("h-full");
        }
      });
      $img.addEventListener("mouseout", () => {
        fnRemovePreview();
        setTimeout(() => {
          fnShowImgIndex($img, "hide");
        }, 1500);
      });
    });
    if ($fixedDiv.dataset.event === "set") return;
    $fixedDiv.addEventListener("mousemove", () => {
      clearTimeout(t);
    });
    $fixedDiv.addEventListener("mouseleave", () => {
      fnRemovePreview();
    });
    $fixedDiv.dataset.event = "set";
  };
  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 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 fnAddImagePreview = () => {
    if (!gob._isHistoryPage() && !gob._isGeneratePage()) {
      return;
    }
    if (gob._isHistoryGallery()) {
      return;
    }
    const clsName = "dzmm-fixed-preview";
    const $fixedDiv = insertPreviewContainer(clsName);
    bindImagePreviewEvents(gob._getImages, $fixedDiv, clsName);
  };
  const fnAddNavLinks = () => {
    fnAddGenerateLink();
    fnAddHistoryLink();
    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();
  };
  const mountLitePage = () => {
    console.log("lite page mounted");
    gob.enablePageObserve(() => {
      fnInitLitePage();
    });
  };
  mountLitePage();
})();