自用辅助脚本,只适用于电脑浏览器
// ==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();
})();