baqu2213 commited on
Commit
db03d2e
โ€ข
1 Parent(s): 3a4cd3b

Upload 2 files

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