hikari-arc 0.4.0__py3-none-any.whl → 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. arc/__init__.py +55 -5
  2. arc/abc/__init__.py +32 -1
  3. arc/abc/client.py +207 -67
  4. arc/abc/command.py +245 -34
  5. arc/abc/error_handler.py +33 -2
  6. arc/abc/hookable.py +24 -0
  7. arc/abc/limiter.py +61 -0
  8. arc/abc/option.py +73 -5
  9. arc/abc/plugin.py +185 -29
  10. arc/client.py +103 -33
  11. arc/command/message.py +21 -18
  12. arc/command/option/attachment.py +9 -5
  13. arc/command/option/bool.py +9 -6
  14. arc/command/option/channel.py +9 -5
  15. arc/command/option/float.py +11 -7
  16. arc/command/option/int.py +11 -7
  17. arc/command/option/mentionable.py +9 -5
  18. arc/command/option/role.py +9 -5
  19. arc/command/option/str.py +11 -7
  20. arc/command/option/user.py +9 -5
  21. arc/command/slash.py +222 -197
  22. arc/command/user.py +20 -17
  23. arc/context/autocomplete.py +1 -0
  24. arc/context/base.py +216 -105
  25. arc/errors.py +52 -10
  26. arc/events.py +5 -1
  27. arc/extension.py +23 -0
  28. arc/internal/about.py +1 -1
  29. arc/internal/deprecation.py +3 -4
  30. arc/internal/options.py +106 -0
  31. arc/internal/sigparse.py +19 -1
  32. arc/internal/sync.py +13 -10
  33. arc/internal/types.py +34 -15
  34. arc/locale.py +28 -0
  35. arc/plugin.py +56 -5
  36. arc/utils/__init__.py +53 -2
  37. arc/utils/hooks/__init__.py +25 -0
  38. arc/utils/{hooks.py → hooks/basic.py} +28 -1
  39. arc/utils/hooks/limiters.py +217 -0
  40. arc/utils/ratelimiter.py +243 -0
  41. {hikari_arc-0.4.0.dist-info → hikari_arc-0.6.0.dist-info}/METADATA +13 -8
  42. hikari_arc-0.6.0.dist-info/RECORD +52 -0
  43. hikari_arc-0.4.0.dist-info/RECORD +0 -47
  44. {hikari_arc-0.4.0.dist-info → hikari_arc-0.6.0.dist-info}/LICENSE +0 -0
  45. {hikari_arc-0.4.0.dist-info → hikari_arc-0.6.0.dist-info}/WHEEL +0 -0
  46. {hikari_arc-0.4.0.dist-info → hikari_arc-0.6.0.dist-info}/top_level.txt +0 -0
arc/command/user.py CHANGED
@@ -14,7 +14,7 @@ if t.TYPE_CHECKING:
14
14
  import asyncio
15
15
 
16
16
  from arc.abc.command import CallableCommandProto
17
- from arc.internal.types import UserContextCallbackT
17
+ from arc.internal.types import UserCommandCallbackT
18
18
 
19
19
  __all__ = ("UserCommand", "user_command")
20
20
 
