baqu2213's picture
Upload prompt_selector_1215.py
0ab257b
raw
history blame
128 kB
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import filedialog
import os
import csv
import random
import time
from collections import Counter
import re
import ast
import pyautogui
import threading
from pynput import keyboard
from base64 import urlsafe_b64encode
from hashlib import blake2b
import argon2
import requests
import json
from os import environ as env
import zipfile
import io
from pathlib import Path
from datetime import datetime
import numpy as np
from PIL import Image, ImageOps, ImageDraw, ImageFont,ImageTk
from IPython.display import display
import win32clipboard
from io import BytesIO
from datetime import datetime
import arti_list, tagbag, wlist, copyright_list_reformatted, remove_result_e, remove_result_qe
import character_dictionary as cd
import pandas as pd
import webbrowser
from collections import OrderedDict
BASE_URL="https://api.novelai.net"
copyright_keys = copyright_list_reformatted.copyright_list
character_keys = list(cd.character_dictionary.keys())
nsfw_word = list(remove_result_e.keyword_counts.keys())
questionable_word = list(remove_result_qe.keyword_counts.keys())
qe_word = nsfw_word + questionable_word
def argon_hash(email: str, password: str, size: int, domain: str) -> str:
pre_salt = f"{password[:6]}{email}{domain}"
# salt
blake = blake2b(digest_size=16)
blake.update(pre_salt.encode())
salt = blake.digest()
raw = argon2.low_level.hash_secret_raw(
password.encode(),
salt,
2,
int(2000000 / 1024),
1,
size,
argon2.low_level.Type.ID,
)
hashed = urlsafe_b64encode(raw).decode()
return hashed
def login(key) -> str:
response = requests.post(f"{BASE_URL}/user/login", json={ "key": key })
# catch any errors
return response.json()["accessToken"]
def get_access_key(email: str, password: str) -> str:
return argon_hash(email, password, 64, "novelai_data_access_key")[:64]
def get_max_size():
global window
width = window.winfo_screenheight()
return 768 if width < 1440 else 1024
def generate_image(access_token, prompt, model, action, parameters):
data = {
"input": prompt,
"model": model,
"action": action,
"parameters": parameters,
}
response = requests.post(f"{BASE_URL}/ai/generate-image", json=data, headers={ "Authorization": f"Bearer {access_token}" })
# catch any errors
return response.content
def history_queue(image, prompt, seed):
global history
history.append([image, prompt, seed])
if len(history) > 5:
history.pop(0)
def show_history():
global history
# ์ƒˆ๋กœ์šด toplevel ์ฐฝ ์ƒ์„ฑ
history_window = tk.Toplevel(window)
history_window.title("History")
# history_window์—์„œ ์ธ๋„ค์ผ๊ณผ ํ…์ŠคํŠธ๋ฅผ ํ‘œ์‹œํ•  grid ์„ค์ •
for index, (image, prompt, seed) in enumerate(history):
# ์ด๋ฏธ์ง€๋ฅผ ์ธ๋„ค์ผ๋กœ ๋ณ€ํ™˜
image.thumbnail((192, 192)) # ๊ฐ€๋กœ ์„ธ๋กœ 100ํ”ฝ์…€๋กœ ์กฐ์ •
photo = ImageTk.PhotoImage(image)
# ์ธ๋„ค์ผ ์ด๋ฏธ์ง€ ๋ผ๋ฒจ ์ƒ์„ฑ
image_label = tk.Label(history_window, image=photo)
image_label.image = photo # ์ฐธ์กฐ๋ฅผ ์œ ์ง€
image_label.grid(row=index, column=0)
# prompt์™€ seed๋ฅผ ๊ฒฐํ•ฉํ•œ ํ…์ŠคํŠธ ์ƒ์„ฑ
text_prompt = prompt + ' Seed: ' + str(seed)
text_widget = tk.Text(history_window, height=10, width=75) # UI ์‚ฌ์ด์ฆˆ์— ๋งž๊ฒŒ width์™€ height ์กฐ์ ˆ
text_widget.insert('1.0', text_prompt)
text_widget.grid(row=index, column=1)
text_widget.config(state='disabled') # ํ…์ŠคํŠธ ์œ„์ ฏ์„ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์„ค์ •
def generate(width, height, positive, negative, button):
global temp_clipboard_image
global current_sampler
global NAI_width, NAI_height
global running_flag
global last_generation_seed
try:
scale = float(entry_CFG_value.get())
except:
scale = 5.0
if scale > 7.0: scale = 7.0
elif scale < 4.0: scale = 4.0
else: scale = round(scale, 1)
try:
scale2 = float(entry_rescale_value.get())
except:
scale2 = 0
if scale2 > 1.00: scale = 1.00
elif scale2 < 0.0: scale = 0.00
else: scale2 = round(scale2, 2)
params = {
"legacy": False,
"quality_toggle": False,
"width": width,
"height": height,
"n_samples": 1,
"seed": random.randint(0,9999999999),
"extra_noise_seed": random.randint(0,9999999999),
"sampler": current_sampler,
"steps": 28,
"scale": scale,
"uncond_scale": 1.0,
"negative_prompt": negative_text.get("1.0", "end-1c").strip(),
"sm" : sema_button_var.get(),
"sm_dyn" : dyn_button_var.get(),
"decrisper": False,
"controlnet_strength": 1.0,
"add_original_image": False,
"cfg_rescale": scale2,
"noise_schedule": "native",
}
if (hold_seed_var.get()):
params['seed'] = last_generation_seed
def resize_and_fill(image, max_size=None):
if max_size is None:
max_size = get_max_size()
original_width, original_height = image.size
if original_width > max_size or original_height > max_size:
# ๋น„์œจ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ํฌ๊ธฐ ์กฐ์ •
image.thumbnail((max_size, max_size))
# ์ƒˆ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ๊ณ„์‚ฐ
width, height = image.size
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(image, ((max_size - width) // 2, (max_size - height) // 2))
return new_image
else:
return image
def log_error(e, output_file_path="output_file_path"):
# ํ˜„์žฌ ์‹œ๊ฐ„์„ ์–ป์Šต๋‹ˆ๋‹ค
current_time = datetime.now().strftime("%m/%d %H:%M:%S")
# ์—๋Ÿฌ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€
error_message = f"#### Error occured at {current_time} ####\nError: {e}\n############################################\n"
# ์ง€์ •๋œ ์ถœ๋ ฅ ํด๋”์˜ error_log.txt ํŒŒ์ผ์— ์“ฐ๊ธฐ
with open(f"error_log.txt", "a") as file:
file.write(error_message)
global access_token, access_token_multi, error_count, multi_token_enable
while (running_flag):
time.sleep(1)
try:
running_flag = True
tprint("Running : NAI request received")
if not (multi_token_enable): zipped_bytes = generate_image(access_token, positive, "nai-diffusion-3", "generate", params)
else: zipped_bytes = generate_image(access_token_multi, positive, "nai-diffusion-3", "generate", params)
d = Path(f"output_NAI/{start_time}/txt2img")
d.mkdir(parents=True, exist_ok=True)
zipped = zipfile.ZipFile(io.BytesIO(zipped_bytes))
image_bytes = zipped.read(zipped.infolist()[0])
(d / f"{datetime.now().strftime('%Y%m%d_%H%M%S')}.png" ).write_bytes(image_bytes)
i = Image.open(io.BytesIO(image_bytes))
i = ImageOps.exif_transpose(i).convert("RGB")
if temp_clipboard_image is not None:
temp_clipboard_image.close()
temp_clipboard_image = i
i_resized = resize_and_fill(i)
if 'tk_image' in globals():
globals()['tk_image'] = None
tk_image = ImageTk.PhotoImage(i_resized)
image_label.config(image=tk_image)
image_label.original_image = i.copy()
image_label.image = tk_image # ์ฐธ์กฐ ์œ ์ง€
output_file_path = "output_image.jpg"
history_queue(i_resized.copy(), positive, params['seed'])
i.save(output_file_path)
error_count = 0
except Exception as e:
#text_output.insert(tk.END, f"Error: {e}", fg='red')
log_error(zipped_bytes.decode('utf-8')[2:-2], "path_to_output_folder")
time.sleep(random.uniform(1.0, 2.5))
error_count += 1
if error_count > 5:
mac_var.set(0)
button.config(state=tk.NORMAL)
global delay_offset
time.sleep(delay_offset)
running_flag = False
last_generation_seed = params['seed']
entry_seed_value.set(last_generation_seed)
if mac_var.get() and not running_flag:
random_function()
time.sleep(random.uniform(5.1, 8.5))
button.config(state=tk.DISABLED)
window.event_generate(GENERATE_EVENT, when="tail")
else:
time.sleep(random.uniform(1.0, 2.5))
button.config(state=tk.NORMAL)
tprint('state : idle')
def filter_csv(input_file, output_file, _search_strings):
output_directory = os.getcwd()
output_file = os.path.join(output_directory, output_file)
search_strings = [s.strip() for s in _search_strings.split(',')]
with open(input_file, 'r', newline='', encoding='utf-8') as f_in, \
open(output_file, 'w', newline='', encoding='utf-8') as f_out:
reader = csv.reader(f_in)
writer = csv.writer(f_out)
writer_count = 0
for row in reader:
if all(search_str in value for search_str in search_strings for value in row):
writer.writerow(row)
writer_count += 1
return writer_count
def open_file():
initial_dir = os.getcwd()
filepath = filedialog.askopenfilename(
initialdir=initial_dir,
filetypes=[("CSV Files", "*.csv")]
)
if filepath:
entry_file_path.delete(0, tk.END)
entry_file_path.insert(0, filepath)
def search():
global total_rows, cached_rows # cached_rows๋ฅผ global๋กœ ์„ ์–ธ
input_file = entry_file_path.get()
keywords = entry_keyword.get()
output_file = 'txt2img_temp_prompt.csv'
writer_count = filter_csv(input_file, output_file, keywords)
total_rows = writer_count
total_rows_count_label.config(text=f".csv ๋‚ด ํ”„๋กฌํ”„ํŠธ ํ–‰: {writer_count}", fg="blue")
text_output.insert(tk.END, f"์ด {writer_count}๊ฐœ์˜ ๋ฌธ์ž์—ด์ด ๊ฒ€์ƒ‰๋˜์–ด ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.\n")
# ๊ฒ€์ƒ‰ ํ›„ cached_rows ์ดˆ๊ธฐํ™”
cached_rows = []
def exclude():
global total_rows, cached_rows # cached_rows๋ฅผ global๋กœ ์„ ์–ธ
input_file = entry_file_path.get()
keywords = entry_keyword.get()
output_file = 'txt2img_temp_prompt.csv'
keyword_label.config(text="๊ฒ€์ƒ‰ํ•  ํ‚ค์›Œ๋“œ: ")
output_directory = os.getcwd()
output_file = os.path.join(output_directory, output_file)
search_strings = [s.strip() for s in keywords.split(',')]
with open(input_file, 'r', newline='', encoding='utf-8') as f_in, \
open(output_file, 'w', newline='', encoding='utf-8') as f_out:
reader = csv.reader(f_in)
writer = csv.writer(f_out)
writer_count = 0
for row in reader:
if not any(search_str in value for search_str in search_strings for value in row):
writer.writerow(row)
writer_count += 1
total_rows = writer_count
total_rows_count_label.config(text=f".csv ๋‚ด ํ”„๋กฌํ”„ํŠธ ํ–‰: {writer_count}", fg="red")
text_output.insert(tk.END, f"์ด {writer_count}๊ฐœ์˜ ๋ฌธ์ž์—ด์ด ๊ฒ€์ƒ‰๋˜์–ด ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.\n")
# ์ œ์™ธ ํ›„ cached_rows ์ดˆ๊ธฐํ™”
cached_rows = []
def copy_image_to_clipboard():
global temp_clipboard_image
image = temp_clipboard_image
output = BytesIO()
image.convert('RGB').save(output, format='BMP')
data = output.getvalue()[14:] # BMP ํŒŒ์ผ ํ—ค๋” ์ œ๊ฑฐ
output.close()
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
win32clipboard.CloseClipboard()
def reset():
cached_rows = None
entry_file_path.delete(0, tk.END)
entry_keyword.delete(0, tk.END)
entry_deep_search.delete(0, tk.END)
text_output.delete('1.0', tk.END)
def rearrange_keywords_boys_girls(keywords):
boy_keyword = None
girl_keyword = None
# ์ฒ˜์Œ 10๊ฐœ ํ‚ค์›Œ๋“œ๋ฅผ ํ™•์ธ
for keyword in keywords[:10]:
if 'boy' in keyword and len(keyword) <= 5:
boy_keyword = keyword
if 'girl' in keyword and len(keyword) <= 5:
girl_keyword = keyword
# 'boy'์™€ 'girl' ํ‚ค์›Œ๋“œ๊ฐ€ ์กด์žฌํ•˜๊ณ , ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๊ฒฝ์šฐ
if boy_keyword and girl_keyword:
boy_index = keywords.index(boy_keyword)
if boy_index != 0:
keywords.insert(0, keywords.pop(boy_index))
girl_index = keywords.index(girl_keyword)
if girl_index > boy_index:
keywords.insert(boy_index + 1, keywords.pop(girl_index))
return keywords
def random_function():
global last_deep_search_keywords, cached_rows, last_selected_row_keywords, top_100_keywords, previous_artist, top_100_counts
global current_wildcard_character, current_wildcard_artist
global previous_wildcard_artist, previous_wildcard_character, character_keys, copyright_keys
current_deep_search_keywords = entry_deep_search.get().strip()
auto_hide_keywords = entry_auto_hide.get().split(',')
auto_hide_keywords = [keyword.strip() for keyword in auto_hide_keywords if keyword.strip()]
current_artist = None
curly_brackets_keywords = re.findall(r'\{([^}]+)\}', current_deep_search_keywords)
# ๊ฐ ๋ธŒ๋ž˜ํ‚ท ๋‚ด ํ‚ค์›Œ๋“œ ๊ทธ๋ฃน์„ ์ฒ˜๋ฆฌํ•˜์—ฌ ์™„๋ฒฝ ์ผ์น˜ ํ‚ค์›Œ๋“œ์™€ ์ผ๋ฐ˜ ํ‚ค์›Œ๋“œ๋ฅผ ๊ตฌ๋ถ„
processed_keywords = []
for group in curly_brackets_keywords:
perfect_match_group = [kw[1:].strip() for kw in group.split('|') if kw.startswith('*')]
regular_group = [kw.strip() for kw in group.split('|') if not kw.startswith('*')]
processed_keywords.append((perfect_match_group, regular_group))
modified_deep_search_keywords = re.sub(r'\{[^}]+\}', '', current_deep_search_keywords)
# ๋‚จ์€ ํ‚ค์›Œ๋“œ๋“ค์„ ์‰ผํ‘œ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์ฒ˜๋ฆฌ
remaining_keywords = [kw.strip() for kw in modified_deep_search_keywords.split(',') if kw.strip()]
perfect_match_keywords = [kw[1:].strip() for kw in remaining_keywords if kw.startswith('*')]
# exclude_keywords์™€ include_keywords ์ •์˜
exclude_keywords = [kw[1:].strip() for kw in remaining_keywords if kw.startswith('~') and not kw[1:].startswith('*')]
include_keywords = [kw for kw in remaining_keywords if not kw.startswith('~') and not kw.startswith('*')]
if current_deep_search_keywords != last_deep_search_keywords or not cached_rows:
if not os.path.exists('txt2img_temp_prompt.csv'):
text_output.delete('1.0', tk.END)
text_output.insert(tk.END, "txt2img_temp_prompt.csv๊ฐ€ ์—†์–ด ์žฌ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ž‘์—…์—๋Š” ๋งค์šฐ ๊ธด ์‹œ๊ฐ„์ด ์†Œ์š”๋ฉ๋‹ˆ๋‹ค. tags.csv ํŒŒ์ผ์— ๋Œ€ํ•ด ์ดˆ๊ธฐํ™” ํ‚ค์›Œ๋“œ ๋ฐ .csv ๋‚ด๋ณด๋‚ด๊ธฐ ๊ธฐ๋Šฅ์„ ํ™œ์šฉ ํ•ด ์ฃผ์„ธ์š”.")
try:
with open('txt2img_temp_prompt.csv', 'r', newline='', encoding='utf-8') as f:
reader = csv.reader(f)
rows = []
for row in reader:
if all(re.search(r'(?:^|, )' + re.escape(kw) + r'(?:,|$)', ', '.join(row)) for kw in perfect_match_keywords) \
and not any(re.search(r'\b' + re.escape(exclude) + r'\b', cell) for exclude in exclude_keywords for cell in row) \
and all(include in cell for include in include_keywords for cell in row):
# '{}' ์•ˆ์˜ ํ‚ค์›Œ๋“œ ์ฒ˜๋ฆฌ
if all(any(re.search(r'(?:^|, )' + re.escape(kw) + r'(?:,|$)', ', '.join(cell)) for kw in perfect_group) or
any(kw in cell for kw in regular_group) for perfect_group, regular_group in processed_keywords for cell in row):
rows.append(row)
cached_rows = rows
except:
try:
search()
with open('txt2img_temp_prompt.csv', 'r', newline='', encoding='utf-8') as f:
reader = csv.reader(f)
rows = []
for row in reader:
if all(re.search(r'(?:^|, )' + re.escape(kw) + r'(?:,|$)', ', '.join(row)) for kw in perfect_match_keywords) \
and not any(re.search(r'\b' + re.escape(exclude) + r'\b', cell) for exclude in exclude_keywords for cell in row) \
and all(include in cell for include in include_keywords for cell in row):
# '{}' ์•ˆ์˜ ํ‚ค์›Œ๋“œ ์ฒ˜๋ฆฌ
if all(any(re.search(r'(?:^|, )' + re.escape(kw) + r'(?:,|$)', ', '.join(cell)) for kw in perfect_group) or
any(kw in cell for kw in regular_group) for perfect_group, regular_group in processed_keywords for cell in row):
rows.append(row)
cached_rows = rows
except:
def open_link(url):
webbrowser.open_new(url)
text_output.delete('1.0', tk.END)
text_output.insert(tk.END, "tags.csv ํŒŒ์ผ์„ [ํŒŒ์ผ ์—ด๊ธฐ] ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ํƒ‘์žฌํ•˜๊ฑฐ๋‚˜,")
text_output.insert(tk.END, "https://huggingface.co/baqu2213/PoemForSmallFThings/blob/main/Danbooru%20Prompt%20Selector/tags_2023.csv", "link")
text_output.insert(tk.END, " ์—์„œ ๋‹ค์šด๋กœ๋“œ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.")
text_output.tag_config("link", foreground="blue", underline=True)
text_output.tag_bind("link", "<Button-1>", lambda e: open_link("https://huggingface.co/baqu2213/PoemForSmallFThings/blob/main/Danbooru%20Prompt%20Selector/tags_2023.csv"))
return
last_deep_search_keywords = current_deep_search_keywords
if not toggle_prompt_var.get(): text_output.delete('1.0', tk.END)
if random_artist_var.get():
if(not entry_fixed_prompt.get()): entry_fixed_prompt.insert(tk.END,'1girl')
if not os.path.exists("counting_result.txt"):
keyword_counts = analyze_cached_rows(cached_rows)
excluded_keywords = set(whitelist[:2974])
with open("counting_result.txt", "w") as file:
for keyword, count in sorted(keyword_counts.items(), key=lambda item: item[1], reverse=True):
if keyword not in excluded_keywords and keyword in afilter_30000:
file.write(f"{keyword}: {count}\n")
with open("counting_result.txt", "r") as file:
lines = file.readlines()
top_100_data = [
(line.split(":")[0].strip(), int(line.split(":")[1].strip()))
for line in lines[:3000]
if line.split(":")[0].strip() in afilter_30000[:8528]
]
top_100_keywords, top_100_counts = zip(*top_100_data) if top_100_data else ([], [])
elif (not top_100_keywords):
with open("counting_result.txt", "r") as file:
lines = file.readlines()
top_100_data = [
(line.split(":")[0].strip(), int(line.split(":")[1].strip()))
for line in lines[:3000]
if line.split(":")[0].strip() in afilter_30000[:8528]
]
top_100_keywords, top_100_counts = zip(*top_100_data) if top_100_data else ([], [])
formatted_artist_random_keyword = []
if top_100_keywords:
temp_keyword = []
temp_keyword += top_100_keywords
whatthefuck = random.random()
if(whatthefuck > 0.9):
for i in range(4):
random_keyword = random.choice(temp_keyword)
temp_keyword.remove(random_keyword)
if(i == 0): formatted_artist_random_keyword = "{{{artist:"+random_keyword+"}}}"
if(i == 1): formatted_artist_random_keyword += ",{artist:"+random_keyword+"}"
if(i == 2): formatted_artist_random_keyword += ",artist:"+random_keyword
if(i == 3): formatted_artist_random_keyword += ",[[artist:"+random_keyword+"]]"
elif(whatthefuck > 0.7):
for i in range(3):
random_keyword = random.choice(temp_keyword)
temp_keyword.remove(random_keyword)
if(i == 0): formatted_artist_random_keyword = "{{{artist:"+random_keyword+"}}}"
if(i == 1): formatted_artist_random_keyword += ",{artist:"+random_keyword+"}"
if(i == 2): formatted_artist_random_keyword += ",[[artist:"+random_keyword+"]]"
elif(whatthefuck > 0.45):
for i in range(2):
random_keyword = random.choice(temp_keyword)
temp_keyword.remove(random_keyword)
if(i == 0): formatted_artist_random_keyword = "{{{artist:"+random_keyword+"}}}"
if(i == 2): formatted_artist_random_keyword += ",[[artist:"+random_keyword+"]]"
else:
random_keyword = random.choice(temp_keyword)
temp_keyword.remove(random_keyword)
formatted_artist_random_keyword = "{{artist:"+random_keyword+"}}"
current_artist = formatted_artist_random_keyword
if not top_100_keywords: random_artist_var.set(0)
else:
formatted_artist_random_keyword = f"์ž‘๊ฐ€ ํ‚ค์›Œ๋“œ๊ฐ€ ์—†์Œ!!"
if cached_rows:
if toggle_prompt_var.get() and last_selected_row_keywords:
random_row_keywords = [keyword.strip() for keyword in text_output.get("1.0", "end-1c").split(',')]
random_row_keywords = [keyword.strip() for keyword in text_output.get("1.0", "end-1c").split(',')]
#random_row_keywords[-1].strip()
#if random_row_keywords[0]=='': random_row_keywords = last_selected_row_keywords
text_output.delete('1.0', tk.END)
else:
if (safe_search_var.get()):
for i in range(100):
random_index = random.randint(0, len(cached_rows) - 1)
random_row = cached_rows.pop(random_index)
random_row_keywords = [keyword.strip() for keyword in random_row[0].split(',')]
# random_row_keywords์— qe_word ํ•ด๋‹นํ•˜๋Š” ํ‚ค์›Œ๋“œ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธ
if not any(keyword in nsfw_word for keyword in random_row_keywords):
break # nsfw_word์— ํ•ด๋‹นํ•˜๋Š” ํ‚ค์›Œ๋“œ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๋ฐ˜๋ณต๋ฌธ ํƒˆ์ถœ
if len(cached_rows) == 0:
random_row_keywords = [keyword.strip() for keyword in "1girl, blank eyes, cell phone, chibi, crying, crying with eyes open, gloom (expression), holding, holding phone, open mouth, phone, smartphone, solo, surprised, tears, turn pale, white background, simple background, Search fail (text)".split(',')]
break
if i == 99: random_row_keywords = random_row_keywords = [keyword.strip() for keyword in "1girl, blank eyes, cell phone, chibi, crying, crying with eyes open, gloom (expression), holding, holding phone, open mouth, phone, smartphone, solo, surprised, tears, turn pale, white background, simple background, Search fail (text)".split(',')]
last_selected_row_keywords = random_row_keywords.copy()
else:
random_index = random.randint(0, len(cached_rows) - 1)
random_row = cached_rows.pop(random_index)
random_row_keywords = [keyword.strip() for keyword in random_row[0].split(',')]
last_selected_row_keywords = random_row_keywords.copy()
if(entry_fixed_prompt.get()):
entry_text_keywords = entry_fixed_prompt.get()
if(',' not in entry_text_keywords[-2:]): entry_text_keywords += ','
entry_text_keywords = entry_text_keywords.split(',')
entry_text_keywords = [kw.strip() for kw in entry_text_keywords if kw.strip()]
temp_first_keywords = []
#print("1 :", temp_first_keywords)
# entry_text_keywords์˜ ๋ชจ๋“  ํ‚ค์›Œ๋“œ๋ฅผ temp_first_keywords์— ์ถ”๊ฐ€
for et_kw in entry_text_keywords:
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):
temp_first_keywords.append(et_kw)
# 'boy' ํ‚ค์›Œ๋“œ ์ฒ˜๋ฆฌ
boy_keywords = [kw for kw in random_row_keywords if 'boy' in kw and len(kw) <= 7]
# 'girl' ํ‚ค์›Œ๋“œ ์ฒ˜๋ฆฌ ๋ฐ ์œ„์น˜ ์กฐ์ •
girl_keywords = []
if 'girl' in entry_text_keywords[0] and len(entry_text_keywords[0]) <= 7:
girl_keywords = [kw for kw in random_row_keywords if 'girl' in kw and len(kw) <= 7]
# random_row_keywords์—์„œ boy์™€ girl ํ‚ค์›Œ๋“œ ์ œ๊ฑฐ
for kw in boy_keywords + girl_keywords:
if kw in random_row_keywords:
random_row_keywords.remove(kw)
for kw in temp_first_keywords:
if kw in random_row_keywords:
random_row_keywords.remove(kw)
# temp_first_keywords์— boy์™€ girl ํ‚ค์›Œ๋“œ๋ฅผ ์ ์ ˆํ•œ ์œ„์น˜์— ์ถ”๊ฐ€
if(girl_keywords and 'girl' in temp_first_keywords[0]): temp_first_keywords.pop(0)
#print(wildcard_var.get())
print(random_row_keywords)
if(wildcard_var2.get() == 1):
temp_len = len(girl_keywords)
print('previous : ',previous_wildcard_character, 'type : ', type(previous_wildcard_character))
if previous_wildcard_character in random_row_keywords:
random_row_keywords.remove(previous_wildcard_character)
elif(previous_wildcard_character is not None):
split_previous_wildcard_character = previous_wildcard_character.split(',')
split_previous_wildcard_character = [keyword.strip() for keyword in split_previous_wildcard_character]
for _keyword in split_previous_wildcard_character:
if _keyword in random_row_keywords:
random_row_keywords.remove(_keyword)
if _keyword in random_row_keywords:
random_row_keywords.remove(_keyword)
previous_wildcard_character = get_random_keyword('character')
girl_keywords.append(previous_wildcard_character)
if(wildcard_var.get() == 1):
print('previous : ',previous_wildcard_artist, 'type : ', type(previous_wildcard_artist))
if previous_wildcard_artist is not None and previous_wildcard_artist in random_row_keywords:
random_row_keywords.remove(previous_wildcard_artist)
elif(previous_wildcard_artist is not None):
split_previous_wildcard_artist = previous_wildcard_artist.split(',')
split_previous_wildcard_artist = [keyword.strip() for keyword in split_previous_wildcard_artist]
split_previous_wildcard_artist[0] = split_previous_wildcard_artist[0]
for _keyword in split_previous_wildcard_artist:
if _keyword in random_row_keywords:
random_row_keywords.remove(_keyword)
previous_wildcard_artist = get_random_keyword('artist')
if(wildcard_var2.get() == 1):
girl_keywords.insert(temp_len+1,previous_wildcard_artist)
else:
girl_keywords.append(previous_wildcard_artist)
#print(boy_keywords)
#print(girl_keywords)
#print(temp_first_keywords)
if temp_first_keywords and 'girl' in temp_first_keywords[0]:
girl_in_gkey = False
for gkey in girl_keywords:
if 'girl' in gkey:
girl_in_gkey = True
if not girl_in_gkey:
temp_gkey = temp_first_keywords.pop(0)
girl_keywords.insert(0, temp_gkey)
temp_first_keywords = boy_keywords + girl_keywords + temp_first_keywords
#print("2 :", temp_first_keywords)
if remove_artist_var.get():
for keyword in random_row_keywords:
if keyword in afilter_30000:
random_row_keywords.remove(keyword)
temp_rm = []
if rm_characteristic_var.get():
for keyword in random_row_keywords:
if keyword in bag_of_tags or keyword in character_keys or "(" in keyword or "horns" in keyword:
if keyword not in entry_text_keywords:
temp_rm.append(keyword)
for keyword in temp_rm:
random_row_keywords.remove(keyword)
#NSFW_assert_var
nsfw_temp = []
if NSFW_assert_var.get():
for keyword in random_row_keywords:
if not rm_characteristic_var.get():
if keyword not in qe_word and (keyword not in bag_of_tags and keyword not in character_keys and "(" not in keyword and "horns" not in keyword):
nsfw_temp.append(keyword)
else:
if keyword not in qe_word:
nsfw_temp.append(keyword)
if nsfw_temp is not None:
if not remove_artist_var.get():
temp_rm_arti= []
for keyword in nsfw_temp:
if keyword in afilter_30000:
temp_rm_arti.append(keyword)
for keyword in temp_rm_arti:
nsfw_temp.remove(keyword)
if not rm_copyright_var.get():
for keyword in nsfw_temp:
if keyword not in copyright_keys:
random_row_keywords.remove(keyword)
else:
for keyword in nsfw_temp:
random_row_keywords.remove(keyword)
for keyword in random_row_keywords[:]: # ๋ณต์‚ฌ๋ณธ์„ ์ˆœํšŒํ•˜์—ฌ ์›๋ณธ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆ˜์ •
if " (" in keyword:
temp_first_keywords.append(keyword)
random_row_keywords.remove(keyword)
else:
if not random_row_keywords: random_row_keywords = last_selected_row_keywords
temp_first_keywords = []
for keyword in random_row_keywords[:]: # ๋ณต์‚ฌ๋ณธ์„ ์ˆœํšŒํ•˜์—ฌ ์›๋ณธ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆ˜์ •
if " (" in keyword:
temp_first_keywords.append(keyword)
random_row_keywords.remove(keyword)
t_temp = []
for keyword in temp_first_keywords:
t_temp.append(keyword.strip())
t_temp = list(OrderedDict.fromkeys(t_temp))
temp_first_keywords = list(t_temp)
#last_selected_row_keywords =boy_keywords + girl_keywords[:0] + random_row_keywords
#print("3 :", temp_first_keywords)
if random_artist_var.get():
temp_first_keywords.append(formatted_artist_random_keyword)
#print("4 :", temp_first_keywords)
if (previous_artist and previous_artist in temp_first_keywords): temp_first_keywords.remove(previous_artist)
if (current_artist is (not None)):
for i in range (len(current_artist)):
previous_artist += current_artist[i]
random_row_keywords = temp_first_keywords + random_row_keywords
#print("5 :", random_row_keywords)
#elif toggle_prompt_var.get(): random_row_keywords = temp_first_keywords + random_row_keywords
else: random_row_keywords = temp_first_keywords + random_row_keywords
patterns = auto_hide_keywords
rm_reserved = []
for pattern in patterns:
if pattern in random_row_keywords:
rm_reserved.append(pattern)
for pattern in rm_reserved:
random_row_keywords.remove(pattern)
if entry_fixed_prompt_after.get():
entry_after_text = [keyword.strip() for keyword in entry_fixed_prompt_after.get().split(',')]
for at_kw in entry_after_text:
if at_kw not in random_row_keywords and at_kw not in random_row_keywords:
random_row_keywords.append(at_kw)
rm_copyright = []
if(rm_copyright_var.get()):
for keyword in random_row_keywords:
if keyword in copyright_keys:
rm_copyright.append(keyword)
if rm_copyright is not None:
for keyword in rm_copyright:
random_row_keywords.remove(keyword)
else:
idx = 0
for keyword in random_row_keywords:
if keyword in copyright_keys:
random_row_keywords[idx] = keyword+" (copyright)"
idx += 1
pop_character = []
for keyword in random_row_keywords:
character_temp_keyword = keyword.replace('{', '').replace('}', '').replace('[', '').replace(']', '')
if character_temp_keyword in character_keys:
pop_character.append(keyword)
if pop_character is not None:
found_index = 0
# Search for 'girl' in the first four elements
for i in range(min(10, len(random_row_keywords))):
if 'girl' in random_row_keywords[i]:
found_index = i
break
elif 'boy' in random_row_keywords[i]:
found_index = i
break
elif 'other' in random_row_keywords[i]:
found_index = i
break
for keyword in pop_character:
found_index += 1
random_row_keywords.remove(keyword)
random_row_keywords.insert(found_index,keyword)
pop_artist = []
for keyword in random_row_keywords:
artist_temp_keyword = keyword.replace('{', '').replace('}', '').replace('[', '').replace(']', '')
if artist_temp_keyword in afilter_30000:
pop_artist.append(keyword)
if pop_artist is not None:
for keyword in pop_artist:
found_index += 1
random_row_keywords.remove(keyword)
random_row_keywords.insert(found_index,"artist:"+keyword)
random_row_keywords = rearrange_keywords_boys_girls(random_row_keywords)
#print(random_row_keywords)
text_output.insert(tk.END, f"{', '.join(random_row_keywords)}")
if auto_copy_var.get():
copy_to_clipboard()
else:
text_output.insert(tk.END, "๊ฒ€์ƒ‰ ์กฐ๊ฑด์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๊ฑฐ๋‚˜ CSV ํŒŒ์ผ์— ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.\n")
cached_rows_count_label.config(text=f"์‹ฌ์ธต๊ฒ€์ƒ‰ ํ”„๋กฌํ”„ํŠธ ํ–‰: {len(cached_rows)}")
def add_low_frequency_keywords():
global keyword_counts, most_common_count
keyword_counts = analyze_cached_rows(cached_rows)
if not keyword_counts: # keyword_counts๊ฐ€ ๋น„์–ด์žˆ๋Š” ๊ฒฝ์šฐ ํ•จ์ˆ˜๋ฅผ ๋น ์ ธ๋‚˜์˜ต๋‹ˆ๋‹ค.
return
# ๊ฐ€์žฅ ํ”ํ•œ ํ‚ค์›Œ๋“œ์˜ ๋นˆ๋„์ˆ˜๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
most_common_count = keyword_counts.most_common(1)[0][1]
# ์กฐ๊ฑด์— ๋งž๋Š” ํ‚ค์›Œ๋“œ๋“ค์„ ์ฐพ์Šต๋‹ˆ๋‹ค.
low_freq_keywords = [keyword for keyword, count in keyword_counts.items()
if keyword not in last_deep_search_keywords and keyword not in whitelist and count / most_common_count <= 0.05]
# ์ž๋™ ์ˆจ๊น€ ํ‚ค์›Œ๋“œ ์ž…๋ ฅ์ฐฝ์— ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
existing_keywords = entry_auto_hide.get().split(',')
existing_keywords = [keyword.strip() for keyword in existing_keywords if keyword.strip()] # ๊ณต๋ฐฑ ์ œ๊ฑฐ ๋ฐ ๋นˆ ๋ฌธ์ž์—ด ์ œ๊ฑฐ
# ๊ธฐ์กด ํ‚ค์›Œ๋“œ์— ์ƒˆ๋กœ์šด ์ €๋นˆ๋„ ํ‚ค์›Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
updated_keywords = existing_keywords + low_freq_keywords
unique_keywords = list(set(updated_keywords)) # ์ค‘๋ณต ์ œ๊ฑฐ
for keyword in unique_keywords:
if(keyword in afilter_30000):
unique_keywords.remove(keyword)
entry_auto_hide.delete(0, tk.END)
entry_auto_hide.insert(0, ', '.join(unique_keywords))
def copy_to_clipboard():
window.clipboard_clear()
entry_text = entry_fixed_prompt.get()
if(',' not in entry_text and entry_text): entry_text += ','
combined_text = text_output.get("1.0", tk.END)
window.clipboard_append(combined_text)
def turbo_stop(button):
global turbo_stop_bit
button.config(state=tk.DISABLED)
turbo_stop_bit = True
tprint("Stopping pipelines ... ")
window.after(20000, lambda: button_generate.config(state='normal'))
def exit_program():
global stop_event, auto_thread
if stop_event is not None:
stop_event.set()
if auto_thread is not None and auto_thread.is_alive():
auto_thread.join() # ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆผ
window.destroy()
def save_settings():
global NAI_ID
with open('app_settings.txt', 'w', encoding='utf-8') as f: #1
if(len(entry_file_path.get()) > 4):
f.write(entry_file_path.get() + '\n')
else: f.write(" "+'\n')
if(len(entry_keyword.get()) > 3): #2
f.write(entry_keyword.get() + '\n')
else: f.write(" "+'\n')
if(len(entry_deep_search.get()) > 3): #3
f.write(entry_deep_search.get() + '\n')
else: f.write(" "+'\n')
if(len(entry_fixed_prompt.get()) > 4): #4
f.write(entry_fixed_prompt.get() + '\n')
else: f.write(" "+'\n')
if(len(entry_fixed_prompt_after.get()) > 4): #5
f.write(entry_fixed_prompt_after.get() + '\n')
else: f.write(" "+'\n')
if(len(entry_auto_hide.get()) > 3): #6
f.write(entry_auto_hide.get() + '\n')
else: f.write(" "+'\n')
if(len(negative_text.get("1.0", tk.END)) > 4): #7
f.write(negative_text.get("1.0", tk.END))
else: f.write(" "+'\n')
if(NAI_ID): f.write(NAI_ID + '\n' ) #ํ•ญ์ƒ ๋งˆ์ง€๋ง‰์— ์˜ค๋„๋ก ๊ธฐ์–ต #8
def load_settings():
NAI_ID = ""
if os.path.exists('app_settings.txt'):
with open('app_settings.txt', 'r', encoding='utf-8') as f:
settings = f.readlines()
entry_file_path.insert(0, settings[0].strip())
entry_keyword.insert(0, settings[1].strip())
entry_deep_search.insert(0, settings[2].strip())
entry_fixed_prompt.insert(0, settings[3].strip())
entry_fixed_prompt_after.insert(0, settings[4].strip())
entry_auto_hide.insert(0, settings[5].strip())
if(len(settings)>=7):
negative_text.insert(tk.END, settings[6].strip())
if(len(settings)>=8):
NAI_ID = settings[7].strip() #ํ•ญ์ƒ ๋งˆ์ง€๋ง‰์— ์˜ค๋„๋ก ๊ธฐ์–ต
return NAI_ID
def open_prompt_window():
# ์ƒˆ ์ฐฝ ์ƒ์„ฑ
prompt_window = tk.Toplevel(window)
prompt_title = f"{entry_keyword.get()}+{last_deep_search_keywords}" if last_deep_search_keywords else "์ถ”์ฒœ ํ”„๋กฌํ”„ํŠธ"
prompt_window.title(prompt_title)
# ์ฒซ ๋ฒˆ์งธ Text Output Box ์„ค์ •
text_output1 = tk.Text(prompt_window, height=10, width=50)
text_output1.pack(padx=10, pady=10)
# ๊ตต์€ ๊ธ€์”จ ์Šคํƒ€์ผ ํƒœ๊ทธ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
text_output1.tag_configure('bold', font=('Arial', 10, 'bold'))
# ๋‘ ๋ฒˆ์งธ Text Output Box ์„ค์ •
text_output2 = tk.Text(prompt_window, height=10, width=50)
text_output2.pack(padx=10, pady=10)
# ์„ธ ๋ฒˆ์งธ Text Output Box ์„ค์ •
text_output3 = tk.Text(prompt_window, height=10, width=50)
text_output3.pack(padx=10, pady=10)
# cached_rows ๋ถ„์„
keyword_counts = analyze_cached_rows(cached_rows)
# ๊ฐ€์žฅ ๋†’์€ count ๊ฐ’์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
most_common_count = keyword_counts.most_common(1)[0][1] if keyword_counts else 0
# text_output1์— ๊ฐ€์žฅ ํ”ํ•œ ํ‚ค์›Œ๋“œ๋ฅผ ์ถœ๋ ฅํ•˜๊ณ , ์กฐ๊ฑด์— ๋”ฐ๋ผ ๊ตต๊ฒŒ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
for keyword, count in keyword_counts.most_common(50):
if count / most_common_count >= 0.5: # count๊ฐ€ ๊ฐ€์žฅ ๋†’์€ ํ‚ค์›Œ๋“œ ๋Œ€๋น„ 60% ์ด์ƒ์ธ ๊ฒฝ์šฐ
text_output1.insert(tk.END, f"{keyword}, ", 'bold')
else:
text_output1.insert(tk.END, f"{keyword}, ")
# text_output2์— ๋ชจ๋“  ํ‚ค์›Œ๋“œ์™€ ๋นˆ๋„์ˆ˜ ์ถœ๋ ฅ
for keyword, count in keyword_counts.most_common(200):
text_output2.insert(tk.END, f"{keyword}: {count}, ")
excluded_keywords = set(whitelist[:2974])
artist_count = 0
with open("counting_result.txt", "w") as file:
for keyword, count in sorted(keyword_counts.items(), key=lambda item: item[1], reverse=True):
if keyword not in excluded_keywords and keyword in afilter_30000:
file.write(f"{keyword}: {count}\n")
if(artist_count < 150):
text_output3.insert(tk.END, f"{keyword}: {count}, ")
artist_count += 1
# ๋‹ซ๊ธฐ ๋ฒ„ํŠผ ์„ค์ •
close_button = tk.Button(prompt_window, text="๋‹ซ๊ธฐ", command=prompt_window.destroy)
close_button.pack(pady=10)
def analyze_cached_rows(cached_rows):
global top_100_keywords
top_100_keywords = []
counts = Counter()
for row in cached_rows:
substrings = [substring.strip() for value in row for substring in value.split(',') if substring.strip()]
counts.update(substrings)
return counts
def exit_program():
save_settings()
window.destroy()
def on_ctrl_enter(event):
random_function()
def on_shift_enter(event):
random_function()
copy_to_clipboard()
def export_csv():
source_file = os.path.join(os.getcwd(), 'txt2img_temp_prompt.csv')
if not os.path.exists(source_file):
print("์†Œ์Šค ํŒŒ์ผ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")
return
# ๊ธฐ๋ณธ ํŒŒ์ผ ์ด๋ฆ„์„ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ํ‚ค์›Œ๋“œ๋กœ ์„ค์ •
default_filename = f"{entry_keyword.get()}.csv" if entry_keyword.get() else "exported.csv"
file_types = [('CSV ํŒŒ์ผ', '*.csv')]
dest_file = filedialog.asksaveasfilename(defaultextension='.csv', filetypes=file_types, initialfile=default_filename)
if dest_file: # ์‚ฌ์šฉ์ž๊ฐ€ ํŒŒ์ผ ์ด๋ฆ„์„ ์„ ํƒํ–ˆ์„ ๊ฒฝ์šฐ
import shutil
shutil.copy(source_file, dest_file)
print(f"ํŒŒ์ผ์ด ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค: {dest_file}")
def export_csv_search():
if not cached_rows:
print("๋น„์–ด์žˆ๋Š” ํ”„๋กฌํ”„ํŠธํ–‰.")
return
# ๊ธฐ๋ณธ ํŒŒ์ผ ์ด๋ฆ„์„ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ํ‚ค์›Œ๋“œ๋กœ ์„ค์ •
default_filename = f"{entry_keyword.get()}.csv" if entry_keyword.get() else "exported.csv"
file_types = [('CSV ํŒŒ์ผ', '*.csv')]
dest_file = filedialog.asksaveasfilename(defaultextension='.csv', filetypes=file_types, initialfile=default_filename)
if dest_file: # ์‚ฌ์šฉ์ž๊ฐ€ ํŒŒ์ผ ์œ„์น˜๋ฅผ ์„ ํƒํ–ˆ๋‹ค๋ฉด
with open(dest_file, 'w', newline='', encoding='utf-8') as file:
writer = csv.writer(file)
for row in cached_rows:
writer.writerow(row) # ๊ฐ ํ–‰์„ csv ํŒŒ์ผ์— ์“ด๋‹ค
def for_canonical(f):
return lambda k: f(listener.canonical(k))
# ๋ผ๋ฒจ์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•จ์ˆ˜
def update_label(label, text):
def task():
label.config(text=text)
label.after(1000, task) # ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ UI ์—…๋ฐ์ดํŠธ
def NAI_generation(width, height, button):
global access_token_multi, NAI_width, NAI_height
global button_stop, running_flag
def run_function():
time.sleep(1)
random_function()
time.sleep(2)
window.event_generate(GENERATE_EVENT, when="tail")
origin = text_output.get("1.0", tk.END)
pretest =origin.split(', ')
if (turbo_var.get() == 1):
if (('sex' not in pretest and 'group sex' not in pretest) or ('1girl' not in pretest and 'girls' not in origin[:20]) or ('1boy' not in pretest and 'boys' not in origin[:20])):
tprint('๋ถ€์ŠคํŠธ ๊ธฐ๋Šฅ์€ 1girl, 1boy, sex / boys์™€ ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค.','color=red')
if not mac_var.get():
button.config(state='normal')
return
else:
thread = threading.Thread(target=run_function)
thread.start()
return
if(rand_resolution_var.get() == 1):
resolutions = ["1024 x 1024", "960 x 1088", "896 x 1152", "832 x 1216", "1088 x 960", "1152 x 896", "1216 x 832"]
random_resolution = random.choice(resolutions)
selected_resolution.set(random_resolution)
if(turbo_var.get() == 1 and access_token):
button_stop.config(state='normal')
NAI_generation_turbo(NAI_width, NAI_height, button)
else:
if not (running_flag):
NAI_generation_normal(NAI_width, NAI_height, button)
def Auto_login_check():
global access_token, access_token_multi
if os.path.exists('token.txt'):
with open('token.txt', 'r', encoding='utf-8') as f:
tokens = f.readlines()
if(tokens[0]):
access_token = tokens[0].strip()
tprint("1 Account automatically loaded : ",access_token[-5:])
try:
if(len(tokens)>=2):
access_token_multi = tokens[1].strip()
tprint("2 Account automatically loaded : ",access_token[-5:]+", "+access_token_multi[-5:])
except:
access_token_multi = None
if(access_token): button_generate.config(state='normal')
def character_search_thread():
search_thread = threading.Thread(target=character_search, daemon=True)
search_thread.start()
def character_search():
def on_search():
# ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜
selected_indices = listbox.curselection()
if not selected_indices: # If there is no selection
print("No selection made.")
return
# Assuming the first selected index (single selection mode)
selected_index = selected_indices[0]
# Get the keyword from the listbox, split by '-', and trim whitespace
keyword_with_count = listbox.get(selected_index).strip()
keyword = keyword_with_count.split('-')[0].strip()
# Call the analyze function with the selected keyword
print(f"Analyzing keyword: {keyword}")
character, cosplay = analyze_keywords_in_data('csdataset.parquet', keyword)
character_prompt.delete('1.0', tk.END)
character_prompt.insert(tk.END, f"{', '.join(character)}")
cosplay_prompt.delete('1.0', tk.END)
cosplay_prompt.insert(tk.END, f"{', '.join(cosplay)}")
def on_key_release(event):
# Get the current search keyword
search_keyword = search_entry.get()
# Update the listbox with matching keywords
update_listbox(search_keyword)
def analyze_keywords_in_data(parquet_file, keyword):
# Parquet ํŒŒ์ผ ์ฝ๊ธฐ
df = pd.read_parquet(parquet_file)
bag_of_tags = ['penis', 'character name', 'upper body', 'full body', 'artist name', 'male focus', 'open mouth', 'mature male', 'muscular', 'muscular male', 'closed mouth','closed eyes','1girl', '1boy', '1other', 'white background', 'solo', 'breasts', 'simple background', 'smile', 'looking at viewer', 'flat chest', 'small breasts', 'medium breasts', 'large breasts', 'huge breasts','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', 'heterochromia', 'multicolored eyes', 'aqua pupils', 'blue pupils', 'brown pupils', 'green pupils', 'grey pupils', 'orange pupils', 'pink pupils', 'purple pupils', 'red pupils', 'white pupils', 'yellow pupils', 'pointy ears', 'long pointy ears', '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', 'multicolored hair', 'colored inner hair', 'colored tips', 'roots (hair)', 'gradient hair', 'print hair', 'rainbow hair', 'split-color hair', 'spotted hair', 'streaked hair', 'two-tone hair', 'very short hair', 'short hair', 'medium hair', 'long hair', 'very long hair', 'absurdly long hair', 'big hair', 'bald', 'bald girl', 'bob cut', 'inverted bob', 'bowl cut', 'buzz cut', 'chonmage', 'crew cut', 'flattop', 'okappa', 'pixie cut', 'undercut', 'flipped hair', 'wolf cut', 'cornrows', 'dreadlocks', 'hime cut', 'mullet', 'bow-shaped hair', 'braid', 'braided bangs', 'front braid', 'side braid', 'french braid', 'crown braid', 'single braid', 'multiple braids', 'twin braids', 'low twin braids', 'tri braids', 'quad braids', 'flower-shaped hair', 'hair bun', 'braided bun', 'single hair bun', 'double bun', 'cone hair bun', 'doughnut hair bun', 'heart hair bun', 'triple bun', 'cone hair bun', 'hair rings', 'single hair ring', 'half updo', 'one side up', 'two side up', 'low-braided long hair', 'low-tied long hair', 'mizura', 'multi-tied hair', 'nihongami', 'ponytail', 'folded ponytail', 'front ponytail', 'high ponytail', 'short ponytail', 'side ponytail', 'split ponytail', 'star-shaped hair', 'topknot', 'twintails', 'low twintails', 'short twintails', 'uneven twintails', 'tri tails', 'quad tails', 'quin tails', 'twisted hair', 'afro', 'huge afro', 'beehive hairdo', 'crested hair', 'pompadour', 'quiff', 'shouten pegasus mix mori', 'curly hair', 'drill hair', 'twin drills', 'tri drills', 'hair flaps', 'messy hair', 'pointy hair', 'ringlets', 'spiked hair', 'straight hair', 'wavy hair', 'bangs', 'arched bangs', 'asymmetrical bangs', 'bangs pinned back', 'blunt bangs', 'crossed bangs', 'diagonal bangs', 'dyed bangs', 'fanged bangs', 'hair over eyes', 'hair over one eye', 'long bangs', 'parted bangs', 'curtained hair', 'ribbon bangs', 'short bangs', 'swept bangs', 'hair between eyes', 'hair intakes', 'single hair intake', 'sidelocks', 'asymmetrical sidelocks', 'drill sidelocks', 'low-tied sidelocks', 'sidelocks tied back', 'single sidelock', 'ahoge', 'heart ahoge', 'huge ahoge', 'antenna hair', 'heart antenna hair', 'comb over', 'hair pulled back', 'hair slicked back', 'mohawk', 'oseledets', 'lone nape hair', 'hair bikini', 'hair censor', 'hair in own mouth', 'hair over breasts', 'hair over one breast', 'hair over crotch', 'hair over shoulder', 'hair scarf', 'alternate hairstyle', 'hair down', 'hair up', 'asymmetrical hair', 'sidecut', 'blunt ends', 'dark skin', 'dark-skinned female', 'pale skin', 'sun tatoo', 'black skin', 'blue skin', 'green skin', 'grey skin', 'orange skin', 'pink skin', 'purple skin', 'red skin', 'white skin', 'yellow skin', 'colored skin', 'multiple tails', 'demon tail', 'dragon tail', 'ghost tail', 'pikachu tail', 'snake head tail', 'fiery tail', 'bear tail', 'rabbit tail', 'cat tail', 'cow tail', 'deer tail', 'dog tail', 'ermine tail', 'fox tail', 'horse tail', 'leopard tail', 'lion tail', 'monkey tail', 'mouse tail', 'pig tail', 'sheep tail', 'squirrel tail', 'tiger tail', 'wolf tail', 'crocodilian tail', 'fish tail', 'scorpion tail', 'snake tail', 'tadpole tail']
mini_bag_of_tags = ['penis', 'character name', 'upper body', 'full body', 'artist name', 'male focus', 'open mouth', 'mature male', 'muscular', 'muscular male', 'closed mouth','closed eyes','1girl', '1boy', '1other', 'white background', 'solo', 'breasts', 'simple background', 'smile', 'looking at viewer']
# 'character' ์—ด์—์„œ keyword์— ํ•ด๋‹นํ•˜๋Š” ํ–‰๋งŒ ํ•„ํ„ฐ๋ง
filtered_df = df[df['character'] == keyword]
filtered_df = filtered_df[~filtered_df['character'].str.contains(',', na=False)]
if filtered_df.empty:
filtered_df = df[df['character'].str.contains(keyword, na=False, regex=False)]
filtered_df = filtered_df[~(filtered_df['rating'] == 'e')]
print(len(filtered_df))
# keyword:count ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ ์ง‘๊ณ„ํ•  ๋”•์…”๋„ˆ๋ฆฌ ์ƒ์„ฑ
keyword_count_dict = {}
# ๊ฐ ํ–‰์˜ 'general' ์—ด ์ฒ˜๋ฆฌ
for general in filtered_df['general']:
# ๋ฌธ์ž์—ด ๋ถ„ํ• 
tags = [tag.strip() for tag in general.split(',')]
# ๋”•์…”๋„ˆ๋ฆฌ์— ๊ฐ ํƒœ๊ทธ์˜ count ์ถ”๊ฐ€
for tag in tags:
keyword_count_dict[tag] = keyword_count_dict.get(tag, 0) + 1
# ํŠน์ • ํ‚ค์›Œ๋“œ ์ œ์™ธ
exclude_keywords = bag_of_tags
keyword_count_dict1 = keyword_count_dict.copy()
keyword_count_dict1 = {k: v for k, v in keyword_count_dict1.items() if k not in mini_bag_of_tags}
keyword_count_dict = {k: v for k, v in keyword_count_dict.items() if k not in exclude_keywords}
# ๊ฐ€์žฅ ๋†’์€ count ๊ฐ’ ์ฐพ๊ธฐ
highest_count = max(keyword_count_dict.values()) if keyword_count_dict else 0
highest_count1 = max(keyword_count_dict1.values()) if keyword_count_dict1 else 0
if(len(filtered_df)) < 10:
weight = 0.6
elif(len(filtered_df)) < 30:
weight = 0.5
elif(len(filtered_df)) < 80:
weight = 0.45
elif(len(filtered_df)) < 160:
weight = 0.35
elif(len(filtered_df)) < 280:
weight = 0.3
else:
weight = 0.2
result_list = []
result_list1 = []
# count๊ฐ€ highest_count*0.4 ์ด์ƒ์ธ ํ‚ค์›Œ๋“œ ์ถœ๋ ฅ
for k, v in keyword_count_dict.items():
if '|' in k: continue
if v >= highest_count * weight:
result_list.append(k)
for k, v in keyword_count_dict1.items():
if '|' in k: continue
if v >= highest_count1 * weight:
result_list1.append(k)
result_list1.insert(0, keyword)
result_list.insert(0, "["+keyword+" (cosplay)]")
return result_list1, result_list
def update_listbox(search_keyword):
# Clear the listbox
listbox.delete(0, tk.END)
# Check if the search keyword is not empty
if search_keyword:
# Find matching keywords in the dictionary
# Sort them by count in descending order
matching_keywords = sorted(
((k, v) for k, v in cd.character_dictionary.items() if search_keyword.lower() in k.lower()),
key=lambda item: item[1],
reverse=True
)
# Insert the matching keywords into the listbox
for keyword, count in matching_keywords:
listbox.insert(tk.END, f"{keyword} - {count}")
else:
# Sort all keywords by count in descending order
all_keywords = sorted(cd.character_dictionary.items(), key=lambda item: item[1], reverse=True)
for keyword, count in all_keywords:
listbox.insert(tk.END, f"{keyword} - {count}")
# ๋ฉ”์ธ ์œˆ๋„์šฐ ์ƒ์„ฑ
ch_search_window = tk.Toplevel(window)
ch_search_window.title("์บ๋ฆญํ„ฐ ๊ฒ€์ƒ‰")
# ํ”„๋ ˆ์ž„ ์ƒ์„ฑ (left, center, right)
left_frame = tk.Frame(ch_search_window)
center_frame = tk.Frame(ch_search_window)
right_frame = tk.Frame(ch_search_window)
# ํ”„๋ ˆ์ž„ ๋ฐฐ์น˜
left_frame.grid(row=0, column=0, sticky="nsew")
center_frame.grid(row=0, column=1, sticky="ns")
right_frame.grid(row=0, column=2, sticky="nsew")
# left_frame ๋‚ด๋ถ€ ๊ตฌ์„ฑ
search_label = tk.Label(left_frame, text="๊ฒ€์ƒ‰ ํ•˜๋ ค๋Š” ์บ๋ฆญํ„ฐ:")
search_label.grid(row=0, column=0, padx=10, pady=5, sticky="ew")
search_entry = tk.Entry(left_frame, width=35)
search_entry.grid(row=1, column=0, padx=10, pady=5, sticky="ew")
search_entry.bind("<KeyRelease>", on_key_release)
result_label = tk.Label(left_frame, text="๋งค์นญ ์บ๋ฆญํ„ฐ:")
result_label.grid(row=2, column=0, padx=10, pady=5, sticky="ew")
listbox = tk.Listbox(left_frame)
listbox.grid(row=3, column=0, padx=10, pady=5, sticky="nsew")
# center_frame ๋‚ด๋ถ€ ๊ตฌ์„ฑ
search_button = tk.Button(center_frame, text="๊ฒ€์ƒ‰", command=on_search)
search_button.grid(row=2, column=0, rowspan=4, padx=10, pady=175)
def character_prompt_auto_insert():
selected_indices = listbox.curselection()
if not selected_indices: # If there is no selection
print("No selection made.")
return
# Assuming the first selected index (single selection mode)
selected_index = selected_indices[0]
# Get the keyword from the listbox, split by '-', and trim whitespace
keyword_with_count = listbox.get(selected_index).strip()
keyword = keyword_with_count.split('-')[0].strip()
prompt = character_prompt.get("1.0", tk.END).replace(keyword+',','')
if(len(prompt) > 8):
text_output.delete('1.0', tk.END)
entry_prompt = entry_fixed_prompt.get().replace('1girl', f'1girl, {keyword}')
result_text = entry_prompt+", "+prompt[:-2]+", "+entry_fixed_prompt_after.get()
text_output.insert(tk.END, result_text)
return (len(prompt) > 8)
def character_prompt_auto_generate():
global running_flag
if(character_prompt_auto_insert() and not running_flag):
window.event_generate(GENERATE_EVENT, when="tail")
def character_cosplay_auto_insert():
prompt = cosplay_prompt.get("1.0", tk.END)
if(len(prompt) > 8):
text_output.delete('1.0', tk.END)
result_text = entry_fixed_prompt.get()+", "+prompt[:-2]+", "+entry_fixed_prompt_after.get()
text_output.insert(tk.END, result_text)
return (len(prompt) > 8)
def character_cosplay_auto_generate():
if(character_cosplay_auto_insert() and not running_flag):
window.event_generate(GENERATE_EVENT, when="tail")
def wildcard_insertion():
global bag_of_tags, character_wildcard_saved
text = character_prompt.get("1.0", tk.END).split(',')
text_list = [keyword.strip() for keyword in text]
charactersitics = []
count = 0
for texts in text_list:
if count < 4 and texts in bag_of_tags[5:] and 'tail' not in texts and 'pupil' not in texts:
charactersitics.append(texts)
count += 1
keyword = text_list[0]
character_wildcard_saved.append('100:{{'+keyword+', '+', '.join(charactersitics)+'}}')
character_prompt.insert(tk.END, '\n์ €์žฅ๋œ ์™€์ผ๋“œ์นด๋“œ : 100:{{'+keyword+', '+', '.join(charactersitics)+'}} ํƒ‘์žฌ๋Š” ๋”ฐ๋กœ ํ•œ๋ฒˆ ๋” ํ•ด์ฃผ์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค.')
# right_frame ๋‚ด๋ถ€ ๊ตฌ์„ฑ
character_prompt_frame = tk.Frame(right_frame)
character_prompt_frame.grid(row=0, column=0, padx=10, pady=5, sticky="ew")
prompt_label = tk.Label(character_prompt_frame, text="์บ๋ฆญํ„ฐ ํ”„๋กฌํ”„ํŠธ:")
prompt_label.grid(row=0, column=0, padx=10, pady=5, sticky="ew")
character_prompt_insert = tk.Button(character_prompt_frame, text="์ž๋™์ž…๋ ฅ", command=character_prompt_auto_insert)
character_prompt_insert.grid(row=0, column=1, padx=10, pady=5, sticky="ew")
character_prompt_generate = tk.Button(character_prompt_frame, text="์ฆ‰์‹œ์ƒ์„ฑ", command=character_prompt_auto_generate)
character_prompt_generate.grid(row=0, column=2, padx=10, pady=5, sticky="ew")
character_prompt_wildcard = tk.Button(character_prompt_frame, text="์™€์ผ๋“œ์นด๋“œ ์‚ฝ์ž…", command=wildcard_insertion)
character_prompt_wildcard.grid(row=0, column=3, padx=10, pady=5, sticky="ew")
character_prompt = tk.Text(right_frame, height=10)
character_prompt.grid(row=1, column=0, padx=10, pady=5, sticky="nsew")
#row=3, column=0, padx=10, pady=5, sticky="nsew"
character_cosplay_frame = tk.Frame(right_frame)
character_cosplay_frame.grid(row=2, column=0, padx=10, pady=5, sticky="ew")
cosplay_label = tk.Label(character_cosplay_frame, text="์บ๋ฆญํ„ฐ (Cosplay):")
cosplay_label.grid(row=0, column=0, padx=10, pady=5, sticky="ew")
character_cosplay_insert = tk.Button(character_cosplay_frame, text="์ž๋™์ž…๋ ฅ", command=character_cosplay_auto_insert)
character_cosplay_insert.grid(row=0, column=1, padx=10, pady=5, sticky="ew")
character_prompt_generate = tk.Button(character_cosplay_frame, text="์ฆ‰์‹œ์ƒ์„ฑ", command=character_cosplay_auto_generate)
character_prompt_generate.grid(row=0, column=2, padx=10, pady=5, sticky="ew")
cosplay_prompt = tk.Text(right_frame, height=10)
cosplay_prompt.grid(row=3, column=0, padx=10, pady=5, sticky="ew")
# ๊ฐ€์ค‘์น˜ ์„ค์ •
left_frame.grid_rowconfigure(0, weight=1)
left_frame.grid_rowconfigure(1, weight=1)
left_frame.grid_rowconfigure(2, weight=1)
left_frame.grid_rowconfigure(3, weight=7)
right_frame.grid_rowconfigure(0, weight=1)
right_frame.grid_rowconfigure(1, weight=4)
right_frame.grid_rowconfigure(2, weight=1)
right_frame.grid_rowconfigure(3, weight=4)
# ์œˆ๋„์šฐ ๊ฐ€์ค‘์น˜ ์„ค์ •
ch_search_window.grid_columnconfigure(0, weight=3, minsize=250) # left_frame
ch_search_window.grid_columnconfigure(1, weight=1) # center_frame
ch_search_window.grid_columnconfigure(2, weight=6) # right_frame
all_keywords = sorted(cd.character_dictionary.items(), key=lambda item: item[1], reverse=True)
for keyword, count in all_keywords:
listbox.insert(tk.END, f"{keyword} - {count}")
def NAI_generation_normal(width, height, button):
button.config(state=tk.DISABLED)
positive = text_output.get("1.0", tk.END)
negative = negative_text.get("1.0", "end-1c").strip()
global auto_count_left_flag, auto_count_left
if(auto_count_left_flag and auto_count_left > 0):
auto_count_left -= 1
thread = threading.Thread(target=generate, args=(width, height, positive, negative, button))
thread.start()
def NAI_generation_turbo(width, height, button):
global turbo_count, access_token, access_token_multi
button.config(state=tk.DISABLED)
positive = text_output.get("1.0", tk.END)
negative = negative_text.get("1.0", "end-1c").strip()
def SELECT(positive):
lines = positive
result = {
"boys": False,
"girls": False,
"1girl": False,
"1boy": False,
"1other": False,
"others": False
}
state = {
"nude,": False,
"pov,": False,
"cum,": False,
"after ": False,
"pussy juice": False,
"barefoot": False,
"breasts": False,
"ejaculation": False,
}
def insert_spaces(source_list, reference_list):
modified_list = source_list.copy()
for index, keyword in enumerate(reference_list):
if keyword not in source_list:
space_count = len(keyword) # ํ‚ค์›Œ๋“œ ๊ธธ์ด๋งŒํผ์˜ ๊ณต๋ฐฑ ๋ฌธ์ž
modified_list.insert(index, ' ' * space_count)
return modified_list
keywords = positive.split(', ')
filtered_keywords = []
removed_indices = []
positive0, positive1, positive2, positive3 = None, None, None, None
for word in result.keys():
if word in lines:
result[word] = True
for word in state.keys():
if word in positive:
state[word] = True
key_index = int((len(keywords)/2)-1)
global bag_of_tags
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']
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']
if not wildcard_var2.get() and not rm_characteristic_var.get():
key_features = []
for tag in bag_of_tags:
if tag in keywords:
key_features.append(tag)
keywords.remove(tag)
if not any(color in key_features for color in eye_color): key_features.append(random.choice(eye_color))
if not any(color in key_features for color in hair_color): key_features.append(random.choice(hair_color))
key_feature = "{" +' ,'.join(key_features) + "}"
keywords.insert(2, key_feature)
if(result["1boy"]) or (result["boys"]):
if(result["1girl"]):
if('sex,' in positive):
sex_pos_keywords = ['stomach bulge','insertion', 'fucked silly', 'x-ray', 'orgasm', 'cross-section', 'uterus', 'overflow', 'rape', 'vaginal', 'anal']
facial_keywords = ['tongue','ahegao']
temp_sex_pos = []
temp_facial = []
cum_events = []
explicit_check = []
if 'open mouth' in keywords: keywords.remove('open mouth')
if 'closed mouth' in keywords: keywords.remove('closed mouth')
if 'after rape' in keywords:
keywords.remove('after rape')
explicit_check.append('after rape')
for keyword in keywords:
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):
filtered_keywords.append(keyword)
elif 'sex' in keyword:
removed_indices.append(keyword)
elif 'penetration' in keyword:
removed_indices.append(keyword)
elif 'cum' in keyword and keyword != 'cum':
cum_events.append(keyword)
elif any(sex_pos in keyword for sex_pos in sex_pos_keywords):
for sex_pos in sex_pos_keywords:
if sex_pos in keyword:
temp_sex_pos.append(sex_pos)
elif any(facial not in keyword for facial in facial_keywords):
for facial in facial_keywords:
if facial in keyword:
temp_facial.append(facial)
filtered_keywords.insert(int((len(filtered_keywords)/2)-1), ' no penetration, imminent penetration')
filtered_keywords_positive0 = filtered_keywords.copy()
filtered_keywords.remove(' no penetration, imminent penetration')
#0 imminent penetration, imminent sex
for i, keyword in enumerate(filtered_keywords):
if 'pantyhose' in keyword:
filtered_keywords[i] = 'torn ' + filtered_keywords[i]
#1 default
key_index = int((len(filtered_keywords)/2)-1)
if 'pussy' in filtered_keywords: key_index = filtered_keywords.index('pussy')
if 'penis' in filtered_keywords: key_index = filtered_keywords.index('penis')
filtered_keywords[key_index:key_index] = ['motion lines', 'surprised']
for keyword in removed_indices:
if 'cum' not in keyword and 'ejaculation' not in keyword:
filtered_keywords.insert(key_index,keyword)
if(temp_sex_pos): filtered_keywords[key_index:key_index] = temp_sex_pos
if('clothed sex' in filtered_keywords and not 'bottomless' in filtered_keywords): filtered_keywords.insert(filtered_keywords.index('clothed sex')+1, 'bottomless')
pos1_copied_keywords = filtered_keywords.copy()
for i, keyword in enumerate(pos1_copied_keywords):
if 'closed eyes' in keyword:
rand_num = random.randint(0,2)
if(rand_num == 0): pos1_copied_keywords[i] = 'half-' + pos1_copied_keywords[i]
elif(rand_num == 1 and 'closed eyes' in pos1_copied_keywords):
pos1_copied_keywords.remove('closed eyes')
filtered_keywords[i] = 'half-closed eyes'
filtered_keywords_positive1 = pos1_copied_keywords.copy()
#2 ejaculation,cum in pussy
key_index = filtered_keywords.index('surprised')
filtered_keywords.remove('surprised')
filtered_keywords[key_index:key_index] = ["ejaculation","cum"]
for keyword in removed_indices:
if 'cum' in keyword:
filtered_keywords.insert(key_index,keyword)
if(temp_facial): filtered_keywords[key_index:key_index] =temp_facial
filtered_keywords_positive2 = filtered_keywords.copy()
#3 after sex, after ejaculation
for i, keyword in enumerate(filtered_keywords):
if 'closed eyes' in keyword:
rand_num = random.randint(0,2)
if(rand_num == 0 and filtered_keywords[i] != 'half-closed eyes'): filtered_keywords[i] = 'half-' + filtered_keywords[i]
elif(rand_num == 1): filtered_keywords[i] = 'empty eyes'
else: filtered_keywords[i] = 'empty eyes, half-closed eyes'
if 'sex' in filtered_keywords:
key_index = filtered_keywords.index('sex')
elif 'group sex' in filtered_keywords:
key_index = filtered_keywords.index('group sex')
filtered_keywords.remove('ejaculation')
filtered_keywords[key_index:key_index] = ['cum drip', 'erection'] + cum_events
if(explicit_check): filtered_keywords[key_index:key_index] = explicit_check
if 'sex' in filtered_keywords and 'group sex' not in filtered_keywords:
if('pussy' in filtered_keywords and not 'anal' in filtered_keywords): filtered_keywords.insert(filtered_keywords.index('sex')+1, 'after vaginal, spread pussy')
elif('anal' in filtered_keywords): filtered_keywords.insert(filtered_keywords.index('sex')+1, 'after anus, cum in ass')
filtered_keywords.insert(filtered_keywords.index('sex'), 'after sex')
filtered_keywords.remove('sex')
elif 'group sex' in filtered_keywords:
if('vaginal' in filtered_keywords and not 'anal' in filtered_keywords):
filtered_keywords.insert(filtered_keywords.index('group sex')+1, 'after vaginal, spread pussy')
if 'multiple penises' in filtered_keywords: filtered_keywords.insert(filtered_keywords.index('group sex')+3, 'cum on body, bukkake')
elif('anal' in filtered_keywords):
filtered_keywords.insert(filtered_keywords.index('group sex')+1, 'after anus, cum in ass')
if 'multiple penises' in filtered_keywords: filtered_keywords.insert(filtered_keywords.index('group sex')+3, 'cum on body, bukkake')
else: filtered_keywords.insert(filtered_keywords.index('group sex')+1, 'cum on body, {bukkake}')
temp_post_keyword = []
for keyword in sex_pos_keywords:
if not (keyword == 'orgasm' or keyword == 'overflow'):
if keyword in filtered_keywords:
temp_post_keyword.append(keyword)
for keyword in temp_post_keyword:
filtered_keywords.remove(keyword)
positive0 = ', '.join(insert_spaces(filtered_keywords_positive0, filtered_keywords)).strip()
print("round 1 : ",positive0)
positive1 = ', '.join(insert_spaces(filtered_keywords_positive1, filtered_keywords)).strip()
print("round 2 : ",positive1)
positive2 = ', '.join(insert_spaces(filtered_keywords_positive2, filtered_keywords)).strip()
print("round 3 : ",positive2)
positive3 = ', '.join(filtered_keywords).strip()
print("round 4 : ",positive3)
elif(', penis' in positive):
if(', oral' in positive):
pass
elif(', paizuri' in positive):
pass
elif('job,' in positive):
if('handjob' in positive):
pass
elif('footjob' in positive):
pass
return positive0, positive1, positive2, positive3
positive0, positive1, positive2, positive3 = SELECT(text_output.get("1.0", tk.END));
if not hold_seed_var.get(): seed = random.randint(0,9999999999)
else: seed = last_generation_seed
sleep0 = random.uniform(13.5,19.5)
sleep1 = sleep0 + random.uniform(13.5,19.5)
sleep2 = sleep1 + random.uniform(13.5,19.5)
sleep3 = sleep2 + random.uniform(13.5,19.5)
global auto_count_left_flag, auto_count_left, turbo_stop_bit
if(auto_count_left_flag and auto_count_left > 0):
auto_count_left -= 5
thread_init = threading.Thread(target=generate_turbo, args=(seed,turbo_count, access_token, width, height, positive, negative, button, 0, 0))
thread_init.start()
thread0 = threading.Thread(target=generate_turbo, args=(seed,turbo_count, access_token, width, height, positive0, negative, button, 1, sleep0))
thread0.start()
thread1 = threading.Thread(target=generate_turbo, args=(seed,turbo_count, access_token, width, height, positive1, negative, button, 2, sleep1))
thread1.start()
thread2 = threading.Thread(target=generate_turbo, args=(seed,turbo_count, access_token, width, height, positive2, negative, button, 3, sleep2))
thread2.start()
thread3 = threading.Thread(target=generate_turbo, args=(seed,turbo_count, access_token, width, height, positive3, negative, button, 4, sleep3))
thread3.start()
turbo_count += 1
def generate_turbo(_seed, turbo_count, tb_access_token,width, height, positive, negative, button, pipe_number, sleeptime):
global temp_clipboard_image
global current_sampler
global NAI_width, NAI_height
global running_flag
global image_queue
global turbo_stop_bit
global task_finished
if(pipe_number == 0): image_queue.clear()
try:
scale = float(entry_CFG_value.get())
except:
scale = 5.0
if scale > 7.0: scale = 7.0
elif scale < 4.0: scale = 4.0
else: scale = round(scale, 1)
try:
scale2 = float(entry_rescale_value.get())
except:
scale2 = 0
if scale2 > 1.00: scale = 1.00
elif scale2 < 0.0: scale = 0.00
else: scale2 = round(scale2, 2)
params = {
"legacy": False,
"quality_toggle": False,
"width": width,
"height": height,
"n_samples": 1,
"seed": _seed,
"extra_noise_seed": random.randint(0,9999999999),
"sampler": current_sampler,
"steps": 28,
"scale": scale,
"uncond_scale": 1.0,
"negative_prompt": negative,
"sm" : sema_button_var.get(),
"sm_dyn" : dyn_button_var.get(),
"decrisper": False,
"controlnet_strength": 1.0,
"add_original_image": False,
"cfg_rescale": scale2,
"noise_schedule": "native",
}
if (hold_seed_var.get()):
global last_generation_seed
params['seed'] = last_generation_seed
def merge_images(image_queue):
if len(image_queue) < 4:
return None # ์ด๋ฏธ์ง€๊ฐ€ 4๊ฐœ ๋ฏธ๋งŒ์ธ ๊ฒฝ์šฐ None์„ ๋ฐ˜ํ™˜
# ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๋ฅผ ๋™์ผํ•˜๊ฒŒ ์กฐ์ •
# ์˜ˆ์‹œ๋ฅผ ์œ„ํ•ด ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”์— ๋”ฐ๋ผ ์ˆ˜์ • ๊ฐ€๋Šฅ
width, height = image_queue[0].size
new_image = Image.new('RGB', (width * 2, height * 2))
# ์ด๋ฏธ์ง€ ์œ„์น˜ ๋งคํ•‘
positions = [(0, 0), (width, 0), (0, height), (width, height)]
# ์ด๋ฏธ์ง€ ๋ณ‘ํ•ฉ
for i, img in enumerate(image_queue):
pos = positions[i]
new_image.paste(img, pos)
return new_image
def insert_queue(i, _number, turbo_count):
global image_queue, temp_clipboard_image
while len(image_queue) < 4: image_queue.append(None)
if _number <= 4:
image_queue[_number-1] = i.copy()
i_resized = resize_and_fill(i)
box_position = (i_resized.width - 25, 10)
draw = ImageDraw.Draw(i_resized)
draw.rectangle([box_position, (box_position[0] + 25, box_position[1] + 25)], fill="black")
font = ImageFont.load_default()
text_position = (box_position[0] + 12, box_position[1] + 12) # ํ…์ŠคํŠธ ์œ„์น˜ ์กฐ์ •
draw.text(text_position, str(_number), fill="white", font=font)
if 'tk_image' in globals():
globals()['tk_image'] = None
tk_image = ImageTk.PhotoImage(i_resized)
image_label.config(image=tk_image)
image_label.original_image = i.copy()
image_label.image = tk_image # ์ฐธ์กฐ ์œ ์ง€
history_queue(i_resized.copy(), positive, params['seed'])
if all(img is not None for img in image_queue):
time.sleep(5)
merged_image = merge_images(image_queue)
temp_clipboard_image = merged_image.copy()
if merged_image is not None:
output_directory = Path(f"output_NAI/{start_time}/turbo/grid")
output_directory.mkdir(parents=True, exist_ok=True)
file_path = output_directory / f"{turbo_count:05}.png"
merged_image.save(file_path)
i_resized = resize_and_fill(merged_image)
if 'tk_image' in globals():
globals()['tk_image'] = None
tk_image = ImageTk.PhotoImage(i_resized)
image_label.config(image=tk_image)
image_label.original_image = i_resized.copy()
image_label.image = tk_image # ์ฐธ์กฐ ์œ ์ง€
output_file_path = "output_image.jpg"
merged_image.save(output_file_path)
image_queue = [] # ์ด๋ฏธ์ง€ ํ ์ดˆ๊ธฐํ™”
def resize_and_fill(image, max_size=None):
if max_size is None:
max_size = get_max_size()
original_width, original_height = image.size
if original_width > max_size or original_height > max_size:
# ๋น„์œจ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ํฌ๊ธฐ ์กฐ์ •
image.thumbnail((max_size, max_size))
# ์ƒˆ ์ด๋ฏธ์ง€ ํฌ๊ธฐ ๊ณ„์‚ฐ
width, height = image.size
new_image = Image.new("RGB", (max_size, max_size), "black")
new_image.paste(image, ((max_size - width) // 2, (max_size - height) // 2))
return new_image
else:
return image
def log_error(e, output_file_path="output_file_path"):
# ํ˜„์žฌ ์‹œ๊ฐ„์„ ์–ป์Šต๋‹ˆ๋‹ค
current_time = datetime.now().strftime("%m/%d %H:%M:%S")
# ์—๋Ÿฌ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€
error_message = f"#### Error occured at {current_time} ####\nError: {e}\n############################################\n"
# ์ง€์ •๋œ ์ถœ๋ ฅ ํด๋”์˜ error_log.txt ํŒŒ์ผ์— ์“ฐ๊ธฐ
with open(f"error_log.txt", "a") as file:
file.write(error_message)
if(pipe_number != 0):
pipe_start_time = time.time()
while time.time() - pipe_start_time < sleeptime:
if(turbo_stop_bit):
return
time.sleep(1)
while running_flag:
time.sleep(1)
print('running_flag : ',running_flag,'pipe_number : ',pipe_number, ' : already running ')
if(turbo_stop_bit):
return
print('containing : ',pipe_number)
running_flag = True
tprint("Running : request received, pipeline : "+str(pipe_number))
global error_count
try:
zipped_bytes = generate_image(tb_access_token, positive, "nai-diffusion-3", "generate", params)
if(pipe_number != 0):
d = Path(f"output_NAI/{start_time}/turbo")
d.mkdir(parents=True, exist_ok=True)
else:
d = Path(f"output_NAI/{start_time}/turbo/preprocessing")
d.mkdir(parents=True, exist_ok=True)
zipped = zipfile.ZipFile(io.BytesIO(zipped_bytes))
image_bytes = zipped.read(zipped.infolist()[0])
(d / f"{turbo_count:05}_{pipe_number}.png" ).write_bytes(image_bytes)
i = Image.open(io.BytesIO(image_bytes))
i = ImageOps.exif_transpose(i).convert("RGB")
error_count = 0
if(pipe_number != 0):
if temp_clipboard_image is not None:
temp_clipboard_image.close()
if(pipe_number == 1 and len(image_queue) < 4): image_queue.clear()
temp_clipboard_image = i
insert_queue(i, pipe_number, turbo_count)
tprint("image inserted, pipe number : "+str(pipe_number))
else:
if temp_clipboard_image is not None:
temp_clipboard_image.close()
temp_clipboard_image = i
i_resized = resize_and_fill(i)
if 'tk_image' in globals():
globals()['tk_image'] = None
tk_image = ImageTk.PhotoImage(i_resized)
image_label.config(image=tk_image)
image_label.original_image = i.copy()
image_label.image = tk_image # ์ฐธ์กฐ ์œ ์ง€
except Exception as e:
#text_output.insert(tk.END, f"Error: {e}", fg='red')
log_error(zipped_bytes.decode('utf-8')[2:-2], "path_to_output_folder")
error_count += 1
if error_count > 5:
mac_var.set(0)
time.sleep(random.uniform(3.0, 9.0))
insert_queue(temp_clipboard_image, pipe_number, turbo_count)
task_finished += 1 #ํ„ฐ๋ณด ๊ธฐ๋Šฅ์˜ ์•ˆ์ „์žฅ์น˜์ž…๋‹ˆ๋‹ค.
time.sleep(random.uniform(3.0, 5.5))
if(pipe_number == 4): button.config(state=tk.NORMAL)
running_flag = False
last_generation_seed = params['seed']
entry_seed_value.set(last_generation_seed)
global delay_offset
time.sleep(delay_offset)
stopped = False
if (turbo_stop_bit):
time.sleep(1.5)
turbo_stop_bit = False
button.config(state=tk.NORMAL)
stopped = True
if (pipe_number != 4):
tprint("Stopped : request stopped before assign pipeline :"+str(pipe_number+1))
if pipe_number == 4 and mac_var.get():
wait_limit = 0
while(task_finished < 5 and wait_limit < 20):
wait_limit += 1
print(f"Wait other pipeline ... : ({wait_limit}/20)")
time.sleep(3)
if(wait_limit == 20):
print(f"Process : {turbo_count} request time-out")
task_finished = 0
else:
task_finished = 0
running_flag = False
random_function()
time.sleep(random.uniform(2.1, 5.5))
if not (turbo_stop_bit):
button.config(state=tk.DISABLED)
window.event_generate(GENERATE_EVENT, when="tail")
else:
turbo_stop_bit = False
if(mac_var.get() and not running_flag):
button.config(state=tk.DISABLED)
window.event_generate(GENERATE_EVENT, when="tail")
else:
if(pipe_number == 4):
global button_stop
button_stop.config(state='disabled')
tprint('state : idle')
def NAI_setting(button, button_generate):
global NAI_ID
NAI_setting_window = tk.Toplevel(window)
NAI_setting_window_title = "NAI ๋กœ๊ทธ์ธ"
def NAI_close():
NAI_setting_window.destroy()
def NAI_token_save(button):
global access_token
with open('token.txt', 'w', encoding='utf-8') as f:
f.write(access_token)
NAI_State_label.config(text="(ํ”„๋กœ๊ทธ๋žจ ๊ฒฝ๋กœ์— token.txt๊ฐ€ ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.)", fg="blue")
button.config(state=tk.DISABLED)
def NAI_connect(button, connect_button, token_button):
global access_token, NAI_ID
username = entry_NAI_ID.get().strip()
password = entry_NAI_PW.get().strip()
access_key = get_access_key(username, password)
try:
access_token = login(access_key)
access_result = requests.get("https://api.novelai.net/user/information", headers={ "Authorization": f"Bearer {access_token}" })
NAI_State_label.config(text="(๋กœ๊ทธ์ธ ์„ฑ๊ณต, ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”.)", fg="blue")
button.config(state=tk.DISABLED)
button_generate.config(state="normal")
connect_button.config(state=tk.DISABLED)
NAI_ID = username
token_button.config(state=tk.NORMAL)
except Exception as e:
print(e)
NAI_close()
button_frame0 = tk.Frame(NAI_setting_window)
button_frame0.grid(row=0, padx=5, pady=5, sticky='ew')
button_frame1 = tk.Frame(button_frame0)
button_frame1.grid(row=0, padx=5, pady=5, sticky='ew')
button_frame1.columnconfigure(0, weight=1)
button_frame1.columnconfigure(1, weight=3)
button_frame1.columnconfigure(2, weight=3)
button_frame1.columnconfigure(3, weight=1)
NAI_ID_label = tk.Label(button_frame1, text="NAI ID: ")
NAI_ID_label.grid(row=0, column=0, sticky='ew')
entry_NAI_ID = tk.Entry(button_frame1)
entry_NAI_ID.grid(row=0, column=1, columnspan=3, padx=5, pady=5, sticky='ew')
if(NAI_ID): entry_NAI_ID.insert(tk.END,NAI_ID)
NAI_PW_label = tk.Label(button_frame1, text="NAI PW: ")
NAI_PW_label.grid(row=1, column=0,sticky='ew')
entry_NAI_PW = tk.Entry(button_frame1, show="*")
entry_NAI_PW.grid(row=1, column=1, columnspan=3,padx=5, pady=5, sticky='ew')
token_output = tk.Button(button_frame0, text="๋กœ๊ทธ์ธ ์ •๋ณด ๊ธฐ์–ตํ•˜๊ธฐ", command=lambda: NAI_token_save(token_output))
token_output.grid(row=2, column=1, padx=5, pady=5, sticky='ew')
connect_button = tk.Button(button_frame0, text="์—ฐ๊ฒฐ", command=lambda: NAI_connect(button, connect_button, token_output))
connect_button.grid(row=2, column=0, padx=5, pady=5, sticky='ew')
close_button = tk.Button(button_frame0, text="๋‹ซ๊ธฐ", command=NAI_close)
close_button.grid(row=2, column=2, padx=5, pady=5, sticky='ew')
NAI_State_label = tk.Label(button_frame0, text="ํ•ด๋‹น ์ ‘์†๊ธฐ๋Šฅ์€ ์ •์ƒ์ ์ธ ์ ‘์† ํŒจํ„ด์ด ์•„๋‹Œ์  ์ฐธ๊ณ  ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.", fg="red")
NAI_State_label.grid(row=3, column=0, sticky='ew')
def NAI_setting_multi(button):
global NAI_ID_multi
NAI_setting_window_multi = tk.Toplevel(window)
NAI_setting_window_title = "NAI ๋กœ๊ทธ์ธ"
def NAI_close():
NAI_setting_window_multi.destroy()
NAI_ID_label = tk.Label(NAI_setting_window_multi, text="NAI ID: ")
NAI_ID_label.grid(row=0, column=0, columnspan=2, sticky='w')
entry_NAI_ID = tk.Entry(NAI_setting_window_multi, width=50)
entry_NAI_ID.grid(row=0, column=1, columnspan=2, padx=100, pady=5, sticky='e')
if(NAI_ID_multi): entry_NAI_ID.insert(tk.END,NAI_ID_multi)
NAI_PW_label = tk.Label(NAI_setting_window_multi, text="NAI PW: ")
NAI_PW_label.grid(row=1, column=0, columnspan=2, sticky='w')
entry_NAI_PW = tk.Entry(NAI_setting_window_multi, width=50, show="*")
entry_NAI_PW.grid(row=1, column=1, columnspan=2, padx=100, pady=5, sticky='e')
def NAI_connect(button, connect_button):
global access_token_multi, NAI_ID, NAI_ID_multi
username = entry_NAI_ID.get().strip()
password = entry_NAI_PW.get().strip()
access_key = get_access_key(username, password)
try:
access_token_multi = login(access_key)
access_result = requests.get("https://api.novelai.net/user/information", headers={ "Authorization": f"Bearer {access_token}" })
if NAI_ID == NAI_ID_multi: NAI_State_label.config(text="(๊ฐ™์€ ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธ ํ•˜์…จ์Šต๋‹ˆ๋‹ค.)", fg="red")
else: NAI_State_label.config(text="(๋กœ๊ทธ์ธ ์„ฑ๊ณต, ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”.)", fg="blue")
button.config(state=tk.DISABLED)
connect_button.config(state=tk.DISABLED)
NAI_ID_multi = username
except Exception as e:
print(e)
NAI_close()
connect_button = tk.Button(NAI_setting_window_multi, text="์—ฐ๊ฒฐ", command=lambda: NAI_connect(button, connect_button))
connect_button.grid(row=2, column=1, columnspan=2, padx=5, pady=5, sticky='w')
close_button = tk.Button(NAI_setting_window_multi, text="๋‹ซ๊ธฐ", command=NAI_close)
close_button.grid(row=2, column=2, columnspan=2, padx=5, pady=5, sticky='w')
NAI_State_label = tk.Label(NAI_setting_window_multi, text="ํ•ด๋‹น ๊ธฐ๋Šฅ์€ NAI Opus ๊ตฌ๋… ๊ณ„์ • 2๊ฐœ๊ฐ€ ์š”๊ตฌ๋ฉ๋‹ˆ๋‹ค..", fg="red")
NAI_State_label.grid(row=3, column=1, sticky='ew')
def on_resolution_change(*args):
global NAI_width, NAI_height
resolution = selected_resolution.get()
NAI_width, NAI_height = resolution.split(' x ')
def on_option_select(value):
global current_sampler
current_sampler = value
def open_file_explorer():
output_file_path = "output_NAI"
if os.path.exists(output_file_path):
os.startfile(output_file_path)
def on_generate_event(event):
global running_flag
if not (running_flag):
NAI_generation(NAI_width, NAI_height, button_generate)
def random_artist_management():
global top_100_keywords, top_100_counts, cached_rows
if not cached_rows: return
if not (top_100_keywords):
if not os.path.exists("counting_result.txt"):
keyword_counts = analyze_cached_rows(cached_rows)
excluded_keywords = set(whitelist[:2974])
with open("counting_result.txt", "w") as file:
for keyword, count in sorted(keyword_counts.items(), key=lambda item: item[1], reverse=True):
if keyword not in excluded_keywords and keyword in afilter_30000:
file.write(f"{keyword}: {count}\n")
with open("counting_result.txt", "r") as file:
lines = file.readlines()
top_100_data = [
(line.split(":")[0].strip(), int(line.split(":")[1].strip()))
for line in lines[:3000]
if line.split(":")[0].strip() in afilter_30000[:8528]
]
top_100_keywords, top_100_counts = zip(*top_100_data) if top_100_data else ([], [])
elif (not top_100_keywords):
with open("counting_result.txt", "r") as file:
lines = file.readlines()
top_100_data = [
(line.split(":")[0].strip(), int(line.split(":")[1].strip()))
for line in lines[:3000]
if line.split(":")[0].strip() in afilter_30000[:8528]
]
top_100_keywords, top_100_counts = zip(*top_100_data) if top_100_data else ([], [])
# top_100_keywords ๋‚ด์˜
# ์ƒˆ ์ฐฝ ์ƒ์„ฑ
random_artist_window = tk.Toplevel(window)
# ์ฒซ ๋ฒˆ์งธ Text Output Box ์„ค์ •
text_output1 = tk.Text(random_artist_window, height=40, width=50)
text_output1.pack(padx=10, pady=10)
for keyword, count in zip(top_100_keywords, top_100_counts):
text_output1.insert(tk.END, f"{keyword}: {count}\n")
def update_lists():
# Text ์œ„์ ฏ์—์„œ ๋‚ด์šฉ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
content = text_output1.get("1.0", tk.END)
lines = content.strip().split("\n") # ์ค„๋ฐ”๊ฟˆ์œผ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
# ๊ฐฑ์‹ ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ๋‘ ๊ฐœ์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
updated_keywords = []
updated_counts = []
# ๊ฐ ์ค„์„ ์ฒ˜๋ฆฌํ•˜์—ฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
for line in lines:
if line: # ๋นˆ ์ค„์ด ์•„๋‹Œ ๊ฒฝ์šฐ์—๋งŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
parts = line.split(":")
if len(parts) == 2: # "ํ‚ค์›Œ๋“œ: ์นด์šดํŠธ" ํ˜•์‹์ด ๋งž๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
updated_keywords.append(parts[0].strip())
updated_counts.append(int(parts[1].strip()))
# ์ „์—ญ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
global top_100_keywords, top_100_counts
top_100_keywords = updated_keywords
top_100_counts = updated_counts
with open("random_artist_keywords_"+str(len(top_100_keywords))+".txt", "w") as f:
for keyword in updated_keywords:
f.write('100: artist:'+keyword + "\n")
# ๋ฒ„ํŠผ๋“ค์„ ๋‹ด์„ ํ”„๋ ˆ์ž„ ์ƒ์„ฑ
buttons_frame = tk.Frame(random_artist_window)
buttons_frame.pack(pady=10)
# '์ €์žฅ' ๋ฒ„ํŠผ์„ ํ”„๋ ˆ์ž„์˜ ์™ผ์ชฝ์— ๋ฐฐ์น˜
save_button = tk.Button(buttons_frame, text="์ €์žฅ", command=update_lists)
save_button.pack(side=tk.LEFT, padx=5)
# '๋‹ซ๊ธฐ' ๋ฒ„ํŠผ์„ ํ”„๋ ˆ์ž„์˜ ์˜ค๋ฅธ์ชฝ์— ๋ฐฐ์น˜
close_button = tk.Button(buttons_frame, text="๋‹ซ๊ธฐ", command=random_artist_window.destroy)
close_button.pack(side=tk.RIGHT, padx=5)
random_artist_label = tk.Label(random_artist_window, text='์ž‘๊ฐ€์ด๋ฆ„ ์ด '+str(len(top_100_keywords))+'๊ฐœ, ์ €์žฅ์œ„์น˜: exeํŒŒ์ผ ์œ„์น˜')
random_artist_label.pack()
def open_wildcard_setting():
global artist_wildcard_saved, character_wildcard_saved
# ์ƒˆ ์ฐฝ ์ƒ์„ฑ
wildcard_window = tk.Toplevel(window)
wildcard_window.title("์™€์ผ๋“œ ์นด๋“œ ์„ค์ •")
# ์ž‘๊ฐ€๋ช… ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
artist_label = tk.Label(wildcard_window, text="์ž‘๊ฐ€๋ช… ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ->")
artist_label.grid(row=0, column=0)
artist_button = tk.Button(wildcard_window, text="์—ด๊ธฐ", command=lambda: load_wildcard(artist_text, wildcard_window, 'artist'))
artist_button.grid(row=0, column=1)
artist_text = tk.Text(wildcard_window, height=15, width=60)
artist_text.grid(row=1, column=0, columnspan=2)
if artist_wildcard_saved:
artist_text_content = '\n'.join(artist_wildcard_saved)
artist_text.insert('1.0', artist_text_content)
# ์บ๋ฆญํ„ฐ ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
character_label = tk.Label(wildcard_window, text="์บ๋ฆญํ„ฐ ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ->")
character_label.grid(row=2, column=0)
character_button = tk.Button(wildcard_window, text="์—ด๊ธฐ", command=lambda: load_wildcard(character_text, wildcard_window, 'character'))
character_button.grid(row=2, column=1)
character_text = tk.Text(wildcard_window, height=15, width=60)
character_text.grid(row=3, column=0, columnspan=2)
if character_wildcard_saved:
character_text_content = '\n'.join(character_wildcard_saved)
character_text.insert('1.0', character_text_content)
# ๋ฒ„ํŠผ๋“ค
buttons_frame = tk.Frame(wildcard_window)
buttons_frame.grid(row=4, column=0, columnspan=2)
text_label = tk.Label(wildcard_window, text="wildcard ๋ฌธ๋ฒ•(์ž‘๊ฐ€):\noffset:wildcard1 150:null (helloworld)\noffset:wildcard2 100:none (goodbye)\n์—†์œผ๋ฉด 100: ์œผ๋กœ ๊ฐ„์ฃผ\noffset/offset ์ดํ•ฉ: wildcard ํ™•๋ฅ ")
text_label.grid(row=5, column=0,sticky='ew')
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...")
text_label2.grid(row=6, column=0,sticky='ew')
load_button = tk.Button(buttons_frame, text="์™€์ผ๋“œ์นด๋“œ ํƒ‘์žฌ", command=lambda: apply_wildcard(artist_text, character_text, wildcard_window))
load_button.pack(side=tk.LEFT, padx=10)
close_button = tk.Button(buttons_frame, text="๋‹ซ๊ธฐ", command=wildcard_window.destroy)
close_button.pack(side=tk.RIGHT, padx=10)
def apply_wildcard(artist_text, character_text, window):
global artist_wildcard_saved
artist_wildcard_check = artist_text.get("1.0", tk.END)
if len(artist_wildcard_check) > 5:
lines = artist_wildcard_check.strip().split("\n")
artist_wildcard_saved = lines.copy()
akeywords = []
current_index = 0
for line in lines:
parts = line.strip().split(':', 1)
if len(parts) == 2 and parts[0].strip().isdigit():
weight = int(parts[0].strip())
else:
weight = 100
parts = ['100', line.strip()] # '100:'์„ ์•ž์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
keyword = parts[1].strip()
akeywords.append((current_index, current_index + weight - 1, keyword))
current_index += weight
global artist_wildcard
artist_wildcard = akeywords
check_wildcard.config(state='normal')
character_wildcard_check = character_text.get("1.0", tk.END)
global character_wildcard_saved
if len(character_wildcard_check) > 5:
lines = character_wildcard_check.strip().split("\n")
character_wildcard_saved = lines.copy()
ckeywords = []
current_index = 0
for line in lines:
parts = line.strip().split(':', 1)
if len(parts) == 2 and parts[0].strip().isdigit():
weight = int(parts[0].strip())
else:
weight = 100
parts = ['100', line.strip()] # '100:'์„ ์•ž์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
keyword = parts[1].strip()
ckeywords.append((current_index, current_index + weight - 1, keyword))
current_index += weight
global character_wildcard
character_wildcard = ckeywords
check_wildcard2.config(state='normal')
window.destroy()
def load_wildcard(text_widget, window, _type):
global artist_wildcard_saved, character_wildcard_saved
window.iconify()
filepath = filedialog.askopenfilename(filetypes=[("ํ…์ŠคํŠธ ํŒŒ์ผ", "*.txt")])
if filepath:
with open(filepath, 'r', encoding='utf-8') as file:
lines = file.readlines()
updated_lines = []
for line in lines:
line = line.strip()
if ':' in line:
prefix, _ = line.split(':', 1)
if not prefix.strip().isdigit():
line = f"100: {line}"
else:
line = f"100: {line}"
updated_lines.append(line)
text_widget.delete('1.0', tk.END)
text_widget.insert('1.0', '\n'.join(updated_lines))
if(_type == 'artist'):
artist_wildcard_saved = updated_lines.copy()
elif(_type == 'character'):
character_wildcard_saved = updated_lines.copy()
window.deiconify()
def find_keyword(index, keywords):
for start, end, keyword in keywords:
if start <= index <= end:
return keyword
return None
def get_random_keyword(req_keyword):
#called from artist_wildcard, character_wildcard
global artist_wildcard, character_wildcard
if(req_keyword == 'artist'): keywords = artist_wildcard
elif(req_keyword == 'character'): keywords = character_wildcard
print('lenghth = ',len(keywords))
max_index = keywords[-1][1]
random_index = random.randint(0, max_index)
return find_keyword(random_index, keywords)
def tprint(*args):
ctext = ""
color = None
for t in args:
if(type(t) is str and 'color=' in t):
color = t[6:]
else:
ctext += str(t)
if not color: running_state.config(text=ctext, fg='black')
else: running_state.config(text=ctext, fg='red')
def show_automation_option():
global auto_thread, stop_event
top = tk.Toplevel(window)
top.title("Automation Stop Condition")
global var, timer_label, timer_entry, count_label, count_entry
var = tk.StringVar(value="unlimited")
def show_option():
if var.get() == 'timer':
timer_label.grid(row=4, column=0)
timer_entry.grid(row=4, column=1)
count_label.grid_forget()
count_entry.grid_forget()
elif var.get() == 'count':
count_label.grid(row=4, column=0)
count_entry.grid(row=4, column=1)
timer_label.grid_forget()
timer_entry.grid_forget()
else:
timer_label.grid_forget()
timer_entry.grid_forget()
count_label.grid_forget()
count_entry.grid_forget()
label_time = tk.Label(top, text="์ด๋ฏธ์ง€ ์ƒ์„ฑ๋‹น ์ง€์—ฐ์‹œ๊ฐ„ ์ถ”๊ฐ€ (์ดˆ)")
label_time.grid(row=0, column=0, columnspan=3)
delay_entry = tk.Entry(top)
delay_entry.grid(row=1, column=0, columnspan=3)
label = tk.Label(top, text="์ž๋™ํ™” ์ข…๋ฃŒ ์กฐ๊ฑด")
label.grid(row=2, column=0, columnspan=3)
radio1 = tk.Radiobutton(top, text="๋ฌด์ œํ•œ", variable=var, value="unlimited", command=show_option)
radio1.grid(row=3, column=0)
radio2 = tk.Radiobutton(top, text="ํƒ€์ด๋จธ", variable=var, value="timer", command=show_option)
radio2.grid(row=3, column=1)
radio3 = tk.Radiobutton(top, text="์ƒ์„ฑ ์นด์šดํŠธ", variable=var, value="count", command=show_option)
radio3.grid(row=3, column=2)
timer_label = tk.Label(top, text="์ž๋™ํ™” ๋™์ž‘ ์‹œ๊ฐ„(๋ถ„) :")
timer_entry = tk.Entry(top)
count_label = tk.Label(top, text="์ž๋™ ์ƒ์„ฑ ํšŸ์ˆ˜:")
count_entry = tk.Entry(top)
# "A.์„ค์ •" ์ฐฝ์—์„œ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ
def on_apply(top):
global auto_time_left_flag, auto_time_left, auto_count_left_flag, auto_count_left, delay_offset, delay_offset_label
selected_option = var.get()
if delay_entry.get():
try:
delay_offset = round(float(delay_entry.get()), 1)
delay_offset_label.config(text="Dealy offset : "+str(delay_offset))
except ValueError as e:
print(e)
delay_offset = 0
else:
delay_offset = 0
delay_offset_label.config(text="")
if selected_option == "timer":
auto_time_left_flag = True
auto_count_left_flag = False
try:
# ์—”ํŠธ๋ฆฌ์—์„œ ์ž…๋ ฅ๋œ ์‹œ๊ฐ„์„ ๋ถ„ ๋‹จ์œ„์—์„œ ์ดˆ ๋‹จ์œ„๋กœ ๋ณ€ํ™˜
auto_time_left = int(timer_entry.get()) * 60
except ValueError:
# ์ž˜๋ชป๋œ ์ž…๋ ฅ ์ฒ˜๋ฆฌ
print("Invalid input for timer. Please enter a number.")
return
elif selected_option == "count":
auto_count_left_flag = True
auto_time_left_flag = False
try:
auto_count_left = int(count_entry.get())
except ValueError:
# ์ž˜๋ชป๋œ ์ž…๋ ฅ ์ฒ˜๋ฆฌ
print("Invalid input for count. Please enter a number.")
return
else:
auto_time_left_flag = False
auto_count_left_flag = False
stop_auto_thread() # ์ด์ „ ์Šค๋ ˆ๋“œ ์ข…๋ฃŒ
start_auto_thread() # ์ƒˆ ์Šค๋ ˆ๋“œ ์‹œ์ž‘
mac_var.set(1)
top.destroy()
apply_button = tk.Button(top, text="์ ์šฉ", command=lambda: on_apply(top))
stop_button = tk.Button(top, text="์ค‘๋‹จ", command=on_stop)
close_button = tk.Button(top, text="๋‹ซ๊ธฐ", command=top.destroy)
apply_button.grid(row=5, column=0, pady=5)
stop_button.grid(row=5, column=1, pady=5)
close_button.grid(row=5, column=2, pady=5)
def auto_time_thread(stop_event):
global auto_time_left, auto_time_left_flag
def seconds_to_hms(seconds):
h = seconds // 3600
m = (seconds % 3600) // 60
s = seconds % 60
return f"{h:02d}:{m:02d}:{s:02d}"
def update_label_for_time_finished():
automation_state.config(text="์ง€์ •ํ•œ ์‹œ๊ฐ„์ด ๋ชจ๋‘ ์†Œ์ง„๋˜์–ด ์ž๋™ํ™”๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
auto_time_left_flag = False
mac_var.set(0)
while not stop_event.is_set() and auto_time_left > 0:
time.sleep(1)
auto_time_left -= 1
remaining_time = seconds_to_hms(auto_time_left)
window.after(0, lambda: automation_state.config(text=f"์ž๋™ํ™” ๋‚จ์€์‹œ๊ฐ„ : {remaining_time}"))
if auto_time_left <= 0:
window.after(0, update_label_for_time_finished)
if stop_event.is_set():
window.after(0, lambda: automation_state.config(text="Conditional automation not set (A.์„ค์ •)"))
auto_time_left_flag = False
def auto_count_thread(stop_event):
global auto_count_left, auto_count_left_flag
def update_label_for_count_finished():
mac_var.set(0) # ์ž๋™ํ™” ์ข…๋ฃŒ ์กฐ๊ฑด ์ถฉ์กฑ
auto_count_left_flag = False
automation_state.config(text="์ง€์ •ํ•œ ํšŸ์ˆ˜๊ฐ€ ๋ชจ๋‘ ์†Œ์ง„๋˜์–ด ์ž๋™ํ™”๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
while not stop_event.is_set():
time.sleep(1) # ์ฃผ๊ธฐ์ ์œผ๋กœ ํ™•์ธ
window.after(0, lambda: automation_state.config(text=f"์ž๋™ํ™” ๋‚จ์€ํšŸ์ˆ˜ : {auto_count_left}"))
if auto_count_left <= 0:
window.after(0, update_label_for_count_finished)
break # ๋ฃจํ”„ ํƒˆ์ถœ
if stop_event.is_set():
window.after(0, lambda: automation_state.config(text="Conditional automation not set (A.์„ค์ •)"))
mac_var.set(0)
auto_count_left_flag = False
# ์Šค๋ ˆ๋“œ ์‹œ์ž‘ ๋ฐ ์ข…๋ฃŒ ํ•จ์ˆ˜
def start_auto_thread():
global auto_thread, stop_event
stop_event = threading.Event()
auto_thread = None
if auto_time_left_flag:
auto_thread = threading.Thread(target=auto_time_thread, args=(stop_event,))
elif auto_count_left_flag:
auto_thread = threading.Thread(target=auto_count_thread, args=(stop_event,))
if auto_thread is not None:
auto_thread.start()
def stop_auto_thread():
global stop_event, auto_thread
if stop_event is not None:
stop_event.set()
#if auto_thread is not None and auto_thread.is_alive():
# auto_thread.join()
def on_stop():
global auto_thread, stop_event
stop_auto_thread() # ์Šค๋ ˆ๋“œ ์ข…๋ฃŒ
def on_hold_seed_button_click():
global last_generation_seed
last_generation_seed = entry_seed_value.get()
def update_fullscreen_image(new_window, new_image_label):
last_updated_image = None
while True:
time.sleep(1)
if not new_window.winfo_exists():
break
try:
current_image = getattr(image_label, 'original_image', None)
if current_image and current_image != last_updated_image:
resized_image = resize_image_to_fit(current_image, new_window.winfo_height())
tk_image = ImageTk.PhotoImage(resized_image)
new_window.after(0, lambda img=tk_image: new_image_label.config(image=img))
new_image_label.image = tk_image
last_updated_image = current_image
except ValueError:
print(ValueError)
def show_fullscreen_image():
new_window = tk.Toplevel()
new_window.attributes('-fullscreen', True)
new_window.configure(bg='black')
new_image_label = tk.Label(new_window, relief='solid', borderwidth=1, bg='black')
new_image_label.pack(expand=True, fill='both')
new_window.bind("<Escape>", lambda e: new_window.destroy())
update_thread = threading.Thread(target=update_fullscreen_image, args=(new_window, new_image_label))
update_thread.daemon = True
update_thread.start()
def resize_image_to_fit(image, target_height):
original_width, original_height = image.size
ratio = target_height / float(original_height)
new_width = int(original_width * ratio)
resized_image = image.resize((new_width, target_height), Image.Resampling.LANCZOS)
return resized_image
auto_time_left_flag = False
auto_time_left = 0
auto_count_left_flag = False
auto_count_left = 0
stop_event = None
auto_thread = None
delay_offset = 0
start_time = datetime.now().strftime('%Y%m%d_%H%M')
thread_controller = False
turbo_count = 0
on_press_flag = False
window = tk.Tk()
window.title("Prompt Selector for Danbooru tags")
last_deep_search_keywords = None
cached_rows = []
total_rows = 0
last_selected_row_keywords = ['1girl','nahida (genshin impact)', 'looking at viewer', 'garden']
top_100_keywords = []
top_100_counts = []
previous_artist = None
listener = None
current_keys = set()
click_count = 0
access_token = None
temp_clipboard_image = None
NAI_width = 1024
NAI_height = 1024
current_sampler = "k_euler_ancestral"
running_flag = False
NAI_ID = None
artist_wildcard = []
character_wildcard_saved = []
artist_wildcard_saved = []
character_wildcard =[]
access_token_multi = None
NAI_ID_multi = None
image_queue = []
last_generation_seed = random.randint(0,9999999999)
turbo_stop_bit = False
task_finished = 0
error_count = 0
multi_token_enable = False
whitelist = wlist.whitelist
bag_of_tags = tagbag.bag_of_tags
afilter_30000 = arti_list.afilter_30000
history = []
current_wildcard_artist = []
current_wildcard_character = []
previous_wildcard_artist = None
previous_wildcard_character = None
GENERATE_EVENT = "<<GenerateEvent>>"
window.bind(GENERATE_EVENT, on_generate_event)
left_frame = tk.Frame(window)
left_frame.grid(row=0, column=0, sticky="nsew")
#left_frame.grid_columnconfigure(0, weight=1)
right_frame = tk.Frame(window)
right_frame.grid(row=0, column=1, sticky="nsew")
window.grid_columnconfigure(0, weight=1)
window.grid_columnconfigure(1, weight=1)
#ํŒŒ์ผ ๊ฒฝ๋กœ ๋ฐ ํ‚ค์›Œ๋“œ ์ž…๋ ฅ์ฐฝ ๊ทธ๋ฆฌ๋“œ ๊ด€๋ฆฌ
frame_row0 = tk.Frame(left_frame)
frame_row0.grid(row=0, column=0, padx=5, pady=5, sticky='w')
# ํŒŒ์ผ ๊ฒฝ๋กœ ์ž…๋ ฅ์ฐฝ
label_file_path = tk.Label(frame_row0, text="CSV ํŒŒ์ผ ๊ฒฝ๋กœ:")
label_file_path.grid(row=0, column=0, sticky='w')
entry_file_path = tk.Entry(frame_row0, width=55)
entry_file_path.grid(row=0, column=1, columnspan=4, padx=5, pady=5, sticky='ew')
button_open_file = tk.Button(frame_row0, text="ํŒŒ์ผ ์—ด๊ธฐ", command=open_file)
button_open_file.grid(row=0, column=5, padx=5, pady=6, sticky='e')
# ํ‚ค์›Œ๋“œ ์ž…๋ ฅ์ฐฝ
keyword_label = tk.Label(frame_row0, text="์ดˆ๊ธฐํ™” ํ‚ค์›Œ๋“œ: ")
keyword_label.grid(row=1, column=0, sticky='w')
entry_keyword = tk.Entry(frame_row0)
entry_keyword.grid(row=1, column=1, columnspan=4, padx=5, pady=5, sticky='ew')
button_export_csv = tk.Button(frame_row0, text=".csv ๋‚ด๋ณด๋‚ด๊ธฐ", command=export_csv)
button_export_csv.grid(row=1, column=5, padx=5, pady=6, sticky='e')
# ๋ฒ„ํŠผ ํ”„๋ ˆ์ž„
frame_buttons = tk.Frame(left_frame)
frame_buttons.grid(row=1, column=0, sticky='ew')
frame_buttons.columnconfigure(0, weight=1) # ์™ผ์ชฝ์— ๊ฐ€์ค‘์น˜ ๋ถ€์—ฌ
frame_buttons.columnconfigure(1, weight=0) # ๋ฒ„ํŠผ ์—ด์€ ๊ฐ€์ค‘์น˜ ์—†์Œ
frame_buttons.columnconfigure(2, weight=0) # ๋ฒ„ํŠผ ์—ด์€ ๊ฐ€์ค‘์น˜ ์—†์Œ
frame_buttons.columnconfigure(3, weight=1) # ์˜ค๋ฅธ์ชฝ์— ๊ฐ€์ค‘์น˜ ๋ถ€์—ฌ
# ๋ฒ„ํŠผ๋“ค
button_search = tk.Button(frame_buttons, text="ํ•ด๋‹น ํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰", command=search)
button_search.grid(row=0, column=1, padx=5, sticky='ew') # ๋ณ€๊ฒฝ: column=1
button_exclude = tk.Button(frame_buttons, text="ํ•ด๋‹น ํ‚ค์›Œ๋“œ ์ œ์™ธ", command=exclude)
button_exclude.grid(row=0, column=2, padx=5, sticky='ew') # ๋ณ€๊ฒฝ: column=2
total_rows_count_label = tk.Label(frame_buttons, text=".csv ๋‚ด ํ”„๋กฌํ”„ํŠธ ํ–‰: 0")
total_rows_count_label.grid(row=0, column=3, padx=5, sticky='ew')
# ์‹ฌ์ธต๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ ์ž…๋ ฅ์ฐฝ
deep_search_frame = tk.Frame(left_frame)
deep_search_frame.grid(row=2, column=0, pady=10, sticky='w')
deep_search_frame.columnconfigure(0, weight=2)
deep_search_frame.columnconfigure(1, weight=2)
deep_search_frame.columnconfigure(2, weight=1)
label_deep_search = tk.Label(deep_search_frame, text="์‹ฌ์ธต๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ ์ž…๋ ฅ: key,*key,~key,{key1|key2} ")
label_deep_search.grid(row=0, column=0, sticky='w')
# Tkinter UI ์„ค์ • ๋ถ€๋ถ„์— ๋ ˆ์ด๋ธ” ์ถ”๊ฐ€
cached_rows_count_label = tk.Label(deep_search_frame, text="์‹ฌ์ธต๊ฒ€์ƒ‰ ํ”„๋กฌํ”„ํŠธ ํ–‰: 0")
cached_rows_count_label.grid(row=0, column=1, padx=5, sticky='w')
button_export_deep_csv = tk.Button(deep_search_frame, text=".csv ๋‚ด๋ณด๋‚ด๊ธฐ", command=export_csv_search)
button_export_deep_csv.grid(row=0, column=2, padx=5, sticky='e')
entry_deep_search = tk.Entry(deep_search_frame, width=82)
entry_deep_search.grid(row=1, column=0, columnspan=3,padx=5, pady=5, sticky='ew')
# ๋ฒ„ํŠผ๋“ค์„ ํฌํ•จํ•  ํ”„๋ ˆ์ž„ ์ƒ์„ฑ
button_frame = tk.Frame(left_frame)
button_frame.grid(row=5, column=0, padx=5, sticky='w')
# ๋ฒ„ํŠผ ํ”„๋ ˆ์ž„ ๋‚ด์˜ ์—ด ์„ค์ •
button_frame.columnconfigure(0, weight=1)
button_frame.columnconfigure(1, weight=1)
button_frame.columnconfigure(2, weight=1)
button_frame.columnconfigure(3, weight=1)
button_frame.columnconfigure(4, weight=1)
button_frame.columnconfigure(5, weight=1)
button_frame.columnconfigure(6, weight=1)
# "๋žœ๋ค" ๋ฒ„ํŠผ
button_random = tk.Button(button_frame, text="๋žœ๋ค", command=random_function)
button_random.grid(row=0, column=0, sticky='ew')
# "ํ”„๋กฌํ”„ํŠธ ๊ณ ์ •" ํ† ๊ธ€ ๋ฒ„ํŠผ
button_frame_frame = tk.Frame(button_frame)
button_frame_frame.grid(row=0, column=1, sticky='ew')
toggle_prompt_var = tk.IntVar()
button_toggle_prompt = tk.Checkbutton(button_frame_frame, text="ํ”„๋กฌํ”„ํŠธ ๊ณ ์ •", variable=toggle_prompt_var)
button_toggle_prompt.grid(row=0, column=0, sticky='ew')
safe_search_var = tk.IntVar()
button_toggle_safe_search = tk.Checkbutton(button_frame_frame, text="์„ธ์ดํ”„์„œ์น˜", variable=safe_search_var)
button_toggle_safe_search.grid(row=1, column=0, sticky='ew')
# "์ž๋™ ๋ณต์‚ฌ" ์ฒดํฌ๋ฐ•์Šค
auto_copy_var = tk.IntVar()
check_auto_copy = tk.Checkbutton(button_frame, text="์ž๋™ ๋ณต์‚ฌ", variable=auto_copy_var)
check_auto_copy.grid(row=0, column=2, sticky='ew')
# "์ข…๋ฃŒ" ๋ฒ„ํŠผ
button_exit = tk.Button(button_frame, text="์ข…๋ฃŒ", command=exit_program)
button_exit.grid(row=0, column=3, sticky='ew')
# "์ƒ์„ฑ" ๋ฒ„ํŠผ
button_generate = tk.Button(button_frame, text="NAI ์š”์ฒญ", command=lambda: NAI_generation(NAI_width, NAI_height, button_generate))
button_generate.grid(row=0, column=4, sticky='ew')
button_generate.config(state='disabled')
# "์ค‘๋‹จ"๋ฒ„ํŠผ
button_stop = tk.Button(button_frame, text="์ค‘๋‹จ",command=lambda: turbo_stop(button_stop))
button_stop.grid(row=0, column=5, sticky='ew')
button_stop.config(state='disabled')
# "์„ค์ •" ๋ฒ„ํŠผ
button_setting = tk.Button(button_frame, text="NAI ์„ค์ •", command=lambda: NAI_setting(button_setting, button_generate))
button_setting.grid(row=0, column=6, sticky='ew')
# '์ž๋™ํ™”'์™€ 'ํ„ฐ๋ณดon'์„ ํฌํ•จํ•  ์„œ๋ธŒ ํ”„๋ ˆ์ž„ ์ƒ์„ฑ
sub_frame = tk.Frame(button_frame)
sub_frame.grid(row=0, column=7, sticky='ns') # ์„œ๋ธŒ ํ”„๋ ˆ์ž„์„ ์—ด 8์— ๋ฐฐ์น˜
# '์ž๋™ํ™”' ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„œ๋ธŒ ํ”„๋ ˆ์ž„์— ๋ฐฐ์น˜
mac_var = tk.IntVar()
mac_button = tk.Checkbutton(sub_frame, text="์ž๋™ํ™”", variable=mac_var)
mac_button.grid(row=0, column=0, sticky='ew') # ์ฒซ ๋ฒˆ์งธ ํ–‰์— ๋ฐฐ์น˜
# 'ํ„ฐ๋ณดon' ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„œ๋ธŒ ํ”„๋ ˆ์ž„์— ๋ฐฐ์น˜
turbo_var = tk.IntVar()
turbo_button = tk.Checkbutton(sub_frame, text="ํ„ฐ๋ณดon", variable=turbo_var)
turbo_button.grid(row=1, column=0, sticky='ew') # ๋‘ ๋ฒˆ์งธ ํ–‰์— ๋ฐฐ์น˜
# "A.์„ค์ •" ๋ฒ„ํŠผ
button_auto_setting = tk.Button(button_frame, text="A.์„ค์ •", command=show_automation_option)
button_auto_setting.grid(row=0, column=8, sticky='ew')
# ํ…์ŠคํŠธ ๋ฐ ๊ณ ์ • ํ”„๋กฌํ”„ํŠธ ๋„ค๊ฑฐํ‹ฐ๋ธŒ ๋“ฑ ํ”„๋กฌํ”„ํŠธ ์ฐฝ
text_frame = tk.Frame(left_frame)
text_frame.grid(row=6, column=0, padx=5, pady=5, sticky='w')
text_frame.columnconfigure(0, weight=1)
text_frame.columnconfigure(1, weight=7)
text_frame2 = tk.Frame(left_frame)
text_frame2.grid(row=8, column=0, padx=5, pady=5, sticky='w')
text_frame2.columnconfigure(0, weight=1)
text_frame2.columnconfigure(1, weight=7)
_size = get_max_size()
# ์ถœ๋ ฅ ํ…์ŠคํŠธ ์ฐฝ
text_output_label = tk.Label(text_frame, text="ํ”„๋กฌํ”„ํŠธ", borderwidth=1, relief="solid",height=6)
text_output_label.grid(row=0, column=0, padx=5, pady=5, sticky='w')
if _size<=768: text_output_width = 74
else: text_output_width = 65
text_output = tk.Text(text_frame, width=text_output_width, height=7)
text_output.grid(row=0, column=1, sticky='ew')
fixed_prompt_frame = tk.Frame(left_frame)
fixed_prompt_frame.grid(row=7, column=0, padx=5, pady=5, sticky='w')
fixed_prompt_frame.columnconfigure(0, weight=1)
fixed_prompt_frame.columnconfigure(1, weight=1)
fixed_prompt_label_left = tk.Label(fixed_prompt_frame, text="์„ ํ–‰ ๊ณ ์ • ํ”„๋กฌํ”„ํŠธ (ํ”„๋กฌํ”„ํŠธ ์•ž)")
fixed_prompt_label_left.grid(row=0, column=0, sticky='ew')
fixed_prompt_label_right = tk.Label(fixed_prompt_frame, text="ํ›„ํ–‰ ๊ณ ์ • ํ”„๋กฌํ”„ํŠธ (ํ”„๋กฌํ”„ํŠธ ๋’ค)")
fixed_prompt_label_right.grid(row=0, column=1, sticky='ew')
entry_fixed_prompt = tk.Entry(fixed_prompt_frame, width=40)
entry_fixed_prompt.grid(row=1, column=0,padx=5, pady=5, sticky='ew')
entry_fixed_prompt_after = tk.Entry(fixed_prompt_frame, width=40)
entry_fixed_prompt_after.grid(row=1, column=1, padx=5, pady=5, sticky='ew')
# ๋„ค๊ฑฐํ‹ฐ๋ธŒ ํ”„๋กฌํ”„ํŠธ
NP_label = tk.Label(text_frame2, text="๋„ค๊ฑฐํ‹ฐ๋ธŒ\nํ”„๋กฌํ”„ํŠธ", borderwidth=1, relief="solid",height=2)
NP_label.grid(row=0,column=0, padx=5, pady=5, sticky='ew')
negative_text = tk.Text(text_frame2, width=65, height=3)
negative_text.grid(row=0, column=1, padx=5, pady=5, sticky='w')
auto_hide_frame = tk.Frame(left_frame)
auto_hide_frame.grid(row=9, column=0, padx=5, pady=5, sticky='w')
auto_hide_frame.columnconfigure(0, weight=2)
auto_hide_frame.columnconfigure(1, weight=2)
auto_hide_frame.columnconfigure(2, weight=1)
# ์ž๋™ ์ˆจ๊น€ ํ‚ค์›Œ๋“œ ๋ผ๋ฒจ๊ณผ ์ž…๋ ฅ์ฐฝ ์ถ”๊ฐ€
auto_hide_label = tk.Label(auto_hide_frame, text="์ž๋™ ์ˆจ๊น€ ํ‚ค์›Œ๋“œ: keyword1, keyword2, ...")
auto_hide_label.grid(row=0, column=0, sticky='w')
entry_auto_hide = tk.Entry(auto_hide_frame, width=82)
entry_auto_hide.grid(row=1, column=0, columnspan=3, padx=5, pady=5, sticky='ew')
# ์ถ”์ฒœ ํ”„๋กฌํ”„ํŠธ ์กฐํšŒ ๋ฒ„ํŠผ ์„ค์ •
character_search_button = tk.Button(auto_hide_frame, text="์บ๋ฆญํ„ฐ ๊ฒ€์ƒ‰", command=character_search_thread)
character_search_button.grid(row=0, column=1, padx=2, pady=5, sticky='e')
recommend_prompt_button = tk.Button(auto_hide_frame, text="์ถ”์ฒœ ํ”„๋กฌํ”„ํŠธ", command=open_prompt_window)
recommend_prompt_button.grid(row=0, column=2, padx=2, pady=5, sticky='e') # sticky ์˜ต์…˜์„ 'e'๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ์˜ค๋ฅธ์ชฝ ์ •๋ ฌ
# ์ฒดํฌ๋ฐ•์Šค๋“ค์„ ํฌํ•จํ•  ํ”„๋ ˆ์ž„ ์ƒ์„ฑ
checkbox_frame = tk.Frame(left_frame)
checkbox_frame.grid(row=10, column=0, pady=15, sticky='ew')
checkbox_frame2 = tk.Frame(left_frame)
checkbox_frame2.grid(row=10, column=1, padx=5, pady=15, sticky='ew')
# ์ฒดํฌ๋ฐ•์Šค ํ”„๋ ˆ์ž„ ๋‚ด์˜ ์—ด ์„ค์ •
checkbox_frame.columnconfigure(0, weight=1)
checkbox_frame.columnconfigure(1, weight=1)
checkbox_frame.columnconfigure(2, weight=1)
checkbox_frame.columnconfigure(3, weight=1)
checkbox_frame.columnconfigure(4, weight=1)
checkbox_frame.columnconfigure(5, weight=1)
# "์ž‘๊ฐ€๋ช… ์ œ๊ฑฐ" ์ฒดํฌ๋ฐ•์Šค
remove_artist_var = tk.IntVar() # ์ฒดํฌ๋ฐ•์Šค ์ƒํƒœ๋ฅผ ์ €์žฅํ•  ๋ณ€์ˆ˜
check_remove_artist = tk.Checkbutton(checkbox_frame, text="์ž‘๊ฐ€๋ช… ์ œ๊ฑฐ", variable=remove_artist_var)
check_remove_artist.grid(row=0, column=0, sticky='ew')
# "๋žœ๋ค ์ž‘๊ฐ€ ์ถ”๊ฐ€" ์ฒดํฌ๋ฐ•์Šค
random_artist_var = tk.IntVar()
check_random_artist = tk.Checkbutton(checkbox_frame, text="๋žœ๋ค ์ž‘๊ฐ€ ์ถ”๊ฐ€", variable=random_artist_var)
check_random_artist.grid(row=0, column=1, sticky='ew')
# ๋žœ๋ค์ž‘๊ฐ€ ๊ด€๋ฆฌ
random_artist_setting = tk.Button(checkbox_frame, text="๋žœ๋ค ์ž‘๊ฐ€ ๊ด€๋ฆฌ", command=random_artist_management) #output_file_path
random_artist_setting.grid(row=0, column=2, sticky='ew')
# "์บ๋ฆญํ„ฐ ํŠน์ง• ์ œ๊ฑฐ" ์ฒดํฌ๋ฐ•์Šค
rm_characteristic_var = tk.IntVar()
rm_characteristic_label = tk.Checkbutton(checkbox_frame, text="์บ๋ฆญํ„ฐ ํŠน์ง• ์ œ๊ฑฐ", variable=rm_characteristic_var)
rm_characteristic_label.grid(row=0, column=3, sticky='ew')
# ์™€์ผ๋“œ ์นด๋“œ
wildcard_var = tk.IntVar(value= 0)
check_wildcard = tk.Checkbutton(checkbox_frame, text="์™€์ผ๋“œ์นด๋“œ(์ž‘๊ฐ€)", variable=wildcard_var, state='disabled')
check_wildcard.grid(row=1, column=0, sticky='ew')
# ์™€์ผ๋“œ ์นด๋“œ2
wildcard_var2 = tk.IntVar(value= 0)
check_wildcard2 = tk.Checkbutton(checkbox_frame, text="์™€์ผ๋“œ์นด๋“œ(์บ๋ฆญํ„ฐ)", variable=wildcard_var2, state='disabled')
check_wildcard2.grid(row=1, column=1, sticky='ew')
# ์™€์ผ๋“œ ์นด๋“œ ์„ค์ •
widldcard_button = tk.Button(checkbox_frame, text="์™€์ผ๋“œ์นด๋“œ ์„ค์ •", command=open_wildcard_setting) #output_file_path
widldcard_button.grid(row=1, column=2, sticky='ew')
#ํด๋” ํ˜ธ์ถœ ๋ฒ„ํŠผ
folder_button = tk.Button(checkbox_frame, text="์ €์žฅ ํด๋”", command=open_file_explorer) #output_file_path
folder_button.grid(row=1, column=3, padx=5, sticky='ew')
# "์ž‘ํ’ˆ๋ช… ์ œ๊ฑฐ" ์ฒดํฌ๋ฐ•์Šค
rm_copyright_var = tk.IntVar()
rm_copyright_label = tk.Checkbutton(checkbox_frame, text="์ž‘ํ’ˆ๋ช… ์ œ๊ฑฐ", variable=rm_copyright_var)
rm_copyright_label.grid(row=2, column=0, pady=5, sticky='ew')
# "NSFW Only ์ฒดํฌ๋ฐ•์Šค
NSFW_assert_var = tk.IntVar()
NSFW_assert_label = tk.Checkbutton(checkbox_frame, text="NSFW Only", variable=NSFW_assert_var)
NSFW_assert_label.grid(row=2, column=1, pady=5, sticky='ew')
window.bind('<Control-Return>', on_ctrl_enter)
window.bind('<Shift-Return>', on_shift_enter)
NAI_ID = load_settings()
if not (entry_keyword.get()): entry_keyword.insert(0, "1girl")
if not (entry_fixed_prompt.get()): entry_fixed_prompt.insert(0, '1girl,')
if not (entry_fixed_prompt_after.get()): entry_fixed_prompt_after.insert(0, 'great quality, aesthetic, absurdres')
if not (entry_auto_hide.get()): entry_auto_hide.insert(0, 'monochrome, doujin cover, bad source, censored, bar censor')
resolution1_frame = tk.Frame(left_frame)
resolution1_frame.grid(row=16, column=0, padx=5, pady=5, sticky='ew')
resolution2_frame = tk.Frame(left_frame)
resolution2_frame.grid(row=17, column=0, padx=5, pady=5, sticky='ew')
selected_resolution = tk.StringVar(value="1024 x 1024")
tk.Radiobutton(resolution1_frame, text="1024 x 1024", variable=selected_resolution, value="1024 x 1024").grid(row=0, column=0, sticky='w')
tk.Radiobutton(resolution1_frame, text="960 x 1088", variable=selected_resolution, value="960 x 1088").grid(row=0, column=1, sticky='w')
tk.Radiobutton(resolution1_frame, text="896 x 1152", variable=selected_resolution, value="896 x 1152").grid(row=0, column=2, sticky='w')
tk.Radiobutton(resolution1_frame, text="832 x 1216", variable=selected_resolution, value="832 x 1216").grid(row=0, column=3, sticky='w')
tk.Radiobutton(resolution2_frame, text="1088 x 960", variable=selected_resolution, value="1088 x 960").grid(row=0, column=0, sticky='w')
tk.Radiobutton(resolution2_frame, text="1152 x 896", variable=selected_resolution, value="1152 x 896").grid(row=0, column=1, sticky='w')
tk.Radiobutton(resolution2_frame, text="1216 x 832", variable=selected_resolution, value="1216 x 832").grid(row=0, column=2, sticky='w')
selected_resolution.trace_add('write', on_resolution_change)
sema_button_var = tk.IntVar(value=1)
sema_button = tk.Checkbutton(resolution1_frame, text="SEMA", variable=sema_button_var)
sema_button.grid(row=0, column=5, sticky='w')
dyn_button_var = tk.IntVar()
dyn_button = tk.Checkbutton(resolution1_frame, text="+DYN", variable=dyn_button_var)
dyn_button.grid(row=0, column=6, sticky='w')
rand_resolution_var = tk.IntVar()
rand_resolution_button = tk.Checkbutton(resolution1_frame, text="๋žœ๋ค ํ•ด์ƒ๋„", variable=rand_resolution_var)
rand_resolution_button.grid(row=0, column=7, sticky='w')
entry_CFG_value = tk.StringVar()
entry_CFG_label = tk.Label(resolution2_frame, text=" CFG Scale : ", justify=tk.LEFT)
entry_CFG_label.grid(row=0, column=4, sticky='w')
entry_CFG_value.set("5.0")
entry_CFG = tk.Entry(resolution2_frame, width=5, textvariable=entry_CFG_value)
entry_CFG.grid(row=0, column=5, sticky='w')
options = ["k_euler", "k_euler_ancestral", "k_dpmpp_2s_ancestral", "k_dpmpp_sde"]
selected_option = tk.StringVar()
selected_option.set(options[1])
option_menu = tk.OptionMenu(resolution2_frame, selected_option, *options, command=on_option_select)
option_menu.grid(row=0, column=6, padx=5, sticky='ew')
resolution3_frame = tk.Frame(left_frame)
resolution3_frame.grid(row=18, column=0, padx=5, pady=5, sticky='ew')
resolution3_frame.columnconfigure(0, weight=2)
resolution3_frame.columnconfigure(1, weight=1)
resolution3_frame.columnconfigure(2, weight=1)
running_state = tk.Label(resolution3_frame, text="state : idle")
running_state.grid(row = 0, column= 0, sticky='w')
automation_state = tk.Label(resolution3_frame, text="Conditional automation not set (A.์„ค์ •)")
automation_state.grid(row = 1, column= 0, sticky='w')
delay_offset_label = tk.Label(resolution3_frame, text="Dealy offset : "+str(delay_offset))
delay_offset_label.grid(row = 1, column= 1, sticky='e')
entry_rescale_value = tk.StringVar()
entry_rescale_label = tk.Label(resolution3_frame, text=" Prompt Guidance Rescale : ", justify=tk.LEFT)
entry_rescale_label.grid(row=0, column=1, sticky='e')
entry_rescale_value.set("0.0")
entry_rescale = tk.Entry(resolution3_frame, width=5, textvariable=entry_rescale_value)
entry_rescale.grid(row=0, column=2, sticky='w')
image_label = tk.Label(right_frame, relief='solid', borderwidth=1)
image_label.grid(row=0, column=0, rowspan=15, padx=10, pady=10, sticky="n")
right_frame_area16 = tk.Frame(right_frame)
right_frame_area16.grid(row=16, column=0, padx=5, pady=5, sticky='ew')
entry_seed_value = tk.IntVar()
entry_seed_label = tk.Label(right_frame_area16, text=" seed : ", justify=tk.LEFT)
entry_seed_label.grid(row=0, column=0, sticky='ew')
entry_seed_value.set(last_generation_seed)
entry_seed = tk.Entry(right_frame_area16, width=15, textvariable=entry_seed_value)
entry_seed.grid(row=0, column=1, sticky='ew')
hold_seed_var = tk.IntVar(value=0)
hold_seed_button = tk.Checkbutton(right_frame_area16, text="์‹œ๋“œ๊ณ ์ •", variable=hold_seed_var, command=on_hold_seed_button_click)
hold_seed_button.grid(row=0, column=2, sticky='ew')
btn_add_low_freq = tk.Button(right_frame_area16, text="์ด๋ฏธ์ง€๋ฅผ ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌ", fg="blue", command=copy_image_to_clipboard)
btn_add_low_freq.grid(row=0, column=3, padx=5, pady=5, sticky='ew')
show_fullscreen_btn = tk.Button(right_frame_area16, text="์ „์ฒดํ™”๋ฉด ๋ณด๊ธฐ (ESC๋กœ ๋‹ซ๊ธฐ)", command=show_fullscreen_image)
show_fullscreen_btn.grid(row=0, column=4, padx=5, pady=5, sticky='ew')
show_history_btn = tk.Button(right_frame_area16, text="history", command=show_history)
show_history_btn.grid(row=0, column=5, padx=5, pady=5, sticky='ew')
# ํ•˜์–€์ƒ‰ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
white_image = Image.new('RGB', (_size, _size), 'white')
white_photo = ImageTk.PhotoImage(white_image)
# ๋ผ๋ฒจ์— ์ด๋ฏธ์ง€ ์„ค์ •
image_label.config(image=white_photo)
image_label.image = white_photo
Auto_login_check()
window.protocol("WM_DELETE_WINDOW", exit_program)
window.mainloop()