Skip to content

Commit

Permalink
Add commands.RegexConverter
Browse files Browse the repository at this point in the history
  • Loading branch information
Soheab committed Sep 25, 2024
1 parent 59f877f commit 58c3744
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
77 changes: 77 additions & 0 deletions discord/ext/commands/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
'clean_content',
'Greedy',
'Range',
'RegexConverter',
'run_converters',
)

Expand Down Expand Up @@ -951,6 +952,82 @@ async def convert(self, ctx: Context[BotT], argument: str) -> discord.ScheduledE
return result


class RegexConverter(Converter[str]):
"""Converter that checks if the argument matches a custom regular expression.
This converter is useful for creating custom validation logic.
.. versionadded:: 2.5
Parameters
-----------
pattern: Union[:class:`str`, :class:`re.Pattern`]
The pattern to match against. If a string is provided, it will be compiled into a regular expression.
case_insensitive: :class:`bool`
Whether the pattern should be case insensitive.
This sets the :attr:`re.IGNORECASE` flag.
This cannot be used with a pre-compiled pattern.
Defaults to ``False``.
force_ascii: :class:`bool`
Whether to force ASCII encoding on the pattern.
This sets the :attr:`re.ASCII` flag.
This cannot be used with a pre-compiled pattern.
Defaults to ``False``.
multiline: :class:`bool`
Whether the pattern should match across multiple lines.
This sets the :attr:`re.MULTILINE` flag.
This cannot be used with a pre-compiled pattern.
Defaults to ``False``.
flags: Union[:class:`int`, :class:`re.RegexFlag`]
The flags to pass to the regular expression compiler.
:attr:`re.IGNORECASE`, :attr:`re.ASCII` and :attr:`re.MULTILINE`
are set to this if the respective parameters are set to ``True``.
This cannot be used with a pre-compiled pattern.
Defaults to ``0``.
Attributes
------------
pattern: :class:`re.Pattern`
The compiled regular expression pattern.
"""

def __init__(
self,
pattern: Union[str, re.Pattern[str]],
case_insensitive: bool = False,
force_ascii: bool = False,
multiline: bool = False,
flags: Union[int, re.RegexFlag] = 0,
) -> None:
flags = flags or 0
if case_insensitive:
flags |= re.IGNORECASE
if force_ascii:
flags |= re.ASCII
if multiline:
flags |= re.MULTILINE

if flags and isinstance(pattern, re.Pattern):
raise ValueError('Cannot specify flags with a pre-compiled pattern')

self.pattern: re.Pattern[str] = pattern if isinstance(pattern, re.Pattern) else re.compile(pattern, flags)

async def convert(self, ctx: Context[BotT], argument: str) -> re.Match[str]:
match_ = self.pattern.fullmatch(argument)
if match_ is None:
raise NoMatch(self.pattern, argument)

return match_

class clean_content(Converter[str]):
"""Converts the argument to mention scrubbed version of
said content.
Expand Down
24 changes: 24 additions & 0 deletions discord/ext/commands/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from __future__ import annotations

import re
from typing import TYPE_CHECKING, Any, Callable, List, Optional, Tuple, Union

from discord.errors import ClientException, DiscordException
Expand Down Expand Up @@ -105,6 +106,7 @@
'MissingRequiredFlag',
'HybridCommandError',
'RangeError',
'NoMatch',
)


Expand Down Expand Up @@ -1186,6 +1188,28 @@ def __init__(self, flag: Flag) -> None:
self.flag: Flag = flag
super().__init__(f'Flag {flag.name!r} does not have an argument')

class NoMatch(ArgumentParsingError):
"""An exception raised when the parser fails to match a user's input to a pattern.
This inherits from :exc:`ArgumentParsingError`.
.. versionadded:: 2.5
Attributes
-----------
pattern: :class:`re.Pattern`
The pattern that failed to match.
argument: :class:`str`
The argument that failed to match.
"""

def __init__(self, pattern: re.Pattern, argument: str) -> None:
self.pattern: re.Pattern = pattern
self.argument: str = argument
super().__init__(
f'{argument!r} did not match the required pattern: {pattern.pattern}'
)


class HybridCommandError(CommandError):
"""An exception raised when a :class:`~discord.ext.commands.HybridCommand` raises
Expand Down

0 comments on commit 58c3744

Please sign in to comment.