comprobot 2.3.1__tar.gz → 2.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {comprobot-2.3.1 → comprobot-2.3.2}/PKG-INFO +1 -1
- {comprobot-2.3.1 → comprobot-2.3.2}/comprobot.egg-info/PKG-INFO +1 -1
- {comprobot-2.3.1 → comprobot-2.3.2}/pyproject.toml +1 -1
- {comprobot-2.3.1 → comprobot-2.3.2}/src/__main__.py +3 -2
- {comprobot-2.3.1 → comprobot-2.3.2}/src/api.py +3 -3
- {comprobot-2.3.1 → comprobot-2.3.2}/src/commands.py +5 -10
- comprobot-2.3.2/src/data.py +159 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/src/process.py +3 -13
- {comprobot-2.3.1 → comprobot-2.3.2}/src/start.py +23 -1
- {comprobot-2.3.1 → comprobot-2.3.2}/src/templates.py +0 -3
- comprobot-2.3.1/src/data.py +0 -87
- {comprobot-2.3.1 → comprobot-2.3.2}/LICENSE +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/README.md +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/comprobot.egg-info/SOURCES.txt +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/comprobot.egg-info/dependency_links.txt +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/comprobot.egg-info/entry_points.txt +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/comprobot.egg-info/requires.txt +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/comprobot.egg-info/top_level.txt +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/setup.cfg +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/src/__init__.py +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/src/bot.py +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/src/config.py +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/src/functions.py +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/src/moderation.py +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/src/money_system.py +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/src/onboarding.py +0 -0
- {comprobot-2.3.1 → comprobot-2.3.2}/src/testing.py +0 -0
|
@@ -14,7 +14,8 @@ def main():
|
|
|
14
14
|
description="A self-hostable open-source Discord bot built for maximum customization.",
|
|
15
15
|
)
|
|
16
16
|
subparsers = parser.add_subparsers(dest="command", metavar="")
|
|
17
|
-
subparsers.add_parser("start", help="Start the bot.")
|
|
17
|
+
start_parser = subparsers.add_parser("start", help="Start the bot.")
|
|
18
|
+
start_parser.add_argument("--daemon", action="store_true", help="Daemonize the process.")
|
|
18
19
|
subparsers.add_parser("onboard", help="Set up Comprobot for the first time.")
|
|
19
20
|
config_parser = subparsers.add_parser("config", help="Configure the bot's settings.")
|
|
20
21
|
config_parser.add_argument("config_args", nargs=argparse.REMAINDER)
|
|
@@ -25,7 +26,7 @@ def main():
|
|
|
25
26
|
|
|
26
27
|
match args.command:
|
|
27
28
|
case "start":
|
|
28
|
-
start()
|
|
29
|
+
start(daemon=getattr(args, "daemon", False))
|
|
29
30
|
case "onboard":
|
|
30
31
|
settings = onboarding()
|
|
31
32
|
|
|
@@ -29,7 +29,7 @@ def access_api(url, parameter, error_message, headers=None):
|
|
|
29
29
|
# ---------- Commands ----------
|
|
30
30
|
def quote():
|
|
31
31
|
try:
|
|
32
|
-
quote_response = requests.get("https://zenquotes.io/api/random")
|
|
32
|
+
quote_response = requests.get("https://zenquotes.io/api/random", timeout=10)
|
|
33
33
|
except requests.exceptions.RequestException as e:
|
|
34
34
|
return f"{error_messages['quote']} ({e})"
|
|
35
35
|
if quote_response.status_code != 200:
|
|
@@ -143,8 +143,8 @@ def bible(
|
|
|
143
143
|
choice(output["general"]["bible"])
|
|
144
144
|
.replace(r"{{PASSAGE}}", verse["text"].strip())
|
|
145
145
|
.replace(r"{{BOOK}}", verse["book"].strip())
|
|
146
|
-
.replace(r"{{CHAPTER}}", str(verse["chapter"].strip())
|
|
147
|
-
.replace(r"{{VERSE}}", str(verse["verse"].strip())
|
|
146
|
+
.replace(r"{{CHAPTER}}", str(verse["chapter"]).strip())
|
|
147
|
+
.replace(r"{{VERSE}}", str(verse["verse"]).strip())
|
|
148
148
|
)
|
|
149
149
|
elif "text" in data and "reference" in data:
|
|
150
150
|
parts = data["reference"].split()
|
|
@@ -23,15 +23,10 @@ def calculate(calculation):
|
|
|
23
23
|
|
|
24
24
|
def help(category=None):
|
|
25
25
|
if not category:
|
|
26
|
-
message = "#
|
|
26
|
+
message = "# Categories"
|
|
27
|
+
|
|
27
28
|
for category in list(keywords.keys()):
|
|
28
|
-
message += f"\n
|
|
29
|
-
for command in list(keywords[category].keys()):
|
|
30
|
-
if active.get(command, True):
|
|
31
|
-
message += f"\n**{config['prefix']}{keywords[category][command][0]}** - {descriptions[category][command]}"
|
|
32
|
-
if len(keywords[category][command]) > 1:
|
|
33
|
-
message += f"\n-# Aliases: {config['prefix']}{', '.join(keywords[category][command][1:])}"
|
|
34
|
-
message += "\n-# \u200b"
|
|
29
|
+
message += f"\n**{category.title()}**\n!help {category}\n-# \u200b"
|
|
35
30
|
return message
|
|
36
31
|
else:
|
|
37
32
|
if not category.lower() in list(keywords.keys()):
|
|
@@ -41,8 +36,8 @@ def help(category=None):
|
|
|
41
36
|
if active.get(command, True):
|
|
42
37
|
message += f"\n**{config['prefix']}{keywords[category.lower()][command][0]}** - {descriptions[category.lower()][command]}"
|
|
43
38
|
if len(keywords[category.lower()][command]) > 1:
|
|
44
|
-
message += f"\n-# Aliases: {config['prefix']
|
|
45
|
-
message += "\n-# "
|
|
39
|
+
message += f"\n-# Aliases: {', '.join(config['prefix'] + alias for alias in keywords[category.lower()][command][1:])}"
|
|
40
|
+
message += "\n-# \u200b"
|
|
46
41
|
return message
|
|
47
42
|
|
|
48
43
|
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from collections.abc import Mapping
|
|
3
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
4
|
+
|
|
5
|
+
import appdirs
|
|
6
|
+
import tomlkit
|
|
7
|
+
import tomlkit.exceptions
|
|
8
|
+
|
|
9
|
+
from . import templates
|
|
10
|
+
|
|
11
|
+
Migration = Union[Tuple[str, str], Callable]
|
|
12
|
+
|
|
13
|
+
RENAME_COMMANDS: List[Migration] = [("commands", "general")]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_data_path(filename: str) -> str:
|
|
17
|
+
base_dir = appdirs.user_data_dir(appname="Comprobot", appauthor=False)
|
|
18
|
+
return os.path.join(base_dir, filename)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _write(path: str, data) -> None:
|
|
22
|
+
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
23
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
24
|
+
tomlkit.dump(data, f)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _apply_migrations(data, migrations: List[Migration]) -> bool:
|
|
28
|
+
changed = False
|
|
29
|
+
for migration in migrations:
|
|
30
|
+
if callable(migration):
|
|
31
|
+
changed |= bool(migration(data))
|
|
32
|
+
else:
|
|
33
|
+
old_key, new_key = migration
|
|
34
|
+
if old_key in data:
|
|
35
|
+
if new_key not in data:
|
|
36
|
+
data[new_key] = data[old_key]
|
|
37
|
+
del data[old_key]
|
|
38
|
+
changed = True
|
|
39
|
+
return changed
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _merge_defaults(data, defaults) -> bool:
|
|
43
|
+
changed = False
|
|
44
|
+
for key, value in defaults.items():
|
|
45
|
+
if key not in data:
|
|
46
|
+
data[key] = value
|
|
47
|
+
changed = True
|
|
48
|
+
elif isinstance(value, Mapping) and isinstance(data.get(key), Mapping):
|
|
49
|
+
changed |= _merge_defaults(data[key], value)
|
|
50
|
+
return changed
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _reorder(data, defaults) -> bool:
|
|
54
|
+
in_data = set(data.keys())
|
|
55
|
+
target = [k for k in defaults if k in in_data] + [k for k in in_data if k not in defaults]
|
|
56
|
+
|
|
57
|
+
if list(data.keys()) == target:
|
|
58
|
+
changed = False
|
|
59
|
+
for key in defaults:
|
|
60
|
+
if isinstance(defaults[key], Mapping) and isinstance(data.get(key), Mapping):
|
|
61
|
+
changed |= _reorder(data[key], defaults[key])
|
|
62
|
+
return changed
|
|
63
|
+
|
|
64
|
+
snapshot = {k: data[k] for k in in_data}
|
|
65
|
+
for key in list(in_data):
|
|
66
|
+
del data[key]
|
|
67
|
+
for key in target:
|
|
68
|
+
data[key] = snapshot[key]
|
|
69
|
+
|
|
70
|
+
for key in defaults:
|
|
71
|
+
if isinstance(defaults[key], Mapping) and isinstance(data.get(key), Mapping):
|
|
72
|
+
_reorder(data[key], defaults[key])
|
|
73
|
+
|
|
74
|
+
return True
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _prune(data, defaults) -> bool:
|
|
78
|
+
changed = False
|
|
79
|
+
for key in [k for k in data if k not in defaults]:
|
|
80
|
+
del data[key]
|
|
81
|
+
changed = True
|
|
82
|
+
for key, value in defaults.items():
|
|
83
|
+
if isinstance(value, Mapping) and isinstance(data.get(key), Mapping):
|
|
84
|
+
changed |= _prune(data[key], value)
|
|
85
|
+
return changed
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def load_or_create(
|
|
89
|
+
path: str,
|
|
90
|
+
template_content: str,
|
|
91
|
+
migrations: Optional[List[Migration]] = None,
|
|
92
|
+
prune_obsolete: bool = True,
|
|
93
|
+
) -> dict:
|
|
94
|
+
defaults = tomlkit.loads(template_content)
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
98
|
+
data = tomlkit.loads(f.read())
|
|
99
|
+
except FileNotFoundError:
|
|
100
|
+
_write(path, defaults)
|
|
101
|
+
return defaults
|
|
102
|
+
except tomlkit.exceptions.TOMLKitError:
|
|
103
|
+
backup = path + ".bak"
|
|
104
|
+
os.replace(path, backup)
|
|
105
|
+
print(f"[Comprobot] Corrupt TOML at {path!r} — backed up to {backup!r}, resetting to defaults.")
|
|
106
|
+
_write(path, defaults)
|
|
107
|
+
return defaults
|
|
108
|
+
|
|
109
|
+
changed = _apply_migrations(data, migrations or [])
|
|
110
|
+
changed |= _merge_defaults(data, defaults)
|
|
111
|
+
if prune_obsolete:
|
|
112
|
+
changed |= _prune(data, defaults)
|
|
113
|
+
changed |= _reorder(data, defaults)
|
|
114
|
+
|
|
115
|
+
if changed:
|
|
116
|
+
_write(path, data)
|
|
117
|
+
|
|
118
|
+
return data
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def save_toml(data, path: str) -> None:
|
|
122
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
123
|
+
tomlkit.dump(data, f)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
error_messages: Dict[str, str] = load_or_create(
|
|
127
|
+
get_data_path("error-messages.toml"), templates.error_messages
|
|
128
|
+
)
|
|
129
|
+
config: Dict[str, Any] = load_or_create(
|
|
130
|
+
get_data_path("config.toml"), templates.config
|
|
131
|
+
)
|
|
132
|
+
keywords: Dict[str, Dict[str, List[str]]] = load_or_create(
|
|
133
|
+
get_data_path("keywords.toml"), templates.keywords, migrations=RENAME_COMMANDS
|
|
134
|
+
)
|
|
135
|
+
ai: Dict[str, Any] = load_or_create(
|
|
136
|
+
get_data_path("ai.toml"), templates.ai
|
|
137
|
+
)
|
|
138
|
+
system_prompt_text: str = str(ai["system_prompt"])
|
|
139
|
+
money: Dict[str, Dict[str, int]] = load_or_create(
|
|
140
|
+
get_data_path("money.toml"), "[members]\n", prune_obsolete=False
|
|
141
|
+
)
|
|
142
|
+
active: Dict[str, bool] = load_or_create(
|
|
143
|
+
get_data_path("active.toml"), templates.active
|
|
144
|
+
)
|
|
145
|
+
output: Dict[str, Dict[str, List[str]]] = load_or_create(
|
|
146
|
+
get_data_path("output.toml"), templates.output, migrations=RENAME_COMMANDS
|
|
147
|
+
)
|
|
148
|
+
moderation: Dict[Any, Any] = load_or_create(
|
|
149
|
+
get_data_path("moderation.toml"), templates.moderation
|
|
150
|
+
)
|
|
151
|
+
descriptions: Dict[str, Dict[str, str]] = load_or_create(
|
|
152
|
+
get_data_path("descriptions.toml"), templates.descriptions, migrations=RENAME_COMMANDS
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
env_path = get_data_path(".env")
|
|
156
|
+
if not os.path.isfile(env_path):
|
|
157
|
+
os.makedirs(os.path.dirname(env_path), exist_ok=True)
|
|
158
|
+
with open(env_path, "w", encoding="utf-8") as f:
|
|
159
|
+
f.write(templates.env)
|
|
@@ -61,17 +61,7 @@ class Comprobot(ext_commands.Cog):
|
|
|
61
61
|
@ext_commands.check(lambda ctx: active["waifu"])
|
|
62
62
|
async def waifu_cmd(self, ctx):
|
|
63
63
|
await ctx.send(api.waifu())
|
|
64
|
-
|
|
65
|
-
@ext_commands.group(
|
|
66
|
-
name=keywords["general"]["image"][0],
|
|
67
|
-
aliases=keywords["general"]["image"][1:],
|
|
68
|
-
invoke_without_command=True,
|
|
69
|
-
)
|
|
70
|
-
@ext_commands.check(lambda ctx: active["image"])
|
|
71
|
-
async def image_cmd(self, ctx):
|
|
72
|
-
await ctx.send(error_messages["missing_argument"])
|
|
73
|
-
|
|
74
|
-
@image_cmd.command(
|
|
64
|
+
@ext_commands.command(
|
|
75
65
|
name=keywords["general"]["duck"][0],
|
|
76
66
|
aliases=keywords["general"]["duck"][1:],
|
|
77
67
|
)
|
|
@@ -79,7 +69,7 @@ class Comprobot(ext_commands.Cog):
|
|
|
79
69
|
async def duck_cmd(self, ctx):
|
|
80
70
|
await ctx.send(api.duck())
|
|
81
71
|
|
|
82
|
-
@
|
|
72
|
+
@ext_commands.command(
|
|
83
73
|
name=keywords["general"]["dog"][0],
|
|
84
74
|
aliases=keywords["general"]["dog"][1:],
|
|
85
75
|
)
|
|
@@ -87,7 +77,7 @@ class Comprobot(ext_commands.Cog):
|
|
|
87
77
|
async def dog_cmd(self, ctx):
|
|
88
78
|
await ctx.send(api.dog())
|
|
89
79
|
|
|
90
|
-
@
|
|
80
|
+
@ext_commands.command(
|
|
91
81
|
name=keywords["general"]["cat"][0],
|
|
92
82
|
aliases=keywords["general"]["cat"][1:],
|
|
93
83
|
)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os
|
|
1
2
|
import platform
|
|
2
3
|
import sys
|
|
3
4
|
from os import getenv as os_getenv
|
|
@@ -33,6 +34,14 @@ async def _setup_hook():
|
|
|
33
34
|
client.setup_hook = _setup_hook
|
|
34
35
|
|
|
35
36
|
|
|
37
|
+
@client.event
|
|
38
|
+
async def on_message(message):
|
|
39
|
+
if message.author == client.user:
|
|
40
|
+
return
|
|
41
|
+
ctx = await client.get_context(message)
|
|
42
|
+
await client.invoke(ctx)
|
|
43
|
+
|
|
44
|
+
|
|
36
45
|
@client.event
|
|
37
46
|
async def on_ready():
|
|
38
47
|
user_name = client.user.name if client.user else "Unknown"
|
|
@@ -40,7 +49,20 @@ async def on_ready():
|
|
|
40
49
|
para()
|
|
41
50
|
|
|
42
51
|
|
|
43
|
-
def
|
|
52
|
+
def _daemonize():
|
|
53
|
+
if os.fork() != 0:
|
|
54
|
+
os._exit(0)
|
|
55
|
+
os.setsid()
|
|
56
|
+
if os.fork() != 0:
|
|
57
|
+
os._exit(0)
|
|
58
|
+
devnull = os.open(os.devnull, os.O_RDONLY)
|
|
59
|
+
os.dup2(devnull, 0)
|
|
60
|
+
os.close(devnull)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def start(daemon=False):
|
|
64
|
+
if daemon:
|
|
65
|
+
_daemonize()
|
|
44
66
|
print(
|
|
45
67
|
f"Configuration directory: {appdirs.user_data_dir(appname='Comprobot', appauthor=False)}"
|
|
46
68
|
)
|
|
@@ -80,7 +80,6 @@ quote = ["quote"]
|
|
|
80
80
|
joke = ["joke"]
|
|
81
81
|
meme = ["meme"]
|
|
82
82
|
waifu = ["waifu"]
|
|
83
|
-
image = ["image", "picture"]
|
|
84
83
|
duck = ["duck"]
|
|
85
84
|
dog = ["dog"]
|
|
86
85
|
cat = ["cat"]
|
|
@@ -128,7 +127,6 @@ active = r"""quote = true
|
|
|
128
127
|
joke = true
|
|
129
128
|
meme = true
|
|
130
129
|
waifu = true
|
|
131
|
-
image = true
|
|
132
130
|
duck = true
|
|
133
131
|
dog = true
|
|
134
132
|
cat = true
|
|
@@ -157,7 +155,6 @@ quote = "Get a random inspirational quote."
|
|
|
157
155
|
joke = "Get a random two-part joke"
|
|
158
156
|
meme = "Get a random meme image"
|
|
159
157
|
waifu = "Compare two random waifu images"
|
|
160
|
-
image = "Get a random animal image (duck/dog/cat)"
|
|
161
158
|
duck = "Get a random duck image"
|
|
162
159
|
dog = "Get a random dog image"
|
|
163
160
|
cat = "Get a random cat image"
|
comprobot-2.3.1/src/data.py
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from typing import Any, Dict, List
|
|
3
|
-
|
|
4
|
-
import appdirs
|
|
5
|
-
import tomlkit
|
|
6
|
-
|
|
7
|
-
from . import templates
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def get_data_path(filename):
|
|
11
|
-
|
|
12
|
-
base_dir = appdirs.user_data_dir(appname="Comprobot", appauthor=False)
|
|
13
|
-
return os.path.join(base_dir, filename)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def ensure_file(path, content):
|
|
17
|
-
|
|
18
|
-
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
19
|
-
if not os.path.isfile(path):
|
|
20
|
-
with open(path, "w", encoding="utf-8") as f:
|
|
21
|
-
f.write(content)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def merge_defaults(data, defaults):
|
|
25
|
-
for key, value in defaults.items():
|
|
26
|
-
if key not in data:
|
|
27
|
-
data[key] = value
|
|
28
|
-
elif isinstance(value, dict) and isinstance(data.get(key), dict):
|
|
29
|
-
merge_defaults(data[key], value)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def migrate_section(data, old_key, new_key):
|
|
33
|
-
if old_key in data and new_key not in data:
|
|
34
|
-
data[new_key] = data[old_key]
|
|
35
|
-
del data[old_key]
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def load_or_create(path, template_content):
|
|
39
|
-
try:
|
|
40
|
-
with open(path, "r", encoding="utf-8") as f:
|
|
41
|
-
data = tomlkit.loads(f.read())
|
|
42
|
-
except FileNotFoundError:
|
|
43
|
-
ensure_file(path, template_content)
|
|
44
|
-
with open(path, "r", encoding="utf-8") as f:
|
|
45
|
-
data = tomlkit.loads(f.read())
|
|
46
|
-
|
|
47
|
-
migrate_section(data, "commands", "general")
|
|
48
|
-
|
|
49
|
-
defaults = tomlkit.loads(template_content)
|
|
50
|
-
merge_defaults(data, defaults)
|
|
51
|
-
|
|
52
|
-
if data != defaults:
|
|
53
|
-
with open(path, "w", encoding="utf-8") as f:
|
|
54
|
-
tomlkit.dump(data, f)
|
|
55
|
-
|
|
56
|
-
return data
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
error_messages: Dict[str, str] = load_or_create(
|
|
60
|
-
get_data_path("error-messages.toml"), templates.error_messages
|
|
61
|
-
)
|
|
62
|
-
config: Dict[str, Any] = load_or_create(get_data_path("config.toml"), templates.config)
|
|
63
|
-
keywords: Dict[str, Dict[str, List[str]]] = load_or_create(
|
|
64
|
-
get_data_path("keywords.toml"), templates.keywords
|
|
65
|
-
)
|
|
66
|
-
ai: Dict[str, Any] = load_or_create(get_data_path("ai.toml"), templates.ai)
|
|
67
|
-
system_prompt_text: str = str(ai["system_prompt"])
|
|
68
|
-
money: Dict[str, Dict[str, int]] = load_or_create(
|
|
69
|
-
get_data_path("money.toml"), r"""members = {}"""
|
|
70
|
-
)
|
|
71
|
-
active: Dict[str, bool] = load_or_create(get_data_path("active.toml"), templates.active)
|
|
72
|
-
output: Dict[str, Dict[str, List[str]]] = load_or_create(
|
|
73
|
-
get_data_path("output.toml"), templates.output
|
|
74
|
-
)
|
|
75
|
-
moderation: Dict[Any, Any] = load_or_create(
|
|
76
|
-
get_data_path("moderation.toml"), templates.moderation
|
|
77
|
-
)
|
|
78
|
-
descriptions: Dict[str, Dict[str, str]] = load_or_create(
|
|
79
|
-
get_data_path("descriptions.toml"), templates.descriptions
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
ensure_file(get_data_path(".env"), templates.env)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def save_toml(data, path):
|
|
86
|
-
with open(path, "w", encoding="utf-8") as f:
|
|
87
|
-
tomlkit.dump(data, f)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|