v1.5
parent
0056e47de0
commit
0cff65be7c
63
README.cn.md
63
README.cn.md
|
|
@ -3,23 +3,31 @@ Stable Diffusion Webui 扩展Civitai助手,用于更轻松的管理和使用Ci
|
|||
|
||||
[Civitai Url](https://civitai.com/models/16768/civitai-helper-sd-webui-civitai-extension)
|
||||
|
||||
# 注意
|
||||
在安装或更新新版本之后,需要整个关闭SD Webui,重新启动它。光是Reload UI对本插件不起作用。
|
||||
|
||||
# 功能
|
||||
* 扫描所有模型,从Civitai下载模型信息和预览图
|
||||
* 通过civitai模型的页面url,连接一个本地模型和civitai模型的信息
|
||||
* 通过civitai模型页面url,连接本地模型和civitai模型信息
|
||||
* 通过Civitai模型页面url,下载模型(含信息和预览图)到SD目录或子目录。
|
||||
* 下载支持断点续传
|
||||
* 批量检查本地模型,在civitai上的新版本
|
||||
* 直接下载新版本模型到SD模型目录内(含信息和预览图)
|
||||
* 修改了内置的"Extra Network"模型卡片,每个卡片增加了如下功能按钮:
|
||||
- 🖼: 修改文字"replace preview"为这个图标
|
||||
- 🌐: 在新标签页打开这个模型的Civitai页面
|
||||
- 💡: 一键添加这个模型的触发词到关键词输入框
|
||||
- 🏷: 一键使用这个模型预览图所使用的关键词
|
||||
* 以上额外功能按钮支持thumbnail模式
|
||||
* 增加一直显示按钮的选项,以供触屏用户使用
|
||||
|
||||
|
||||
# 安装
|
||||
下载本项目为zip文件,解压到`你的SD webui目录/extensions`下即可。
|
||||
|
||||
然后使用设置页面的"Reload UI"按钮重新加载UI。
|
||||
然后整个关闭SD Webui,重新启动它。只是Reload UI不起作用。以后更新也是,必须重启SD Webui。
|
||||
|
||||
(不了解git的国内用户,请勿通过SD webui的插件界面安装或升级。
|
||||
它安装的时候,是调用你本地的git命令行工具来下载,不是通过浏览器下载。你的git工具没有配置过代理和SSL的话,就会下载失败)
|
||||
(如果用SD webui的插件界面安装,请先给git配置代理。它不是通过浏览器下载,是通过git下载。)
|
||||
|
||||
|
||||
# 使用方法
|
||||
|
|
@ -67,12 +75,19 @@ Stable Diffusion Webui 扩展Civitai助手,用于更轻松的管理和使用Ci
|
|||
每次当Extra Network刷新,他都会删除掉额外的修改,我们的按钮就会消失。这时你就需要点击`Refresh Civitai Helper`把这些功能添加回去。
|
||||
|
||||
|
||||
## 根据URL获取1个模型信息
|
||||
如果无法在civitai上找到你的模型的SHA256,但你还是希望能把你的模型连接到一个civitai模型,你可以在本扩展页面,从列表中选择你的模型,并提供一个civitai模型页面的url。
|
||||
### 小图模式
|
||||
以上功能按钮支持小图模式,但受制于SD Webui的CSS问题,目前,只能要么一直显示,要么一直不显示,不能鼠标滑过才显示。
|
||||

|
||||
|
||||
点击按钮之后,扩展就会下载那个civitai模型的信息,作为你这个本地模型的信息使用。
|
||||
## 下载
|
||||
通过Civitai模型页面Url下载模型,要3个步骤:
|
||||
* 填入url,点击按钮获取模型信息
|
||||
* 扩展会自动填入模型名称和类型,你需要选择下载的子目录和模型版本。
|
||||
* 点击下载
|
||||

|
||||
|
||||

|
||||
下载过程会显示在命令行界面带个进度条。
|
||||
支持断点续传,无畏大文件。
|
||||
|
||||
|
||||
## 批量检查模型新版本
|
||||
|
|
@ -85,10 +100,30 @@ Stable Diffusion Webui 扩展Civitai助手,用于更轻松的管理和使用Ci
|
|||
|
||||
**检查完毕之后**,就会如下图,在UI上显示所有找到的新版本的信息。
|
||||
|
||||
每个模型新版本,都有2个链接。第一个是这个模型的网页。第二个是这个新版本的下载地址。
|
||||
每个模型新版本,都有3个链接。
|
||||
* 第一个是这个模型的网页。
|
||||
* 第二个是这个新版本的下载地址。
|
||||
* 第三个是个按钮,在python端,直接下载新版本到模型目录内。
|
||||
这种方式下载,下载详情显示在"Download Model"的区域和命令行窗口中。一次一个任务,不支持多任务。
|
||||

|
||||
|
||||
|
||||
|
||||
## 根据URL获取模型信息
|
||||
如果无法在civitai上找到你的模型的SHA256,但你还是希望能把你的模型连接到一个civitai模型,你可以在本扩展页面,从列表中选择你的模型,并提供一个civitai模型页面的url。
|
||||
|
||||
点击按钮之后,扩展就会下载那个civitai模型的信息,作为你这个本地模型的信息使用。
|
||||
|
||||

|
||||
|
||||
|
||||
## 其他设置
|
||||
**保存设置按钮, 会保存扫描模型区域,以及其他设置 这两个区域的选项**
|
||||
|
||||
* "一直显示按钮" 是为了方便触屏。
|
||||
* "小图模式显示功能按钮" 会开关功能按钮在小图模式的显示
|
||||

|
||||
|
||||
## 预览图
|
||||
Extra Network支持两种预览图命名:`model_name.png` 和 `model_name.preview.png`。其中,`model_name.png`优先级较高。
|
||||
|
||||
|
|
@ -116,12 +151,18 @@ civitai不是每个图片都有关键词,一个模型中,也不是所有预
|
|||
|
||||
|
||||
|
||||
## Civitai本身挂掉
|
||||
## Civitai API失效
|
||||
Civitai在面临类似DDos的问题的时候,会把整个网站立刻置于Cloudflare验证机制的保护下,包括API的接口。于是,API请求,就会被跳转到Cloudflare的真人验证页面而无法获取任何信息。
|
||||
|
||||
这种情况,请耐心等待Civitai恢复之后,再使用需要连接Civitai的功能。根据以往经验,每次Civitai这样折腾一轮要6-8小时。
|
||||
这种情况,请耐心等待Civitai恢复之后,再连接Civitai。根据以往经验,每次Civitai这样折腾一轮要6-8小时。
|
||||
|
||||
|
||||
## 新特性
|
||||
从v1.5开始,v1.x不再接受任何新特性。所有新特性进入2.x。
|
||||
|
||||
2.x专注于自定义模型信息,并可能改名为"Model Info Helper"。因为不再是专注Civitai了。
|
||||
|
||||
从v1.5开始。v1.x进入维护阶段。
|
||||
|
||||
Enjoy!
|
||||
|
||||
|
|
|
|||
73
README.md
73
README.md
|
|
@ -2,7 +2,7 @@
|
|||
[中文](README.cn.md)
|
||||
|
||||
# Notice
|
||||
After updating to new version, you need to shutdown SD webui and re-launch. Just Reload UI won't work!
|
||||
After install or update to new version, you need to shutdown SD webui and re-launch. Just Reload UI won't work!
|
||||
|
||||
# Stable-Diffusion-Webui-Civitai-Helper
|
||||
Stable Diffusion Webui Extension for Civitai, to handle your models much more easily.
|
||||
|
|
@ -12,12 +12,17 @@ Civitai: [Civitai Url](https://civitai.com/models/16768/civitai-helper-sd-webui-
|
|||
# Features
|
||||
* Scans all models to download model information and preview images from Civitai.
|
||||
* Link 1 model to a civitai model by civitai model's url
|
||||
* Checking all your local model's new version from civitai
|
||||
* Download a model(with info+preview) by Civitai Url into SD's model folder or subfolder.
|
||||
* Downloading can resume from break-point, which is good for large file.
|
||||
* Checking all your local model's new version from Civitai
|
||||
* Download a new version directly into SD model folder (with info+preview)
|
||||
* Modified Built-in "Extra Network" cards, to add the following buttons on each card:
|
||||
- 🖼: Modified "replace preview" text into this icon
|
||||
- 🌐: Open this model's Civitai url in a new tab
|
||||
- 💡: Add this model's trigger words to prompt
|
||||
- 🏷: Use this model's preview image's prompt
|
||||
* Also support thumbnail mode of Extra Network
|
||||
* Option to always show addtional buttons, so now they work with touch screen.
|
||||
|
||||
|
||||
# Install
|
||||
|
|
@ -26,7 +31,7 @@ Copy this project's url into it, click install.
|
|||
|
||||
Alternatively, download this project as a zip file, and unzip it to `Your SD webui folder/extensions`.
|
||||
|
||||
Then reload UI with "Reload UI" Button in Setting tab.
|
||||
Then shutdown SD Webui and Relaunch it. Just "Reload UI" won't work for this extension.
|
||||
|
||||
Done.
|
||||
|
||||
|
|
@ -74,13 +79,20 @@ Move your mouse on to the bottom of a model card. It will show 4 icon buttons:
|
|||

|
||||
Everytime after Extra Network tab refreshed, it will remove all these additional buttons. So, you need to click `Refresh Civitai Helper` button to bring them back.
|
||||
|
||||
## Get 1 Model Info By Url
|
||||
If a model's SHA256 can not be found in civitai, but you still want to link it to a civitai model. You can choose this model from list, then offer a civitai model page's url you want to link.
|
||||
### Thumbnail Mode
|
||||
Additional buttons work on thumbnail too, but due to SD webui's CSS issue, for now, they must be always displayed on thumbnail or don't display at all.
|
||||

|
||||
|
||||
After clicking button, extension will download that civitai model's model info for this local model file you picked.
|
||||
|
||||

|
||||
## Download
|
||||
To download a model by Civitai Model Page's Url, you need 3 steps:
|
||||
* Fill url, click button to get model info
|
||||
* It will show model name and type automatically. Just choose sub-folder and model version
|
||||
* Click download.
|
||||

|
||||
|
||||
Detail will be displayed on console log, with a progress bar.
|
||||
Downloading can resume from break-point, so no fear for large file.
|
||||
|
||||
## Checking Model's New Version
|
||||
You can checking your local model's new version from civitai by model types. You can select multiple model types.
|
||||
|
|
@ -92,11 +104,30 @@ This is to protect Civitai from facing issue like DDos from this extension. Some
|
|||
|
||||
**After checking process done**, it will display all new version's information on UI.
|
||||
|
||||
There are 2 urls for each new version. First one is model's page. Second one is this version's download url.
|
||||
There are 3 urls for each new version.
|
||||
* First one is model's page.
|
||||
* Second one is new version's download url.
|
||||
* Third one is a button to download it into your SD's model folder with python.
|
||||
With this one, output information is on "Download Model" section's log and console log. One task at a time.
|
||||
|
||||

|
||||
|
||||
|
||||
## Get Model Info By Url
|
||||
If a model's SHA256 can not be found in civitai, but you still want to link it to a civitai model. You can choose this model from list, then offer a civitai model page's url you want to link.
|
||||
|
||||
After clicking button, extension will download that civitai model's model info for this local model file you picked.
|
||||
|
||||

|
||||
|
||||
## Other Setting
|
||||
**The Save Setting button, will save both "Scan Model"'s setting and other setting.**
|
||||
|
||||
* "Always Display Button" is good for touch screen.
|
||||
* "Show Buttons on Thumb Mode" will turn on/off additional Buttons on thumbnail.
|
||||

|
||||
|
||||
|
||||
## Preview Image
|
||||
Extra network uses both `model_file.png` and `model_file.preview.png` as preview image. But `model_file.png` has higher priority, because it is created by yourself.
|
||||
|
||||
|
|
@ -108,31 +139,39 @@ When you click the button "Use prompt from preview image", it does not use the p
|
|||
On civitai, a model's preview images may not has prompt. This extension will check this model's all civitai preview images' information and use the first one has prompt in it.
|
||||
|
||||
## SHA256
|
||||
To create a file SHA256, it need to read the whole file to generate a hash code. It gonna be slow for big files.
|
||||
To create a file SHA256, it need to read the whole file to generate a hash code. It gonna be slow for large files.
|
||||
|
||||
Default, it uses a Memory Optimized SHA256 which won't stuck your system.(It is the only choice in latest version). So, do not uncheck it if you want to use your computer when scanning.
|
||||
Also, extension uses Memory Optimized SHA256, which won't stuck your system and works with colab.
|
||||
|
||||
There are 2 cases this hash code can not find the model on civitai:
|
||||
* Some old models, which do not have SHA256 code on civitai.
|
||||
* The model's owner changed file on civitai, but does not change version number and description. So, the file on civitai is actually not the one on your manchine.
|
||||
* The model's owner changed file on civitai, but does not change version name and description. So, the file on civitai is actually not the one on your manchine.
|
||||
|
||||
In these cases, you can always link a model to civitai by filling its URL in this extension.
|
||||
|
||||
|
||||
## Civitai down
|
||||
## Civitai API Fail
|
||||
When Civitai is facing some issue like DDos, it gonna put civitai under Cloudflare's protection, which gonna re-direct our API request to a real human checking page. Then this extension can not get any information back.
|
||||
|
||||
In that case, juse wait for civitai's recovering. It could take 6-8 hours.
|
||||
|
||||
|
||||
## Feature Request
|
||||
No new feature for v1.x after v1.5. All new feature will go to 2.x.
|
||||
|
||||
2.x will focus on custom model information and may change name to "Model Info Helper", because it is not just focus on Civitai anymore.
|
||||
|
||||
From v1.5, v1.x goes into maintenance phase.
|
||||
|
||||
Enjoy!
|
||||
|
||||
|
||||
# Change Log
|
||||
## v1.5
|
||||
## v1.5.0
|
||||
* Download a model by Civitai model page's url
|
||||
* Resume downloading from break-point
|
||||
* Download new version into SD Webui's model folder
|
||||
* Addtional button now works on thumbnail mode
|
||||
* Add option to always show addtion button, for touch screen.
|
||||
* Download a model by model page's url into SD webui's model folder
|
||||
* Display checking new version's result as gallery and download new version into SD Webui's model folder
|
||||
* Option to always show addtion button, for touch screen.
|
||||
|
||||
## v1.4.2
|
||||
* ignore .vae file in model folder when scanning
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 116 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
|
|
@ -1,5 +1,19 @@
|
|||
"use strict";
|
||||
|
||||
// send msg to python side by filling a hidden text box
|
||||
// then will click a button to trigger an action
|
||||
// msg is an object, not a string, will be stringify in this function
|
||||
function send_ch_py_msg(msg){
|
||||
console.log("run send_ch_py_msg")
|
||||
let js_msg_txtbox = gradioApp().querySelector("#ch_js_msg_txtbox textarea");
|
||||
if (js_msg_txtbox && msg) {
|
||||
// fill to msg box
|
||||
js_msg_txtbox.value = JSON.stringify(msg);
|
||||
js_msg_txtbox.dispatchEvent(new Event("input"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// get msg from python side from a hidden textbox
|
||||
// normally this is an old msg, need to wait for a new msg
|
||||
function get_ch_py_msg(){
|
||||
|
|
@ -17,9 +31,8 @@ function get_ch_py_msg(){
|
|||
|
||||
|
||||
// get msg from python side from a hidden textbox
|
||||
// if textbox's value is different from old value then it will consider it is a new msg
|
||||
// it will try once in every sencond, until it reach the max try times
|
||||
const get_new_ch_py_msg = (old_value, max_count=3) => new Promise((resolve, reject) => {
|
||||
const get_new_ch_py_msg = (max_count=3) => new Promise((resolve, reject) => {
|
||||
console.log("run get_new_ch_py_msg")
|
||||
|
||||
let count = 0;
|
||||
|
|
@ -35,15 +48,23 @@ const get_new_ch_py_msg = (old_value, max_count=3) => new Promise((resolve, reje
|
|||
console.log(py_msg_txtbox.value)
|
||||
|
||||
new_msg = py_msg_txtbox.value
|
||||
if (new_msg != old_value) {
|
||||
if (new_msg != "") {
|
||||
find_msg=true
|
||||
}
|
||||
}
|
||||
|
||||
if (find_msg) {
|
||||
//clear msg in both sides
|
||||
py_msg_txtbox.value = "";
|
||||
py_msg_txtbox.dispatchEvent(new Event("input"));
|
||||
|
||||
resolve(new_msg);
|
||||
clearInterval(interval);
|
||||
} else if (count > max_count) {
|
||||
//clear msg in both sides
|
||||
py_msg_txtbox.value = "";
|
||||
py_msg_txtbox.dispatchEvent(new Event("input"));
|
||||
|
||||
reject('');
|
||||
clearInterval(interval);
|
||||
}
|
||||
|
|
@ -51,6 +72,9 @@ const get_new_ch_py_msg = (old_value, max_count=3) => new Promise((resolve, reje
|
|||
}, 1000);
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
function getActivePrompt() {
|
||||
const currentTab = get_uiCurrentTabContent();
|
||||
switch (currentTab.id) {
|
||||
|
|
@ -79,8 +103,10 @@ async function open_model_url(event, model_type, search_term){
|
|||
console.log("start open_model_url");
|
||||
|
||||
//get hidden components of extension
|
||||
let js_msg_txtbox = gradioApp().querySelector("#ch_js_msg_txtbox textarea");
|
||||
let js_open_url_btn = gradioApp().getElementById("ch_js_open_url_btn");
|
||||
if (!js_open_url_btn) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
//msg to python side
|
||||
|
|
@ -100,11 +126,7 @@ async function open_model_url(event, model_type, search_term){
|
|||
msg["neg_prompt"] = "";
|
||||
|
||||
// fill to msg box
|
||||
js_msg_txtbox.value = JSON.stringify(msg);
|
||||
js_msg_txtbox.dispatchEvent(new Event("input"));
|
||||
|
||||
//get old py msg
|
||||
let py_msg = get_ch_py_msg();
|
||||
send_ch_py_msg(msg)
|
||||
|
||||
//click hidden button
|
||||
js_open_url_btn.click();
|
||||
|
|
@ -114,7 +136,7 @@ async function open_model_url(event, model_type, search_term){
|
|||
event.preventDefault()
|
||||
|
||||
//check response msg from python
|
||||
let new_py_msg = await get_new_ch_py_msg("");
|
||||
let new_py_msg = await get_new_ch_py_msg();
|
||||
console.log("new_py_msg:");
|
||||
console.log(new_py_msg);
|
||||
|
||||
|
|
@ -142,9 +164,10 @@ function add_trigger_words(event, model_type, search_term){
|
|||
console.log("start add_trigger_words");
|
||||
|
||||
//get hidden components of extension
|
||||
let js_msg_txtbox = gradioApp().querySelector("#ch_js_msg_txtbox textarea");
|
||||
let js_add_trigger_words_btn = gradioApp().getElementById("ch_js_add_trigger_words_btn");
|
||||
|
||||
if (!js_add_trigger_words_btn) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
//msg to python side
|
||||
|
|
@ -166,8 +189,7 @@ function add_trigger_words(event, model_type, search_term){
|
|||
msg["prompt"] = prompt.value;
|
||||
|
||||
// fill to msg box
|
||||
js_msg_txtbox.value = JSON.stringify(msg);
|
||||
js_msg_txtbox.dispatchEvent(new Event("input"));
|
||||
send_ch_py_msg(msg)
|
||||
|
||||
//click hidden button
|
||||
js_add_trigger_words_btn.click();
|
||||
|
|
@ -184,10 +206,10 @@ function use_preview_prompt(event, model_type, search_term){
|
|||
console.log("start use_preview_prompt");
|
||||
|
||||
//get hidden components of extension
|
||||
let js_msg_txtbox = gradioApp().querySelector("#ch_js_msg_txtbox textarea");
|
||||
let js_use_preview_prompt_btn = gradioApp().getElementById("ch_js_use_preview_prompt_btn");
|
||||
|
||||
|
||||
if (!js_use_preview_prompt_btn) {
|
||||
return
|
||||
}
|
||||
|
||||
//msg to python side
|
||||
let msg = {
|
||||
|
|
@ -211,8 +233,7 @@ function use_preview_prompt(event, model_type, search_term){
|
|||
msg["neg_prompt"] = neg_prompt.value;
|
||||
|
||||
// fill to msg box
|
||||
js_msg_txtbox.value = JSON.stringify(msg);
|
||||
js_msg_txtbox.dispatchEvent(new Event("input"));
|
||||
send_ch_py_msg(msg)
|
||||
|
||||
//click hidden button
|
||||
js_use_preview_prompt_btn.click();
|
||||
|
|
@ -225,6 +246,51 @@ function use_preview_prompt(event, model_type, search_term){
|
|||
}
|
||||
|
||||
|
||||
|
||||
// download model's new version into SD at python side
|
||||
function ch_dl_model_new_version(event, model_path, version_id, download_url){
|
||||
console.log("start ch_dl_model_new_version");
|
||||
|
||||
// must confirm before downloading
|
||||
let dl_confirm = "\nConfirm to download.\n\nCheck Download Model Section's log and console log for detail.";
|
||||
if (!confirm(dl_confirm)) {
|
||||
return
|
||||
}
|
||||
|
||||
//get hidden components of extension
|
||||
let js_dl_model_new_version_btn = gradioApp().getElementById("ch_js_dl_model_new_version_btn");
|
||||
if (!js_dl_model_new_version_btn) {
|
||||
return
|
||||
}
|
||||
|
||||
//msg to python side
|
||||
let msg = {
|
||||
"action": "",
|
||||
"model_path": "",
|
||||
"version_id": "",
|
||||
"download_url": "",
|
||||
}
|
||||
|
||||
msg["action"] = "dl_model_new_version";
|
||||
msg["model_path"] = model_path;
|
||||
msg["version_id"] = version_id;
|
||||
msg["download_url"] = download_url;
|
||||
|
||||
// fill to msg box
|
||||
send_ch_py_msg(msg)
|
||||
|
||||
//click hidden button
|
||||
js_dl_model_new_version_btn.click();
|
||||
|
||||
console.log("end dl_model_new_version");
|
||||
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
onUiLoaded(() => {
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ def on_ui_tabs():
|
|||
# init
|
||||
|
||||
# get prompt textarea
|
||||
# UI structure
|
||||
# check modules/ui.py, search for txt2img_paste_fields
|
||||
# Negative prompt is the second element
|
||||
txt2img_prompt = modules.ui.txt2img_paste_fields[0][0]
|
||||
|
|
@ -49,6 +48,18 @@ def on_ui_tabs():
|
|||
return model_name_drop.update(choices=names)
|
||||
|
||||
|
||||
def get_model_info_by_url(url):
|
||||
r = model_action_civitai.get_model_info_by_url(url)
|
||||
|
||||
model_info = {}
|
||||
model_name = ""
|
||||
model_type = ""
|
||||
subfolders = []
|
||||
version_strs = []
|
||||
if r:
|
||||
model_info, model_name, model_type, subfolders, version_strs = r
|
||||
|
||||
return [model_info, model_name, model_type, dl_subfolder_drop.update(choices=subfolders), dl_version_drop.update(choices=version_strs)]
|
||||
|
||||
# ====UI====
|
||||
# with gr.Blocks(analytics_enabled=False) as civitai_helper:
|
||||
|
|
@ -64,6 +75,10 @@ def on_ui_tabs():
|
|||
model_types = list(model.folders.keys())
|
||||
no_info_model_names = civitai.get_model_names_by_input("ckp", False)
|
||||
|
||||
# session data
|
||||
dl_model_info = gr.State({})
|
||||
|
||||
|
||||
|
||||
# with gr.Tab("Model"):
|
||||
with gr.Box():
|
||||
|
|
@ -84,13 +99,30 @@ def on_ui_tabs():
|
|||
gr.Markdown("### Get Civitai Model Info by Model Page URL")
|
||||
with gr.Row():
|
||||
model_type_drop = gr.Dropdown(choices=model_types, label="Model Type", value="ckp", multiselect=False)
|
||||
empty_info_only_ckb = gr.Checkbox(label="Only Show Models have no Info file", value=False, elem_id="cn_empty_info_only_ckb")
|
||||
empty_info_only_ckb = gr.Checkbox(label="Only Show Models have no Info", value=False, elem_id="cn_empty_info_only_ckb")
|
||||
model_name_drop = gr.Dropdown(choices=no_info_model_names, label="Model", value="ckp", multiselect=False)
|
||||
|
||||
model_url_or_id = gr.Textbox(label="Civitai URL or Model ID", lines=1, value="")
|
||||
model_url_or_id_txtbox = gr.Textbox(label="Civitai URL or Model ID", lines=1, value="")
|
||||
get_civitai_model_info_by_id_btn = gr.Button(value="Get Model Info from Civitai", variant="primary")
|
||||
get_model_by_id_log_md = gr.Markdown("")
|
||||
|
||||
with gr.Box():
|
||||
with gr.Column():
|
||||
gr.Markdown("### Download Model")
|
||||
with gr.Row():
|
||||
dl_model_url_or_id_txtbox = gr.Textbox(label="Civitai URL or Model ID", lines=1, value="")
|
||||
dl_model_info_btn = gr.Button(value="1. Get Model Info by Civitai Url", variant="primary")
|
||||
|
||||
gr.Markdown(value="2. Pick Subfolder and Model Version")
|
||||
with gr.Row():
|
||||
dl_model_name_txtbox = gr.Textbox(label="Model Name", interactive=False, lines=1, value="")
|
||||
dl_model_type_txtbox = gr.Textbox(label="Model Type", interactive=False, lines=1, value="")
|
||||
dl_subfolder_drop = gr.Dropdown(choices=[], label="Sub-folder", value="", interactive=True, multiselect=False)
|
||||
dl_version_drop = gr.Dropdown(choices=[], label="Model Version", value="", interactive=True, multiselect=False)
|
||||
|
||||
dl_civitai_model_by_id_btn = gr.Button(value="3. Download Model", variant="primary")
|
||||
dl_log_md = gr.Markdown(value="Check Console log for Downloading Status")
|
||||
|
||||
with gr.Box():
|
||||
with gr.Column():
|
||||
gr.Markdown("### Check models' new version")
|
||||
|
|
@ -98,19 +130,7 @@ def on_ui_tabs():
|
|||
model_types_ckbg = gr.CheckboxGroup(choices=model_types, label="Model Types", value=["lora"])
|
||||
check_models_new_version_btn = gr.Button(value="Check New Version from Civitai", variant="primary")
|
||||
|
||||
check_models_new_version_log_md = gr.Markdown("It takes time, just wait. Check console log for detail")
|
||||
|
||||
|
||||
with gr.Box():
|
||||
with gr.Column():
|
||||
gr.Markdown("### Download Model")
|
||||
with gr.Row():
|
||||
dl_model_type_drop = gr.Dropdown(choices=model_types, label="Model Type", value="ckp", multiselect=False)
|
||||
dl_subfolder_drop = gr.Dropdown(choices=model_types, label="Sub-folder", value="", multiselect=False)
|
||||
|
||||
dl_model_url_or_id = gr.Textbox(label="Civitai URL or Model ID", lines=1, value="")
|
||||
dl_civitai_model_by_id_btn = gr.Button(value="Download Model from Civitai", variant="primary")
|
||||
|
||||
check_models_new_version_log_md = gr.HTML("It takes time, just wait. Check console log for detail")
|
||||
|
||||
with gr.Box():
|
||||
with gr.Column():
|
||||
|
|
@ -120,8 +140,8 @@ def on_ui_tabs():
|
|||
always_display_ckb = gr.Checkbox(label="Always Display Buttons", value=always_display, elem_id="ch_always_display_ckb")
|
||||
show_btn_on_thumb_ckb = gr.Checkbox(label="Show Button On Thumb Mode", value=show_btn_on_thumb, elem_id="ch_show_btn_on_thumb_ckb")
|
||||
|
||||
save_setting_btn = gr.Button(value="Save Setting", elem_id="ch_save_setting_btn")
|
||||
general_log_md = gr.Markdown(value="", elem_id="ch_general_log_md")
|
||||
save_setting_btn = gr.Button(value="Save Setting")
|
||||
general_log_md = gr.Markdown(value="")
|
||||
|
||||
|
||||
# ====Footer====
|
||||
|
|
@ -130,29 +150,37 @@ def on_ui_tabs():
|
|||
# ====hidden component for js, not in any tab====
|
||||
js_msg_txtbox = gr.Textbox(label="Request Msg From Js", visible=False, lines=1, value="", elem_id="ch_js_msg_txtbox")
|
||||
py_msg_txtbox = gr.Textbox(label="Response Msg From Python", visible=False, lines=1, value="", elem_id="ch_py_msg_txtbox")
|
||||
|
||||
js_open_url_btn = gr.Button(value="Open Model Url", visible=False, elem_id="ch_js_open_url_btn")
|
||||
js_add_trigger_words_btn = gr.Button(value="Add Trigger Words", visible=False, elem_id="ch_js_add_trigger_words_btn")
|
||||
js_use_preview_prompt_btn = gr.Button(value="Use Prompt from Preview Image", visible=False, elem_id="ch_js_use_preview_prompt_btn")
|
||||
js_dl_model_new_version_btn = gr.Button(value="Download Model's new version", visible=False, elem_id="ch_js_dl_model_new_version_btn")
|
||||
|
||||
# ====events====
|
||||
# Model
|
||||
# Scan Models for Civitai
|
||||
scan_model_civitai_btn.click(model_action_civitai.scan_model, inputs=[max_size_preview_ckb, skip_nsfw_preview_ckb], outputs=scan_model_log_md)
|
||||
|
||||
# Get Civitai Model Info by Model Page URL
|
||||
model_type_drop.change(get_model_names_by_input, inputs=[model_type_drop, empty_info_only_ckb], outputs=model_name_drop)
|
||||
empty_info_only_ckb.change(get_model_names_by_input, inputs=[model_type_drop, empty_info_only_ckb], outputs=model_name_drop)
|
||||
|
||||
get_civitai_model_info_by_id_btn.click(model_action_civitai.get_model_info_by_input, inputs=[model_type_drop, model_name_drop, model_url_or_id, max_size_preview_ckb, skip_nsfw_preview_ckb], outputs=get_model_by_id_log_md)
|
||||
get_civitai_model_info_by_id_btn.click(model_action_civitai.get_model_info_by_input, inputs=[model_type_drop, model_name_drop, model_url_or_id_txtbox, max_size_preview_ckb, skip_nsfw_preview_ckb], outputs=get_model_by_id_log_md)
|
||||
|
||||
# Download Model
|
||||
dl_model_info_btn.click(get_model_info_by_url, inputs=dl_model_url_or_id_txtbox, outputs=[dl_model_info, dl_model_name_txtbox, dl_model_type_txtbox, dl_subfolder_drop, dl_version_drop])
|
||||
dl_civitai_model_by_id_btn.click(model_action_civitai.dl_model_by_input, inputs=[dl_model_info, dl_model_type_txtbox, dl_subfolder_drop, dl_version_drop, max_size_preview_ckb, skip_nsfw_preview_ckb], outputs=dl_log_md)
|
||||
|
||||
# Check models' new version
|
||||
check_models_new_version_btn.click(model_action_civitai.check_models_new_version_to_md, inputs=model_types_ckbg, outputs=check_models_new_version_log_md)
|
||||
|
||||
|
||||
# General
|
||||
# Other Setting
|
||||
save_setting_btn.click(setting.save_from_input, inputs=[max_size_preview_ckb, skip_nsfw_preview_ckb, open_url_with_js_ckb, always_display_ckb, show_btn_on_thumb_ckb], outputs=general_log_md)
|
||||
|
||||
# js action
|
||||
js_open_url_btn.click(js_action_civitai.open_model_url, inputs=[js_msg_txtbox, open_url_with_js_ckb], outputs=py_msg_txtbox)
|
||||
js_add_trigger_words_btn.click(js_action_civitai.add_trigger_words, inputs=[js_msg_txtbox], outputs=[txt2img_prompt, img2img_prompt])
|
||||
js_use_preview_prompt_btn.click(js_action_civitai.use_preview_image_prompt, inputs=[js_msg_txtbox], outputs=[txt2img_prompt, txt2img_neg_prompt, img2img_prompt, img2img_neg_prompt])
|
||||
js_dl_model_new_version_btn.click(js_action_civitai.dl_model_new_version, inputs=[js_msg_txtbox, max_size_preview_ckb, skip_nsfw_preview_ckb], outputs=dl_log_md)
|
||||
|
||||
# the third parameter is the element id on html, with a "tab_" as prefix
|
||||
return (civitai_helper , "Civitai Helper", "civitai_helper"),
|
||||
|
|
|
|||
|
|
@ -18,6 +18,14 @@ url_dict = {
|
|||
"hash": "https://civitai.com/api/v1/model-versions/by-hash/"
|
||||
}
|
||||
|
||||
model_type_dict = {
|
||||
"Checkpoint": "ckp",
|
||||
"TextualInversion": "ti",
|
||||
"Hypernetwork": "hyper",
|
||||
"LORA": "lora",
|
||||
}
|
||||
|
||||
|
||||
# get image with full size
|
||||
# width is in number, not string
|
||||
# return: url str
|
||||
|
|
@ -107,7 +115,7 @@ def get_version_info_by_version_id(id:str) -> dict:
|
|||
util.printD("id is empty")
|
||||
return
|
||||
|
||||
r = requests.get(url_dict["modelVersionId"]+id)
|
||||
r = requests.get(url_dict["modelVersionId"]+str(id))
|
||||
if not r.ok:
|
||||
if r.status_code == 404:
|
||||
# this is not a civitai model
|
||||
|
|
@ -303,7 +311,7 @@ def get_model_id_from_url(url:str) -> str:
|
|||
|
||||
# get preview image by model path
|
||||
# image will be saved to file, so no return
|
||||
def get_preview_image_by_model_path(model_path:str, max_size_preview, skip_nsfw_preview) -> str:
|
||||
def get_preview_image_by_model_path(model_path:str, max_size_preview, skip_nsfw_preview):
|
||||
if not model_path:
|
||||
util.printD("model_path is empty")
|
||||
return
|
||||
|
|
@ -599,3 +607,4 @@ def check_models_new_version_by_model_types(model_types:list, delay:float=1) ->
|
|||
return new_versions
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
import sys
|
||||
import requests
|
||||
import os
|
||||
import util
|
||||
|
||||
|
||||
dl_ext = ".downloading"
|
||||
|
||||
# disable ssl warning info
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
def download(url, file_path, size):
|
||||
# use a temp file for downloading
|
||||
base, ext = os.path.splitext(file_path)
|
||||
dl_file_path = os.path.join(base, dl_ext)
|
||||
|
||||
total_size = 0
|
||||
if size:
|
||||
total_size = size
|
||||
else:
|
||||
# get file size
|
||||
rhead = requests.get(url, stream=True, verify=False)
|
||||
total_size = int(rhead.headers['Content-Length'])
|
||||
|
||||
util.printD(f"File size: {total_size}")
|
||||
|
||||
util.printD(f"Downloading to temp file: {dl_file_path}")
|
||||
|
||||
# check if downloading file is exsited
|
||||
downloaded_size = 0
|
||||
if os.path.exists(dl_file_path):
|
||||
downloaded_size = os.path.getsize(dl_file_path)
|
||||
|
||||
util.printD(f"Downloaded size: {downloaded_size}")
|
||||
|
||||
# get header range
|
||||
headers = {'Range': 'bytes=%d-' % downloaded_size}
|
||||
# download with header
|
||||
r = requests.get(url, stream=True, verify=False, headers=headers)
|
||||
|
||||
# write to file
|
||||
with open(file_path, "ab") as f:
|
||||
for chunk in r.iter_content(chunk_size=1024):
|
||||
if chunk:
|
||||
downloaded_size += len(chunk)
|
||||
f.write(chunk)
|
||||
# force to write to disk
|
||||
f.flush()
|
||||
|
||||
# progress
|
||||
progress = int(50 * downloaded_size / total_size)
|
||||
sys.stdout.write("\r[%s%s] %d%%" % ('█' * progress, ' ' * (50 - progress), 100 * downloaded_size / total_size))
|
||||
sys.stdout.flush()
|
||||
|
||||
print()
|
||||
|
||||
# rename file
|
||||
os.rename(dl_file_path, file_path)
|
||||
util.printD(f"File Downloaded to: {file_path}")
|
||||
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
import sys
|
||||
import requests
|
||||
import os
|
||||
from . import util
|
||||
|
||||
|
||||
dl_ext = ".downloading"
|
||||
|
||||
# disable ssl warning info
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
# output is downloaded file path
|
||||
def dl(url, folder, filename, filepath):
|
||||
util.printD("Start downloading from: " + url)
|
||||
# get file_path
|
||||
file_path = ""
|
||||
if filepath:
|
||||
file_path = filepath
|
||||
else:
|
||||
# if file_path is not in parameter, then folder must be in parameter
|
||||
if not folder:
|
||||
util.printD("folder is none")
|
||||
return
|
||||
|
||||
if not os.path.isdir(folder):
|
||||
util.printD("folder does not exist: "+folder)
|
||||
return
|
||||
|
||||
if filename:
|
||||
file_path = os.path.join(folder, filename)
|
||||
|
||||
# first request for header
|
||||
rh = requests.get(url, stream=True, verify=False)
|
||||
# get file size
|
||||
total_size = 0
|
||||
total_size = int(rh.headers['Content-Length'])
|
||||
util.printD(f"File size: {total_size}")
|
||||
|
||||
# if file_path is empty, need to get file name from download url's header
|
||||
if not file_path:
|
||||
filename = ""
|
||||
if "Content-Disposition" in rh.headers.keys():
|
||||
cd = rh.headers["Content-Disposition"]
|
||||
# Extract the filename from the header
|
||||
# content of a CD: "attachment;filename=FileName.txt"
|
||||
# in case "" is in CD filename's start and end, need to strip them out
|
||||
filename = cd.split("=")[1].strip('"')
|
||||
if not filename:
|
||||
util.printD("Fail to get file name from Content-Disposition: " + cd)
|
||||
return
|
||||
|
||||
if not filename:
|
||||
util.printD("Can not get file name from download url's header")
|
||||
return
|
||||
|
||||
# with folder and filename, now we have the full file path
|
||||
file_path = os.path.join(folder, filename)
|
||||
|
||||
|
||||
util.printD("Target file path: " + file_path)
|
||||
|
||||
# use a temp file for downloading
|
||||
base, ext = os.path.splitext(file_path)
|
||||
dl_file_path = base+dl_ext
|
||||
|
||||
|
||||
util.printD(f"Downloading to temp file: {dl_file_path}")
|
||||
|
||||
# check if downloading file is exsited
|
||||
downloaded_size = 0
|
||||
if os.path.exists(dl_file_path):
|
||||
downloaded_size = os.path.getsize(dl_file_path)
|
||||
|
||||
util.printD(f"Downloaded size: {downloaded_size}")
|
||||
|
||||
# create header range
|
||||
headers = {'Range': 'bytes=%d-' % downloaded_size}
|
||||
# download with header
|
||||
r = requests.get(url, stream=True, verify=False, headers=headers)
|
||||
|
||||
# write to file
|
||||
with open(dl_file_path, "ab") as f:
|
||||
for chunk in r.iter_content(chunk_size=1024):
|
||||
if chunk:
|
||||
downloaded_size += len(chunk)
|
||||
f.write(chunk)
|
||||
# force to write to disk
|
||||
f.flush()
|
||||
|
||||
# progress
|
||||
progress = int(50 * downloaded_size / total_size)
|
||||
sys.stdout.write("\r[%s%s] %d%%" % ('█' * progress, ' ' * (50 - progress), 100 * downloaded_size / total_size))
|
||||
sys.stdout.flush()
|
||||
|
||||
print()
|
||||
|
||||
# rename file
|
||||
os.rename(dl_file_path, file_path)
|
||||
util.printD(f"File Downloaded to: {file_path}")
|
||||
return file_path
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ from . import util
|
|||
from . import model
|
||||
from . import civitai
|
||||
from . import msg_handler
|
||||
|
||||
from . import downloader
|
||||
|
||||
|
||||
|
||||
|
|
@ -24,7 +24,8 @@ def open_model_url(msg, open_url_with_js):
|
|||
util.printD("Parsing js ms failed")
|
||||
return
|
||||
|
||||
action, model_type, search_term, prompt, neg_prompt = result
|
||||
model_type = result["model_type"]
|
||||
search_term = result["search_term"]
|
||||
|
||||
model_info = civitai.load_model_info_by_search_term(model_type, search_term)
|
||||
if not model_info:
|
||||
|
|
@ -73,7 +74,9 @@ def add_trigger_words(msg):
|
|||
util.printD("Parsing js ms failed")
|
||||
return
|
||||
|
||||
action, model_type, search_term, prompt, neg_prompt = result
|
||||
model_type = result["model_type"]
|
||||
search_term = result["search_term"]
|
||||
prompt = result["prompt"]
|
||||
|
||||
|
||||
model_info = civitai.load_model_info_by_search_term(model_type, search_term)
|
||||
|
|
@ -122,7 +125,10 @@ def use_preview_image_prompt(msg):
|
|||
util.printD("Parsing js ms failed")
|
||||
return
|
||||
|
||||
action, model_type, search_term, prompt, neg_prompt = result
|
||||
model_type = result["model_type"]
|
||||
search_term = result["search_term"]
|
||||
prompt = result["prompt"]
|
||||
neg_prompt = result["neg_prompt"]
|
||||
|
||||
|
||||
model_info = civitai.load_model_info_by_search_term(model_type, search_term)
|
||||
|
|
@ -170,3 +176,73 @@ def use_preview_image_prompt(msg):
|
|||
return [preview_prompt, preview_neg_prompt, preview_prompt, preview_neg_prompt]
|
||||
|
||||
|
||||
# download model's new verson by model path, version id and download url
|
||||
# output is a md log
|
||||
def dl_model_new_version(msg, max_size_preview, skip_nsfw_preview):
|
||||
util.printD("Start dl_model_new_version")
|
||||
|
||||
output = ""
|
||||
|
||||
result = msg_handler.parse_js_msg(msg)
|
||||
if not result:
|
||||
output = "Parsing js ms failed"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
model_path = result["model_path"]
|
||||
version_id = result["version_id"]
|
||||
download_url = result["download_url"]
|
||||
|
||||
util.printD("model_path: " + model_path)
|
||||
util.printD("version_id: " + str(version_id))
|
||||
util.printD("download_url: " + download_url)
|
||||
|
||||
# check data
|
||||
if not model_path:
|
||||
output = "model_path is empty"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
if not version_id:
|
||||
output = "version_id is empty"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
if not download_url:
|
||||
output = "download_url is empty"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
if not os.path.isfile(model_path):
|
||||
output = "model_path is not a file: "+ model_path
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
# get model folder from model path
|
||||
model_folder = os.path.dirname(model_path)
|
||||
|
||||
# download file
|
||||
new_model_path = downloader.dl(download_url, model_folder, None, None)
|
||||
if not new_model_path:
|
||||
output = "Download failed, check console log for detail. Download url: " + download_url
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
# get version info
|
||||
version_info = civitai.get_version_info_by_version_id(version_id)
|
||||
if not version_info:
|
||||
output = "Model downloaded, but failed to get version info, check console log for detail. Model saved to: " + new_model_path
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
# now write version info to file
|
||||
base, ext = os.path.splitext(new_model_path)
|
||||
info_file = base + civitai.suffix + model.info_ext
|
||||
model.write_model_info(info_file, version_info)
|
||||
|
||||
# then, get preview image
|
||||
civitai.get_preview_image_by_model_path(new_model_path, max_size_preview, skip_nsfw_preview)
|
||||
|
||||
output = "Done. Model downloaded to: " + new_model_path
|
||||
util.printD(output)
|
||||
return output
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import os
|
|||
from . import util
|
||||
from . import model
|
||||
from . import civitai
|
||||
|
||||
from . import downloader
|
||||
|
||||
|
||||
# scan model to generate SHA256, then use this SHA256 to get model info from civitai
|
||||
|
|
@ -139,24 +139,33 @@ def check_models_new_version_to_md(model_types:list) -> str:
|
|||
model_path, model_id, model_name, new_verion_id, new_version_name, description, download_url, img_url = new_version
|
||||
# in md, each part is something like this:
|
||||
# [model_name](model_url)
|
||||
# [version_name](download_url)
|
||||
# version description
|
||||
url = civitai.url_dict["modelPage"]+str(model_id)
|
||||
|
||||
part = f'<b>Model: <a href="{url}" target="_blank">{model_name}</a></b> <br>'
|
||||
part = part + f"File: {model_path} <br>"
|
||||
part = f'<div style="font-size:20px;margin:6px 0px;"><b>Model: <a href="{url}" target="_blank"><u>{model_name}</u></a></b></div>'
|
||||
part = part + f'<div style="font-size:16px">File: {model_path}</div>'
|
||||
if download_url:
|
||||
part = part + f'New Version: <a href="{download_url}" target="_blank">{new_version_name}</a>'
|
||||
# replace "\" to "/" in model_path for windows
|
||||
model_path = model_path.replace('\\', '\\\\')
|
||||
part = part + f'<div style="font-size:16px;margin:6px 0px;">New Version: <u><a href="{download_url}" target="_blank" style="margin:0px 10px;">{new_version_name}</a></u>'
|
||||
# add js function to download new version into SD webui by python
|
||||
part = part + " "
|
||||
# in embed HTML, onclick= will also follow a ", never a ', so have to write it as following
|
||||
part = part + f"<u><a href='#' style='margin:0px 10px;' onclick=\"ch_dl_model_new_version(event, '{model_path}', '{new_verion_id}', '{download_url}')\">[Download into SD]</a></u>"
|
||||
|
||||
else:
|
||||
part = part + f"New Version: {new_version_name}"
|
||||
part = part + " <br>"
|
||||
part = part + f'<div style="font-size:16px;margin:6px 0px;">New Version: {new_version_name}'
|
||||
part = part + '</div>'
|
||||
|
||||
# description
|
||||
if description:
|
||||
part = part + description
|
||||
part = part + '<blockquote style="font-size:16px;margin:6px 0px;">'+ description + '</blockquote><br>'
|
||||
|
||||
# preview image
|
||||
if img_url:
|
||||
part = part + f" <br>"
|
||||
part = part + f"<img src='{img_url}'><br>"
|
||||
|
||||
|
||||
output = output + part
|
||||
|
||||
|
|
@ -165,3 +174,233 @@ def check_models_new_version_to_md(model_types:list) -> str:
|
|||
return output
|
||||
|
||||
|
||||
# get model info by url
|
||||
def get_model_info_by_url(model_url_or_id:str) -> tuple:
|
||||
util.printD("Getting model info by: " + model_url_or_id)
|
||||
|
||||
# parse model id
|
||||
model_id = civitai.get_model_id_from_url(model_url_or_id)
|
||||
if not model_id:
|
||||
util.printD("failed to parse model id from url or id")
|
||||
return
|
||||
|
||||
model_info = civitai.get_model_info_by_id(model_id)
|
||||
if not model_info:
|
||||
util.printD("failed to get model info from url or id")
|
||||
return
|
||||
|
||||
# parse model type, model name, subfolder, version from this model info
|
||||
# get model type
|
||||
if "type" not in model_info.keys():
|
||||
util.printD("model type is not in model_info")
|
||||
return
|
||||
|
||||
civitai_model_type = model_info["type"]
|
||||
if civitai_model_type not in civitai.model_type_dict.keys():
|
||||
util.printD("This model type is not supported:"+civitai_model_type)
|
||||
return
|
||||
|
||||
model_type = civitai.model_type_dict[civitai_model_type]
|
||||
|
||||
# get model type
|
||||
if "name" not in model_info.keys():
|
||||
util.printD("model name is not in model_info")
|
||||
return
|
||||
|
||||
model_name = model_info["name"]
|
||||
if not model_name:
|
||||
util.printD("model name is Empty")
|
||||
model_name = ""
|
||||
|
||||
# get version list
|
||||
if "modelVersions" not in model_info.keys():
|
||||
util.printD("modelVersions is not in model_info")
|
||||
return
|
||||
|
||||
modelVersions = model_info["modelVersions"]
|
||||
if not modelVersions:
|
||||
util.printD("modelVersions is Empty")
|
||||
return
|
||||
|
||||
version_strs = []
|
||||
for version in modelVersions:
|
||||
# version name can not be used as id
|
||||
# version id is not readable
|
||||
# so , we use name_id as version string
|
||||
version_str = version["name"]+"_"+str(version["id"])
|
||||
version_strs.append(version_str)
|
||||
|
||||
# get folder by model type
|
||||
folder = model.folders[model_type]
|
||||
# get subfolders
|
||||
subfolders = util.get_subfolders(folder)
|
||||
if not subfolders:
|
||||
subfolders = []
|
||||
|
||||
# add default root folder
|
||||
subfolders.append("/")
|
||||
|
||||
util.printD("Get following info for downloading:")
|
||||
util.printD(f"model_name:{model_name}")
|
||||
util.printD(f"model_type:{model_type}")
|
||||
util.printD(f"subfolders:{subfolders}")
|
||||
util.printD(f"version_strs:{version_strs}")
|
||||
|
||||
return (model_info, model_name, model_type, subfolders, version_strs)
|
||||
|
||||
|
||||
# get download url from model info by version string
|
||||
# return - (version_id, download_url)
|
||||
def get_id_and_dl_url_by_version_str(version_str:str, model_info:dict) -> tuple:
|
||||
if not version_str:
|
||||
util.printD("version_str is empty")
|
||||
return
|
||||
|
||||
if not model_info:
|
||||
util.printD("model_info is None")
|
||||
return
|
||||
|
||||
# get version list
|
||||
if "modelVersions" not in model_info.keys():
|
||||
util.printD("modelVersions is not in model_info")
|
||||
return
|
||||
|
||||
modelVersions = model_info["modelVersions"]
|
||||
if not modelVersions:
|
||||
util.printD("modelVersions is Empty")
|
||||
return
|
||||
|
||||
# find version by version_str
|
||||
version = None
|
||||
for ver in modelVersions:
|
||||
# version name can not be used as id
|
||||
# version id is not readable
|
||||
# so , we use name_id as version string
|
||||
ver_str = ver["name"]+"_"+str(ver["id"])
|
||||
if ver_str == version_str:
|
||||
# find version
|
||||
version = ver
|
||||
|
||||
if not version:
|
||||
util.printD("can not find version by version string: " + version_str)
|
||||
return
|
||||
|
||||
# get version id
|
||||
if "id" not in version.keys():
|
||||
util.printD("this version has no id")
|
||||
return
|
||||
|
||||
version_id = version["id"]
|
||||
if not version_id:
|
||||
util.printD("version id is Empty")
|
||||
return
|
||||
|
||||
# get download url
|
||||
if "downloadUrl" not in version.keys():
|
||||
util.printD("downloadUrl is not in this version")
|
||||
return
|
||||
|
||||
downloadUrl = version["downloadUrl"]
|
||||
if not downloadUrl:
|
||||
util.printD("downloadUrl is Empty")
|
||||
return
|
||||
|
||||
util.printD("Get Download Url: " + downloadUrl)
|
||||
|
||||
return (version_id, downloadUrl)
|
||||
|
||||
|
||||
# download model from civitai by input
|
||||
# output to markdown log
|
||||
def dl_model_by_input(model_info:dict, model_type:str, subfolder_str:str, version_str:str, max_size_preview:bool, skip_nsfw_preview:bool) -> str:
|
||||
|
||||
output = ""
|
||||
|
||||
if not model_info:
|
||||
output = "model_info is None"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
if not model_type:
|
||||
output = "model_type is None"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
if not subfolder_str:
|
||||
output = "subfolder string is None"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
if not version_str:
|
||||
output = "version_str is None"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
# get model root folder
|
||||
if model_type not in model.folders.keys():
|
||||
output = "Unknow model type: "+model_type
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
model_root_folder = model.folders[model_type]
|
||||
|
||||
|
||||
# get subfolder
|
||||
subfolder = ""
|
||||
if subfolder_str == "/" or subfolder_str == "\\":
|
||||
subfolder = ""
|
||||
elif subfolder_str[:1] == "/" or subfolder_str[:1] == "\\":
|
||||
subfolder = subfolder_str[1:]
|
||||
else:
|
||||
subfolder = subfolder_str
|
||||
|
||||
# get model folder for downloading
|
||||
model_folder = os.path.join(model_root_folder, subfolder)
|
||||
if not os.path.isdir(model_folder):
|
||||
output = "Model folder is not a dir: "+ model_folder
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
# get download url
|
||||
r = get_id_and_dl_url_by_version_str(version_str, model_info)
|
||||
if not r:
|
||||
output = "Fail to get download url, check console log for detail"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
version_id, url = r
|
||||
if not version_id:
|
||||
output = "Fail to get version id, check console log for detail"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
if not url:
|
||||
output = "Fail to get download url, check console log for detail"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
# download
|
||||
filepath = downloader.dl(url, model_folder, None, None)
|
||||
if not filepath:
|
||||
output = "Downloading failed, check console log for detail"
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
# get version info
|
||||
version_info = civitai.get_version_info_by_version_id(version_id)
|
||||
if not version_info:
|
||||
output = "Model downloaded, but failed to get version info, check console log for detail. Model saved to: " + filepath
|
||||
util.printD(output)
|
||||
return output
|
||||
|
||||
# write version info to file
|
||||
base, ext = os.path.splitext(filepath)
|
||||
info_file = base + civitai.suffix + model.info_ext
|
||||
model.write_model_info(info_file, version_info)
|
||||
|
||||
# then, get preview image
|
||||
civitai.get_preview_image_by_model_path(filepath, max_size_preview, skip_nsfw_preview)
|
||||
|
||||
output = "Done. Model downloaded to: " + filepath
|
||||
util.printD(output)
|
||||
return output
|
||||
|
|
|
|||
|
|
@ -4,63 +4,37 @@ import json
|
|||
from . import util
|
||||
|
||||
# action list
|
||||
js_actions = ("open_url", "add_trigger_words", "use_preview_prompt")
|
||||
py_actions = ("open_url", "scan_log", "model_new_version")
|
||||
js_actions = ("open_url", "add_trigger_words", "use_preview_prompt", "dl_model_new_version")
|
||||
py_actions = ("open_url")
|
||||
|
||||
|
||||
# handle request from javascript
|
||||
# parameter: msg - msg from js as string in a hidden textbox
|
||||
# return: (action, model_type, search_term, prompt, neg_prompt)
|
||||
# return: dict for result
|
||||
def parse_js_msg(msg):
|
||||
util.printD("Start parse js msg")
|
||||
msg_dict = json.loads(msg)
|
||||
|
||||
# in case client side run JSON.stringify twice
|
||||
if (type(msg_dict) == str):
|
||||
msg_dict = json.loads(msg_dict)
|
||||
|
||||
if "action" not in msg_dict.keys():
|
||||
util.printD("Can not find action from js request")
|
||||
return
|
||||
|
||||
if "model_type" not in msg_dict.keys():
|
||||
util.printD("Can not find model type from js request")
|
||||
return
|
||||
|
||||
if "search_term" not in msg_dict.keys():
|
||||
util.printD("Can not find search_term from js request")
|
||||
return
|
||||
|
||||
if "prompt" not in msg_dict.keys():
|
||||
util.printD("Can not find prompt from js request")
|
||||
return
|
||||
|
||||
if "neg_prompt" not in msg_dict.keys():
|
||||
util.printD("Can not find neg_prompt from js request")
|
||||
return
|
||||
|
||||
action = msg_dict["action"]
|
||||
model_type = msg_dict["model_type"]
|
||||
search_term = msg_dict["search_term"]
|
||||
prompt = msg_dict["prompt"]
|
||||
neg_prompt = msg_dict["neg_prompt"]
|
||||
|
||||
if not action:
|
||||
util.printD("Action from js request is None")
|
||||
return
|
||||
|
||||
if not model_type:
|
||||
util.printD("model_type from js request is None")
|
||||
return
|
||||
|
||||
if not search_term:
|
||||
util.printD("search_term from js request is None")
|
||||
return
|
||||
|
||||
|
||||
if action not in js_actions:
|
||||
util.printD("Unknow action: " + action)
|
||||
return
|
||||
|
||||
util.printD("End parse js msg")
|
||||
|
||||
return (action, model_type, search_term, prompt, neg_prompt)
|
||||
return msg_dict
|
||||
|
||||
|
||||
# build python side msg for sending to js
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
import os
|
||||
import hashlib
|
||||
import requests
|
||||
import shutil
|
||||
|
||||
version = "1.4.3"
|
||||
version = "1.5.0"
|
||||
|
||||
# print for debugging
|
||||
def printD(msg):
|
||||
|
|
@ -41,3 +42,26 @@ def download_file(url, path):
|
|||
shutil.copyfileobj(r.raw, f)
|
||||
|
||||
printD("File downloaded to: " + path)
|
||||
|
||||
# get subfolder list
|
||||
def get_subfolders(folder:str) -> list:
|
||||
printD("Get subfolder for: " + folder)
|
||||
if not folder:
|
||||
printD("folder can not be None")
|
||||
return
|
||||
|
||||
if not os.path.isdir(folder):
|
||||
printD("path is not a folder")
|
||||
return
|
||||
|
||||
prefix_len = len(folder)
|
||||
subfolders = []
|
||||
for root, dirs, files in os.walk(folder, followlinks=True):
|
||||
for dir in dirs:
|
||||
full_dir_path = os.path.join(root, dir)
|
||||
# get subfolder path from it
|
||||
subfolder = full_dir_path[prefix_len:]
|
||||
subfolders.append(subfolder)
|
||||
|
||||
return subfolders
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue