Greasy Fork 还支持 简体中文。

liblib助手[废弃]

liblib助手,下载作者例图、返图、生成信息

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==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 });
})();