@@ -66,33 +66,36 @@ class UserCommand(CallableCommandBase[ClientT, hikari.api.ContextMenuCommandBuil
66
66
  def user_command(
67
67
  name: str,
68
68
  *,
69
- guilds: t.Sequence[hikari.SnowflakeishOr[hikari.PartialGuild]] | None = None,
70
- is_dm_enabled: bool = True,
71
- is_nsfw: bool = False,
72
- autodefer: bool | AutodeferMode = True,
73
- default_permissions: hikari.UndefinedOr[hikari.Permissions] = hikari.UNDEFINED,
69
+ guilds: t.Sequence[hikari.PartialGuild | hikari.Snowflakeish] | hikari.UndefinedType = hikari.UNDEFINED,
70
+ is_dm_enabled: bool | hikari.UndefinedType = hikari.UNDEFINED,
71
+ is_nsfw: bool | hikari.UndefinedType = hikari.UNDEFINED,
72
+ autodefer: bool | AutodeferMode | hikari.UndefinedType = hikari.UNDEFINED,
73
+ default_permissions: hikari.Permissions | hikari.UndefinedType = hikari.UNDEFINED,
74
74
  name_localizations: t.Mapping[hikari.Locale, str] | None = None,
75
- ) -> t.Callable[[UserContextCallbackT[ClientT]], UserCommand[ClientT]]:
75
+ ) -> t.Callable[[UserCommandCallbackT[ClientT]], UserCommand[ClientT]]:
76
76
  """A decorator that creates a context-menu command on a user.
77
77
 
78
78
  Parameters
79
79
  ----------
80
80
  name : str
81
81
  The name of the command.
82
- guilds : t.Sequence[hikari.SnowflakeishOr[hikari.PartialGuild]] | None
83
- The guilds this command is available in.
84
- is_dm_enabled : bool
82
+ guilds : t.Sequence[hikari.PartialGuild | hikari.Snowflakeish] | hikari.UndefinedType
83
+ The guilds this command should be enabled in, if left as undefined, the command is global
84
+ is_dm_enabled : bool | hikari.UndefinedType
85
85
  Whether this command is enabled in DMs.
86
- is_nsfw : bool
86
+ is_nsfw : bool | hikari.UndefinedType
87
87
  Whether this command is NSFW.
88
- autodefer : bool | AutodeferMode
89
- If True, this command will be automatically deferred if it takes longer than 2 seconds to respond, by default True
90
- default_permissions : hikari.UndefinedOr[hikari.Permissions]
88
+ autodefer : bool | AutodeferMode | hikari.UndefinedType
89
+ If True, this command will be automatically deferred if it takes longer than 2 seconds to respond
90
+ default_permissions : hikari.Permissions | hikari.UndefinedType
91
91
  The default permissions for this command.
92
92
  Keep in mind that guild administrators can change this, it should only be used to provide safe defaults.
93
93
  name_localizations : t.Mapping[hikari.Locale, str] | None
94
94
  The localizations for this command's name.
95
95
 
96
+ !!! note
97
+ Parameters left as `hikari.UNDEFINED` will be inherited from the parent plugin or client.
98
+
96
99
  Usage
97
100
  -----
98
101
  ```py
@@ -103,13 +106,13 @@ def user_command(
103
106
  ```
104
107
  """
105
108
 
106
- def decorator(callback: UserContextCallbackT[ClientT]) -> UserCommand[ClientT]:
107
- guild_ids = [hikari.Snowflake(guild) for guild in guilds] if guilds else []
109
+ def decorator(callback: UserCommandCallbackT[ClientT]) -> UserCommand[ClientT]:
110
+ guild_ids = tuple(hikari.Snowflake(i) for i in guilds) if guilds is not hikari.UNDEFINED else hikari.UNDEFINED
108
111
 
109
112
  return UserCommand(
110
113
  callback=callback,
111
114
  name=name,
112
- autodefer=AutodeferMode(autodefer),
115
+ autodefer=AutodeferMode(autodefer) if isinstance(autodefer, bool) else autodefer,
113
116
  guilds=guild_ids,
114
117
  is_dm_enabled=is_dm_enabled,
115
118
  is_nsfw=is_nsfw,
@@ -16,6 +16,7 @@ __all__ = ("AutocompleteData",)
16
16
 
17
17
 
18
18
  # Don't slot, because we want to use cached_property.
19
+ @t.final
19
20
  @attr.define(slots=False, kw_only=True)
20
21
  class AutocompleteData(t.Generic[ClientT, ChoiceT]):
21
22
  """The data that is provided to an autocomplete callback."""
arc/context/base.py CHANGED
@@ -10,7 +10,9 @@ from contextlib import suppress
10
10
  import attr
11
11
  import hikari
12
12
 
13
+ from arc.abc.option import OptionType # noqa: TCH001 Needed for tests
13
14
  from arc.errors import NoResponseIssuedError, ResponseAlreadyIssuedError
15
+ from arc.internal.options import OPTIONTYPE_TO_TYPE, resolve_snowflake_value
14
16
  from arc.internal.types import ClientT, ResponseBuilderT
15
17
  from arc.locale import CustomLocaleRequest
16
18
 
@@ -22,7 +24,10 @@ __all__ = ("Context", "InteractionResponse", "AutodeferMode")
22
24
  logger = logging.getLogger(__name__)
23
25
 
24
26
 
27
+ @t.final
25
28
  class AutodeferMode(enum.IntEnum):
29
+ """An enum representing autodefer configuration."""
30
+
26
31
  OFF = 0
27
32
  """Do not autodefer."""
28
33
 
@@ -42,18 +47,18 @@ class AutodeferMode(enum.IntEnum):
42
47
  class _ResponseGlue:
43
48
  """A glue object to allow for easy creation of responses in both REST and Gateway contexts."""
44
49
 
45
- content: hikari.UndefinedOr[t.Any] = hikari.UNDEFINED
50
+ content: t.Any | hikari.UndefinedType = hikari.UNDEFINED
46
51
  flags: int | hikari.MessageFlag | hikari.UndefinedType = hikari.UNDEFINED
47
- tts: hikari.UndefinedOr[bool] = hikari.UNDEFINED
48
- component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED
49
- components: hikari.UndefinedOr[t.Sequence[hikari.api.ComponentBuilder]] = hikari.UNDEFINED
50
- attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED
51
- attachments: hikari.UndefinedOr[t.Sequence[hikari.Resourceish]] = hikari.UNDEFINED
52
- embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED
53
- embeds: hikari.UndefinedOr[t.Sequence[hikari.Embed]] = hikari.UNDEFINED
54
- mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED
55
- user_mentions: hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialUser] | bool] = hikari.UNDEFINED
56
- role_mentions: hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialRole] | bool] = hikari.UNDEFINED
52
+ tts: bool | hikari.UndefinedType = hikari.UNDEFINED
53
+ component: hikari.api.ComponentBuilder | hikari.UndefinedType = hikari.UNDEFINED
54
+ components: t.Sequence[hikari.api.ComponentBuilder] | hikari.UndefinedType = hikari.UNDEFINED
55
+ attachment: hikari.Resourceish | hikari.UndefinedType = hikari.UNDEFINED
56
+ attachments: t.Sequence[hikari.Resourceish] | hikari.UndefinedType = hikari.UNDEFINED
57
+ embed: hikari.Embed | hikari.UndefinedType = hikari.UNDEFINED
58
+ embeds: t.Sequence[hikari.Embed] | hikari.UndefinedType = hikari.UNDEFINED
59
+ mentions_everyone: bool | hikari.UndefinedType = hikari.UNDEFINED
60
+ user_mentions: t.Sequence[hikari.Snowflakeish | hikari.PartialUser] | bool | hikari.UndefinedType = hikari.UNDEFINED
61
+ role_mentions: t.Sequence[hikari.Snowflakeish | hikari.PartialRole] | bool | hikari.UndefinedType = hikari.UNDEFINED
57
62
 
