baqu2213 commited on
Commit
4f8ca79
โ€ข
1 Parent(s): 37e237e

Upload 2 files

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