comfyui-discord/lib/parser.py

109 lines
3.6 KiB
Python

import random
import re
import copy
def get_prompt_parameters(user_message, settings):
params = {}
if "defaults" in settings.keys():
params = settings["defaults"].copy()
mutable_string = user_message
mutable_string = re.sub(r"[^A-Za-z0-9 \-,\.>\(\)]", "", mutable_string)
mutable_string = re.sub(r"\s{1,}", " ", mutable_string)
# Get the options from the mutable string:
options = ""
options_re = r"^((.+)>)"
match = re.search(options_re, mutable_string)
if match is not None:
options = match.group(2).strip()
mutable_string = re.sub(options_re, "", mutable_string)
# Get the repeat_n_times from the mutable string:
repeat_re = r"( x([0-9]{1,2}))$"
match = re.search(repeat_re, mutable_string)
if match is not None:
params["repeat_n_times"] = int(match.group(2).strip())
mutable_string = re.sub(repeat_re, "", mutable_string)
# Get the negative prompt from the mutable string:
negative_re = r"( -(.+))$"
match = re.search(negative_re, mutable_string)
if match is not None:
params["negative"] = match.group(2).strip()
mutable_string = re.sub(negative_re, "", mutable_string)
params["positive"] = mutable_string.strip()
# Allow the user to set the square size by SSSp:
if params["width"] == params["height"]:
match = re.search(r"([1-9][0-9]{2,3})p", options)
if match is not None:
s = int(match.group(1))
params["width"] = s
params["height"] = s
# Allow user to specify ratio:
match = re.search(r"([0-9\.]{1,5})(x|\:)([0-9\.]{1,5})", options)
if match is not None:
# Use the smallest dimension for calculations:
size = params["width"] if params["width"] <= params["height"] else params["height"]
r_num = float(match.group(1))
r_den = float(match.group(3))
# Largest dimension not to exceed the size:
if r_num > r_den:
ratio = 1.0 * r_num / r_den
params["width"] = size
params["height"] = size * (1 / ratio)
elif r_num < r_den:
ratio = 1.0 * r_num / r_den
params["width"] = size * ratio
params["height"] = size
# Allow user to explicitly set the size by WWWxHHHp:
match = re.search(r"([0-9]{3,})(x)([0-9]{3,})p", options)
if match is not None:
params["width"] = int(match.group(1))
params["height"] = int(match.group(3))
# Allow all other explicit parameter overrides:
overwrite_re = r"([A-Za-z_]{1,})=?([0-9\.]{1,})"
for (k, v) in re.findall(overwrite_re, options):
params[k] = float(v)
# Process limitations, e.g. max_width and max_height:
params_clone = copy.deepcopy(params)
for key in params.keys():
limit_value = params[key]
term = "min_"
if re.search(rf"^{term}", key):
target_key = re.sub(rf"^{term}", "", key)
if target_key not in params.keys():
params_clone[target_key] = limit_value
params_clone[target_key] = limit_value if params[target_key] < limit_value else params[target_key]
term = "max_"
if re.search(rf"^{term}", key):
target_key = re.sub(rf"^{term}", "", key)
if target_key in params.keys():
params_clone[target_key] = limit_value if params[target_key] > limit_value else params[target_key]
term = "force_"
if re.search(rf"^{term}", key):
target_key = re.sub(rf"^{term}", "", key)
params_clone[target_key] = limit_value
params = params_clone
return params