Skip to content

Commit f5c6e3a

Browse files
authored
feat💥: rework slash command parameter processing (#1275)
* feat💥: rework slash command parameter processing This both makes it much faster and allows for proper parsing of Annotated. This does break a few niche cases though - most notably, CMD_* are gone. * revert: don't touch autocomplete * chore: remove breakpoint comment * refactor: use annotated class directly --------- Co-authored-by: Astrea49 <25420078+Astrea49@users.noreply.github.com>
1 parent ec481ac commit f5c6e3a

File tree

10 files changed

+208
-191
lines changed

10 files changed

+208
-191
lines changed

docs/src/Guides/08 Converters.md

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class DatabaseEntry():
1515
score: int
1616

1717
@classmethod # you can also use staticmethod
18-
async def convert(cls, ctx: Context, value: str) -> DatabaseEntry:
18+
async def convert(cls, ctx: BaseContext, value: str) -> DatabaseEntry:
1919
"""This is where the magic happens"""
2020
return cls(hypothetical_database.lookup(ctx.guild.id, value))
2121

@@ -44,7 +44,7 @@ You may also use the `Converter` class that `interactions.py` has as well.
4444

4545
```python
4646
class UpperConverter(Converter):
47-
async def convert(ctx: PrefixedContext, argument: str):
47+
async def convert(ctx: BaseContext, argument: str):
4848
return argument.upper()
4949

5050
# Slash Command:
@@ -64,23 +64,9 @@ async def upper(ctx: PrefixedContext, to_upper: UpperConverter):
6464
await ctx.reply(to_upper)
6565
```
6666

67-
## Built-in Converters
67+
## Discord Model Converters
6868

69-
### Context-based Arguments
70-
71-
The library provides `CMD_ARGS`, `CMD_AUTHOR`, `CMD_BODY`, and `CMD_CHANNEL` to get the arguments, the author, the body, and the channel of an instance of a command based on its context. While you can do these yourself in the command itself, having this as an argument may be useful to you, especially for cases where you only have one argument that takes in the rest of the message:
72-
73-
```python
74-
# this example is only viable for prefixed commands
75-
# the other CMD_* can be used with slash commands, however
76-
@prefixed_command()
77-
async def say(ctx: PrefixedContext, content: CMD_BODY):
78-
await ctx.reply(content)
79-
```
80-
81-
### Discord Model Converters
82-
83-
There are also `Converter`s that represent some Discord models that you can subclass from. These are largely useful for prefixed commands, but you may find a use for them elsewhere.
69+
There are `Converter`s that represent some Discord models that you can subclass from. These are largely useful for prefixed commands, but you may find a use for them elsewhere.
8470

8571
A table of objects and their respective converter is as follows:
8672

@@ -109,3 +95,33 @@ A table of objects and their respective converter is as follows:
10995
| `Role` | `RoleConverter` |
11096
| `PartialEmoji` | `PartialEmojiConverter` |
11197
| `CustomEmoji` | `CustomEmojiConverter` |
98+
99+
100+
## `typing.Annotated`
101+
102+
Using `typing.Annotated` can allow you to have more proper typehints when using converters:
103+
104+
```python
105+
class UpperConverter(Converter):
106+
async def convert(ctx: BaseContext, argument: str):
107+
return argument.upper()
108+
109+
# Slash Command:
110+
@slash_command(name="upper", description="Sends back the input in all caps.")
111+
@slash_option(
112+
name="to_upper",
113+
description="The thing to make all caps.",
114+
required=True,
115+
opt_type=OptionType.STRING
116+
)
117+
async def upper(ctx: InteractionContext, to_upper: Annotated[str, UpperConverter]):
118+
await ctx.send(to_upper)
119+
120+
# Prefixed Command:
121+
@prefixed_command()
122+
async def upper(ctx: PrefixedContext, to_upper: Annotated[str, UpperConverter]):
123+
await ctx.reply(to_upper)
124+
```
125+
126+
For slash commands, `interactions.py` will find the first argument in `Annotated` (besides for the first argument) that are like the converters in this guide and use that.
127+
For prefixed commands, `interactions.py` will always use the second parameter in `Annotated` as the actual converter/parameter to process.

docs/src/Guides/26 Prefixed Commands.md

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -255,22 +255,6 @@ async def one_or_two(ctx: PrefixedContext, num: Literal[1, 2]):
255255

256256
![Literal Conversion](../images/PrefixedCommands/LiteralConversion.png "The above running with the arguments: 1")
257257

258-
#### `typing.Annotated`
259-
260-
Using `typing.Annotated` can allow you to have more proper typehints when using converters:
261-
262-
```python
263-
class JudgementConverter(Converter):
264-
async def convert(self, ctx: PrefixedContext, argument: str):
265-
return f"{ctx.author.mention} is {argument}."
266-
267-
@prefixed_command()
268-
async def judgement(ctx: PrefixedContext, judgment: Annotated[str, JudgementConverter]):
269-
await ctx.reply(judgment)
270-
```
271-
272-
`interactions.py` will use the second parameter in `Annotated` as the actual converter.
273-
274258
#### `Greedy`
275259

276260
The `Greedy` class, included in this library, specifies `interactions.py` to keep converting as many arguments as it can until it fails to do so. For example:

interactions/__init__.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,6 @@
9292
ChannelSelectMenu,
9393
ChannelType,
9494
check,
95-
CMD_ARGS,
96-
CMD_AUTHOR,
97-
CMD_CHANNEL,
9895
Color,
9996
COLOR_TYPES,
10097
Colour,
@@ -266,6 +263,7 @@
266263
SlashCommand,
267264
SlashCommandChoice,
268265
SlashCommandOption,
266+
SlashCommandParameter,
269267
SlashContext,
270268
Snowflake,
271269
Snowflake_Type,
@@ -393,9 +391,6 @@
393391
"ChannelType",
394392
"check",
395393
"Client",
396-
"CMD_ARGS",
397-
"CMD_AUTHOR",
398-
"CMD_CHANNEL",
399394
"Color",
400395
"COLOR_TYPES",
401396
"Colour",
@@ -596,6 +591,7 @@
596591
"SlashCommand",
597592
"SlashCommandChoice",
598593
"SlashCommandOption",
594+
"SlashCommandParameter",
599595
"SlashContext",
600596
"smart_cache",
601597
"Snowflake",

interactions/client/client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,9 @@ def add_interaction(self, command: InteractionCommand) -> bool:
12011201
if command.callback is None:
12021202
return False
12031203

1204+
if isinstance(command, SlashCommand):
1205+
command._parse_parameters()
1206+
12041207
base, group, sub, *_ = command.resolved_name.split(" ") + [None, None]
12051208

12061209
for scope in command.scopes:

interactions/models/__init__.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,6 @@
199199
CallbackType,
200200
ChannelConverter,
201201
check,
202-
CMD_ARGS,
203-
CMD_AUTHOR,
204-
CMD_CHANNEL,
205202
component_callback,
206203
ComponentCommand,
207204
ComponentContext,
@@ -276,6 +273,7 @@
276273
SlashCommand,
277274
SlashCommandChoice,
278275
SlashCommandOption,
276+
SlashCommandParameter,
279277
SlashContext,
280278
SnowflakeConverter,
281279
subcommand,
@@ -343,9 +341,6 @@
343341
"ChannelSelectMenu",
344342
"ChannelType",
345343
"check",
346-
"CMD_ARGS",
347-
"CMD_AUTHOR",
348-
"CMD_CHANNEL",
349344
"Color",
350345
"COLOR_TYPES",
351346
"Colour",
@@ -517,6 +512,7 @@
517512
"SlashCommand",
518513
"SlashCommandChoice",
519514
"SlashCommandOption",
515+
"SlashCommandParameter",
520516
"SlashContext",
521517
"Snowflake",
522518
"Snowflake_Type",

interactions/models/internal/__init__.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
from .annotations import (
2-
CMD_ARGS,
3-
CMD_AUTHOR,
4-
CMD_CHANNEL,
52
slash_attachment_option,
63
slash_bool_option,
74
slash_channel_option,
@@ -37,6 +34,7 @@
3734
SlashCommand,
3835
SlashCommandChoice,
3936
SlashCommandOption,
37+
SlashCommandParameter,
4038
subcommand,
4139
sync_needed,
4240
)
@@ -108,9 +106,6 @@
108106
"CallbackType",
109107
"ChannelConverter",
110108
"check",
111-
"CMD_ARGS",
112-
"CMD_AUTHOR",
113-
"CMD_CHANNEL",
114109
"component_callback",
115110
"ComponentCommand",
116111
"ComponentContext",
@@ -185,6 +180,7 @@
185180
"SlashCommand",
186181
"SlashCommandChoice",
187182
"SlashCommandOption",
183+
"SlashCommandParameter",
188184
"SlashContext",
189185
"SnowflakeConverter",
190186
"subcommand",

interactions/models/internal/annotations/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from .argument import CMD_ARGS, CMD_AUTHOR, CMD_CHANNEL
21
from .slash import (
32
slash_attachment_option,
43
slash_bool_option,
@@ -12,9 +11,6 @@
1211
)
1312

1413
__all__ = (
15-
"CMD_ARGS",
16-
"CMD_AUTHOR",
17-
"CMD_CHANNEL",
1814
"slash_attachment_option",
1915
"slash_bool_option",
2016
"slash_channel_option",

interactions/models/internal/annotations/argument.py

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)