mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-10 21:28:55 -05:00
[Core] Improve API token converter (#2692)
* improve api converter * make usage more clear
This commit is contained in:
parent
2e271d695b
commit
68590dfdb8
@ -1,7 +1,9 @@
|
||||
import re
|
||||
from typing import TYPE_CHECKING
|
||||
import functools
|
||||
from typing import TYPE_CHECKING, Optional, List, Dict
|
||||
|
||||
import discord
|
||||
from discord.ext import commands as dpy_commands
|
||||
|
||||
from . import BadArgument
|
||||
from ..i18n import Translator
|
||||
@ -9,7 +11,7 @@ from ..i18n import Translator
|
||||
if TYPE_CHECKING:
|
||||
from .context import Context
|
||||
|
||||
__all__ = ["GuildConverter"]
|
||||
__all__ = ["GuildConverter", "APIToken", "DictConverter", "get_dict_converter"]
|
||||
|
||||
_ = Translator("commands.converter", __file__)
|
||||
|
||||
@ -47,16 +49,20 @@ class APIToken(discord.ext.commands.Converter):
|
||||
This will parse the input argument separating the key value pairs into a
|
||||
format to be used for the core bots API token storage.
|
||||
|
||||
This will split the argument by either `;` or `,` and return a dict
|
||||
This will split the argument by either `;` ` `, or `,` and return a dict
|
||||
to be stored. Since all API's are different and have different naming convention,
|
||||
this leaves the onus on the cog creator to clearly define how to setup the correct
|
||||
credential names for their cogs.
|
||||
|
||||
Note: Core usage of this has been replaced with DictConverter use instead.
|
||||
|
||||
This may be removed at a later date (with warning)
|
||||
"""
|
||||
|
||||
async def convert(self, ctx, argument) -> dict:
|
||||
bot = ctx.bot
|
||||
result = {}
|
||||
match = re.split(r";|,", argument)
|
||||
match = re.split(r";|,| ", argument)
|
||||
# provide two options to split incase for whatever reason one is part of the api key we're using
|
||||
if len(match) > 1:
|
||||
result[match[0]] = "".join(r for r in match[1:])
|
||||
@ -65,3 +71,48 @@ class APIToken(discord.ext.commands.Converter):
|
||||
if not result:
|
||||
raise BadArgument(_("The provided tokens are not in a valid format."))
|
||||
return result
|
||||
|
||||
|
||||
class DictConverter(dpy_commands.Converter):
|
||||
"""
|
||||
Converts pairs of space seperated values to a dict
|
||||
"""
|
||||
|
||||
def __init__(self, *expected_keys: str, delims: Optional[List[str]] = None):
|
||||
self.expected_keys = expected_keys
|
||||
self.delims = delims or [" "]
|
||||
self.pattern = re.compile(r"|".join(re.escape(d) for d in self.delims))
|
||||
|
||||
async def convert(self, ctx: "Context", argument: str) -> Dict[str, str]:
|
||||
|
||||
ret: Dict[str, str] = {}
|
||||
args = self.pattern.split(argument)
|
||||
|
||||
if len(args) % 2 != 0:
|
||||
raise BadArgument()
|
||||
|
||||
iterator = iter(args)
|
||||
|
||||
for key in iterator:
|
||||
if self.expected_keys and key not in self.expected_keys:
|
||||
raise BadArgument(_("Unexpected key {key}").format(key))
|
||||
|
||||
ret[key] = next(iterator)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def get_dict_converter(*expected_keys: str, delims: Optional[List[str]] = None) -> type:
|
||||
"""
|
||||
Returns a typechecking safe `DictConverter` suitable for use with discord.py
|
||||
"""
|
||||
|
||||
class PartialMeta(type(DictConverter)):
|
||||
__call__ = functools.partialmethod(
|
||||
type(DictConverter).__call__, *expected_keys, delims=delims
|
||||
)
|
||||
|
||||
class ValidatedConverter(DictConverter, metaclass=PartialMeta):
|
||||
pass
|
||||
|
||||
return ValidatedConverter
|
||||
|
||||
@ -45,6 +45,8 @@ log = logging.getLogger("red")
|
||||
|
||||
_ = i18n.Translator("Core", __file__)
|
||||
|
||||
TokenConverter = commands.get_dict_converter(delims=[" ", ",", ";"])
|
||||
|
||||
|
||||
class CoreLogic:
|
||||
def __init__(self, bot: "Red"):
|
||||
@ -1063,7 +1065,7 @@ class Core(commands.Cog, CoreLogic):
|
||||
|
||||
@_set.command()
|
||||
@checks.is_owner()
|
||||
async def api(self, ctx: commands.Context, service: str, *tokens: commands.converter.APIToken):
|
||||
async def api(self, ctx: commands.Context, service: str, *, tokens: TokenConverter):
|
||||
"""Set various external API tokens.
|
||||
|
||||
This setting will be asked for by some 3rd party cogs and some core cogs.
|
||||
@ -1076,8 +1078,7 @@ class Core(commands.Cog, CoreLogic):
|
||||
"""
|
||||
if ctx.channel.permissions_for(ctx.me).manage_messages:
|
||||
await ctx.message.delete()
|
||||
entry = {k: v for t in tokens for k, v in t.items()}
|
||||
await ctx.bot.db.api_tokens.set_raw(service, value=entry)
|
||||
await ctx.bot.db.api_tokens.set_raw(service, value=tokens)
|
||||
await ctx.send(_("`{service}` API tokens have been set.").format(service=service))
|
||||
|
||||
@commands.group()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user