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/abc/option.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import abc
4
+ import enum
4
5
  import typing as t
5
6
  from typing import Any
6
7
 
@@ -16,7 +17,15 @@ if t.TYPE_CHECKING:
16
17
  from arc.abc.client import Client
17
18
  from arc.abc.command import CommandProto
18
19
 
19
- __all__ = ("Option", "OptionParams", "OptionWithChoices", "OptionWithChoicesParams", "OptionBase", "CommandOptionBase")
20
+ __all__ = (
21
+ "Option",
22
+ "OptionParams",
23
+ "OptionWithChoices",
24
+ "OptionWithChoicesParams",
25
+ "OptionBase",
26
+ "CommandOptionBase",
27
+ "OptionType",
28
+ )
20
29
 
21
30
  T = t.TypeVar("T")
22
31
 
@@ -37,6 +46,65 @@ arc.Option[int, arc.IntParams(...)]
37
46
  """
38
47
 
39
48
 
49
+ class OptionType(enum.IntEnum):
50
+ """The type of a command option.
51
+
52
+ This is practically identical to `hikari.OptionType` at the moment.
53
+ It may however be used in the future to define custom option types.
54
+ """
55
+
56
+ SUB_COMMAND = 1
57
+ """Denotes a command option where the value will be a sub command."""
58
+
59
+ SUB_COMMAND_GROUP = 2
60
+ """Denotes a command option where the value will be a sub command group."""
61
+
62
+ STRING = 3
63
+ """Denotes a command option where the value will be a string."""
64
+
65
+ INTEGER = 4
66
+ """Denotes a command option where the value will be a int.
67
+
68
+ This is range limited between -2^53 and 2^53.
69
+ """
70
+
71
+ BOOLEAN = 5
72
+ """Denotes a command option where the value will be a bool."""
73
+
74
+ USER = 6
75
+ """Denotes a command option where the value will be resolved to a user."""
76
+
77
+ CHANNEL = 7
78
+ """Denotes a command option where the value will be resolved to a channel."""
79
+
80
+ ROLE = 8
81
+ """Denotes a command option where the value will be resolved to a role."""
82
+
83
+ MENTIONABLE = 9
84
+ """Denotes a command option where the value will be a snowflake ID."""
85
+
86
+ FLOAT = 10
87
+ """Denotes a command option where the value will be a float.
88
+
89
+ This is range limited between -2^53 and 2^53.
90
+ """
91
+
92
+ ATTACHMENT = 11
93
+ """Denotes a command option where the value will be an attachment."""
94
+
95
+ @classmethod
96
+ def from_hikari(cls, option_type: hikari.OptionType) -> OptionType:
97
+ """Convert a hikari.OptionType to an OptionType."""
98
+ return cls(option_type.value)
99
+
100
+ def to_hikari(self) -> hikari.OptionType:
101
+ """Convert an OptionType to a hikari.OptionType."""
102
+ # TODO: Map custom option types to their respective hikari.OptionType
103
+ return hikari.OptionType(self.value)
104
+
105
+ # TODO: When adding custom convertible option types, add them with an offset of 1000 or so
106
+
107
+
40
108
  class OptionParams(t.Generic[T]):
41
109
  """The base class for all option parameters objects.
42
110
 
@@ -54,9 +122,9 @@ class OptionParams(t.Generic[T]):
54
122
 
55
123
  def __init__(
56
124
  self,
57
- name: str | None = None,
58
125
  description: str = "No description provided.",
59
126
  *,
127
+ name: str | None = None,
60
128
  name_localizations: t.Mapping[hikari.Locale, str] | None = None,
61
129
  description_localizations: t.Mapping[hikari.Locale, str] | None = None,
62
130
  ) -> None:
