toto10 commited on
Commit
759809a
·
1 Parent(s): b36180c

de62fe58e29c640df0d1bdacc1202aca1f811659137622e64c565ae8cb27305c

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +1 -0
  2. Stable-Diffusion-Webui-Civitai-Helper/img/all_in_one.png +3 -0
  3. Stable-Diffusion-Webui-Civitai-Helper/img/check_model_new_version.jpg +0 -0
  4. Stable-Diffusion-Webui-Civitai-Helper/img/check_model_new_version_output.jpg +0 -0
  5. Stable-Diffusion-Webui-Civitai-Helper/img/download_model.jpg +0 -0
  6. Stable-Diffusion-Webui-Civitai-Helper/img/extension_tab.jpg +0 -0
  7. Stable-Diffusion-Webui-Civitai-Helper/img/extra_network.jpg +0 -0
  8. Stable-Diffusion-Webui-Civitai-Helper/img/get_one_model_info.jpg +0 -0
  9. Stable-Diffusion-Webui-Civitai-Helper/img/model_card.jpg +0 -0
  10. Stable-Diffusion-Webui-Civitai-Helper/img/model_info_file.jpg +0 -0
  11. Stable-Diffusion-Webui-Civitai-Helper/img/other_setting.jpg +0 -0
  12. Stable-Diffusion-Webui-Civitai-Helper/img/refresh_ch.jpg +0 -0
  13. Stable-Diffusion-Webui-Civitai-Helper/img/thumb_mode.jpg +0 -0
  14. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/blame_sdweui_update_to_this_ext.jpg +0 -0
  15. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/changed_model_folder_name_then_forget_part1.jpg +0 -0
  16. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/changed_model_folder_name_then_forget_part2.jpg +0 -0
  17. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/changed_model_folder_name_then_forget_part3.jpg +0 -0
  18. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/changed_model_folder_name_then_forget_part4.jpg +0 -0
  19. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/css_issue_part1.jpg +0 -0
  20. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/css_issue_part2.jpg +0 -0
  21. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/css_issue_part3.jpg +0 -0
  22. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/css_issue_part4.jpg +0 -0
  23. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/did_not_relaunch_sdwebui.jpg +0 -0
  24. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/do_not_even_use_this_ext.jpg +0 -0
  25. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/have_not_scan_model.jpg +0 -0
  26. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/have_not_update_sdwebui.jpg +0 -0
  27. Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/request_a_feature_it_already_has.jpg +0 -0
  28. Stable-Diffusion-Webui-Civitai-Helper/javascript/civitai_helper.js +728 -0
  29. Stable-Diffusion-Webui-Civitai-Helper/scripts/__pycache__/civitai_helper.cpython-310.pyc +0 -0
  30. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__init__.py +0 -0
  31. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/__init__.cpython-310.pyc +0 -0
  32. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/civitai.cpython-310.pyc +0 -0
  33. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/downloader.cpython-310.pyc +0 -0
  34. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/js_action_civitai.cpython-310.pyc +0 -0
  35. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/model.cpython-310.pyc +0 -0
  36. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/model_action_civitai.cpython-310.pyc +0 -0
  37. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/msg_handler.cpython-310.pyc +0 -0
  38. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/setting.cpython-310.pyc +0 -0
  39. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/util.cpython-310.pyc +0 -0
  40. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/civitai.py +612 -0
  41. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/downloader.py +115 -0
  42. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/js_action_civitai.py +256 -0
  43. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/model.py +120 -0
  44. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/model_action_civitai.py +511 -0
  45. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/msg_handler.py +64 -0
  46. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/setting.py +113 -0
  47. Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/util.py +105 -0
  48. Stable-Diffusion-Webui-Civitai-Helper/scripts/civitai_helper.py +218 -0
  49. Stable-Diffusion-Webui-Civitai-Helper/style.css +18 -0
  50. a1111-microsoftexcel-locon/.gitignore +1 -0
.gitattributes CHANGED
@@ -36,3 +36,4 @@ Auto-Photoshop-StableDiffusion-Plugin/docs/heal_brush.gif filter=lfs diff=lfs me
36
  Auto-Photoshop-StableDiffusion-Plugin/docs/inpainting.gif filter=lfs diff=lfs merge=lfs -text
37
  Auto-Photoshop-StableDiffusion-Plugin/docs/outpainting.gif filter=lfs diff=lfs merge=lfs -text
38
  Auto-Photoshop-StableDiffusion-Plugin/docs/prompt_shortcut.gif filter=lfs diff=lfs merge=lfs -text
 
 
36
  Auto-Photoshop-StableDiffusion-Plugin/docs/inpainting.gif filter=lfs diff=lfs merge=lfs -text
37
  Auto-Photoshop-StableDiffusion-Plugin/docs/outpainting.gif filter=lfs diff=lfs merge=lfs -text
38
  Auto-Photoshop-StableDiffusion-Plugin/docs/prompt_shortcut.gif filter=lfs diff=lfs merge=lfs -text
39
+ Stable-Diffusion-Webui-Civitai-Helper/img/all_in_one.png filter=lfs diff=lfs merge=lfs -text
Stable-Diffusion-Webui-Civitai-Helper/img/all_in_one.png ADDED

Git LFS Details

  • SHA256: bedc58968db1a83c84e57d94327c4e27f5cd6fbd93c45a59627a5257b06c8a47
  • Pointer size: 132 Bytes
  • Size of remote file: 1.1 MB
