baqu2213 commited on
Commit
f7f0d05
โ€ข
1 Parent(s): f11c2fb

Upload 2 files

Browse files
.gitattributes CHANGED
@@ -88,3 +88,4 @@ Danbooru[[:space:]]Prompt[[:space:]]Selector/TEST/prompt_selector_auto_1202_test
88
  Danbooru[[:space:]]Prompt[[:space:]]Selector/prompt_selector_auto_1202.exe filter=lfs diff=lfs merge=lfs -text
89
  Danbooru[[:space:]]Prompt[[:space:]]Selector/TEST/prompt_selector_auto_1204_test.exe filter=lfs diff=lfs merge=lfs -text
90
  Danbooru[[:space:]]Prompt[[:space:]]Selector/TEST/prompt_selector_auto_1205_test.exe filter=lfs diff=lfs merge=lfs -text
 
 
88
  Danbooru[[:space:]]Prompt[[:space:]]Selector/prompt_selector_auto_1202.exe filter=lfs diff=lfs merge=lfs -text
89
  Danbooru[[:space:]]Prompt[[:space:]]Selector/TEST/prompt_selector_auto_1204_test.exe filter=lfs diff=lfs merge=lfs -text
90
  Danbooru[[:space:]]Prompt[[:space:]]Selector/TEST/prompt_selector_auto_1205_test.exe filter=lfs diff=lfs merge=lfs -text
