自用辅助脚本,只适用于电脑浏览器
// ==UserScript==
// @name dzmm-helper
// @namespace oninashi
// @version 1.2.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 GM_getValue
// @grant GM_setValue
// @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_setValue = (() => typeof GM_setValue != "undefined" ? GM_setValue : 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 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 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 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 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) {
console.log("Loaded arts:", arts);
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();
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) => {
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 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();
storePublic.isPublic($img);
if ($img.dataset.event === "set") return;
$img.dataset.event = "set";
if (!isListMode) {
$img.draggable = true;
}
fnPromptHandle($img, isListMode);
fnBadgeHandle($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 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 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 fnAddStoreArt = () => {
if (!gob._isHistoryPage() && !gob._isGeneratePage() && !gob._isDrawPage()) {
return;
}
const clsName = "dzmm-store-art-btn";
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 $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", "px-2", "py-1.5", "text-sm", "rounded-full", "bg-muted", "hidden");
$subNav.insertAdjacentElement("beforeend", $input);
$subNav.insertAdjacentElement("beforeend", $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;
const _ToggleInput = (to) => {
const flagFocus = $input.dataset.focus === "true";
if (to === "show") {
clearTimeout(t);
$input.classList.remove("hidden");
$input.focus();
$input.dataset.focus = "true";
}
else {
$input.blur();
if (flagFocus) return;
t = setTimeout(() => {
$input.classList.add("hidden");
}, 500);
}
};
const $parent = $subNav.parentElement;
$parent?.addEventListener("mouseenter", () => {
_ToggleInput("show");
});
$parent?.addEventListener("mouseleave", () => {
_ToggleInput("hide");
});
$btn.addEventListener("click", () => {
fnSubmitArt();
});
$input.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
fnSubmitArt();
}
});
};
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);
}
};
if ($p && $p.tagName === "DIV") {
fnChangePrompt($p);
const observer = new MutationObserver(() => {
fnChangePrompt($p);
});
observer.observe($p, { childList: true, subtree: true });
}
};
const fnAddNavLinks = () => {
fnAddGalleryLink();
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();
fnAddStoreArt();
fnAddPromptExt();
};
const mountLitePage = () => {
console.log("lite page mounted");
gob.enablePageObserve(() => {
fnInitLitePage();
});
};
mountLitePage();
})();