liblib助手

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