您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays Stable Diffusion metadata generated as an overlay on Discord images.
当前为
// ==UserScript== // @name Stable Diffusion Metadata Discord Image Overlay // @namespace http://tampermonkey.net/ // @version 0.1 // @description Displays Stable Diffusion metadata generated as an overlay on Discord images. // @author moony // @icon https://iconarchive.com/icons/ccard3dev/dynamic-yosemite/256/Preview-icon.png // @match https://discord.com/* // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/exif-reader.min.js // @license MIT // @grant GM_xmlhttpRequest // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; function readExif(url) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: url, responseType: "arraybuffer", onload: (response) => { const fileBuffer = response.response; const tags = ExifReader.load(fileBuffer, { expanded: true }); const prompt = getPromptFromTags(tags); resolve(prompt); }, onerror: (error) => { reject(error); } }); }); } function getPromptFromTags(tags) { let com = ""; if (tags.exif && tags.exif.UserComment) { com = decodeUnicode(tags.exif.UserComment.value); return com; } if (!tags.pngText) return ""; if (tags.pngText.parameters) { com = tags.pngText.parameters.description; return com; } if (tags.pngText.Dream) { com = tags.pngText.Dream.description; com += tags.pngText["sd-metadata"] ? "\r\n" + tags.pngText["sd-metadata"].description : ""; return com; } if (tags.pngText.Software && tags.pngText.Software.description == "NovelAI") { const positive = tags.pngText.Description.description; const negative = tags.pngText.Comment.description.replaceAll(/\\u00a0/g, " ").match(/"uc": "([^]+)"[,}]/)[1]; let others = tags.pngText.Comment.description.replaceAll(/\\u00a0/g, " ") + "\r\n"; others += tags.pngText.Software.description + "\r\n"; others += tags.pngText.Title.description + "\r\n"; others += tags.pngText.Source.description; const prompt = { positive: positive, negative: negative, others: others }; return JSON.stringify(prompt); } Object.keys(tags.pngText).forEach(tag => { com += tags.pngText[tag].description; }); return com; } function decodeUnicode(array) { const plain = array.map(t => t.toString(16).padStart(2, "0")).join(""); if (!plain.match(/^554e49434f44450/)) { return ""; } const hex = plain.replace(/^554e49434f44450[0-9]/, "").replace(/[0-9a-f]{4}/g, ",0x$&").replace(/^,/, ""); const arhex = hex.split(","); let decode = ""; arhex.forEach(v => { decode += String.fromCodePoint(v); }); return decode; } // Main Function to retrieve prompt from URL async function getExif(url) { try { const result = await readExif(url); return result; } catch (error) { console.error(error); return ''; } } // Function to process the URL and return the shortened version async function processUrl(url, maxWidth) { const cleanUrl = url.split('?')[0]; const text = await getExif(cleanUrl); let truncatedText = ''; let words = text.split(' '); // console.log(text); for (let word of words) { if ((truncatedText + word).length > maxWidth) { truncatedText += '\n'; } truncatedText += word + ' '; } return truncatedText.trim(); } // Function to add text overlay with URL to a given image async function addTextOverlayWithUrl(img) { // Create a new div to hold the image and the text let wrapper = document.createElement('div'); wrapper.style.position = 'relative'; wrapper.style.display = 'inline-block'; // Create a new div for the text overlay let textOverlay = document.createElement('div'); textOverlay.className = 'text-overlay'; // Create a span element for the URL text let urlText = document.createElement('span'); urlText.textContent = await processUrl(img.src, img.clientWidth); // Wait for the promise to resolve // Insert the new elements img.parentNode.insertBefore(wrapper, img); wrapper.appendChild(textOverlay); wrapper.appendChild(img); textOverlay.appendChild(urlText); } // Function to check for new images and add text overlay with URL async function checkForNewImages() { let images = document.querySelectorAll('.imageWrapper-oMkQl4 img'); // Loop through each image for (let img of images) { // Check if the image already has a text overlay if (!img.parentNode.classList.contains('textOverlayAdded')) { // Add text overlay with URL to new image await addTextOverlayWithUrl(img); // Wait for the promise to resolve img.parentNode.classList.add('textOverlayAdded'); } } } // Wait 5 sec for page loads setTimeout(() => setInterval(checkForNewImages, 2000), 5000); GM_addStyle(` .text-overlay { position: absolute; top: 0; left: 0; width: 100%; background-color: rgba(0, 0, 0, 0.5); padding: 5px; color: white; font-family: sans-serif; font-size: 12px; word-wrap: break-word; white-space: pre-wrap; } .text-overlay span { color: white; text-decoration: none; } `); })();