58
63
  def _to_dict(self) -> dict[str, t.Any]:
59
64
  return {
@@ -89,6 +94,7 @@ class _ResponseGlue:
89
94
  )
90
95
 
91
96
 
97
+ @t.final
92
98
  class InteractionResponse:
93
99
  """Represents a message response to an interaction, allows for standardized handling of such responses.
94
100
  This class is not meant to be directly instantiated, and is instead returned by [Context][arc.context.base.Context]
@@ -145,7 +151,6 @@ class InteractionResponse:
145
151
  if self._message:
146
152
  return self._message
147
153
 
148
- assert isinstance(self._context.interaction, (hikari.ComponentInteraction, hikari.ModalInteraction))
149
154
  return await self._context.interaction.fetch_initial_response()
150
155
 
151
156
  async def delete(self) -> None:
@@ -157,41 +162,45 @@ class InteractionResponse:
157
162
 
158
163
  async def edit(
159
164
  self,
160
- content: hikari.UndefinedOr[t.Any] = hikari.UNDEFINED,
165
+ content: t.Any | hikari.UndefinedType = hikari.UNDEFINED,
161
166
  *,
162
- component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED,
163
- components: hikari.UndefinedOr[t.Sequence[hikari.api.ComponentBuilder]] = hikari.UNDEFINED,
164
- attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED,
165
- attachments: hikari.UndefinedOr[t.Sequence[hikari.Resourceish]] = hikari.UNDEFINED,
166
- embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED,
167
- embeds: hikari.UndefinedOr[t.Sequence[hikari.Embed]] = hikari.UNDEFINED,
168
- mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED,
169
- user_mentions: hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialUser] | bool] = hikari.UNDEFINED,
170
- role_mentions: hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialRole] | bool] = hikari.UNDEFINED,
167
+ component: hikari.api.ComponentBuilder | hikari.UndefinedType = hikari.UNDEFINED,
168
+ components: t.Sequence[hikari.api.ComponentBuilder] | hikari.UndefinedType = hikari.UNDEFINED,
169
+ attachment: hikari.Resourceish | hikari.UndefinedType = hikari.UNDEFINED,
170
+ attachments: t.Sequence[hikari.Resourceish] | hikari.UndefinedType = hikari.UNDEFINED,
171
+ embed: hikari.Embed | hikari.UndefinedType = hikari.UNDEFINED,
172
+ embeds: t.Sequence[hikari.Embed] | hikari.UndefinedType = hikari.UNDEFINED,
173
+ mentions_everyone: bool | hikari.UndefinedType = hikari.UNDEFINED,
174
+ user_mentions: t.Sequence[hikari.Snowflakeish | hikari.PartialUser]
175
+ | bool
176
+ | hikari.UndefinedType = hikari.UNDEFINED,
177
+ role_mentions: t.Sequence[hikari.Snowflakeish | hikari.PartialRole]
178
+ | bool
179
+ | hikari.UndefinedType = hikari.UNDEFINED,
171
180
  ) -> InteractionResponse:
172
181
  """A short-hand method to edit the message belonging to this response.
173
182
 
174
183
  Parameters
175
184
  ----------
176
- content : hikari.UndefinedOr[t.Any], optional
185
+ content : t.Any | hikari.UndefinedType
177
186
  The content of the message. Anything passed here will be cast to str.
