hikari-arc 0.5.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.
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
 
@@ -252,6 +254,7 @@ class Context(t.Generic[ClientT]):
252
254
  "_created_at",
253
255
  "_autodefer_task",
254
256
  "_has_command_failed",
257
+ "_options",
255
258
  )
256
259
 
257
260
  def __init__(
@@ -260,6 +263,7 @@ class Context(t.Generic[ClientT]):
260
263
  self._client = client
261
264
  self._command = command
262
265
  self._interaction: hikari.CommandInteraction = interaction
266
+ self._options: t.Sequence[hikari.CommandInteractionOption] | None = None
263
267
  self._responses: t.MutableSequence[InteractionResponse] = []
264
268
  self._resp_builder: asyncio.Future[ResponseBuilderT] = asyncio.Future()
265
269
  self._issued_response: bool = False
@@ -272,11 +276,11 @@ class Context(t.Generic[ClientT]):
272
276
  def interaction(self) -> hikari.CommandInteraction:
273
277
  """The underlying interaction object.
274
278
 
275
- .. warning::
279
+ !!! warning
276
280
  This should not be used directly in most cases, and is only exposed for advanced use cases.
277
281
 
278
- If you use the interaction to create a response in a view,
279
- 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.
280
284
  """
281
285
  return self._interaction
282
286
 
@@ -404,6 +408,82 @@ class Context(t.Generic[ClientT]):
404
408
  """Gets the channel this context represents, None if in a DM. Requires application cache."""
405
409
  return self._interaction.get_channel()
406
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
+
407
487
  def loc(self, key: str, use_guild: bool = True, force_locale: hikari.Locale | None = None, **kwargs: t.Any) -> str:
408
488
  """Get a localized string using the interaction's locale.
409
489
 
@@ -578,7 +658,8 @@ class Context(t.Generic[ClientT]):
578
658
  ...
579
659
 
580
660
  async def respond_with_builder(self, builder: ResponseBuilderT) -> InteractionResponse | None:
581
- """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.
582
663
 
583
664
  Parameters
584
665
  ----------
@@ -593,13 +674,13 @@ class Context(t.Generic[ClientT]):
593
674
  Raises
594
675
  ------
595
676
  RuntimeError
596
- 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.
597
678
  """
598
679
  async with self._response_lock:
599
- if self._issued_response:
680
+ if self._issued_response and not isinstance(builder, hikari.api.InteractionMessageBuilder):
600
681
  raise RuntimeError("This interaction was already issued an initial response.")
601
682
 
602
- if self.client.is_rest:
683
+ if self.client.is_rest and not self._issued_response:
603
684
  self._resp_builder.set_result(builder)
604
685
  self._issued_response = True
605
686
  if not isinstance(builder, hikari.api.InteractionModalBuilder):
@@ -608,25 +689,38 @@ class Context(t.Generic[ClientT]):
608
689
  return
609
690
 
610
691
  if isinstance(builder, hikari.api.InteractionMessageBuilder):
611
- await self.interaction.create_initial_response(
612
- response_type=hikari.ResponseType.MESSAGE_CREATE,
613
- content=builder.content,
614
- tts=builder.is_tts,
615
- components=builder.components,
616
- attachments=builder.attachments,
617
- embeds=builder.embeds,
618
- mentions_everyone=builder.mentions_everyone,
619
- user_mentions=builder.user_mentions,
620
- role_mentions=builder.role_mentions,
621
- flags=builder.flags,
622
- )
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
+ )
623
717
  elif isinstance(builder, hikari.api.InteractionDeferredBuilder):
624
718
  await self.interaction.create_initial_response(
625
719
  response_type=hikari.ResponseType.DEFERRED_MESSAGE_CREATE, flags=builder.flags
626
720
  )
627
721
  else:
628
722
  await self.interaction.create_modal_response(
629
- 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
630
724
  )
631
725
 
632
726
  self._issued_response = True
arc/errors.py CHANGED
@@ -5,18 +5,9 @@ import typing as t
5
5
  if t.TYPE_CHECKING:
6
6
  import hikari
7
7
 
8
+ from arc.abc.command import CommandProto
8
9
  from arc.abc.limiter import LimiterProto
9
10
 
10
- __all__ = (
11
- "ArcError",
12
- "AutocompleteError",
13
- "CommandInvokeError",
14
- "ExtensionError",
15
- "ExtensionLoadError",
16
- "ExtensionUnloadError",
17
- "NoResponseIssuedError",
18
- )
19
-
20
11
 
21
12
  class ArcError(Exception):
22
13
  """Base exception for all Arc errors."""
@@ -120,10 +111,10 @@ class UnderCooldownError(ArcError):
120
111
 
121
112
  Attributes
122
113
  ----------
123
- retry_after : float
124
- The amount of time in seconds until the command is off cooldown.
125
114
  limiter : arc.abc.limiter.LimiterProto
126
115
  The limiter that was rate limited.
116
+ retry_after : float
117
+ The amount of time in seconds until the command is off cooldown.
127
118
  """
128
119
 
129
120
  def __init__(self, limiter: LimiterProto[t.Any], retry_after: float, *args: t.Any) -> None:
@@ -132,6 +123,34 @@ class UnderCooldownError(ArcError):
132
123
  super().__init__(*args)
133
124
 
134
125
 
126
+ class CommandPublishFailedError(ArcError):
127
+ """Raised when a command could not be published to Discord.
128
+
129
+ Attributes
130
+ ----------
131
+ command : arc.abc.command.CommandProto
132
+ The command that failed to publish.
133
+ """
134
+
135
+ def __init__(self, command: CommandProto, *args: t.Any) -> None:
136
+ self.command = command
137
+ super().__init__(*args)
138
+
139
+
140
+ class GuildCommandPublishFailedError(ArcError):
141
+ """Raised when a set of commands could not be published to a guild.
142
+
143
+ Attributes
144
+ ----------
145
+ guild_id : hikari.Snowflake
146
+ The guild that commands could not be published to.
147
+ """
148
+
149
+ def __init__(self, guild_id: hikari.Snowflake, *args: t.Any) -> None:
150
+ self.guild_id = guild_id
151
+ super().__init__(*args)
152
+
153
+
135
154
  # MIT License
136
155
  #
137
156
  # Copyright (c) 2023-present hypergonial
arc/events.py CHANGED
@@ -17,7 +17,11 @@ class ArcEvent(hikari.Event):
17
17
 
18
18
 
19
19
  class CommandErrorEvent(ArcEvent, t.Generic[GatewayClientT]):
20
- """Event dispatched when a command raises an exception that is not handled by any error handlers."""
20
+ """Event dispatched when a command raises an exception that is not handled by any error handlers.
21
+
22
+ !!! warning
23
+ Creating any listeners for this event will disable the client error handler completely.
24
+ """
21
25
 
22
26
  def __init__(self, client: GatewayClientT, context: Context[GatewayClientT], exception: Exception) -> None:
23
27
  self._context = context
arc/internal/about.py CHANGED
@@ -5,7 +5,7 @@ __author_email__: t.Final[str] = "46067571+hypergonial@users.noreply.github.com"
5
5
  __maintainer__: t.Final[str] = "hypergonial"
6
6
  __license__: t.Final[str] = "MIT"
7
7
  __url__: t.Final[str] = "https://github.com/hypergonial/hikari-arc"
8
- __version__: t.Final[str] = "0.5.0"
8
+ __version__: t.Final[str] = "0.6.0"
9
9
 
10
10
  # MIT License
11
11
  #
@@ -0,0 +1,106 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ import hikari
6
+
7
+ from arc.abc.option import OptionType
8
+
9
+ if t.TYPE_CHECKING:
10
+ from arc.abc.option import CommandOptionBase
11
+ from arc.internal.types import ClientT
12
+
13
+
14
+ OPTIONTYPE_TO_TYPE: dict[OptionType, type[t.Any]] = {
15
+ OptionType.STRING: str,
16
+ OptionType.INTEGER: int,
17
+ OptionType.BOOLEAN: bool,
18
+ OptionType.USER: hikari.PartialUser,
19
+ OptionType.CHANNEL: hikari.PartialChannel,
20
+ OptionType.ROLE: hikari.Role,
21
+ OptionType.MENTIONABLE: hikari.Unique,
22
+ OptionType.FLOAT: float,
23
+ OptionType.ATTACHMENT: hikari.Attachment,
24
+ }
25
+ """Used for runtime type checking in Context.get_option, not much else at the moment."""
26
+
27
+
28
+ def resolve_snowflake_value(
29
+ value: hikari.Snowflake, opt_type: hikari.OptionType | int, resolved: hikari.ResolvedOptionData
30
+ ) -> t.Any:
31
+ """Resolve a snowflake value into a resolved option.
32
+
33
+ Parameters
34
+ ----------
35
+ value : hikari.Snowflake
36
+ The snowflake value to resolve.
37
+ opt_type : hikari.OptionType | int
38
+ The type of the option.
39
+ resolved : hikari.ResolvedOptionData
40
+ The resolved option data of the interaction.
41
+
42
+ Returns
43
+ -------
44
+ Any
45
+ The resolved snowflake value.
46
+
47
+ Raises
48
+ ------
49
+ ValueError
50
+ If the option type is not a valid option type.
51
+ """
52
+ match opt_type:
53
+ case hikari.OptionType.USER:
54
+ out = resolved.members.get(value) or resolved.users[value]
55
+ case hikari.OptionType.ATTACHMENT:
56
+ out = resolved.attachments[value]
57
+ case hikari.OptionType.CHANNEL:
58
+ out = resolved.channels[value]
59
+ case hikari.OptionType.ROLE:
60
+ out = resolved.roles[value]
61
+ case hikari.OptionType.MENTIONABLE:
62
+ out = resolved.members.get(value) or resolved.users.get(value) or resolved.roles[value]
63
+ case _:
64
+ raise ValueError(f"Unexpected option type '{opt_type}.'")
65
+
66
+ return out
67
+
68
+
69
+ def resolve_options(
70
+ local_options: t.MutableMapping[str, CommandOptionBase[ClientT, t.Any, t.Any]],
71
+ incoming_options: t.Sequence[hikari.CommandInteractionOption],
72
+ resolved: hikari.ResolvedOptionData | None,
73
+ ) -> dict[str, t.Any]:
74
+ """Resolve the options into kwargs for the callback.
75
+
76
+ Parameters
77
+ ----------
78
+ local_options : t.MutableMapping[str, Option[t.Any, t.Any]]
79
+ The options of the locally stored command.
80
+ incoming_options : t.Sequence[hikari.CommandInteractionOption]
81
+ The options of the interaction.
82
+ resolved : hikari.ResolvedOptionData
83
+ The resolved option data of the interaction.
84
+
85
+ Returns
86
+ -------
87
+ dict[str, Any]
88
+ The resolved options as kwargs, ready to be passed to the callback.
89
+ """
90
+ option_kwargs: dict[str, t.Any] = {}
91
+
92
+ for arg_name, opt in local_options.items():
93
+ inter_opt = next((o for o in incoming_options if o.name == opt.name), None)
94
+
95
+ if inter_opt is None:
96
+ continue
97
+
98
+ if isinstance(inter_opt.value, hikari.Snowflake) and resolved:
99
+ option_kwargs[arg_name] = resolve_snowflake_value(inter_opt.value, inter_opt.type, resolved)
100
+
101
+ elif isinstance(inter_opt.value, hikari.Snowflake):
102
+ raise ValueError(f"Missing resolved option data for '{inter_opt.name}'.")
103
+ else:
104
+ option_kwargs[arg_name] = inter_opt.value
105
+
106
+ return option_kwargs
arc/internal/sigparse.py CHANGED
@@ -41,6 +41,7 @@ TYPE_TO_OPTION_MAPPING: dict[t.Type[t.Any], t.Type[CommandOptionBase[t.Any, t.An
41
41
  int: IntOption,
42
42
  str: StrOption,
43
43
  float: FloatOption,
44
+ hikari.Role: RoleOption,
44
45
  hikari.User | hikari.Role: MentionableOption,
45
46
  t.Union[hikari.User, hikari.Role]: MentionableOption,
46
47
  hikari.Attachment: AttachmentOption,
@@ -51,11 +52,14 @@ TYPE_TO_OPTION_MAPPING: dict[t.Type[t.Any], t.Type[CommandOptionBase[t.Any, t.An
51
52
  hikari.GuildNewsChannel: ChannelOption,
52
53
  hikari.GuildPrivateThread: ChannelOption,
53
54
  hikari.GuildPublicThread: ChannelOption,
55
+ hikari.GuildNewsThread: ChannelOption,
54
56
  hikari.GuildForumChannel: ChannelOption,
57
+ hikari.GuildThreadChannel: ChannelOption,
55
58
  hikari.DMChannel: ChannelOption,
56
59
  hikari.GroupDMChannel: ChannelOption,
57
60
  hikari.GuildStageChannel: ChannelOption,
58
61
  hikari.PartialChannel: ChannelOption,
62
+ hikari.InteractionChannel: ChannelOption,
59
63
  hikari.TextableChannel: ChannelOption,
60
64
  hikari.GuildChannel: ChannelOption,
61
65
  hikari.PrivateChannel: ChannelOption,
@@ -83,6 +87,7 @@ CHANNEL_TYPES_MAPPING: dict[t.Type[hikari.PartialChannel], hikari.ChannelType |
83
87
  hikari.GuildNewsChannel: hikari.ChannelType.GUILD_NEWS,
84
88
  hikari.GuildPrivateThread: hikari.ChannelType.GUILD_PRIVATE_THREAD,
85
89
  hikari.GuildPublicThread: hikari.ChannelType.GUILD_PUBLIC_THREAD,
90
+ hikari.GuildNewsThread: hikari.ChannelType.GUILD_NEWS_THREAD,
86
91
  hikari.GuildForumChannel: hikari.ChannelType.GUILD_FORUM,
87
92
  hikari.DMChannel: hikari.ChannelType.DM,
88
93
  hikari.GroupDMChannel: hikari.ChannelType.GROUP_DM,
@@ -105,6 +110,19 @@ CHANNEL_TYPES_MAPPING: dict[t.Type[hikari.PartialChannel], hikari.ChannelType |
105
110
  hikari.ChannelType.GROUP_DM,
106
111
  hikari.ChannelType.GUILD_STAGE,
107
112
  },
113
+ hikari.InteractionChannel: {
114
+ hikari.ChannelType.GUILD_TEXT,
115
+ hikari.ChannelType.GUILD_VOICE,
116
+ hikari.ChannelType.GUILD_CATEGORY,
117
+ hikari.ChannelType.GUILD_NEWS,
118
+ hikari.ChannelType.GUILD_FORUM,
119
+ hikari.ChannelType.GUILD_NEWS_THREAD,
120
+ hikari.ChannelType.GUILD_PUBLIC_THREAD,
121
+ hikari.ChannelType.GUILD_PRIVATE_THREAD,
122
+ hikari.ChannelType.DM,
123
+ hikari.ChannelType.GROUP_DM,
124
+ hikari.ChannelType.GUILD_STAGE,
125
+ },
108
126
  hikari.TextableChannel: {
109
127
  hikari.ChannelType.GUILD_TEXT,
110
128
  hikari.ChannelType.GUILD_VOICE,
@@ -366,7 +384,7 @@ def parse_command_signature( # noqa: C901
366
384
  return options
367
385
 
368
386
 
369
- def parse_event_signature(func: t.Callable[t.Concatenate[EventT, ...], t.Awaitable[None]]) -> list[type[EventT]]:
387
+ def parse_event_signature(func: t.Callable[[EventT], t.Awaitable[None]]) -> list[type[EventT]]:
370
388
  """Parse an event callback function's signature and return the event type, ignore other type hints."""
371
389
  hints = t.get_type_hints(func)
372
390
 
arc/internal/sync.py CHANGED
@@ -8,6 +8,8 @@ from contextlib import suppress
8
8
 
9
9
  import hikari
10
10
 
11
+ from arc.errors import GuildCommandPublishFailedError
12
+
11
13
  if t.TYPE_CHECKING:
12
14
  from arc.abc.client import Client
13
15
  from arc.abc.command import CommandBase
@@ -153,7 +155,7 @@ def _get_all_commands(
153
155
  ] = defaultdict(lambda: defaultdict(lambda: defaultdict(dict))) # type: ignore
154
156
 
155
157
  for command in itertools.chain(
156
- client.slash_commands.values(), client.message_commands.values(), client.user_commands.values()
158
+ client._slash_commands.values(), client._message_commands.values(), client._user_commands.values()
157
159
  ):
158
160
  if command.guilds:
159
161
  for guild_id in command.guilds:
@@ -293,7 +295,10 @@ async def _sync_commands_for_guild(
293
295
  builders.append(existing._build())
294
296
  created += 1
295
297
 
296
- created = await client.app.rest.set_application_commands(client.application, builders, guild)
298
+ try:
299
+ created = await client.app.rest.set_application_commands(client.application, builders, guild)
300
+ except Exception as e:
301
+ raise GuildCommandPublishFailedError(guild_id, e, f"Failed to register commands in guild {guild_id}.") from e
297
302
 
298
303
  for existing in created:
299
304
  with suppress(KeyError):
arc/internal/types.py CHANGED
@@ -24,19 +24,14 @@ EventT = t.TypeVar("EventT", bound="hikari.Event")
24
24
  BuilderT = t.TypeVar("BuilderT", bound="hikari.api.SlashCommandBuilder | hikari.api.ContextMenuCommandBuilder")
25
25
  ParamsT = t.TypeVar("ParamsT", bound="OptionParams[t.Any]")
26
26
  HookableT = t.TypeVar("HookableT", bound="Hookable[t.Any]")
27
- P = t.ParamSpec("P")
28
27
 
29
28
  # Type aliases
30
- EventCallbackT: t.TypeAlias = "t.Callable[t.Concatenate[EventT, ...], t.Awaitable[None]]"
31
- ErrorHandlerCallbackT: t.TypeAlias = (
32
- "t.Callable[t.Concatenate[Context[ClientT], Exception, ...], t.Coroutine[t.Any, t.Any, None]]"
33
- )
29
+ EventCallbackT: t.TypeAlias = "t.Callable[[EventT], t.Awaitable[None]]"
30
+ ErrorHandlerCallbackT: t.TypeAlias = "t.Callable[[Context[ClientT], Exception], t.Awaitable[None]]"
34
31
  SlashCommandLike: t.TypeAlias = "SlashCommand[ClientT] | SlashGroup[ClientT]"
35
32
  CommandCallbackT: t.TypeAlias = "t.Callable[t.Concatenate[Context[ClientT], ...], t.Awaitable[None]]"
36
- MessageContextCallbackT: t.TypeAlias = (
37
- "t.Callable[t.Concatenate[Context[ClientT], hikari.Message, ...], t.Awaitable[None]]"
38
- )
39
- UserContextCallbackT: t.TypeAlias = "t.Callable[t.Concatenate[Context[ClientT], hikari.User, ...], t.Awaitable[None]]"
33
+ MessageCommandCallbackT: t.TypeAlias = "t.Callable[[Context[ClientT], hikari.Message], t.Awaitable[None]]"
34
+ UserCommandCallbackT: t.TypeAlias = "t.Callable[[Context[ClientT], hikari.User], t.Awaitable[None]]"
40
35
  AutocompleteCallbackT: t.TypeAlias = "t.Callable[[AutocompleteData[ClientT, ChoiceT]], t.Awaitable[t.Sequence[ChoiceT]]] | t.Callable[[AutocompleteData[ClientT, ChoiceT]], t.Awaitable[t.Sequence[hikari.api.AutocompleteChoiceBuilder]]]"
41
36
  ResponseBuilderT: t.TypeAlias = (
42
37
  "hikari.api.InteractionMessageBuilder | hikari.api.InteractionDeferredBuilder | hikari.api.InteractionModalBuilder"
@@ -44,9 +39,9 @@ ResponseBuilderT: t.TypeAlias = (
44
39
  HookT: t.TypeAlias = "t.Callable[[Context[ClientT]], t.Awaitable[HookResult]] | t.Callable[[Context[ClientT]], HookResult] | t.Callable[[Context[ClientT]], None] | t.Callable[[Context[ClientT]], t.Awaitable[None]]"
45
40
  PostHookT: t.TypeAlias = "t.Callable[[Context[ClientT]], None] | t.Callable[[Context[ClientT]], t.Awaitable[None]]"
46
41
  LifeCycleHookT: t.TypeAlias = "t.Callable[[ClientT], t.Awaitable[None]]"
47
- CommandLocaleRequestT: t.TypeAlias = "t.Callable[t.Concatenate[CommandLocaleRequest, ...], LocaleResponse]"
48
- OptionLocaleRequestT: t.TypeAlias = "t.Callable[t.Concatenate[OptionLocaleRequest, ...], LocaleResponse]"
49
- CustomLocaleRequestT: t.TypeAlias = "t.Callable[t.Concatenate[CustomLocaleRequest, ...], str]"
42
+ CommandLocaleRequestT: t.TypeAlias = "t.Callable[[CommandLocaleRequest], LocaleResponse]"
43
+ OptionLocaleRequestT: t.TypeAlias = "t.Callable[[OptionLocaleRequest], LocaleResponse]"
44
+ CustomLocaleRequestT: t.TypeAlias = "t.Callable[[CustomLocaleRequest], str]"
50
45
 
51
46
  # MIT License
52
47
  #
arc/plugin.py CHANGED
@@ -140,7 +140,7 @@ class GatewayPluginBase(PluginBase[GatewayClientT]):
140
140
  ----------
141
141
  event : type[hikari.Event]
142
142
  The event to subscribe to.
143
- callback : Callable[[EventT], Awaitable[None]]
143
+ callback : t.Callable[[EventT], t.Awaitable[None]]
144
144
  The callback to call when the event is dispatched.
145
145
  """
146
146
  if event not in self.listeners:
@@ -158,7 +158,7 @@ class GatewayPluginBase(PluginBase[GatewayClientT]):
158
158
  ----------
159
159
  event : type[hikari.Event]
160
160
  The event to unsubscribe from.
161
- callback : Callable[[EventT], Awaitable[None]]
161
+ callback : t.Callable[[EventT], t.Awaitable[None]]
162
162
  The callback to unsubscribe.
163
163
  """
164
164
  if event not in self.listeners:
arc/utils/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from .hooks import (
2
- RateLimiter,
2
+ LimiterHook,
3
3
  bot_has_permissions,
4
4
  channel_limiter,
5
5
  custom_limiter,
@@ -12,6 +12,7 @@ from .hooks import (
12
12
  owner_only,
13
13
  user_limiter,
14
14
  )
15
+ from .ratelimiter import RateLimiter, RateLimiterExhaustedError
15
16
 
16
17
  __all__ = (
17
18
  "guild_only",
@@ -25,7 +26,9 @@ __all__ = (
25
26
  "member_limiter",
26
27
  "channel_limiter",
27
28
  "custom_limiter",
29
+ "LimiterHook",
28
30
  "RateLimiter",
31
+ "RateLimiterExhaustedError",
29
32
  )
30
33
 
31
34
  # MIT License
@@ -1,6 +1,6 @@
1
1
  from .basic import bot_has_permissions, dm_only, guild_only, has_permissions, owner_only
2
2
  from .limiters import (
3
- RateLimiter,
3
+ LimiterHook,
4
4
  channel_limiter,
5
5
  custom_limiter,
6
6
  global_limiter,
@@ -21,5 +21,5 @@ __all__ = (
21
21
  "user_limiter",
22
22
  "member_limiter",
23
23
  "custom_limiter",
24
- "RateLimiter",
24
+ "LimiterHook",
25
25
  )