dzmm-helper

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

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==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();
})();