178
- attachment : hikari.UndefinedOr[hikari.Resourceish], optional
187
+ attachment : hikari.Resourceish | hikari.UndefinedType
179
188
  An attachment to add to this message.
180
- attachments : hikari.UndefinedOr[t.Sequence[hikari.Resourceish]], optional
189
+ attachments : t.Sequence[hikari.Resourceish] | hikari.UndefinedType
181
190
  A sequence of attachments to add to this message.
182
- component : hikari.UndefinedOr[hikari.api.ComponentBuilder], optional
191
+ component : hikari.api.ComponentBuilder | hikari.UndefinedType
183
192
  A component to add to this message.
184
- components : hikari.UndefinedOr[t.Sequence[hikari.api.ComponentBuilder]], optional
193
+ components : t.Sequence[hikari.api.ComponentBuilder] | hikari.UndefinedType
185
194
  A sequence of components to add to this message.
186
- embed : hikari.UndefinedOr[hikari.Embed], optional
195
+ embed : hikari.Embed | hikari.UndefinedType
187
196
  An embed to add to this message.
188
- embeds : hikari.UndefinedOr[t.Sequence[hikari.Embed]], optional
197
+ embeds : t.Sequence[hikari.Embed] | hikari.UndefinedType
189
198
  A sequence of embeds to add to this message.
190
- mentions_everyone : hikari.UndefinedOr[bool], optional
199
+ mentions_everyone : bool | hikari.UndefinedType
191
200
  If True, mentioning @everyone will be allowed.
192
- user_mentions : hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialUser] | bool], optional
201
+ user_mentions : t.Sequence[hikari.Snowflakish | hikari.PartialUser] | bool | hikari.UndefinedType
193
202
  The set of allowed user mentions in this message. Set to True to allow all.
194
- role_mentions : hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialRole] | bool], optional
203
+ role_mentions : t.Sequence[hikari.Snowflakish | hikari.PartialRole] | bool | hikari.UndefinedType
195
204
  The set of allowed role mentions in this message. Set to True to allow all.
196
205
 
197
206
  Returns
@@ -229,6 +238,7 @@ class InteractionResponse:
229
238
  return await self._context._create_response(message)
230
239
 
231
240
 
241
+ @t.final
232
242
  class Context(t.Generic[ClientT]):
233
243
  """A context object that is proxying a Discord command interaction."""
234
244
 
@@ -244,6 +254,7 @@ class Context(t.Generic[ClientT]):
244
254
  "_created_at",
245
255
  "_autodefer_task",
246
256
  "_has_command_failed",
257
+ "_options",
247
258
  )
248
259
 