@@ -110,9 +178,9 @@ class OptionWithChoicesParams(OptionParams[ChoiceT], t.Generic[ChoiceT, ClientT]
110
178
 
111
179
  def __init__(
112
180
  self,
113
- name: str | None = None,
114
181
  description: str = "No description provided.",
115
182
  *,
183
+ name: str | None = None,
116
184
  name_localizations: t.Mapping[hikari.Locale, str] | None = None,
117
185
  description_localizations: t.Mapping[hikari.Locale, str] | None = None,
118
186
  choices: t.Sequence[ChoiceT | hikari.CommandChoice] | t.Mapping[str, ChoiceT] | None = None,
@@ -153,13 +221,13 @@ class OptionBase(abc.ABC, t.Generic[T]):
153
221
 
154
222
  @property
155
223
  @abc.abstractmethod
156
- def option_type(self) -> hikari.OptionType:
224
+ def option_type(self) -> OptionType:
157
225
  """The type of the option. Used to register the command."""
158
226
 
159
227
  def _to_dict(self) -> dict[str, t.Any]:
160
228
  """Convert the option to a dictionary of kwargs that can be passed to hikari.CommandOption."""
161
229
  return {
162
- "type": self.option_type,
230
+ "type": self.option_type.to_hikari(),
163
231
  "name": self.name,
164
232
  "description": self.description,
165
233
  "autocomplete": False,
arc/abc/plugin.py CHANGED
@@ -8,15 +8,16 @@ import typing as t
8
8
 
9
9
  import hikari
10
10
 
11
+ from arc.abc.command import _CommandSettings
11
12
  from arc.abc.error_handler import HasErrorHandler
12
13
  from arc.abc.hookable import Hookable
13
14
  from arc.command import MessageCommand, SlashCommand, SlashGroup, UserCommand
15
+ from arc.command.slash import SlashSubCommand, SlashSubGroup
14
16
  from arc.context import AutodeferMode, Context
15
17
  from arc.internal.types import BuilderT, ClientT, ErrorHandlerCallbackT, HookT, PostHookT, SlashCommandLike
16
18
 
17
19
  if t.TYPE_CHECKING:
18
20
  from arc.abc.command import CommandBase
19
- from arc.command import SlashSubCommand, SlashSubGroup
20
21
 
21
22
  __all__ = ("PluginBase",)
22
23
 
@@ -31,17 +32,52 @@ class PluginBase(HasErrorHandler[ClientT], Hookable[ClientT]):
31
32
  ----------
32
33
  name : str
33
34
  The name of this plugin. This must be unique across all plugins.
35
+ default_enabled_guilds : t.Sequence[hikari.Snowflake] | hikari.UndefinedType
36
+ The default guilds to enable commands in
37
+ autodefer : bool | AutodeferMode
38
+ If True, all commands in this plugin will automatically defer if it is taking longer than 2 seconds to respond.
39
+ This can be overridden on a per-command basis.
40
+ is_dm_enabled : bool | hikari.UndefinedType
41
+ Whether commands in this plugin are enabled in DMs
42
+ This can be overridden on a per-command basis.
43
+ default_permissions : hikari.Permissions | hikari.UndefinedType
44
+ The default permissions for this plugin
45
+ This can be overridden on a per-command basis.
46
+ is_nsfw : bool | hikari.UndefinedType
47
+ Whether this plugin is only usable in NSFW channels
48
+
49
+ !!! note
50
+ Parameters left as `hikari.UNDEFINED` will be inherited from the parent client.
34
51
  """
35
52
 
36
53
  def __init__(
37
- self, name: str, *, default_enabled_guilds: hikari.UndefinedOr[t.Sequence[hikari.Snowflake]] = hikari.UNDEFINED
54
+ self,
55
+ name: str,
56
+ *,
57
+ default_enabled_guilds: t.Sequence[hikari.Snowflakeish | hikari.PartialGuild]
58
+ | hikari.UndefinedType = hikari.UNDEFINED,
59
+ autodefer: bool | AutodeferMode | hikari.UndefinedType = hikari.UNDEFINED,
60
+ is_dm_enabled: bool | hikari.UndefinedType = hikari.UNDEFINED,
61
+ default_permissions: hikari.Permissions | hikari.UndefinedType = hikari.UNDEFINED,
62
+ is_nsfw: bool | hikari.UndefinedType = hikari.UNDEFINED,
38
63
  ) -> None:
39
64
  self._client: ClientT | None = None
40
65
  self._name = name
66
+ self._default_enabled_guilds = (
67
+ tuple(hikari.Snowflake(i) for i in default_enabled_guilds)
68
+ if default_enabled_guilds is not hikari.UNDEFINED
69
+ else hikari.UNDEFINED
70
+ )
71
+ self._cmd_settings = _CommandSettings(
72
+ autodefer=AutodeferMode(autodefer) if isinstance(autodefer, bool) else autodefer,
73
+ is_dm_enabled=is_dm_enabled,
74
+ default_permissions=default_permissions,
75
+ is_nsfw=is_nsfw,
76
+ )
77
+
41
78
  self._slash_commands: dict[str, SlashCommandLike[ClientT]] = {}
42
79
  self._user_commands: dict[str, UserCommand[ClientT]] = {}
43
80
  self._message_commands: dict[str, MessageCommand[ClientT]] = {}
44
- self._default_enabled_guilds = default_enabled_guilds
45
81
  self._error_handler: ErrorHandlerCallbackT[ClientT] | None = None
46
82
  self._hooks: list[HookT[ClientT]] = []
47
83
  self._post_hooks: list[PostHookT[ClientT]] = []
@@ -86,7 +122,7 @@ class PluginBase(HasErrorHandler[ClientT], Hookable[ClientT]):
86
122
  return self._client
87
123
 
88
124
  @property
89
- def default_enabled_guilds(self) -> hikari.UndefinedOr[t.Sequence[hikari.Snowflake]]:
125
+ def default_enabled_guilds(self) -> t.Sequence[hikari.Snowflake] | hikari.UndefinedType:
90
126
  """The default guilds to enable commands in."""
91
127
  return self._default_enabled_guilds
92
128
 
@@ -99,6 +135,10 @@ class PluginBase(HasErrorHandler[ClientT], Hookable[ClientT]):
99
135
  except Exception as exc:
100
136
  await self.client._on_error(ctx, exc)
101
137
 
138
+ def _resolve_settings(self) -> _CommandSettings:
139
+ settings = self._client._cmd_settings if self._client is not None else _CommandSettings.default()
140
+ return settings.apply(self._cmd_settings)
141
+
102
142
  def _resolve_hooks(self) -> list[HookT[ClientT]]:
103
143
  return self._hooks
104
144
 
@@ -183,13 +223,13 @@ class PluginBase(HasErrorHandler[ClientT], Hookable[ClientT]):
183
223
  name: str,
184
224
  description: str = "No description provided.",
185
225
  *,
186
- guilds: hikari.UndefinedOr[t.Sequence[hikari.Snowflake]] = hikari.UNDEFINED,
187
- autodefer: bool | AutodeferMode = True,
188
- is_dm_enabled: bool = True,
189
- default_permissions: hikari.UndefinedOr[hikari.Permissions] = hikari.UNDEFINED,
190
- name_localizations: dict[hikari.Locale, str] | None = None,
191
- description_localizations: dict[hikari.Locale, str] | None = None,
192
- is_nsfw: bool = False,
226
+ guilds: t.Sequence[hikari.Snowflakeish | hikari.PartialGuild] | hikari.UndefinedType = hikari.UNDEFINED,
227
+ autodefer: bool | AutodeferMode | hikari.UndefinedType = hikari.UNDEFINED,
228
+ is_dm_enabled: bool | hikari.UndefinedType = hikari.UNDEFINED,
229
+ is_nsfw: bool | hikari.UndefinedType = hikari.UNDEFINED,
230
+ default_permissions: hikari.Permissions | hikari.UndefinedType = hikari.UNDEFINED,
231
+ name_localizations: t.Mapping[hikari.Locale, str] | None = None,
232
+ description_localizations: t.Mapping[hikari.Locale, str] | None = None,
193
233
  ) -> SlashGroup[ClientT]:
194
234
  """Add a new slash command group to this client.
195
235
 
@@ -199,27 +239,30 @@ class PluginBase(HasErrorHandler[ClientT], Hookable[ClientT]):
199
239
  The name of the slash command group.
200
240
  description : str
201
241
  The description of the slash command group.
202
- guilds : hikari.UndefinedOr[t.Sequence[hikari.Snowflake]], optional
203
- The guilds to register the slash command group in, by default hikari.UNDEFINED
204
- autodefer : bool | AutodeferMode, optional
242
+ guilds : t.Sequence[hikari.Snowflake] | hikari.UndefinedType
243
+ The guilds to register the slash command group in
244
+ autodefer : bool | AutodeferMode
205
245
  If True, all commands in this group will automatically defer if it is taking longer than 2 seconds to respond.
206
246
  This can be overridden on a per-subcommand basis.
207
- is_dm_enabled : bool, optional
208
- Whether the slash command group is enabled in DMs, by default True
209
- default_permissions : hikari.UndefinedOr[hikari.Permissions], optional
210
- The default permissions for the slash command group, by default hikari.UNDEFINED
211
- name_localizations : dict[hikari.Locale, str], optional
212
- The name of the slash command group in different locales, by default None
213
- description_localizations : dict[hikari.Locale, str], optional
214
- The description of the slash command group in different locales, by default None
215
- is_nsfw : bool, optional
216
- Whether the slash command group is only usable in NSFW channels, by default False
247
+ is_dm_enabled : bool
248
+ Whether the slash command group is enabled in DMs
249
+ default_permissions : hikari.Permissions | hikari.UndefinedType
250
+ The default permissions for the slash command group
251
+ name_localizations : dict[hikari.Locale, str]
252
+ The name of the slash command group in different locales
253
+ description_localizations : dict[hikari.Locale, str]
254
+ The description of the slash command group in different locales
255
+ is_nsfw : bool
256
+ Whether the slash command group is only usable in NSFW channels
217
257
 
218
258
  Returns
219
259
  -------
220
260
  SlashGroup[te.Self]
221
261
  The slash command group that was created.
222
262
 
263
+ !!! note
264
+ Parameters left as `hikari.UNDEFINED` will be inherited from the parent plugin or client.
265
+
223
266
  Usage
224
267
  -----
225
268
  ```py
@@ -231,14 +274,13 @@ class PluginBase(HasErrorHandler[ClientT], Hookable[ClientT]):
231
274
  await ctx.respond("Hello!")
232
275
  ```
233
276
  """
234
- children: dict[str, SlashSubCommand[ClientT] | SlashSubGroup[ClientT]] = {}
277
+ guild_ids = tuple(hikari.Snowflake(i) for i in guilds) if guilds is not hikari.UNDEFINED else hikari.UNDEFINED
235
278
 
236
- group = SlashGroup(
279
+ group: SlashGroup[ClientT] = SlashGroup(
237
280
  name=name,
238
281
  description=description,
239
- children=children,
240
- guilds=guilds,
241
- autodefer=AutodeferMode(autodefer),
282
+ guilds=guild_ids,
283
+ autodefer=AutodeferMode(autodefer) if isinstance(autodefer, bool) else autodefer,
242
284
  is_dm_enabled=is_dm_enabled,
243
285
  default_permissions=default_permissions,
244
286
  name_localizations=name_localizations or {},
@@ -326,3 +368,117 @@ class PluginBase(HasErrorHandler[ClientT], Hookable[ClientT]):
326
368
  return decorator(func)
327
369
 
328
370
  return decorator
371
+
372
+ @t.overload
373
+ def walk_commands(
374
+ self, command_type: t.Literal[hikari.CommandType.USER], *, callable_only: bool = False
375
+ ) -> t.Iterator[UserCommand[ClientT]]:
376
+ ...
377
+
378
+ @t.overload
379
+ def walk_commands(
380
+ self, command_type: t.Literal[hikari.CommandType.MESSAGE], *, callable_only: bool = False
381
+ ) -> t.Iterator[MessageCommand[ClientT]]:
382
+ ...
383
+
384
+ @t.overload
385
+ def walk_commands(
386
+ self, command_type: t.Literal[hikari.CommandType.SLASH], *, callable_only: t.Literal[False]
387
+ ) -> t.Iterator[SlashCommand[ClientT] | SlashSubCommand[ClientT] | SlashGroup[ClientT] | SlashSubGroup[ClientT]]:
388
+ ...
389
+
390
+ @t.overload
391
+ def walk_commands(
392
+ self, command_type: t.Literal[hikari.CommandType.SLASH], *, callable_only: t.Literal[True]
393
+ ) -> t.Iterator[SlashCommand[ClientT] | SlashSubCommand[ClientT]]:
394
+ ...
395
+
396
+ def walk_commands( # noqa: C901
397
+ self, command_type: hikari.CommandType, *, callable_only: bool = False
398
+ ) -> t.Iterator[t.Any]:
399
+ """Iterate over all commands of a certain type added to this plugin.
400
+
401
+ Parameters
402
+ ----------
403
+ command_type : hikari.CommandType
404
+ The type of commands to return.
405
+ callable_only : bool
406
+ Whether to only return commands that are directly callable.
407
+ If True, command groups and subgroups will be skipped.
408
+
409
+ Yields
410
+ ------
411
+ CommandT[ClientT]
412
+ The next command that matches the given criteria.
413
+
414
+ Usage
415
+ -----
416
+ ```py
417
+ for cmd in plugin.walk_commands(hikari.CommandType.SLASH):
418
+ print(cmd.name)
419
+ ```
420
+
421
+ !!! tip
422
+ To iterate over all types of commands, you may use [`itertools.chain()`][itertools.chain]:
423
+
424
+ ```py
425
+ import itertools
426
+
427
+ for cmd in itertools.chain(
428
+ plugin.walk_commands(hikari.CommandType.SLASH),
429
+ plugin.walk_commands(hikari.CommandType.MESSAGE),
430
+ plugin.walk_commands(hikari.CommandType.USER),
431
+ ):
432
+ print(cmd.name)
433
+ ```
434
+ """
435
+ if hikari.CommandType.SLASH is command_type:
436
+ for command in self._slash_commands.values():
437
+ if isinstance(command, SlashCommand):
438
+ yield command
439
+ continue
440
+
441
+ if not callable_only:
442
+ yield command
443
+
444
+ for sub in command.children.values():
445
+ if isinstance(sub, SlashSubCommand):
446
+ yield sub
447
+ continue
448
+
449
+ if not callable_only:
450
+ yield sub
451
+
452
+ for subsub in sub.children.values():
453
+ yield subsub
454
+
455
+ elif hikari.CommandType.MESSAGE is command_type:
456
+ for command in self._message_commands.values():
457
+ yield command
458
+
459
+ elif hikari.CommandType.USER is command_type:
460
+ for command in self._user_commands.values():
461
+ yield command
462
+
463
+
464
+ # MIT License
465
+ #
466
+ # Copyright (c) 2023-present hypergonial
467
+ #
468
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
469
+ # of this software and associated documentation files (the "Software"), to deal
470
+ # in the Software without restriction, including without limitation the rights
471
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
472
+ # copies of the Software, and to permit persons to whom the Software is
473
+ # furnished to do so, subject to the following conditions:
474
+ #
475
+ # The above copyright notice and this permission notice shall be included in all
476
+ # copies or substantial portions of the Software.
477
+ #
478
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
479
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
480
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
481
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
482
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
483
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
484
+ # SOFTWARE.
arc/client.py CHANGED
@@ -10,14 +10,26 @@ from arc.context import Context
10
10
  from arc.errors import NoResponseIssuedError
11
11
  from arc.events import CommandErrorEvent
12
12
  from arc.internal.sigparse import parse_event_signature
13
+ from arc.internal.types import GatewayBotT, RESTBotT
13
14
  from arc.plugin import GatewayPluginBase, RESTPluginBase
14
15
 
15
16
  if t.TYPE_CHECKING:
16
17
  import typing_extensions as te
17
18
 
19
+ from arc import AutodeferMode
20
+
18
21
  from .internal.types import EventCallbackT, EventT, ResponseBuilderT
19
22
 
20
- __all__ = ("GatewayClient", "RESTClient")
23
+ __all__ = (
24
+ "GatewayClientBase",
25
+ "RESTClientBase",
26
+ "GatewayClient",
27
+ "RESTClient",
28
+ "GatewayContext",
29
+ "RESTContext",
30
+ "RESTPlugin",
31
+ "GatewayPlugin",
32
+ )
21
33
 
22
34
 
23
35
  T = t.TypeVar("T")
@@ -26,20 +38,33 @@ P = t.ParamSpec("P")
26
38
  logger = logging.getLogger(__name__)
27
39
 
28
40
 
29
- class GatewayClient(Client[hikari.GatewayBotAware]):
30
- """The default implementation for an arc client with `hikari.GatewayBotAware` support.
31
- If you want to use a `hikari.RESTBotAware`, use [`RESTClient`][arc.client.RESTClient] instead.
41
+ class GatewayClientBase(Client[GatewayBotT]):
42
+ """The base class for an arc client with Gateway support.
43
+
44
+ If you want to use a RESTBot, use [`RESTClientBase`][arc.client.RESTClientBase] instead.
32
45
 
33
46
  Parameters
34
47
  ----------
35
48
  app : hikari.GatewayBotAware
36
49
  The application this client is for.
37
- default_enabled_guilds : t.Sequence[hikari.Snowflake] | None, optional
38
- The guilds that slash commands will be registered in by default, by default None
39
- autosync : bool, optional
40
- Whether to automatically sync commands on startup, by default True
41
- provided_locales : t.Sequence[hikari.Locale] | None, optional
42
- The locales that will be provided to the client by locale provider callbacks, by default None
50
+ default_enabled_guilds : t.Sequence[hikari.Snowflakeish] | None
51
+ The guilds that commands will be registered in by default
52
+ autosync : bool
53
+ Whether to automatically sync commands on startup
54
+ autodefer : bool | AutodeferMode
55
+ Whether to automatically defer responses
56
+ This applies to all commands, and can be overridden on a per-command basis.
57
+ default_permissions : hikari.Permissions | hikari.UndefinedType
58
+ The default permissions for commands
59
+ This applies to all commands, and can be overridden on a per-command basis.
60
+ is_nsfw : bool
61
+ Whether commands are NSFW
62
+ This applies to all commands, and can be overridden on a per-command basis.
63
+ is_dm_enabled : bool
64
+ Whether commands are enabled in DMs
65
+ This applies to all commands, and can be overridden on a per-command basis.
66
+ provided_locales : t.Sequence[hikari.Locale] | None
67
+ The locales that will be provided to the client by locale provider callbacks
43
68
 
44
69
  Usage
45
70
  -----
@@ -48,6 +73,7 @@ class GatewayClient(Client[hikari.GatewayBotAware]):
48
73
  import arc
49
74
 
50
75
  bot = hikari.GatewayBot("TOKEN")
76
+ # Default client implementation
51
77
  client = arc.GatewayClient(bot)
52
78
 
53
79
  ...
@@ -58,14 +84,26 @@ class GatewayClient(Client[hikari.GatewayBotAware]):
58
84
 
59
85
  def __init__(
60
86
  self,
61
- app: hikari.GatewayBotAware,
87
+ app: GatewayBotT,
62
88
  *,
63
- default_enabled_guilds: t.Sequence[hikari.Snowflake] | None = None,
89
+ default_enabled_guilds: t.Sequence[hikari.Snowflakeish | hikari.PartialGuild]
90
+ | hikari.UndefinedType = hikari.UNDEFINED,
64
91
  autosync: bool = True,
92
+ autodefer: bool | AutodeferMode = True,
93
+ default_permissions: hikari.Permissions | hikari.UndefinedType = hikari.UNDEFINED,
94
+ is_nsfw: bool = False,
95
+ is_dm_enabled: bool = True,
65
96
  provided_locales: t.Sequence[hikari.Locale] | None = None,
66
97
  ) -> None:
67
98
  super().__init__(
68
- app, default_enabled_guilds=default_enabled_guilds, autosync=autosync, provided_locales=provided_locales
99
+ app,
100
+ default_enabled_guilds=default_enabled_guilds,
101
+ autosync=autosync,
102
+ autodefer=autodefer,
103
+ default_permissions=default_permissions,
104
+ is_nsfw=is_nsfw,
105
+ is_dm_enabled=is_dm_enabled,
106
+ provided_locales=provided_locales,
69
107
  )
70
108
  self.app.event_manager.subscribe(hikari.StartedEvent, self._on_gatewaybot_startup)
71
109
  self.app.event_manager.subscribe(hikari.StoppingEvent, self._on_gatewaybot_shutdown)
@@ -108,7 +146,7 @@ class GatewayClient(Client[hikari.GatewayBotAware]):
108
146
  The event type to subscribe to.
109
147
 
110
148
  `EventT` must be a subclass of `hikari.events.base_events.Event`.
111
- callback : t.Callable[t.Concatenate[EventT, ...], t.Awaitable[None]]
149
+ callback : t.Callable[EventT], t.Awaitable[None]]
112
150
  The callback to call when the event is dispatched.
113
151
  """
114
152
  self.app.event_manager.subscribe(event_type, callback) # pyright: ignore reportGeneralTypeIssues
@@ -120,7 +158,7 @@ class GatewayClient(Client[hikari.GatewayBotAware]):
120
158
  ----------
121
159
  event_type : type[EventT]
122
160
  The event type to unsubscribe from.
123
- callback : t.Callable[t.Concatenate[EventT, ...], t.Awaitable[None]]
161
+ callback : t.Callable[[EventT], t.Awaitable[None]]
124
162
  The callback to unsubscribe.
125
163
  """
126
164
  self.app.event_manager.unsubscribe(event_type, callback) # pyright: ignore reportGeneralTypeIssues
@@ -140,7 +178,7 @@ class GatewayClient(Client[hikari.GatewayBotAware]):
140
178
 
141
179
  Returns
142
180
  -------
143
- t.Callable[t.Callable[t.Concatenate[EventT, ...], t.Awaitable[None]]], t.Callable[t.Concatenate[EventT, ...], t.Awaitable[None]]]
181
+ t.Callable[t.Callable[[EventT], t.Awaitable[None]]], t.Callable[[EventT], t.Awaitable[None]]]
144
182
  A decorator for a coroutine function that passes it to
145
183
  `EventManager.subscribe` before returning the function
146
184
  reference.
@@ -157,20 +195,33 @@ class GatewayClient(Client[hikari.GatewayBotAware]):
157
195
  return decorator
158
196
 
159
197
 
160
- class RESTClient(Client[hikari.RESTBotAware]):
161
- """The default implementation for an arc client with `hikari.RESTBotAware` support.
162
- If you want to use `hikari.GatewayBotAware`, use [`GatewayClient`][arc.client.GatewayClient] instead.
198
+ class RESTClientBase(Client[RESTBotT]):
199
+ """The base class for an arc client with REST support.
200
+
201
+ If you want to use GatewayBot, use [`GatewayClient`][arc.client.GatewayClientBase] instead.
163
202
 
164
203
  Parameters
165
204
  ----------
166
- app : hikari.RESTBotAware
205
+ app : hikari.GatewayBotAware
167
206
  The application this client is for.
168
- default_enabled_guilds : t.Sequence[hikari.Snowflake] | None, optional
169
- The guilds that slash commands will be registered in by default, by default None
170
- autosync : bool, optional
171
- Whether to automatically sync commands on startup, by default True
172
- provided_locales : t.Sequence[hikari.Locale] | None, optional
173
- The locales that will be provided to the client by locale provider callbacks, by default None
207
+ default_enabled_guilds : t.Sequence[hikari.Snowflakeish | hikari.PartialGuild] | None
208
+ The guilds that commands will be registered in by default
209
+ autosync : bool
210
+ Whether to automatically sync commands on startup
211
+ autodefer : bool | AutodeferMode
212
+ Whether to automatically defer responses
213
+ This applies to all commands, and can be overridden on a per-command basis.
214
+ default_permissions : hikari.Permissions | hikari.UndefinedType
215
+ The default permissions for commands
216
+ This applies to all commands, and can be overridden on a per-command basis.
217
+ is_nsfw : bool
218
+ Whether commands are NSFW
219
+ This applies to all commands, and can be overridden on a per-command basis.
220
+ is_dm_enabled : bool
221
+ Whether commands are enabled in DMs
222
+ This applies to all commands, and can be overridden on a per-command basis.
223
+ provided_locales : t.Sequence[hikari.Locale] | None
224
+ The locales that will be provided to the client by locale provider callbacks
174
225
 
175
226
 
176
227
  Usage
@@ -180,6 +231,7 @@ class RESTClient(Client[hikari.RESTBotAware]):
180
231
  import arc
181
232
 
182
233
  bot = hikari.RESTBot("TOKEN")
234
+ # Default client implementation
183
235
  client = arc.RESTClient(bot)
184
236
 
185
237
  ...
@@ -193,14 +245,26 @@ class RESTClient(Client[hikari.RESTBotAware]):
193
245
 
194
246
  def __init__(
195
247
  self,
196
- app: hikari.RESTBotAware,
248
+ app: RESTBotT,
197
249
  *,
198
- default_enabled_guilds: t.Sequence[hikari.Snowflake] | None = None,
250
+ default_enabled_guilds: t.Sequence[hikari.Snowflakeish | hikari.PartialGuild]
251
+ | hikari.UndefinedType = hikari.UNDEFINED,
199
252
  autosync: bool = True,
253
+ autodefer: bool | AutodeferMode = True,
254
+ default_permissions: hikari.Permissions | hikari.UndefinedType = hikari.UNDEFINED,
255
+ is_nsfw: bool = False,
256
+ is_dm_enabled: bool = True,
200
257
  provided_locales: t.Sequence[hikari.Locale] | None = None,
201
258
  ) -> None:
202
259
  super().__init__(
203
- app, default_enabled_guilds=default_enabled_guilds, autosync=autosync, provided_locales=provided_locales
260
+ app,
261
+ default_enabled_guilds=default_enabled_guilds,
262
+ autosync=autosync,
263
+ autodefer=autodefer,
264
+ default_permissions=default_permissions,
265
+ is_nsfw=is_nsfw,
266
+ is_dm_enabled=is_dm_enabled,
267
+ provided_locales=provided_locales,
204
268
  )
205
269
  self.app.add_startup_callback(self._on_restbot_startup)
206
270
  self.app.add_shutdown_callback(self._on_restbot_shutdown)
@@ -261,16 +325,22 @@ class RESTClient(Client[hikari.RESTBotAware]):
261
325
  return builder
262
326
 
263
327
 
264
- GatewayContext = Context[GatewayClient]
328
+ GatewayClient = GatewayClientBase[hikari.GatewayBotAware]
329
+ """The default gateway client implementation. An alias for [`arc.GatewayClientBase[hikari.GatewayBotAware]`][arc.client.GatewayClientBase]."""
330
+
331
+ RESTClient = RESTClientBase[hikari.RESTBotAware]
332
+ """The default REST client implementation. An alias for [`arc.RESTClientBase[hikari.RESTBotAware]`][arc.client.RESTClientBase]."""
333
+
334
+ GatewayContext = Context[GatewayClientBase[hikari.GatewayBotAware]]
265
335
  """A context using the default gateway client implementation. An alias for [`arc.Context[arc.GatewayClient]`][arc.context.base.Context]."""
266
336
 
267
- RESTContext = Context[RESTClient]
337
+ RESTContext = Context[RESTClientBase[hikari.RESTBotAware]]
268
338
  """A context using the default REST client implementation. An alias for [`arc.Context[arc.RESTClient]`][arc.context.base.Context]."""
269
339
 
270
- RESTPlugin = RESTPluginBase[RESTClient]
340
+ RESTPlugin = RESTPluginBase[RESTClientBase[hikari.RESTBotAware]]
271
341
  """A plugin using the default REST client implementation. An alias for [`arc.RESTPluginBase[arc.RESTClient]`][arc.plugin.RESTPluginBase]."""
272
342
 
273
- GatewayPlugin = GatewayPluginBase[GatewayClient]
343
+ GatewayPlugin = GatewayPluginBase[GatewayClientBase[hikari.GatewayBotAware]]
274
344
  """An alias for [`arc.GatewayPluginBase[arc.GatewayClient]`][arc.plugin.GatewayPluginBase]."""
275
345
 
276
346
  # MIT License