You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RedditVideoMakerBot/utils/gui_utils.py

213 lines
6.3 KiB

import json
import re
from pathlib import Path
import toml
import tomlkit
from flask import flash
# Get validation checks from template
def get_checks():
template = toml.load("utils/.config.template.toml")
checks = {}
def unpack_checks(obj: dict):
for key in obj.keys():
if "optional" in obj[key].keys():
checks[key] = obj[key]
else:
unpack_checks(obj[key])
unpack_checks(template)
return checks
# Get current config (from config.toml) as dict
def get_config(obj: dict, done={}):
for key in obj.keys():
if not isinstance(obj[key], dict):
done[key] = obj[key]
else:
get_config(obj[key], done)
return done
# Checks if value is valid
def check(value, checks):
incorrect = False
if value == "False":
value = ""
if not incorrect and "type" in checks:
try:
value = eval(checks["type"])(value)
except Exception:
incorrect = True
if (
not incorrect and "options" in checks and value not in checks["options"]
): # FAILSTATE Value is not one of the options
incorrect = True
if (
not incorrect
and "regex" in checks
and (
(isinstance(value, str) and re.match(checks["regex"], value) is None)
or not isinstance(value, str)
)
): # FAILSTATE Value doesn't match regex, or has regex but is not a string.
incorrect = True
if (
not incorrect
and not hasattr(value, "__iter__")
and (
("nmin" in checks and checks["nmin"] is not None and value < checks["nmin"])
or ("nmax" in checks and checks["nmax"] is not None and value > checks["nmax"])
)
):
incorrect = True
if (
not incorrect
and hasattr(value, "__iter__")
and (
("nmin" in checks and checks["nmin"] is not None and len(value) < checks["nmin"])
or ("nmax" in checks and checks["nmax"] is not None and len(value) > checks["nmax"])
)
):
incorrect = True
if incorrect:
return "Error"
return value
# Modify settings (after form is submitted)
def modify_settings(data: dict, config_load, checks: dict):
# Modify config settings
def modify_config(obj: dict, name: str, value: any):
for key in obj.keys():
if name == key:
obj[key] = value
elif not isinstance(obj[key], dict):
continue
else:
modify_config(obj[key], name, value)
# Remove empty/incorrect key-value pairs
data = {key: value for key, value in data.items() if value and key in checks.keys()}
# Validate values
for name in data.keys():
value = check(data[name], checks[name])
# Value is invalid
if value == "Error":
flash("Some values were incorrect and didn't save!", "error")
else:
# Value is valid
modify_config(config_load, name, value)
# Save changes in config.toml
with Path("config.toml").open("w") as toml_file:
toml_file.write(tomlkit.dumps(config_load))
flash("Settings saved!")
return get_config(config_load)
# Delete background video
def delete_background(key):
# Read backgrounds.json
with open("utils/backgrounds.json", "r", encoding="utf-8") as backgrounds:
data = json.load(backgrounds)
# Remove background from backgrounds.json
with open("utils/backgrounds.json", "w", encoding="utf-8") as backgrounds:
if data.pop(key, None):
json.dump(data, backgrounds, ensure_ascii=False, indent=4)
else:
flash("Couldn't find this background. Try refreshing the page.", "error")
return
# Remove background video from ".config.template.toml"
config = tomlkit.loads(Path("utils/.config.template.toml").read_text())
config["settings"]["background"]["background_choice"]["options"].remove(key)
with Path("utils/.config.template.toml").open("w") as toml_file:
toml_file.write(tomlkit.dumps(config))
flash(f'Successfully removed "{key}" background!')
# Add background video
def add_background(youtube_uri, filename, citation, position):
# Validate YouTube URI
regex = re.compile(r"(?:\/|%3D|v=|vi=)([0-9A-z\-_]{11})(?:[%#?&]|$)").search(youtube_uri)
if not regex:
flash("YouTube URI is invalid!", "error")
return
youtube_uri = f"https://www.youtube.com/watch?v={regex.group(1)}"
# Check if position is valid
if position == "" or position == "center":
position = "center"
elif position.isdecimal():
position = int(position)
else:
flash('Position is invalid! It can be "center" or decimal number.', "error")
return
# Sanitize filename
regex = re.compile(r"^([a-zA-Z0-9\s_-]{1,100})$").match(filename)
if not regex:
flash("Filename is invalid!", "error")
return
filename = filename.replace(" ", "_")
# Check if background doesn't already exist
with open("utils/backgrounds.json", "r", encoding="utf-8") as backgrounds:
data = json.load(backgrounds)
# Check if key isn't already taken
if filename in list(data.keys()):
flash("Background video with this name already exist!", "error")
return
# Check if the YouTube URI isn't already used under different name
if youtube_uri in [data[i][0] for i in list(data.keys())]:
flash("Background video with this YouTube URI is already added!", "error")
return
# Add background video to json file
with open("utils/backgrounds.json", "r+", encoding="utf-8") as backgrounds:
data = json.load(backgrounds)
data[filename] = [youtube_uri, filename + ".mp4", citation, position]
backgrounds.seek(0)
json.dump(data, backgrounds, ensure_ascii=False, indent=4)
# Add background video to ".config.template.toml"
config = tomlkit.loads(Path("utils/.config.template.toml").read_text())
config["settings"]["background"]["background_choice"]["options"].append(filename)
with Path("utils/.config.template.toml").open("w") as toml_file:
toml_file.write(tomlkit.dumps(config))
flash(f'Added "{citation}-{filename}.mp4" as a new background video!')
return