update(setup): improve setup UI

This commit is contained in:
Romain J 2020-08-26 17:15:38 +02:00
parent 1f88499d44
commit c1e253689d
4 changed files with 112 additions and 75 deletions

View File

@ -39,12 +39,12 @@ Continue to [create the venv](#creating-the-virtual-environnement).
#### Windows #### Windows
*go to hell* *not for now and not for the future*
## Creating the Virtual Environnement ## Creating the Virtual Environment
To set up the virtual environnement and install the bot, simply run this two commands: To set up the virtual environment and install the bot, simply run this two commands:
```shell script ```shell script
make make

View File

@ -24,11 +24,11 @@ install_requires =
certifi==2020.4.5.1 certifi==2020.4.5.1
chardet==3.0.4 chardet==3.0.4
ciso8601==2.1.3 ciso8601==2.1.3
click==7.1.2
colorama==0.4.3 colorama==0.4.3
discord-flags==2.1.1 discord-flags==2.1.1
discord.py==1.3.3 discord.py==1.3.4
dnspython==1.16.0 dnspython==1.16.0
flatten-dict==0.3.0
humanize==2.4.0 humanize==2.4.0
idna==2.9 idna==2.9
import-expression==1.1.3 import-expression==1.1.3
@ -43,13 +43,13 @@ install_requires =
pytz==2020.1 pytz==2020.1
regex==2020.6.7 regex==2020.6.7
requests==2.23.0 requests==2.23.0
rich==6.0.0
six==1.15.0 six==1.15.0
toml>=0.9.4 toml>=0.9.4
tortoise-orm==0.16.13 tortoise-orm==0.16.13
typed-ast>=1.4.0 typed-ast>=1.4.0
typing-extensions==3.7.4.2 typing-extensions==3.7.4.2
urllib3==1.25.9 urllib3==1.25.9
websockets==8.1
wheel==0.34.2 wheel==0.34.2
yarl==1.4.2 yarl==1.4.2

View File

@ -1,3 +1,5 @@
from setuptools import setup from setuptools import setup
setup(python_requires=">=3.7") setup(
python_requires=">=3.7",
)

View File

@ -3,14 +3,17 @@ import logging
import re import re
import sys import sys
from pathlib import Path from pathlib import Path
from typing import NoReturn, Union, List, Set from typing import NoReturn, Union, List
import click from rich.prompt import Prompt, IntPrompt
from colorama import Fore, Style, init from rich.console import Console
from rich.rule import Rule
from rich import print
from tuxbot.core.data_manager import config_dir, app_dir from tuxbot.core.data_manager import config_dir, app_dir
init() console = Console()
console.clear()
try: try:
config_dir.mkdir(parents=True, exist_ok=True) config_dir.mkdir(parents=True, exist_ok=True)
@ -77,14 +80,15 @@ def get_name() -> str:
""" """
name = "" name = ""
while not name: while not name:
print( name = Prompt.ask(
"What name do you want to give this instance?\n" "What name do you want to give this instance?\n"
"(valid characters: A-Z, a-z, 0-9, _, -)" "[i](valid characters: A-Z, a-z, 0-9, _, -)[/i]\n",
default="prod",
console=console
) )
name = input("> ")
if re.fullmatch(r"[a-zA-Z0-9_\-]*", name) is None: if re.fullmatch(r"[a-zA-Z0-9_\-]*", name) is None:
print() print()
print(Fore.RED + "ERROR: Invalid characters provided" + Style.RESET_ALL) print("[prompt.invalid]ERROR: Invalid characters provided")
name = "" name = ""
return name return name
@ -113,42 +117,35 @@ def get_data_dir(instance_name: str) -> Path:
except OSError: except OSError:
print() print()
print( print(
Fore.RED + f"mkdir: cannot create directory '{path}':" f"mkdir: cannot create directory '{path}': Permission denied"
f" Permission denied" + Style.RESET_ALL
) )
path = "" path = ""
return path return path
while not data_path_input: while not data_path_input:
print( data_path_input = Path(
"where do you want to save the configurations?\n" Prompt.ask(
"Press [enter] to keep the default path" "where do you want to save the configurations?",
default=str(data_path),
console=console
)
) )
print()
print(f"Default: {data_path}")
data_path_input = input("> ") try:
exists = data_path_input.exists()
except OSError:
print()
print(
"[prompt.invalid]"
"Impossible to verify the validity of the path,"
" make sure it does not contain any invalid characters."
)
data_path_input = ""
exists = False
if data_path_input != "": if data_path_input and not exists:
data_path_input = Path(data_path_input) data_path_input = make_data_dir(data_path_input)
try:
exists = data_path_input.exists()
except OSError:
print()
print(
Fore.RED + "Impossible to verify the validity of the path, "
"make sure it does not contain any invalid characters."
+ Style.RESET_ALL
)
data_path_input = ""
exists = False
if data_path_input and not exists:
data_path_input = make_data_dir(data_path_input)
else:
data_path_input = make_data_dir(data_path)
print() print()
print( print(
@ -156,7 +153,11 @@ def get_data_dir(instance_name: str) -> Path:
f"`{instance_name}` instance" f"`{instance_name}` instance"
) )
if not click.confirm("Please confirm", default=True): if Prompt.ask(
"Please confirm",
choices=["y", "n"], default="y",
console=console
) != "y":
print("Rerun the process to redo this configuration.") print("Rerun the process to redo this configuration.")
sys.exit(0) sys.exit(0)
@ -178,25 +179,23 @@ def get_token() -> str:
token = "" token = ""
while not token: while not token:
print( token = Prompt.ask(
"Please enter the bot token\n" "Please enter the bot token "
"(you can find it at https://discord.com/developers/applications)" "(you can find it at https://discord.com/developers/applications)",
console=console
) )
token = input("> ") if re.fullmatch(
if ( r"([a-zA-Z0-9]{24}\.[a-zA-Z0-9_]{6}\.[a-zA-Z0-9_\-]{27}"
re.fullmatch( r"|mfa\.[a-zA-Z0-9_\-]{84})",
r"([a-zA-Z0-9]{24}\.[a-zA-Z0-9_]{6}\.[a-zA-Z0-9_\-]{27}|mfa\.[a-zA-Z0-9_\-]{84})", token) \
token, is None:
) print("[prompt.invalid]ERROR: Invalid token provided")
is None
):
print(Fore.RED + "ERROR: Invalid token provided" + Style.RESET_ALL)
token = "" token = ""
return token return token
def get_multiple( def get_multiple(
question: str, confirmation: str, value_type: type question: str, confirmation: str, value_type: type
) -> List[Union[str, int]]: ) -> List[Union[str, int]]:
"""Give possibility to user to fill multiple value. """Give possibility to user to fill multiple value.
@ -214,15 +213,29 @@ def get_multiple(
List[Union[str, int]] List[Union[str, int]]
List containing user filled values. List containing user filled values.
""" """
print(question) prompt = IntPrompt if value_type is int else Prompt
user_input = input("> ")
user_input = prompt.ask(question, console=console)
if not user_input: if not user_input:
return [] return []
values = [user_input] values = [user_input]
while click.confirm(confirmation, default=False): while Prompt.ask(
values.append(value_type(input("> "))) confirmation,
choices=["y", "n"], default="y",
console=console
) != "n":
new = prompt.ask("Other")
if new not in values:
values.append(new)
else:
print(
f"[prompt.invalid]"
f"ERROR: `{new}` is already present, [i]ignored[/i]"
)
return values return values
@ -236,24 +249,23 @@ def additional_config() -> dict:
Dict with cog name as key and configs as value. Dict with cog name as key and configs as value.
""" """
p = Path(r"tuxbot/cogs").glob("**/additional_config.json") p = Path(r"tuxbot/cogs").glob("**/additional_config.json")
datas = {} data = {}
for file in p: for file in p:
print() print("\n" * 4)
cog_name = str(file.parent).split("/")[-1] cog_name = str(file.parent).split("/")[-1]
datas[cog_name] = {} data[cog_name] = {}
with file.open("r") as f: with file.open("r") as f:
data = json.load(f) data = json.load(f)
print(f"\n==Configuration for `{cog_name}` module==") print(Rule(f"\nConfiguration for `{cog_name}` module"))
for key, value in data.items(): for key, value in data.items():
print() print()
print(value["description"]) data[cog_name][key] = Prompt.ask(value["description"])
datas[cog_name][key] = input("> ")
return datas return data
def finish_setup(data_dir: Path) -> NoReturn: def finish_setup(data_dir: Path) -> NoReturn:
@ -264,15 +276,29 @@ def finish_setup(data_dir: Path) -> NoReturn:
data_dir:Path data_dir:Path
Where to save configs. Where to save configs.
""" """
print("Now, it's time to finish this setup by giving bot informations\n") print(
Rule(
"Now, it's time to finish this setup by giving bot information"
)
)
print()
token = get_token() token = get_token()
print() print()
prefixes = get_multiple( prefixes = get_multiple(
"Choice a (or multiple) prefix for the bot", "Add another prefix ?", str "Choice a (or multiple) prefix for the bot", "Add another prefix ?",
str
) )
mentionable = click.confirm("Does the bot answer if it's mentioned?", default=True)
print()
mentionable = Prompt.ask(
"Does the bot answer if it's mentioned?",
choices=["y", "n"],
default="y"
) == "y"
print()
owners_id = get_multiple( owners_id = get_multiple(
"Give the owner id of this bot", "Add another owner ?", int "Give the owner id of this bot", "Add another owner ?", int
) )
@ -305,7 +331,13 @@ def basic_setup() -> NoReturn:
"""Configs who refer to instances. """Configs who refer to instances.
""" """
print("Hi ! it's time for you to give me informations about you instance") print(
Rule(
"Hi ! it's time for you to give me information about you instance"
)
)
print()
name = get_name() name = get_name()
data_dir = get_data_dir(name) data_dir = get_data_dir(name)
@ -318,11 +350,14 @@ def basic_setup() -> NoReturn:
if name in instances_list: if name in instances_list:
print() print()
print( console.print(
Fore.RED + f"WARNING: An instance named `{name}` already exists " f"WARNING: An instance named `{name}` already exists "
f"Continuing will overwrite this instance configs." + Style.RESET_ALL f"Continuing will overwrite this instance configs.", style="red"
) )
if not click.confirm("Are you sure you want to continue?", default=False): if Prompt.ask(
"Are you sure you want to continue?",
choices=["y", "n"], default="n"
) == "n":
print("Abandon...") print("Abandon...")
sys.exit(0) sys.exit(0)