PoemForSmallFThings / Danbooru Prompt Selector /TEST /prompt_selector_auto_1208_testv6.py
baqu2213's picture
Upload 2 files
4eae981
raw
history blame
103 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
BASE_URL="https://api.novelai.net"
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 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"
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 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
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:
entry_auto_hide.delete(0, tk.END)
entry_auto_hide.insert(tk.END, 'monochrome, doujin cover, bad source, censored, bar censor, photoshop (medium)')
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(exclude in 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
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 = 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:
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())
if(wildcard_var2.get() == 1):
temp_len = len(girl_keywords)
girl_keywords.append(get_random_keyword('character'))
if(wildcard_var.get() == 1):
if(wildcard_var2.get() == 1):
girl_keywords.insert(temp_len+1,get_random_keyword('artist'))
else:
girl_keywords.append(get_random_keyword('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 "(" in keyword or "horns" in keyword:
temp_rm.append(keyword)
for keyword in temp_rm:
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)
# ํƒ€์œจ ๊ฐœ์„  ํ”„๋กฌํ”„ํŠธ
valid_keywords = []
for keyword in temp_first_keywords:
if "(" in keyword and "(artist)" not in keyword and "(style)" not in keyword:
start = keyword.find("(") + 1
end = keyword.find(")")
if start < end and keyword[start:end] in current_deep_search_keywords:
valid_keywords.append(keyword)
for keyword in valid_keywords:
if keyword in temp_first_keywords:
temp_first_keywords.remove(keyword)
girl_index = next((i for i, k in enumerate(temp_first_keywords) if 'girl' in k), None)
if girl_index is not None:
for keyword in valid_keywords:
temp_first_keywords.insert(girl_index + 1, keyword)
girl_index += 1
# ๊ฒฐ๊ณผ ์ถœ๋ ฅ
print(temp_first_keywords)
#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 = [r'\b{}\b'.format(re.escape(keyword)) for keyword in auto_hide_keywords]
for pattern in patterns:
random_row_keywords = [re.sub(pattern + '(, )?', '', keyword) for keyword in random_row_keywords]
random_row_keywords = [re.sub('(?<=, )' + pattern, '', keyword) for keyword in random_row_keywords]
if entry_fixed_prompt_after.get():
entry_after_text = entry_fixed_prompt_after.get().strip().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)
random_row_keywords = [keyword.strip(', ') for keyword in random_row_keywords]
random_row_keywords = [keyword for keyword in random_row_keywords if keyword]
#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 ... ")
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 simulate_shortcuts():
global listener, on_press_flag
on_press_flag = True
random_function()
on_press_flag = False
try:
current_keys.clear()
current_keys.add(keyboard.Key.ctrl_l)
except KeyError:
pass
def on_activate_simulate_shortcuts():
simulate_shortcuts()
def for_canonical(f):
return lambda k: f(listener.canonical(k))
def start_keyboard_listener():
global listener
listener = keyboard.Listener(on_press=on_press, on_release=on_release)
listener.start()
def on_press(key):
global on_press_flag
current_keys.add(key)
# Ctrl + ` ์กฐํ•ฉ ๊ฐ์ง€
if keyboard.Key.ctrl_l in current_keys:
if any(k.vk == 192 for k in current_keys if hasattr(k, 'vk')):
on_press_flag = True
simulate_shortcuts()
def on_release(key):
try:
current_keys.remove(key)
except KeyError:
pass
def v_automatic(save_position, prompt_position):
# ํ”„๋กฌํ”„ํŠธ ์ฐฝ ํด๋ฆญ
copy_to_clipboard()
pyautogui.click(prompt_position)
time.sleep(0.5)
random_function()
pyautogui.hotkey('ctrl', 'a', 'v','Right','Right','Enter')
time.sleep(0.5)
pyautogui.click(save_position)
def start_automation(save_position, prompt_position, label, window_to_close, automation_event):
def automation_task():
while automation_event.is_set():
random_delay = random.uniform(17.5, 23.5)
next_click_time = time.time() + random_delay
while time.time() < next_click_time and automation_event.is_set():
time_remaining = max(next_click_time - time.time(), 0)
label.config(text=f"๋‹ค์Œ ํด๋ฆญ๊นŒ์ง€: {time_remaining:.2f}์ดˆ")
time.sleep(0.1)
if automation_event.is_set():
v_automatic(save_position, prompt_position)
automation_thread = threading.Thread(target=automation_task, daemon=True)
automation_thread.start()
random_function()
def stop_automation():
automation_event.clear()
window_to_close.destroy()
window_to_close.protocol("WM_DELETE_WINDOW", stop_automation)
def stop_automation(window_to_close, automation_event, start_button, stop_button):
automation_event.clear() # Stop the automation task
start_button['state'] = 'normal' # Enable the start button
stop_button['state'] = 'disabled' # Disable the stop button
window_to_close.destroy() # Close the automation window
window.deiconify()
# ๋ผ๋ฒจ์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํ•จ์ˆ˜
def update_label(label, text):
def task():
label.config(text=text)
label.after(1000, task) # ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ UI ์—…๋ฐ์ดํŠธ
def open_automation_window():
window.iconify()
automation_event = threading.Event()
automation_event.set() # Enable the automation event
auto_window = tk.Toplevel(window)
auto_window.title("์ž๋™ํ™” ์„ค์ •")
auto_window.geometry("300x200") # ์ฐฝ ํฌ๊ธฐ ์กฐ์ •
auto_window.attributes('-topmost', True) # ์ฐฝ์„ ํ•ญ์ƒ ๋งจ ์œ„์— ์œ„์น˜
auto_window.focus_force() # ์ฐฝ ์—ด๋ฆด ๋•Œ ํฌ์ปค์Šค ๊ฐ•์ œ ์ด๋™
save_position = None
prompt_position = None
automation_running = threading.Event()
def get_mouse_position(event=None):
nonlocal save_position, prompt_position
x, y = pyautogui.position()
if not save_position:
save_position = (x, y)
position_label.config(text=f"์ €์žฅ ๋ฒ„ํŠผ์˜ ์ขŒํ‘œ: {x}, {y}\nํ”„๋กฌํ”„ํŠธ ์ฐฝ์˜ ์ขŒํ‘œ: ")
elif not prompt_position:
prompt_position = (x, y)
position_label.config(text=f"์ €์žฅ ๋ฒ„ํŠผ์˜ ์ขŒํ‘œ: {save_position[0]}, {save_position[1]}\nํ”„๋กฌํ”„ํŠธ ์ฐฝ์˜ ์ขŒํ‘œ: {x}, {y}")
start_button.config(state="normal")
if save_position and prompt_position:
start_button.config(state="normal")
stop_button.config(state="normal")
position_label = tk.Label(auto_window, text="์—”ํ„ฐ๋ฅผ ๋ˆŒ๋Ÿฌ ๋งˆ์šฐ์Šค ์ขŒํ‘œ๋ฅผ ์ €์žฅํ•˜์„ธ์š”\n(ํด๋ฆญ X, 1.์ €์žฅ->2.ํ”„๋กฌํ”„ํŠธ์ฐฝ ์ˆœ์„œ)", justify=tk.LEFT)
position_label.pack(pady=10)
start_button = tk.Button(auto_window, text="์‹œ์ž‘", state="disabled",
command=lambda: start_automation(save_position, prompt_position, countdown_label, auto_window, automation_event))
start_button.pack(side=tk.LEFT, fill='x', expand=True)
stop_button = tk.Button(auto_window, text="์ค‘์ง€", state="disabled",
command=lambda: stop_automation(auto_window, automation_event, start_button, stop_button))
stop_button.pack(side=tk.RIGHT, fill='x', expand=True)
countdown_label = tk.Label(auto_window, text="")
countdown_label.pack(pady=10)
auto_window.bind('<Return>', get_mouse_position)
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")
pretest = text_output.get("1.0", tk.END).split(', ')
if (turbo_var.get() == 1):
if ( 'sex' not in pretest or '1girl' not in pretest or '1boy' not in pretest):
tprint('๋ถ€์ŠคํŠธ ๊ธฐ๋Šฅ์€ 1girl, 1boy, sex ์„ธ๊ฐ€์ง€ ํ‚ค์›Œ๋“œ๊ฐ€ ์žˆ์–ด์•ผ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.','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 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[:25]
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
if(result["boys"]):
#group sex
if(result["girls"]):
pass
#gangbang
elif(result["1girl"]):
pass
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"]):
if(result["girls"]):
pass
elif(result["1girl"]):
if('sex,' in positive):
sex_pos_keywords = ['stomach bulge','insertion', 'fucked silly', 'x-ray', 'orgasm', 'cross-section', 'uterus', 'overflow', 'rape']
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'
key_index = filtered_keywords.index('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('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')
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 # ์ฐธ์กฐ ์œ ์ง€
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
current_wildcard_artist = []
current_wildcard_character = []
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')
# "ํ”„๋กฌํ”„ํŠธ ๊ณ ์ •" ํ† ๊ธ€ ๋ฒ„ํŠผ
toggle_prompt_var = tk.IntVar()
button_toggle_prompt = tk.Checkbutton(button_frame, text="ํ”„๋กฌํ”„ํŠธ ๊ณ ์ •", variable=toggle_prompt_var)
button_toggle_prompt.grid(row=0, column=1, 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')
# ์ถ”์ฒœ ํ”„๋กฌํ”„ํŠธ ์กฐํšŒ ๋ฒ„ํŠผ ์„ค์ •
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')
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=15, column=0, padx=5, pady=5, sticky='ew')
resolution2_frame = tk.Frame(left_frame)
resolution2_frame.grid(row=16, 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=17, 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')
# ํ•˜์–€์ƒ‰ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
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
# ๋ฆฌ์Šค๋„ˆ ์‹œ์ž‘
listener = keyboard.Listener(on_press=on_press, on_release=on_release)
listener.start()
# ํ‚ค๋ณด๋“œ ๋ฆฌ์Šค๋„ˆ ์Šค๋ ˆ๋“œ ์‹œ์ž‘
listener_thread = threading.Thread(target=listener.join, daemon=True)
listener_thread.start()
Auto_login_check()
window.protocol("WM_DELETE_WINDOW", exit_program)
window.mainloop()