hikari-arc 1.4.0__py3-none-any.whl → 2.0.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/__init__.py +79 -84
- arc/abc/__init__.py +14 -14
- arc/abc/client.py +113 -146
- arc/abc/command.py +54 -11
- arc/abc/option.py +6 -6
- arc/abc/plugin.py +84 -14
- arc/client.py +45 -17
- arc/command/__init__.py +27 -27
- arc/command/message.py +10 -5
- arc/command/option/__init__.py +16 -16
- arc/command/option/custom/__init__.py +2 -2
- arc/command/option/float.py +1 -1
- arc/command/option/int.py +1 -1
- arc/command/option/str.py +1 -1
- arc/command/slash.py +18 -10
- arc/command/user.py +10 -5
- arc/context/__init__.py +1 -1
- arc/context/autocomplete.py +19 -5
- arc/context/base.py +68 -14
- arc/internal/__init__.py +1 -10
- arc/internal/about.py +1 -6
- arc/internal/sync.py +6 -3
- arc/internal/version.py +1 -1
- arc/locale.py +3 -3
- arc/plugin.py +15 -7
- arc/utils/__init__.py +19 -19
- arc/utils/concurrency_limiter.py +7 -7
- arc/utils/hooks/__init__.py +8 -8
- arc/utils/hooks/basic.py +1 -1
- arc/utils/hooks/limiters.py +3 -3
- arc/utils/loops.py +2 -2
- arc/utils/ratelimiter.py +1 -1
- {hikari_arc-1.4.0.dist-info → hikari_arc-2.0.0.dist-info}/METADATA +20 -34
- hikari_arc-2.0.0.dist-info/RECORD +59 -0
- {hikari_arc-1.4.0.dist-info → hikari_arc-2.0.0.dist-info}/WHEEL +1 -2
- hikari_arc-1.4.0.dist-info/RECORD +0 -60
- hikari_arc-1.4.0.dist-info/top_level.txt +0 -1
- {hikari_arc-1.4.0.dist-info → hikari_arc-2.0.0.dist-info/licenses}/LICENSE +0 -0
arc/command/slash.py
CHANGED
|
@@ -25,8 +25,8 @@ if t.TYPE_CHECKING:
|
|
|
25
25
|
from arc.abc.plugin import PluginBase
|
|
26
26
|
|
|
27
27
|
__all__ = (
|
|
28
|
-
"SlashCommandLike",
|
|
29
28
|
"SlashCommand",
|
|
29
|
+
"SlashCommandLike",
|
|
30
30
|
"SlashGroup",
|
|
31
31
|
"SlashSubCommand",
|
|
32
32
|
"SlashSubGroup",
|
|
@@ -108,7 +108,8 @@ class SlashCommand(CallableCommandBase[ClientT, hikari.api.SlashCommandBuilder])
|
|
|
108
108
|
id=id,
|
|
109
109
|
options=[option.to_command_option() for option in self.options.values()],
|
|
110
110
|
default_member_permissions=self.default_permissions,
|
|
111
|
-
|
|
111
|
+
integration_types=self.integration_types,
|
|
112
|
+
context_types=self.invocation_contexts,
|
|
112
113
|
is_nsfw=self.is_nsfw,
|
|
113
114
|
name_localizations={str(key): value for key, value in self.name_localizations.items()},
|
|
114
115
|
description_localizations={str(key): value for key, value in self.description_localizations.items()},
|
|
@@ -263,7 +264,8 @@ class SlashGroup(CommandBase[ClientT, hikari.api.SlashCommandBuilder]):
|
|
|
263
264
|
id=id,
|
|
264
265
|
options=[subcmd.to_command_option() for subcmd in self.children.values()],
|
|
265
266
|
default_member_permissions=self.default_permissions,
|
|
266
|
-
|
|
267
|
+
integration_types=self.integration_types,
|
|
268
|
+
context_types=self.invocation_contexts,
|
|
267
269
|
is_nsfw=self.is_nsfw,
|
|
268
270
|
name_localizations={str(key): value for key, value in self.name_localizations.items()},
|
|
269
271
|
description_localizations={str(key): value for key, value in self.description_localizations.items()},
|
|
@@ -363,7 +365,7 @@ class SlashGroup(CommandBase[ClientT, hikari.api.SlashCommandBuilder]):
|
|
|
363
365
|
opt = next(o for o in subsub.options if o.name in subsubcmd.options and o.is_focused)
|
|
364
366
|
local_opt = subsubcmd.options[opt.name]
|
|
365
367
|
|
|
366
|
-
if not isinstance(local_opt, OptionWithChoices) or not local_opt.autocomplete_with:
|
|
368
|
+
if not isinstance(local_opt, OptionWithChoices) or not local_opt.autocomplete_with: # pyright: ignore reportUnknownMemberType
|
|
367
369
|
raise AutocompleteError(
|
|
368
370
|
f"Slash option got autocomplete interaction without autocomplete callback: '{local_opt.name}'."
|
|
369
371
|
)
|
|
@@ -522,7 +524,8 @@ class SlashSubGroup(SubCommandBase[ClientT, SlashGroup[ClientT]]):
|
|
|
522
524
|
autodefer=self._autodefer,
|
|
523
525
|
default_permissions=hikari.UNDEFINED,
|
|
524
526
|
is_nsfw=hikari.UNDEFINED,
|
|
525
|
-
|
|
527
|
+
integration_types=hikari.UNDEFINED,
|
|
528
|
+
invocation_contexts=hikari.UNDEFINED,
|
|
526
529
|
)
|
|
527
530
|
)
|
|
528
531
|
|
|
@@ -675,7 +678,8 @@ class SlashSubCommand(
|
|
|
675
678
|
autodefer=self._autodefer,
|
|
676
679
|
default_permissions=hikari.UNDEFINED,
|
|
677
680
|
is_nsfw=hikari.UNDEFINED,
|
|
678
|
-
|
|
681
|
+
integration_types=hikari.UNDEFINED,
|
|
682
|
+
invocation_contexts=hikari.UNDEFINED,
|
|
679
683
|
)
|
|
680
684
|
)
|
|
681
685
|
|
|
@@ -739,7 +743,8 @@ def slash_command(
|
|
|
739
743
|
description: str = "No description provided.",
|
|
740
744
|
*,
|
|
741
745
|
guilds: t.Sequence[hikari.PartialGuild | hikari.Snowflakeish] | hikari.UndefinedType = hikari.UNDEFINED,
|
|
742
|
-
|
|
746
|
+
integration_types: t.Sequence[hikari.ApplicationIntegrationType] | hikari.UndefinedType = hikari.UNDEFINED,
|
|
747
|
+
invocation_contexts: t.Sequence[hikari.ApplicationContextType] | hikari.UndefinedType = hikari.UNDEFINED,
|
|
743
748
|
is_nsfw: bool | hikari.UndefinedType = hikari.UNDEFINED,
|
|
744
749
|
autodefer: bool | AutodeferMode | hikari.UndefinedType = hikari.UNDEFINED,
|
|
745
750
|
default_permissions: hikari.Permissions | hikari.UndefinedType = hikari.UNDEFINED,
|
|
@@ -756,8 +761,10 @@ def slash_command(
|
|
|
756
761
|
The description of the command
|
|
757
762
|
guilds : t.Sequence[hikari.PartialGuild | hikari.Snowflakeish] | hikari.UndefinedType
|
|
758
763
|
The guilds this command should be enabled in, if left as undefined, the command is global
|
|
759
|
-
|
|
760
|
-
|
|
764
|
+
integration_types : t.Sequence[hikari.ApplicationIntegrationType] | hikari.UndefinedType
|
|
765
|
+
The integration types this command supports the installation of
|
|
766
|
+
invocation_contexts : t.Sequence[hikari.ApplicationContextType] | hikari.UndefinedType
|
|
767
|
+
The context types this command can be invoked in
|
|
761
768
|
is_nsfw : bool | hikari.UndefinedType
|
|
762
769
|
If True, the command is only usable in NSFW channels
|
|
763
770
|
autodefer : bool | AutodeferMode | hikari.UndefinedType
|
|
@@ -804,7 +811,8 @@ def slash_command(
|
|
|
804
811
|
description_localizations=description_localizations or {},
|
|
805
812
|
default_permissions=default_permissions,
|
|
806
813
|
guilds=guild_ids,
|
|
807
|
-
|
|
814
|
+
integration_types=integration_types,
|
|
815
|
+
invocation_contexts=invocation_contexts,
|
|
808
816
|
is_nsfw=is_nsfw,
|
|
809
817
|
)
|
|
810
818
|
|
arc/command/user.py
CHANGED
|
@@ -46,7 +46,8 @@ class UserCommand(CallableCommandBase[ClientT, hikari.api.ContextMenuCommandBuil
|
|
|
46
46
|
type=self.command_type,
|
|
47
47
|
id=id,
|
|
48
48
|
default_member_permissions=self.default_permissions,
|
|
49
|
-
|
|
49
|
+
context_types=self.invocation_contexts,
|
|
50
|
+
integration_types=self.integration_types,
|
|
50
51
|
is_nsfw=self.is_nsfw,
|
|
51
52
|
name_localizations={str(key): value for key, value in self.name_localizations.items()},
|
|
52
53
|
)
|
|
@@ -70,7 +71,8 @@ def user_command(
|
|
|
70
71
|
name: str,
|
|
71
72
|
*,
|
|
72
73
|
guilds: t.Sequence[hikari.PartialGuild | hikari.Snowflakeish] | hikari.UndefinedType = hikari.UNDEFINED,
|
|
73
|
-
|
|
74
|
+
invocation_contexts: t.Sequence[hikari.ApplicationContextType] | hikari.UndefinedType = hikari.UNDEFINED,
|
|
75
|
+
integration_types: t.Sequence[hikari.ApplicationIntegrationType] | hikari.UndefinedType = hikari.UNDEFINED,
|
|
74
76
|
is_nsfw: bool | hikari.UndefinedType = hikari.UNDEFINED,
|
|
75
77
|
autodefer: bool | AutodeferMode | hikari.UndefinedType = hikari.UNDEFINED,
|
|
76
78
|
default_permissions: hikari.Permissions | hikari.UndefinedType = hikari.UNDEFINED,
|
|
@@ -87,8 +89,10 @@ def user_command(
|
|
|
87
89
|
The name of the command.
|
|
88
90
|
guilds : t.Sequence[hikari.PartialGuild | hikari.Snowflakeish] | hikari.UndefinedType
|
|
89
91
|
The guilds this command should be enabled in, if left as undefined, the command is global
|
|
90
|
-
|
|
91
|
-
|
|
92
|
+
integration_types : t.Sequence[hikari.ApplicationIntegrationType] | hikari.UndefinedType
|
|
93
|
+
The integration types this command supports the installation of
|
|
94
|
+
invocation_contexts : t.Sequence[hikari.ApplicationContextType] | hikari.UndefinedType
|
|
95
|
+
The context types this command can be invoked in
|
|
92
96
|
is_nsfw : bool | hikari.UndefinedType
|
|
93
97
|
Whether this command is NSFW.
|
|
94
98
|
autodefer : bool | AutodeferMode | hikari.UndefinedType
|
|
@@ -117,7 +121,8 @@ def user_command(
|
|
|
117
121
|
name=name,
|
|
118
122
|
autodefer=AutodeferMode(autodefer) if isinstance(autodefer, bool) else autodefer,
|
|
119
123
|
guilds=guild_ids,
|
|
120
|
-
|
|
124
|
+
invocation_contexts=invocation_contexts,
|
|
125
|
+
integration_types=integration_types,
|
|
121
126
|
is_nsfw=is_nsfw,
|
|
122
127
|
default_permissions=default_permissions,
|
|
123
128
|
name_localizations=name_localizations or {},
|
arc/context/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from .autocomplete import AutocompleteData
|
|
2
2
|
from .base import AutodeferMode, Context, InteractionResponse
|
|
3
3
|
|
|
4
|
-
__all__ = ("
|
|
4
|
+
__all__ = ("AutocompleteData", "AutodeferMode", "Context", "InteractionResponse")
|
|
5
5
|
|
|
6
6
|
# MIT License
|
|
7
7
|
#
|
arc/context/autocomplete.py
CHANGED
|
@@ -51,7 +51,7 @@ class AutocompleteData(t.Generic[ClientT, ChoiceT]):
|
|
|
51
51
|
"""
|
|
52
52
|
if self.focused_option is None:
|
|
53
53
|
return None
|
|
54
|
-
return t.cast(ChoiceT | str, self.focused_option.value)
|
|
54
|
+
return t.cast("ChoiceT | str", self.focused_option.value)
|
|
55
55
|
|
|
56
56
|
@property
|
|
57
57
|
def guild_id(self) -> hikari.Snowflake | None:
|
|
@@ -68,19 +68,33 @@ class AutocompleteData(t.Generic[ClientT, ChoiceT]):
|
|
|
68
68
|
"""The member that triggered the interaction."""
|
|
69
69
|
return self.interaction.member
|
|
70
70
|
|
|
71
|
+
@property
|
|
72
|
+
def invocation_context(self) -> hikari.ApplicationContextType:
|
|
73
|
+
"""The context in which the interaction was invoked."""
|
|
74
|
+
return self.interaction.context
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def authorizing_integration_owners(self) -> t.Mapping[hikari.ApplicationIntegrationType, hikari.Snowflake]:
|
|
78
|
+
"""Includes details about the authorizing user or server for the installation(s) relevant to the interaction.
|
|
79
|
+
|
|
80
|
+
For apps installed to a user, it can be used to tell the difference between the authorizing user
|
|
81
|
+
and the user that triggered an interaction (like a message component).
|
|
82
|
+
"""
|
|
83
|
+
return self.interaction.authorizing_integration_owners
|
|
84
|
+
|
|
71
85
|
@property
|
|
72
86
|
def user(self) -> hikari.User:
|
|
73
87
|
"""The user that triggered the interaction."""
|
|
74
88
|
return self.interaction.user
|
|
75
89
|
|
|
90
|
+
@property
|
|
91
|
+
def channel(self) -> hikari.InteractionChannel:
|
|
92
|
+
return self.interaction.channel
|
|
93
|
+
|
|
76
94
|
def get_guild(self) -> hikari.Guild | None:
|
|
77
95
|
"""Get the guild that triggered the interaction."""
|
|
78
96
|
return self.interaction.get_guild()
|
|
79
97
|
|
|
80
|
-
def get_channel(self) -> hikari.TextableGuildChannel | None:
|
|
81
|
-
"""Get the channel that triggered the interaction."""
|
|
82
|
-
return self.interaction.get_channel()
|
|
83
|
-
|
|
84
98
|
|
|
85
99
|
# MIT License
|
|
86
100
|
#
|
arc/context/base.py
CHANGED
|
@@ -11,7 +11,7 @@ import alluka
|
|
|
11
11
|
import attr
|
|
12
12
|
import hikari
|
|
13
13
|
|
|
14
|
-
from arc.abc.option import OptionType # noqa:
|
|
14
|
+
from arc.abc.option import OptionType # noqa: TC001 Needed for tests
|
|
15
15
|
from arc.errors import NoResponseIssuedError, ResponseAlreadyIssuedError
|
|
16
16
|
from arc.internal.options import OPTIONTYPE_TO_TYPE, resolve_snowflake_value
|
|
17
17
|
from arc.internal.types import ClientT, ResponseBuilderT
|
|
@@ -20,7 +20,7 @@ from arc.locale import CustomLocaleRequest
|
|
|
20
20
|
if t.TYPE_CHECKING:
|
|
21
21
|
from arc.abc.command import CallableCommandProto
|
|
22
22
|
|
|
23
|
-
__all__ = ("
|
|
23
|
+
__all__ = ("AutodeferMode", "Context", "InteractionResponse")
|
|
24
24
|
|
|
25
25
|
logger = logging.getLogger(__name__)
|
|
26
26
|
|
|
@@ -105,7 +105,7 @@ class InteractionResponse:
|
|
|
105
105
|
when a message response is issued.
|
|
106
106
|
"""
|
|
107
107
|
|
|
108
|
-
__slots__ = ("_context", "
|
|
108
|
+
__slots__ = ("_context", "_delete_after_task", "_message")
|
|
109
109
|
|
|
110
110
|
def __init__(self, context: Context[t.Any], message: hikari.Message | None = None) -> None:
|
|
111
111
|
self._context: Context[t.Any] = context
|
|
@@ -247,18 +247,18 @@ class Context(t.Generic[ClientT]):
|
|
|
247
247
|
"""A context object that is proxying a Discord command interaction."""
|
|
248
248
|
|
|
249
249
|
__slots__ = (
|
|
250
|
+
"_autodefer_task",
|
|
250
251
|
"_client",
|
|
251
252
|
"_command",
|
|
252
|
-
"_interaction",
|
|
253
|
-
"_responses",
|
|
254
|
-
"_resp_builder",
|
|
255
|
-
"_issued_response",
|
|
256
|
-
"_response_lock",
|
|
257
|
-
"_autodefer_task",
|
|
258
253
|
"_created_at",
|
|
259
254
|
"_has_command_failed",
|
|
260
|
-
"_options",
|
|
261
255
|
"_injection_ctx",
|
|
256
|
+
"_interaction",
|
|
257
|
+
"_issued_response",
|
|
258
|
+
"_options",
|
|
259
|
+
"_resp_builder",
|
|
260
|
+
"_response_lock",
|
|
261
|
+
"_responses",
|
|
262
262
|
)
|
|
263
263
|
|
|
264
264
|
def __init__(
|
|
@@ -341,11 +341,69 @@ class Context(t.Generic[ClientT]):
|
|
|
341
341
|
"""The ID of the channel the context represents."""
|
|
342
342
|
return self._interaction.channel_id
|
|
343
343
|
|
|
344
|
+
@property
|
|
345
|
+
def channel(self) -> hikari.InteractionChannel:
|
|
346
|
+
"""The channel the context represents."""
|
|
347
|
+
return self._interaction.channel
|
|
348
|
+
|
|
344
349
|
@property
|
|
345
350
|
def guild_id(self) -> hikari.Snowflake | None:
|
|
346
351
|
"""The ID of the guild the context represents. Will be None in DMs."""
|
|
347
352
|
return self._interaction.guild_id
|
|
348
353
|
|
|
354
|
+
@property
|
|
355
|
+
def invocation_context(self) -> hikari.ApplicationContextType:
|
|
356
|
+
"""The context in which the interaction was invoked.
|
|
357
|
+
|
|
358
|
+
This can be used to determine if the command was invoked in DMs, a guild, or a group DM.
|
|
359
|
+
"""
|
|
360
|
+
return self._interaction.context
|
|
361
|
+
|
|
362
|
+
@property
|
|
363
|
+
def authorizing_integration_owners(self) -> t.Mapping[hikari.ApplicationIntegrationType, hikari.Snowflake]:
|
|
364
|
+
"""Includes details about the authorizing user or guild for the installation(s) relevant to the interaction.
|
|
365
|
+
|
|
366
|
+
For apps installed to a user, it can be used to tell the difference between the authorizing user
|
|
367
|
+
and the user that triggered an interaction.
|
|
368
|
+
"""
|
|
369
|
+
return self._interaction.authorizing_integration_owners
|
|
370
|
+
|
|
371
|
+
@property
|
|
372
|
+
def authorizing_guild_id(self) -> hikari.Snowflake | None:
|
|
373
|
+
"""The ID of the guild that this command was installed in.
|
|
374
|
+
|
|
375
|
+
This will be `None` if the command was not installed in the guild.
|
|
376
|
+
|
|
377
|
+
This is a shorthand for
|
|
378
|
+
|
|
379
|
+
```
|
|
380
|
+
authorizing_integration_owners.get(hikari.ApplicationIntegrationType.GUILD_INSTALL)
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
!!! note
|
|
384
|
+
It is possible for both this value and `authorizing_user_id` to not be `None`, if the command is installed
|
|
385
|
+
in both a guild and by a user.
|
|
386
|
+
"""
|
|
387
|
+
return self._interaction.authorizing_integration_owners.get(hikari.ApplicationIntegrationType.GUILD_INSTALL)
|
|
388
|
+
|
|
389
|
+
@property
|
|
390
|
+
def authorizing_user_id(self) -> hikari.Snowflake | None:
|
|
391
|
+
"""The ID of the user that installed this command.
|
|
392
|
+
|
|
393
|
+
This will be `None` if the command was not installed by a user.
|
|
394
|
+
|
|
395
|
+
This is a shorthand for
|
|
396
|
+
|
|
397
|
+
```
|
|
398
|
+
authorizing_integration_owners.get(hikari.ApplicationIntegrationType.USER_INSTALL)
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
!!! note
|
|
402
|
+
It is possible for both this value and `authorizing_guild_id` to not be `None`, if the command is installed
|
|
403
|
+
in both a guild and by a user.
|
|
404
|
+
"""
|
|
405
|
+
return self._interaction.authorizing_integration_owners.get(hikari.ApplicationIntegrationType.USER_INSTALL)
|
|
406
|
+
|
|
349
407
|
@property
|
|
350
408
|
def is_valid(self) -> bool:
|
|
351
409
|
"""Returns if the underlying interaction expired or not.
|
|
@@ -414,10 +472,6 @@ class Context(t.Generic[ClientT]):
|
|
|
414
472
|
"""Gets the guild this context represents, if any. Requires application cache."""
|
|
415
473
|
return self._interaction.get_guild()
|
|
416
474
|
|
|
417
|
-
def get_channel(self) -> hikari.TextableGuildChannel | None:
|
|
418
|
-
"""Gets the channel this context represents, None if in a DM. Requires application cache."""
|
|
419
|
-
return self._interaction.get_channel()
|
|
420
|
-
|
|
421
475
|
@t.overload
|
|
422
476
|
def get_option(self, name: str, opt_type: t.Literal[OptionType.EMOJI]) -> hikari.Emoji | None: ...
|
|
423
477
|
|
arc/internal/__init__.py
CHANGED
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
from .about import __author__, __author_email__, __maintainer__, __version__
|
|
2
1
|
from .deprecation import warn_deprecate
|
|
3
2
|
from .version import CURRENT_VERSION, Version
|
|
4
3
|
|
|
5
|
-
__all__ = (
|
|
6
|
-
"warn_deprecate",
|
|
7
|
-
"Version",
|
|
8
|
-
"CURRENT_VERSION",
|
|
9
|
-
"__author__",
|
|
10
|
-
"__author_email__",
|
|
11
|
-
"__maintainer__",
|
|
12
|
-
"__version__",
|
|
13
|
-
)
|
|
4
|
+
__all__ = ("CURRENT_VERSION", "Version", "warn_deprecate")
|
|
14
5
|
|
|
15
6
|
# MIT License
|
|
16
7
|
#
|
arc/internal/about.py
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import typing as t
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
__author_email__: t.Final[str] = "git@hypergonial.com"
|
|
5
|
-
__maintainer__: t.Final[str] = "hypergonial"
|
|
6
|
-
__license__: t.Final[str] = "MIT"
|
|
7
|
-
__url__: t.Final[str] = "https://github.com/hypergonial/hikari-arc"
|
|
8
|
-
__version__: t.Final[str] = "1.4.0"
|
|
3
|
+
__version__: t.Final[str] = "2.0.0"
|
|
9
4
|
|
|
10
5
|
# MIT License
|
|
11
6
|
#
|
arc/internal/sync.py
CHANGED
|
@@ -50,8 +50,9 @@ def _rebuild_hikari_command(
|
|
|
50
50
|
description=command.description,
|
|
51
51
|
options=list(command.options) if command.options else [],
|
|
52
52
|
default_member_permissions=command.default_member_permissions,
|
|
53
|
-
is_dm_enabled=command.is_dm_enabled,
|
|
54
53
|
is_nsfw=command.is_nsfw,
|
|
54
|
+
integration_types=command.integration_types,
|
|
55
|
+
context_types=command.context_types,
|
|
55
56
|
name_localizations=command.name_localizations,
|
|
56
57
|
description_localizations=command.description_localizations,
|
|
57
58
|
)
|
|
@@ -61,8 +62,9 @@ def _rebuild_hikari_command(
|
|
|
61
62
|
id=command.id,
|
|
62
63
|
type=command.type,
|
|
63
64
|
default_member_permissions=command.default_member_permissions,
|
|
64
|
-
is_dm_enabled=command.is_dm_enabled,
|
|
65
65
|
is_nsfw=command.is_nsfw,
|
|
66
|
+
integration_types=command.integration_types,
|
|
67
|
+
context_types=command.context_types,
|
|
66
68
|
name_localizations=command.name_localizations,
|
|
67
69
|
)
|
|
68
70
|
else:
|
|
@@ -93,7 +95,8 @@ def _compare_commands(arc_command: CommandBase[t.Any, t.Any], hk_command: hikari
|
|
|
93
95
|
and arc_command.name == hk_command.name
|
|
94
96
|
and cmd_dict.get("description") == getattr(hk_command, "description", None)
|
|
95
97
|
and arc_command.is_nsfw == hk_command.is_nsfw
|
|
96
|
-
and arc_command.
|
|
98
|
+
and set(arc_command.invocation_contexts) == set(hk_command.context_types)
|
|
99
|
+
and set(arc_command.integration_types) == set(hk_command.integration_types)
|
|
97
100
|
and (
|
|
98
101
|
hk_command.guild_id in arc_command.guilds
|
|
99
102
|
if hk_command.guild_id is not None and arc_command.guilds is not hikari.UNDEFINED
|
arc/internal/version.py
CHANGED
arc/locale.py
CHANGED
|
@@ -14,12 +14,12 @@ if t.TYPE_CHECKING:
|
|
|
14
14
|
from arc.context.base import Context
|
|
15
15
|
|
|
16
16
|
__all__ = (
|
|
17
|
-
"
|
|
17
|
+
"CommandLocaleRequest",
|
|
18
|
+
"CustomLocaleRequest",
|
|
18
19
|
"LocaleRequest",
|
|
20
|
+
"LocaleRequestType",
|
|
19
21
|
"LocaleResponse",
|
|
20
|
-
"CommandLocaleRequest",
|
|
21
22
|
"OptionLocaleRequest",
|
|
22
|
-
"CustomLocaleRequest",
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
|
arc/plugin.py
CHANGED
|
@@ -11,7 +11,7 @@ from arc.internal.types import EventCallbackT, EventT, GatewayClientT, RESTClien
|
|
|
11
11
|
if t.TYPE_CHECKING:
|
|
12
12
|
from arc.context.base import AutodeferMode
|
|
13
13
|
|
|
14
|
-
__all__ = ("
|
|
14
|
+
__all__ = ("GatewayPluginBase", "RESTPluginBase")
|
|
15
15
|
|
|
16
16
|
P = t.ParamSpec("P")
|
|
17
17
|
T = t.TypeVar("T")
|
|
@@ -33,8 +33,11 @@ class RESTPluginBase(PluginBase[RESTClientT]):
|
|
|
33
33
|
autodefer : bool | AutodeferMode
|
|
34
34
|
If True, all commands in this plugin will automatically defer if it is taking longer than 2 seconds to respond.
|
|
35
35
|
This can be overridden on a per-command basis.
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
integration_types : t.Sequence[hikari.ApplicationIntegrationType] | hikari.UndefinedType
|
|
37
|
+
The integration types that commands will support the installation of
|
|
38
|
+
This can be overridden on a per-command basis.
|
|
39
|
+
invocation_contexts : t.Sequence[hikari.ApplicationContextType] | hikari.UndefinedType
|
|
40
|
+
The context types that commands can be invoked in
|
|
38
41
|
This can be overridden on a per-command basis.
|
|
39
42
|
default_permissions : hikari.Permissions | hikari.UndefinedType
|
|
40
43
|
The default permissions for this plugin
|
|
@@ -81,8 +84,11 @@ class GatewayPluginBase(PluginBase[GatewayClientT]):
|
|
|
81
84
|
autodefer : bool | AutodeferMode
|
|
82
85
|
If True, all commands in this plugin will automatically defer if it is taking longer than 2 seconds to respond.
|
|
83
86
|
This can be overridden on a per-command basis.
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
integration_types : t.Sequence[hikari.ApplicationIntegrationType] | hikari.UndefinedType
|
|
88
|
+
The integration types that commands will support the installation of
|
|
89
|
+
This can be overridden on a per-command basis.
|
|
90
|
+
invocation_contexts : t.Sequence[hikari.ApplicationContextType] | hikari.UndefinedType
|
|
91
|
+
The context types that commands can be invoked in
|
|
86
92
|
This can be overridden on a per-command basis.
|
|
87
93
|
default_permissions : hikari.Permissions | hikari.UndefinedType
|
|
88
94
|
The default permissions for this plugin
|
|
@@ -115,7 +121,8 @@ class GatewayPluginBase(PluginBase[GatewayClientT]):
|
|
|
115
121
|
default_enabled_guilds: t.Sequence[hikari.Snowflakeish | hikari.PartialGuild]
|
|
116
122
|
| hikari.UndefinedType = hikari.UNDEFINED,
|
|
117
123
|
autodefer: bool | AutodeferMode | hikari.UndefinedType = hikari.UNDEFINED,
|
|
118
|
-
|
|
124
|
+
integration_types: t.Sequence[hikari.ApplicationIntegrationType] | hikari.UndefinedType = hikari.UNDEFINED,
|
|
125
|
+
invocation_contexts: t.Sequence[hikari.ApplicationContextType] | hikari.UndefinedType = hikari.UNDEFINED,
|
|
119
126
|
default_permissions: hikari.Permissions | hikari.UndefinedType = hikari.UNDEFINED,
|
|
120
127
|
is_nsfw: bool | hikari.UndefinedType = hikari.UNDEFINED,
|
|
121
128
|
) -> None:
|
|
@@ -123,7 +130,8 @@ class GatewayPluginBase(PluginBase[GatewayClientT]):
|
|
|
123
130
|
name=name,
|
|
124
131
|
default_enabled_guilds=default_enabled_guilds,
|
|
125
132
|
autodefer=autodefer,
|
|
126
|
-
|
|
133
|
+
integration_types=integration_types,
|
|
134
|
+
invocation_contexts=invocation_contexts,
|
|
127
135
|
default_permissions=default_permissions,
|
|
128
136
|
is_nsfw=is_nsfw,
|
|
129
137
|
)
|
arc/utils/__init__.py
CHANGED
|
@@ -26,32 +26,32 @@ from .loops import CronLoop, IntervalLoop, cron_loop, interval_loop
|
|
|
26
26
|
from .ratelimiter import RateLimiter, RateLimiterExhaustedError
|
|
27
27
|
|
|
28
28
|
__all__ = (
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"bot_has_permissions",
|
|
34
|
-
"global_limiter",
|
|
35
|
-
"guild_limiter",
|
|
36
|
-
"user_limiter",
|
|
37
|
-
"member_limiter",
|
|
38
|
-
"channel_limiter",
|
|
39
|
-
"custom_limiter",
|
|
29
|
+
"CommandConcurrencyLimiter",
|
|
30
|
+
"ConcurrencyLimiter",
|
|
31
|
+
"CronLoop",
|
|
32
|
+
"IntervalLoop",
|
|
40
33
|
"LimiterHook",
|
|
41
34
|
"RateLimiter",
|
|
42
35
|
"RateLimiterExhaustedError",
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
36
|
+
"bot_has_permissions",
|
|
37
|
+
"channel_concurrency",
|
|
38
|
+
"channel_limiter",
|
|
46
39
|
"cron_loop",
|
|
47
|
-
"
|
|
48
|
-
"
|
|
40
|
+
"custom_concurrency",
|
|
41
|
+
"custom_limiter",
|
|
42
|
+
"dm_only",
|
|
49
43
|
"global_concurrency",
|
|
44
|
+
"global_limiter",
|
|
50
45
|
"guild_concurrency",
|
|
51
|
-
"
|
|
52
|
-
"
|
|
46
|
+
"guild_limiter",
|
|
47
|
+
"guild_only",
|
|
48
|
+
"has_permissions",
|
|
49
|
+
"interval_loop",
|
|
53
50
|
"member_concurrency",
|
|
54
|
-
"
|
|
51
|
+
"member_limiter",
|
|
52
|
+
"owner_only",
|
|
53
|
+
"user_concurrency",
|
|
54
|
+
"user_limiter",
|
|
55
55
|
)
|
|
56
56
|
|
|
57
57
|
# MIT License
|
arc/utils/concurrency_limiter.py
CHANGED
|
@@ -9,14 +9,14 @@ from arc.context.base import Context
|
|
|
9
9
|
from arc.internal.types import ClientT
|
|
10
10
|
|
|
11
11
|
__all__ = (
|
|
12
|
-
"ConcurrencyLimiter",
|
|
13
12
|
"CommandConcurrencyLimiter",
|
|
13
|
+
"ConcurrencyLimiter",
|
|
14
|
+
"channel_concurrency",
|
|
15
|
+
"custom_concurrency",
|
|
14
16
|
"global_concurrency",
|
|
15
17
|
"guild_concurrency",
|
|
16
|
-
"channel_concurrency",
|
|
17
|
-
"user_concurrency",
|
|
18
18
|
"member_concurrency",
|
|
19
|
-
"
|
|
19
|
+
"user_concurrency",
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
KeyT = t.TypeVar("KeyT")
|
|
@@ -32,7 +32,7 @@ class _BoundedSemaphore(asyncio.BoundedSemaphore):
|
|
|
32
32
|
class _Bucket(t.Generic[KeyT]):
|
|
33
33
|
"""Handles the concurrency limiting of a single item. (E.g. a single user or a channel)."""
|
|
34
34
|
|
|
35
|
-
__slots__ = ("_key", "
|
|
35
|
+
__slots__ = ("_key", "_limiter", "_max_concurrent", "_semaphore")
|
|
36
36
|
|
|
37
37
|
def __init__(self, key: str, max_concurrent: int, limiter: ConcurrencyLimiter[KeyT]) -> None:
|
|
38
38
|
self._key = key
|
|
@@ -74,7 +74,7 @@ class _Bucket(t.Generic[KeyT]):
|
|
|
74
74
|
|
|
75
75
|
|
|
76
76
|
class _ConcurrencyLimiterContextManager(t.Generic[KeyT]):
|
|
77
|
-
__slots__ = ("
|
|
77
|
+
__slots__ = ("_item", "_limiter")
|
|
78
78
|
|
|
79
79
|
def __init__(self, limiter: ConcurrencyLimiter[KeyT], item: KeyT) -> None:
|
|
80
80
|
self._limiter = limiter
|
|
@@ -122,7 +122,7 @@ class ConcurrencyLimiter(t.Generic[KeyT]):
|
|
|
122
122
|
- [`custom_concurrency()`][arc.utils.concurrency_limiter.custom_concurrency]
|
|
123
123
|
"""
|
|
124
124
|
|
|
125
|
-
__slots__: t.Sequence[str] = ("
|
|
125
|
+
__slots__: t.Sequence[str] = ("_buckets", "_capacity", "_get_key")
|
|
126
126
|
|
|
127
127
|
def __init__(self, capacity: int, *, get_key_with: t.Callable[[KeyT], str]) -> None:
|
|
128
128
|
self._capacity = capacity
|
arc/utils/hooks/__init__.py
CHANGED
|
@@ -10,16 +10,16 @@ from .limiters import (
|
|
|
10
10
|
)
|
|
11
11
|
|
|
12
12
|
__all__ = (
|
|
13
|
-
"
|
|
14
|
-
"owner_only",
|
|
15
|
-
"dm_only",
|
|
16
|
-
"has_permissions",
|
|
13
|
+
"LimiterHook",
|
|
17
14
|
"bot_has_permissions",
|
|
15
|
+
"channel_limiter",
|
|
16
|
+
"custom_limiter",
|
|
17
|
+
"dm_only",
|
|
18
18
|
"global_limiter",
|
|
19
19
|
"guild_limiter",
|
|
20
|
-
"
|
|
21
|
-
"
|
|
20
|
+
"guild_only",
|
|
21
|
+
"has_permissions",
|
|
22
22
|
"member_limiter",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
23
|
+
"owner_only",
|
|
24
|
+
"user_limiter",
|
|
25
25
|
)
|
arc/utils/hooks/basic.py
CHANGED
|
@@ -5,7 +5,7 @@ import typing as t
|
|
|
5
5
|
import hikari
|
|
6
6
|
|
|
7
7
|
from arc.abc.hookable import HookResult
|
|
8
|
-
from arc.context import Context # noqa:
|
|
8
|
+
from arc.context import Context # noqa: TC001 Needed for DI to work
|
|
9
9
|
from arc.errors import (
|
|
10
10
|
BotMissingPermissionsError,
|
|
11
11
|
DMOnlyError,
|
arc/utils/hooks/limiters.py
CHANGED
|
@@ -10,12 +10,12 @@ from arc.utils.ratelimiter import RateLimiter, RateLimiterExhaustedError
|
|
|
10
10
|
|
|
11
11
|
__all__ = (
|
|
12
12
|
"LimiterHook",
|
|
13
|
+
"channel_limiter",
|
|
14
|
+
"custom_limiter",
|
|
13
15
|
"global_limiter",
|
|
14
16
|
"guild_limiter",
|
|
15
|
-
"channel_limiter",
|
|
16
|
-
"user_limiter",
|
|
17
17
|
"member_limiter",
|
|
18
|
-
"
|
|
18
|
+
"user_limiter",
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
|
arc/utils/loops.py
CHANGED
|
@@ -6,7 +6,7 @@ import sys
|
|
|
6
6
|
import traceback
|
|
7
7
|
import typing as t
|
|
8
8
|
|
|
9
|
-
__all__ = ("
|
|
9
|
+
__all__ = ("CronLoop", "IntervalLoop", "cron_loop", "interval_loop")
|
|
10
10
|
|
|
11
11
|
P = t.ParamSpec("P")
|
|
12
12
|
|
|
@@ -25,7 +25,7 @@ class _LoopBase(abc.ABC, t.Generic[P]):
|
|
|
25
25
|
- [`CronLoop`][arc.utils.loops.CronLoop]
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
-
__slots__ = ("_coro", "
|
|
28
|
+
__slots__ = ("_coro", "_failed", "_run_on_start", "_stop_next", "_task")
|
|
29
29
|
|
|
30
30
|
def __init__(self, callback: t.Callable[P, t.Awaitable[None]], *, run_on_start: bool = True) -> None:
|
|
31
31
|
self._coro = callback
|
arc/utils/ratelimiter.py
CHANGED
|
@@ -117,7 +117,7 @@ class RateLimiter(t.Generic[KeyT]):
|
|
|
117
117
|
A callable that returns a key for the ratelimiter bucket.
|
|
118
118
|
"""
|
|
119
119
|
|
|
120
|
-
__slots__ = ("
|
|
120
|
+
__slots__ = ("_buckets", "_gc_task", "_get_key", "limit", "period")
|
|
121
121
|
|
|
122
122
|
def __init__(self, period: float, limit: int, *, get_key_with: t.Callable[[KeyT], str]) -> None:
|
|
123
123
|
self.period: float = period
|