feat(setup): add configurator step
This commit is contained in:
parent
9020fe7201
commit
79ca4f95d6
5 changed files with 343 additions and 11 deletions
|
@ -2,8 +2,35 @@
|
|||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="c97c8a30-7573-4dcd-a0d4-5bf94b8ddbbd" name="5ed57ed9960f35191182a924 core" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.github/issue_template.md" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/dictionaries/romain.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/discord.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/inspectionProfiles/Project_Default.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/inspectionProfiles/profiles_settings.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/modules.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/tuxbot-bot-rewrite.iml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/vcs.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/setup.cfg" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/setup.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/__init__.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/__main__.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/cogs/images/__init__.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/cogs/images/images.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/cogs/logs/__init__.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/cogs/logs/logs.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/cogs/network/__init__.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/cogs/network/network.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/core/__init__.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/core/bot.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/core/config.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/core/models/__init__.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/core/utils/functions/cli.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/core/utils/functions/extra.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/tuxbot/setup.py" beforeDir="false" />
|
||||
</list>
|
||||
<list id="a3abf5c0-7587-46e4-8f09-88e34a1ab8a4" name="5ed41911b012e33f68a07e7a i18n" comment="" />
|
||||
<list id="6566fca1-2e90-48bb-9e74-dd3badbaca99" name="Default Changelist" comment="" />
|
||||
|
@ -35,7 +62,7 @@
|
|||
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
|
||||
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$/tuxbot/cogs/network" />
|
||||
<property name="node.js.detected.package.eslint" value="true" />
|
||||
<property name="node.js.detected.package.tslint" value="true" />
|
||||
<property name="node.js.path.for.package.eslint" value="project" />
|
||||
|
@ -54,8 +81,8 @@
|
|||
<recent name="$PROJECT_DIR$/tuxbot/core" />
|
||||
</key>
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$" />
|
||||
<recent name="$PROJECT_DIR$/tuxbot/cogs/network" />
|
||||
<recent name="$PROJECT_DIR$" />
|
||||
<recent name="$PROJECT_DIR$/tuxbot/cogs" />
|
||||
<recent name="$PROJECT_DIR$/utils/locales" />
|
||||
<recent name="$PROJECT_DIR$/cogs" />
|
||||
|
@ -93,7 +120,7 @@
|
|||
</task>
|
||||
<task id="5ed41911b012e33f68a07e7a" summary="i18n">
|
||||
<changelist id="a3abf5c0-7587-46e4-8f09-88e34a1ab8a4" name="5ed41911b012e33f68a07e7a i18n" comment="" />
|
||||
<created>1591139389877</created>
|
||||
<created>1591200420454</created>
|
||||
<option name="issue" value="true" />
|
||||
<url>https://trello.com/c/vK0cBbF2/38-i18n</url>
|
||||
<option name="number" value="38" />
|
||||
|
@ -105,7 +132,7 @@
|
|||
</task>
|
||||
<task active="true" id="5ed57ed9960f35191182a924" summary="core">
|
||||
<changelist id="c97c8a30-7573-4dcd-a0d4-5bf94b8ddbbd" name="5ed57ed9960f35191182a924 core" comment="" />
|
||||
<created>1591139389877</created>
|
||||
<created>1591200420454</created>
|
||||
<option name="issue" value="true" />
|
||||
<url>https://trello.com/c/SafaMBht/40-core</url>
|
||||
<option name="number" value="40" />
|
||||
|
@ -114,7 +141,7 @@
|
|||
<workItem from="1591049956280" duration="4910000" />
|
||||
<workItem from="1591054878071" duration="1039000" />
|
||||
<workItem from="1591088657371" duration="4107000" />
|
||||
<workItem from="1591128560850" duration="9119000" />
|
||||
<workItem from="1591128560850" duration="24277000" />
|
||||
</task>
|
||||
<option name="localTasksCounter" value="2" />
|
||||
<option name="createBranch" value="false" />
|
||||
|
@ -182,10 +209,10 @@
|
|||
<screen x="1920" y="0" width="1920" height="1080" />
|
||||
</state>
|
||||
<state x="2440" y="156" width="873" height="799" key="com.intellij.openapi.editor.actions.MultiplePasteAction$ClipboardContentChooser/1920.0.1920.1080/0.29.1920.1051@1920.0.1920.1080" timestamp="1590155739870" />
|
||||
<state x="2673" y="469" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2" timestamp="1590879398033">
|
||||
<state x="2673" y="469" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2" timestamp="1591199362509">
|
||||
<screen x="1920" y="0" width="1920" height="1080" />
|
||||
</state>
|
||||
<state x="2673" y="469" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2/1920.0.1920.1080/0.29.1920.1051@1920.0.1920.1080" timestamp="1590879398033" />
|
||||
<state x="2673" y="469" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2/1920.0.1920.1080/0.29.1920.1051@1920.0.1920.1080" timestamp="1591199362509" />
|
||||
<state x="2584" y="164" width="592" height="783" key="find.popup" timestamp="1589983672115">
|
||||
<screen x="1920" y="0" width="1920" height="1080" />
|
||||
</state>
|
||||
|
|
|
@ -8,7 +8,7 @@ It is preferable to install the bot on a dedicated user. If you don't know how t
|
|||
- Python 3.7 or greater
|
||||
- Pip
|
||||
- Git
|
||||
- JRE 11
|
||||
- JRE 11 (voice support)
|
||||
|
||||
### Operating systems
|
||||
|
||||
|
|
22
tuxbot/cogs/logs/additional_config.json
Normal file
22
tuxbot/cogs/logs/additional_config.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"dm": {
|
||||
"description": "Webhook url for DMs events",
|
||||
"value": "str"
|
||||
},
|
||||
"mentions": {
|
||||
"description": "Webhook url for mentions events",
|
||||
"value": "str"
|
||||
},
|
||||
"guilds": {
|
||||
"description": "Webhook url for guilds events",
|
||||
"value": "str"
|
||||
},
|
||||
"errors": {
|
||||
"description": "Webhook url for errors events",
|
||||
"value": "str"
|
||||
},
|
||||
"gateway": {
|
||||
"description": "Webhook url for gateway events",
|
||||
"value": "str"
|
||||
}
|
||||
}
|
6
tuxbot/cogs/network/additional_config.json
Normal file
6
tuxbot/cogs/network/additional_config.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"ipinfo": {
|
||||
"description": "API token for ipinfo.io",
|
||||
"value": "str"
|
||||
}
|
||||
}
|
279
tuxbot/setup.py
279
tuxbot/setup.py
|
@ -1,2 +1,279 @@
|
|||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import NoReturn, Union, List
|
||||
|
||||
import appdirs
|
||||
import click
|
||||
from colorama import Fore, Style, init
|
||||
|
||||
init()
|
||||
|
||||
app_dir = appdirs.AppDirs("Tuxbot-bot")
|
||||
config_dir = Path(app_dir.user_config_dir)
|
||||
|
||||
try:
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
except PermissionError:
|
||||
print(f"mkdir: cannot create directory '{config_dir}': Permission denied")
|
||||
sys.exit(1)
|
||||
|
||||
config_file = config_dir / "config.json"
|
||||
|
||||
|
||||
def load_existing_config() -> dict:
|
||||
if not config_file.exists():
|
||||
return {}
|
||||
|
||||
with config_file.open() as fs:
|
||||
return json.load(fs)
|
||||
|
||||
|
||||
instances_data = load_existing_config()
|
||||
if not instances_data:
|
||||
instances_list = []
|
||||
else:
|
||||
instances_list = list(instances_data.keys())
|
||||
|
||||
|
||||
def save_config(name, data, delete=False):
|
||||
_config = load_existing_config()
|
||||
|
||||
if delete and name in _config:
|
||||
_config.pop(name)
|
||||
else:
|
||||
_config[name] = data
|
||||
|
||||
with config_file.open("w") as fs:
|
||||
json.dump(_config, fs, indent=4)
|
||||
|
||||
|
||||
def get_name() -> str:
|
||||
name = ""
|
||||
while not name:
|
||||
print(
|
||||
"What name do you want to give this instance?\n"
|
||||
"(valid characters: A-Z, a-z, 0-9, _, -)"
|
||||
)
|
||||
name = input("> ")
|
||||
if re.fullmatch(r"[a-zA-Z0-9_\-]*", name) is None:
|
||||
print()
|
||||
print(
|
||||
Fore.RED
|
||||
+ "ERROR: Invalid characters provided"
|
||||
+ Style.RESET_ALL
|
||||
)
|
||||
name = ""
|
||||
return name
|
||||
|
||||
|
||||
def get_data_dir(instance_name: str) -> Path:
|
||||
data_path = Path(app_dir.user_data_dir) / "data" / instance_name
|
||||
data_path_input = ""
|
||||
print()
|
||||
|
||||
def make_data_dir(path: Path) -> Union[Path, str]:
|
||||
try:
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
except OSError:
|
||||
print()
|
||||
print(
|
||||
Fore.RED
|
||||
+ f"mkdir: cannot create directory '{path}':"
|
||||
f" Permission denied"
|
||||
+ Style.RESET_ALL
|
||||
)
|
||||
path = ""
|
||||
|
||||
return path
|
||||
|
||||
while not data_path_input:
|
||||
print(
|
||||
"where do you want to save the configurations?\n"
|
||||
"Press [enter] to keep the default path"
|
||||
)
|
||||
print()
|
||||
print(f"Default: {data_path}")
|
||||
|
||||
data_path_input = input("> ")
|
||||
|
||||
if data_path_input != '':
|
||||
data_path_input = Path(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(
|
||||
f"You have chosen {data_path_input} to be your config directory for "
|
||||
f"`{instance_name}` instance"
|
||||
)
|
||||
|
||||
if not click.confirm("Please confirm", default=True):
|
||||
print("Rerun the process to redo this configuration.")
|
||||
sys.exit(0)
|
||||
|
||||
(data_path_input / 'core').mkdir(parents=True, exist_ok=True)
|
||||
(data_path_input / 'cogs').mkdir(parents=True, exist_ok=True)
|
||||
|
||||
return data_path_input
|
||||
|
||||
|
||||
def get_token() -> str:
|
||||
token = ""
|
||||
|
||||
while not token:
|
||||
print(
|
||||
"Please enter the bot token\n"
|
||||
"(you can find it at https://discord.com/developers/applications)"
|
||||
)
|
||||
token = input("> ")
|
||||
if re.fullmatch(r"([a-zA-Z0-9]{24}\.[a-zA-Z0-9_]{6}\.[a-zA-Z0-9_\-]{27}|mfa\.[a-zA-Z0-9_\-]{84})", token) is None:
|
||||
print(
|
||||
Fore.RED
|
||||
+ "ERROR: Invalid token provided"
|
||||
+ Style.RESET_ALL
|
||||
)
|
||||
token = ""
|
||||
return token
|
||||
|
||||
|
||||
def get_prefixes() -> List[str]:
|
||||
print("Choice a (or multiple) prefix for the bot")
|
||||
prefixes = [input('> ')]
|
||||
|
||||
while click.confirm("Add another prefix ?", default=False):
|
||||
prefixes.append(input('> '))
|
||||
|
||||
return prefixes
|
||||
|
||||
|
||||
def additional_config() -> dict:
|
||||
p = Path(r'tuxbot/cogs').glob('**/additional_config.json')
|
||||
datas = {}
|
||||
|
||||
for file in p:
|
||||
print()
|
||||
cog_name = str(file.parent).split('/')[-1]
|
||||
datas[cog_name] = {}
|
||||
|
||||
with file.open('r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
print(f"\n==Configuration for `{cog_name}` module==")
|
||||
|
||||
for key, value in data.items():
|
||||
print()
|
||||
print(value['description'])
|
||||
datas[cog_name][key] = input('> ')
|
||||
|
||||
return datas
|
||||
|
||||
|
||||
def finish_setup(data_dir: Path) -> NoReturn:
|
||||
print("Now, it's time to finish this setup by giving bot informations\n")
|
||||
|
||||
token = get_token()
|
||||
print()
|
||||
prefixes = get_prefixes()
|
||||
mentionable = click.confirm("Does the bot answer if it's mentioned?", default=True)
|
||||
|
||||
cogs_config = additional_config()
|
||||
|
||||
core_file = data_dir / 'core' / 'settings.json'
|
||||
core = {
|
||||
'token': token,
|
||||
'prefixes': prefixes,
|
||||
'mentionable': mentionable,
|
||||
}
|
||||
|
||||
with core_file.open("w") as fs:
|
||||
json.dump(core, fs, indent=4)
|
||||
|
||||
for cog, data in cogs_config.items():
|
||||
data_cog_dir = data_dir / 'cogs' / cog
|
||||
data_cog_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
data_cog_file = data_cog_dir / 'settings.json'
|
||||
|
||||
with data_cog_file.open("w") as fs:
|
||||
json.dump(data, fs, indent=4)
|
||||
|
||||
|
||||
def basic_setup() -> NoReturn:
|
||||
print("Hi ! it's time for you to give me informations about you instance")
|
||||
name = get_name()
|
||||
|
||||
data_dir = get_data_dir(name)
|
||||
|
||||
configs = load_existing_config()
|
||||
instance_config = configs[name] if name in instances_list else {}
|
||||
|
||||
instance_config["DATA_PATH"] = str(data_dir.resolve())
|
||||
instance_config["IS_RUNNING"] = False
|
||||
|
||||
if name in instances_list:
|
||||
print()
|
||||
print(
|
||||
Fore.RED
|
||||
+ f"WARNING: An instance named `{name}` already exists "
|
||||
f"Continuing will overwrite this instance configs."
|
||||
+ Style.RESET_ALL
|
||||
)
|
||||
if not click.confirm("Are you sure you want to continue?",
|
||||
default=False):
|
||||
print("Abandon...")
|
||||
sys.exit(0)
|
||||
|
||||
save_config(name, instance_config)
|
||||
|
||||
print("\n"*4)
|
||||
|
||||
finish_setup(data_dir)
|
||||
|
||||
print()
|
||||
print(
|
||||
f"Instance successfully created! "
|
||||
f"You can now run `tuxbot {name}` to launch this instance"
|
||||
)
|
||||
|
||||
|
||||
def setup():
|
||||
...
|
||||
try:
|
||||
"""Create a new instance."""
|
||||
level = logging.DEBUG
|
||||
base_logger = logging.getLogger("tux")
|
||||
base_logger.setLevel(level)
|
||||
formatter = logging.Formatter(
|
||||
"[{asctime}] [{levelname}] {name}: {message}",
|
||||
datefmt="%Y-%m-%d %H:%M:%S", style="{"
|
||||
)
|
||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||
stdout_handler.setFormatter(formatter)
|
||||
base_logger.addHandler(stdout_handler)
|
||||
|
||||
basic_setup()
|
||||
except KeyboardInterrupt:
|
||||
print("Exiting...")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup()
|
||||
|
|
Loading…
Reference in a new issue