completely revampted .env.template syntax, shiny new checker, better formatting and more

remotes/origin/CordlessCoder-envchecker
CordlessCoder 2 years ago
parent b2b4a08741
commit 629b74c5d4

@ -1,24 +1,40 @@
REDDIT_CLIENT_ID="" REDDIT_CLIENT_ID=""
#EXPLANATION the ID of your Reddit app of SCRIPT type #EXPLANATION the ID of your Reddit app of SCRIPT type
#RANGE 12:30
#MATCH_REGEX [-a-zA-Z0-9._~+/]+=*$
#OOB_ERROR The ID should be over 12 and under 30 characters, double check your input.
REDDIT_CLIENT_SECRET="" REDDIT_CLIENT_SECRET=""
#EXPLANATION the SECRET of your Reddit app of SCRIPT type #EXPLANATION the SECRET of your Reddit app of SCRIPT type
#RANGE 20:40
#MATCH_REGEX [-a-zA-Z0-9._~+/]+=*$
#OOB_ERROR The secret should be over 20 and under 40 characters, double check your input.
REDDIT_USERNAME="" REDDIT_USERNAME=""
#EXPLANATION the username of your reddit account #EXPLANATION the username of your reddit account
#RANGE 3:20
#MATCH_REGEX [_0-9a-zA-Z]+$
#OOB_ERROR A username HAS to be between 3 and 20 characters
REDDIT_PASSWORD="" REDDIT_PASSWORD=""
#EXPLANATION the password of your reddit account #EXPLANATION the password of your reddit account
#RANGE 8:None
#OOB_ERROR Password too short
#OPTIONAL #OPTIONAL
RANDOM_THREAD="no" RANDOM_THREAD="no"
#EXPLANATION If set to no, it will ask you a thread link to extract the thread, if yes it will randomize it. Default: "no" # If set to no, it will ask you a thread link to extract the thread, if yes it will randomize it. Default: "no"
REDDIT_2FA="" REDDIT_2FA=""
#MATCH_REGEX ^(yes|no) #MATCH_REGEX ^(yes|no)
#EXPLANATION Whether you have Reddit 2FA enabled, Valid options are "yes" and "no" #EXPLANATION Whether you have Reddit 2FA enabled, Valid options are "yes" and "no"
SUBREDDIT="AskReddit" SUBREDDIT="AskReddit"
#EXPLANATION what subreddit to pull posts from, the name of the sub, not the URL
#RANGE 3:20
#MATCH_REGEX [_0-9a-zA-Z]+$
#OOB_ERROR A subreddit name HAS to be between 3 and 20 characters
ALLOW_NSFW="False" ALLOW_NSFW="False"
#EXPLANATION Whether to allow NSFW content, True or False #EXPLANATION Whether to allow NSFW content, True or False
#MATCH_REGEX ^(True|False)$ #MATCH_REGEX ^(True|False)$
@ -29,16 +45,22 @@ POST_ID=""
THEME="LIGHT" THEME="LIGHT"
#EXPLANATION sets the Reddit theme, either LIGHT or DARK #EXPLANATION sets the Reddit theme, either LIGHT or DARK
#MATCH_REGEX ^(dark|light|DARK|LIGHT)$
TIMES_TO_RUN="" TIMES_TO_RUN=""
#EXPLANATION used if you want to run multiple times. set to an int e.g. 4 or 29 and leave blank for 1 #EXPLANATION used if you want to run multiple times. set to an int e.g. 4 or 29 and leave blank for 1
MAX_COMMENT_LENGTH="500" MAX_COMMENT_LENGTH="500"
#EXPLANATION max number of characters a comment can have. default is 500 #EXPLANATION max number of characters a comment can have. default is 500
#RANGE 0:10000
#MATCH_TYPE int
#OOB_ERROR the max comment length should be between 0 and 10000
#OPTIONAL
OPACITY="1" OPACITY="1"
#EXPLANATION sets the opacity of the comments, Range is 0 -> 1 recommended around 0.8-0.9 #EXPLANATION Sets the opacity of the comments when overlayed over the background
#RANGE 0:1
#MATCH_TYPE float
#OOB_ERROR The opacity HAS to be between 0 and 1
# see different voice options: todo: add docs # see different voice options: todo: add docs
VOICE="Matthew" VOICE="Matthew"
@ -49,4 +71,4 @@ TTsChoice="polly"
#OPTIONAL #OPTIONAL
STORYMODE="False" STORYMODE="False"
#EXPLANATION IN-PROGRESS - not yet implemented # IN-PROGRESS - not yet implemented

