Skip to content

Commit d9d0176

Browse files
committed
added validation for config inputs
1 parent ed59c3a commit d9d0176

File tree

3 files changed

+59
-15
lines changed

3 files changed

+59
-15
lines changed

discordbot/cogs/config.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,29 @@
33
from cogs.func import Context
44
from discord.ext import commands
55

6+
from utils.config import ConfigError
7+
68

79
class Config(commands.Cog):
810
def __init__(self, bot):
911
self.log = logging.getLogger("cog")
1012
self.bot = bot
1113

1214
@commands.Command
13-
async def set(self, ctx: Context, key: str, val: str):
15+
async def set(self, ctx: Context, key: str, *, val: str):
1416
"""Set a config parameter for your bot instance"""
1517
id = ctx.message.guild.id
16-
if not self.bot.config.exists(id):
17-
self.log.info(f"{id} - Setting initial config with {key}={val}")
18-
self.bot.config.add_config_for(id, {key: val})
19-
else:
20-
self.log.info(f"{id} - Updating config with {key}={val}")
21-
self.bot.config.update_config_for(id, key, val)
18+
val = val.strip()
19+
try:
20+
if not self.bot.config.exists(id):
21+
self.log.info(f"{id} - Setting initial config with {key}={val}")
22+
self.bot.config.add_config_for(id, {key: val})
23+
else:
24+
self.log.info(f"{id} - Updating config with {key}={val}")
25+
self.bot.config.update_config_for(id, key, val)
26+
27+
except ConfigError as e:
28+
return await ctx.reply_formatted_error(f"{e}", error_title="Config Error")
2229

2330
return await ctx.tick(True)
2431

discordbot/cogs/wikipedia.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ async def explain(self, ctx: commands.Context, *, query: str):
4141
await ctx.send(f"{page[:until_last_sentence]}...")
4242

4343
if self.t2s is not None:
44-
await self.t2s.say(ctx, page[:until_last_sentence])
44+
await self.t2s.say(ctx=ctx, message=page[:until_last_sentence])
4545

4646
except wikipedia.DisambiguationError as e:
4747
return await ctx.send(f"{query} may refer to {e.options}")

discordbot/utils/config.py

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,44 @@
11
import atexit
22
import json
33
import logging
4+
import re
45
from typing import Any, Dict, List
56

6-
defaultConfig = {"languageCode": "en-US", "voiceId": "Amy", "wikiLanguage": "en"}
7+
DEFAULT_CONFIG = {"languageCode": "en-US", "voiceId": "Amy", "wikiLanguage": "en"}
78

8-
default_configfile_name = "discordbot_config.json"
9+
DEFAULT_CONFIGFILE_NAME = "discordbot_config.json"
910

1011

12+
# See https://docs.aws.amazon.com/de_de/polly/latest/dg/voicelist.html
13+
VALID_T2S_LANGUGAGE_CODES = ['arb','cmn-CN','cy-GB','da-DK','de-DE','en-AU','en-GB','en-GB-WLS','en-IN','en-US','es-ES','es-MX','es-US','fr-CA','fr-FR','is-IS','it-IT','ja-JP','hi-IN','ko-KR','nb-NO','nl-NL','pl-PL','pt-BR','pt-PT','ro-RO','ru-RU','sv-SE','tr-TR','en-NZ','en-ZA']
14+
VALID_T2S_VOICE_IDS = ['Aditi','Amy','Astrid','Bianca','Brian','Camila','Carla','Carmen','Celine','Chantal','Conchita','Cristiano','Dora','Emma','Enrique','Ewa','Filiz','Gabrielle','Geraint','Giorgio','Gwyneth','Hans','Ines','Ivy','Jacek','Jan','Joanna','Joey','Justin','Karl','Kendra','Kevin','Kimberly','Lea','Liv','Lotte','Lucia','Lupe','Mads','Maja','Marlene','Mathieu','Matthew','Maxim','Mia','Miguel','Mizuki','Naja','Nicole','Olivia','Penelope','Raveena','Ricardo','Ruben','Russell','Salli','Seoyeon','Takumi','Tatyana','Vicki','Vitoria','Zeina','Zhiyu','Aria','Ayanda']
15+
16+
INPUT_VALIDATION_RAW_RE = r"^[a-zA-Z]{2}$"
17+
INPUT_VALIDATION_STR = re.compile(INPUT_VALIDATION_RAW_RE)
18+
19+
VALID_CONFIG_PARAM_KEYS = {
20+
"languageCode": {
21+
"description": "The language code to use for the Polly API. See https://docs.aws.amazon.com/de_de/polly/latest/dg/voicelist.html",
22+
"valid_inputs": lambda val : val in VALID_T2S_LANGUGAGE_CODES
23+
},
24+
"voiceId": {
25+
"description": "The voice ID to use for the Polly API. See https://docs.aws.amazon.com/de_de/polly/latest/dg/voicelist.html",
26+
"valid_inputs": lambda val : val in VALID_T2S_VOICE_IDS
27+
},
28+
"wikiLanguage": {
29+
"description": f"The language code to use for the Wikipedia API. Must match '{INPUT_VALIDATION_RAW_RE}'",
30+
"valid_inputs": lambda val: INPUT_VALIDATION_STR.match(val)
31+
}
32+
}
33+
34+
class ConfigError(Exception):
35+
pass
36+
1137
class ConfigMap:
1238
def __init__(self, configs: List[Dict[str, Any]], configfile_name: str = None):
1339
self.log = logging.getLogger("config")
1440
self._configs = dict()
15-
self.configfile_name = configfile_name or default_configfile_name
41+
self.configfile_name = configfile_name or DEFAULT_CONFIGFILE_NAME
1642

1743
for cfg in configs:
1844
id = cfg["id"]
@@ -35,10 +61,12 @@ def get_config_for(self, id: str, key: str = "", default: Any = None):
3561
)
3662

3763
def add_config_for(self, id: str, config: Dict[str, Any]):
64+
for key in config:
65+
self.is_valid_config_parameter(key, config[key])
3866
self._configs[id] = config
3967

4068
def update_config_for(self, id: str, key: str, val: str):
41-
if self.exists(id):
69+
if self.exists(id) and self.is_valid_config_parameter(key, val):
4270
self._configs[id][key] = val
4371

4472
def remove_config_for(self, id: str):
@@ -48,11 +76,20 @@ def remove_config_for(self, id: str):
4876
def set_defaults_for(self, id: str):
4977
if not self.exists(id):
5078
self.log.info("Setting default config")
51-
self.add_config_for(id, defaultConfig)
52-
pass
79+
self.add_config_for(id, DEFAULT_CONFIG)
80+
self.log.info(f'Config for {id} already exists. Cannot set defaults...')
81+
82+
def is_valid_config_parameter(self, key: str, val: str) -> bool:
83+
if not key in VALID_CONFIG_PARAM_KEYS.keys():
84+
raise ConfigError(f"'{key}' is not a valid config parameter. Try one of {VALID_CONFIG_PARAM_KEYS}")
85+
else:
86+
val_info = VALID_CONFIG_PARAM_KEYS[key]
87+
if not val_info["valid_inputs"](val):
88+
raise ConfigError(f"'{val}' is not a valid value for '{key}': {val_info['description']}")
89+
return True
5390

5491
@classmethod
55-
def from_file(cls, configfile_name: str = default_configfile_name):
92+
def from_file(cls, configfile_name: str = DEFAULT_CONFIGFILE_NAME):
5693
try:
5794
with open(configfile_name, "r") as f:
5895
data = json.load(f)

0 commit comments

Comments
 (0)