Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enum options #1292

Merged
merged 10 commits into from
May 7, 2022
16 changes: 13 additions & 3 deletions discord/commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import re
import types
from collections import OrderedDict
from enum import Enum
from typing import (
TYPE_CHECKING,
Any,
Expand Down Expand Up @@ -677,12 +678,12 @@ def _parse_options(self, params) -> List[Option]:

if self._is_typing_union(option):
if self._is_typing_optional(option):
option = Option(option.__args__[0], "No description provided", required=False)
option = Option(option.__args__[0], None, required=False)
else:
option = Option(option.__args__, "No description provided")
option = Option(option.__args__, None)
Lulalaby marked this conversation as resolved.
Show resolved Hide resolved

if not isinstance(option, Option):
option = Option(option, "No description provided")
option = Option(option, None)
Lulalaby marked this conversation as resolved.
Show resolved Hide resolved

if option.default is None:
if p_obj.default == inspect.Parameter.empty:
Expand Down Expand Up @@ -825,6 +826,15 @@ async def _invoke(self, ctx: ApplicationContext) -> None:
elif op.input_type == SlashCommandOptionType.string and (converter := op.converter) is not None:
arg = await converter.convert(converter, ctx, arg)

elif issubclass(op._raw_type, Enum):
if isinstance(arg, str) and arg.isdigit():
try:
arg = op._raw_type(int(arg))
except ValueError:
arg = op._raw_type(arg)
else:
arg = op._raw_type(arg)

kwargs[op._parameter_name] = arg

for o in self.options:
Expand Down
22 changes: 19 additions & 3 deletions discord/commands/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
DEALINGS IN THE SOFTWARE.
"""

import inspect
from typing import Any, Dict, List, Literal, Optional, Union
from enum import Enum

from ..enums import ChannelType, SlashCommandOptionType
from ..enums import ChannelType, SlashCommandOptionType, Enum as DiscordEnum

__all__ = (
"ThreadOption",
Expand Down Expand Up @@ -119,14 +121,21 @@ def __init__(self, input_type: Any, /, description: str = None, **kwargs) -> Non
self.name: Optional[str] = kwargs.pop("name", None)
if self.name is not None:
self.name = str(self.name)
self.description = description or "No description provided"
self.converter = None
self._raw_type = input_type
self.channel_types: List[ChannelType] = kwargs.pop("channel_types", [])
enum_choices = []
if not isinstance(input_type, SlashCommandOptionType):
if hasattr(input_type, "convert"):
self.converter = input_type
input_type = SlashCommandOptionType.string
elif issubclass(input_type, (Enum, DiscordEnum)):
enum_choices = [OptionChoice(e.name, e.value) for e in input_type]
if len(enum_choices) != len([elem for elem in enum_choices if elem.value.__class__ == enum_choices[0].value.__class__]):
enum_choices = [OptionChoice(e.name, str(e.value)) for e in input_type]
input_type = SlashCommandOptionType.string
else:
input_type = SlashCommandOptionType.from_datatype(enum_choices[0].value.__class__)
else:
try:
_type = SlashCommandOptionType.from_datatype(input_type)
Expand Down Expand Up @@ -154,10 +163,17 @@ def __init__(self, input_type: Any, /, description: str = None, **kwargs) -> Non
self.input_type = input_type
self.required: bool = kwargs.pop("required", True) if "default" not in kwargs else False
self.default = kwargs.pop("default", None)
self.choices: List[OptionChoice] = [
self.choices: List[OptionChoice] = enum_choices or [
o if isinstance(o, OptionChoice) else OptionChoice(o) for o in kwargs.pop("choices", list())
]

if description is not None:
self.description = description
elif issubclass(self._raw_type, Enum) and (doc := inspect.getdoc(self._raw_type)) is not None:
self.description = doc
else:
self.description = "No description provided"

if self.input_type == SlashCommandOptionType.integer:
minmax_types = (int, type(None))
elif self.input_type == SlashCommandOptionType.number:
Expand Down