249
260
  def __init__(
@@ -252,6 +263,7 @@ class Context(t.Generic[ClientT]):
252
263
  self._client = client
253
264
  self._command = command
254
265
  self._interaction: hikari.CommandInteraction = interaction
266
+ self._options: t.Sequence[hikari.CommandInteractionOption] | None = None
255
267
  self._responses: t.MutableSequence[InteractionResponse] = []
256
268
  self._resp_builder: asyncio.Future[ResponseBuilderT] = asyncio.Future()
257
269
  self._issued_response: bool = False
@@ -264,11 +276,11 @@ class Context(t.Generic[ClientT]):
264
276
  def interaction(self) -> hikari.CommandInteraction:
265
277
  """The underlying interaction object.
266
278
 
267
- .. warning::
279
+ !!! warning
268
280
  This should not be used directly in most cases, and is only exposed for advanced use cases.
269
281
 
270
- If you use the interaction to create a response in a view,
271
- you should disable the autodefer feature in your View.
282
+ If you use the interaction to create a response,
283
+ you should disable the autodefer feature in your command.
272
284
  """
273
285
  return self._interaction
274
286
 
@@ -396,6 +408,82 @@ class Context(t.Generic[ClientT]):
396
408
  """Gets the channel this context represents, None if in a DM. Requires application cache."""
397
409
  return self._interaction.get_channel()
398
410
 
411
+ @t.overload
412
+ def get_option(self, name: str, opt_type: t.Literal[OptionType.ATTACHMENT]) -> hikari.Attachment | None:
413
+ ...
414
+
415
+ @t.overload
416
+ def get_option(self, name: str, opt_type: t.Literal[OptionType.MENTIONABLE]) -> hikari.User | hikari.Role | None:
417
+ ...
418
+
419
+ @t.overload
420
+ def get_option(self, name: str, opt_type: t.Literal[OptionType.USER]) -> hikari.User | None:
421
+ ...
422
+
423
+ @t.overload
424
+ def get_option(self, name: str, opt_type: t.Literal[OptionType.ROLE]) -> hikari.Role | None:
425
+ ...
426
+
427
+ @t.overload
428
+ def get_option(self, name: str, opt_type: t.Literal[OptionType.CHANNEL]) -> hikari.PartialChannel | None:
429
+ ...
430
+
431
+ @t.overload
432
+ def get_option(self, name: str, opt_type: t.Literal[OptionType.STRING]) -> str | None:
433
+ ...
434
+
435
+ @t.overload
436
+ def get_option(self, name: str, opt_type: t.Literal[OptionType.BOOLEAN]) -> bool | None:
437
+ ...
438
+
439
+ @t.overload
440
+ def get_option(self, name: str, opt_type: t.Literal[OptionType.FLOAT]) -> float | None:
441
+ ...
442
+
443
+ @t.overload
444
+ def get_option(self, name: str, opt_type: t.Literal[OptionType.INTEGER]) -> int | None:
445
+ ...
446
+
447
+ def get_option(self, name: str, opt_type: OptionType) -> t.Any | None:
448
+ """Get the value of an option by name.
449
+
450
+ Parameters
451
+ ----------
452
+ name : str
453
+ The name of the option.
454
+ opt_type : hikari.OptionType
455
+ The type of the option.
456
+
457
+ Returns
458
+ -------
459
+ ValueT | None
460
+ The value of the option, or None if it does not exist, or is not of the correct type.
461
+
462
+ Usage
463
+ -----
464
+ ```py
465
+ value = ctx.get_option("name", arc.OptionType.STRING)
466
+ if value is None:
467
+ # Option does not exist or is not a string
468
+
469
+ # Do something with the value
470
+ print(value)
471
+ ```
472
+
473
+ """
474
+ if self._options is None:
475
+ return None
476
+
477
+ value = next((x.value for x in self._options if x.name == name), None)
478
+
479
+ if value is hikari.Snowflake and self._interaction.resolved is not None:
480
+ value = resolve_snowflake_value(value, opt_type, self._interaction.resolved)
481
+
482
+ if not isinstance(value, OPTIONTYPE_TO_TYPE[opt_type]):
483
+ return None
484
+
485
+ return value
486
+
399
487
  def loc(self, key: str, use_guild: bool = True, force_locale: hikari.Locale | None = None, **kwargs: t.Any) -> str:
400
488
  """Get a localized string using the interaction's locale.
401
489
 
@@ -403,9 +491,9 @@ class Context(t.Generic[ClientT]):
403
491
  ----------
404
492
  key : str
405
493
  The key of the string to localize.
406
- use_guild : bool, optional
494
+ use_guild : bool
407
495
  Whether to use the guild or not, if in a guild.
408
- force_locale : hikari.Locale | None, optional
496
+ force_locale : hikari.Locale | None
409
497
  Force a locale to use, instead of the context's locale.
410
498
  kwargs : t.Any
411
499
  The keyword arguments to pass to the string formatter.
@@ -457,51 +545,55 @@ class Context(t.Generic[ClientT]):
457
545
 
458
546
  async def respond(
459
547
  self,
460
- content: hikari.UndefinedOr[t.Any] = hikari.UNDEFINED,
548
+ content: t.Any | hikari.UndefinedType = hikari.UNDEFINED,
461
549
  *,
462
550
  flags: int | hikari.MessageFlag | hikari.UndefinedType = hikari.UNDEFINED,
463
- tts: hikari.UndefinedOr[bool] = hikari.UNDEFINED,
464
- component: hikari.UndefinedOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED,
465
- components: hikari.UndefinedOr[t.Sequence[hikari.api.ComponentBuilder]] = hikari.UNDEFINED,
466
- attachment: hikari.UndefinedOr[hikari.Resourceish] = hikari.UNDEFINED,
467
- attachments: hikari.UndefinedOr[t.Sequence[hikari.Resourceish]] = hikari.UNDEFINED,
468
- embed: hikari.UndefinedOr[hikari.Embed] = hikari.UNDEFINED,
469
- embeds: hikari.UndefinedOr[t.Sequence[hikari.Embed]] = hikari.UNDEFINED,
470
- mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED,
471
- user_mentions: hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialUser] | bool] = hikari.UNDEFINED,
472
- role_mentions: hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialRole] | bool] = hikari.UNDEFINED,
473
- delete_after: hikari.UndefinedOr[float | int | datetime.timedelta] = hikari.UNDEFINED,
551
+ tts: bool | hikari.UndefinedType = hikari.UNDEFINED,
552
+ attachment: hikari.Resourceish | hikari.UndefinedType = hikari.UNDEFINED,
553
+ attachments: t.Sequence[hikari.Resourceish] | hikari.UndefinedType = hikari.UNDEFINED,
554
+ component: hikari.api.ComponentBuilder | hikari.UndefinedType = hikari.UNDEFINED,
555
+ components: t.Sequence[hikari.api.ComponentBuilder] | hikari.UndefinedType = hikari.UNDEFINED,
556
+ embed: hikari.Embed | hikari.UndefinedType = hikari.UNDEFINED,
557
+ embeds: t.Sequence[hikari.Embed] | hikari.UndefinedType = hikari.UNDEFINED,
558
+ mentions_everyone: bool | hikari.UndefinedType = hikari.UNDEFINED,
559
+ user_mentions: t.Sequence[hikari.Snowflakeish | hikari.PartialUser]
560
+ | bool
561
+ | hikari.UndefinedType = hikari.UNDEFINED,
562
+ role_mentions: t.Sequence[hikari.Snowflake | hikari.PartialRole]
563
+ | bool
564
+ | hikari.UndefinedType = hikari.UNDEFINED,
565
+ delete_after: float | int | datetime.timedelta | hikari.UndefinedType = hikari.UNDEFINED,
474
566
  ) -> InteractionResponse:
475
567
  """Short-hand method to create a new message response via the interaction this context represents.
476
568
  This function automatically determines if the response should be an initial response or a followup.
477
569
 
478
570
  Parameters
479
571
  ----------
480
- content : hikari.UndefinedOr[Any], optional
572
+ content : Any | hikari.UndefinedType
481
573
  The content of the message. Anything passed here will be cast to str.
482
- tts : hikari.UndefinedOr[bool], optional
574
+ tts : bool | hikari.UndefinedType
483
575
  If the message should be tts or not.
484
- attachment : hikari.UndefinedOr[hikari.Resourceish], optional
576
+ attachment : hikari.Resourceish | hikari.UndefinedType
485
577
  An attachment to add to this message.
486
- attachments : hikari.UndefinedOr[t.Sequence[hikari.Resourceish]], optional
578
+ attachments : t.Sequence[hikari.Resourceish] | hikari.UndefinedType
487
579
  A sequence of attachments to add to this message.
488
- component : hikari.UndefinedOr[hikari.api.special_endpoints.ComponentBuilder], optional
580
+ component : hikari.api.special_endpoints.ComponentBuilder | hikari.UndefinedType
489
581
  A component to add to this message.
490
- components : hikari.UndefinedOr[t.Sequence[hikari.api.special_endpoints.ComponentBuilder]], optional
582
+ components : t.Sequence[hikari.api.special_endpoints.ComponentBuilder] | hikari.UndefinedType
491
583
  A sequence of components to add to this message.
492
- embed : hikari.UndefinedOr[hikari.Embed], optional
584
+ embed : hikari.Embed | hikari.UndefinedType
493
585
  An embed to add to this message.
494
- embeds : hikari.UndefinedOr[Sequence[hikari.Embed]], optional
586
+ embeds : Sequence[hikari.Embed] | hikari.UndefinedType
495
587
  A sequence of embeds to add to this message.
496
- mentions_everyone : hikari.UndefinedOr[bool], optional
588
+ mentions_everyone : bool | hikari.UndefinedType
497
589
  If True, mentioning @everyone will be allowed.
498
- user_mentions : hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialUser] | bool], optional
590
+ user_mentions : hikari.SnowflakeishSequence[hikari.PartialUser] | bool | hikari.UndefinedType
499
591
  The set of allowed user mentions in this message. Set to True to allow all.
