|
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, ImageFilter,ImageTk |
|
from IPython.display import display |
|
import win32clipboard |
|
from io import BytesIO |
|
from datetime import datetime |
|
import arti_list, tagbag, wlist |
|
from ttkthemes import ThemedTk |
|
|
|
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}" |
|
|
|
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 }) |
|
|
|
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}" }) |
|
|
|
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 |
|
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) |
|
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": 0.0, |
|
"noise_schedule": "native", |
|
} |
|
|
|
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" |
|
|
|
|
|
with open(f"error_log.txt", "a") as file: |
|
file.write(error_message) |
|
|
|
global access_token |
|
try: |
|
zipped_bytes = generate_image(access_token, positive, "nai-diffusion-3", "generate", params) |
|
d = Path("output_NAI") |
|
d.mkdir(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.image = tk_image |
|
output_file_path = "output_image.jpg" |
|
i.save(output_file_path) |
|
except Exception as e: |
|
|
|
log_error(e, "path_to_output_folder") |
|
time.sleep(random.uniform(3.0, 9.0)) |
|
button.config(state=tk.DISABLED) |
|
window.event_generate(GENERATE_EVENT, when="tail") |
|
|
|
time.sleep(random.uniform(1.0, 2.5)) |
|
button.config(state=tk.NORMAL) |
|
running_flag = False |
|
|
|
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") |
|
|
|
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 |
|
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 = [] |
|
|
|
def exclude(): |
|
global total_rows, cached_rows |
|
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 = [] |
|
|
|
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:] |
|
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 |
|
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 = [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() |
|
print(whatthefuck) |
|
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 |
|
print(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(',') |
|
|
|
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 |
|
|
|
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 = [] |
|
|
|
|
|
|
|
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_keywords = [kw for kw in random_row_keywords if 'boy' in kw and len(kw) <= 7] |
|
|
|
|
|
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] |
|
|
|
|
|
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) |
|
|
|
|
|
|
|
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')) |
|
temp_first_keywords = boy_keywords + girl_keywords + 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: |
|
random_row_keywords.remove(keyword) |
|
temp_rm.append(keyword) |
|
for keyword in random_row_keywords: |
|
if "(" in keyword: |
|
random_row_keywords.remove(keyword) |
|
temp_rm.append(keyword) |
|
print('removed : ',temp_rm) |
|
|
|
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) |
|
|
|
last_selected_row_keywords = random_row_keywords |
|
|
|
if random_artist_var.get(): |
|
temp_first_keywords.append(formatted_artist_random_keyword) |
|
|
|
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 |
|
|
|
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] |
|
|
|
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: |
|
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 exit_program(): |
|
window.destroy() |
|
|
|
def save_settings(): |
|
global NAI_ID |
|
with open('app_settings.txt', 'w', encoding='utf-8') as f: |
|
if(len(entry_file_path.get()) > 4): |
|
f.write(entry_file_path.get() + '\n') |
|
else: f.write(" "+'\n') |
|
if(len(entry_keyword.get()) > 3): |
|
f.write(entry_keyword.get() + '\n') |
|
else: f.write(" "+'\n') |
|
if(len(entry_deep_search.get()) > 3): |
|
f.write(entry_deep_search.get() + '\n') |
|
else: f.write(" "+'\n') |
|
if(len(entry_fixed_prompt.get()) > 4): |
|
f.write(entry_fixed_prompt.get() + '\n') |
|
else: f.write(" "+'\n') |
|
if(len(entry_fixed_prompt_after.get()) > 4): |
|
f.write(entry_fixed_prompt_after.get() + '\n') |
|
else: f.write(" "+'\n') |
|
if(len(entry_auto_hide.get()) > 3): |
|
f.write(entry_auto_hide.get() + '\n') |
|
else: f.write(" "+'\n') |
|
if(len(negative_text.get("1.0", tk.END)) > 4): |
|
f.write(negative_text.get("1.0", tk.END)) |
|
else: f.write(" "+'\n') |
|
if(NAI_ID): f.write(NAI_ID + '\n' ) |
|
|
|
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_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_output2 = tk.Text(prompt_window, height=10, width=50) |
|
text_output2.pack(padx=10, pady=10) |
|
|
|
|
|
text_output3 = tk.Text(prompt_window, height=10, width=50) |
|
text_output3.pack(padx=10, pady=10) |
|
|
|
|
|
keyword_counts = analyze_cached_rows(cached_rows) |
|
|
|
|
|
most_common_count = keyword_counts.most_common(1)[0][1] if keyword_counts else 0 |
|
|
|
|
|
for keyword, count in keyword_counts.most_common(50): |
|
if count / most_common_count >= 0.5: |
|
text_output1.insert(tk.END, f"{keyword}, ", 'bold') |
|
else: |
|
text_output1.insert(tk.END, f"{keyword}, ") |
|
|
|
|
|
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) |
|
|
|
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) |
|
|
|
|
|
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() |
|
start_button['state'] = 'normal' |
|
stop_button['state'] = 'disabled' |
|
window_to_close.destroy() |
|
window.deiconify() |
|
|
|
|
|
def update_label(label, text): |
|
def task(): |
|
label.config(text=text) |
|
label.after(1000, task) |
|
|
|
def open_automation_window(): |
|
window.iconify() |
|
automation_event = threading.Event() |
|
automation_event.set() |
|
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): |
|
button.config(state=tk.DISABLED) |
|
positive = text_output.get("1.0", tk.END) |
|
negative = negative_text.get("1.0", "end-1c").strip() |
|
thread = threading.Thread(target=generate, args=(width, height, positive, negative, button)) |
|
thread.start() |
|
|
|
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() |
|
|
|
NAI_ID_label = tk.Label(NAI_setting_window, text="NAI ID: ") |
|
NAI_ID_label.grid(row=0, column=0, columnspan=2, sticky='w') |
|
entry_NAI_ID = tk.Entry(NAI_setting_window, width=50) |
|
entry_NAI_ID.grid(row=0, column=1, columnspan=2, padx=100, pady=5, sticky='e') |
|
if(NAI_ID): entry_NAI_ID.insert(tk.END,NAI_ID) |
|
NAI_PW_label = tk.Label(NAI_setting_window, text="NAI PW: ") |
|
NAI_PW_label.grid(row=1, column=0, columnspan=2, sticky='w') |
|
entry_NAI_PW = tk.Entry(NAI_setting_window, 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, 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 |
|
except Exception as e: |
|
print(e) |
|
NAI_close() |
|
|
|
connect_button = tk.Button(NAI_setting_window, 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, 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, text="ํด๋น ์ ์๊ธฐ๋ฅ์ ์ ์์ ์ธ ์ ์ ํจํด์ด ์๋์ ์ฐธ๊ณ ๋ถํ๋๋ฆฝ๋๋ค.", 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) |
|
running_flag = True |
|
|
|
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 ([], []) |
|
|
|
|
|
|
|
random_artist_window = tk.Toplevel(window) |
|
|
|
|
|
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(): |
|
|
|
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(): |
|
|
|
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_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) |
|
|
|
|
|
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_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) |
|
|
|
|
|
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): |
|
artist_wildcard_check = artist_text.get("1.0", tk.END) |
|
if len(artist_wildcard_check) > 5: |
|
lines = artist_wildcard_check.strip().split("\n") |
|
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()] |
|
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) |
|
if len(character_wildcard_check) > 5: |
|
lines = character_wildcard_check.strip().split("\n") |
|
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()] |
|
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): |
|
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)) |
|
window.deiconify() |
|
|
|
def find_keyword(index, keywords): |
|
for start, end, keyword in keywords: |
|
if start <= index <= end: |
|
print(keyword) |
|
return keyword |
|
return None |
|
|
|
def get_random_keyword(req_keyword): |
|
|
|
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] |
|
print(len(keywords)) |
|
random_index = random.randint(0, max_index) |
|
print(random_index) |
|
return find_keyword(random_index, keywords) |
|
|
|
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 =[] |
|
|
|
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") |
|
|
|
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') |
|
button_exclude = tk.Button(frame_buttons, text="ํด๋น ํค์๋ ์ ์ธ", command=exclude) |
|
button_exclude.grid(row=0, column=2, padx=5, sticky='ew') |
|
|
|
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') |
|
|
|
|
|
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, pady=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_copy = tk.Button(button_frame, text="๋ณต์ฌ", command=copy_to_clipboard) |
|
button_copy.grid(row=0, column=3, sticky='ew') |
|
|
|
|
|
button_exit = tk.Button(button_frame, text="์ข
๋ฃ", command=exit_program) |
|
button_exit.grid(row=0, column=4, 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=5, sticky='ew') |
|
button_generate.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') |
|
|
|
mac_var = tk.IntVar() |
|
mac_button = tk.Checkbutton(button_frame, text="์๋์์ฑ", variable=mac_var) |
|
mac_button.grid(row=0, column=7, 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') |
|
|
|
|
|
|
|
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) |
|
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') |
|
|
|
|
|
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) |
|
widldcard_button.grid(row=1, column=2, sticky='ew') |
|
|
|
|
|
folder_button = tk.Button(checkbox_frame, text="์ ์ฅ ํด๋", command=open_file_explorer) |
|
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') |
|
|
|
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') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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") |
|
|
|
|
|
btn_add_low_freq = tk.Button(right_frame, text="์ด๋ฏธ์ง๋ฅผ ํด๋ฆฝ๋ณด๋์ ๋ณต์ฌ", fg="blue", command=copy_image_to_clipboard) |
|
btn_add_low_freq.grid(row=16, column=0, 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() |
|
|
|
window.mainloop() |
|
|