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/__init__.py CHANGED
@@ -11,10 +11,20 @@ https://arc.hypergonial.com
11
11
  from alluka import Client as Injector
12
12
  from alluka import inject
13
13
 
14
- from arc import abc, command
14
+ from arc import abc, command, utils
15
15
 
16
- from .abc import HookResult, Option, with_hook, with_post_hook
17
- from .client import Client, GatewayClient, GatewayContext, GatewayPlugin, RESTClient, RESTContext, RESTPlugin
16
+ from .abc import HookResult, Option, OptionType, with_hook, with_post_hook
17
+ from .client import (
18
+ Client,
19
+ GatewayClient,
20
+ GatewayClientBase,
21
+ GatewayContext,
22
+ GatewayPlugin,
23
+ RESTClient,
24
+ RESTClientBase,
25
+ RESTContext,
26
+ RESTPlugin,
27
+ )
18
28
  from .command import (
19
29
  AttachmentParams,
20
30
  BoolParams,
@@ -37,7 +47,18 @@ from .command import (
37
47
  user_command,
38
48
  )
39
49
  from .context import AutocompleteData, AutodeferMode, Context, InteractionResponse
40
- from .errors import ArcError, AutocompleteError, CommandInvokeError
50
+ from .errors import (
51
+ ArcError,
52
+ AutocompleteError,
53
+ CommandInvokeError,
54
+ CommandPublishFailedError,
55
+ DMOnlyError,
56
+ GuildCommandPublishFailedError,
57
+ GuildOnlyError,
58
+ InvokerMissingPermissionsError,
59
+ NotOwnerError,
60
+ UnderCooldownError,
61
+ )
41
62
  from .events import ArcEvent, CommandErrorEvent
42
63
  from .extension import loader, unloader
43
64
  from .internal.about import __author__, __author_email__, __license__, __maintainer__, __url__, __version__
@@ -50,7 +71,19 @@ from .locale import (
50
71
  OptionLocaleRequest,
51
72
  )
52
73
  from .plugin import GatewayPluginBase, PluginBase, RESTPluginBase
53
- from .utils import bot_has_permissions, dm_only, guild_only, has_permissions, owner_only
74
+ from .utils import (
75
+ bot_has_permissions,
76
+ channel_limiter,
77
+ custom_limiter,
78
+ dm_only,
79
+ global_limiter,
80
+ guild_limiter,
81
+ guild_only,
82
+ has_permissions,
83
+ member_limiter,
84
+ owner_only,
85
+ user_limiter,
86
+ )
54
87
 
55
88
  __all__ = (
56
89
  "__version__",
@@ -86,11 +119,21 @@ __all__ = (
86
119
  "slash_command",
87
120
  "slash_subcommand",
88
121
  "Client",
122
+ "GatewayClientBase",
123
+ "RESTClientBase",
89
124
  "GatewayClient",
90
125
  "RESTClient",
126
+ "OptionType",
91
127
  "ArcError",
92
128
  "AutocompleteError",
129
+ "UnderCooldownError",
130
+ "InvokerMissingPermissionsError",
131
+ "GuildOnlyError",
132
+ "NotOwnerError",
133
+ "DMOnlyError",
93
134
  "CommandInvokeError",
135
+ "GuildCommandPublishFailedError",
136
+ "CommandPublishFailedError",
94
137
  "PluginBase",
95
138
  "RESTPluginBase",
96
139
  "GatewayPluginBase",
@@ -111,6 +154,7 @@ __all__ = (
111
154
  "CommandLocaleRequest",
112
155
  "OptionLocaleRequest",
113
156
  "abc",
157
+ "utils",
114
158
  "command",
115
159
  "with_hook",
116
160
  "with_post_hook",
@@ -119,6 +163,12 @@ __all__ = (
119
163
  "guild_only",
120
164
  "has_permissions",
121
165
  "owner_only",
166
+ "global_limiter",
167
+ "guild_limiter",
168
+ "channel_limiter",
169
+ "user_limiter",
170
+ "member_limiter",
171
+ "custom_limiter",
122
172
  )
123
173
 
124
174
  # MIT License
arc/abc/__init__.py CHANGED
@@ -2,7 +2,15 @@ from .client import Client
2
2
  from .command import CallableCommandBase, CallableCommandProto, CommandBase, CommandProto
3
3
  from .error_handler import HasErrorHandler
4
4
  from .hookable import Hookable, HookResult, with_hook, with_post_hook
5
- from .option import CommandOptionBase, Option, OptionBase, OptionParams, OptionWithChoices, OptionWithChoicesParams
5
+ from .option import (
6
+ CommandOptionBase,
7
+ Option,
8
+ OptionBase,
9
+ OptionParams,
10
+ OptionType,
11
+ OptionWithChoices,
12
+ OptionWithChoicesParams,
13
+ )
6
14
  from .plugin import PluginBase
7
15
 
8
16
  __all__ = (
@@ -13,6 +21,7 @@ __all__ = (
13
21
  "CallableCommandBase",
14
22
  "Option",
15
23
  "OptionBase",
24
+ "OptionType",
16
25
  "CommandOptionBase",
17
26
  "OptionParams",
18
27
  "OptionWithChoices",
@@ -24,3 +33,25 @@ __all__ = (
24
33
  "with_hook",
25
34
  "with_post_hook",
26
35
  )
36
+
37
+ # MIT License
38
+ #
39
+ # Copyright (c) 2023-present hypergonial
40
+ #
41
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
42
+ # of this software and associated documentation files (the "Software"), to deal
43
+ # in the Software without restriction, including without limitation the rights
44
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45
+ # copies of the Software, and to permit persons to whom the Software is
46
+ # furnished to do so, subject to the following conditions:
47
+ #
48
+ # The above copyright notice and this permission notice shall be included in all
49
+ # copies or substantial portions of the Software.
50
+ #
51
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
54
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
57
+ # SOFTWARE.
arc/abc/client.py CHANGED
@@ -15,6 +15,7 @@ from contextlib import suppress
15
15
  import alluka
16
16
  import hikari
17
17
 
18
+ from arc.abc.command import _CommandSettings
18
19
  from arc.abc.plugin import PluginBase
19
20
  from arc.command.message import MessageCommand
20
21
  from arc.command.slash import SlashCommand, SlashGroup, SlashSubCommand, SlashSubGroup
@@ -53,16 +54,28 @@ logger = logging.getLogger(__name__)
53
54
 
54
55
  class Client(t.Generic[AppT], abc.ABC):
55
56
  """The abstract base class for an `arc` client.
56
- See [`GatewayClient`][arc.client.GatewayClient] and [`RESTClient`][arc.client.RESTClient] for implementations.
57
+ See [`GatewayClientBase`][arc.client.GatewayClientBase] and [`RESTClientBase`][arc.client.RESTClientBase] for implementations.
57
58
 
58
59
  Parameters
59
60
  ----------
60
61
  app : AppT
61
62
  The application this client is for.
62
- default_enabled_guilds : t.Sequence[hikari.Snowflake] | None, optional
63
- The guilds that slash commands will be registered in by default, by default None
64
- autosync : bool, optional
65
- Whether to automatically sync commands on startup, by default True
63
+ default_enabled_guilds : t.Sequence[hikari.Snowflake] | None
64
+ The guilds that slash commands will be registered in by default
65
+ autosync : bool
66
+ Whether to automatically sync commands on startup
67
+ autodefer : bool | AutodeferMode
68
+ Whether to automatically defer commands that take longer than 2 seconds to respond
69
+ This applies to all commands, and can be overridden on a per-command basis.
70
+ default_permissions : hikari.Permissions | hikari.UndefinedType
71
+ The default permissions for commands
72
+ This applies to all commands, and can be overridden on a per-command basis.
73
+ is_nsfw : bool
74
+ Whether to mark commands as NSFW
75
+ This applies to all commands, and can be overridden on a per-command basis.
76
+ is_dm_enabled : bool
77
+ Whether to enable commands in DMs
78
+ This applies to all commands, and can be overridden on a per-command basis.
66
79
  """
67
80
 
68
81
  __slots__: t.Sequence[str] = (
@@ -86,20 +99,36 @@ class Client(t.Generic[AppT], abc.ABC):
86
99
  "_command_locale_provider",
87
100
  "_option_locale_provider",
88
101
  "_custom_locale_provider",
102
+ "_cmd_settings",
89
103
  )
90
104
 
91
105
  def __init__(
92
106
  self,
93
107
  app: AppT,
94
108
  *,
95
- default_enabled_guilds: t.Sequence[hikari.Snowflake] | None = None,
109
+ default_enabled_guilds: t.Sequence[hikari.Snowflakeish | hikari.PartialGuild]
110
+ | hikari.UndefinedType = hikari.UNDEFINED,
96
111
  autosync: bool = True,
112
+ autodefer: bool | AutodeferMode = True,
113
+ default_permissions: hikari.Permissions | hikari.UndefinedType = hikari.UNDEFINED,
114
+ is_nsfw: bool = False,
115
+ is_dm_enabled: bool = True,
97
116
  provided_locales: t.Sequence[hikari.Locale] | None = None,
98
117
  ) -> None:
99
118
  self._app = app
100
- self._default_enabled_guilds = default_enabled_guilds
119
+ self._default_enabled_guilds = (
120
+ tuple(hikari.Snowflake(i) for i in default_enabled_guilds)
121
+ if default_enabled_guilds is not hikari.UNDEFINED
122
+ else hikari.UNDEFINED
123
+ )
101
124
  self._autosync = autosync
102
125
  self._provided_locales: t.Sequence[hikari.Locale] | None = provided_locales
126
+ self._cmd_settings = _CommandSettings(
127
+ autodefer=AutodeferMode(autodefer),
128
+ default_permissions=default_permissions,
129
+ is_nsfw=is_nsfw,
130
+ is_dm_enabled=is_dm_enabled,
131
+ )
103
132
 
104
133
  self._application: hikari.Application | None = None
105
134
  self._slash_commands: dict[str, SlashCommandLike[te.Self]] = {}
@@ -127,6 +156,20 @@ class Client(t.Generic[AppT], abc.ABC):
127
156
  will return interaction response builders to be sent back to Discord, otherwise they will return None.
128
157
  """
129
158
 
159
+ @property
160
+ def _commands(self) -> t.Mapping[hikari.CommandType, t.Mapping[str, CommandBase[te.Self, t.Any]]]:
161
+ """All top-level commands added to this client, categorized by command type.
162
+
163
+ !!! note
164
+ This does not include subcommands & subgroups due to implementation details, therefore
165
+ you should use [`Client.walk_commands()`][arc.abc.client.Client.walk_commands] instead.
166
+ """
167
+ return {
168
+ hikari.CommandType.SLASH: self._slash_commands,
169
+ hikari.CommandType.MESSAGE: self._message_commands,
170
+ hikari.CommandType.USER: self._user_commands,
171
+ }
172
+
130
173
  @property
131
174
  def app(self) -> AppT:
132
175
  """The application this client is for."""
@@ -148,34 +191,10 @@ class Client(t.Generic[AppT], abc.ABC):
148
191
  return self._injector
149
192
 
150
193
  @property
151
- def default_enabled_guilds(self) -> t.Sequence[hikari.Snowflake] | None:
194
+ def default_enabled_guilds(self) -> t.Sequence[hikari.Snowflake] | hikari.UndefinedType:
152
195
  """The guilds that slash commands will be registered in by default."""
153
196
  return self._default_enabled_guilds
154
197
 
155
- @property
156
- def commands(self) -> t.Mapping[hikari.CommandType, t.Mapping[str, CommandBase[te.Self, t.Any]]]:
157
- """All commands added to this client, categorized by command type."""
158
- return {
159
- hikari.CommandType.SLASH: self.slash_commands,
160
- hikari.CommandType.MESSAGE: self._message_commands,
161
- hikari.CommandType.USER: self._user_commands,
162
- }
163
-
164
- @property
165
- def slash_commands(self) -> t.Mapping[str, SlashCommandLike[te.Self]]:
166
- """The slash commands added to this client. This only includes top-level commands and groups."""
167
- return self._slash_commands
168
-
169
- @property
170
- def message_commands(self) -> t.Mapping[str, MessageCommand[te.Self]]:
171
- """The message commands added to this client."""
172
- return self._message_commands
173
-
174
- @property
175
- def user_commands(self) -> t.Mapping[str, UserCommand[te.Self]]:
176
- """The user commands added to this client."""
177
- return self._user_commands
178
-
179
198
  @property
180
199
  def plugins(self) -> t.Mapping[str, PluginBase[te.Self]]:
181
200
  """The plugins added to this client."""
@@ -289,11 +308,11 @@ class Client(t.Generic[AppT], abc.ABC):
289
308
 
290
309
  match interaction.command_type:
291
310
  case hikari.CommandType.SLASH:
292
- command = self.slash_commands.get(interaction.command_name)
311
+ command = self._slash_commands.get(interaction.command_name)
293
312
  case hikari.CommandType.MESSAGE:
294
- command = self.message_commands.get(interaction.command_name)
313
+ command = self._message_commands.get(interaction.command_name)
295
314
  case hikari.CommandType.USER:
296
- command = self.user_commands.get(interaction.command_name)
315
+ command = self._user_commands.get(interaction.command_name)
297
316
  case _:
298
317
  pass
299
318
 
@@ -343,7 +362,7 @@ class Client(t.Generic[AppT], abc.ABC):
343
362
  hikari.api.InteractionAutocompleteBuilder | None
344
363
  The autocomplete builder to send back to Discord, if using a REST client.
345
364
  """
346
- command = self.slash_commands.get(interaction.command_name)
365
+ command = self._slash_commands.get(interaction.command_name)
347
366
 
348
367
  if command is None:
349
368
  logger.warning(f"Received autocomplete interaction for unknown command '{interaction.command_name}'.")
@@ -351,6 +370,98 @@ class Client(t.Generic[AppT], abc.ABC):
351
370
 
352
371
  return await command._on_autocomplete(interaction)
353
372
 
373
+ @t.overload
374
+ def walk_commands(
375
+ self, command_type: t.Literal[hikari.CommandType.USER], *, callable_only: bool = False
376
+ ) -> t.Iterator[UserCommand[te.Self]]:
377
+ ...
378
+
379
+ @t.overload
380
+ def walk_commands(
381
+ self, command_type: t.Literal[hikari.CommandType.MESSAGE], *, callable_only: bool = False
382
+ ) -> t.Iterator[MessageCommand[te.Self]]:
383
+ ...
384
+
385
+ @t.overload
386
+ def walk_commands(
387
+ self, command_type: t.Literal[hikari.CommandType.SLASH], *, callable_only: t.Literal[False] = False
388
+ ) -> t.Iterator[SlashCommand[te.Self] | SlashSubCommand[te.Self] | SlashGroup[te.Self] | SlashSubGroup[te.Self]]:
389
+ ...
390
+
391
+ @t.overload
392
+ def walk_commands(
393
+ self, command_type: t.Literal[hikari.CommandType.SLASH], *, callable_only: t.Literal[True] = True
394
+ ) -> t.Iterator[SlashCommand[te.Self] | SlashSubCommand[te.Self]]:
395
+ ...
396
+
397
+ def walk_commands( # noqa: C901
398
+ self, command_type: hikari.CommandType, *, callable_only: bool = False
399
+ ) -> t.Iterator[t.Any]:
400
+ """Iterate over all commands of a certain type added to this plugin.
401
+
402
+ Parameters
403
+ ----------
404
+ command_type : hikari.CommandType
405
+ The type of commands to return.
406
+ callable_only : bool
407
+ Whether to only return commands that are directly callable.
408
+ If True, command groups and subgroups will be skipped.
409
+ This is only applicable to slash commands.
410
+
411
+ Yields
412
+ ------
413
+ CommandT[te.Self]
414
+ The next command that matches the given criteria.
415
+
416
+ Usage
417
+ -----
418
+ ```py
419
+ for cmd in plugin.walk_commands(hikari.CommandType.SLASH):
420
+ print(cmd.name)
421
+ ```
422
+
423
+ !!! tip
424
+ To iterate over all types of commands, you may use [`itertools.chain()`][itertools.chain]:
425
+
426
+ ```py
427
+ import itertools
428
+
429
+ for cmd in itertools.chain(
430
+ plugin.walk_commands(hikari.CommandType.SLASH),
431
+ plugin.walk_commands(hikari.CommandType.MESSAGE),
432
+ plugin.walk_commands(hikari.CommandType.USER),
433
+ ):
434
+ print(cmd.name)
435
+ ```
436
+ """
437
+ if hikari.CommandType.SLASH is command_type:
438
+ for command in self._slash_commands.values():
439
+ if isinstance(command, SlashCommand):
440
+ yield command
441
+ continue
442
+
443
+ if not callable_only:
444
+ yield command
445
+
446
+ for sub in command.children.values():
447
+ if isinstance(sub, SlashSubCommand):
448
+ yield sub
449
+ continue
450
+
451
+ if not callable_only:
452
+ yield sub
453
+
454
+ for subsub in sub.children.values():
455
+ yield subsub
456
+
457
+ elif hikari.CommandType.MESSAGE is command_type:
458
+ for command in self._message_commands.values():
459
+ yield command
460
+
461
+ elif hikari.CommandType.USER is command_type:
462
+ for command in self._user_commands.values():
463
+ yield command
464
+
354
465
  @t.overload
355
466
  def include(self) -> t.Callable[[CommandBase[te.Self, BuilderT]], CommandBase[te.Self, BuilderT]]:
356
467
  ...
@@ -394,7 +505,7 @@ class Client(t.Generic[AppT], abc.ABC):
394
505
  f"\nYou should use '{type(self).__name__}.add_plugin()' to add the entire plugin to the client."
395
506
  )
396
507
 
397
- if existing := self.commands[command.command_type].get(command.name):
508
+ if existing := self._commands[command.command_type].get(command.name):
398
509
  logger.warning(
399
510
  f"Shadowing already registered command '{command.name}'. Did you define multiple commands with the same name?"
400
511
  )
@@ -413,12 +524,12 @@ class Client(t.Generic[AppT], abc.ABC):
413
524
  name: str,
414
525
  description: str = "No description provided.",
415
526
  *,
416
- guilds: hikari.UndefinedOr[t.Sequence[hikari.Snowflake]] = hikari.UNDEFINED,
417
- autodefer: bool | AutodeferMode = True,
418
- is_dm_enabled: bool = True,
419
- default_permissions: hikari.UndefinedOr[hikari.Permissions] = hikari.UNDEFINED,
420
- name_localizations: dict[hikari.Locale, str] | None = None,
421
- description_localizations: dict[hikari.Locale, str] | None = None,
527
+ guilds: t.Sequence[hikari.Snowflakeish | hikari.PartialGuild] | hikari.UndefinedType = hikari.UNDEFINED,
528
+ autodefer: bool | AutodeferMode | hikari.UndefinedType = hikari.UNDEFINED,
529
+ is_dm_enabled: bool | hikari.UndefinedType = hikari.UNDEFINED,
530
+ default_permissions: hikari.Permissions | hikari.UndefinedType = hikari.UNDEFINED,
531
+ name_localizations: t.Mapping[hikari.Locale, str] | None = None,
532
+ description_localizations: t.Mapping[hikari.Locale, str] | None = None,
422
533
  is_nsfw: bool = False,
423
534
  ) -> SlashGroup[te.Self]:
424
535
  """Add a new slash command group to this client.
@@ -429,27 +540,30 @@ class Client(t.Generic[AppT], abc.ABC):
429
540
  The name of the slash command group.
430
541
  description : str
431
542
  The description of the slash command group.
432
- guilds : hikari.UndefinedOr[t.Sequence[hikari.Snowflake]], optional
433
- The guilds to register the slash command group in, by default hikari.UNDEFINED
434
- autodefer : bool | AutodeferMode, optional
543
+ guilds : t.Sequence[hikari.Snowflake] | hikari.UndefinedType
544
+ The guilds to register the slash command group in
545
+ autodefer : bool | AutodeferMode
435
546
  If True, all commands in this group will automatically defer if it is taking longer than 2 seconds to respond.
436
547
  This can be overridden on a per-subcommand basis.
437
- is_dm_enabled : bool, optional
438
- Whether the slash command group is enabled in DMs, by default True
439
- default_permissions : hikari.UndefinedOr[hikari.Permissions], optional
440
- The default permissions for the slash command group, by default hikari.UNDEFINED
441
- name_localizations : dict[hikari.Locale, str], optional
442
- The name of the slash command group in different locales, by default None
443
- description_localizations : dict[hikari.Locale, str], optional
444
- The description of the slash command group in different locales, by default None
445
- is_nsfw : bool, optional
446
- Whether the slash command group is only usable in NSFW channels, by default False
548
+ is_dm_enabled : bool
549
+ Whether the slash command group is enabled in DMs
550
+ default_permissions : hikari.Permissions | hikari.UndefinedType
551
+ The default permissions for the slash command group
552
+ name_localizations : dict[hikari.Locale, str]
553
+ The name of the slash command group in different locales
554
+ description_localizations : dict[hikari.Locale, str]
555
+ The description of the slash command group in different locales
556
+ is_nsfw : bool
557
+ Whether the slash command group is only usable in NSFW channels
447
558
 
448
559
  Returns
449
560
  -------
450
561
  SlashGroup[te.Self]
451
562
  The slash command group that was created.
452
563
 
564
+ !!! note
565
+ Parameters left as `hikari.UNDEFINED` will be inherited from the parent client.
566
+
453
567
  Usage
454
568
  -----
455
569
  ```py
@@ -461,14 +575,13 @@ class Client(t.Generic[AppT], abc.ABC):
461
575
  await ctx.respond("Hello!")
462
576
  ```
463
577
  """
464
- children: dict[str, SlashSubCommand[te.Self] | SlashSubGroup[te.Self]] = {}
578
+ guild_ids = tuple(hikari.Snowflake(i) for i in guilds) if guilds is not hikari.UNDEFINED else hikari.UNDEFINED
465
579
 
466
- group = SlashGroup(
580
+ group: SlashGroup[te.Self] = SlashGroup(
467
581
  name=name,
468
582
  description=description,
469
- children=children,
470
- guilds=guilds,
471
- autodefer=AutodeferMode(autodefer),
583
+ guilds=guild_ids,
584
+ autodefer=AutodeferMode(autodefer) if isinstance(autodefer, bool) else autodefer,
472
585
  is_dm_enabled=is_dm_enabled,
473
586
  default_permissions=default_permissions,
474
587
  name_localizations=name_localizations or {},
@@ -632,6 +745,10 @@ class Client(t.Generic[AppT], abc.ABC):
632
745
  await ctx.respond(f"❌ Something went wrong: {exception}")
633
746
  ```
634
747
 
748
+ !!! warning
749
+ Errors that cannot be handled by the error handler should be re-raised.
750
+ Otherwise tracebacks will not be printed to stderr.
751
+
635
752
  Or, as a function:
636
753
 
637
754
  ```py
@@ -931,8 +1048,8 @@ class Client(t.Generic[AppT], abc.ABC):
931
1048
  ----------
932
1049
  dir_path : str
933
1050
  The path to the directory to load extensions from.
934
- recursive : bool, optional
935
- Whether to load extensions from subdirectories, by default False
1051
+ recursive : bool
1052
+ Whether to load extensions from subdirectories
936
1053
 
937
1054
  Returns
938
1055
  -------
@@ -1074,7 +1191,7 @@ class Client(t.Generic[AppT], abc.ABC):
1074
1191
  self._injector.set_type_dependency(type_, instance)
1075
1192
  return self
1076
1193
 
1077
- def get_type_dependency(self, type_: t.Type[T]) -> hikari.UndefinedOr[T]:
1194
+ def get_type_dependency(self, type_: t.Type[T]) -> T | hikari.UndefinedType:
1078
1195
  """Get a type dependency for this client.
1079
1196
 
1080
1197
  Parameters
@@ -1084,7 +1201,7 @@ class Client(t.Generic[AppT], abc.ABC):
1084
1201
 
1085
1202
  Returns
1086
1203
  -------
1087
- hikari.UndefinedOr[T]
1204
+ T | hikari.UndefinedType
1088
1205
  The instance of the dependency, if it exists.
1089
1206
  """
1090
1207
  return self._injector.get_type_dependency(type_, default=hikari.UNDEFINED)
@@ -1170,8 +1287,8 @@ class Client(t.Generic[AppT], abc.ABC):
1170
1287
 
1171
1288
  Parameters
1172
1289
  ----------
1173
- guild : hikari.SnowflakeishOr[hikari.PartialGuild] | None, optional
1174
- The guild to purge commands from, by default None
1290
+ guild : hikari.SnowflakeishOr[hikari.PartialGuild] | None
1291
+ The guild to purge commands from
1175
1292
  If a `guild` is not provided, this will purge global commands.
1176
1293
 
1177
1294
  !!! warning
@@ -1191,3 +1308,26 @@ class Client(t.Generic[AppT], abc.ABC):
1191
1308
  await self.rest.set_application_commands(self.application, [], guild_id)
1192
1309
  else:
1193
1310
  await self.rest.set_application_commands(self.application, [])
1311
+
1312
+
1313
+ # MIT License
1314
+ #
1315
+ # Copyright (c) 2023-present hypergonial
1316
+ #
1317
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
1318
+ # of this software and associated documentation files (the "Software"), to deal
1319
+ # in the Software without restriction, including without limitation the rights
1320
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1321
+ # copies of the Software, and to permit persons to whom the Software is
1322
+ # furnished to do so, subject to the following conditions:
1323
+ #
1324
+ # The above copyright notice and this permission notice shall be included in all
1325
+ # copies or substantial portions of the Software.
1326
+ #
1327
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1328
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1329
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1330
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1331
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1332
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1333
+ # SOFTWARE.