From 5dec62f4c057b86883414dbe67875d7022551c1b Mon Sep 17 00:00:00 2001 From: Nadir Chowdhury Date: Fri, 16 Apr 2021 13:18:57 +0100 Subject: [PATCH] [commands] Add a converter for discord.Object --- discord/ext/commands/converter.py | 25 +++++++++++++++++++++++++ discord/ext/commands/errors.py | 18 ++++++++++++++++++ docs/ext/commands/api.rst | 3 +++ docs/ext/commands/commands.rst | 3 +++ 4 files changed, 49 insertions(+) diff --git a/discord/ext/commands/converter.py b/discord/ext/commands/converter.py index b2d280754..e94a08efb 100644 --- a/discord/ext/commands/converter.py +++ b/discord/ext/commands/converter.py @@ -37,6 +37,7 @@ if TYPE_CHECKING: __all__ = ( 'Converter', + 'ObjectConverter', 'MemberConverter', 'UserConverter', 'MessageConverter', @@ -122,6 +123,30 @@ class IDConverter(Converter[T_co]): return _ID_REGEX.match(argument) +class ObjectConverter(IDConverter[discord.Object]): + """Converts to a :class:`~discord.Object`. + + The argument must follow the valid ID or mention formats (e.g. `<@80088516616269824>`). + + .. versionadded:: 2.0 + + The lookup strategy is as follows (in order): + + 1. Lookup by ID. + 2. Lookup by member, role, or channel mention. + """ + + async def convert(self, ctx: Context, argument: str) -> discord.Object: + match = self._get_id_match(argument) or re.match(r'<(?:@(?:!|&)?|#)([0-9]{15,20})>$', argument) + + if match is None: + raise ObjectNotFound(argument) + + result = int(match.group(1)) + + return discord.Object(id=result) + + class MemberConverter(IDConverter[discord.Member]): """Converts to a :class:`~discord.Member`. diff --git a/discord/ext/commands/errors.py b/discord/ext/commands/errors.py index 98154d108..bfbe55fc7 100644 --- a/discord/ext/commands/errors.py +++ b/discord/ext/commands/errors.py @@ -42,6 +42,7 @@ __all__ = ( 'MaxConcurrencyReached', 'NotOwner', 'MessageNotFound', + 'ObjectNotFound', 'MemberNotFound', 'GuildNotFound', 'UserNotFound', @@ -213,6 +214,23 @@ class NotOwner(CheckFailure): """ pass +class ObjectNotFound(BadArgument): + """Exception raised when the argument provided did not match the format + of an ID or a mention. + + This inherits from :exc:`BadArgument` + + .. versionadded:: 2.0 + + Attributes + ----------- + argument: :class:`str` + The argument supplied by the caller that was not matched + """ + def __init__(self, argument): + self.argument = argument + super().__init__(f'{argument!r} does not follow a valid ID or mention format.') + class MemberNotFound(BadArgument): """Exception raised when the member provided was not found in the bot's cache. diff --git a/docs/ext/commands/api.rst b/docs/ext/commands/api.rst index 99cb28acc..eb9300390 100644 --- a/docs/ext/commands/api.rst +++ b/docs/ext/commands/api.rst @@ -273,6 +273,9 @@ Converters .. autoclass:: discord.ext.commands.Converter :members: +.. autoclass:: discord.ext.commands.ObjectConverter + :members: + .. autoclass:: discord.ext.commands.MemberConverter :members: diff --git a/docs/ext/commands/commands.rst b/docs/ext/commands/commands.rst index b0dc3466a..e473a0189 100644 --- a/docs/ext/commands/commands.rst +++ b/docs/ext/commands/commands.rst @@ -374,6 +374,7 @@ or just a regular username. The default set of converters have been written to b A lot of discord models work out of the gate as a parameter: +- :class:`Object` (since v2.0) - :class:`Member` - :class:`User` - :class:`Message` (since v1.1) @@ -400,6 +401,8 @@ converter is given below: +--------------------------+-------------------------------------------------+ | Discord Class | Converter | +--------------------------+-------------------------------------------------+ +| :class:`Object` | :class:`~ext.commands.ObjectConverter` | ++--------------------------+-------------------------------------------------+ | :class:`Member` | :class:`~ext.commands.MemberConverter` | +--------------------------+-------------------------------------------------+ | :class:`User` | :class:`~ext.commands.UserConverter` |