Greasy Fork is available in English.
liblib助手,下载作者例图、返图、生成信息
// ==UserScript== // @name liblib助手 // @namespace http://tampermonkey.net/ // @version 1.6.2 // @description liblib助手,下载作者例图、返图、生成信息 // @author kaiery // @match https://www.liblib.ai/modelinfo/* // @match https://www.liblib.art/modelinfo/* // @grant none // @license MIT License // ==/UserScript== (function() { 'use strict'; // 定义全局变量 var modelDir; var textDesc, uuid, buildId, webid, modelId, modelName, modelVersionId, downloadUrl; var page = 1; var pageSize = 16; var sortType = 0; const default_download_pic_num = 100; // --------------------------------------------------------------- // demo // --------------------------------------------------------------- async function createDirectory() { // open directory picker const dirHandle = await window.showDirectoryPicker({mode:"readwrite"}); // create a new directory named 'newDir' const newDirHandle = await dirHandle.getDirectoryHandle('newDir', {create: true}); console.log(newDirHandle); } // --------------------------------------------------------------- // html转文本 // --------------------------------------------------------------- function htmlToText(html) { var tempDiv = document.createElement('div'); tempDiv.innerHTML = html; var text = ''; for (var i = 0; i < tempDiv.childNodes.length; i++) { if (tempDiv.childNodes[i].nodeName === 'P') { text += tempDiv.childNodes[i].textContent + '\n'; } } return text; } // --------------------------------------------------------------- // 保存作者图片信息 // --------------------------------------------------------------- async function saveAuthImagesInfo() { var modelType = 1; // 1:CheckPoint 2:embedding;3:HYPERNETWORK ;4:AESTHETIC GRADIENT; 5:Lora;6:LyCORIS; 9:WILDCARDS var hasTriggerWord = false; // open directory picker const dirHandle = await window.showDirectoryPicker({mode:"readwrite"}); // 根据选项卡获取模型版本id const div = document.querySelector('.ant-tabs-tab.ant-tabs-tab-active'); const modelVersionId = parseInt(div.getAttribute('data-node-key')); const modelVer = div.innerText.replace(/ /g, "").replace(/[/\\?%*:|"<>]/g, ''); var allElements = document.querySelectorAll('div'); allElements.forEach(function(element) { var classNames = element.className.split(/\s+/); for (var i = 0; i < classNames.length; i++) { if (classNames[i].startsWith('ModelDescription_desc')) { textDesc = htmlToText(element.innerHTML); textDesc = textDesc.replace(/\\n/g, '\n'); break; } } }); if(textDesc){ // Get the content of the script element var scriptContent = document.getElementById('__NEXT_DATA__').textContent; var scriptJson = JSON.parse(scriptContent); // Extract uuid, buildId, and webid uuid = scriptJson.query.uuid; buildId = scriptJson.buildId; webid = scriptJson.props.webid; //------------ // 预请求地址 var url_acceptor = "https://liblib-api.vibrou.com/api/www/log/acceptor/f"; // 模型信息地址 var url_model = "https://liblib-api.vibrou.com/api/www/model/getByUuid/" + uuid; // 发送预请求------------------------------------------------------- const resp_acc = await fetch(url_acceptor, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({timestamp: Date.now()}) }) // 发送模型信息 const resp = await fetch(url_model, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({timestamp: Date.now()}) }) const model_data = await resp.json(); // console.log("----------模型信息-----------"); // console.log(model_data); if(model_data.code!==0){ return;} modelId = model_data.data.id modelName = model_data.data.name.replace(/ /g, "").replace(/[/\\?%*:|"<>]/g, ''); modelDir = modelName; modelName = modelDir+"_"+modelVer; if(modelName.slice(-1)==='.'){ modelName = modelName.substring(0, modelName.length -1); } modelType = model_data.data.modelType // 1:CheckPoint 2:embedding;3:HYPERNETWORK ;4:AESTHETIC GRADIENT; 5:Lora;6:LyCORIS; 9:WILDCARDS var modelTypeName = '未分类' switch (modelType){ case 1: modelTypeName = 'CheckPoint' hasTriggerWord = false break; case 2: modelTypeName = 'embedding' hasTriggerWord = true break; case 3: modelTypeName = 'HYPERNETWORK' hasTriggerWord = true break; case 4: modelTypeName = 'AESTHETIC GRADIENT' hasTriggerWord = true break; case 5: modelTypeName = 'Lora' hasTriggerWord = true break; case 6: modelTypeName = 'LyCORIS' hasTriggerWord = true break; case 9: modelTypeName = 'WILDCARDS' hasTriggerWord = true break; } // console.log(modelDir+"/"+modelName); const versions = model_data.data.versions; for (const verItem of versions){ // 匹配版本号 if(verItem.id === modelVersionId){ // 模型信息json信息 var modelInfoJson = { modelType:modelTypeName, description: textDesc, uuid: uuid, buildId: buildId, webid: webid }; var triggerWord = '无'; if(hasTriggerWord){ if('triggerWord' in verItem && verItem.triggerWord){ triggerWord = verItem.triggerWord modelInfoJson.triggerWord = triggerWord } } // 创建模型目录 const modelDirHandle = await dirHandle.getDirectoryHandle(modelDir, {create: true}); // 创建模型版本目录 const modelVerDirHandle = await modelDirHandle.getDirectoryHandle(modelName, {create: true}); // 获取文件句柄 const savejsonHandle = await modelDirHandle.getFileHandle(modelName+".json", { create: true }); // 写入模型信息json文件 const writablejson = await savejsonHandle.createWritable(); await writablejson.write(JSON.stringify(modelInfoJson)); await writablejson.close(); const authImages = verItem.imageGroup.images; let isCover = false; const numberInput1 = document.getElementById('numberInput1'); numberInput1.setAttribute('value', authImages.length); numberInput1.dispatchEvent(new Event('change')); var count = 0; for(const authImage of authImages){ const authImageUrl = authImage.imageUrl; var authimageName = authImage.id; var authimageExt = authImageUrl.split("/").pop().split(".").pop(); var tmp = authimageExt.indexOf("?"); if (tmp>0){ authimageExt = authimageExt.substring(0,tmp); } const authImageUuid = authImage.uuid; if(!isCover){ // 下载封面图片 isCover = true; // 下载图片 const resp_download = await fetch(authImageUrl); const blob = await resp_download.blob(); // 获取文件句柄 const picHandle = await modelDirHandle.getFileHandle(modelName+"."+authimageExt, { create: true }); // 写入图片 const writable = await picHandle.createWritable(); await writable.write(blob); await writable.close(); } // 下载图片 const resp_download = await fetch(authImageUrl); const blob = await resp_download.blob(); // 获取文件句柄 const picHandle = await modelVerDirHandle.getFileHandle(authimageName+"."+authimageExt, { create: true }); // 写入图片 const writable = await picHandle.createWritable(); await writable.write(blob); await writable.close(); // 查看图片生成信息地址 var url_img_generate = "https://liblib-api.vibrou.com/api/www/img/generate/"+authImageUuid+"?timestamp="+Date.now(); // 请求图片生成信息 const response_img_gen = await fetch(url_img_generate, { method: 'POST', headers: { 'Content-Type': 'application/json' } }) const data_img_gen = await response_img_gen.json(); if(data_img_gen.code===0){ var metainformation = data_img_gen.data.metainformation; if(!metainformation){ metainformation = 'prompt:'+data_img_gen.data.prompt +"\n"; metainformation = metainformation + 'negativePrompt:'+data_img_gen.data.negativePrompt +"\n"; metainformation = metainformation + 'modelNames:'+data_img_gen.data.modelNames +"\n"; metainformation = metainformation + 'seed:'+data_img_gen.data.seed +"\n"; metainformation = metainformation + 'samplingMethod:'+data_img_gen.data.samplingMethod +"\n"; metainformation = metainformation + 'samplingStep:'+data_img_gen.data.samplingStep +"\n"; metainformation = metainformation + 'cfgScale:'+data_img_gen.data.cfgScale +"\n"; } // console.log(metainformation); // 获取文件句柄 const savefileHandle = await modelVerDirHandle.getFileHandle(authimageName+".json", { create: true }); // 写入文件 const writablefile = await savefileHandle.createWritable(); await writablefile.write(metainformation); await writablefile.close(); } count++; const numberInput1 = document.getElementById('numberInput1'); numberInput1.setAttribute('value', authImages.length-count); numberInput1.dispatchEvent(new Event('change')); } } } } alert("作者图例信息下载完成"); } // --------------------------------------------------------------- // 保存返图信息 // --------------------------------------------------------------- async function saveReturnImagesInfo() { // open directory picker const dirHandle = await window.showDirectoryPicker({mode:"readwrite"}); // 根据选项卡获取模型版本id const div = document.querySelector('.ant-tabs-tab.ant-tabs-tab-active'); const modelVersionId = parseInt(div.getAttribute('data-node-key')); const modelVer = div.innerText.replace(/ /g, "").replace(/[/\\?%*:|"<>]/g, ''); // Get the content of the script element var scriptContent = document.getElementById('__NEXT_DATA__').textContent; var scriptJson = JSON.parse(scriptContent); // Extract uuid, buildId, and webid uuid = scriptJson.query.uuid; //------------ // 预请求地址 var url_acceptor = "https://liblib-api.vibrou.com/api/www/log/acceptor/f"; // 模型信息地址 var url_model = "https://liblib-api.vibrou.com/api/www/model/getByUuid/" + uuid; // 评论列表地址 var url_community = "https://liblib-api.vibrou.com/api/www/community/returnPicList?timestamp="+Date.now(); // 发送预请求------------------------------------------------------- const resp_acc = await fetch(url_acceptor, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({timestamp: Date.now()}) }) // 发送模型信息 const resp = await fetch(url_model, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({timestamp: Date.now()}) }) const model_data = await resp.json(); // console.log("----------模型信息-----------"); // console.log(model_data); if(model_data.code!==0){ return;} modelId = model_data.data.id modelName = model_data.data.name.replace(/ /g, "").replace(/[/\\?%*:|"<>]/g, ''); // modelName = modelName+"_返图"; modelDir = modelName; modelName = modelDir+"_"+modelVer; if(modelName.slice(-1)==='.'){ modelName = modelName.substring(0, modelName.length -1); } // 创建模型目录 const modelDirHandle = await dirHandle.getDirectoryHandle(modelDir, {create: true}); // 创建一个返图目录 const newDirHandle = await modelDirHandle.getDirectoryHandle(modelName, {create: true}); let count = 0; var number = 0; const numberInput2 = document.getElementById('numberInput2'); number = parseInt(numberInput2.value); if(number> returnNum){ number = returnNum; } while (true) { // 请求回图列表 const response = await fetch(url_community, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ page: page, pageSize: pageSize, sortType: sortType, uuid: uuid }) }); // 解析JSON数据 const data = await response.json(); // console.log(data); if(data.code===0){ var datalist = data.data.dataList; var returnNum = data.data.returnNum; for(var i=0;i<datalist.length;i++){ var commItem = datalist[i]; var pics = commItem.pics; for(var j=0;j<pics.length;j++){ var picItem = pics[j]; var picUuid = picItem.uuid; var imageUrl = picItem.imageUrl; var imageName = picItem.id; var imageExt = imageUrl.split("/").pop().split(".").pop(); var tmp = imageExt.indexOf("?"); if (tmp>0){ imageExt = imageExt.substring(0,tmp); } // 下载图片 const resp_download = await fetch(imageUrl); const blob = await resp_download.blob(); // 获取文件句柄 // console.log(imageName+"."+imageExt); const picHandle = await newDirHandle.getFileHandle(imageName+"."+imageExt, { create: true }); // 写入文件 const writable = await picHandle.createWritable(); await writable.write(blob); await writable.close(); // 查看图片生成信息地址 var url_img_generate = "https://liblib-api.vibrou.com/api/www/img/generate/"+picUuid+"?timestamp="+Date.now(); // 请求图片生成信息 const response_img_gen = await fetch(url_img_generate, { method: 'POST', headers: { 'Content-Type': 'application/json' } }) const data_img_gen = await response_img_gen.json(); if(data_img_gen.code===0){ var metainformation = data_img_gen.data.metainformation; if(!metainformation){ metainformation = 'prompt:'+data_img_gen.data.prompt +"\n"; metainformation = metainformation + 'negativePrompt:'+data_img_gen.data.negativePrompt +"\n"; metainformation = metainformation + 'modelNames:'+data_img_gen.data.modelNames +"\n"; metainformation = metainformation + 'seed:'+data_img_gen.data.seed +"\n"; metainformation = metainformation + 'samplingMethod:'+data_img_gen.data.samplingMethod +"\n"; metainformation = metainformation + 'samplingStep:'+data_img_gen.data.samplingStep +"\n"; metainformation = metainformation + 'cfgScale:'+data_img_gen.data.cfgScale +"\n"; } // console.log(metainformation); // 获取文件句柄 const savefileHandle = await newDirHandle.getFileHandle(imageName+".json", { create: true }); // 写入文件 const writablefile = await savefileHandle.createWritable(); await writablefile.write(metainformation); await writablefile.close(); } count ++; const numberInput2 = document.getElementById('numberInput2'); numberInput2.setAttribute('value', number-count); numberInput2.dispatchEvent(new Event('change')); // 如果已经获取了所有数据,就跳出循环 if (count >= number) { alert("返图信息下载完成"); const numberInput2 = document.getElementById('numberInput2'); numberInput2.setAttribute('value', default_download_pic_num); numberInput2.dispatchEvent(new Event('change')); return; } } } } // 增加page以获取下一页的数据 page++; } } // 定义元素------------------------------------ var div1 = document.createElement('div'); div1.style.display = 'flex'; div1.style.justifyContent="space-between"; div1.style.alignItems = "center"; var button1 = document.createElement('button'); button1.textContent = '下载作者图例+生成信息'; button1.onclick = saveAuthImagesInfo; button1.style.padding = '10px'; button1.style.width = "200px"; button1.style.backgroundColor = 'red'; button1.style.color = 'white'; button1.style.display = 'none'; button1.style.flex = "1"; const span1 = document.createElement('span'); span1.textContent = '数量:'; span1.style.marginLeft = "8px"; const numberInput1 = document.createElement('input'); numberInput1.setAttribute('type', 'number'); numberInput1.setAttribute('id', 'numberInput1'); numberInput1.setAttribute('value', 0); numberInput1.style.display = 'none'; numberInput1.style.border = "1px solid"; numberInput1.style.textAlign = "center"; numberInput1.style.width = "80px"; numberInput1.style.height = "38px"; numberInput1.disabled = true; div1.appendChild(button1); div1.appendChild(span1); div1.appendChild(numberInput1); //---------------------------------------------- var div2 = document.createElement('div'); div2.style.display = 'flex'; div2.style.justifyContent="space-between"; div2.style.alignItems = "center"; div2.style.margin = "2px 0"; var button2 = document.createElement('button'); button2.textContent = '下载返图图片+生成信息'; button2.onclick = saveReturnImagesInfo; button2.style.padding = '10px'; button2.style.width = "200px"; button2.style.backgroundColor = 'blue'; button2.style.color = 'white'; button2.style.display = 'none'; button2.style.flex = "1"; const span2 = document.createElement('span'); span2.textContent = '数量:'; span2.style.marginLeft = "8px"; const numberInput2 = document.createElement('input'); numberInput2.setAttribute('type', 'number'); numberInput2.setAttribute('id', 'numberInput2'); numberInput2.setAttribute('value', default_download_pic_num); numberInput2.style.display = 'none'; numberInput2.style.border = "1px solid"; numberInput2.style.textAlign = "center"; numberInput2.style.width = "80px"; numberInput2.style.height = "38px"; div2.appendChild(button2); div2.appendChild(span2); div2.appendChild(numberInput2); // 监听 var observer = new MutationObserver(function(mutations) { var found = false; mutations.forEach(function(mutation) { if (mutation.type === 'childList' && !found) { var allElements = document.querySelectorAll('div'); allElements.forEach(function(element) { var classNames = element.className.split(/\s+/); for (var i = 0; i < classNames.length; i++) { if (classNames[i].startsWith('ModelDescription_desc')) { found = true; observer.disconnect(); // 停止观察 var actionCard = document.querySelector('[class^="ModelActionCard_modelActionCard"]'); if (actionCard) { actionCard.parentNode.insertBefore(div2, actionCard); actionCard.parentNode.insertBefore(div1, div2); button1.style.display = 'block'; numberInput1.style.display = 'block'; button2.style.display = 'block'; numberInput2.style.display = 'block'; } break; } } }); } }); }); observer.observe(document.body, { childList: true, subtree: true }); })();