Stable-Diffusion-Webui-Civitai-Helper/img/check_model_new_version.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/check_model_new_version_output.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/download_model.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/extension_tab.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/extra_network.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/get_one_model_info.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/model_card.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/model_info_file.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/other_setting.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/refresh_ch.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/thumb_mode.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/blame_sdweui_update_to_this_ext.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/changed_model_folder_name_then_forget_part1.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/changed_model_folder_name_then_forget_part2.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/changed_model_folder_name_then_forget_part3.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/changed_model_folder_name_then_forget_part4.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/css_issue_part1.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/css_issue_part2.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/css_issue_part3.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/css_issue_part4.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/did_not_relaunch_sdwebui.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/do_not_even_use_this_ext.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/have_not_scan_model.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/have_not_update_sdwebui.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/img/user_claim_wall/request_a_feature_it_already_has.jpg ADDED
Stable-Diffusion-Webui-Civitai-Helper/javascript/civitai_helper.js ADDED
@@ -0,0 +1,728 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+
4
+ function ch_convert_file_path_to_url(path){
5
+ let prefix = "file=";
6
+ let path_to_url = path.replaceAll('\\', '/');
7
+ return prefix+path_to_url;
8
+ }
9
+
10
+ function ch_img_node_str(path){
11
+ return `<img src='${ch_convert_file_path_to_url(path)}' style="width:24px"/>`;
12
+ }
13
+
14
+
15
+ function ch_gradio_version(){
16
+ let foot = gradioApp().getElementById("footer");
17
+ if (!foot){return null;}
18
+
19
+ let versions = foot.querySelector(".versions");
20
+ if (!versions){return null;}
21
+
22
+ if (versions.innerHTML.indexOf("gradio: 3.16.2")>0) {
23
+ return "3.16.2";
24
+ } else {
25
+ return "3.23.0";
26
+ }
27
+
28
+ }
29
+
30
+
31
+ // send msg to python side by filling a hidden text box
32
+ // then will click a button to trigger an action
33
+ // msg is an object, not a string, will be stringify in this function
34
+ function send_ch_py_msg(msg){
35
+ console.log("run send_ch_py_msg")
36
+ let js_msg_txtbox = gradioApp().querySelector("#ch_js_msg_txtbox textarea");
37
+ if (js_msg_txtbox && msg) {
38
+ // fill to msg box
39
+ js_msg_txtbox.value = JSON.stringify(msg);
40
+ js_msg_txtbox.dispatchEvent(new Event("input"));
41
+ }
42
+
43
+ }
44
+
45
+ // get msg from python side from a hidden textbox
46
+ // normally this is an old msg, need to wait for a new msg
47
+ function get_ch_py_msg(){
48
+ console.log("run get_ch_py_msg")
49
+ const py_msg_txtbox = gradioApp().querySelector("#ch_py_msg_txtbox textarea");
50
+ if (py_msg_txtbox && py_msg_txtbox.value) {
51
+ console.log("find py_msg_txtbox");
52
+ console.log("py_msg_txtbox value: ");
53
+ console.log(py_msg_txtbox.value)
54
+ return py_msg_txtbox.value
55
+ } else {
56
+ return ""
57
+ }
58
+ }
59
+
60
+
61
+ // get msg from python side from a hidden textbox
62
+ // it will try once in every sencond, until it reach the max try times
63
+ const get_new_ch_py_msg = (max_count=3) => new Promise((resolve, reject) => {
64
+ console.log("run get_new_ch_py_msg")
65
+
66
+ let count = 0;
67
+ let new_msg = "";
68
+ let find_msg = false;
69
+ const interval = setInterval(() => {
70
+ const py_msg_txtbox = gradioApp().querySelector("#ch_py_msg_txtbox textarea");
71
+ count++;
72
+
73
+ if (py_msg_txtbox && py_msg_txtbox.value) {
74
+ console.log("find py_msg_txtbox");
75
+ console.log("py_msg_txtbox value: ");
76
+ console.log(py_msg_txtbox.value)
77
+
78
+ new_msg = py_msg_txtbox.value
79
+ if (new_msg != "") {
80
+ find_msg=true
81
+ }
82
+ }
83
+
84
+ if (find_msg) {
85
+ //clear msg in both sides
86
+ py_msg_txtbox.value = "";
87
+ py_msg_txtbox.dispatchEvent(new Event("input"));
88
+
89
+ resolve(new_msg);
90
+ clearInterval(interval);
91
+ } else if (count > max_count) {
92
+ //clear msg in both sides
93
+ py_msg_txtbox.value = "";
94
+ py_msg_txtbox.dispatchEvent(new Event("input"));
95
+
96
+ reject('');
97
+ clearInterval(interval);
98
+ }
99
+
100
+ }, 1000);
101
+ })
102
+
103
+
104
+ function getActiveTabType() {
105
+ const currentTab = get_uiCurrentTabContent();
106
+ switch (currentTab.id) {
107
+ case "tab_txt2img":
108
+ return "txt2img";
109
+ case "tab_img2img":
110
+ return "img2img";
111
+ }
112
+ return null;
113
+ }
114
+
115
+
116
+
117
+ function getActivePrompt() {
118
+ const currentTab = get_uiCurrentTabContent();
119
+ switch (currentTab.id) {
120
+ case "tab_txt2img":
121
+ return currentTab.querySelector("#txt2img_prompt textarea");
122
+ case "tab_img2img":
123
+ return currentTab.querySelector("#img2img_prompt textarea");
124
+ }
125
+ return null;
126
+ }
127
+
128
+ function getActiveNegativePrompt() {
129
+ const currentTab = get_uiCurrentTabContent();
130
+ switch (currentTab.id) {
131
+ case "tab_txt2img":
132
+ return currentTab.querySelector("#txt2img_neg_prompt textarea");
133
+ case "tab_img2img":
134
+ return currentTab.querySelector("#img2img_neg_prompt textarea");
135
+ }
136
+ return null;
137
+ }
138
+
139
+
140
+ //button's click function
141
+ async function open_model_url(event, model_type, search_term){
142
+ console.log("start open_model_url");
143
+
144
+ //get hidden components of extension
145
+ let js_open_url_btn = gradioApp().getElementById("ch_js_open_url_btn");
146
+ if (!js_open_url_btn) {
147
+ return
148
+ }
149
+
150
+
151
+ //msg to python side
152
+ let msg = {
153
+ "action": "",
154
+ "model_type": "",
155
+ "search_term": "",
156
+ "prompt": "",
157
+ "neg_prompt": "",
158
+ }
159
+
160
+
161
+ msg["action"] = "open_url";
162
+ msg["model_type"] = model_type;
163
+ msg["search_term"] = search_term;
164
+ msg["prompt"] = "";
165
+ msg["neg_prompt"] = "";
166
+
167
+ // fill to msg box
168
+ send_ch_py_msg(msg)
169
+
170
+ //click hidden button
171
+ js_open_url_btn.click();
172
+
173
+ // stop parent event
174
+ event.stopPropagation()
175
+ event.preventDefault()
176
+
177
+ //check response msg from python
178
+ let new_py_msg = await get_new_ch_py_msg();
179
+ console.log("new_py_msg:");
180
+ console.log(new_py_msg);
181
+
182
+ //check msg
183
+ if (new_py_msg) {
184
+ let py_msg_json = JSON.parse(new_py_msg);
185
+ //check for url
186
+ if (py_msg_json && py_msg_json.content) {
187
+ if (py_msg_json.content.url) {
188
+ window.open(py_msg_json.content.url, "_blank");
189
+ }
190
+
191
+ }
192
+
193
+
194
+ }
195
+
196
+
197
+ console.log("end open_model_url");
198
+
199
+
200
+ }
201
+
202
+ function add_trigger_words(event, model_type, search_term){
203
+ console.log("start add_trigger_words");
204
+
205
+ //get hidden components of extension
206
+ let js_add_trigger_words_btn = gradioApp().getElementById("ch_js_add_trigger_words_btn");
207
+ if (!js_add_trigger_words_btn) {
208
+ return
209
+ }
210
+
211
+
212
+ //msg to python side
213
+ let msg = {
214
+ "action": "",
215
+ "model_type": "",
216
+ "search_term": "",
217
+ "prompt": "",
218
+ "neg_prompt": "",
219
+ }
220
+
221
+ msg["action"] = "add_trigger_words";
222
+ msg["model_type"] = model_type;
223
+ msg["search_term"] = search_term;
224
+ msg["neg_prompt"] = "";
225
+
226
+ // get active prompt
227
+ let act_prompt = getActivePrompt();
228
+ msg["prompt"] = act_prompt.value;
229
+
230
+ // fill to msg box
231
+ send_ch_py_msg(msg)
232
+
233
+ //click hidden button
234
+ js_add_trigger_words_btn.click();
235
+
236
+ console.log("end add_trigger_words");
237
+
238
+ event.stopPropagation()
239
+ event.preventDefault()
240
+
241
+
242
+ }
243
+
244
+ function use_preview_prompt(event, model_type, search_term){
245
+ console.log("start use_preview_prompt");
246
+
247
+ //get hidden components of extension
248
+ let js_use_preview_prompt_btn = gradioApp().getElementById("ch_js_use_preview_prompt_btn");
249
+ if (!js_use_preview_prompt_btn) {
250
+ return
251
+ }
252
+
253
+ //msg to python side
254
+ let msg = {
255
+ "action": "",
256
+ "model_type": "",
257
+ "search_term": "",
258
+ "prompt": "",
259
+ "neg_prompt": "",
260
+ }
261
+
262
+ msg["action"] = "use_preview_prompt";
263
+ msg["model_type"] = model_type;
264
+ msg["search_term"] = search_term;
265
+
266
+ // get active prompt
267
+ let act_prompt = getActivePrompt();
268
+ msg["prompt"] = act_prompt.value;
269
+
270
+ // get active neg prompt
271
+ let neg_prompt = getActiveNegativePrompt();
272
+ msg["neg_prompt"] = neg_prompt.value;
273
+
274
+ // fill to msg box
275
+ send_ch_py_msg(msg)
276
+
277
+ //click hidden button
278
+ js_use_preview_prompt_btn.click();
279
+
280
+ console.log("end use_preview_prompt");
281
+
282
+ event.stopPropagation()
283
+ event.preventDefault()
284
+
285
+ }
286
+
287
+
288
+
289
+ // download model's new version into SD at python side
290
+ function ch_dl_model_new_version(event, model_path, version_id, download_url){
291
+ console.log("start ch_dl_model_new_version");
292
+
293
+ // must confirm before downloading
294
+ let dl_confirm = "\nConfirm to download.\n\nCheck Download Model Section's log and console log for detail.";
295
+ if (!confirm(dl_confirm)) {
296
+ return
297
+ }
298
+
299
+ //get hidden components of extension
300
+ let js_dl_model_new_version_btn = gradioApp().getElementById("ch_js_dl_model_new_version_btn");
301
+ if (!js_dl_model_new_version_btn) {
302
+ return
303
+ }
304
+
305
+ //msg to python side
306
+ let msg = {
307
+ "action": "",
308
+ "model_path": "",
309
+ "version_id": "",
310
+ "download_url": "",
311
+ }
312
+
313
+ msg["action"] = "dl_model_new_version";
314
+ msg["model_path"] = model_path;
315
+ msg["version_id"] = version_id;
316
+ msg["download_url"] = download_url;
317
+
318
+ // fill to msg box
319
+ send_ch_py_msg(msg)
320
+
321
+ //click hidden button
322
+ js_dl_model_new_version_btn.click();
323
+
324
+ console.log("end dl_model_new_version");
325
+
326
+ event.stopPropagation()
327
+ event.preventDefault()
328
+
329
+
330
+ }
331
+
332
+
333
+ onUiLoaded(() => {
334
+
335
+ //get gradio version
336
+ let gradio_ver = ch_gradio_version();
337
+ console.log("gradio_ver:" + gradio_ver);
338
+
339
+ // get all extra network tabs
340
+ let tab_prefix_list = ["txt2img", "img2img"];
341
+ let model_type_list = ["textual_inversion", "hypernetworks", "checkpoints", "lora"];
342
+ let cardid_suffix = "cards";
343
+
344
+ //get init py msg
345
+ // let init_py_msg_str = get_ch_py_msg();
346
+ // let extension_path = "";
347
+ // if (!init_py_msg_str) {
348
+ // console.log("Can not get init_py_msg");
349
+ // } else {
350
+ // init_py_msg = JSON.parse(init_py_msg_str);
351
+ // if (init_py_msg) {
352
+ // extension_path = init_py_msg.extension_path;
353
+ // console.log("get extension path: " + extension_path);
354
+ // }
355
+ // }
356
+
357
+ // //icon image node as string
358
+ // function icon(icon_name){
359
+ // let icon_path = extension_path+"/icon/"+icon_name;
360
+ // return ch_img_node_str(icon_path);
361
+ // }
362
+
363
+
364
+ // update extra network tab pages' cards
365
+ // * replace "replace preview" text button into an icon
366
+ // * add 3 button to each card:
367
+ // - open model url 🌐
368
+ // - add trigger words 💡
369
+ // - use preview image's prompt 🏷️
370
+ // notice: javascript can not get response from python side
371
+ // so, these buttons just sent request to python
372
+ // then, python side gonna open url and update prompt text box, without telling js side.
373
+ function update_card_for_civitai(){
374
+
375
+ //css
376
+ let btn_margin = "0px 5px";
377
+ let btn_fontSize = "200%";
378
+ let btn_thumb_fontSize = "100%";
379
+ let btn_thumb_display = "inline";
380
+ let btn_thumb_pos = "static";
381
+ let btn_thumb_backgroundImage = "none";
382
+ let btn_thumb_background = "rgba(0, 0, 0, 0.8)";
383
+
384
+ let ch_btn_txts = ['🌐', '💡', '🏷️'];
385
+ let replace_preview_text = getTranslation("replace preview");
386
+ if (!replace_preview_text) {
387
+ replace_preview_text = "replace preview";
388
+ }
389
+
390
+
391
+
392
+ // get component
393
+ let ch_always_display_ckb = gradioApp().querySelector("#ch_always_display_ckb input");
394
+ let ch_show_btn_on_thumb_ckb = gradioApp().querySelector("#ch_show_btn_on_thumb_ckb input");
395
+ let ch_always_display = false;
396
+ let ch_show_btn_on_thumb = false;
397
+ if (ch_always_display_ckb) {
398
+ ch_always_display = ch_always_display_ckb.checked;
399
+ }
400
+ if (ch_show_btn_on_thumb_ckb) {
401
+ ch_show_btn_on_thumb = ch_show_btn_on_thumb_ckb.checked;
402
+ }
403
+
404
+
405
+ //change all "replace preview" into an icon
406
+ let extra_network_id = "";
407
+ let extra_network_node = null;
408
+ let metadata_button = null;
409
+ let additional_node = null;
410
+ let replace_preview_btn = null;
411
+ let ul_node = null;
412
+ let search_term_node = null;
413
+ let search_term = "";
414
+ let model_type = "";
415
+ let cards = null;
416
+ let need_to_add_buttons = false;
417
+ let is_thumb_mode = false;
418
+
419
+ //get current tab
420
+ let active_tab_type = getActiveTabType();
421
+ if (!active_tab_type){active_tab_type = "txt2img";}
422
+
423
+ for (const tab_prefix of tab_prefix_list) {
424
+ if (tab_prefix != active_tab_type) {continue;}
425
+
426
+
427
+ //find out current selected model type tab
428
+ let active_extra_tab_type = "";
429
+ let extra_tabs = gradioApp().getElementById(tab_prefix+"_extra_tabs");
430
+ if (!extra_tabs) {console.log("can not find extra_tabs: " + tab_prefix+"_extra_tabs");}
431
+
432
+ //get active extratab
433
+ const active_extra_tab = Array.from(get_uiCurrentTabContent().querySelectorAll('.extra-network-cards,.extra-network-thumbs'))
434
+ .find(el => el.closest('.tabitem').style.display === 'block')
435
+ ?.id.match(/^(txt2img|img2img)_(.+)_cards$/)[2]
436
+
437
+
438
+ console.log("found active tab: " + active_extra_tab);
439
+
440
+ switch (active_extra_tab) {
441
+ case "textual_inversion":
442
+ active_extra_tab_type = "ti";
443
+ break;
444
+ case "hypernetworks":
445
+ active_extra_tab_type = "hyper";
446
+ break;
447
+ case "checkpoints":
448
+ active_extra_tab_type = "ckp";
449
+ break;
450
+ case "lora":
451
+ active_extra_tab_type = "lora";
452
+ break;
453
+ }
454
+
455
+
456
+ for (const js_model_type of model_type_list) {
457
+ //get model_type for python side
458
+ switch (js_model_type) {
459
+ case "textual_inversion":
460
+ model_type = "ti";
461
+ break;
462
+ case "hypernetworks":
463
+ model_type = "hyper";
464
+ break;
465
+ case "checkpoints":
466
+ model_type = "ckp";
467
+ break;
468
+ case "lora":
469
+ model_type = "lora";
470
+ break;
471
+ }
472
+
473
+ if (!model_type) {
474
+ console.log("can not get model_type from: " + js_model_type);
475
+ continue;
476
+ }
477
+
478
+
479
+ //only handle current sub-tab
480
+ if (model_type != active_extra_tab_type) {
481
+ continue;
482
+ }
483
+
484
+ console.log("handle active extra tab");
485
+
486
+
487
+ extra_network_id = tab_prefix+"_"+js_model_type+"_"+cardid_suffix;
488
+ // console.log("searching extra_network_node: " + extra_network_id);
489
+ extra_network_node = gradioApp().getElementById(extra_network_id);
490
+ // check if extr network is under thumbnail mode
491
+ is_thumb_mode = false
492
+ if (extra_network_node) {
493
+ if (extra_network_node.className == "extra-network-thumbs") {
494
+ console.log(extra_network_id + " is in thumbnail mode");
495
+ is_thumb_mode = true;
496
+ // if (!ch_show_btn_on_thumb) {continue;}
497
+ }
498
+ } else {
499
+ console.log("can not find extra_network_node: " + extra_network_id);
500
+ continue;
501
+ }
502
+ // console.log("find extra_network_node: " + extra_network_id);
503
+
504
+ // get all card nodes
505
+ cards = extra_network_node.querySelectorAll(".card");
506
+ for (let card of cards) {
507
+ //metadata_buttoncard
508
+ metadata_button = card.querySelector(".metadata-button");
509
+ //additional node
510
+ additional_node = card.querySelector(".actions .additional");
511
+ //get ul node, which is the parent of all buttons
512
+ ul_node = card.querySelector(".actions .additional ul");
513
+ // replace preview text button
514
+ replace_preview_btn = card.querySelector(".actions .additional a");
515
+
516
+ // check thumb mode
517
+ if (is_thumb_mode) {
518
+ additional_node.style.display = null;
519
+
520
+ if (ch_show_btn_on_thumb) {
521
+ ul_node.style.background = btn_thumb_background;
522
+ } else {
523
+ //reset
524
+ ul_node.style.background = null;
525
+ // console.log("remove existed buttons");
526
+ // remove existed buttons
527
+ if (ul_node) {
528
+ // find all .a child nodes
529
+ let atags = ul_node.querySelectorAll("a");
530
+
531
+ for (let atag of atags) {
532
+ //reset display
533
+ atag.style.display = null;
534
+ //remove extension's button
535
+ if (ch_btn_txts.indexOf(atag.innerHTML)>=0) {
536
+ //need to remove
537
+ ul_node.removeChild(atag);
538
+ } else {
539
+ //do not remove, just reset
540
+ atag.innerHTML = replace_preview_text;
541
+ atag.style.display = null;
542
+ atag.style.fontSize = null;
543
+ atag.style.position = null;
544
+ atag.style.backgroundImage = null;
545
+ }
546
+ }
547
+
548
+ //also remove br tag in ul
549
+ let brtag = ul_node.querySelector("br");
550
+ if (brtag) {
551
+ ul_node.removeChild(brtag);
552
+ }
553
+
554
+ }
555
+ //just reset and remove nodes, do nothing else
556
+ continue;
557
+
558
+ }
559
+
560
+ } else {
561
+ // full preview mode
562
+ if (ch_always_display) {
563
+ additional_node.style.display = "block";
564
+ } else {
565
+ additional_node.style.display = null;
566
+ }
567
+
568
+ // remove br tag
569
+ let brtag = ul_node.querySelector("br");
570
+ if (brtag) {
571
+ ul_node.removeChild(brtag);
572
+ }
573
+
574
+ }
575
+
576
+ // change replace preview text button into icon
577
+ if (replace_preview_btn) {
578
+ if (replace_preview_btn.innerHTML !== "🖼️") {
579
+ need_to_add_buttons = true;
580
+ replace_preview_btn.innerHTML = "🖼️";
581
+ if (!is_thumb_mode) {
582
+ replace_preview_btn.style.fontSize = btn_fontSize;
583
+ replace_preview_btn.style.margin = btn_margin;
584
+ } else {
585
+ replace_preview_btn.style.display = btn_thumb_display;
586
+ replace_preview_btn.style.fontSize = btn_thumb_fontSize;
587
+ replace_preview_btn.style.position = btn_thumb_pos;
588
+ replace_preview_btn.style.backgroundImage = btn_thumb_backgroundImage;
589
+ }
590
+
591
+ }
592
+ }
593
+
594
+ if (!need_to_add_buttons) {
595
+ continue;
596
+ }
597
+
598
+
599
+ // search_term node
600
+ // search_term = subfolder path + model name + ext
601
+ search_term_node = card.querySelector(".actions .additional .search_term");
602
+ if (!search_term_node){
603
+ console.log("can not find search_term node for cards in " + extra_network_id);
604
+ continue;
605
+ }
606
+
607
+ // get search_term
608
+ search_term = search_term_node.innerHTML;
609
+ if (!search_term) {
610
+ console.log("search_term is empty for cards in " + extra_network_id);
611
+ continue;
612
+ }
613
+
614
+
615
+
616
+ // if (is_thumb_mode) {
617
+ // ul_node.style.background = btn_thumb_background;
618
+ // }
619
+
620
+ // then we need to add 3 buttons to each ul node:
621
+ let open_url_node = document.createElement("a");
622
+ open_url_node.href = "#";
623
+ open_url_node.innerHTML = "🌐";
624
+ if (!is_thumb_mode) {
625
+ open_url_node.style.fontSize = btn_fontSize;
626
+ open_url_node.style.margin = btn_margin;
627
+ } else {
628
+ open_url_node.style.display = btn_thumb_display;
629
+ open_url_node.style.fontSize = btn_thumb_fontSize;
630
+ open_url_node.style.position = btn_thumb_pos;
631
+ open_url_node.style.backgroundImage = btn_thumb_backgroundImage;
632
+ }
633
+ open_url_node.title = "Open this model's civitai url";
634
+ open_url_node.setAttribute("onclick","open_model_url(event, '"+model_type+"', '"+search_term+"')");
635
+
636
+ let add_trigger_words_node = document.createElement("a");
637
+ add_trigger_words_node.href = "#";
638
+ add_trigger_words_node.innerHTML = "💡";
639
+ if (!is_thumb_mode) {
640
+ add_trigger_words_node.style.fontSize = btn_fontSize;
641
+ add_trigger_words_node.style.margin = btn_margin;
642
+ } else {
643
+ add_trigger_words_node.style.display = btn_thumb_display;
644
+ add_trigger_words_node.style.fontSize = btn_thumb_fontSize;
645
+ add_trigger_words_node.style.position = btn_thumb_pos;
646
+ add_trigger_words_node.style.backgroundImage = btn_thumb_backgroundImage;
647
+ }
648
+
649
+ add_trigger_words_node.title = "Add trigger words to prompt";
650
+ add_trigger_words_node.setAttribute("onclick","add_trigger_words(event, '"+model_type+"', '"+search_term+"')");
651
+
652
+ let use_preview_prompt_node = document.createElement("a");
653
+ use_preview_prompt_node.href = "#";
654
+ use_preview_prompt_node.innerHTML = "🏷️";
655
+ if (!is_thumb_mode) {
656
+ use_preview_prompt_node.style.fontSize = btn_fontSize;
657
+ use_preview_prompt_node.style.margin = btn_margin;
658
+ } else {
659
+ use_preview_prompt_node.style.display = btn_thumb_display;
660
+ use_preview_prompt_node.style.fontSize = btn_thumb_fontSize;
661
+ use_preview_prompt_node.style.position = btn_thumb_pos;
662
+ use_preview_prompt_node.style.backgroundImage = btn_thumb_backgroundImage;
663
+ }
664
+ use_preview_prompt_node.title = "Use prompt from preview image";
665
+ use_preview_prompt_node.setAttribute("onclick","use_preview_prompt(event, '"+model_type+"', '"+search_term+"')");
666
+
667
+ //add to card
668
+ ul_node.appendChild(open_url_node);
669
+ //add br if metadata_button exists
670
+ if (is_thumb_mode && metadata_button) {
671
+ ul_node.appendChild(document.createElement("br"));
672
+ }
673
+ ul_node.appendChild(add_trigger_words_node);
674
+ ul_node.appendChild(use_preview_prompt_node);
675
+
676
+
677
+
678
+
679
+ }
680
+
681
+
682
+ }
683
+ }
684
+
685
+
686
+ }
687
+
688
+
689
+ let tab_id = ""
690
+ let extra_tab = null;
691
+ let extra_toolbar = null;
692
+ let extra_network_refresh_btn = null;
693
+ //add refresh button to extra network's toolbar
694
+ for (let prefix of tab_prefix_list) {
695
+ tab_id = prefix + "_extra_tabs";
696
+ extra_tab = gradioApp().getElementById(tab_id);
697
+
698
+ //get toolbar
699
+ //get Refresh button
700
+ extra_network_refresh_btn = gradioApp().getElementById(prefix+"_extra_refresh");
701
+
702
+
703
+ if (!extra_network_refresh_btn){
704
+ console.log("can not get extra network refresh button for " + tab_id);
705
+ continue;
706
+ }
707
+
708
+ // add refresh button to toolbar
709
+ let ch_refresh = document.createElement("button");
710
+ ch_refresh.innerHTML = "🔁";
711
+ ch_refresh.title = "Refresh Civitai Helper's additional buttons";
712
+ ch_refresh.className = "lg secondary gradio-button";
713
+ ch_refresh.style.fontSize = "200%";
714
+ ch_refresh.onclick = update_card_for_civitai;
715
+
716
+ extra_network_refresh_btn.parentNode.appendChild(ch_refresh);
717
+
718
+ }
719
+
720
+
721
+ //run it once
722
+ update_card_for_civitai();
723
+
724
+
725
+ });
726
+
727
+
728
+
Stable-Diffusion-Webui-Civitai-Helper/scripts/__pycache__/civitai_helper.cpython-310.pyc ADDED
Binary file (6.99 kB). View file
 
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__init__.py ADDED
File without changes
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (192 Bytes). View file
 
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/civitai.cpython-310.pyc ADDED
Binary file (9.18 kB). View file
 
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/downloader.cpython-310.pyc ADDED
Binary file (2.14 kB). View file
 
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/js_action_civitai.cpython-310.pyc ADDED
Binary file (4.56 kB). View file
 
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/model.cpython-310.pyc ADDED
Binary file (2.68 kB). View file
 
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/model_action_civitai.cpython-310.pyc ADDED
Binary file (8.58 kB). View file
 
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/msg_handler.cpython-310.pyc ADDED
Binary file (1.21 kB). View file
 
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/setting.cpython-310.pyc ADDED
Binary file (1.78 kB). View file
 
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/__pycache__/util.cpython-310.pyc ADDED
Binary file (2.63 kB). View file
 
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/civitai.py ADDED
@@ -0,0 +1,612 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: UTF-8 -*-
2
+ # handle msg between js and python side
3
+ import os
4
+ import time
5
+ import json
6
+ import re
7
+ import requests
8
+ from . import util
9
+ from . import model
10
+ from . import setting
11
+
12
+ suffix = ".civitai"
13
+
14
+ url_dict = {
15
+ "modelPage":"https://civitai.com/models/",
16
+ "modelId": "https://civitai.com/api/v1/models/",
17
+ "modelVersionId": "https://civitai.com/api/v1/model-versions/",
18
+ "hash": "https://civitai.com/api/v1/model-versions/by-hash/"
19
+ }
20
+
21
+ model_type_dict = {
22
+ "Checkpoint": "ckp",
23
+ "TextualInversion": "ti",
24
+ "Hypernetwork": "hyper",
25
+ "LORA": "lora",
26
+ "LoCon": "lora",
27
+ }
28
+
29
+
30
+
31
+ # get image with full size
32
+ # width is in number, not string
33
+ # return: url str
34
+ def get_full_size_image_url(image_url, width):
35
+ return re.sub('/width=\d+/', '/width=' + str(width) + '/', image_url)
36
+
37
+
38
+ # use this sha256 to get model info from civitai
39
+ # return: model info dict
40
+ def get_model_info_by_hash(hash:str):
41
+ util.printD("Request model info from civitai")
42
+
43
+ if not hash:
44
+ util.printD("hash is empty")
45
+ return
46
+
47
+ r = requests.get(url_dict["hash"]+hash, headers=util.def_headers, proxies=util.proxies)
48
+ if not r.ok:
49
+ if r.status_code == 404:
50
+ # this is not a civitai model
51
+ util.printD("Civitai does not have this model")
52
+ return {}
53
+ else:
54
+ util.printD("Get error code: " + str(r.status_code))
55
+ util.printD(r.text)
56
+ return
57
+
58
+ # try to get content
59
+ content = None
60
+ try:
61
+ content = r.json()
62
+ except Exception as e:
63
+ util.printD("Parse response json failed")
64
+ util.printD(str(e))
65
+ util.printD("response:")
66
+ util.printD(r.text)
67
+ return
68
+
69
+ if not content:
70
+ util.printD("error, content from civitai is None")
71
+ return
72
+
73
+ return content
74
+
75
+
76
+
77
+ def get_model_info_by_id(id:str) -> dict:
78
+ util.printD("Request model info from civitai")
79
+
80
+ if not id:
81
+ util.printD("id is empty")
82
+ return
83
+
84
+ r = requests.get(url_dict["modelId"]+str(id), headers=util.def_headers, proxies=util.proxies)
85
+ if not r.ok:
86
+ if r.status_code == 404:
87
+ # this is not a civitai model
88
+ util.printD("Civitai does not have this model")
89
+ return {}
90
+ else:
91
+ util.printD("Get error code: " + str(r.status_code))
92
+ util.printD(r.text)
93
+ return
94
+
95
+ # try to get content
96
+ content = None
97
+ try:
98
+ content = r.json()
99
+ except Exception as e:
100
+ util.printD("Parse response json failed")
101
+ util.printD(str(e))
102
+ util.printD("response:")
103
+ util.printD(r.text)
104
+ return
105
+
106
+ if not content:
107
+ util.printD("error, content from civitai is None")
108
+ return
109
+
110
+ return content
111
+
112
+
113
+ def get_version_info_by_version_id(id:str) -> dict:
114
+ util.printD("Request version info from civitai")
115
+
116
+ if not id:
117
+ util.printD("id is empty")
118
+ return
119
+
120
+ r = requests.get(url_dict["modelVersionId"]+str(id), headers=util.def_headers, proxies=util.proxies)
121
+ if not r.ok:
122
+ if r.status_code == 404:
123
+ # this is not a civitai model
124
+ util.printD("Civitai does not have this model version")
125
+ return {}
126
+ else:
127
+ util.printD("Get error code: " + str(r.status_code))
128
+ util.printD(r.text)
129
+ return
130
+
131
+ # try to get content
132
+ content = None
133
+ try:
134
+ content = r.json()
135
+ except Exception as e:
136
+ util.printD("Parse response json failed")
137
+ util.printD(str(e))
138
+ util.printD("response:")
139
+ util.printD(r.text)
140
+ return
141
+
142
+ if not content:
143
+ util.printD("error, content from civitai is None")
144
+ return
145
+
146
+ return content
147
+
148
+
149
+ def get_version_info_by_model_id(id:str) -> dict:
150
+
151
+ model_info = get_model_info_by_id(id)
152
+ if not model_info:
153
+ util.printD(f"Failed to get model info by id: {id}")
154
+ return
155
+
156
+ # check content to get version id
157
+ if "modelVersions" not in model_info.keys():
158
+ util.printD("There is no modelVersions in this model_info")
159
+ return
160
+
161
+ if not model_info["modelVersions"]:
162
+ util.printD("modelVersions is None")
163
+ return
164
+
165
+ if len(model_info["modelVersions"])==0:
166
+ util.printD("modelVersions is Empty")
167
+ return
168
+
169
+ def_version = model_info["modelVersions"][0]
170
+ if not def_version:
171
+ util.printD("default version is None")
172
+ return
173
+
174
+ if "id" not in def_version.keys():
175
+ util.printD("default version has no id")
176
+ return
177
+
178
+ version_id = def_version["id"]
179
+
180
+ if not version_id:
181
+ util.printD("default version's id is None")
182
+ return
183
+
184
+ # get version info
185
+ version_info = get_version_info_by_version_id(str(version_id))
186
+ if not version_info:
187
+ util.printD(f"Failed to get version info by version_id: {version_id}")
188
+ return
189
+
190
+ return version_info
191
+
192
+
193
+
194
+
195
+ # get model info file's content by model type and search_term
196
+ # parameter: model_type, search_term
197
+ # return: model_info
198
+ def load_model_info_by_search_term(model_type, search_term):
199
+ util.printD(f"Load model info of {search_term} in {model_type}")
200
+ if model_type not in model.folders.keys():
201
+ util.printD("unknow model type: " + model_type)
202
+ return
203
+
204
+ # search_term = subfolderpath + model name + ext. And it always start with a / even there is no sub folder
205
+ base, ext = os.path.splitext(search_term)
206
+ model_info_base = base
207
+ if base[:1] == "/":
208
+ model_info_base = base[1:]
209
+
210
+ model_folder = model.folders[model_type]
211
+ model_info_filename = model_info_base + suffix + model.info_ext
212
+ model_info_filepath = os.path.join(model_folder, model_info_filename)
213
+
214
+ if not os.path.isfile(model_info_filepath):
215
+ util.printD("Can not find model info file: " + model_info_filepath)
216
+ return
217
+
218
+ return model.load_model_info(model_info_filepath)
219
+
220
+
221
+
222
+
223
+
224
+ # get model file names by model type
225
+ # parameter: model_type - string
226
+ # parameter: filter - dict, which kind of model you need
227
+ # return: model name list
228
+ def get_model_names_by_type_and_filter(model_type:str, filter:dict) -> list:
229
+
230
+ model_folder = model.folders[model_type]
231
+
232
+ # set filter
233
+ # only get models don't have a civitai info file
234
+ no_info_only = False
235
+ empty_info_only = False
236
+
237
+ if filter:
238
+ if "no_info_only" in filter.keys():
239
+ no_info_only = filter["no_info_only"]
240
+ if "empty_info_only" in filter.keys():
241
+ empty_info_only = filter["empty_info_only"]
242
+
243
+
244
+
245
+ # get information from filter
246
+ # only get those model names don't have a civitai model info file
247
+ model_names = []
248
+ for root, dirs, files in os.walk(model_folder, followlinks=True):
249
+ for filename in files:
250
+ item = os.path.join(root, filename)
251
+ # check extension
252
+ base, ext = os.path.splitext(item)
253
+ if ext in model.exts:
254
+ # find a model
255
+
256
+ # check filter
257
+ if no_info_only:
258
+ # check model info file
259
+ info_file = base + suffix + model.info_ext
260
+ if os.path.isfile(info_file):
261
+ continue
262
+
263
+ if empty_info_only:
264
+ # check model info file
265
+ info_file = base + suffix + model.info_ext
266
+ if os.path.isfile(info_file):
267
+ # load model info
268
+ model_info = model.load_model_info(info_file)
269
+ # check content
270
+ if model_info:
271
+ if "id" in model_info.keys():
272
+ # find a non-empty model info file
273
+ continue
274
+
275
+ model_names.append(filename)
276
+
277
+
278
+ return model_names
279
+
280
+ def get_model_names_by_input(model_type, empty_info_only):
281
+ return get_model_names_by_type_and_filter(model_type, {"empty_info_only":empty_info_only})
282
+
283
+
284
+ # get id from url
285
+ def get_model_id_from_url(url:str) -> str:
286
+ util.printD("Run get_model_id_from_url")
287
+ id = ""
288
+
289
+ if not url:
290
+ util.printD("url or model id can not be empty")
291
+ return ""
292
+
293
+ if url.isnumeric():
294
+ # is already an id
295
+ id = str(url)
296
+ return id
297
+
298
+ s = re.sub("\\?.+$", "", url).split("/")
299
+ if len(s) < 2:
300
+ util.printD("url is not valid")
301
+ return ""
302
+
303
+ if s[-2].isnumeric():
304
+ id = s[-2]
305
+ elif s[-1].isnumeric():
306
+ id = s[-1]
307
+ else:
308
+ util.printD("There is no model id in this url")
309
+ return ""
310
+
311
+ return id
312
+
313
+
314
+ # get preview image by model path
315
+ # image will be saved to file, so no return
316
+ def get_preview_image_by_model_path(model_path:str, max_size_preview, skip_nsfw_preview):
317
+ if not model_path:
318
+ util.printD("model_path is empty")
319
+ return
320
+
321
+ if not os.path.isfile(model_path):
322
+ util.printD("model_path is not a file: "+model_path)
323
+ return
324
+
325
+ base, ext = os.path.splitext(model_path)
326
+ first_preview = base+".png"
327
+ sec_preview = base+".preview.png"
328
+ info_file = base + suffix + model.info_ext
329
+
330
+ # check preview image
331
+ if not os.path.isfile(sec_preview):
332
+ # need to download preview image
333
+ util.printD("Checking preview image for model: " + model_path)
334
+ # load model_info file
335
+ if os.path.isfile(info_file):
336
+ model_info = model.load_model_info(info_file)
337
+ if not model_info:
338
+ util.printD("Model Info is empty")
339
+ return
340
+
341
+ if "images" in model_info.keys():
342
+ if model_info["images"]:
343
+ for img_dict in model_info["images"]:
344
+ if "nsfw" in img_dict.keys():
345
+ if img_dict["nsfw"]:
346
+ util.printD("This image is NSFW")
347
+ if skip_nsfw_preview:
348
+ util.printD("Skip NSFW image")
349
+ continue
350
+
351
+ if "url" in img_dict.keys():
352
+ img_url = img_dict["url"]
353
+ if max_size_preview:
354
+ # use max width
355
+ if "width" in img_dict.keys():
356
+ if img_dict["width"]:
357
+ img_url = get_full_size_image_url(img_url, img_dict["width"])
358
+
359
+ util.download_file(img_url, sec_preview)
360
+ # we only need 1 preview image
361
+ break
362
+
363
+
364
+
365
+ # search local model by version id in 1 folder, no subfolder
366
+ # return - model_info
367
+ def search_local_model_info_by_version_id(folder:str, version_id:int) -> dict:
368
+ util.printD("Searching local model by version id")
369
+ util.printD("folder: " + folder)
370
+ util.printD("version_id: " + str(version_id))
371
+
372
+ if not folder:
373
+ util.printD("folder is none")
374
+ return
375
+
376
+ if not os.path.isdir(folder):
377
+ util.printD("folder is not a dir")
378
+ return
379
+
380
+ if not version_id:
381
+ util.printD("version_id is none")
382
+ return
383
+
384
+ # search civitai model info file
385
+ for filename in os.listdir(folder):
386
+ # check ext
387
+ base, ext = os.path.splitext(filename)
388
+ if ext == model.info_ext:
389
+ # find info file
390
+ if len(base) < 9:
391
+ # not a civitai info file
392
+ continue
393
+
394
+ if base[-8:] == suffix:
395
+ # find a civitai info file
396
+ path = os.path.join(folder, filename)
397
+ model_info = model.load_model_info(path)
398
+ if not model_info:
399
+ continue
400
+
401
+ if "id" not in model_info.keys():
402
+ continue
403
+
404
+ id = model_info["id"]
405
+ if not id:
406
+ continue
407
+
408
+ # util.printD(f"Compare version id, src: {id}, target:{version_id}")
409
+ if str(id) == str(version_id):
410
+ # find the one
411
+ return model_info
412
+
413
+
414
+ return
415
+
416
+
417
+
418
+
419
+
420
+ # check new version for a model by model path
421
+ # return (model_path, model_id, model_name, new_verion_id, new_version_name, description, download_url, img_url)
422
+ def check_model_new_version_by_path(model_path:str, delay:float=1) -> tuple:
423
+ if not model_path:
424
+ util.printD("model_path is empty")
425
+ return
426
+
427
+ if not os.path.isfile(model_path):
428
+ util.printD("model_path is not a file: "+model_path)
429
+ return
430
+
431
+ # get model info file name
432
+ base, ext = os.path.splitext(model_path)
433
+ info_file = base + suffix + model.info_ext
434
+
435
+ if not os.path.isfile(info_file):
436
+ return
437
+
438
+ # get model info
439
+ model_info_file = model.load_model_info(info_file)
440
+ if not model_info_file:
441
+ return
442
+
443
+ if "id" not in model_info_file.keys():
444
+ return
445
+
446
+ local_version_id = model_info_file["id"]
447
+ if not local_version_id:
448
+ return
449
+
450
+ if "modelId" not in model_info_file.keys():
451
+ return
452
+
453
+ model_id = model_info_file["modelId"]
454
+ if not model_id:
455
+ return
456
+
457
+ # get model info by id from civitai
458
+ model_info = get_model_info_by_id(model_id)
459
+ # delay before next request, to prevent to be treat as DDoS
460
+ util.printD(f"delay:{delay} second")
461
+ time.sleep(delay)
462
+
463
+ if not model_info:
464
+ return
465
+
466
+ if "modelVersions" not in model_info.keys():
467
+ return
468
+
469
+ modelVersions = model_info["modelVersions"]
470
+ if not modelVersions:
471
+ return
472
+
473
+ if not len(modelVersions):
474
+ return
475
+
476
+ current_version = modelVersions[0]
477
+ if not current_version:
478
+ return
479
+
480
+ if "id" not in current_version.keys():
481
+ return
482
+
483
+ current_version_id = current_version["id"]
484
+ if not current_version_id:
485
+ return
486
+
487
+ util.printD(f"Compare version id, local: {local_version_id}, remote: {current_version_id} ")
488
+ if current_version_id == local_version_id:
489
+ return
490
+
491
+ model_name = ""
492
+ if "name" in model_info.keys():
493
+ model_name = model_info["name"]
494
+
495
+ if not model_name:
496
+ model_name = ""
497
+
498
+
499
+ new_version_name = ""
500
+ if "name" in current_version.keys():
501
+ new_version_name = current_version["name"]
502
+
503
+ if not new_version_name:
504
+ new_version_name = ""
505
+
506
+ description = ""
507
+ if "description" in current_version.keys():
508
+ description = current_version["description"]
509
+
510
+ if not description:
511
+ description = ""
512
+
513
+ downloadUrl = ""
514
+ if "downloadUrl" in current_version.keys():
515
+ downloadUrl = current_version["downloadUrl"]
516
+
517
+ if not downloadUrl:
518
+ downloadUrl = ""
519
+
520
+ # get 1 preview image
521
+ img_url = ""
522
+ if "images" in current_version.keys():
523
+ if current_version["images"]:
524
+ if current_version["images"][0]:
525
+ if "url" in current_version["images"][0].keys():
526
+ img_url = current_version["images"][0]["url"]
527
+ if not img_url:
528
+ img_url = ""
529
+
530
+
531
+
532
+ return (model_path, model_id, model_name, current_version_id, new_version_name, description, downloadUrl, img_url)
533
+
534
+
535
+
536
+
537
+ # check model's new version
538
+ # parameter: delay - float, how many seconds to delay between each request to civitai
539
+ # return: new_versions - a list for all new versions, each one is (model_path, model_id, model_name, new_verion_id, new_version_name, description, download_url, img_url)
540
+ def check_models_new_version_by_model_types(model_types:list, delay:float=1) -> list:
541
+ util.printD("Checking models' new version")
542
+
543
+ if not model_types:
544
+ return []
545
+
546
+ # check model types, which cloud be a string as 1 type
547
+ mts = []
548
+ if type(model_types) == str:
549
+ mts.append(model_types)
550
+ elif type(model_types) == list:
551
+ mts = model_types
552
+ else:
553
+ util.printD("Unknow model types:")
554
+ util.printD(model_types)
555
+ return []
556
+
557
+ # output is a markdown document string to show a list of new versions on UI
558
+ output = ""
559
+ # new version list
560
+ new_versions = []
561
+
562
+ # walk all models
563
+ for model_type, model_folder in model.folders.items():
564
+ if model_type not in mts:
565
+ continue
566
+
567
+ util.printD("Scanning path: " + model_folder)
568
+ for root, dirs, files in os.walk(model_folder, followlinks=True):
569
+ for filename in files:
570
+ # check ext
571
+ item = os.path.join(root, filename)
572
+ base, ext = os.path.splitext(item)
573
+ if ext in model.exts:
574
+ # find a model
575
+ r = check_model_new_version_by_path(item, delay)
576
+
577
+ if not r:
578
+ continue
579
+
580
+ model_path, model_id, model_name, current_version_id, new_version_name, description, downloadUrl, img_url = r
581
+ # check exist
582
+ if not current_version_id:
583
+ continue
584
+
585
+ # check this version id in list
586
+ is_already_in_list = False
587
+ for new_version in new_versions:
588
+ if current_version_id == new_version[3]:
589
+ # already in list
590
+ is_already_in_list = True
591
+ break
592
+
593
+ if is_already_in_list:
594
+ util.printD("New version is already in list")
595
+ continue
596
+
597
+ # search this new version id to check if this model is already downloaded
598
+ target_model_info = search_local_model_info_by_version_id(root, current_version_id)
599
+ if target_model_info:
600
+ util.printD("New version is already existed")
601
+ continue
602
+
603
+ # add to list
604
+ new_versions.append(r)
605
+
606
+
607
+
608
+
609
+ return new_versions
610
+
611
+
612
+
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/downloader.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: UTF-8 -*-
2
+ import sys
3
+ import requests
4
+ import os
5
+ from . import util
6
+
7
+
8
+ dl_ext = ".downloading"
9
+
10
+ # disable ssl warning info
11
+ requests.packages.urllib3.disable_warnings()
12
+
13
+ # output is downloaded file path
14
+ def dl(url, folder, filename, filepath):
15
+ util.printD("Start downloading from: " + url)
16
+ # get file_path
17
+ file_path = ""
18
+ if filepath:
19
+ file_path = filepath
20
+ else:
21
+ # if file_path is not in parameter, then folder must be in parameter
22
+ if not folder:
23
+ util.printD("folder is none")
24
+ return
25
+
26
+ if not os.path.isdir(folder):
27
+ util.printD("folder does not exist: "+folder)
28
+ return
29
+
30
+ if filename:
31
+ file_path = os.path.join(folder, filename)
32
+
33
+ # first request for header
34
+ rh = requests.get(url, stream=True, verify=False, headers=util.def_headers, proxies=util.proxies)
35
+ # get file size
36
+ total_size = 0
37
+ total_size = int(rh.headers['Content-Length'])
38
+ util.printD(f"File size: {total_size}")
39
+
40
+ # if file_path is empty, need to get file name from download url's header
41
+ if not file_path:
42
+ filename = ""
43
+ if "Content-Disposition" in rh.headers.keys():
44
+ cd = rh.headers["Content-Disposition"]
45
+ # Extract the filename from the header
46
+ # content of a CD: "attachment;filename=FileName.txt"
47
+ # in case "" is in CD filename's start and end, need to strip them out
48
+ filename = cd.split("=")[1].strip('"')
49
+ if not filename:
50
+ util.printD("Fail to get file name from Content-Disposition: " + cd)
51
+ return
52
+
53
+ if not filename:
54
+ util.printD("Can not get file name from download url's header")
55
+ return
56
+
57
+ # with folder and filename, now we have the full file path
58
+ file_path = os.path.join(folder, filename)
59
+
60
+
61
+ util.printD("Target file path: " + file_path)
62
+ base, ext = os.path.splitext(file_path)
63
+
64
+ # check if file is already exist
65
+ count = 2
66
+ new_base = base
67
+ while os.path.isfile(file_path):
68
+ util.printD("Target file already exist.")
69
+ # re-name
70
+ new_base = base + "_" + str(count)
71
+ file_path = new_base + ext
72
+ count += 1
73
+
74
+ # use a temp file for downloading
75
+ dl_file_path = new_base+dl_ext
76
+
77
+
78
+ util.printD(f"Downloading to temp file: {dl_file_path}")
79
+
80
+ # check if downloading file is exsited
81
+ downloaded_size = 0
82
+ if os.path.exists(dl_file_path):
83
+ downloaded_size = os.path.getsize(dl_file_path)
84
+
85
+ util.printD(f"Downloaded size: {downloaded_size}")
86
+
87
+ # create header range
88
+ headers = {'Range': 'bytes=%d-' % downloaded_size}
89
+ headers['User-Agent'] = util.def_headers['User-Agent']
90
+
91
+ # download with header
92
+ r = requests.get(url, stream=True, verify=False, headers=headers, proxies=util.proxies)
93
+
94
+ # write to file
95
+ with open(dl_file_path, "ab") as f:
96
+ for chunk in r.iter_content(chunk_size=1024):
97
+ if chunk:
98
+ downloaded_size += len(chunk)
99
+ f.write(chunk)
100
+ # force to write to disk
101
+ f.flush()
102
+
103
+ # progress
104
+ progress = int(50 * downloaded_size / total_size)
105
+ sys.stdout.reconfigure(encoding='utf-8')
106
+ sys.stdout.write("\r[%s%s] %d%%" % ('-' * progress, ' ' * (50 - progress), 100 * downloaded_size / total_size))
107
+ sys.stdout.flush()
108
+
109
+ print()
110
+
111
+ # rename file
112
+ os.rename(dl_file_path, file_path)
113
+ util.printD(f"File Downloaded to: {file_path}")
114
+ return file_path
115
+
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/js_action_civitai.py ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: UTF-8 -*-
2
+ # handle msg between js and python side
3
+ import os
4
+ import json
5
+ import requests
6
+ import webbrowser
7
+ from . import util
8
+ from . import model
9
+ from . import civitai
10
+ from . import msg_handler
11
+ from . import downloader
12
+
13
+
14
+
15
+ # get civitai's model url and open it in browser
16
+ # parameter: model_type, search_term
17
+ # output: python msg - will be sent to hidden textbox then picked by js side
18
+ def open_model_url(msg, open_url_with_js):
19
+ util.printD("Start open_model_url")
20
+
21
+ output = ""
22
+ result = msg_handler.parse_js_msg(msg)
23
+ if not result:
24
+ util.printD("Parsing js ms failed")
25
+ return
26
+
27
+ model_type = result["model_type"]
28
+ search_term = result["search_term"]
29
+
30
+ model_info = civitai.load_model_info_by_search_term(model_type, search_term)
31
+ if not model_info:
32
+ util.printD(f"Failed to get model info for {model_type} {search_term}")
33
+ return ""
34
+
35
+ if "modelId" not in model_info.keys():
36
+ util.printD(f"Failed to get model id from info file for {model_type} {search_term}")
37
+ return ""
38
+
39
+ model_id = model_info["modelId"]
40
+ if not model_id:
41
+ util.printD(f"model id from info file of {model_type} {search_term} is None")
42
+ return ""
43
+
44
+ url = civitai.url_dict["modelPage"]+str(model_id)
45
+
46
+
47
+ # msg content for js
48
+ content = {
49
+ "url":""
50
+ }
51
+
52
+ if not open_url_with_js:
53
+ util.printD("Open Url: " + url)
54
+ # open url
55
+ webbrowser.open_new_tab(url)
56
+ else:
57
+ util.printD("Send Url to js")
58
+ content["url"] = url
59
+ output = msg_handler.build_py_msg("open_url", content)
60
+
61
+ util.printD("End open_model_url")
62
+ return output
63
+
64
+
65
+
66
+ # add trigger words to prompt
67
+ # parameter: model_type, search_term, prompt
68
+ # return: [new_prompt, new_prompt] - new prompt with trigger words, return twice for txt2img and img2img
69
+ def add_trigger_words(msg):
70
+ util.printD("Start add_trigger_words")
71
+
72
+ result = msg_handler.parse_js_msg(msg)
73
+ if not result:
74
+ util.printD("Parsing js ms failed")
75
+ return
76
+
77
+ model_type = result["model_type"]
78
+ search_term = result["search_term"]
79
+ prompt = result["prompt"]
80
+
81
+
82
+ model_info = civitai.load_model_info_by_search_term(model_type, search_term)
83
+ if not model_info:
84
+ util.printD(f"Failed to get model info for {model_type} {search_term}")
85
+ return [prompt, prompt]
86
+
87
+ if "trainedWords" not in model_info.keys():
88
+ util.printD(f"Failed to get trainedWords from info file for {model_type} {search_term}")
89
+ return [prompt, prompt]
90
+
91
+ trainedWords = model_info["trainedWords"]
92
+ if not trainedWords:
93
+ util.printD(f"No trainedWords from info file for {model_type} {search_term}")
94
+ return [prompt, prompt]
95
+
96
+ if len(trainedWords) == 0:
97
+ util.printD(f"trainedWords from info file for {model_type} {search_term} is empty")
98
+ return [prompt, prompt]
99
+
100
+ # get ful trigger words
101
+ trigger_words = ""
102
+ for word in trainedWords:
103
+ trigger_words = trigger_words + word + ", "
104
+
105
+ new_prompt = prompt + " " + trigger_words
106
+ util.printD("trigger_words: " + trigger_words)
107
+ util.printD("prompt: " + prompt)
108
+ util.printD("new_prompt: " + new_prompt)
109
+
110
+ util.printD("End add_trigger_words")
111
+
112
+ # add to prompt
113
+ return [new_prompt, new_prompt]
114
+
115
+
116
+
117
+ # use preview image's prompt as prompt
118
+ # parameter: model_type, model_name, prompt, neg_prompt
119
+ # return: [new_prompt, new_neg_prompt, new_prompt, new_neg_prompt,] - return twice for txt2img and img2img
120
+ def use_preview_image_prompt(msg):
121
+ util.printD("Start use_preview_image_prompt")
122
+
123
+ result = msg_handler.parse_js_msg(msg)
124
+ if not result:
125
+ util.printD("Parsing js ms failed")
126
+ return
127
+
128
+ model_type = result["model_type"]
129
+ search_term = result["search_term"]
130
+ prompt = result["prompt"]
131
+ neg_prompt = result["neg_prompt"]
132
+
133
+
134
+ model_info = civitai.load_model_info_by_search_term(model_type, search_term)
135
+ if not model_info:
136
+ util.printD(f"Failed to get model info for {model_type} {search_term}")
137
+ return [prompt, neg_prompt, prompt, neg_prompt]
138
+
139
+ if "images" not in model_info.keys():
140
+ util.printD(f"Failed to get images from info file for {model_type} {search_term}")
141
+ return [prompt, neg_prompt, prompt, neg_prompt]
142
+
143
+ images = model_info["images"]
144
+ if not images:
145
+ util.printD(f"No images from info file for {model_type} {search_term}")
146
+ return [prompt, neg_prompt, prompt, neg_prompt]
147
+
148
+ if len(images) == 0:
149
+ util.printD(f"images from info file for {model_type} {search_term} is empty")
150
+ return [prompt, neg_prompt, prompt, neg_prompt]
151
+
152
+ # get prompt from preview images' meta data
153
+ preview_prompt = ""
154
+ preview_neg_prompt = ""
155
+ for img in images:
156
+ if "meta" in img.keys():
157
+ if img["meta"]:
158
+ if "prompt" in img["meta"].keys():
159
+ if img["meta"]["prompt"]:
160
+ preview_prompt = img["meta"]["prompt"]
161
+
162
+ if "negativePrompt" in img["meta"].keys():
163
+ if img["meta"]["negativePrompt"]:
164
+ preview_neg_prompt = img["meta"]["negativePrompt"]
165
+
166
+ # we only need 1 prompt
167
+ if preview_prompt:
168
+ break
169
+
170
+ if not preview_prompt:
171
+ util.printD(f"There is no prompt of {model_type} {search_term} in its preview image")
172
+ return [prompt, neg_prompt, prompt, neg_prompt]
173
+
174
+ util.printD("End use_preview_image_prompt")
175
+
176
+ return [preview_prompt, preview_neg_prompt, preview_prompt, preview_neg_prompt]
177
+
178
+
179
+ # download model's new verson by model path, version id and download url
180
+ # output is a md log
181
+ def dl_model_new_version(msg, max_size_preview, skip_nsfw_preview):
182
+ util.printD("Start dl_model_new_version")
183
+
184
+ output = ""
185
+
186
+ result = msg_handler.parse_js_msg(msg)
187
+ if not result:
188
+ output = "Parsing js ms failed"
189
+ util.printD(output)
190
+ return output
191
+
192
+ model_path = result["model_path"]
193
+ version_id = result["version_id"]
194
+ download_url = result["download_url"]
195
+
196
+ util.printD("model_path: " + model_path)
197
+ util.printD("version_id: " + str(version_id))
198
+ util.printD("download_url: " + download_url)
199
+
200
+ # check data
201
+ if not model_path:
202
+ output = "model_path is empty"
203
+ util.printD(output)
204
+ return output
205
+
206
+ if not version_id:
207
+ output = "version_id is empty"
208
+ util.printD(output)
209
+ return output
210
+
211
+ if not download_url:
212
+ output = "download_url is empty"
213
+ util.printD(output)
214
+ return output
215
+
216
+ if not os.path.isfile(model_path):
217
+ output = "model_path is not a file: "+ model_path
218
+ util.printD(output)
219
+ return output
220
+
221
+ # get model folder from model path
222
+ model_folder = os.path.dirname(model_path)
223
+
224
+ # no need to check when downloading new version, since checking new version is already checked
225
+ # check if this model is already existed
226
+ # r = civitai.search_local_model_info_by_version_id(model_folder, version_id)
227
+ # if r:
228
+ # output = "This model version is already existed"
229
+ # util.printD(output)
230
+ # return output
231
+
232
+ # download file
233
+ new_model_path = downloader.dl(download_url, model_folder, None, None)
234
+ if not new_model_path:
235
+ output = "Download failed, check console log for detail. Download url: " + download_url
236
+ util.printD(output)
237
+ return output
238
+
239
+ # get version info
240
+ version_info = civitai.get_version_info_by_version_id(version_id)
241
+ if not version_info:
242
+ output = "Model downloaded, but failed to get version info, check console log for detail. Model saved to: " + new_model_path
243
+ util.printD(output)
244
+ return output
245
+
246
+ # now write version info to file
247
+ base, ext = os.path.splitext(new_model_path)
248
+ info_file = base + civitai.suffix + model.info_ext
249
+ model.write_model_info(info_file, version_info)
250
+
251
+ # then, get preview image
252
+ civitai.get_preview_image_by_model_path(new_model_path, max_size_preview, skip_nsfw_preview)
253
+
254
+ output = "Done. Model downloaded to: " + new_model_path
255
+ util.printD(output)
256
+ return output
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/model.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: UTF-8 -*-
2
+ # handle msg between js and python side
3
+ import os
4
+ import json
5
+ from . import util
6
+ from modules import shared
7
+
8
+
9
+ # this is the default root path
10
+ root_path = os.getcwd()
11
+
12
+ # if command line arguement is used to change model folder,
13
+ # then model folder is in absolute path, not based on this root path anymore.
14
+ # so to make extension work with those absolute model folder paths, model folder also need to be in absolute path
15
+ folders = {
16
+ "ti": os.path.join(root_path, "embeddings"),
17
+ "hyper": os.path.join(root_path, "models", "hypernetworks"),
18
+ "ckp": os.path.join(root_path, "models", "Stable-diffusion"),
19
+ "lora": os.path.join(root_path, "models", "Lora"),
20
+ }
21
+
22
+ exts = (".bin", ".pt", ".safetensors", ".ckpt")
23
+ info_ext = ".info"
24
+ vae_suffix = ".vae"
25
+
26
+
27
+ # get cusomter model path
28
+ def get_custom_model_folder():
29
+ util.printD("Get Custom Model Folder")
30
+
31
+ global folders
32
+
33
+ if shared.cmd_opts.embeddings_dir and os.path.isdir(shared.cmd_opts.embeddings_dir):
34
+ folders["ti"] = shared.cmd_opts.embeddings_dir
35
+
36
+ if shared.cmd_opts.hypernetwork_dir and os.path.isdir(shared.cmd_opts.hypernetwork_dir):
37
+ folders["hyper"] = shared.cmd_opts.hypernetwork_dir
38
+
39
+ if shared.cmd_opts.ckpt_dir and os.path.isdir(shared.cmd_opts.ckpt_dir):
40
+ folders["ckp"] = shared.cmd_opts.ckpt_dir
41
+
42
+ if shared.cmd_opts.lora_dir and os.path.isdir(shared.cmd_opts.lora_dir):
43
+ folders["lora"] = shared.cmd_opts.lora_dir
44
+
45
+
46
+
47
+
48
+
49
+ # write model info to file
50
+ def write_model_info(path, model_info):
51
+ util.printD("Write model info to file: " + path)
52
+ with open(os.path.realpath(path), 'w') as f:
53
+ f.write(json.dumps(model_info, indent=4))
54
+
55
+
56
+ def load_model_info(path):
57
+ # util.printD("Load model info from file: " + path)
58
+ model_info = None
59
+ with open(os.path.realpath(path), 'r') as f:
60
+ try:
61
+ model_info = json.load(f)
62
+ except Exception as e:
63
+ util.printD("Selected file is not json: " + path)
64
+ util.printD(e)
65
+ return
66
+
67
+ return model_info
68
+
69
+
70
+ # get model file names by model type
71
+ # parameter: model_type - string
72
+ # return: model name list
73
+ def get_model_names_by_type(model_type:str) -> list:
74
+
75
+ model_folder = folders[model_type]
76
+
77
+ # get information from filter
78
+ # only get those model names don't have a civitai model info file
79
+ model_names = []
80
+ for root, dirs, files in os.walk(model_folder, followlinks=True):
81
+ for filename in files:
82
+ item = os.path.join(root, filename)
83
+ # check extension
84
+ base, ext = os.path.splitext(item)
85
+ if ext in exts:
86
+ # find a model
87
+ model_names.append(filename)
88
+
89
+
90
+ return model_names
91
+
92
+
93
+ # return 2 values: (model_root, model_path)
94
+ def get_model_path_by_type_and_name(model_type:str, model_name:str) -> str:
95
+ util.printD("Run get_model_path_by_type_and_name")
96
+ if model_type not in folders.keys():
97
+ util.printD("unknown model_type: " + model_type)
98
+ return
99
+
100
+ if not model_name:
101
+ util.printD("model name can not be empty")
102
+ return
103
+
104
+ folder = folders[model_type]
105
+
106
+ # model could be in subfolder, need to walk.
107
+ model_root = ""
108
+ model_path = ""
109
+ for root, dirs, files in os.walk(folder, followlinks=True):
110
+ for filename in files:
111
+ if filename == model_name:
112
+ # find model
113
+ model_root = root
114
+ model_path = os.path.join(root, filename)
115
+ return (model_root, model_path)
116
+
117
+ return
118
+
119
+
120
+
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/model_action_civitai.py ADDED
@@ -0,0 +1,511 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: UTF-8 -*-
2
+ # handle msg between js and python side
3
+ import os
4
+ import time
5
+ from . import util
6
+ from . import model
7
+ from . import civitai
8
+ from . import downloader
9
+
10
+
11
+ # scan model to generate SHA256, then use this SHA256 to get model info from civitai
12
+ # return output msg
13
+ def scan_model(scan_model_types, max_size_preview, skip_nsfw_preview):
14
+ util.printD("Start scan_model")
15
+ output = ""
16
+
17
+ # check model types
18
+ if not scan_model_types:
19
+ output = "Model Types is None, can not scan."
20
+ util.printD(output)
21
+ return output
22
+
23
+ model_types = []
24
+ # check type if it is a string
25
+ if type(scan_model_types) == str:
26
+ model_types.append(scan_model_types)
27
+ else:
28
+ model_types = scan_model_types
29
+
30
+ model_count = 0
31
+ image_count = 0
32
+ # scan_log = ""
33
+ for model_type, model_folder in model.folders.items():
34
+ if model_type not in model_types:
35
+ continue
36
+
37
+ util.printD("Scanning path: " + model_folder)
38
+ for root, dirs, files in os.walk(model_folder, followlinks=True):
39
+ for filename in files:
40
+ # check ext
41
+ item = os.path.join(root, filename)
42
+ base, ext = os.path.splitext(item)
43
+ if ext in model.exts:
44
+ # ignore vae file
45
+ if len(base) > 4:
46
+ if base[-4:] == model.vae_suffix:
47
+ # find .vae
48
+ util.printD("This is a vae file: " + filename)
49
+ continue
50
+
51
+ # find a model
52
+ # get info file
53
+ info_file = base + civitai.suffix + model.info_ext
54
+ # check info file
55
+ if not os.path.isfile(info_file):
56
+ util.printD("Creating model info for: " + filename)
57
+ # get model's sha256
58
+ hash = util.gen_file_sha256(item)
59
+
60
+ if not hash:
61
+ output = "failed generating SHA256 for model:" + filename
62
+ util.printD(output)
63
+ return output
64
+
65
+ # use this sha256 to get model info from civitai
66
+ model_info = civitai.get_model_info_by_hash(hash)
67
+ # delay 1 second for ti
68
+ if model_type == "ti":
69
+ util.printD("Delay 1 second for TI")
70
+ time.sleep(1)
71
+
72
+ if model_info is None:
73
+ output = "Connect to Civitai API service failed. Wait a while and try again"
74
+ util.printD(output)
75
+ return output+", check console log for detail"
76
+
77
+ # write model info to file
78
+ model.write_model_info(info_file, model_info)
79
+
80
+ # set model_count
81
+ model_count = model_count+1
82
+
83
+ # check preview image
84
+ civitai.get_preview_image_by_model_path(item, max_size_preview, skip_nsfw_preview)
85
+ image_count = image_count+1
86
+
87
+
88
+ # scan_log = "Done"
89
+
90
+ output = f"Done. Scanned {model_count} models, checked {image_count} images"
91
+
92
+ util.printD(output)
93
+
94
+ return output
95
+
96
+
97
+
98
+ # Get model info by model type, name and url
99
+ # output is log info to display on markdown component
100
+ def get_model_info_by_input(model_type, model_name, model_url_or_id, max_size_preview, skip_nsfw_preview):
101
+ output = ""
102
+ # parse model id
103
+ model_id = civitai.get_model_id_from_url(model_url_or_id)
104
+ if not model_id:
105
+ output = "failed to parse model id from url: " + model_url_or_id
106
+ util.printD(output)
107
+ return output
108
+
109
+ # get model file path
110
+ # model could be in subfolder
111
+ result = model.get_model_path_by_type_and_name(model_type, model_name)
112
+ if not result:
113
+ output = "failed to get model file path"
114
+ util.printD(output)
115
+ return output
116
+
117
+ model_root, model_path = result
118
+ if not model_path:
119
+ output = "model path is empty"
120
+ util.printD(output)
121
+ return output
122
+
123
+ # get info file path
124
+ base, ext = os.path.splitext(model_path)
125
+ info_file = base + civitai.suffix + model.info_ext
126
+
127
+ # get model info
128
+ #we call it model_info, but in civitai, it is actually version info
129
+ model_info = civitai.get_version_info_by_model_id(model_id)
130
+
131
+ if not model_info:
132
+ output = "failed to get model info from url: " + model_url_or_id
133
+ util.printD(output)
134
+ return output
135
+
136
+ # write model info to file
137
+ model.write_model_info(info_file, model_info)
138
+
139
+ util.printD("Saved model info to: "+ info_file)
140
+
141
+ # check preview image
142
+ civitai.get_preview_image_by_model_path(model_path, max_size_preview, skip_nsfw_preview)
143
+
144
+ output = "Model Info saved to: " + info_file
145
+ return output
146
+
147
+
148
+
149
+ # check models' new version and output to UI as markdown doc
150
+ def check_models_new_version_to_md(model_types:list) -> str:
151
+ new_versions = civitai.check_models_new_version_by_model_types(model_types, 1)
152
+
153
+ count = 0
154
+ output = ""
155
+ if not new_versions:
156
+ output = "No model has new version"
157
+ else:
158
+ output = "Found new version for following models: <br>"
159
+ for new_version in new_versions:
160
+ count = count+1
161
+ model_path, model_id, model_name, new_verion_id, new_version_name, description, download_url, img_url = new_version
162
+ # in md, each part is something like this:
163
+ # [model_name](model_url)
164
+ # [version_name](download_url)
165
+ # version description
166
+ url = civitai.url_dict["modelPage"]+str(model_id)
167
+
168
+ part = f'<div style="font-size:20px;margin:6px 0px;"><b>Model: <a href="{url}" target="_blank"><u>{model_name}</u></a></b></div>'
169
+ part = part + f'<div style="font-size:16px">File: {model_path}</div>'
170
+ if download_url:
171
+ # replace "\" to "/" in model_path for windows
172
+ model_path = model_path.replace('\\', '\\\\')
173
+ 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>'
174
+ # add js function to download new version into SD webui by python
175
+ part = part + " "
176
+ # in embed HTML, onclick= will also follow a ", never a ', so have to write it as following
177
+ 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>"
178
+
179
+ else:
180
+ part = part + f'<div style="font-size:16px;margin:6px 0px;">New Version: {new_version_name}'
181
+ part = part + '</div>'
182
+
183
+ # description
184
+ if description:
185
+ part = part + '<blockquote style="font-size:16px;margin:6px 0px;">'+ description + '</blockquote><br>'
186
+
187
+ # preview image
188
+ if img_url:
189
+ part = part + f"<img src='{img_url}'><br>"
190
+
191
+
192
+ output = output + part
193
+
194
+ util.printD(f"Done. Find {count} models have new version. Check UI for detail.")
195
+
196
+ return output
197
+
198
+
199
+ # get model info by url
200
+ def get_model_info_by_url(model_url_or_id:str) -> tuple:
201
+ util.printD("Getting model info by: " + model_url_or_id)
202
+
203
+ # parse model id
204
+ model_id = civitai.get_model_id_from_url(model_url_or_id)
205
+ if not model_id:
206
+ util.printD("failed to parse model id from url or id")
207
+ return
208
+
209
+ model_info = civitai.get_model_info_by_id(model_id)
210
+ if model_info is None:
211
+ util.printD("Connect to Civitai API service failed. Wait a while and try again")
212
+ return
213
+
214
+ if not model_info:
215
+ util.printD("failed to get model info from url or id")
216
+ return
217
+
218
+ # parse model type, model name, subfolder, version from this model info
219
+ # get model type
220
+ if "type" not in model_info.keys():
221
+ util.printD("model type is not in model_info")
222
+ return
223
+
224
+ civitai_model_type = model_info["type"]
225
+ if civitai_model_type not in civitai.model_type_dict.keys():
226
+ util.printD("This model type is not supported:"+civitai_model_type)
227
+ return
228
+
229
+ model_type = civitai.model_type_dict[civitai_model_type]
230
+
231
+ # get model type
232
+ if "name" not in model_info.keys():
233
+ util.printD("model name is not in model_info")
234
+ return
235
+
236
+ model_name = model_info["name"]
237
+ if not model_name:
238
+ util.printD("model name is Empty")
239
+ model_name = ""
240
+
241
+ # get version list
242
+ if "modelVersions" not in model_info.keys():
243
+ util.printD("modelVersions is not in model_info")
244
+ return
245
+
246
+ modelVersions = model_info["modelVersions"]
247
+ if not modelVersions:
248
+ util.printD("modelVersions is Empty")
249
+ return
250
+
251
+ version_strs = []
252
+ for version in modelVersions:
253
+ # version name can not be used as id
254
+ # version id is not readable
255
+ # so , we use name_id as version string
256
+ version_str = version["name"]+"_"+str(version["id"])
257
+ version_strs.append(version_str)
258
+
259
+ # get folder by model type
260
+ folder = model.folders[model_type]
261
+ # get subfolders
262
+ subfolders = util.get_subfolders(folder)
263
+ if not subfolders:
264
+ subfolders = []
265
+
266
+ # add default root folder
267
+ subfolders.append("/")
268
+
269
+ util.printD("Get following info for downloading:")
270
+ util.printD(f"model_name:{model_name}")
271
+ util.printD(f"model_type:{model_type}")
272
+ util.printD(f"subfolders:{subfolders}")
273
+ util.printD(f"version_strs:{version_strs}")
274
+
275
+ return (model_info, model_name, model_type, subfolders, version_strs)
276
+
277
+ # get version info by version string
278
+ def get_ver_info_by_ver_str(version_str:str, model_info:dict) -> dict:
279
+ if not version_str:
280
+ util.printD("version_str is empty")
281
+ return
282
+
283
+ if not model_info:
284
+ util.printD("model_info is None")
285
+ return
286
+
287
+ # get version list
288
+ if "modelVersions" not in model_info.keys():
289
+ util.printD("modelVersions is not in model_info")
290
+ return
291
+
292
+ modelVersions = model_info["modelVersions"]
293
+ if not modelVersions:
294
+ util.printD("modelVersions is Empty")
295
+ return
296
+
297
+ # find version by version_str
298
+ version = None
299
+ for ver in modelVersions:
300
+ # version name can not be used as id
301
+ # version id is not readable
302
+ # so , we use name_id as version string
303
+ ver_str = ver["name"]+"_"+str(ver["id"])
304
+ if ver_str == version_str:
305
+ # find version
306
+ version = ver
307
+
308
+ if not version:
309
+ util.printD("can not find version by version string: " + version_str)
310
+ return
311
+
312
+ # get version id
313
+ if "id" not in version.keys():
314
+ util.printD("this version has no id")
315
+ return
316
+
317
+ return version
318
+
319
+
320
+ # get download url from model info by version string
321
+ # return - (version_id, download_url)
322
+ def get_id_and_dl_url_by_version_str(version_str:str, model_info:dict) -> tuple:
323
+ if not version_str:
324
+ util.printD("version_str is empty")
325
+ return
326
+
327
+ if not model_info:
328
+ util.printD("model_info is None")
329
+ return
330
+
331
+ # get version list
332
+ if "modelVersions" not in model_info.keys():
333
+ util.printD("modelVersions is not in model_info")
334
+ return
335
+
336
+ modelVersions = model_info["modelVersions"]
337
+ if not modelVersions:
338
+ util.printD("modelVersions is Empty")
339
+ return
340
+
341
+ # find version by version_str
342
+ version = None
343
+ for ver in modelVersions:
344
+ # version name can not be used as id
345
+ # version id is not readable
346
+ # so , we use name_id as version string
347
+ ver_str = ver["name"]+"_"+str(ver["id"])
348
+ if ver_str == version_str:
349
+ # find version
350
+ version = ver
351
+
352
+ if not version:
353
+ util.printD("can not find version by version string: " + version_str)
354
+ return
355
+
356
+ # get version id
357
+ if "id" not in version.keys():
358
+ util.printD("this version has no id")
359
+ return
360
+
361
+ version_id = version["id"]
362
+ if not version_id:
363
+ util.printD("version id is Empty")
364
+ return
365
+
366
+ # get download url
367
+ if "downloadUrl" not in version.keys():
368
+ util.printD("downloadUrl is not in this version")
369
+ return
370
+
371
+ downloadUrl = version["downloadUrl"]
372
+ if not downloadUrl:
373
+ util.printD("downloadUrl is Empty")
374
+ return
375
+
376
+ util.printD("Get Download Url: " + downloadUrl)
377
+
378
+ return (version_id, downloadUrl)
379
+
380
+
381
+ # download model from civitai by input
382
+ # output to markdown log
383
+ def dl_model_by_input(model_info:dict, model_type:str, subfolder_str:str, version_str:str, dl_all_bool:bool, max_size_preview:bool, skip_nsfw_preview:bool) -> str:
384
+
385
+ output = ""
386
+
387
+ if not model_info:
388
+ output = "model_info is None"
389
+ util.printD(output)
390
+ return output
391
+
392
+ if not model_type:
393
+ output = "model_type is None"
394
+ util.printD(output)
395
+ return output
396
+
397
+ if not subfolder_str:
398
+ output = "subfolder string is None"
399
+ util.printD(output)
400
+ return output
401
+
402
+ if not version_str:
403
+ output = "version_str is None"
404
+ util.printD(output)
405
+ return output
406
+
407
+ # get model root folder
408
+ if model_type not in model.folders.keys():
409
+ output = "Unknow model type: "+model_type
410
+ util.printD(output)
411
+ return output
412
+
413
+ model_root_folder = model.folders[model_type]
414
+
415
+
416
+ # get subfolder
417
+ subfolder = ""
418
+ if subfolder_str == "/" or subfolder_str == "\\":
419
+ subfolder = ""
420
+ elif subfolder_str[:1] == "/" or subfolder_str[:1] == "\\":
421
+ subfolder = subfolder_str[1:]
422
+ else:
423
+ subfolder = subfolder_str
424
+
425
+ # get model folder for downloading
426
+ model_folder = os.path.join(model_root_folder, subfolder)
427
+ if not os.path.isdir(model_folder):
428
+ output = "Model folder is not a dir: "+ model_folder
429
+ util.printD(output)
430
+ return output
431
+
432
+ # get version info
433
+ ver_info = get_ver_info_by_ver_str(version_str, model_info)
434
+ if not ver_info:
435
+ output = "Fail to get version info, check console log for detail"
436
+ util.printD(output)
437
+ return output
438
+
439
+ version_id = ver_info["id"]
440
+
441
+
442
+ if dl_all_bool:
443
+ # get all download url from files info
444
+ # some model versions have multiple files
445
+ download_urls = []
446
+ if "files" in ver_info.keys():
447
+ for file_info in ver_info["files"]:
448
+ if "downloadUrl" in file_info.keys():
449
+ download_urls.append(file_info["downloadUrl"])
450
+
451
+ if not len(download_urls):
452
+ if "downloadUrl" in ver_info.keys():
453
+ download_urls.append(ver_info["downloadUrl"])
454
+
455
+
456
+ # check if this model is already existed
457
+ r = civitai.search_local_model_info_by_version_id(model_folder, version_id)
458
+ if r:
459
+ output = "This model version is already existed"
460
+ util.printD(output)
461
+ return output
462
+
463
+ # download
464
+ filepath = ""
465
+ for url in download_urls:
466
+ model_filepath = downloader.dl(url, model_folder, None, None)
467
+ if not model_filepath:
468
+ output = "Downloading failed, check console log for detail"
469
+ util.printD(output)
470
+ return output
471
+
472
+ if url == ver_info["downloadUrl"]:
473
+ filepath = model_filepath
474
+ else:
475
+ # only download one file
476
+ # get download url
477
+ url = ver_info["downloadUrl"]
478
+ if not url:
479
+ output = "Fail to get download url, check console log for detail"
480
+ util.printD(output)
481
+ return output
482
+
483
+ # download
484
+ filepath = downloader.dl(url, model_folder, None, None)
485
+ if not filepath:
486
+ output = "Downloading failed, check console log for detail"
487
+ util.printD(output)
488
+ return output
489
+
490
+
491
+ if not filepath:
492
+ filepath = model_filepath
493
+
494
+ # get version info
495
+ version_info = civitai.get_version_info_by_version_id(version_id)
496
+ if not version_info:
497
+ output = "Model downloaded, but failed to get version info, check console log for detail. Model saved to: " + filepath
498
+ util.printD(output)
499
+ return output
500
+
501
+ # write version info to file
502
+ base, ext = os.path.splitext(filepath)
503
+ info_file = base + civitai.suffix + model.info_ext
504
+ model.write_model_info(info_file, version_info)
505
+
506
+ # then, get preview image
507
+ civitai.get_preview_image_by_model_path(filepath, max_size_preview, skip_nsfw_preview)
508
+
509
+ output = "Done. Model downloaded to: " + filepath
510
+ util.printD(output)
511
+ return output
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/msg_handler.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: UTF-8 -*-
2
+ # handle msg between js and python side
3
+ import json
4
+ from . import util
5
+
6
+ # action list
7
+ js_actions = ("open_url", "add_trigger_words", "use_preview_prompt", "dl_model_new_version")
8
+ py_actions = ("open_url")
9
+
10
+
11
+ # handle request from javascript
12
+ # parameter: msg - msg from js as string in a hidden textbox
13
+ # return: dict for result
14
+ def parse_js_msg(msg):
15
+ util.printD("Start parse js msg")
16
+ msg_dict = json.loads(msg)
17
+
18
+ # in case client side run JSON.stringify twice
19
+ if (type(msg_dict) == str):
20
+ msg_dict = json.loads(msg_dict)
21
+
22
+ if "action" not in msg_dict.keys():
23
+ util.printD("Can not find action from js request")
24
+ return
25
+
26
+ action = msg_dict["action"]
27
+ if not action:
28
+ util.printD("Action from js request is None")
29
+ return
30
+
31
+ if action not in js_actions:
32
+ util.printD("Unknow action: " + action)
33
+ return
34
+
35
+ util.printD("End parse js msg")
36
+
37
+ return msg_dict
38
+
39
+
40
+ # build python side msg for sending to js
41
+ # parameter: content dict
42
+ # return: msg as string, to fill into a hidden textbox
43
+ def build_py_msg(action:str, content:dict):
44
+ util.printD("Start build_msg")
45
+ if not content:
46
+ util.printD("Content is None")
47
+ return
48
+
49
+ if not action:
50
+ util.printD("Action is None")
51
+ return
52
+
53
+ if action not in py_actions:
54
+ util.printD("Unknow action: " + action)
55
+ return
56
+
57
+ msg = {
58
+ "action" : action,
59
+ "content": content
60
+ }
61
+
62
+
63
+ util.printD("End build_msg")
64
+ return json.dumps(msg)
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/setting.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: UTF-8 -*-
2
+ # collecting settings to here
3
+ import json
4
+ import os
5
+ import modules.scripts as scripts
6
+ from . import util
7
+
8
+
9
+ name = "setting.json"
10
+ path = os.path.join(scripts.basedir(), name)
11
+
12
+ data = {
13
+ "model":{
14
+ "max_size_preview": True,
15
+ "skip_nsfw_preview": False
16
+ },
17
+ "general":{
18
+ "open_url_with_js": True,
19
+ "always_display": False,
20
+ "show_btn_on_thumb": True,
21
+ "proxy": "",
22
+ },
23
+ "tool":{
24
+ }
25
+ }
26
+
27
+
28
+
29
+ # save setting
30
+ # return output msg for log
31
+ def save():
32
+ print("Saving setting to: " + path)
33
+
34
+ json_data = json.dumps(data, indent=4)
35
+
36
+ output = ""
37
+
38
+ #write to file
39
+ try:
40
+ with open(path, 'w') as f:
41
+ f.write(json_data)
42
+ except Exception as e:
43
+ util.printD("Error when writing file:"+path)
44
+ output = str(e)
45
+ util.printD(str(e))
46
+ return output
47
+
48
+ output = "Setting saved to: " + path
49
+ util.printD(output)
50
+
51
+ return output
52
+
53
+
54
+ # load setting to global data
55
+ def load():
56
+ # load data into globel data
57
+ global data
58
+
59
+ util.printD("Load setting from: " + path)
60
+
61
+ if not os.path.isfile(path):
62
+ util.printD("No setting file, use default")
63
+ return
64
+
65
+ json_data = None
66
+ with open(path, 'r') as f:
67
+ json_data = json.load(f)
68
+
69
+ # check error
70
+ if not json_data:
71
+ util.printD("load setting file failed")
72
+ return
73
+
74
+ data = json_data
75
+
76
+ # check for new key
77
+ if "always_display" not in data["general"].keys():
78
+ data["general"]["always_display"] = False
79
+
80
+ if "show_btn_on_thumb" not in data["general"].keys():
81
+ data["general"]["show_btn_on_thumb"] = True
82
+
83
+ if "proxy" not in data["general"].keys():
84
+ data["general"]["proxy"] = ""
85
+
86
+
87
+ return
88
+
89
+ # save setting from parameter
90
+ def save_from_input(max_size_preview, skip_nsfw_preview, open_url_with_js, always_display, show_btn_on_thumb, proxy):
91
+ global data
92
+ data = {
93
+ "model":{
94
+ "max_size_preview": max_size_preview,
95
+ "skip_nsfw_preview": skip_nsfw_preview
96
+ },
97
+ "general":{
98
+ "open_url_with_js": open_url_with_js,
99
+ "always_display": always_display,
100
+ "show_btn_on_thumb": show_btn_on_thumb,
101
+ "proxy": proxy,
102
+ },
103
+ "tool":{
104
+ }
105
+ }
106
+
107
+ output = save()
108
+
109
+ if not output:
110
+ output = ""
111
+
112
+ return output
113
+
Stable-Diffusion-Webui-Civitai-Helper/scripts/ch_lib/util.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: UTF-8 -*-
2
+ import os
3
+ import io
4
+ import hashlib
5
+ import requests
6
+ import shutil
7
+
8
+
9
+ version = "1.6.4"
10
+
11
+ def_headers = {'User-Agent': 'Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148'}
12
+
13
+
14
+ proxies = None
15
+
16
+
17
+ # print for debugging
18
+ def printD(msg):
19
+ print(f"Civitai Helper: {msg}")
20
+
21
+
22
+ def read_chunks(file, size=io.DEFAULT_BUFFER_SIZE):
23
+ """Yield pieces of data from a file-like object until EOF."""
24
+ while True:
25
+ chunk = file.read(size)
26
+ if not chunk:
27
+ break
28
+ yield chunk
29
+
30
+ # Now, hashing use the same way as pip's source code.
31
+ def gen_file_sha256(filname):
32
+ printD("Use Memory Optimized SHA256")
33
+ blocksize=1 << 20
34
+ h = hashlib.sha256()
35
+ length = 0
36
+ with open(os.path.realpath(filname), 'rb') as f:
37
+ for block in read_chunks(f, size=blocksize):
38
+ length += len(block)
39
+ h.update(block)
40
+
41
+ hash_value = h.hexdigest()
42
+ printD("sha256: " + hash_value)
43
+ printD("length: " + str(length))
44
+ return hash_value
45
+
46
+
47
+
48
+ # get preview image
49
+ def download_file(url, path):
50
+ printD("Downloading file from: " + url)
51
+ # get file
52
+ r = requests.get(url, stream=True, headers=def_headers, proxies=proxies)
53
+ if not r.ok:
54
+ printD("Get error code: " + str(r.status_code))
55
+ printD(r.text)
56
+ return
57
+
58
+ # write to file
59
+ with open(os.path.realpath(path), 'wb') as f:
60
+ r.raw.decode_content = True
61
+ shutil.copyfileobj(r.raw, f)
62
+
63
+ printD("File downloaded to: " + path)
64
+
65
+ # get subfolder list
66
+ def get_subfolders(folder:str) -> list:
67
+ printD("Get subfolder for: " + folder)
68
+ if not folder:
69
+ printD("folder can not be None")
70
+ return
71
+
72
+ if not os.path.isdir(folder):
73
+ printD("path is not a folder")
74
+ return
75
+
76
+ prefix_len = len(folder)
77
+ subfolders = []
78
+ for root, dirs, files in os.walk(folder, followlinks=True):
79
+ for dir in dirs:
80
+ full_dir_path = os.path.join(root, dir)
81
+ # get subfolder path from it
82
+ subfolder = full_dir_path[prefix_len:]
83
+ subfolders.append(subfolder)
84
+
85
+ return subfolders
86
+
87
+
88
+ # get relative path
89
+ def get_relative_path(item_path:str, parent_path:str) -> str:
90
+ # printD("item_path:"+item_path)
91
+ # printD("parent_path:"+parent_path)
92
+ # item path must start with parent_path
93
+ if not item_path:
94
+ return ""
95
+ if not parent_path:
96
+ return ""
97
+ if not item_path.startswith(parent_path):
98
+ return item_path
99
+
100
+ relative = item_path[len(parent_path):]
101
+ if relative[:1] == "/" or relative[:1] == "\\":
102
+ relative = relative[1:]
103
+
104
+ # printD("relative:"+relative)
105
+ return relative
Stable-Diffusion-Webui-Civitai-Helper/scripts/civitai_helper.py ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: UTF-8 -*-
2
+ # This extension can help you manage your models from civitai. It can download preview, add trigger words, open model page and use the prompt from preview image
3
+ # repo: https://github.com/butaixianran/
4
+
5
+
6
+
7
+ import modules.scripts as scripts
8
+ import gradio as gr
9
+ import os
10
+ import webbrowser
11
+ import requests
12
+ import random
13
+ import hashlib
14
+ import json
15
+ import shutil
16
+ import re
17
+ import modules
18
+ from modules import script_callbacks
19
+ from modules import shared
20
+ from scripts.ch_lib import model
21
+ from scripts.ch_lib import js_action_civitai
22
+ from scripts.ch_lib import model_action_civitai
23
+ from scripts.ch_lib import setting
24
+ from scripts.ch_lib import civitai
25
+ from scripts.ch_lib import util
26
+
27
+
28
+ # init
29
+
30
+ # root path
31
+ root_path = os.getcwd()
32
+
33
+ # extension path
34
+ extension_path = scripts.basedir()
35
+
36
+ model.get_custom_model_folder()
37
+ setting.load()
38
+
39
+ # set proxy
40
+ if setting.data["general"]["proxy"]:
41
+ util.printD("Set Proxy: "+setting.data["general"]["proxy"])
42
+ util.proxies = {
43
+ "http": setting.data["general"]["proxy"],
44
+ "https": setting.data["general"]["proxy"],
45
+ }
46
+
47
+
48
+
49
+
50
+ def on_ui_tabs():
51
+ # init
52
+ # init_py_msg = {
53
+ # # relative extension path
54
+ # "extension_path": util.get_relative_path(extension_path, root_path),
55
+ # }
56
+ # init_py_msg_str = json.dumps(init_py_msg)
57
+
58
+
59
+ # get prompt textarea
60
+ # check modules/ui.py, search for txt2img_paste_fields
61
+ # Negative prompt is the second element
62
+ txt2img_prompt = modules.ui.txt2img_paste_fields[0][0]
63
+ txt2img_neg_prompt = modules.ui.txt2img_paste_fields[1][0]
64
+ img2img_prompt = modules.ui.img2img_paste_fields[0][0]
65
+ img2img_neg_prompt = modules.ui.img2img_paste_fields[1][0]
66
+
67
+ # ====Event's function====
68
+ def get_model_names_by_input(model_type, empty_info_only):
69
+ names = civitai.get_model_names_by_input(model_type, empty_info_only)
70
+ return model_name_drop.update(choices=names)
71
+
72
+
73
+ def get_model_info_by_url(url):
74
+ r = model_action_civitai.get_model_info_by_url(url)
75
+
76
+ model_info = {}
77
+ model_name = ""
78
+ model_type = ""
79
+ subfolders = []
80
+ version_strs = []
81
+ if r:
82
+ model_info, model_name, model_type, subfolders, version_strs = r
83
+
84
+ return [model_info, model_name, model_type, dl_subfolder_drop.update(choices=subfolders), dl_version_drop.update(choices=version_strs)]
85
+
86
+ # ====UI====
87
+ with gr.Blocks(analytics_enabled=False) as civitai_helper:
88
+ # with gr.Blocks(css=".block.padded {padding: 10px !important}") as civitai_helper:
89
+
90
+ # init
91
+ max_size_preview = setting.data["model"]["max_size_preview"]
92
+ skip_nsfw_preview = setting.data["model"]["skip_nsfw_preview"]
93
+ open_url_with_js = setting.data["general"]["open_url_with_js"]
94
+ always_display = setting.data["general"]["always_display"]
95
+ show_btn_on_thumb = setting.data["general"]["show_btn_on_thumb"]
96
+ proxy = setting.data["general"]["proxy"]
97
+
98
+ model_types = list(model.folders.keys())
99
+ no_info_model_names = civitai.get_model_names_by_input("ckp", False)
100
+
101
+ # session data
102
+ dl_model_info = gr.State({})
103
+
104
+
105
+
106
+ with gr.Box(elem_classes="ch_box"):
107
+ with gr.Column():
108
+ gr.Markdown("### Scan Models for Civitai")
109
+ with gr.Row():
110
+ max_size_preview_ckb = gr.Checkbox(label="Download Max Size Preview", value=max_size_preview, elem_id="ch_max_size_preview_ckb")
111
+ skip_nsfw_preview_ckb = gr.Checkbox(label="Skip NSFW Preview Images", value=skip_nsfw_preview, elem_id="ch_skip_nsfw_preview_ckb")
112
+ scan_model_types_ckbg = gr.CheckboxGroup(choices=model_types, label="Model Types", value=model_types)
113
+
114
+ # with gr.Row():
115
+ scan_model_civitai_btn = gr.Button(value="Scan", variant="primary", elem_id="ch_scan_model_civitai_btn")
116
+ # with gr.Row():
117
+ scan_model_log_md = gr.Markdown(value="Scanning takes time, just wait. Check console log for detail", elem_id="ch_scan_model_log_md")
118
+
119
+
120
+ with gr.Box(elem_classes="ch_box"):
121
+ with gr.Column():
122
+ gr.Markdown("### Get Model Info from Civitai by URL")
123
+ gr.Markdown("Use this when scanning can not find a local model on civitai")
124
+ with gr.Row():
125
+ model_type_drop = gr.Dropdown(choices=model_types, label="Model Type", value="ckp", multiselect=False)
126
+ empty_info_only_ckb = gr.Checkbox(label="Only Show Models have no Info", value=False, elem_id="ch_empty_info_only_ckb", elem_classes="ch_vpadding")
127
+ model_name_drop = gr.Dropdown(choices=no_info_model_names, label="Model", value="ckp", multiselect=False)
128
+
129
+ model_url_or_id_txtbox = gr.Textbox(label="Civitai URL", lines=1, value="")
130
+ get_civitai_model_info_by_id_btn = gr.Button(value="Get Model Info from Civitai", variant="primary")
131
+ get_model_by_id_log_md = gr.Markdown("")
132
+
133
+ with gr.Box(elem_classes="ch_box"):
134
+ with gr.Column():
135
+ gr.Markdown("### Download Model")
136
+ with gr.Row():
137
+ dl_model_url_or_id_txtbox = gr.Textbox(label="Civitai URL", lines=1, value="")
138
+ dl_model_info_btn = gr.Button(value="1. Get Model Info by Civitai Url", variant="primary")
139
+
140
+ gr.Markdown(value="2. Pick Subfolder and Model Version")
141
+ with gr.Row():
142
+ dl_model_name_txtbox = gr.Textbox(label="Model Name", interactive=False, lines=1, value="")
143
+ dl_model_type_txtbox = gr.Textbox(label="Model Type", interactive=False, lines=1, value="")
144
+ dl_subfolder_drop = gr.Dropdown(choices=[], label="Sub-folder", value="", interactive=True, multiselect=False)
145
+ dl_version_drop = gr.Dropdown(choices=[], label="Model Version", value="", interactive=True, multiselect=False)
146
+ dl_all_ckb = gr.Checkbox(label="Download All files", value=False, elem_id="ch_dl_all_ckb", elem_classes="ch_vpadding")
147
+
148
+ dl_civitai_model_by_id_btn = gr.Button(value="3. Download Model", variant="primary")
149
+ dl_log_md = gr.Markdown(value="Check Console log for Downloading Status")
150
+
151
+ with gr.Box(elem_classes="ch_box"):
152
+ with gr.Column():
153
+ gr.Markdown("### Check models' new version")
154
+ with gr.Row():
155
+ model_types_ckbg = gr.CheckboxGroup(choices=model_types, label="Model Types", value=["lora"])
156
+ check_models_new_version_btn = gr.Button(value="Check New Version from Civitai", variant="primary")
157
+
158
+ check_models_new_version_log_md = gr.HTML("It takes time, just wait. Check console log for detail")
159
+
160
+ with gr.Box(elem_classes="ch_box"):
161
+ with gr.Column():
162
+ gr.Markdown("### Other Setting")
163
+ with gr.Row():
164
+ open_url_with_js_ckb = gr.Checkbox(label="Open Url At Client Side", value=open_url_with_js, elem_id="ch_open_url_with_js_ckb")
165
+ always_display_ckb = gr.Checkbox(label="Always Display Buttons", value=always_display, elem_id="ch_always_display_ckb")
166
+ 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")
167
+
168
+ proxy_txtbox = gr.Textbox(label="Proxy", interactive=True, lines=1, value=proxy, info="format: http://127.0.0.1:port")
169
+
170
+ save_setting_btn = gr.Button(value="Save Setting")
171
+ general_log_md = gr.Markdown(value="")
172
+
173
+
174
+ # ====Footer====
175
+ gr.Markdown(f"<center>version:{util.version}</center>")
176
+
177
+ # ====hidden component for js, not in any tab====
178
+ js_msg_txtbox = gr.Textbox(label="Request Msg From Js", visible=False, lines=1, value="", elem_id="ch_js_msg_txtbox")
179
+ py_msg_txtbox = gr.Textbox(label="Response Msg From Python", visible=False, lines=1, value="", elem_id="ch_py_msg_txtbox")
180
+
181
+ js_open_url_btn = gr.Button(value="Open Model Url", visible=False, elem_id="ch_js_open_url_btn")
182
+ js_add_trigger_words_btn = gr.Button(value="Add Trigger Words", visible=False, elem_id="ch_js_add_trigger_words_btn")
183
+ js_use_preview_prompt_btn = gr.Button(value="Use Prompt from Preview Image", visible=False, elem_id="ch_js_use_preview_prompt_btn")
184
+ 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")
185
+
186
+ # ====events====
187
+ # Scan Models for Civitai
188
+ scan_model_civitai_btn.click(model_action_civitai.scan_model, inputs=[scan_model_types_ckbg, max_size_preview_ckb, skip_nsfw_preview_ckb], outputs=scan_model_log_md)
189
+
190
+ # Get Civitai Model Info by Model Page URL
191
+ model_type_drop.change(get_model_names_by_input, inputs=[model_type_drop, empty_info_only_ckb], outputs=model_name_drop)
192
+ empty_info_only_ckb.change(get_model_names_by_input, inputs=[model_type_drop, empty_info_only_ckb], outputs=model_name_drop)
193
+
194
+ 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)
195
+
196
+ # Download Model
197
+ 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])
198
+ 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, dl_all_ckb, max_size_preview_ckb, skip_nsfw_preview_ckb], outputs=dl_log_md)
199
+
200
+ # Check models' new version
201
+ 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)
202
+
203
+ # Other Setting
204
+ 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, proxy_txtbox], outputs=general_log_md)
205
+
206
+ # js action
207
+ js_open_url_btn.click(js_action_civitai.open_model_url, inputs=[js_msg_txtbox, open_url_with_js_ckb], outputs=py_msg_txtbox)
208
+ js_add_trigger_words_btn.click(js_action_civitai.add_trigger_words, inputs=[js_msg_txtbox], outputs=[txt2img_prompt, img2img_prompt])
209
+ 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])
210
+ 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)
211
+
212
+ # the third parameter is the element id on html, with a "tab_" as prefix
213
+ return (civitai_helper , "Civitai Helper", "civitai_helper"),
214
+
215
+ script_callbacks.on_ui_tabs(on_ui_tabs)
216
+
217
+
218
+
Stable-Diffusion-Webui-Civitai-Helper/style.css ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ blockquote ul {
2
+ list-style:disc;
3
+ margin:4px 40px;
4
+ }
5
+
6
+ blockquote ol {
7
+ list-style:decimal;
8
+ margin:4px 40px;
9
+ }
10
+
11
+ .block.padded.ch_box {
12
+ padding: 10px !important;
13
+ }
14
+
15
+ .block.padded.ch_vpadding {
16
+ padding: 10px 0 !important;
17
+ }
18
+
a1111-microsoftexcel-locon/.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ __pycache__