@ -1,3 +1,4 @@
# For most projects, this workflow file will not need changing; you simply need # For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository. # to commit it to your repository.
# #

@ -1,5 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python
import time
from subprocess import Popen from subprocess import Popen
from dotenv import load_dotenv from dotenv import load_dotenv
@ -26,23 +25,16 @@ print(
""" """
) )
load_dotenv()
# Modified by JasonLovesDoggo # Modified by JasonLovesDoggo
print_markdown( print_markdown(
"### Thanks for using this tool! [Feel free to contribute to this project on GitHub!](https://lewismenelaws.com) If you have any questions, feel free to reach out to me on Twitter or submit a GitHub issue. You can find solutions to many common problems in the [Documentation](https://luka-hietala.gitbook.io/documentation-for-the-reddit-bot/)" "### Thanks for using this tool! [Feel free to contribute to this project on GitHub!](https://lewismenelaws.com) If you have any questions, feel free to reach out to me on Twitter or submit a GitHub issue. You can find solutions to many common problems in the [Documentation](https://luka-hietala.gitbook.io/documentation-for-the-reddit-bot/)"
) )
client_id = getenv("REDDIT_CLIENT_ID")
client_secret = getenv("REDDIT_CLIENT_SECRET")
username = getenv("REDDIT_USERNAME")
password = getenv("REDDIT_PASSWORD")
reddit2fa = getenv("REDDIT_2FA")
def main(): def main():
if check_env() is not True: if check_env() is not True:
exit() exit()
load_dotenv()
cleanup() cleanup()
def get_obj(): def get_obj():
@ -58,8 +50,7 @@ def main():
def run_many(times): def run_many(times):
for x in range(times): for x in range(1, times + 1):
x = x + 1
print_step( print_step(
f'on the {x}{("st" if x == 1 else ("nd" if x == 2 else ("rd" if x == 3 else "th")))} iteration of {times}' f'on the {x}{("st" if x == 1 else ("nd" if x == 2 else ("rd" if x == 3 else "th")))} iteration of {times}'
) # correct 1st 2nd 3rd 4th 5th.... ) # correct 1st 2nd 3rd 4th 5th....

@ -1,75 +1,184 @@
#!/usr/bin/env python #!/usr/bin/env python
import os import os
from rich.console import Console from rich.console import Console
from rich.table import Table
from rich import box
import re import re
import dotenv import dotenv
from utils.console import handle_input from utils.console import handle_input
console = Console() console = Console()
success = True
def check_env() -> bool: def check_env() -> bool:
if not os.path.exists(".env.template"): if not os.path.exists(".env.template"):
console.print("[red]Couldn't find .env.template. Unable to check variables.") console.print("[red]Couldn't find .env.template. Unable to check variables.")
return False return True
if not os.path.exists(".env"):
console.print("[red]Couldn't find the .env file, creating one now.")
with open(".env", "x") as file:
file.write("")
with open(".env.template", "r") as template: with open(".env.template", "r") as template:
# req_envs = [env.split("=")[0] for env in template.readlines() if "=" in env] # req_envs = [env.split("=")[0] for env in template.readlines() if "=" in env]
matching = {} matching = {}
explanations = {} explanations = {}
bounds = {}
types = {}
oob_errors = {}
req_envs = [] req_envs = []
var_optional = False var_optional = False
for line in template.readlines(): for line in template.readlines():
if "=" in line and var_optional is not True: if line.startswith("#") is not True and "=" in line and var_optional is not True:
req_envs.append(line.split("=")[0]) req_envs.append(line.split("=")[0])
elif "#OPTIONAL" in line: elif "#OPTIONAL" in line:
var_optional = True var_optional = True
elif line.startswith("#MATCH_REGEX "): elif line.startswith("#MATCH_REGEX "):
matching[req_envs[-1]] = line.removeprefix("#MATCH_REGEX ")[:-1] matching[req_envs[-1]] = line.removeprefix("#MATCH_REGEX ")[:-1]
var_optional = False var_optional = False
elif line.startswith("#OOB_ERROR "):
oob_errors[req_envs[-1]] = line.removeprefix("#OOB_ERROR ")[:-1]
var_optional = False
elif line.startswith("#RANGE "):
bounds[req_envs[-1]] = tuple(
map(
lambda x: float(x) if x != "None" else None,
line.removeprefix("#RANGE ")[:-1].split(":"),
)
)
var_optional = False
elif line.startswith("#MATCH_TYPE "):
types[req_envs[-1]] = eval(line.removeprefix("#MATCH_TYPE ")[:-1].split()[0])
var_optional = False
elif line.startswith("#EXPLANATION "): elif line.startswith("#EXPLANATION "):
explanations[req_envs[-1]] = line.removeprefix("#EXPLANATION ")[:-1] explanations[req_envs[-1]] = line.removeprefix("#EXPLANATION ")[:-1]
var_optional = False var_optional = False
else: else:
var_optional = False var_optional = False
missing = [] missing = set()
incorrect = [] incorrect = set()
dotenv.load_dotenv() dotenv.load_dotenv()
for env in req_envs: for env in req_envs:
value = os.getenv(env) value = os.getenv(env)
if value is None: if value is None:
missing.append(env) missing.add(env)
continue continue
if env in matching.keys(): if env in matching.keys():
env, re.match(matching[env], value) is None and incorrect.append(env) re.match(matching[env], value) is None and incorrect.add(env)
if len(missing): if env in bounds.keys() and env not in types.keys():
for i in range(len(missing)): len(value) >= bounds[env][0] or (
len(bounds[env]) > 1 and bounds[env][1] >= len(value)
) or incorrect.add(env)
continue
if env in types.keys():
try: try:
missing[i] = missing[i] + ": " + explanations[missing[i]] temp = types[env](value)
except KeyError: if env in bounds.keys():
pass (bounds[env][0] <= temp or incorrect.add(env)) and len(bounds[env]) > 1 and (
console.print( bounds[env][1] >= temp or incorrect.add(env)
f"[red]{'These variables are'*(len(missing) > 1) or 'This variable is'} non-optional and missing: \n\n" )
+ "\n\n".join(missing) except ValueError:
incorrect.add(env)
if len(missing):
table = Table(
title="Missing variables",
highlight=True,
show_lines=True,
box=box.ROUNDED,
border_style="#414868",
header_style="#C0CAF5 bold",
title_justify="left",
title_style="#C0CAF5 bold",
)
table.add_column("Variable", justify="left", style="#7AA2F7 bold", no_wrap=True)
table.add_column("Explanation", justify="left", style="#BB9AF7", no_wrap=False)
table.add_column("Type", justify="center", style="#F7768E", no_wrap=True)
table.add_column("Min", justify="right", style="#F7768E", no_wrap=True)
table.add_column("Max", justify="left", style="#F7768E", no_wrap=True)
for env in missing:
table.add_row(
env,
explanations[env] if env in explanations.keys() else "No explanation given",
str(types[env].__name__) if env in types.keys() else "str",
str(bounds[env][0]) if env in bounds.keys() and bounds[env][1] is not None else "",
str(bounds[env][1])
if env in bounds.keys() and len(bounds[env]) > 1 and bounds[env][1] is not None
else "",
) )
console.print(table)
success = False success = False
if len(incorrect): if len(incorrect):
table = Table(
title="Incorrect variables",
highlight=True,
show_lines=True,
box=box.ROUNDED,
border_style="#414868",
header_style="#C0CAF5 bold",
title_justify="left",
title_style="#C0CAF5 bold",
)
table.add_column("Variable", justify="left", style="#7AA2F7 bold", no_wrap=True)
table.add_column("Current value", justify="left", style="#F7768E", no_wrap=False)
table.add_column("Explanation", justify="left", style="#BB9AF7", no_wrap=False)
table.add_column("Type", justify="center", style="#F7768E", no_wrap=True)
table.add_column("Min", justify="right", style="#F7768E", no_wrap=True)
table.add_column("Max", justify="left", style="#F7768E", no_wrap=True)
for env in incorrect:
table.add_row(
env,
os.getenv(env),
explanations[env] if env in explanations.keys() else "No explanation given",
str(types[env].__name__) if env in types.keys() else "str",
str(bounds[env][0]) if env in bounds.keys() else "None",
str(bounds[env][1]) if env in bounds.keys() and len(bounds[env]) > 1 else "None",
)
missing.add(env)
console.print(table)
if success is True:
return True
console.print( console.print(
f"[red]{'These variables are'*(len(incorrect) > 1) or 'This variable is'} set incorrectly: " "[green]Do you want to automatically overwrite incorrect variables and add the missing variables? (y/n)"
+ "\n".join(incorrect)
) )
success = False if not input().casefold().startswith("y"):
# if success is True: console.print("[red]Aborting: Unresolved missing variables")
# return True return False
# console.print("[green]Do you want to enter the missing variables by hand(y/n)") if len(incorrect):
# if not input().casefold().startswith("y"): with open(".env", "r+") as env_file:
# console.print("[red]Aborting: Unresolved missing variables") lines = []
# return success for line in env_file.readlines():
# with open(".env", "a") as env_file: line.split("=")[0].strip() not in incorrect and lines.append(line)
# for env in missing: env_file.seek(0)
# pass env_file.write("\n".join(lines))
return success env_file.truncate()
console.print("[green]Successfully removed incorrectly set variables from .env")
with open(".env", "a") as env_file:
for env in missing:
env_file.write(
env
+ "="
+ ('"' if env not in types.keys() else "")
+ str(
handle_input(
"[#F7768E bold]" + env + "[#C0CAF5 bold]=",
types[env] if env in types.keys() else False,
matching[env] if env in matching.keys() else ".*",
explanations[env]
if env in explanations.keys()
else "Incorrect input. Try again.",
bounds[env][0] if env in bounds.keys() else None,
bounds[env][1] if env in bounds.keys() and len(bounds[env]) > 1 else None,
oob_errors[env] if env in oob_errors.keys() else "Input too long/short.",
extra_info="[#C0CAF5 bold]⮶ "
+ (
explanations[env] if env in explanations.keys() else "No info available"
),
)
)
+ ('"' if env not in types.keys() else "")
+ "\n"
)
return True
if __name__ == "__main__": if __name__ == "__main__":

@ -36,10 +36,13 @@ def handle_input(
nmin=None, nmin=None,
nmax=None, nmax=None,
oob_error="", oob_error="",
extra_info="",
): ):
match = re.compile(match + "$") match = re.compile(match + "$")
console.print(extra_info, no_wrap=True)
while True: while True:
user_input = input(message + "\n> ").strip() console.print(message, end="")
user_input = input("").strip()
if re.match(match, user_input) is not None: if re.match(match, user_input) is not None:
if check_type is not False: if check_type is not False:
try: try:

Loading…
Cancel
Save