91
+ Danbooru[[:space:]]Prompt[[:space:]]Selector/TEST/prompt_selector_auto_1208_testv6.exe filter=lfs diff=lfs merge=lfs -text
Danbooru Prompt Selector/TEST/prompt_selector_auto_1208_testv6.exe ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:de41ed78bdc5594f6081bc831c2f1c4942a3c10b28643298c9511d34760dacbb
3
+ size 81784364
Danbooru Prompt Selector/TEST/prompt_selector_auto_1208_testv6.py ADDED
@@ -0,0 +1,2033 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tkinter as tk
2
+ import tkinter.ttk as ttk
3
+ from tkinter import filedialog
4
+ import os
5
+ import csv
6
+ import random
7
+ import time
8
+ from collections import Counter
9
+ import re
10
+ import ast
11
+ import pyautogui
12
+ import threading
13
+ from pynput import keyboard
14
+ from base64 import urlsafe_b64encode
15
+ from hashlib import blake2b
16
+ import argon2
17
+ import requests
18
+ import json
19
+ from os import environ as env
20
+ import zipfile
21
+ import io
22
+ from pathlib import Path
23
+ from datetime import datetime
24
+ import numpy as np
25
+ from PIL import Image, ImageOps, ImageDraw, ImageFont,ImageTk
26
+ from IPython.display import display
27
+ import win32clipboard
28
+ from io import BytesIO
29
+ from datetime import datetime
30
+ import arti_list, tagbag, wlist
31
+
32
+ BASE_URL="https://api.novelai.net"
33
+
34
+ def argon_hash(email: str, password: str, size: int, domain: str) -> str:
35
+ pre_salt = f"{password[:6]}{email}{domain}"
36
+ # salt
37
+ blake = blake2b(digest_size=16)
38
+ blake.update(pre_salt.encode())
39
+ salt = blake.digest()
40
+ raw = argon2.low_level.hash_secret_raw(
41
+ password.encode(),
42
+ salt,
43
+ 2,
44
+ int(2000000 / 1024),
45
+ 1,
46
+ size,
47
+ argon2.low_level.Type.ID,
48
+ )
49
+ hashed = urlsafe_b64encode(raw).decode()
50
+ return hashed
51
+
52
+ def login(key) -> str:
53
+ response = requests.post(f"{BASE_URL}/user/login", json={ "key": key })
54
+ # catch any errors
55
+ return response.json()["accessToken"]
56
+
57
+ def get_access_key(email: str, password: str) -> str:
58
+ return argon_hash(email, password, 64, "novelai_data_access_key")[:64]
59
+
60
+ def get_max_size():
61
+ global window
62
+ width = window.winfo_screenheight()
63
+ return 768 if width < 1440 else 1024
64
+
65
+ def generate_image(access_token, prompt, model, action, parameters):
66
+ data = {
67
+ "input": prompt,
68
+ "model": model,
69
+ "action": action,
70
+ "parameters": parameters,
71
+ }
72
+
73
+ response = requests.post(f"{BASE_URL}/ai/generate-image", json=data, headers={ "Authorization": f"Bearer {access_token}" })
74
+ # catch any errors
75
+ return response.content
76
+
77
+ def generate(width, height, positive, negative, button):
78
+ global temp_clipboard_image
79
+ global current_sampler
80
+ global NAI_width, NAI_height
81
+ global running_flag
82
+ global last_generation_seed
83
+ try:
84
+ scale = float(entry_CFG_value.get())
85
+ except:
86
+ scale = 5.0
87
+ if scale > 7.0: scale = 7.0
88
+ elif scale < 4.0: scale = 4.0
89
+ else: scale = round(scale, 1)
90
+
91
+ try:
92
+ scale2 = float(entry_rescale_value.get())
93
+ except:
94
+ scale2 = 0
95
+ if scale2 > 1.00: scale = 1.00
96
+ elif scale2 < 0.0: scale = 0.00
97
+ else: scale2 = round(scale2, 2)
98
+
99
+ params = {
100
+ "legacy": False,
101
+ "quality_toggle": False,
102
+ "width": width,
103
+ "height": height,
104
+ "n_samples": 1,
105
+ "seed": random.randint(0,9999999999),
106
+ "extra_noise_seed": random.randint(0,9999999999),
107
+ "sampler": current_sampler,
108
+ "steps": 28,
109
+ "scale": scale,
110
+ "uncond_scale": 1.0,
111
+ "negative_prompt": negative_text.get("1.0", "end-1c").strip(),
112
+ "sm" : sema_button_var.get(),
113
+ "sm_dyn" : dyn_button_var.get(),
114
+ "decrisper": False,
115
+ "controlnet_strength": 1.0,
116
+ "add_original_image": False,
117
+ "cfg_rescale": scale2,
118
+ "noise_schedule": "native",
119
+ }
120
+
121
+ if (hold_seed_var.get()):
122
+ params['seed'] = last_generation_seed
123
+
124
+ def resize_and_fill(image, max_size=None):
125
+ if max_size is None:
126
+ max_size = get_max_size()
127
+ original_width, original_height = image.size
128
+ if original_width > max_size or original_height > max_size:
129
+ # ๋น„์œจ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ํฌ๊ธฐ ์กฐ์ •
130
+ image.thumbnail((max_size, max_size))
131
+
132
+ # ์ƒˆ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ๊ณ„์‚ฐ
133
+ width, height = image.size
134
+ new_image = Image.new("RGB", (max_size, max_size), "black")
135
+ new_image.paste(image, ((max_size - width) // 2, (max_size - height) // 2))
136
+ return new_image
137
+ else:
138
+ return image
139
+
140
+ def log_error(e, output_file_path="output_file_path"):
141
+ # ํ˜„์žฌ ์‹œ๊ฐ„์„ ์–ป์Šต๋‹ˆ๋‹ค
142
+ current_time = datetime.now().strftime("%m/%d %H:%M:%S")
143
+
144
+ # ์—๋Ÿฌ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€
145
+ error_message = f"#### Error occured at {current_time} ####\nError: {e}\n############################################\n"
146
+
147
+ # ์ง€์ •๋œ ์ถœ๋ ฅ ํด๋”์˜ error_log.txt ํŒŒ์ผ์— ์“ฐ๊ธฐ
148
+ with open(f"error_log.txt", "a") as file:
149
+ file.write(error_message)
150
+
151
+ global access_token
152
+ while (running_flag):
153
+ time.sleep(1)
154
+ try:
155
+ running_flag = True
156
+ tprint("Running : NAI request received")
157
+ zipped_bytes = generate_image(access_token, positive, "nai-diffusion-3", "generate", params)
158
+ d = Path(f"output_NAI/{start_time}/txt2img")
159
+ d.mkdir(parents=True, exist_ok=True)
160
+ zipped = zipfile.ZipFile(io.BytesIO(zipped_bytes))
161
+ image_bytes = zipped.read(zipped.infolist()[0])
162
+ (d / f"{datetime.now().strftime('%Y%m%d_%H%M%S')}.png" ).write_bytes(image_bytes)
163
+ i = Image.open(io.BytesIO(image_bytes))
164
+ i = ImageOps.exif_transpose(i).convert("RGB")
165
+ if temp_clipboard_image is not None:
166
+ temp_clipboard_image.close()
167
+ temp_clipboard_image = i
168
+ i_resized = resize_and_fill(i)
169
+ if 'tk_image' in globals():
170
+ globals()['tk_image'] = None
171
+ tk_image = ImageTk.PhotoImage(i_resized)
172
+ image_label.config(image=tk_image)
173
+ image_label.image = tk_image # ์ฐธ์กฐ ์œ ์ง€
174
+ output_file_path = "output_image.jpg"
175
+ i.save(output_file_path)
176
+ except Exception as e:
177
+ #text_output.insert(tk.END, f"Error: {e}", fg='red')
178
+ log_error(e, "path_to_output_folder")
179
+ time.sleep(random.uniform(1.0, 2.5))
180
+ button.config(state=tk.NORMAL)
181
+
182
+ running_flag = False
183
+ last_generation_seed = params['seed']
184
+ entry_seed_value.set(last_generation_seed)
185
+
186
+ if mac_var.get() and not running_flag:
187
+ random_function()
188
+ time.sleep(random.uniform(5.1, 8.5))
189
+ button.config(state=tk.DISABLED)
190
+ window.event_generate(GENERATE_EVENT, when="tail")
191
+ else:
192
+ time.sleep(random.uniform(1.0, 2.5))
193
+ button.config(state=tk.NORMAL)
194
+ tprint('state : idle')
195
+
196
+ def filter_csv(input_file, output_file, _search_strings):
197
+ output_directory = os.getcwd()
198
+ output_file = os.path.join(output_directory, output_file)
199
+ search_strings = [s.strip() for s in _search_strings.split(',')]
200
+ with open(input_file, 'r', newline='', encoding='utf-8') as f_in, \
201
+ open(output_file, 'w', newline='', encoding='utf-8') as f_out:
202
+ reader = csv.reader(f_in)
203
+ writer = csv.writer(f_out)
204
+ writer_count = 0
205
+ for row in reader:
206
+ if all(search_str in value for search_str in search_strings for value in row):
207
+ writer.writerow(row)
208
+ writer_count += 1
209
+ return writer_count
210
+
211
+ def open_file():
212
+ initial_dir = os.getcwd()
213
+ filepath = filedialog.askopenfilename(
214
+ initialdir=initial_dir,
215
+ filetypes=[("CSV Files", "*.csv")]
216
+ )
217
+ if filepath:
218
+ entry_file_path.delete(0, tk.END)
219
+ entry_file_path.insert(0, filepath)
220
+
221
+ def search():
222
+ global total_rows, cached_rows # cached_rows๋ฅผ global๋กœ ์„ ์–ธ
223
+ input_file = entry_file_path.get()
224
+ keywords = entry_keyword.get()
225
+
226
+ output_file = 'txt2img_temp_prompt.csv'
227
+ writer_count = filter_csv(input_file, output_file, keywords)
228
+ total_rows = writer_count
229
+ total_rows_count_label.config(text=f".csv ๋‚ด ํ”„๋กฌํ”„ํŠธ ํ–‰: {writer_count}", fg="blue")
230
+ text_output.insert(tk.END, f"์ด {writer_count}๊ฐœ์˜ ๋ฌธ์ž์—ด์ด ๊ฒ€์ƒ‰๋˜์–ด ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.\n")
231
+
232
+ # ๊ฒ€์ƒ‰ ํ›„ cached_rows ์ดˆ๊ธฐํ™”
233
+ cached_rows = []
234
+
235
+ def exclude():
236
+ global total_rows, cached_rows # cached_rows๋ฅผ global๋กœ ์„ ์–ธ
237
+ input_file = entry_file_path.get()
238
+ keywords = entry_keyword.get()
239
+ output_file = 'txt2img_temp_prompt.csv'
240
+ keyword_label.config(text="๊ฒ€์ƒ‰ํ•  ํ‚ค์›Œ๋“œ: ")
241
+
242
+ output_directory = os.getcwd()
243
+ output_file = os.path.join(output_directory, output_file)
244
+ search_strings = [s.strip() for s in keywords.split(',')]
245
+
246
+ with open(input_file, 'r', newline='', encoding='utf-8') as f_in, \
247
+ open(output_file, 'w', newline='', encoding='utf-8') as f_out:
248
+ reader = csv.reader(f_in)
249
+ writer = csv.writer(f_out)
250
+ writer_count = 0
251
+ for row in reader:
252
+ if not any(search_str in value for search_str in search_strings for value in row):
253
+ writer.writerow(row)
254
+ writer_count += 1
255
+ total_rows = writer_count
256
+ total_rows_count_label.config(text=f".csv ๋‚ด ํ”„๋กฌํ”„ํŠธ ํ–‰: {writer_count}", fg="red")
257
+ text_output.insert(tk.END, f"์ด {writer_count}๊ฐœ์˜ ๋ฌธ์ž์—ด์ด ๊ฒ€์ƒ‰๋˜์–ด ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.\n")
258
+
259
+ # ์ œ์™ธ ํ›„ cached_rows ์ดˆ๊ธฐํ™”
260
+ cached_rows = []
261
+
262
+ def copy_image_to_clipboard():
263
+ global temp_clipboard_image
264
+ image = temp_clipboard_image
265
+ output = BytesIO()
266
+ image.convert('RGB').save(output, format='BMP')
267
+ data = output.getvalue()[14:] # BMP ํŒŒ์ผ ํ—ค๋” ์ œ๊ฑฐ
268
+ output.close()
269
+
270
+ win32clipboard.OpenClipboard()
271
+ win32clipboard.EmptyClipboard()
272
+ win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
273
+ win32clipboard.CloseClipboard()
274
+
275
+ def reset():
276
+ cached_rows = None
277
+ entry_file_path.delete(0, tk.END)
278
+ entry_keyword.delete(0, tk.END)
279
+ entry_deep_search.delete(0, tk.END)
280
+ text_output.delete('1.0', tk.END)
281
+
282
+ def random_function():
283
+ global last_deep_search_keywords, cached_rows, last_selected_row_keywords, top_100_keywords, previous_artist, top_100_counts
284
+ global current_wildcard_character, current_wildcard_artist
285
+ current_deep_search_keywords = entry_deep_search.get().strip()
286
+ auto_hide_keywords = entry_auto_hide.get().split(',')
287
+ auto_hide_keywords = [keyword.strip() for keyword in auto_hide_keywords if keyword.strip()]
288
+ current_artist = None
289
+
290
+ curly_brackets_keywords = re.findall(r'\{([^}]+)\}', current_deep_search_keywords)
291
+ # ๊ฐ ๋ธŒ๋ž˜ํ‚ท ๋‚ด ํ‚ค์›Œ๋“œ ๊ทธ๋ฃน์„ ์ฒ˜๋ฆฌํ•˜์—ฌ ์™„๋ฒฝ ์ผ์น˜ ํ‚ค์›Œ๋“œ์™€ ์ผ๋ฐ˜ ํ‚ค์›Œ๋“œ๋ฅผ ๊ตฌ๋ถ„
292
+ processed_keywords = []
293
+ for group in curly_brackets_keywords:
294
+ perfect_match_group = [kw[1:].strip() for kw in group.split('|') if kw.startswith('*')]
295
+ regular_group = [kw.strip() for kw in group.split('|') if not kw.startswith('*')]
296
+ processed_keywords.append((perfect_match_group, regular_group))
297
+
298
+ modified_deep_search_keywords = re.sub(r'\{[^}]+\}', '', current_deep_search_keywords)
299
+
300
+ # ๋‚จ์€ ํ‚ค์›Œ๋“œ๋“ค์„ ์‰ผํ‘œ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์ฒ˜๋ฆฌ
301
+ remaining_keywords = [kw.strip() for kw in modified_deep_search_keywords.split(',') if kw.strip()]
302
+ perfect_match_keywords = [kw[1:].strip() for kw in remaining_keywords if kw.startswith('*')]
303
+
304
+ # exclude_keywords์™€ include_keywords ์ •์˜
305
+ exclude_keywords = [kw[1:].strip() for kw in remaining_keywords if kw.startswith('~') and not kw[1:].startswith('*')]
306
+ include_keywords = [kw for kw in remaining_keywords if not kw.startswith('~') and not kw.startswith('*')]
307
+
308
+ if current_deep_search_keywords != last_deep_search_keywords or not cached_rows:
309
+ entry_auto_hide.delete(0, tk.END)
310
+ entry_auto_hide.insert(tk.END, 'monochrome, doujin cover, bad source, censored, bar censor, photoshop (medium)')
311
+ with open('txt2img_temp_prompt.csv', 'r', newline='', encoding='utf-8') as f:
312
+ reader = csv.reader(f)
313
+ rows = []
314
+ for row in reader:
315
+ if all(re.search(r'(?:^|, )' + re.escape(kw) + r'(?:,|$)', ', '.join(row)) for kw in perfect_match_keywords) \
316
+ and not any(exclude in cell for exclude in exclude_keywords for cell in row) \
317
+ and all(include in cell for include in include_keywords for cell in row):
318
+ # '{}' ์•ˆ์˜ ํ‚ค์›Œ๋“œ ์ฒ˜๋ฆฌ
319
+ if all(any(re.search(r'(?:^|, )' + re.escape(kw) + r'(?:,|$)', ', '.join(cell)) for kw in perfect_group) or
320
+ any(kw in cell for kw in regular_group) for perfect_group, regular_group in processed_keywords for cell in row):
321
+ rows.append(row)
322
+ cached_rows = rows
323
+
324
+ last_deep_search_keywords = current_deep_search_keywords
325
+ if not toggle_prompt_var.get(): text_output.delete('1.0', tk.END)
326
+
327
+ if random_artist_var.get():
328
+ if(not entry_fixed_prompt.get()): entry_fixed_prompt.insert(tk.END,'1girl')
329
+
330
+ if not os.path.exists("counting_result.txt"):
331
+ keyword_counts = analyze_cached_rows(cached_rows)
332
+ excluded_keywords = set(whitelist[:2974])
333
+ with open("counting_result.txt", "w") as file:
334
+ for keyword, count in sorted(keyword_counts.items(), key=lambda item: item[1], reverse=True):
335
+ if keyword not in excluded_keywords and keyword in afilter_30000:
336
+ file.write(f"{keyword}: {count}\n")
337
+ with open("counting_result.txt", "r") as file:
338
+ lines = file.readlines()
339
+ top_100_data = [
340
+ (line.split(":")[0].strip(), int(line.split(":")[1].strip()))
341
+ for line in lines[:3000]
342
+ if line.split(":")[0].strip() in afilter_30000[:8528]
343
+ ]
344
+ top_100_keywords, top_100_counts = zip(*top_100_data) if top_100_data else ([], [])
345
+ elif (not top_100_keywords):
346
+ with open("counting_result.txt", "r") as file:
347
+ lines = file.readlines()
348
+ top_100_data = [
349
+ (line.split(":")[0].strip(), int(line.split(":")[1].strip()))
350
+ for line in lines[:3000]
351
+ if line.split(":")[0].strip() in afilter_30000[:8528]
352
+ ]
353
+ top_100_keywords, top_100_counts = zip(*top_100_data) if top_100_data else ([], [])
354
+
355
+ formatted_artist_random_keyword = []
356
+ if top_100_keywords:
357
+ temp_keyword = []
358
+ temp_keyword += top_100_keywords
359
+ whatthefuck = random.random()
360
+ if(whatthefuck > 0.9):
361
+ for i in range(4):
362
+ random_keyword = random.choice(temp_keyword)
363
+ temp_keyword.remove(random_keyword)
364
+ if(i == 0): formatted_artist_random_keyword = "{{{artist:"+random_keyword+"}}}"
365
+ if(i == 1): formatted_artist_random_keyword += ",{artist:"+random_keyword+"}"
366
+ if(i == 2): formatted_artist_random_keyword += ",artist:"+random_keyword
367
+ if(i == 3): formatted_artist_random_keyword += ",[[artist:"+random_keyword+"]]"
368
+ elif(whatthefuck > 0.7):
369
+ for i in range(3):
370
+ random_keyword = random.choice(temp_keyword)
371
+ temp_keyword.remove(random_keyword)
372
+ if(i == 0): formatted_artist_random_keyword = "{{{artist:"+random_keyword+"}}}"
373
+ if(i == 1): formatted_artist_random_keyword += ",{artist:"+random_keyword+"}"
374
+ if(i == 2): formatted_artist_random_keyword += ",[[artist:"+random_keyword+"]]"
375
+ elif(whatthefuck > 0.45):
376
+ for i in range(2):
377
+ random_keyword = random.choice(temp_keyword)
378
+ temp_keyword.remove(random_keyword)
379
+ if(i == 0): formatted_artist_random_keyword = "{{{artist:"+random_keyword+"}}}"
380
+ if(i == 2): formatted_artist_random_keyword += ",[[artist:"+random_keyword+"]]"
381
+ else:
382
+ random_keyword = random.choice(temp_keyword)
383
+ temp_keyword.remove(random_keyword)
384
+ formatted_artist_random_keyword = "{{artist:"+random_keyword+"}}"
385
+ current_artist = formatted_artist_random_keyword
386
+ if not top_100_keywords: random_artist_var.set(0)
387
+ else:
388
+ formatted_artist_random_keyword = f"์ž‘๊ฐ€ ํ‚ค์›Œ๋“œ๊ฐ€ ์—†์Œ!!"
389
+
390
+ if cached_rows:
391
+ if toggle_prompt_var.get() and last_selected_row_keywords:
392
+ random_row_keywords = last_selected_row_keywords
393
+ #random_row_keywords[-1].strip()
394
+ #if random_row_keywords[0]=='': random_row_keywords = last_selected_row_keywords
395
+ text_output.delete('1.0', tk.END)
396
+ else:
397
+ random_index = random.randint(0, len(cached_rows) - 1)
398
+ random_row = cached_rows.pop(random_index)
399
+ random_row_keywords = [keyword.strip() for keyword in random_row[0].split(',')]
400
+ last_selected_row_keywords = random_row_keywords
401
+
402
+ if(entry_fixed_prompt.get()):
403
+ entry_text_keywords = entry_fixed_prompt.get()
404
+ if(',' not in entry_text_keywords[-2:]): entry_text_keywords += ','
405
+ entry_text_keywords = entry_text_keywords.split(',')
406
+ entry_text_keywords = [kw.strip() for kw in entry_text_keywords if kw.strip()]
407
+
408
+ temp_first_keywords = []
409
+ #print("1 :", temp_first_keywords)
410
+
411
+ # entry_text_keywords์˜ ๋ชจ๋“  ํ‚ค์›Œ๋“œ๋ฅผ temp_first_keywords์— ์ถ”๊ฐ€
412
+ for et_kw in entry_text_keywords:
413
+ if ('boy' in et_kw or 'girl' in et_kw) or (' '+et_kw not in random_row_keywords and ' '+et_kw not in random_row_keywords):
414
+ temp_first_keywords.append(et_kw)
415
+
416
+ # 'boy' ํ‚ค์›Œ๋“œ ์ฒ˜๋ฆฌ
417
+ boy_keywords = [kw for kw in random_row_keywords if 'boy' in kw and len(kw) <= 7]
418
+
419
+ # 'girl' ํ‚ค์›Œ๋“œ ์ฒ˜๋ฆฌ ๋ฐ ์œ„์น˜ ์กฐ์ •
420
+ girl_keywords = []
421
+ if 'girl' in entry_text_keywords[0] and len(entry_text_keywords[0]) <= 7:
422
+ girl_keywords = [kw for kw in random_row_keywords if 'girl' in kw and len(kw) <= 7]
423
+
424
+ # random_row_keywords์—์„œ boy์™€ girl ํ‚ค์›Œ๋“œ ์ œ๊ฑฐ
425
+ for kw in boy_keywords + girl_keywords:
426
+ if kw in random_row_keywords:
427
+ random_row_keywords.remove(kw)
428
+
429
+ for kw in temp_first_keywords:
430
+ if kw in random_row_keywords:
431
+ random_row_keywords.remove(kw)
432
+
433
+
434
+ # temp_first_keywords์— boy์™€ girl ํ‚ค์›Œ๋“œ๋ฅผ ์ ์ ˆํ•œ ์œ„์น˜์— ์ถ”๊ฐ€
435
+ if(girl_keywords and 'girl' in temp_first_keywords[0]): temp_first_keywords.pop(0)
436
+ #print(wildcard_var.get())
437
+ if(wildcard_var2.get() == 1):
438
+ temp_len = len(girl_keywords)
439
+ girl_keywords.append(get_random_keyword('character'))
440
+ if(wildcard_var.get() == 1):
441
+ if(wildcard_var2.get() == 1):
442
+ girl_keywords.insert(temp_len+1,get_random_keyword('artist'))
443
+ else:
444
+ girl_keywords.append(get_random_keyword('artist'))
445
+ print(boy_keywords)
446
+ print(girl_keywords)
447
+ print(temp_first_keywords)
448
+ if temp_first_keywords and 'girl' in temp_first_keywords[0]:
449
+ girl_in_gkey = False
450
+ for gkey in girl_keywords:
451
+ if 'girl' in gkey:
452
+ girl_in_gkey = True
453
+ if not girl_in_gkey:
454
+ temp_gkey = temp_first_keywords.pop(0)
455
+ girl_keywords.insert(0, temp_gkey)
456
+
457
+ temp_first_keywords = boy_keywords + girl_keywords + temp_first_keywords
458
+ #print("2 :", temp_first_keywords)
459
+
460
+ if remove_artist_var.get():
461
+ for keyword in random_row_keywords:
462
+ if keyword in afilter_30000:
463
+ random_row_keywords.remove(keyword)
464
+ temp_rm = []
465
+ if rm_characteristic_var.get():
466
+ for keyword in random_row_keywords:
467
+ if keyword in bag_of_tags or "(" in keyword or "horns" in keyword:
468
+ temp_rm.append(keyword)
469
+ for keyword in temp_rm:
470
+ random_row_keywords.remove(keyword)
471
+
472
+ for keyword in random_row_keywords[:]: # ๋ณต์‚ฌ๋ณธ์„ ์ˆœํšŒํ•˜์—ฌ ์›๋ณธ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆ˜์ •
473
+ if " (" in keyword:
474
+ temp_first_keywords.append(keyword)
475
+ random_row_keywords.remove(keyword)
476
+ else:
477
+ if not random_row_keywords: random_row_keywords = last_selected_row_keywords
478
+ temp_first_keywords = []
479
+ for keyword in random_row_keywords[:]: # ๋ณต์‚ฌ๋ณธ์„ ์ˆœํšŒํ•˜์—ฌ ์›๋ณธ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆ˜์ •
480
+ if " (" in keyword:
481
+ temp_first_keywords.append(keyword)
482
+ random_row_keywords.remove(keyword)
483
+
484
+ last_selected_row_keywords =boy_keywords + girl_keywords[:0] + random_row_keywords
485
+ #print("3 :", temp_first_keywords)
486
+ if random_artist_var.get():
487
+ temp_first_keywords.append(formatted_artist_random_keyword)
488
+ #print("4 :", temp_first_keywords)
489
+ if (previous_artist and previous_artist in temp_first_keywords): temp_first_keywords.remove(previous_artist)
490
+ if (current_artist is (not None)):
491
+ for i in range (len(current_artist)):
492
+ previous_artist += current_artist[i]
493
+ random_row_keywords = temp_first_keywords + random_row_keywords
494
+ #print("5 :", random_row_keywords)
495
+ elif toggle_prompt_var.get(): random_row_keywords = temp_first_keywords + random_row_keywords
496
+ else: random_row_keywords = temp_first_keywords + random_row_keywords
497
+
498
+ patterns = [r'\b{}\b'.format(re.escape(keyword)) for keyword in auto_hide_keywords]
499
+
500
+ for pattern in patterns:
501
+ random_row_keywords = [re.sub(pattern + '(, )?', '', keyword) for keyword in random_row_keywords]
502
+ random_row_keywords = [re.sub('(?<=, )' + pattern, '', keyword) for keyword in random_row_keywords]
503
+
504
+ if entry_fixed_prompt_after.get():
505
+ entry_after_text = entry_fixed_prompt_after.get().strip().split(',')
506
+ for at_kw in entry_after_text:
507
+ if at_kw not in random_row_keywords and ' '+at_kw not in random_row_keywords:
508
+ random_row_keywords.append(at_kw)
509
+
510
+ random_row_keywords = [keyword.strip(', ') for keyword in random_row_keywords]
511
+ random_row_keywords = [keyword for keyword in random_row_keywords if keyword]
512
+ #print(random_row_keywords)
513
+ text_output.insert(tk.END, f"{', '.join(random_row_keywords)}")
514
+ if auto_copy_var.get():
515
+ copy_to_clipboard()
516
+ else:
517
+ text_output.insert(tk.END, "๊ฒ€์ƒ‰ ์กฐ๊ฑด์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๊ฑฐ๋‚˜ CSV ํŒŒ์ผ์— ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.\n")
518
+
519
+ cached_rows_count_label.config(text=f"์‹ฌ์ธต๊ฒ€์ƒ‰ ํ”„๋กฌํ”„ํŠธ ํ–‰: {len(cached_rows)}")
520
+
521
+ def add_low_frequency_keywords():
522
+ global keyword_counts, most_common_count
523
+ keyword_counts = analyze_cached_rows(cached_rows)
524
+ if not keyword_counts: # keyword_counts๊ฐ€ ๋น„์–ด์žˆ๋Š” ๊ฒฝ์šฐ ํ•จ์ˆ˜๋ฅผ ๋น ์ ธ๋‚˜์˜ต๋‹ˆ๋‹ค.
525
+ return
526
+
527
+ # ๊ฐ€์žฅ ํ”ํ•œ ํ‚ค์›Œ๋“œ์˜ ๋นˆ๋„์ˆ˜๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
528
+ most_common_count = keyword_counts.most_common(1)[0][1]
529
+
530
+ # ์กฐ๊ฑด์— ๋งž๋Š” ํ‚ค์›Œ๋“œ๋“ค์„ ์ฐพ์Šต๋‹ˆ๋‹ค.
531
+ low_freq_keywords = [keyword for keyword, count in keyword_counts.items()
532
+ if keyword not in last_deep_search_keywords and keyword not in whitelist and count / most_common_count <= 0.05]
533
+
534
+ # ์ž๋™ ์ˆจ๊น€ ํ‚ค์›Œ๋“œ ์ž…๋ ฅ์ฐฝ์— ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
535
+ existing_keywords = entry_auto_hide.get().split(',')
536
+ existing_keywords = [keyword.strip() for keyword in existing_keywords if keyword.strip()] # ๊ณต๋ฐฑ ์ œ๊ฑฐ ๋ฐ ๋นˆ ๋ฌธ์ž์—ด ์ œ๊ฑฐ
537
+
538
+ # ๊ธฐ์กด ํ‚ค์›Œ๋“œ์— ์ƒˆ๋กœ์šด ์ €๋นˆ๋„ ํ‚ค์›Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
539
+ updated_keywords = existing_keywords + low_freq_keywords
540
+ unique_keywords = list(set(updated_keywords)) # ์ค‘๋ณต ์ œ๊ฑฐ
541
+ for keyword in unique_keywords:
542
+ if(keyword in afilter_30000):
543
+ unique_keywords.remove(keyword)
544
+ entry_auto_hide.delete(0, tk.END)
545
+ entry_auto_hide.insert(0, ', '.join(unique_keywords))
546
+
547
+ def copy_to_clipboard():
548
+ window.clipboard_clear()
549
+ entry_text = entry_fixed_prompt.get()
550
+ if(',' not in entry_text and entry_text): entry_text += ','
551
+ combined_text = text_output.get("1.0", tk.END)
552
+ window.clipboard_append(combined_text)
553
+
554
+ def turbo_stop(button):
555
+ global turbo_stop_bit
556
+ button.config(state=tk.DISABLED)
557
+ turbo_stop_bit = True
558
+ tprint("Stopping pipelines ... ")
559
+
560
+ def exit_program():
561
+ window.destroy()
562
+
563
+ def save_settings():
564
+ global NAI_ID
565
+ with open('app_settings.txt', 'w', encoding='utf-8') as f: #1
566
+ if(len(entry_file_path.get()) > 4):
567
+ f.write(entry_file_path.get() + '\n')
568
+ else: f.write(" "+'\n')
569
+ if(len(entry_keyword.get()) > 3): #2
570
+ f.write(entry_keyword.get() + '\n')
571
+ else: f.write(" "+'\n')
572
+ if(len(entry_deep_search.get()) > 3): #3
573
+ f.write(entry_deep_search.get() + '\n')
574
+ else: f.write(" "+'\n')
575
+ if(len(entry_fixed_prompt.get()) > 4): #4
576
+ f.write(entry_fixed_prompt.get() + '\n')
577
+ else: f.write(" "+'\n')
578
+ if(len(entry_fixed_prompt_after.get()) > 4): #5
579
+ f.write(entry_fixed_prompt_after.get() + '\n')
580
+ else: f.write(" "+'\n')
581
+ if(len(entry_auto_hide.get()) > 3): #6
582
+ f.write(entry_auto_hide.get() + '\n')
583
+ else: f.write(" "+'\n')
584
+ if(len(negative_text.get("1.0", tk.END)) > 4): #7
585
+ f.write(negative_text.get("1.0", tk.END))
586
+ else: f.write(" "+'\n')
587
+ if(NAI_ID): f.write(NAI_ID + '\n' ) #ํ•ญ์ƒ ๋งˆ์ง€๋ง‰์— ์˜ค๋„๋ก ๊ธฐ์–ต #8
588
+
589
+ def load_settings():
590
+ NAI_ID = ""
591
+ if os.path.exists('app_settings.txt'):
592
+ with open('app_settings.txt', 'r', encoding='utf-8') as f:
593
+ settings = f.readlines()
594
+ entry_file_path.insert(0, settings[0].strip())
595
+ entry_keyword.insert(0, settings[1].strip())
596
+ entry_deep_search.insert(0, settings[2].strip())
597
+ entry_fixed_prompt.insert(0, settings[3].strip())
598
+ entry_fixed_prompt_after.insert(0, settings[4].strip())
599
+ entry_auto_hide.insert(0, settings[5].strip())
600
+ if(len(settings)>=7):
601
+ negative_text.insert(tk.END, settings[6].strip())
602
+ if(len(settings)>=8):
603
+ NAI_ID = settings[7].strip() #ํ•ญ์ƒ ๋งˆ์ง€๋ง‰์— ์˜ค๋„๋ก ๊ธฐ์–ต
604
+ return NAI_ID
605
+
606
+ def open_prompt_window():
607
+ # ์ƒˆ ์ฐฝ ์ƒ์„ฑ
608
+ prompt_window = tk.Toplevel(window)
609
+ prompt_title = f"{entry_keyword.get()}+{last_deep_search_keywords}" if last_deep_search_keywords else "์ถ”์ฒœ ํ”„๋กฌํ”„ํŠธ"
610
+ prompt_window.title(prompt_title)
611
+
612
+
613
+ # ์ฒซ ๋ฒˆ์งธ Text Output Box ์„ค์ •
614
+ text_output1 = tk.Text(prompt_window, height=10, width=50)
615
+ text_output1.pack(padx=10, pady=10)
616
+
617
+ # ๊ตต์€ ๊ธ€์”จ ์Šคํƒ€์ผ ํƒœ๊ทธ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
618
+ text_output1.tag_configure('bold', font=('Arial', 10, 'bold'))
619
+
620
+ # ๋‘ ๋ฒˆ์งธ Text Output Box ์„ค์ •
621
+ text_output2 = tk.Text(prompt_window, height=10, width=50)
622
+ text_output2.pack(padx=10, pady=10)
623
+
624
+ # ์„ธ ๋ฒˆ์งธ Text Output Box ์„ค์ •
625
+ text_output3 = tk.Text(prompt_window, height=10, width=50)
626
+ text_output3.pack(padx=10, pady=10)
627
+
628
+ # cached_rows ๋ถ„์„
629
+ keyword_counts = analyze_cached_rows(cached_rows)
630
+
631
+ # ๊ฐ€์žฅ ๋†’์€ count ๊ฐ’์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
632
+ most_common_count = keyword_counts.most_common(1)[0][1] if keyword_counts else 0
633
+
634
+ # text_output1์— ๊ฐ€์žฅ ํ”ํ•œ ํ‚ค์›Œ๋“œ๋ฅผ ์ถœ๋ ฅํ•˜๊ณ , ์กฐ๊ฑด์— ๋”ฐ๋ผ ๊ตต๊ฒŒ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
635
+ for keyword, count in keyword_counts.most_common(50):
636
+ if count / most_common_count >= 0.5: # count๊ฐ€ ๊ฐ€์žฅ ๋†’์€ ํ‚ค์›Œ๋“œ ๋Œ€๋น„ 60% ์ด์ƒ์ธ ๊ฒฝ์šฐ
637
+ text_output1.insert(tk.END, f"{keyword}, ", 'bold')
638
+ else:
639
+ text_output1.insert(tk.END, f"{keyword}, ")
640
+
641
+ # text_output2์— ๋ชจ๋“  ํ‚ค์›Œ๋“œ์™€ ๋นˆ๋„์ˆ˜ ์ถœ๋ ฅ
642
+ for keyword, count in keyword_counts.most_common(200):
643
+ text_output2.insert(tk.END, f"{keyword}: {count}, ")
644
+
645
+ excluded_keywords = set(whitelist[:2974])
646
+ artist_count = 0
647
+ with open("counting_result.txt", "w") as file:
648
+ for keyword, count in sorted(keyword_counts.items(), key=lambda item: item[1], reverse=True):
649
+ if keyword not in excluded_keywords and keyword in afilter_30000:
650
+ file.write(f"{keyword}: {count}\n")
651
+ if(artist_count < 150):
652
+ text_output3.insert(tk.END, f"{keyword}: {count}, ")
653
+ artist_count += 1
654
+
655
+ # ๋‹ซ๊ธฐ ๋ฒ„ํŠผ ์„ค์ •
656
+ close_button = tk.Button(prompt_window, text="๋‹ซ๊ธฐ", command=prompt_window.destroy)
657
+ close_button.pack(pady=10)
658
+
659
+ def analyze_cached_rows(cached_rows):
660
+ global top_100_keywords
661
+ top_100_keywords = []
662
+ counts = Counter()
663
+ for row in cached_rows:
664
+ substrings = [substring.strip() for value in row for substring in value.split(',') if substring.strip()]
665
+ counts.update(substrings)
666
+ return counts
667
+
668
+ def exit_program():
669
+ save_settings()
670
+ window.destroy()
671
+
672
+ def on_ctrl_enter(event):
673
+ random_function()
674
+
675
+ def on_shift_enter(event):
676
+ random_function()
677
+ copy_to_clipboard()
678
+
679
+ def export_csv():
680
+ source_file = os.path.join(os.getcwd(), 'txt2img_temp_prompt.csv')
681
+ if not os.path.exists(source_file):
682
+ print("์†Œ์Šค ํŒŒ์ผ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")
683
+ return
684
+
685
+ # ๊ธฐ๋ณธ ํŒŒ์ผ ์ด๋ฆ„์„ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ํ‚ค์›Œ๋“œ๋กœ ์„ค์ •
686
+ default_filename = f"{entry_keyword.get()}.csv" if entry_keyword.get() else "exported.csv"
687
+ file_types = [('CSV ํŒŒ์ผ', '*.csv')]
688
+ dest_file = filedialog.asksaveasfilename(defaultextension='.csv', filetypes=file_types, initialfile=default_filename)
689
+
690
+ if dest_file: # ์‚ฌ์šฉ์ž๊ฐ€ ํŒŒ์ผ ์ด๋ฆ„์„ ์„ ํƒํ–ˆ์„ ๊ฒฝ์šฐ
691
+ import shutil
692
+ shutil.copy(source_file, dest_file)
693
+ print(f"ํŒŒ์ผ์ด ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค: {dest_file}")
694
+
695
+ def export_csv_search():
696
+
697
+ if not cached_rows:
698
+ print("๋น„์–ด์žˆ๋Š” ํ”„๋กฌํ”„ํŠธํ–‰.")
699
+ return
700
+
701
+ # ๊ธฐ๋ณธ ํŒŒ์ผ ์ด๋ฆ„์„ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ํ‚ค์›Œ๋“œ๋กœ ์„ค์ •
702
+ default_filename = f"{entry_keyword.get()}.csv" if entry_keyword.get() else "exported.csv"
703
+ file_types = [('CSV ํŒŒ์ผ', '*.csv')]
704
+ dest_file = filedialog.asksaveasfilename(defaultextension='.csv', filetypes=file_types, initialfile=default_filename)
705
+
706
+ if dest_file: # ์‚ฌ์šฉ์ž๊ฐ€ ํŒŒ์ผ ์œ„์น˜๋ฅผ ์„ ํƒํ–ˆ๋‹ค๋ฉด
707
+ with open(dest_file, 'w', newline='', encoding='utf-8') as file:
708
+ writer = csv.writer(file)
709
+ for row in cached_rows:
710
+ writer.writerow(row) # ๊ฐ ํ–‰์„ csv ํŒŒ์ผ์— ์“ด๋‹ค
711
+
712
+ def simulate_shortcuts():
713
+ global listener, on_press_flag
714
+
715
+ on_press_flag = True
716
+ random_function()
717
+ on_press_flag = False
718
+ try:
719
+ current_keys.clear()
720
+ current_keys.add(keyboard.Key.ctrl_l)
721
+ except KeyError:
722
+ pass
723
+
724
+ def on_activate_simulate_shortcuts():
725
+ simulate_shortcuts()
726
+
727
+ def for_canonical(f):
728
+ return lambda k: f(listener.canonical(k))
729
+
730
+ def start_keyboard_listener():
731
+ global listener
732
+ listener = keyboard.Listener(on_press=on_press, on_release=on_release)
733
+ listener.start()
734
+
735
+ def on_press(key):
736
+ global on_press_flag
737
+
738
+ current_keys.add(key)
739
+
740
+ # Ctrl + ` ์กฐํ•ฉ ๊ฐ์ง€
741
+ if keyboard.Key.ctrl_l in current_keys:
742
+ if any(k.vk == 192 for k in current_keys if hasattr(k, 'vk')):
743
+ on_press_flag = True
744
+ simulate_shortcuts()
745
+
746
+ def on_release(key):
747
+ try:
748
+ current_keys.remove(key)
749
+ except KeyError:
750
+ pass
751
+
752
+ def v_automatic(save_position, prompt_position):
753
+ # ํ”„๋กฌํ”„ํŠธ ์ฐฝ ํด๋ฆญ
754
+ copy_to_clipboard()
755
+ pyautogui.click(prompt_position)
756
+ time.sleep(0.5)
757
+ random_function()
758
+ pyautogui.hotkey('ctrl', 'a', 'v','Right','Right','Enter')
759
+ time.sleep(0.5)
760
+ pyautogui.click(save_position)
761
+
762
+ def start_automation(save_position, prompt_position, label, window_to_close, automation_event):
763
+ def automation_task():
764
+ while automation_event.is_set():
765
+ random_delay = random.uniform(17.5, 23.5)
766
+ next_click_time = time.time() + random_delay
767
+ while time.time() < next_click_time and automation_event.is_set():
768
+ time_remaining = max(next_click_time - time.time(), 0)
769
+ label.config(text=f"๋‹ค์Œ ํด๋ฆญ๊นŒ์ง€: {time_remaining:.2f}์ดˆ")
770
+ time.sleep(0.1)
771
+ if automation_event.is_set():
772
+ v_automatic(save_position, prompt_position)
773
+
774
+ automation_thread = threading.Thread(target=automation_task, daemon=True)
775
+ automation_thread.start()
776
+ random_function()
777
+
778
+ def stop_automation():
779
+ automation_event.clear()
780
+ window_to_close.destroy()
781
+
782
+ window_to_close.protocol("WM_DELETE_WINDOW", stop_automation)
783
+
784
+ def stop_automation(window_to_close, automation_event, start_button, stop_button):
785
+ automation_event.clear() # Stop the automation task
786
+ start_button['state'] = 'normal' # Enable the start button
787
+ stop_button['state'] = 'disabled' # Disable the stop button
788
+ window_to_close.destroy() # Close the automation window
789
+ window.deiconify()
790
+
791
+ # ๋ผ๋ฒจ์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•จ์ˆ˜
792
+ def update_label(label, text):
793
+ def task():
794
+ label.config(text=text)
795
+ label.after(1000, task) # ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ UI ์—…๋ฐ์ดํŠธ
796
+
797
+ def open_automation_window():
798
+ window.iconify()
799
+ automation_event = threading.Event()
800
+ automation_event.set() # Enable the automation event
801
+ auto_window = tk.Toplevel(window)
802
+ auto_window.title("์ž๋™ํ™” ์„ค์ •")
803
+ auto_window.geometry("300x200") # ์ฐฝ ํฌ๊ธฐ ์กฐ์ •
804
+ auto_window.attributes('-topmost', True) # ์ฐฝ์„ ํ•ญ์ƒ ๋งจ ์œ„์— ์œ„์น˜
805
+ auto_window.focus_force() # ์ฐฝ ์—ด๋ฆด ๋•Œ ํฌ์ปค์Šค ๊ฐ•์ œ ์ด๋™
806
+
807
+ save_position = None
808
+ prompt_position = None
809
+ automation_running = threading.Event()
810
+
811
+ def get_mouse_position(event=None):
812
+ nonlocal save_position, prompt_position
813
+ x, y = pyautogui.position()
814
+ if not save_position:
815
+ save_position = (x, y)
816
+ position_label.config(text=f"์ €์žฅ ๋ฒ„ํŠผ์˜ ์ขŒํ‘œ: {x}, {y}\nํ”„๋กฌํ”„ํŠธ ์ฐฝ์˜ ์ขŒํ‘œ: ")
817
+ elif not prompt_position:
818
+ prompt_position = (x, y)
819
+ position_label.config(text=f"์ €์žฅ ๋ฒ„ํŠผ์˜ ์ขŒํ‘œ: {save_position[0]}, {save_position[1]}\nํ”„๋กฌํ”„ํŠธ ์ฐฝ์˜ ์ขŒํ‘œ: {x}, {y}")
820
+ start_button.config(state="normal")
821
+ if save_position and prompt_position:
822
+ start_button.config(state="normal")
823
+ stop_button.config(state="normal")
824
+
825
+
826
+ position_label = tk.Label(auto_window, text="์—”ํ„ฐ๋ฅผ ๋ˆŒ๋Ÿฌ ๋งˆ์šฐ์Šค ์ขŒํ‘œ๋ฅผ ์ €์žฅํ•˜์„ธ์š”\n(ํด๋ฆญ X, 1.์ €์žฅ->2.ํ”„๋กฌํ”„ํŠธ์ฐฝ ์ˆœ์„œ)", justify=tk.LEFT)
827
+ position_label.pack(pady=10)
828
+
829
+ start_button = tk.Button(auto_window, text="์‹œ์ž‘", state="disabled",
830
+ command=lambda: start_automation(save_position, prompt_position, countdown_label, auto_window, automation_event))
831
+ start_button.pack(side=tk.LEFT, fill='x', expand=True)
832
+
833
+ stop_button = tk.Button(auto_window, text="์ค‘์ง€", state="disabled",
834
+ command=lambda: stop_automation(auto_window, automation_event, start_button, stop_button))
835
+ stop_button.pack(side=tk.RIGHT, fill='x', expand=True)
836
+
837
+ countdown_label = tk.Label(auto_window, text="")
838
+ countdown_label.pack(pady=10)
839
+
840
+ auto_window.bind('<Return>', get_mouse_position)
841
+
842
+ def NAI_generation(width, height, button):
843
+ global access_token_multi, NAI_width, NAI_height
844
+ global button_stop, running_flag
845
+
846
+ pretest = text_output.get("1.0", tk.END).split(', ')
847
+ if (turbo_var.get() == 1):
848
+ if ( 'sex' not in pretest or '1girl' not in pretest or '1boy' not in pretest):
849
+ tprint('ํ˜„์žฌ ๋ถ€์ŠคํŠธ ๊ธฐ๋Šฅ์€ 1girl, 1boy, sex ์„ธ๊ฐ€์ง€ ํ‚ค์›Œ๋“œ๊ฐ€ ์žˆ์–ด์•ผ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.')
850
+ return
851
+
852
+ if(rand_resolution_var.get() == 1):
853
+ resolutions = ["1024 x 1024", "960 x 1088", "896 x 1152", "832 x 1216", "1088 x 960", "1152 x 896", "1216 x 832"]
854
+ random_resolution = random.choice(resolutions)
855
+ selected_resolution.set(random_resolution)
856
+
857
+ if(turbo_var.get() == 1 and access_token):
858
+ button_stop.config(state='normal')
859
+ NAI_generation_turbo(NAI_width, NAI_height, button)
860
+ else:
861
+ if not (running_flag):
862
+ NAI_generation_normal(NAI_width, NAI_height, button)
863
+
864
+ def Auto_login_check():
865
+ global access_token, access_token_multi
866
+ if os.path.exists('token.txt'):
867
+ with open('token.txt', 'r', encoding='utf-8') as f:
868
+ tokens = f.readlines()
869
+ if(tokens[0]): access_token = tokens[0].strip()
870
+ if(access_token): button_setting.config(state='disabled')
871
+ if(access_token): button_generate.config(state='normal')
872
+
873
+ def NAI_generation_normal(width, height, button):
874
+ button.config(state=tk.DISABLED)
875
+ positive = text_output.get("1.0", tk.END)
876
+ negative = negative_text.get("1.0", "end-1c").strip()
877
+ thread = threading.Thread(target=generate, args=(width, height, positive, negative, button))
878
+ thread.start()
879
+
880
+ def NAI_generation_turbo(width, height, button):
881
+ global turbo_count, access_token, access_token_multi
882
+ button.config(state=tk.DISABLED)
883
+ positive = text_output.get("1.0", tk.END)
884
+ negative = negative_text.get("1.0", "end-1c").strip()
885
+
886
+
887
+ def SELECT(positive):
888
+ lines = positive[:25]
889
+ result = {
890
+ "boys": False,
891
+ "girls": False,
892
+ "1girl": False,
893
+ "1boy": False,
894
+ "1other": False,
895
+ "others": False
896
+ }
897
+ state = {
898
+ "nude,": False,
899
+ "pov,": False,
900
+ "cum,": False,
901
+ "after ": False,
902
+ "pussy juice": False,
903
+ "barefoot": False,
904
+ "breasts": False,
905
+ "ejaculation": False,
906
+ }
907
+
908
+ def insert_spaces(source_list, reference_list):
909
+ modified_list = source_list.copy()
910
+ for index, keyword in enumerate(reference_list):
911
+ if keyword not in source_list:
912
+ space_count = len(keyword) # ํ‚ค์›Œ๋“œ ๊ธธ์ด๋งŒํผ์˜ ๊ณต๋ฐฑ ๋ฌธ์ž
913
+ modified_list.insert(index, ' ' * space_count)
914
+ return modified_list
915
+
916
+ keywords = positive.split(', ')
917
+ filtered_keywords = []
918
+ removed_indices = []
919
+ positive0, positive1, positive2, positive3 = None, None, None, None
920
+
921
+ for word in result.keys():
922
+ if word in lines:
923
+ result[word] = True
924
+ for word in state.keys():
925
+ if word in positive:
926
+ state[word] = True
927
+
928
+ if(result["boys"]):
929
+ #group sex
930
+ if(result["girls"]):
931
+ pass
932
+ #gangbang
933
+ elif(result["1girl"]):
934
+ pass
935
+
936
+ key_index = int((len(keywords)/2)-1)
937
+
938
+ global bag_of_tags
939
+ eye_color = ['aqua eyes', 'black eyes', 'blue eyes', 'brown eyes', 'green eyes', 'grey eyes', 'orange eyes', 'purple eyes', 'pink eyes', 'red eyes', 'white eyes', 'yellow eyes', 'amber eyes']
940
+ hair_color = ['aqua hair', 'black hair', 'blonde hair', 'blue hair', 'light blue hair', 'dark blue hair', 'brown hair', 'light brown hair', 'green hair', 'dark green hair', 'light green hair', 'grey hair', 'orange hair', 'pink hair', 'purple hair', 'light purple hair', 'red hair', 'white hair']
941
+
942
+ if not wildcard_var2.get() and not rm_characteristic_var.get():
943
+ key_features = []
944
+ for tag in bag_of_tags:
945
+ if tag in keywords:
946
+ key_features.append(tag)
947
+ keywords.remove(tag)
948
+ if not any(color in key_features for color in eye_color): key_features.append(random.choice(eye_color))
949
+ if not any(color in key_features for color in hair_color): key_features.append(random.choice(hair_color))
950
+ key_feature = "{" +' ,'.join(key_features) + "}"
951
+ keywords.insert(2, key_feature)
952
+
953
+ if(result["1boy"]):
954
+ if(result["girls"]):
955
+ pass
956
+ elif(result["1girl"]):
957
+ if('sex,' in positive):
958
+ sex_pos_keywords = ['stomach bulge','insertion', 'fucked silly', 'x-ray', 'orgasm', 'cross-section', 'uterus', 'overflow', 'rape']
959
+ facial_keywords = ['tongue','ahegao']
960
+ temp_sex_pos = []
961
+ temp_facial = []
962
+ cum_events = []
963
+ explicit_check = []
964
+ if 'open mouth' in keywords: keywords.remove('open mouth')
965
+ if 'closed mouth' in keywords: keywords.remove('closed mouth')
966
+ if 'after rape' in keywords:
967
+ keywords.remove('after rape')
968
+ explicit_check.append('after rape')
969
+ for keyword in keywords:
970
+ if ('sex' not in keyword and 'cum' not in keyword and 'ejaculation' not in keyword and 'vaginal' not in keyword and 'penetration' not in keyword) and all(sex_pos not in keyword for sex_pos in sex_pos_keywords) and all(facial not in keyword for facial in facial_keywords):
971
+ filtered_keywords.append(keyword)
972
+ elif 'sex' in keyword:
973
+ removed_indices.append(keyword)
974
+ elif 'penetration' in keyword:
975
+ removed_indices.append(keyword)
976
+ elif 'cum' in keyword and keyword != 'cum':
977
+ cum_events.append(keyword)
978
+ elif any(sex_pos in keyword for sex_pos in sex_pos_keywords):
979
+ for sex_pos in sex_pos_keywords:
980
+ if sex_pos in keyword:
981
+ temp_sex_pos.append(sex_pos)
982
+ elif any(facial not in keyword for facial in facial_keywords):
983
+ for facial in facial_keywords:
984
+ if facial in keyword:
985
+ temp_facial.append(facial)
986
+ filtered_keywords.insert(int((len(filtered_keywords)/2)-1), ' no penetration, imminent penetration')
987
+ filtered_keywords_positive0 = filtered_keywords.copy()
988
+ filtered_keywords.remove(' no penetration, imminent penetration')
989
+ #0 imminent penetration, imminent sex
990
+ for i, keyword in enumerate(filtered_keywords):
991
+ if 'pantyhose' in keyword:
992
+ filtered_keywords[i] = 'torn ' + filtered_keywords[i]
993
+ #1 default
994
+ key_index = int((len(filtered_keywords)/2)-1)
995
+ if 'pussy' in filtered_keywords: key_index = filtered_keywords.index('pussy')
996
+ if 'penis' in filtered_keywords: key_index = filtered_keywords.index('penis')
997
+ filtered_keywords[key_index:key_index] = ['motion lines', 'surprised']
998
+ for keyword in removed_indices:
999
+ if 'cum' not in keyword and 'ejaculation' not in keyword:
1000
+ filtered_keywords.insert(key_index,keyword)
1001
+ if(temp_sex_pos): filtered_keywords[key_index:key_index] = temp_sex_pos
1002
+ if('clothed sex' in filtered_keywords and not 'bottomless' in filtered_keywords): filtered_keywords.insert(filtered_keywords.index('clothed sex')+1, 'bottomless')
1003
+ pos1_copied_keywords = filtered_keywords.copy()
1004
+ for i, keyword in enumerate(pos1_copied_keywords):
1005
+ if 'closed eyes' in keyword:
1006
+ rand_num = random.randint(0,2)
1007
+ if(rand_num == 0): pos1_copied_keywords[i] = 'half-' + pos1_copied_keywords[i]
1008
+ elif(rand_num == 1 and 'closed eyes' in pos1_copied_keywords):
1009
+ pos1_copied_keywords.remove('closed eyes')
1010
+ filtered_keywords[i] = 'half-closed eyes'
1011
+ filtered_keywords_positive1 = pos1_copied_keywords.copy()
1012
+ #2 ejaculation,cum in pussy
1013
+ key_index = filtered_keywords.index('surprised')
1014
+ filtered_keywords.remove('surprised')
1015
+ filtered_keywords[key_index:key_index] = ["ejaculation","cum"]
1016
+ for keyword in removed_indices:
1017
+ if 'cum' in keyword:
1018
+ filtered_keywords.insert(key_index,keyword)
1019
+ if(temp_facial): filtered_keywords[key_index:key_index] =temp_facial
1020
+ filtered_keywords_positive2 = filtered_keywords.copy()
1021
+ #3 after sex, after ejaculation
1022
+ for i, keyword in enumerate(filtered_keywords):
1023
+ if 'closed eyes' in keyword:
1024
+ rand_num = random.randint(0,2)
1025
+ if(rand_num == 0 and filtered_keywords[i] != 'half-closed eyes'): filtered_keywords[i] = 'half-' + filtered_keywords[i]
1026
+ elif(rand_num == 1): filtered_keywords[i] = 'empty eyes'
1027
+ else: filtered_keywords[i] = 'empty eyes, half-closed eyes'
1028
+ key_index = filtered_keywords.index('sex')
1029
+ filtered_keywords.remove('ejaculation')
1030
+ filtered_keywords[key_index:key_index] = ['cum drip', 'erection'] + cum_events
1031
+ if(explicit_check): filtered_keywords[key_index:key_index] = explicit_check
1032
+ if('pussy' in filtered_keywords and not 'anal' in filtered_keywords): filtered_keywords.insert(filtered_keywords.index('sex')+1, 'after vaginal, spread pussy')
1033
+ elif('anal' in filtered_keywords): filtered_keywords.insert(filtered_keywords.index('sex')+1, 'after anus, cum in ass')
1034
+ filtered_keywords.insert(filtered_keywords.index('sex'), 'after sex')
1035
+ filtered_keywords.remove('sex')
1036
+ positive0 = ', '.join(insert_spaces(filtered_keywords_positive0, filtered_keywords)).strip()
1037
+ print("round 1 : ",positive0)
1038
+ positive1 = ', '.join(insert_spaces(filtered_keywords_positive1, filtered_keywords)).strip()
1039
+ print("round 2 : ",positive1)
1040
+ positive2 = ', '.join(insert_spaces(filtered_keywords_positive2, filtered_keywords)).strip()
1041
+ print("round 3 : ",positive2)
1042
+ positive3 = ', '.join(filtered_keywords).strip()
1043
+ print("round 4 : ",positive3)
1044
+ elif(', penis' in positive):
1045
+ if(', oral' in positive):
1046
+ pass
1047
+ elif(', paizuri' in positive):
1048
+ pass
1049
+ elif('job,' in positive):
1050
+ if('handjob' in positive):
1051
+ pass
1052
+ elif('footjob' in positive):
1053
+ pass
1054
+
1055
+ return positive0, positive1, positive2, positive3
1056
+
1057
+ positive0, positive1, positive2, positive3 = SELECT(text_output.get("1.0", tk.END));
1058
+
1059
+ if not hold_seed_var.get(): seed = random.randint(0,9999999999)
1060
+ else: seed = last_generation_seed
1061
+
1062
+ sleep0 = random.uniform(13.5,19.5)
1063
+ sleep1 = sleep0 + random.uniform(13.5,19.5)
1064
+ sleep2 = sleep1 + random.uniform(13.5,19.5)
1065
+ sleep3 = sleep2 + random.uniform(13.5,19.5)
1066
+
1067
+ thread_init = threading.Thread(target=generate_turbo, args=(seed,turbo_count, access_token, width, height, positive, negative, button, 0, 0))
1068
+ thread_init.start()
1069
+ thread0 = threading.Thread(target=generate_turbo, args=(seed,turbo_count, access_token, width, height, positive0, negative, button, 1, sleep0))
1070
+ thread0.start()
1071
+ thread1 = threading.Thread(target=generate_turbo, args=(seed,turbo_count, access_token, width, height, positive1, negative, button, 2, sleep1))
1072
+ thread1.start()
1073
+ thread2 = threading.Thread(target=generate_turbo, args=(seed,turbo_count, access_token, width, height, positive2, negative, button, 3, sleep2))
1074
+ thread2.start()
1075
+ thread3 = threading.Thread(target=generate_turbo, args=(seed,turbo_count, access_token, width, height, positive3, negative, button, 4, sleep3))
1076
+ thread3.start()
1077
+
1078
+ turbo_count += 1
1079
+
1080
+ def generate_turbo(_seed, turbo_count, tb_access_token,width, height, positive, negative, button, pipe_number, sleeptime):
1081
+ global temp_clipboard_image
1082
+ global current_sampler
1083
+ global NAI_width, NAI_height
1084
+ global running_flag
1085
+ global image_queue
1086
+ global turbo_stop_bit
1087
+ global task_finished
1088
+
1089
+ if(pipe_number == 0): image_queue.clear()
1090
+
1091
+ try:
1092
+ scale = float(entry_CFG_value.get())
1093
+ except:
1094
+ scale = 5.0
1095
+ if scale > 7.0: scale = 7.0
1096
+ elif scale < 4.0: scale = 4.0
1097
+ else: scale = round(scale, 1)
1098
+
1099
+ try:
1100
+ scale2 = float(entry_rescale_value.get())
1101
+ except:
1102
+ scale2 = 0
1103
+ if scale2 > 1.00: scale = 1.00
1104
+ elif scale2 < 0.0: scale = 0.00
1105
+ else: scale2 = round(scale2, 2)
1106
+
1107
+ params = {
1108
+ "legacy": False,
1109
+ "quality_toggle": False,
1110
+ "width": width,
1111
+ "height": height,
1112
+ "n_samples": 1,
1113
+ "seed": _seed,
1114
+ "extra_noise_seed": random.randint(0,9999999999),
1115
+ "sampler": current_sampler,
1116
+ "steps": 28,
1117
+ "scale": scale,
1118
+ "uncond_scale": 1.0,
1119
+ "negative_prompt": negative,
1120
+ "sm" : sema_button_var.get(),
1121
+ "sm_dyn" : dyn_button_var.get(),
1122
+ "decrisper": False,
1123
+ "controlnet_strength": 1.0,
1124
+ "add_original_image": False,
1125
+ "cfg_rescale": scale2,
1126
+ "noise_schedule": "native",
1127
+ }
1128
+
1129
+ if (hold_seed_var.get()):
1130
+ global last_generation_seed
1131
+ params['seed'] = last_generation_seed
1132
+
1133
+ def merge_images(image_queue):
1134
+ if len(image_queue) < 4:
1135
+ return None # ์ด๋ฏธ์ง€๊ฐ€ 4๊ฐœ ๋ฏธ๋งŒ์ธ ๊ฒฝ์šฐ None์„ ๋ฐ˜ํ™˜
1136
+
1137
+ # ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๋ฅผ ๋™์ผํ•˜๊ฒŒ ์กฐ์ •
1138
+ # ์˜ˆ์‹œ๋ฅผ ์œ„ํ•ด ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”์— ๋”ฐ๋ผ ์ˆ˜์ • ๊ฐ€๋Šฅ
1139
+ width, height = image_queue[0].size
1140
+ new_image = Image.new('RGB', (width * 2, height * 2))
1141
+
1142
+ # ์ด๋ฏธ์ง€ ์œ„์น˜ ๋งคํ•‘
1143
+ positions = [(0, 0), (width, 0), (0, height), (width, height)]
1144
+
1145
+ # ์ด๋ฏธ์ง€ ๋ณ‘ํ•ฉ
1146
+ for i, img in enumerate(image_queue):
1147
+ pos = positions[i]
1148
+ new_image.paste(img, pos)
1149
+
1150
+ return new_image
1151
+
1152
+ def insert_queue(i, _number):
1153
+ global image_queue, temp_clipboard_image
1154
+ while len(image_queue) < 4: image_queue.append(None)
1155
+ if _number <= 4:
1156
+ image_queue[_number-1] = i.copy()
1157
+ i_resized = resize_and_fill(i)
1158
+ box_position = (i_resized.width - 25, 10)
1159
+ draw = ImageDraw.Draw(i_resized)
1160
+ draw.rectangle([box_position, (box_position[0] + 25, box_position[1] + 25)], fill="black")
1161
+ font = ImageFont.load_default()
1162
+ text_position = (box_position[0] + 12, box_position[1] + 12) # ํ…์ŠคํŠธ ์œ„์น˜ ์กฐ์ •
1163
+ draw.text(text_position, str(_number), fill="white", font=font)
1164
+ if 'tk_image' in globals():
1165
+ globals()['tk_image'] = None
1166
+ tk_image = ImageTk.PhotoImage(i_resized)
1167
+ image_label.config(image=tk_image)
1168
+ image_label.image = tk_image # ์ฐธ์กฐ ์œ ์ง€
1169
+ if all(img is not None for img in image_queue):
1170
+ time.sleep(5)
1171
+ merged_image = merge_images(image_queue)
1172
+ temp_clipboard_image = merged_image.copy()
1173
+ if merged_image is not None:
1174
+ i_resized = resize_and_fill(merged_image)
1175
+ if 'tk_image' in globals():
1176
+ globals()['tk_image'] = None
1177
+ tk_image = ImageTk.PhotoImage(i_resized)
1178
+ image_label.config(image=tk_image)
1179
+ image_label.image = tk_image # ์ฐธ์กฐ ์œ ์ง€
1180
+ output_file_path = "output_image.jpg"
1181
+ merged_image.save(output_file_path)
1182
+ image_queue = [] # ์ด๋ฏธ์ง€ ํ ์ดˆ๊ธฐํ™”
1183
+
1184
+ def resize_and_fill(image, max_size=None):
1185
+ if max_size is None:
1186
+ max_size = get_max_size()
1187
+ original_width, original_height = image.size
1188
+ if original_width > max_size or original_height > max_size:
1189
+ # ๋น„์œจ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ํฌ๊ธฐ ์กฐ์ •
1190
+ image.thumbnail((max_size, max_size))
1191
+
1192
+ # ์ƒˆ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ๊ณ„์‚ฐ
1193
+ width, height = image.size
1194
+ new_image = Image.new("RGB", (max_size, max_size), "black")
1195
+ new_image.paste(image, ((max_size - width) // 2, (max_size - height) // 2))
1196
+ return new_image
1197
+ else:
1198
+ return image
1199
+
1200
+ def log_error(e, output_file_path="output_file_path"):
1201
+ # ํ˜„์žฌ ์‹œ๊ฐ„์„ ์–ป์Šต๋‹ˆ๋‹ค
1202
+ current_time = datetime.now().strftime("%m/%d %H:%M:%S")
1203
+
1204
+ # ์—๋Ÿฌ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€
1205
+ error_message = f"#### Error occured at {current_time} ####\nError: {e}\n############################################\n"
1206
+
1207
+ # ์ง€์ •๋œ ์ถœ๋ ฅ ํด๋”์˜ error_log.txt ํŒŒ์ผ์— ์“ฐ๊ธฐ
1208
+ with open(f"error_log.txt", "a") as file:
1209
+ file.write(error_message)
1210
+
1211
+ if(pipe_number != 0):
1212
+ pipe_start_time = time.time()
1213
+ while time.time() - pipe_start_time < sleeptime:
1214
+ if(turbo_stop_bit):
1215
+ return
1216
+ time.sleep(1)
1217
+
1218
+ while running_flag:
1219
+ time.sleep(1)
1220
+ print('running_flag : ',running_flag,'pipe_number : ',pipe_number, ' : already running ')
1221
+ if(turbo_stop_bit):
1222
+ return
1223
+ print('containing : ',pipe_number)
1224
+
1225
+ running_flag = True
1226
+ tprint("Running : request received, pipeline :",pipe_number)
1227
+ try:
1228
+ zipped_bytes = generate_image(tb_access_token, positive, "nai-diffusion-3", "generate", params)
1229
+ if(pipe_number != 0):
1230
+ d = Path(f"output_NAI/{start_time}/turbo")
1231
+ d.mkdir(parents=True, exist_ok=True)
1232
+ else:
1233
+ d = Path(f"output_NAI/{start_time}/turbo/preprocessing")
1234
+ d.mkdir(parents=True, exist_ok=True)
1235
+ zipped = zipfile.ZipFile(io.BytesIO(zipped_bytes))
1236
+ image_bytes = zipped.read(zipped.infolist()[0])
1237
+ (d / f"{turbo_count:05}_{pipe_number}.png" ).write_bytes(image_bytes)
1238
+ i = Image.open(io.BytesIO(image_bytes))
1239
+ i = ImageOps.exif_transpose(i).convert("RGB")
1240
+ if(pipe_number != 0):
1241
+ if temp_clipboard_image is not None:
1242
+ temp_clipboard_image.close()
1243
+ if(pipe_number == 1 and len(image_queue) < 4): image_queue.clear()
1244
+ temp_clipboard_image = i
1245
+ insert_queue(i, pipe_number)
1246
+ tprint("image inserted, pipe number : ",pipe_number)
1247
+ else:
1248
+ if temp_clipboard_image is not None:
1249
+ temp_clipboard_image.close()
1250
+ temp_clipboard_image = i
1251
+ i_resized = resize_and_fill(i)
1252
+ if 'tk_image' in globals():
1253
+ globals()['tk_image'] = None
1254
+ tk_image = ImageTk.PhotoImage(i_resized)
1255
+ image_label.config(image=tk_image)
1256
+ image_label.image = tk_image # ์ฐธ์กฐ ์œ ์ง€
1257
+ except Exception as e:
1258
+ #text_output.insert(tk.END, f"Error: {e}", fg='red')
1259
+ log_error(e, "path_to_output_folder")
1260
+ time.sleep(random.uniform(3.0, 9.0))
1261
+ insert_queue(temp_clipboard_image, pipe_number)
1262
+
1263
+ task_finished += 1 #ํ„ฐ๋ณด ๊ธฐ๋Šฅ์˜ ์•ˆ์ „์žฅ์น˜์ž…๋‹ˆ๋‹ค.
1264
+
1265
+ time.sleep(random.uniform(3.0, 5.5))
1266
+ if(pipe_number == 4): button.config(state=tk.NORMAL)
1267
+ running_flag = False
1268
+
1269
+ last_generation_seed = params['seed']
1270
+ entry_seed_value.set(last_generation_seed)
1271
+
1272
+ stopped = False
1273
+ if (turbo_stop_bit):
1274
+ time.sleep(1.5)
1275
+ turbo_stop_bit = False
1276
+ button.config(state=tk.NORMAL)
1277
+ stopped = True
1278
+ if (pipe_number != 4):
1279
+ tprint("Stopped : request stopped before assign pipeline :",pipe_number+1)
1280
+
1281
+ if pipe_number == 4 and mac_var.get():
1282
+ wait_limit = 0
1283
+ while(task_finished < 5 and wait_limit < 20):
1284
+ wait_limit += 1
1285
+ print(f"Wait other pipeline ... : ({wait_limit}/20)")
1286
+ time.sleep(3)
1287
+ if(wait_limit == 20):
1288
+ print(f"Process : {turbo_count} request time-out")
1289
+ task_finished = 0
1290
+ else:
1291
+ task_finished = 0
1292
+ running_flag = False
1293
+ random_function()
1294
+ time.sleep(random.uniform(2.1, 5.5))
1295
+ if not (turbo_stop_bit):
1296
+ button.config(state=tk.DISABLED)
1297
+ window.event_generate(GENERATE_EVENT, when="tail")
1298
+ else:
1299
+ turbo_stop_bit = False
1300
+ if(mac_var.get() and not running_flag):
1301
+ button.config(state=tk.DISABLED)
1302
+ window.event_generate(GENERATE_EVENT, when="tail")
1303
+ else:
1304
+ if(pipe_number == 4):
1305
+ global button_stop
1306
+ button_stop.config(state='disabled')
1307
+ tprint('state : idle')
1308
+
1309
+ def NAI_setting(button, button_generate):
1310
+ global NAI_ID
1311
+ NAI_setting_window = tk.Toplevel(window)
1312
+ NAI_setting_window_title = "NAI ๋กœ๊ทธ์ธ"
1313
+
1314
+ def NAI_close():
1315
+ NAI_setting_window.destroy()
1316
+
1317
+ def NAI_token_save(button):
1318
+ global access_token
1319
+ with open('token.txt', 'w', encoding='utf-8') as f:
1320
+ f.write(access_token)
1321
+ NAI_State_label.config(text="(ํ”„๋กœ๊ทธ๋žจ ๊ฒฝ๋กœ์— token.txt๊ฐ€ ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.)", fg="blue")
1322
+ button.config(state=tk.DISABLED)
1323
+
1324
+ def NAI_connect(button, connect_button, token_button):
1325
+ global access_token, NAI_ID
1326
+ username = entry_NAI_ID.get().strip()
1327
+ password = entry_NAI_PW.get().strip()
1328
+ access_key = get_access_key(username, password)
1329
+ try:
1330
+ access_token = login(access_key)
1331
+ access_result = requests.get("https://api.novelai.net/user/information", headers={ "Authorization": f"Bearer {access_token}" })
1332
+ NAI_State_label.config(text="(๋กœ๊ทธ์ธ ์„ฑ๊ณต, ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”.)", fg="blue")
1333
+ button.config(state=tk.DISABLED)
1334
+ button_generate.config(state="normal")
1335
+ connect_button.config(state=tk.DISABLED)
1336
+ NAI_ID = username
1337
+ token_button.config(state=tk.NORMAL)
1338
+ except Exception as e:
1339
+ print(e)
1340
+ NAI_close()
1341
+
1342
+ button_frame0 = tk.Frame(NAI_setting_window)
1343
+ button_frame0.grid(row=0, padx=5, pady=5, sticky='ew')
1344
+ button_frame1 = tk.Frame(button_frame0)
1345
+ button_frame1.grid(row=0, padx=5, pady=5, sticky='ew')
1346
+ button_frame1.columnconfigure(0, weight=1)
1347
+ button_frame1.columnconfigure(1, weight=3)
1348
+ button_frame1.columnconfigure(2, weight=3)
1349
+ button_frame1.columnconfigure(3, weight=1)
1350
+ NAI_ID_label = tk.Label(button_frame1, text="NAI ID: ")
1351
+ NAI_ID_label.grid(row=0, column=0, sticky='ew')
1352
+ entry_NAI_ID = tk.Entry(button_frame1)
1353
+ entry_NAI_ID.grid(row=0, column=1, columnspan=3, padx=5, pady=5, sticky='ew')
1354
+ if(NAI_ID): entry_NAI_ID.insert(tk.END,NAI_ID)
1355
+ NAI_PW_label = tk.Label(button_frame1, text="NAI PW: ")
1356
+ NAI_PW_label.grid(row=1, column=0,sticky='ew')
1357
+ entry_NAI_PW = tk.Entry(button_frame1, show="*")
1358
+ entry_NAI_PW.grid(row=1, column=1, columnspan=3,padx=5, pady=5, sticky='ew')
1359
+ token_output = tk.Button(button_frame0, text="๋กœ๊ทธ์ธ ์ •๋ณด ๊ธฐ์–ตํ•˜๊ธฐ", command=lambda: NAI_token_save(token_output))
1360
+ token_output.grid(row=2, column=1, padx=5, pady=5, sticky='ew')
1361
+ connect_button = tk.Button(button_frame0, text="์—ฐ๊ฒฐ", command=lambda: NAI_connect(button, connect_button, token_output))
1362
+ connect_button.grid(row=2, column=0, padx=5, pady=5, sticky='ew')
1363
+ close_button = tk.Button(button_frame0, text="๋‹ซ๊ธฐ", command=NAI_close)
1364
+ close_button.grid(row=2, column=2, padx=5, pady=5, sticky='ew')
1365
+ NAI_State_label = tk.Label(button_frame0, text="ํ•ด๋‹น ์ ‘์†๊ธฐ๋Šฅ์€ ์ •์ƒ์ ์ธ ์ ‘์† ํŒจํ„ด์ด ์•„๋‹Œ์  ์ฐธ๊ณ  ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.", fg="red")
1366
+ NAI_State_label.grid(row=3, column=0, sticky='ew')
1367
+
1368
+ def NAI_setting_multi(button):
1369
+ global NAI_ID_multi
1370
+ NAI_setting_window_multi = tk.Toplevel(window)
1371
+ NAI_setting_window_title = "NAI ๋กœ๊ทธ์ธ"
1372
+
1373
+ def NAI_close():
1374
+ NAI_setting_window_multi.destroy()
1375
+
1376
+ NAI_ID_label = tk.Label(NAI_setting_window_multi, text="NAI ID: ")
1377
+ NAI_ID_label.grid(row=0, column=0, columnspan=2, sticky='w')
1378
+ entry_NAI_ID = tk.Entry(NAI_setting_window_multi, width=50)
1379
+ entry_NAI_ID.grid(row=0, column=1, columnspan=2, padx=100, pady=5, sticky='e')
1380
+ if(NAI_ID_multi): entry_NAI_ID.insert(tk.END,NAI_ID_multi)
1381
+ NAI_PW_label = tk.Label(NAI_setting_window_multi, text="NAI PW: ")
1382
+ NAI_PW_label.grid(row=1, column=0, columnspan=2, sticky='w')
1383
+ entry_NAI_PW = tk.Entry(NAI_setting_window_multi, width=50, show="*")
1384
+ entry_NAI_PW.grid(row=1, column=1, columnspan=2, padx=100, pady=5, sticky='e')
1385
+
1386
+ def NAI_connect(button, connect_button):
1387
+ global access_token_multi, NAI_ID, NAI_ID_multi
1388
+ username = entry_NAI_ID.get().strip()
1389
+ password = entry_NAI_PW.get().strip()
1390
+ access_key = get_access_key(username, password)
1391
+ try:
1392
+ access_token_multi = login(access_key)
1393
+ access_result = requests.get("https://api.novelai.net/user/information", headers={ "Authorization": f"Bearer {access_token}" })
1394
+
1395
+ if NAI_ID == NAI_ID_multi: NAI_State_label.config(text="(๊ฐ™์€ ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธ ํ•˜์…จ์Šต๋‹ˆ๋‹ค.)", fg="red")
1396
+ else: NAI_State_label.config(text="(๋กœ๊ทธ์ธ ์„ฑ๊ณต, ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”.)", fg="blue")
1397
+ button.config(state=tk.DISABLED)
1398
+ connect_button.config(state=tk.DISABLED)
1399
+ NAI_ID_multi = username
1400
+ except Exception as e:
1401
+ print(e)
1402
+ NAI_close()
1403
+
1404
+ connect_button = tk.Button(NAI_setting_window_multi, text="์—ฐ๊ฒฐ", command=lambda: NAI_connect(button, connect_button))
1405
+ connect_button.grid(row=2, column=1, columnspan=2, padx=5, pady=5, sticky='w')
1406
+ close_button = tk.Button(NAI_setting_window_multi, text="๋‹ซ๊ธฐ", command=NAI_close)
1407
+ close_button.grid(row=2, column=2, columnspan=2, padx=5, pady=5, sticky='w')
1408
+ NAI_State_label = tk.Label(NAI_setting_window_multi, text="ํ•ด๋‹น ๊ธฐ๋Šฅ์€ NAI Opus ๊ตฌ๋… ๊ณ„์ • 2๊ฐœ๊ฐ€ ์š”๊ตฌ๋ฉ๋‹ˆ๋‹ค..", fg="red")
1409
+ NAI_State_label.grid(row=3, column=1, sticky='ew')
1410
+
1411
+ def on_resolution_change(*args):
1412
+ global NAI_width, NAI_height
1413
+ resolution = selected_resolution.get()
1414
+ NAI_width, NAI_height = resolution.split(' x ')
1415
+
1416
+ def on_option_select(value):
1417
+ global current_sampler
1418
+ current_sampler = value
1419
+
1420
+ def open_file_explorer():
1421
+ output_file_path = "output_NAI"
1422
+ if os.path.exists(output_file_path):
1423
+ os.startfile(output_file_path)
1424
+
1425
+ def on_generate_event(event):
1426
+ global running_flag
1427
+ if not (running_flag):
1428
+ NAI_generation(NAI_width, NAI_height, button_generate)
1429
+
1430
+ def random_artist_management():
1431
+ global top_100_keywords, top_100_counts, cached_rows
1432
+ if not cached_rows: return
1433
+ if not (top_100_keywords):
1434
+ if not os.path.exists("counting_result.txt"):
1435
+ keyword_counts = analyze_cached_rows(cached_rows)
1436
+ excluded_keywords = set(whitelist[:2974])
1437
+ with open("counting_result.txt", "w") as file:
1438
+ for keyword, count in sorted(keyword_counts.items(), key=lambda item: item[1], reverse=True):
1439
+ if keyword not in excluded_keywords and keyword in afilter_30000:
1440
+ file.write(f"{keyword}: {count}\n")
1441
+ with open("counting_result.txt", "r") as file:
1442
+ lines = file.readlines()
1443
+ top_100_data = [
1444
+ (line.split(":")[0].strip(), int(line.split(":")[1].strip()))
1445
+ for line in lines[:3000]
1446
+ if line.split(":")[0].strip() in afilter_30000[:8528]
1447
+ ]
1448
+ top_100_keywords, top_100_counts = zip(*top_100_data) if top_100_data else ([], [])
1449
+ elif (not top_100_keywords):
1450
+ with open("counting_result.txt", "r") as file:
1451
+ lines = file.readlines()
1452
+ top_100_data = [
1453
+ (line.split(":")[0].strip(), int(line.split(":")[1].strip()))
1454
+ for line in lines[:3000]
1455
+ if line.split(":")[0].strip() in afilter_30000[:8528]
1456
+ ]
1457
+ top_100_keywords, top_100_counts = zip(*top_100_data) if top_100_data else ([], [])
1458
+
1459
+ # top_100_keywords ๋‚ด์˜
1460
+ # ๏ฟฝ๏ฟฝ๏ฟฝ ์ฐฝ ์ƒ์„ฑ
1461
+ random_artist_window = tk.Toplevel(window)
1462
+
1463
+ # ์ฒซ ๋ฒˆ์งธ Text Output Box ์„ค์ •
1464
+ text_output1 = tk.Text(random_artist_window, height=40, width=50)
1465
+ text_output1.pack(padx=10, pady=10)
1466
+ for keyword, count in zip(top_100_keywords, top_100_counts):
1467
+ text_output1.insert(tk.END, f"{keyword}: {count}\n")
1468
+
1469
+ def update_lists():
1470
+ # Text ์œ„์ ฏ์—์„œ ๋‚ด์šฉ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
1471
+ content = text_output1.get("1.0", tk.END)
1472
+ lines = content.strip().split("\n") # ์ค„๋ฐ”๊ฟˆ์œผ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
1473
+
1474
+ # ๊ฐฑ์‹ ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๋‘ ๊ฐœ์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
1475
+ updated_keywords = []
1476
+ updated_counts = []
1477
+
1478
+ # ๊ฐ ์ค„์„ ์ฒ˜๋ฆฌํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
1479
+ for line in lines:
1480
+ if line: # ๋นˆ ์ค„์ด ์•„๋‹Œ ๊ฒฝ์šฐ์—๋งŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
1481
+ parts = line.split(":")
1482
+ if len(parts) == 2: # "ํ‚ค์›Œ๋“œ: ์นด์šดํŠธ" ํ˜•์‹์ด ๋งž๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
1483
+ updated_keywords.append(parts[0].strip())
1484
+ updated_counts.append(int(parts[1].strip()))
1485
+
1486
+ # ์ „์—ญ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
1487
+ global top_100_keywords, top_100_counts
1488
+ top_100_keywords = updated_keywords
1489
+ top_100_counts = updated_counts
1490
+ with open("random_artist_keywords_"+str(len(top_100_keywords))+".txt", "w") as f:
1491
+ for keyword in updated_keywords:
1492
+ f.write('100: artist:'+keyword + "\n")
1493
+
1494
+ # ๋ฒ„ํŠผ๋“ค์„ ๋‹ด์„ ํ”„๋ ˆ์ž„ ์ƒ์„ฑ
1495
+ buttons_frame = tk.Frame(random_artist_window)
1496
+ buttons_frame.pack(pady=10)
1497
+
1498
+ # '์ €์žฅ' ๋ฒ„ํŠผ์„ ํ”„๋ ˆ์ž„์˜ ์™ผ์ชฝ์— ๋ฐฐ์น˜
1499
+ save_button = tk.Button(buttons_frame, text="์ €์žฅ", command=update_lists)
1500
+ save_button.pack(side=tk.LEFT, padx=5)
1501
+
1502
+ # '๋‹ซ๊ธฐ' ๋ฒ„ํŠผ์„ ํ”„๋ ˆ์ž„์˜ ์˜ค๋ฅธ์ชฝ์— ๋ฐฐ์น˜
1503
+ close_button = tk.Button(buttons_frame, text="๋‹ซ๊ธฐ", command=random_artist_window.destroy)
1504
+ close_button.pack(side=tk.RIGHT, padx=5)
1505
+
1506
+ random_artist_label = tk.Label(random_artist_window, text='์ž‘๊ฐ€์ด๋ฆ„ ์ด '+str(len(top_100_keywords))+'๊ฐœ, ์ €์žฅ์œ„์น˜: exeํŒŒ์ผ ์œ„์น˜')
1507
+ random_artist_label.pack()
1508
+
1509
+ def open_wildcard_setting():
1510
+ global artist_wildcard_saved, character_wildcard_saved
1511
+ # ์ƒˆ ์ฐฝ ์ƒ์„ฑ
1512
+ wildcard_window = tk.Toplevel(window)
1513
+ wildcard_window.title("์™€์ผ๋“œ ์นด๋“œ ์„ค์ •")
1514
+
1515
+ # ์ž‘๊ฐ€๋ช… ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
1516
+ artist_label = tk.Label(wildcard_window, text="์ž‘๊ฐ€๋ช… ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ->")
1517
+ artist_label.grid(row=0, column=0)
1518
+ artist_button = tk.Button(wildcard_window, text="์—ด๊ธฐ", command=lambda: load_wildcard(artist_text, wildcard_window, 'artist'))
1519
+ artist_button.grid(row=0, column=1)
1520
+
1521
+ artist_text = tk.Text(wildcard_window, height=15, width=60)
1522
+ artist_text.grid(row=1, column=0, columnspan=2)
1523
+ if artist_wildcard_saved:
1524
+ artist_text_content = '\n'.join(artist_wildcard_saved)
1525
+ artist_text.insert('1.0', artist_text_content)
1526
+
1527
+ # ์บ๋ฆญํ„ฐ ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
1528
+ character_label = tk.Label(wildcard_window, text="์บ๋ฆญํ„ฐ ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ->")
1529
+ character_label.grid(row=2, column=0)
1530
+ character_button = tk.Button(wildcard_window, text="์—ด๊ธฐ", command=lambda: load_wildcard(character_text, wildcard_window, 'character'))
1531
+ character_button.grid(row=2, column=1)
1532
+
1533
+ character_text = tk.Text(wildcard_window, height=15, width=60)
1534
+ character_text.grid(row=3, column=0, columnspan=2)
1535
+ if character_wildcard_saved:
1536
+ character_text_content = '\n'.join(character_wildcard_saved)
1537
+ character_text.insert('1.0', character_text_content)
1538
+
1539
+ # ๋ฒ„ํŠผ๋“ค
1540
+ buttons_frame = tk.Frame(wildcard_window)
1541
+ buttons_frame.grid(row=4, column=0, columnspan=2)
1542
+
1543
+ text_label = tk.Label(wildcard_window, text="wildcard ๋ฌธ๋ฒ•(์ž‘๊ฐ€):\noffset:wildcard1 150:null (helloworld)\noffset:wildcard2 100:none (goodbye)\n์—†์œผ๋ฉด 100: ์œผ๋กœ ๊ฐ„์ฃผ\noffset/offset ์ดํ•ฉ: wildcard ํ™•๋ฅ ")
1544
+ text_label.grid(row=5, column=0,sticky='ew')
1545
+ text_label2 = tk.Label(wildcard_window, text="wildcard ๋ฌธ๋ฒ•(์บ๋ฆญ):\n200:{{arona (blue archive)}}, blue hair, blue eyes, hair over one eye, ...\n150:{{nahida (genshin impact)}}, green eyes, pointy ears, ...\n...")
1546
+ text_label2.grid(row=6, column=0,sticky='ew')
1547
+
1548
+ load_button = tk.Button(buttons_frame, text="์™€์ผ๋“œ์นด๋“œ ํƒ‘์žฌ", command=lambda: apply_wildcard(artist_text, character_text, wildcard_window))
1549
+ load_button.pack(side=tk.LEFT, padx=10)
1550
+
1551
+ close_button = tk.Button(buttons_frame, text="๋‹ซ๊ธฐ", command=wildcard_window.destroy)
1552
+ close_button.pack(side=tk.RIGHT, padx=10)
1553
+
1554
+ def apply_wildcard(artist_text, character_text, window):
1555
+ global artist_wildcard_saved
1556
+ artist_wildcard_check = artist_text.get("1.0", tk.END)
1557
+ if len(artist_wildcard_check) > 5:
1558
+ lines = artist_wildcard_check.strip().split("\n")
1559
+ artist_wildcard_saved = lines.copy()
1560
+ akeywords = []
1561
+ current_index = 0
1562
+ for line in lines:
1563
+ parts = line.strip().split(':', 1)
1564
+ if len(parts) == 2 and parts[0].strip().isdigit():
1565
+ weight = int(parts[0].strip())
1566
+ else:
1567
+ weight = 100
1568
+ parts = ['100', line.strip()] # '100:'์„ ์•ž์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
1569
+ keyword = parts[1].strip()
1570
+ akeywords.append((current_index, current_index + weight - 1, keyword))
1571
+ current_index += weight
1572
+ global artist_wildcard
1573
+ artist_wildcard = akeywords
1574
+ check_wildcard.config(state='normal')
1575
+
1576
+ character_wildcard_check = character_text.get("1.0", tk.END)
1577
+ global character_wildcard_saved
1578
+ if len(character_wildcard_check) > 5:
1579
+ lines = character_wildcard_check.strip().split("\n")
1580
+ character_wildcard_saved = lines.copy()
1581
+ ckeywords = []
1582
+ current_index = 0
1583
+ for line in lines:
1584
+ parts = line.strip().split(':', 1)
1585
+ if len(parts) == 2 and parts[0].strip().isdigit():
1586
+ weight = int(parts[0].strip())
1587
+ else:
1588
+ weight = 100
1589
+ parts = ['100', line.strip()] # '100:'์„ ์•ž์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
1590
+ keyword = parts[1].strip()
1591
+ ckeywords.append((current_index, current_index + weight - 1, keyword))
1592
+ current_index += weight
1593
+ global character_wildcard
1594
+ character_wildcard = ckeywords
1595
+ check_wildcard2.config(state='normal')
1596
+
1597
+ window.destroy()
1598
+
1599
+
1600
+ def load_wildcard(text_widget, window, _type):
1601
+ global artist_wildcard_saved, character_wildcard_saved
1602
+ window.iconify()
1603
+ filepath = filedialog.askopenfilename(filetypes=[("ํ…์ŠคํŠธ ํŒŒ์ผ", "*.txt")])
1604
+ if filepath:
1605
+ with open(filepath, 'r', encoding='utf-8') as file:
1606
+ lines = file.readlines()
1607
+ updated_lines = []
1608
+ for line in lines:
1609
+ line = line.strip()
1610
+ if ':' in line:
1611
+ prefix, _ = line.split(':', 1)
1612
+ if not prefix.strip().isdigit():
1613
+ line = f"100: {line}"
1614
+ else:
1615
+ line = f"100: {line}"
1616
+ updated_lines.append(line)
1617
+
1618
+ text_widget.delete('1.0', tk.END)
1619
+ text_widget.insert('1.0', '\n'.join(updated_lines))
1620
+
1621
+ if(_type == 'artist'):
1622
+ artist_wildcard_saved = updated_lines.copy()
1623
+ elif(_type == 'character'):
1624
+ character_wildcard_saved = updated_lines.copy()
1625
+
1626
+ window.deiconify()
1627
+
1628
+ def find_keyword(index, keywords):
1629
+ for start, end, keyword in keywords:
1630
+ if start <= index <= end:
1631
+ return keyword
1632
+ return None
1633
+
1634
+ def get_random_keyword(req_keyword):
1635
+ #called from artist_wildcard, character_wildcard
1636
+ global artist_wildcard, character_wildcard
1637
+ if(req_keyword == 'artist'): keywords = artist_wildcard
1638
+ elif(req_keyword == 'character'): keywords = character_wildcard
1639
+ print('lenghth = ',len(keywords))
1640
+ max_index = keywords[-1][1]
1641
+ random_index = random.randint(0, max_index)
1642
+ return find_keyword(random_index, keywords)
1643
+
1644
+ def tprint(*args):
1645
+ ctext = ""
1646
+ for t in args:
1647
+ ctext += str(t)
1648
+ running_state.config(text=ctext)
1649
+
1650
+ start_time = datetime.now().strftime('%Y%m%d_%H%M')
1651
+ thread_controller = False
1652
+ turbo_count = 0
1653
+ on_press_flag = False
1654
+ window = tk.Tk()
1655
+ window.title("Prompt Selector for Danbooru tags")
1656
+ last_deep_search_keywords = None
1657
+ cached_rows = []
1658
+ total_rows = 0
1659
+ last_selected_row_keywords = ['1girl','nahida (genshin impact)', 'looking at viewer', 'garden']
1660
+ top_100_keywords = []
1661
+ top_100_counts = []
1662
+ previous_artist = None
1663
+ listener = None
1664
+ current_keys = set()
1665
+ click_count = 0
1666
+ access_token = None
1667
+ temp_clipboard_image = None
1668
+ NAI_width = 1024
1669
+ NAI_height = 1024
1670
+ current_sampler = "k_euler_ancestral"
1671
+ running_flag = False
1672
+ NAI_ID = None
1673
+ artist_wildcard = []
1674
+ character_wildcard_saved = []
1675
+ artist_wildcard_saved = []
1676
+ character_wildcard =[]
1677
+ access_token_multi = None
1678
+ NAI_ID_multi = None
1679
+ image_queue = []
1680
+ last_generation_seed = random.randint(0,9999999999)
1681
+ turbo_stop_bit = False
1682
+ task_finished = 0
1683
+
1684
+ whitelist = wlist.whitelist
1685
+ bag_of_tags = tagbag.bag_of_tags
1686
+ afilter_30000 = arti_list.afilter_30000
1687
+
1688
+ current_wildcard_artist = []
1689
+ current_wildcard_character = []
1690
+
1691
+ GENERATE_EVENT = "<<GenerateEvent>>"
1692
+ window.bind(GENERATE_EVENT, on_generate_event)
1693
+
1694
+ left_frame = tk.Frame(window)
1695
+ left_frame.grid(row=0, column=0, sticky="nsew")
1696
+ #left_frame.grid_columnconfigure(0, weight=1)
1697
+ right_frame = tk.Frame(window)
1698
+ right_frame.grid(row=0, column=1, sticky="nsew")
1699
+ window.grid_columnconfigure(0, weight=1)
1700
+ window.grid_columnconfigure(1, weight=1)
1701
+
1702
+ #ํŒŒ์ผ ๊ฒฝ๋กœ ๋ฐ ํ‚ค์›Œ๋“œ ์ž…๋ ฅ์ฐฝ ๊ทธ๋ฆฌ๋“œ ๊ด€๋ฆฌ
1703
+ frame_row0 = tk.Frame(left_frame)
1704
+ frame_row0.grid(row=0, column=0, padx=5, pady=5, sticky='w')
1705
+
1706
+ # ํŒŒ์ผ ๊ฒฝ๋กœ ์ž…๋ ฅ์ฐฝ
1707
+ label_file_path = tk.Label(frame_row0, text="CSV ํŒŒ์ผ ๊ฒฝ๋กœ:")
1708
+ label_file_path.grid(row=0, column=0, sticky='w')
1709
+ entry_file_path = tk.Entry(frame_row0, width=55)
1710
+ entry_file_path.grid(row=0, column=1, columnspan=4, padx=5, pady=5, sticky='ew')
1711
+ button_open_file = tk.Button(frame_row0, text="ํŒŒ์ผ ์—ด๊ธฐ", command=open_file)
1712
+ button_open_file.grid(row=0, column=5, padx=5, pady=6, sticky='e')
1713
+
1714
+ # ํ‚ค์›Œ๋“œ ์ž…๋ ฅ์ฐฝ
1715
+ keyword_label = tk.Label(frame_row0, text="์ดˆ๊ธฐํ™” ํ‚ค์›Œ๋“œ: ")
1716
+ keyword_label.grid(row=1, column=0, sticky='w')
1717
+ entry_keyword = tk.Entry(frame_row0)
1718
+ entry_keyword.grid(row=1, column=1, columnspan=4, padx=5, pady=5, sticky='ew')
1719
+ button_export_csv = tk.Button(frame_row0, text=".csv ๋‚ด๋ณด๋‚ด๊ธฐ", command=export_csv)
1720
+ button_export_csv.grid(row=1, column=5, padx=5, pady=6, sticky='e')
1721
+
1722
+ # ๋ฒ„ํŠผ ํ”„๋ ˆ์ž„
1723
+ frame_buttons = tk.Frame(left_frame)
1724
+ frame_buttons.grid(row=1, column=0, sticky='ew')
1725
+ frame_buttons.columnconfigure(0, weight=1) # ์™ผ์ชฝ์— ๊ฐ€์ค‘์น˜ ๋ถ€์—ฌ
1726
+ frame_buttons.columnconfigure(1, weight=0) # ๋ฒ„ํŠผ ์—ด์€ ๊ฐ€์ค‘์น˜ ์—†์Œ
1727
+ frame_buttons.columnconfigure(2, weight=0) # ๋ฒ„ํŠผ ์—ด์€ ๊ฐ€์ค‘์น˜ ์—†์Œ
1728
+ frame_buttons.columnconfigure(3, weight=1) # ์˜ค๋ฅธ์ชฝ์— ๊ฐ€์ค‘์น˜ ๋ถ€์—ฌ
1729
+
1730
+ # ๋ฒ„ํŠผ๋“ค
1731
+ button_search = tk.Button(frame_buttons, text="ํ•ด๋‹น ํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰", command=search)
1732
+ button_search.grid(row=0, column=1, padx=5, sticky='ew') # ๋ณ€๊ฒฝ: column=1
1733
+ button_exclude = tk.Button(frame_buttons, text="ํ•ด๋‹น ํ‚ค์›Œ๋“œ ์ œ์™ธ", command=exclude)
1734
+ button_exclude.grid(row=0, column=2, padx=5, sticky='ew') # ๋ณ€๊ฒฝ: column=2
1735
+
1736
+ total_rows_count_label = tk.Label(frame_buttons, text=".csv ๋‚ด ํ”„๋กฌํ”„ํŠธ ํ–‰: 0")
1737
+ total_rows_count_label.grid(row=0, column=3, padx=5, sticky='ew')
1738
+
1739
+ # ์‹ฌ์ธต๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ ์ž…๋ ฅ์ฐฝ
1740
+ deep_search_frame = tk.Frame(left_frame)
1741
+ deep_search_frame.grid(row=2, column=0, pady=10, sticky='w')
1742
+ deep_search_frame.columnconfigure(0, weight=2)
1743
+ deep_search_frame.columnconfigure(1, weight=2)
1744
+ deep_search_frame.columnconfigure(2, weight=1)
1745
+
1746
+ label_deep_search = tk.Label(deep_search_frame, text="์‹ฌ์ธต๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ ์ž…๋ ฅ: key,*key,~key,{key1|key2} ")
1747
+ label_deep_search.grid(row=0, column=0, sticky='w')
1748
+
1749
+ # Tkinter UI ์„ค์ • ๋ถ€๋ถ„์— ๋ ˆ์ด๋ธ” ์ถ”๊ฐ€
1750
+ cached_rows_count_label = tk.Label(deep_search_frame, text="์‹ฌ์ธต๊ฒ€์ƒ‰ ํ”„๋กฌํ”„ํŠธ ํ–‰: 0")
1751
+ cached_rows_count_label.grid(row=0, column=1, padx=5, sticky='w')
1752
+
1753
+ button_export_deep_csv = tk.Button(deep_search_frame, text=".csv ๋‚ด๋ณด๋‚ด๊ธฐ", command=export_csv_search)
1754
+ button_export_deep_csv.grid(row=0, column=2, padx=5, sticky='e')
1755
+
1756
+ entry_deep_search = tk.Entry(deep_search_frame, width=82)
1757
+ entry_deep_search.grid(row=1, column=0, columnspan=3,padx=5, pady=5, sticky='ew')
1758
+
1759
+ # ๋ฒ„ํŠผ๋“ค์„ ํฌํ•จํ•  ํ”„๋ ˆ์ž„ ์ƒ์„ฑ
1760
+ button_frame = tk.Frame(left_frame)
1761
+ button_frame.grid(row=5, column=0, padx=5, sticky='w')
1762
+
1763
+ # ๋ฒ„ํŠผ ํ”„๋ ˆ์ž„ ๋‚ด์˜ ์—ด ์„ค์ •
1764
+ button_frame.columnconfigure(0, weight=1)
1765
+ button_frame.columnconfigure(1, weight=1)
1766
+ button_frame.columnconfigure(2, weight=1)
1767
+ button_frame.columnconfigure(3, weight=1)
1768
+ button_frame.columnconfigure(4, weight=1)
1769
+ button_frame.columnconfigure(5, weight=1)
1770
+ button_frame.columnconfigure(6, weight=1)
1771
+
1772
+ # "๋žœ๋ค" ๋ฒ„ํŠผ
1773
+ button_random = tk.Button(button_frame, text="๋žœ๋ค", command=random_function)
1774
+ button_random.grid(row=0, column=0, sticky='ew')
1775
+
1776
+ # "ํ”„๋กฌํ”„ํŠธ ๊ณ ์ •" ํ† ๊ธ€ ๋ฒ„ํŠผ
1777
+ toggle_prompt_var = tk.IntVar()
1778
+ button_toggle_prompt = tk.Checkbutton(button_frame, text="ํ”„๋กฌํ”„ํŠธ ๊ณ ์ •", variable=toggle_prompt_var)
1779
+ button_toggle_prompt.grid(row=0, column=1, sticky='ew')
1780
+
1781
+ # "์ž๋™ ๋ณต์‚ฌ" ์ฒดํฌ๋ฐ•์Šค
1782
+ auto_copy_var = tk.IntVar()
1783
+ check_auto_copy = tk.Checkbutton(button_frame, text="์ž๋™ ๋ณต์‚ฌ", variable=auto_copy_var)
1784
+ check_auto_copy.grid(row=0, column=2, sticky='ew')
1785
+
1786
+ # "์ข…๋ฃŒ" ๋ฒ„ํŠผ
1787
+ button_exit = tk.Button(button_frame, text="์ข…๋ฃŒ", command=exit_program)
1788
+ button_exit.grid(row=0, column=3, sticky='ew')
1789
+
1790
+ # "์ƒ์„ฑ" ๋ฒ„ํŠผ
1791
+ button_generate = tk.Button(button_frame, text="NAI ์š”์ฒญ", command=lambda: NAI_generation(NAI_width, NAI_height, button_generate))
1792
+ button_generate.grid(row=0, column=4, sticky='ew')
1793
+ button_generate.config(state='disabled')
1794
+
1795
+ # "์ค‘๋‹จ"๋ฒ„ํŠผ
1796
+ button_stop = tk.Button(button_frame, text="์ค‘๋‹จ",command=lambda: turbo_stop(button_stop))
1797
+ button_stop.grid(row=0, column=5, sticky='ew')
1798
+ button_stop.config(state='disabled')
1799
+
1800
+ # "์„ค์ •" ๋ฒ„ํŠผ
1801
+ button_setting = tk.Button(button_frame, text="NAI ๋กœ๊ทธ์ธ ์„ค์ •", command=lambda: NAI_setting(button_setting, button_generate))
1802
+ button_setting.grid(row=0, column=6, sticky='ew')
1803
+
1804
+ # "ํ„ฐ๋ณด" ๋ฒ„ํŠผ
1805
+ #button_turbo = tk.Button(button_frame, text="ํ„ฐ๋ณด", command=lambda: NAI_setting_multi(button_turbo))
1806
+ #button_turbo.grid(row=0, column=7, sticky='ew')
1807
+
1808
+ # '์ž๋™ํ™”'์™€ 'ํ„ฐ๋ณดon'์„ ํฌํ•จํ•  ์„œ๋ธŒ ํ”„๋ ˆ์ž„ ์ƒ์„ฑ
1809
+ sub_frame = tk.Frame(button_frame)
1810
+ sub_frame.grid(row=0, column=8, sticky='ns') # ์„œ๋ธŒ ํ”„๋ ˆ์ž„์„ ์—ด 8์— ๋ฐฐ์น˜
1811
+
1812
+ # '์ž๋™ํ™”' ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„œ๋ธŒ ํ”„๋ ˆ์ž„์— ๋ฐฐ์น˜
1813
+ mac_var = tk.IntVar()
1814
+ mac_button = tk.Checkbutton(sub_frame, text="์ž๋™ํ™”", variable=mac_var)
1815
+ mac_button.grid(row=0, column=0, sticky='ew') # ์ฒซ ๋ฒˆ์งธ ํ–‰์— ๋ฐฐ์น˜
1816
+
1817
+ # 'ํ„ฐ๋ณดon' ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„œ๋ธŒ ํ”„๋ ˆ์ž„์— ๋ฐฐ์น˜
1818
+ turbo_var = tk.IntVar()
1819
+ turbo_button = tk.Checkbutton(sub_frame, text="ํ„ฐ๋ณดon", variable=turbo_var)
1820
+ turbo_button.grid(row=1, column=0, sticky='ew') # ๋‘ ๋ฒˆ์งธ ํ–‰์— ๋ฐฐ์น˜
1821
+
1822
+ # ํ…์ŠคํŠธ ๋ฐ ๊ณ ์ • ํ”„๋กฌํ”„ํŠธ ๋„ค๊ฑฐํ‹ฐ๋ธŒ ๋“ฑ ํ”„๋กฌํ”„ํŠธ ์ฐฝ
1823
+ text_frame = tk.Frame(left_frame)
1824
+ text_frame.grid(row=6, column=0, padx=5, pady=5, sticky='w')
1825
+ text_frame.columnconfigure(0, weight=1)
1826
+ text_frame.columnconfigure(1, weight=7)
1827
+
1828
+ text_frame2 = tk.Frame(left_frame)
1829
+ text_frame2.grid(row=8, column=0, padx=5, pady=5, sticky='w')
1830
+ text_frame2.columnconfigure(0, weight=1)
1831
+ text_frame2.columnconfigure(1, weight=7)
1832
+
1833
+ _size = get_max_size()
1834
+
1835
+ # ์ถœ๋ ฅ ํ…์ŠคํŠธ ์ฐฝ
1836
+ text_output_label = tk.Label(text_frame, text="ํ”„๋กฌํ”„ํŠธ", borderwidth=1, relief="solid",height=6)
1837
+ text_output_label.grid(row=0, column=0, padx=5, pady=5, sticky='w')
1838
+ if _size<=768: text_output_width = 74
1839
+ else: text_output_width = 65
1840
+ text_output = tk.Text(text_frame, width=text_output_width, height=7)
1841
+ text_output.grid(row=0, column=1, sticky='ew')
1842
+
1843
+ fixed_prompt_frame = tk.Frame(left_frame)
1844
+ fixed_prompt_frame.grid(row=7, column=0, padx=5, pady=5, sticky='w')
1845
+ fixed_prompt_frame.columnconfigure(0, weight=1)
1846
+ fixed_prompt_frame.columnconfigure(1, weight=1)
1847
+
1848
+ fixed_prompt_label_left = tk.Label(fixed_prompt_frame, text="์„ ํ–‰ ๊ณ ์ • ํ”„๋กฌํ”„ํŠธ (ํ”„๋กฌํ”„ํŠธ ์•ž)")
1849
+ fixed_prompt_label_left.grid(row=0, column=0, sticky='ew')
1850
+ fixed_prompt_label_right = tk.Label(fixed_prompt_frame, text="ํ›„ํ–‰ ๊ณ ์ • ํ”„๋กฌํ”„ํŠธ (ํ”„๋กฌํ”„ํŠธ ๋’ค)")
1851
+ fixed_prompt_label_right.grid(row=0, column=1, sticky='ew')
1852
+ entry_fixed_prompt = tk.Entry(fixed_prompt_frame, width=40)
1853
+ entry_fixed_prompt.grid(row=1, column=0,padx=5, pady=5, sticky='ew')
1854
+ entry_fixed_prompt_after = tk.Entry(fixed_prompt_frame, width=40)
1855
+ entry_fixed_prompt_after.grid(row=1, column=1, padx=5, pady=5, sticky='ew')
1856
+
1857
+ # ๋„ค๊ฑฐํ‹ฐ๋ธŒ ํ”„๋กฌํ”„ํŠธ
1858
+ NP_label = tk.Label(text_frame2, text="๋„ค๊ฑฐํ‹ฐ๋ธŒ\nํ”„๋กฌํ”„ํŠธ", borderwidth=1, relief="solid",height=2)
1859
+ NP_label.grid(row=0,column=0, padx=5, pady=5, sticky='ew')
1860
+ negative_text = tk.Text(text_frame2, width=65, height=3)
1861
+ negative_text.grid(row=0, column=1, padx=5, pady=5, sticky='w')
1862
+
1863
+ auto_hide_frame = tk.Frame(left_frame)
1864
+ auto_hide_frame.grid(row=9, column=0, padx=5, pady=5, sticky='w')
1865
+ auto_hide_frame.columnconfigure(0, weight=2)
1866
+ auto_hide_frame.columnconfigure(1, weight=2)
1867
+ auto_hide_frame.columnconfigure(2, weight=1)
1868
+
1869
+ # ์ž๋™ ์ˆจ๊น€ ํ‚ค์›Œ๋“œ ๋ผ๋ฒจ๊ณผ ์ž…๋ ฅ์ฐฝ ์ถ”๊ฐ€
1870
+ auto_hide_label = tk.Label(auto_hide_frame, text="์ž๋™ ์ˆจ๊น€ ํ‚ค์›Œ๋“œ: keyword1, keyword2, ...")
1871
+ auto_hide_label.grid(row=0, column=0, sticky='w')
1872
+ entry_auto_hide = tk.Entry(auto_hide_frame, width=82)
1873
+ entry_auto_hide.grid(row=1, column=0, columnspan=3, padx=5, pady=5, sticky='ew')
1874
+ # ์ถ”์ฒœ ํ”„๋กฌํ”„ํŠธ ์กฐํšŒ ๋ฒ„ํŠผ ์„ค์ •
1875
+ recommend_prompt_button = tk.Button(auto_hide_frame, text="์ถ”์ฒœ ํ”„๋กฌํ”„ํŠธ", command=open_prompt_window)
1876
+ recommend_prompt_button.grid(row=0, column=2, padx=2, pady=5, sticky='e') # sticky ์˜ต์…˜์„ 'e'๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ์˜ค๋ฅธ์ชฝ ์ •๋ ฌ
1877
+
1878
+
1879
+ # ์ฒดํฌ๋ฐ•์Šค๋“ค์„ ํฌํ•จํ•  ํ”„๋ ˆ์ž„ ์ƒ์„ฑ
1880
+ checkbox_frame = tk.Frame(left_frame)
1881
+ checkbox_frame.grid(row=10, column=0, pady=15, sticky='ew')
1882
+ checkbox_frame2 = tk.Frame(left_frame)
1883
+ checkbox_frame2.grid(row=10, column=1, padx=5, pady=15, sticky='ew')
1884
+
1885
+ # ์ฒดํฌ๋ฐ•์Šค ํ”„๋ ˆ์ž„ ๋‚ด์˜ ์—ด ์„ค์ •
1886
+ checkbox_frame.columnconfigure(0, weight=1)
1887
+ checkbox_frame.columnconfigure(1, weight=1)
1888
+ checkbox_frame.columnconfigure(2, weight=1)
1889
+ checkbox_frame.columnconfigure(3, weight=1)
1890
+ checkbox_frame.columnconfigure(4, weight=1)
1891
+ checkbox_frame.columnconfigure(5, weight=1)
1892
+
1893
+
1894
+ # "์ž‘๊ฐ€๋ช… ์ œ๊ฑฐ" ์ฒดํฌ๋ฐ•์Šค
1895
+ remove_artist_var = tk.IntVar() # ์ฒดํฌ๋ฐ•์Šค ์ƒํƒœ๋ฅผ ์ €์žฅํ•  ๋ณ€์ˆ˜
1896
+ check_remove_artist = tk.Checkbutton(checkbox_frame, text="์ž‘๊ฐ€๋ช… ์ œ๊ฑฐ", variable=remove_artist_var)
1897
+ check_remove_artist.grid(row=0, column=0, sticky='ew')
1898
+
1899
+ # "๋žœ๋ค ์ž‘๊ฐ€ ์ถ”๊ฐ€" ์ฒดํฌ๋ฐ•์Šค
1900
+ random_artist_var = tk.IntVar()
1901
+ check_random_artist = tk.Checkbutton(checkbox_frame, text="๋žœ๋ค ์ž‘๊ฐ€ ์ถ”๊ฐ€", variable=random_artist_var)
1902
+ check_random_artist.grid(row=0, column=1, sticky='ew')
1903
+
1904
+ # ๋žœ๋ค์ž‘๊ฐ€ ๊ด€๋ฆฌ
1905
+ random_artist_setting = tk.Button(checkbox_frame, text="๋žœ๋ค ์ž‘๊ฐ€ ๊ด€๋ฆฌ", command=random_artist_management) #output_file_path
1906
+ random_artist_setting.grid(row=0, column=2, sticky='ew')
1907
+
1908
+ # "์บ๋ฆญํ„ฐ ํŠน์ง• ์ œ๊ฑฐ" ์ฒดํฌ๋ฐ•์Šค
1909
+ rm_characteristic_var = tk.IntVar()
1910
+ rm_characteristic_label = tk.Checkbutton(checkbox_frame, text="์บ๋ฆญํ„ฐ ํŠน์ง• ์ œ๊ฑฐ", variable=rm_characteristic_var)
1911
+ rm_characteristic_label.grid(row=0, column=3, sticky='ew')
1912
+
1913
+ # ์™€์ผ๋“œ ์นด๋“œ
1914
+ wildcard_var = tk.IntVar(value= 0)
1915
+ check_wildcard = tk.Checkbutton(checkbox_frame, text="์™€์ผ๋“œ์นด๋“œ(์ž‘๊ฐ€)", variable=wildcard_var, state='disabled')
1916
+ check_wildcard.grid(row=1, column=0, sticky='ew')
1917
+
1918
+ # ์™€์ผ๋“œ ์นด๋“œ2
1919
+ wildcard_var2 = tk.IntVar(value= 0)
1920
+ check_wildcard2 = tk.Checkbutton(checkbox_frame, text="์™€์ผ๋“œ์นด๋“œ(์บ๋ฆญํ„ฐ)", variable=wildcard_var2, state='disabled')
1921
+ check_wildcard2.grid(row=1, column=1, sticky='ew')
1922
+
1923
+ # ์™€์ผ๋“œ ์นด๋“œ ์„ค์ •
1924
+ widldcard_button = tk.Button(checkbox_frame, text="์™€์ผ๋“œ์นด๋“œ ์„ค์ •", command=open_wildcard_setting) #output_file_path
1925
+ widldcard_button.grid(row=1, column=2, sticky='ew')
1926
+
1927
+ #ํด๋” ํ˜ธ์ถœ ๋ฒ„ํŠผ
1928
+ folder_button = tk.Button(checkbox_frame, text="์ €์žฅ ํด๋”", command=open_file_explorer) #output_file_path
1929
+ folder_button.grid(row=1, column=3, padx=5, sticky='ew')
1930
+
1931
+
1932
+ window.bind('<Control-Return>', on_ctrl_enter)
1933
+ window.bind('<Shift-Return>', on_shift_enter)
1934
+
1935
+ NAI_ID = load_settings()
1936
+ if not (entry_keyword.get()): entry_keyword.insert(0, "1girl")
1937
+ if not (entry_fixed_prompt.get()): entry_fixed_prompt.insert(0, '1girl,')
1938
+ if not (entry_fixed_prompt_after.get()): entry_fixed_prompt_after.insert(0, 'great quality, aesthetic, absurdres')
1939
+ if not (entry_auto_hide.get()): entry_auto_hide.insert(0, 'monochrome, doujin cover, bad source, censored, bar censor')
1940
+
1941
+ resolution1_frame = tk.Frame(left_frame)
1942
+ resolution1_frame.grid(row=15, column=0, padx=5, pady=5, sticky='ew')
1943
+ resolution2_frame = tk.Frame(left_frame)
1944
+ resolution2_frame.grid(row=16, column=0, padx=5, pady=5, sticky='ew')
1945
+ selected_resolution = tk.StringVar(value="1024 x 1024")
1946
+
1947
+ tk.Radiobutton(resolution1_frame, text="1024 x 1024", variable=selected_resolution, value="1024 x 1024").grid(row=0, column=0, sticky='w')
1948
+ tk.Radiobutton(resolution1_frame, text="960 x 1088", variable=selected_resolution, value="960 x 1088").grid(row=0, column=1, sticky='w')
1949
+ tk.Radiobutton(resolution1_frame, text="896 x 1152", variable=selected_resolution, value="896 x 1152").grid(row=0, column=2, sticky='w')
1950
+ tk.Radiobutton(resolution1_frame, text="832 x 1216", variable=selected_resolution, value="832 x 1216").grid(row=0, column=3, sticky='w')
1951
+ tk.Radiobutton(resolution2_frame, text="1088 x 960", variable=selected_resolution, value="1088 x 960").grid(row=0, column=0, sticky='w')
1952
+ tk.Radiobutton(resolution2_frame, text="1152 x 896", variable=selected_resolution, value="1152 x 896").grid(row=0, column=1, sticky='w')
1953
+ tk.Radiobutton(resolution2_frame, text="1216 x 832", variable=selected_resolution, value="1216 x 832").grid(row=0, column=2, sticky='w')
1954
+ selected_resolution.trace_add('write', on_resolution_change)
1955
+
1956
+ sema_button_var = tk.IntVar(value=1)
1957
+ sema_button = tk.Checkbutton(resolution1_frame, text="SEMA", variable=sema_button_var)
1958
+ sema_button.grid(row=0, column=5, sticky='w')
1959
+
1960
+ dyn_button_var = tk.IntVar()
1961
+ dyn_button = tk.Checkbutton(resolution1_frame, text="+DYN", variable=dyn_button_var)
1962
+ dyn_button.grid(row=0, column=6, sticky='w')
1963
+
1964
+ rand_resolution_var = tk.IntVar()
1965
+ rand_resolution_button = tk.Checkbutton(resolution1_frame, text="๋žœ๋ค ํ•ด์ƒ๋„", variable=rand_resolution_var)
1966
+ rand_resolution_button.grid(row=0, column=7, sticky='w')
1967
+
1968
+ entry_CFG_value = tk.StringVar()
1969
+ entry_CFG_label = tk.Label(resolution2_frame, text=" CFG Scale : ", justify=tk.LEFT)
1970
+ entry_CFG_label.grid(row=0, column=4, sticky='w')
1971
+ entry_CFG_value.set("5.0")
1972
+
1973
+ entry_CFG = tk.Entry(resolution2_frame, width=5, textvariable=entry_CFG_value)
1974
+ entry_CFG.grid(row=0, column=5, sticky='w')
1975
+
1976
+ options = ["k_euler", "k_euler_ancestral", "k_dpmpp_2s_ancestral", "k_dpmpp_sde"]
1977
+ selected_option = tk.StringVar()
1978
+ selected_option.set(options[1])
1979
+ option_menu = tk.OptionMenu(resolution2_frame, selected_option, *options, command=on_option_select)
1980
+ option_menu.grid(row=0, column=6, padx=5, sticky='ew')
1981
+
1982
+ resolution3_frame = tk.Frame(left_frame)
1983
+ resolution3_frame.grid(row=17, column=0, padx=5, pady=5, sticky='ew')
1984
+ resolution3_frame.columnconfigure(0, weight=2)
1985
+ resolution3_frame.columnconfigure(1, weight=1)
1986
+ resolution3_frame.columnconfigure(2, weight=1)
1987
+
1988
+ running_state = tk.Label(resolution3_frame, text="state : idle")
1989
+ running_state.grid(row = 0, column= 0, sticky='w')
1990
+ entry_rescale_value = tk.StringVar()
1991
+ entry_rescale_label = tk.Label(resolution3_frame, text=" Prompt Guidance Rescale : ", justify=tk.LEFT)
1992
+ entry_rescale_label.grid(row=0, column=1, sticky='e')
1993
+ entry_rescale_value.set("0.0")
1994
+ entry_rescale = tk.Entry(resolution3_frame, width=5, textvariable=entry_rescale_value)
1995
+ entry_rescale.grid(row=0, column=2, sticky='w')
1996
+
1997
+ image_label = tk.Label(right_frame, relief='solid', borderwidth=1)
1998
+ image_label.grid(row=0, column=0, rowspan=15, padx=10, pady=10, sticky="n")
1999
+
2000
+ right_frame_area16 = tk.Frame(right_frame)
2001
+ right_frame_area16.grid(row=16, column=0, padx=5, pady=5, sticky='ew')
2002
+ entry_seed_value = tk.IntVar()
2003
+ entry_seed_label = tk.Label(right_frame_area16, text=" seed : ", justify=tk.LEFT)
2004
+ entry_seed_label.grid(row=0, column=0, sticky='ew')
2005
+ entry_seed_value.set(last_generation_seed)
2006
+ entry_seed = tk.Entry(right_frame_area16, width=15, textvariable=entry_seed_value)
2007
+ entry_seed.grid(row=0, column=1, sticky='ew')
2008
+ hold_seed_var = tk.IntVar(value=0)
2009
+ hold_seed_button = tk.Checkbutton(right_frame_area16, text="์‹œ๋“œ๊ณ ์ •", variable=hold_seed_var)
2010
+ hold_seed_button.grid(row=0, column=2, sticky='ew')
2011
+
2012
+ btn_add_low_freq = tk.Button(right_frame_area16, text="์ด๋ฏธ์ง€๋ฅผ ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌ", fg="blue", command=copy_image_to_clipboard)
2013
+ btn_add_low_freq.grid(row=0, column=3, padx=5, pady=5, sticky='ew')
2014
+
2015
+ # ํ•˜์–€์ƒ‰ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
2016
+ white_image = Image.new('RGB', (_size, _size), 'white')
2017
+ white_photo = ImageTk.PhotoImage(white_image)
2018
+
2019
+ # ๋ผ๋ฒจ์— ์ด๋ฏธ์ง€ ์„ค์ •
2020
+ image_label.config(image=white_photo)
2021
+ image_label.image = white_photo
2022
+
2023
+ # ๋ฆฌ์Šค๋„ˆ ์‹œ์ž‘
2024
+ listener = keyboard.Listener(on_press=on_press, on_release=on_release)
2025
+ listener.start()
2026
+
2027
+ # ํ‚ค๋ณด๋“œ ๋ฆฌ์Šค๋„ˆ ์Šค๋ ˆ๋“œ ์‹œ์ž‘
2028
+ listener_thread = threading.Thread(target=listener.join, daemon=True)
2029
+ listener_thread.start()
2030
+
2031
+ Auto_login_check()
2032
+
2033
+ window.mainloop()