Click Download button will download the file and save the JSON and images at the same time. Also add a button to download JSON and images under details.
当前为
// ==UserScript==
// @name Civitai Text Downloader Mod
// @name:ja Civitai Text Downloader Mod
// @namespace http://tampermonkey.net/
// @version 5.3.5
// @description Click Download button will download the file and save the JSON and images at the same time. Also add a button to download JSON and images under details.
// @description:ja Downloadボタンをクリックするとファイルのダウンロードと同時にJSONと画像が保存されます。また、Detailsの下にJSONと画像をダウンロードするボタンを追加します。
// @author Takenoko3333
// @match https://civitai.com/*
// @icon https://civitai.com/favicon.ico
// @grant GM.addStyle
// @grant GM.xmlHttpRequest
// @connect civitai.com
// @license BSD
// ==/UserScript==
(function() {
'use strict';
GM.addStyle(`.ctd-button:not([data-disabled]) {color: #ffff00;}`);
let file_id = null;
let category = "";
if (typeof MutationObserver !== 'undefined') {
let lastUrl = location.href;
let observerTriggered = false;
const observer = new MutationObserver((mutations) => {
if (lastUrl !== location.href) {
lastUrl = location.href;
observerTriggered = true;
const interval = setInterval(function() {
downloadFiles();
if (file_id || category != "models" ) {
clearInterval(interval);
}
}, 200);
}
});
const config = { subtree: true, childList: true };
observer.observe(document, config);
// URL change not detected (initial access)
setTimeout(() => {
if (!observerTriggered) {
if (isFirefox()) {
runDownloadFilesForFirefox();
} else {
downloadFiles();
}
}
}, 0);
} else {
// MutationObserver is not supported
setInterval(function(){
downloadFiles();
}, 500);
}
function isFirefox() {
const isFirefoxBrowser = typeof InstallTrigger !== 'undefined';
return isFirefoxBrowser;
}
function runDownloadFilesForFirefox() {
let counter = 0;
const interval = setInterval(function() {
downloadFiles();
counter++;
if (category != "models" || counter >= 3) {
clearInterval(interval);
}
}, 500);
}
function createButton() {
const newElement = document.createElement('a');
newElement.className = 'mantine-UnstyledButton-root mantine-Button-root mantine-4fe1an json-image-download-button';
newElement.type = 'button';
newElement.setAttribute('data-button', 'true');
newElement.style.marginTop = '8px';
const innerDiv = document.createElement('div');
innerDiv.className = 'mantine-3xbgk5 mantine-Button-inner';
const innerSpan = document.createElement('span');
innerSpan.className = 'mantine-qo1k2 mantine-Button-label';
innerSpan.textContent = 'JSON and Image Download';
innerDiv.appendChild(innerSpan);
newElement.appendChild(innerDiv);
const tableElement = document.querySelector('table');
let currentElement = tableElement;
while (currentElement && !currentElement.classList.contains('mantine-Accordion-item')) {
currentElement = currentElement.parentElement;
}
if (currentElement) {
currentElement.insertAdjacentElement('afterend', newElement);
}
}
function downloadFiles() {
file_id = null
category = location.pathname.split("/")[1];
if (category != "models") return;
const codeElements = document.querySelectorAll('table code');
codeElements.forEach((element, index) => {
if (element.textContent === '@') {
if (codeElements[index + 1]) {
file_id = codeElements[index + 1].textContent;
}
}
});
const jsonImageDownloadButton = document.querySelector('.json-image-download-button');
if (file_id && !jsonImageDownloadButton) createButton();
document.querySelectorAll('main a[type^="button"]').forEach(button => {
if(!button.classList.contains("ctd-done")){
button.addEventListener("click", function(){
const modelName = document.querySelector('main h1').textContent;
const spanElements = document.querySelectorAll('table span');
let strength = null;
let _id = location.pathname.split("/")[2];
spanElements.forEach((element, index) => {
if (/^Strength:/.test(element.textContent)) {
strength = element.textContent.split(":")[1].trim();
}
});
GM.xmlHttpRequest({
method: "GET",
url: "https://civitai.com/api/v1/models/" + _id,
onload: function(response) {
let j = JSON.parse(response.responseText);
let file = j.modelVersions.find(x => x.id == file_id);
let link = document.createElement('a');
let text = {
"description": "",
"model name": modelName,
"model url": document.URL,
"base model": file.baseModel,
"sd version": "Unknown",
"activation text": "",
"preferred weight": 0,
"notes": document.URL + "\nModel name: " + modelName + "\nBase model: " + file.baseModel
};
if (/^SD 1/.test(file.baseModel)) {
text["sd version"] = "SD1";
} else if (/^SD 2/.test(file.baseModel)) {
text["sd version"] = "SD2";
} else if (/^SDXL/.test(file.baseModel) || /^Pony/.test(file.baseModel)) {
text["sd version"] = "SDXL";
} else if (/^SD 3/.test(file.baseModel)) {
text["sd version"] = "SD3";
}
if (j.description && j.description.textContent) {
text.description = j.description.textContent;
}
if (file.trainedWords) {
text["activation text"] = file.trainedWords.join(" ");
}
if (strength) {
text["preferred weight"] = strength;
}
text = [JSON.stringify(text)];
link.href = window.URL.createObjectURL(new Blob(text));
let filename = file.files.find(x => x).name || file_id + ".json";
filename = filename.replace(/\.[a-z]*$/, ".json")
link.download = filename;
link.click();
let image = file.images.find(x =>x.type === 'image');
if (image) {
GM.xmlHttpRequest({
method: "GET",
url: image.url,
responseType: "blob",
onload: function (response) {
let dlLink = document.createElement("a");
const dataUrl = URL.createObjectURL(response.response);
dlLink.href = dataUrl;
let suffix = "." + image.url.slice(image.url.lastIndexOf('.') + 1).toLowerCase();
if (suffix === ".jpeg") {
suffix = ".jpg";
}
filename = filename.replace(".json", suffix)
dlLink.download = filename;
document.body.insertAdjacentElement("beforeEnd", dlLink);
dlLink.click();
dlLink.remove();
setTimeout(function () {
window.URL.revokeObjectURL(dataUrl);
}, 1000);
}
});
}
}
});
});
if (file_id && !jsonImageDownloadButton) button.classList.add("ctd-button");
button.classList.add("ctd-done");
}
});
}
})();