500
- role_mentions : hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialRole] | bool], optional
592
+ role_mentions : hikari.SnowflakeishSequence[hikari.PartialRole] | bool | hikari.UndefinedType
501
593
  The set of allowed role mentions in this message. Set to True to allow all.
502
- flags : int | hikari.MessageFlag | hikari.UndefinedType, optional
594
+ flags : int | hikari.MessageFlag | hikari.UndefinedType
503
595
  Message flags that should be included with this message.
504
- delete_after: hikari.UndefinedOr[float | int | datetime.timedelta], optional
596
+ delete_after: float | int | datetime.timedelta | hikari.UndefinedType
505
597
  Delete the response after the specified delay.
506
598
 
507
599
  Returns
@@ -566,7 +658,8 @@ class Context(t.Generic[ClientT]):
566
658
  ...
567
659
 
568
660
  async def respond_with_builder(self, builder: ResponseBuilderT) -> InteractionResponse | None:
569
- """Respond to the interaction with a builder.
661
+ """Respond to the interaction with a builder. This method will try to turn the builder into a valid
662
+ response or followup, depending on the builder type and interaction state.
570
663
 
571
664
  Parameters
572
665
  ----------
@@ -581,13 +674,13 @@ class Context(t.Generic[ClientT]):
581
674
  Raises
582
675
  ------
583
676
  RuntimeError
