Rearrange some stuff and add flag support
This commit is contained in:
parent
17096629cd
commit
2f3d59e625
@ -64,6 +64,7 @@ from .core import GroupMixin
|
|||||||
from .converter import Greedy
|
from .converter import Greedy
|
||||||
from .view import StringView, supported_quotes
|
from .view import StringView, supported_quotes
|
||||||
from .context import Context
|
from .context import Context
|
||||||
|
from .flags import FlagConverter
|
||||||
from . import errors
|
from . import errors
|
||||||
from .help import HelpCommand, DefaultHelpCommand
|
from .help import HelpCommand, DefaultHelpCommand
|
||||||
from .cog import Cog
|
from .cog import Cog
|
||||||
@ -1271,7 +1272,20 @@ class BotBase(GroupMixin):
|
|||||||
ignore_params: List[inspect.Parameter] = []
|
ignore_params: List[inspect.Parameter] = []
|
||||||
message.content = f"{prefix}{command_name} "
|
message.content = f"{prefix}{command_name} "
|
||||||
for name, param in command.clean_params.items():
|
for name, param in command.clean_params.items():
|
||||||
option = next((o for o in command_options if o["name"] == name), None) # type: ignore
|
if inspect.isclass(param.annotation) and issubclass(param.annotation, FlagConverter):
|
||||||
|
for name, flag in param.annotation.get_flags().items():
|
||||||
|
option = next((o for o in command_options if o["name"] == name), None)
|
||||||
|
|
||||||
|
if option is None:
|
||||||
|
if flag.required:
|
||||||
|
raise errors.MissingRequiredFlag(flag)
|
||||||
|
else:
|
||||||
|
prefix = param.annotation.__commands_flag_prefix__
|
||||||
|
delimiter = param.annotation.__commands_flag_delimiter__
|
||||||
|
message.content += f"{prefix}{name} {option['value']}{delimiter}" # type: ignore
|
||||||
|
continue
|
||||||
|
|
||||||
|
option = next((o for o in command_options if o["name"] == name), None)
|
||||||
if option is None:
|
if option is None:
|
||||||
if param.default is param.empty and not command._is_typing_optional(param.annotation):
|
if param.default is param.empty and not command._is_typing_optional(param.annotation):
|
||||||
raise errors.MissingRequiredArgument(param)
|
raise errors.MissingRequiredArgument(param)
|
||||||
@ -1280,8 +1294,7 @@ class BotBase(GroupMixin):
|
|||||||
elif option["type"] == 3 and param.kind != param.KEYWORD_ONLY and not isinstance(param.annotation, Greedy):
|
elif option["type"] == 3 and param.kind != param.KEYWORD_ONLY and not isinstance(param.annotation, Greedy):
|
||||||
# String with space in without "consume rest"
|
# String with space in without "consume rest"
|
||||||
option = cast(_ApplicationCommandInteractionDataOptionString, option)
|
option = cast(_ApplicationCommandInteractionDataOptionString, option)
|
||||||
quoted_string = _quote_string_safe(option["value"])
|
message.content += f"{_quote_string_safe(option['value'])} "
|
||||||
message.content += f"{quoted_string} "
|
|
||||||
else:
|
else:
|
||||||
message.content += f'{option.get("value", "")} '
|
message.content += f'{option.get("value", "")} '
|
||||||
|
|
||||||
|
@ -58,13 +58,14 @@ from .converter import CONVERTER_MAPPING, Converter, run_converters, get_convert
|
|||||||
from ._types import _BaseCommand
|
from ._types import _BaseCommand
|
||||||
from .cog import Cog
|
from .cog import Cog
|
||||||
from .context import Context
|
from .context import Context
|
||||||
|
from .flags import FlagConverter
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing_extensions import Concatenate, ParamSpec, TypeGuard
|
from typing_extensions import Concatenate, ParamSpec, TypeGuard
|
||||||
|
|
||||||
from discord.message import Message
|
from discord.message import Message
|
||||||
from discord.types.interactions import EditApplicationCommand
|
from discord.types.interactions import EditApplicationCommand, ApplicationCommandInteractionDataOption
|
||||||
|
|
||||||
from ._types import (
|
from ._types import (
|
||||||
Coro,
|
Coro,
|
||||||
@ -1202,36 +1203,34 @@ class Command(_BaseCommand, Generic[CogT, P, T]):
|
|||||||
finally:
|
finally:
|
||||||
ctx.command = original
|
ctx.command = original
|
||||||
|
|
||||||
def to_application_command(self, nested: int = 0) -> Optional[EditApplicationCommand]:
|
def _param_to_options(
|
||||||
if self.slash_command is False:
|
self, name: str, annotation: Any, required: bool, varadic: bool
|
||||||
return
|
) -> List[Optional[ApplicationCommandInteractionDataOption]]:
|
||||||
elif nested == 3:
|
|
||||||
raise ApplicationCommandRegistrationError(self, f"{self.qualified_name} is too deeply nested!")
|
|
||||||
|
|
||||||
payload = {"name": self.name, "description": self.short_doc or "no description", "options": []}
|
origin = getattr(annotation, "__origin__", None)
|
||||||
if nested != 0:
|
if inspect.isclass(annotation) and issubclass(annotation, FlagConverter):
|
||||||
payload["type"] = 1
|
return [
|
||||||
|
param
|
||||||
|
for name, flag in annotation.get_flags().items()
|
||||||
|
for param in self._param_to_options(
|
||||||
|
name, flag.annotation, required=flag.required, varadic=flag.annotation is tuple
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
for name, param in self.clean_params.items():
|
if varadic:
|
||||||
annotation: Type[Any] = param.annotation if param.annotation is not param.empty else str
|
annotation = str
|
||||||
origin = getattr(param.annotation, "__origin__", None)
|
origin = None
|
||||||
|
|
||||||
if origin is None and isinstance(annotation, Greedy):
|
if not required and origin is not None and len(annotation.__args__) == 2:
|
||||||
annotation = annotation.converter
|
# Unpack Optional[T] (Union[T, None]) into just T
|
||||||
origin = Greedy
|
annotation, origin = annotation.__args__[0], None
|
||||||
|
|
||||||
option: Dict[str, Any] = {
|
option: Dict[str, Any] = {
|
||||||
"name": name,
|
"name": name,
|
||||||
|
"required": required,
|
||||||
"description": self.option_descriptions[name],
|
"description": self.option_descriptions[name],
|
||||||
"required": (param.default is param.empty and not self._is_typing_optional(annotation))
|
|
||||||
or param.kind == param.VAR_POSITIONAL,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
annotation = cast(Any, annotation)
|
|
||||||
if not option["required"] and origin is not None and len(annotation.__args__) == 2:
|
|
||||||
# Unpack Optional[T] (Union[T, None]) into just T
|
|
||||||
annotation, origin = annotation.__args__[0], None
|
|
||||||
|
|
||||||
if origin is None:
|
if origin is None:
|
||||||
if not inspect.isclass(annotation):
|
if not inspect.isclass(annotation):
|
||||||
annotation = type(annotation)
|
annotation = type(annotation)
|
||||||
@ -1261,7 +1260,28 @@ class Command(_BaseCommand, Generic[CogT, P, T]):
|
|||||||
]
|
]
|
||||||
|
|
||||||
option.setdefault("type", 3) # STRING
|
option.setdefault("type", 3) # STRING
|
||||||
payload["options"].append(option)
|
return [option] # type: ignore
|
||||||
|
|
||||||
|
def to_application_command(self, nested: int = 0) -> Optional[EditApplicationCommand]:
|
||||||
|
if self.slash_command is False:
|
||||||
|
return
|
||||||
|
elif nested == 3:
|
||||||
|
raise ApplicationCommandRegistrationError(self, f"{self.qualified_name} is too deeply nested!")
|
||||||
|
|
||||||
|
payload = {"name": self.name, "description": self.short_doc or "no description", "options": []}
|
||||||
|
if nested != 0:
|
||||||
|
payload["type"] = 1
|
||||||
|
|
||||||
|
for name, param in self.clean_params.items():
|
||||||
|
options = self._param_to_options(
|
||||||
|
name,
|
||||||
|
param.annotation if param.annotation is not param.empty else str,
|
||||||
|
varadic=param.kind == param.KEYWORD_ONLY or isinstance(param.annotation, Greedy),
|
||||||
|
required=(param.default is param.empty and not self._is_typing_optional(param.annotation))
|
||||||
|
or param.kind == param.VAR_POSITIONAL,
|
||||||
|
)
|
||||||
|
if options is not None:
|
||||||
|
payload["options"].extend(option for option in options if option is not None)
|
||||||
|
|
||||||
# Now we have all options, make sure required is before optional.
|
# Now we have all options, make sure required is before optional.
|
||||||
payload["options"] = sorted(payload["options"], key=itemgetter("required"), reverse=True)
|
payload["options"] = sorted(payload["options"], key=itemgetter("required"), reverse=True)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user