Click the Download button to save the JSON and images. 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.4
// @description Click the Download button to save the JSON and images. 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 none
// @license BSD
// ==/UserScript==
(function() {
'use strict';
// initial access
let file_id = null;
let category = "";
downloadFiles();
// Processing at page transitions
if (typeof MutationObserver !== 'undefined') {
let lastUrl = location.href;
const observer = new MutationObserver((mutations) => {
if (lastUrl !== location.href) {
lastUrl = location.href;
const interval = setInterval(function() {
downloadFiles();
if (file_id || category != "models" ) {
clearInterval(interval);
}
}, 200);
}
});
const config = { subtree: true, childList: true };
observer.observe(document, config);
} else {
// MutationObserver is not supported
setInterval(function(){
downloadFiles();
}, 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"]:not([href])').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();
}
});
fetch("https://civitai.com/api/v1/models/" + _id).then(x => x.json()).then(j => {
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);
if(image){
let xhr = new XMLHttpRequest();
let src = image.url;
let suffix = "." + src.slice(src.lastIndexOf('.') + 1);
suffix = ".png"; // URLの拡張子がjpegになってても実際にimage.civitai.comが返す画像はpngっぽいのでハードコーディングで決め打ち
xhr.open('GET', src, true);
xhr.responseType = "blob";
xhr.onload = function () {
let dlLink = document.createElement("a");
const dataUrl = URL.createObjectURL(this.response);
dlLink.href = dataUrl;
filename = filename.replace(".json", suffix)
dlLink.download = filename;
document.body.insertAdjacentElement("beforeEnd", dlLink);
dlLink.click();
dlLink.remove();
setTimeout(function () {
window.URL.revokeObjectURL(dataUrl);
}, 1000);
};
xhr.send();
}
});
});
button.style.color = "#ffff00";
button.classList.add("ctd-done");
}
});
}
})();