584
- The interaction was already issued an initial response.
677
+ The interaction was already issued an initial response and the builder can only be used for initial responses.
585
678
  """
586
679
  async with self._response_lock:
587
- if self._issued_response:
680
+ if self._issued_response and not isinstance(builder, hikari.api.InteractionMessageBuilder):
588
681
  raise RuntimeError("This interaction was already issued an initial response.")
589
682
 
590
- if self.client.is_rest:
683
+ if self.client.is_rest and not self._issued_response:
591
684
  self._resp_builder.set_result(builder)
592
685
  self._issued_response = True
593
686
  if not isinstance(builder, hikari.api.InteractionModalBuilder):
@@ -596,25 +689,38 @@ class Context(t.Generic[ClientT]):
596
689
  return
597
690
 
598
691
  if isinstance(builder, hikari.api.InteractionMessageBuilder):
599
- await self.interaction.create_initial_response(
600
- response_type=hikari.ResponseType.MESSAGE_CREATE,
601
- content=builder.content,
602
- tts=builder.is_tts,
603
- components=builder.components,
604
- attachments=builder.attachments,
605
- embeds=builder.embeds,
606
- mentions_everyone=builder.mentions_everyone,
607
- user_mentions=builder.user_mentions,
608
- role_mentions=builder.role_mentions,
609
- flags=builder.flags,
610
- )
692
+ if not self._issued_response:
693
+ await self.interaction.create_initial_response(
694
+ response_type=hikari.ResponseType.MESSAGE_CREATE,
695
+ content=builder.content,
696
+ tts=builder.is_tts,
697
+ components=builder.components,
698
+ attachments=builder.attachments,
699
+ embeds=builder.embeds,
700
+ mentions_everyone=builder.mentions_everyone,
701
+ user_mentions=builder.user_mentions,
702
+ role_mentions=builder.role_mentions,
703
+ flags=builder.flags,
704
+ )
705
+ else:
706
+ await self.interaction.execute(
707
+ content=builder.content,
708
+ tts=builder.is_tts,
709
+ components=builder.components or hikari.UNDEFINED,
710
+ attachments=builder.attachments or hikari.UNDEFINED,
711
+ embeds=builder.embeds or hikari.UNDEFINED,
712
+ mentions_everyone=builder.mentions_everyone,
713
+ user_mentions=builder.user_mentions,
714
+ role_mentions=builder.role_mentions,
715
+ flags=builder.flags,
716
+ )
611
717
  elif isinstance(builder, hikari.api.InteractionDeferredBuilder):
612
718
  await self.interaction.create_initial_response(
613
719
  response_type=hikari.ResponseType.DEFERRED_MESSAGE_CREATE, flags=builder.flags
614
720
  )
615
721
  else:
616
722
  await self.interaction.create_modal_response(
617
- title=builder.title, custom_id=builder.custom_id, components=builder.components
723
+ title=builder.title, custom_id=builder.custom_id, components=builder.components or hikari.UNDEFINED
618
724
  )
619
725
 
620
726
  self._issued_response = True
@@ -660,43 +766,48 @@ class Context(t.Generic[ClientT]):
660
766
 
661
767
  async def edit_initial_response(
662
768
  self,
663
- content: hikari.UndefinedNoneOr[t.Any] = hikari.UNDEFINED,
769
+ content: t.Any | None | hikari.UndefinedType = hikari.UNDEFINED,
664
770
  *,
665
- component: hikari.UndefinedNoneOr[hikari.api.ComponentBuilder] = hikari.UNDEFINED,
666
- components: hikari.UndefinedNoneOr[t.Sequence[hikari.api.ComponentBuilder]] = hikari.UNDEFINED,
667
- attachment: hikari.UndefinedNoneOr[hikari.Resourceish] = hikari.UNDEFINED,
668
- attachments: hikari.UndefinedNoneOr[t.Sequence[hikari.Resourceish]] = hikari.UNDEFINED,
669
- embed: hikari.UndefinedNoneOr[hikari.Embed] = hikari.UNDEFINED,
670
- embeds: hikari.UndefinedNoneOr[t.Sequence[hikari.Embed]] = hikari.UNDEFINED,
671
- mentions_everyone: hikari.UndefinedOr[bool] = hikari.UNDEFINED,
672
- user_mentions: hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialUser] | bool] = hikari.UNDEFINED,
673
- role_mentions: hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialRole] | bool] = hikari.UNDEFINED,
771
+ attachment: hikari.Resourceish | None | hikari.UndefinedType = hikari.UNDEFINED,
772
+ attachments: t.Sequence[hikari.Resourceish] | None | hikari.UndefinedType = hikari.UNDEFINED,
773
+ component: hikari.api.ComponentBuilder | None | hikari.UndefinedType = hikari.UNDEFINED,
774
+ components: t.Sequence[hikari.api.ComponentBuilder] | None | hikari.UndefinedType = hikari.UNDEFINED,
775
+ embed: hikari.Embed | None | hikari.UndefinedType = hikari.UNDEFINED,
776
+ embeds: t.Sequence[hikari.Embed] | None | hikari.UndefinedType = hikari.UNDEFINED,
777
+ mentions_everyone: bool | hikari.UndefinedType = hikari.UNDEFINED,
778
+ user_mentions: t.Sequence[hikari.Snowflakeish | hikari.PartialUser]
779
+ | bool
780
+ | hikari.UndefinedType = hikari.UNDEFINED,
781
+ role_mentions: t.Sequence[hikari.Snowflake | hikari.PartialRole]
782
+ | bool
783
+ | hikari.UndefinedType = hikari.UNDEFINED,
674
784
  ) -> InteractionResponse:
675
- """A short-hand method to edit the initial response belonging to this interaction. If you want to edit a followup,
676
- you should use the [`edit()`][arc.context.base.InteractionResponse.edit] method of the returned
677
- [`InteractionResponse`][arc.context.base.InteractionResponse] response object instead.
785
+ """A short-hand method to edit the initial response belonging to this interaction.
786
+
787
+ If you want to edit a followup, you should use the [`edit()`][arc.context.base.InteractionResponse.edit]
788
+ method of the returned [`InteractionResponse`][arc.context.base.InteractionResponse] response object instead.
678
789
 
679
790
  Parameters
680
791
  ----------
681
- content : hikari.UndefinedOr[Any], optional
792
+ content : t.Any | None | hikari.UndefinedType
682
793
  The content of the message. Anything passed here will be cast to str.
683
- attachment : hikari.UndefinedOr[hikari.Resourceish], optional
794
+ attachment : hikari.Resourceish | None | hikari.UndefinedType
684
795
  An attachment to add to this message.
685
- attachments : hikari.UndefinedOr[t.Sequence[hikari.Resourceish]], optional
796
+ attachments : t.Sequence[hikari.Resourceish] | None | hikari.UndefinedType
686
797
  A sequence of attachments to add to this message.
687
- component : hikari.UndefinedOr[hikari.api.special_endpoints.ComponentBuilder], optional
798
+ component : hikari.api.ComponentBuilder | None | hikari.UndefinedType
688
799
  A component to add to this message.
689
- components : hikari.UndefinedOr[t.Sequence[hikari.api.special_endpoints.ComponentBuilder]], optional
800
+ components : t.Sequence[hikari.api.ComponentBuilder] | None | hikari.UndefinedType
690
801
  A sequence of components to add to this message.
691
- embed : hikari.UndefinedOr[hikari.Embed], optional
802
+ embed : hikari.Embed | None | hikari.UndefinedType
692
803
  An embed to add to this message.
693
- embeds : hikari.UndefinedOr[Sequence[hikari.Embed]], optional
804
+ embeds : t.Sequence[hikari.Embed] | None | hikari.UndefinedType
694
805
  A sequence of embeds to add to this message.
695
- mentions_everyone : hikari.UndefinedOr[bool], optional
806
+ mentions_everyone : bool | hikari.UndefinedType
696
807
  If True, mentioning @everyone will be allowed.
697
- user_mentions : hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialUser] | bool], optional
808
+ user_mentions : t.Sequence[hikari.Snowflakeish | hikari.PartialUser] | bool | hikari.UndefinedType
698
809
  The set of allowed user mentions in this message. Set to True to allow all.
699
- role_mentions : hikari.UndefinedOr[hikari.SnowflakeishSequence[hikari.PartialRole] | bool], optional
810
+ role_mentions : t.Sequence[hikari.Snowflakeish | hikari.PartialRole] | bool | hikari.UndefinedType
700
811
  The set of allowed role mentions in this message. Set to True to allow all.
701
812
 
702
813
  Returns
@@ -728,14 +839,14 @@ class Context(t.Generic[ClientT]):
728
839
  else:
729
840
  raise NoResponseIssuedError("This interaction was not yet issued an initial response.")
730
841
 
731
- async def defer(self, flags: hikari.UndefinedOr[int | hikari.MessageFlag] = hikari.UNDEFINED) -> None:
842
+ async def defer(self, flags: int | hikari.MessageFlag | hikari.UndefinedType = hikari.UNDEFINED) -> None:
732
843
  """Short-hand method to defer an interaction response. Raises ResponseAlreadyIssuedError
733
844
  if the interaction was already responded to.
734
845
 
735
846
  Parameters
736
847
  ----------
737
- flags : hikari.UndefinedOr[int | hikari.MessageFlag], optional
738
- Message flags that should be included with this defer request, by default None
848
+ flags : int | hikari.MessageFlag | hikari.UndefinedType
849
+ Message flags that should be included with this defer request
739
850
 
740
851
  Raises
741
852
  ------