Skip to content

Commit 4937bec

Browse files
Implement Slash Command Permissions (#720)
* Rename interaction modules * Move Command to hikari.commands * Add application command permissions * Add permission rest methods to Command class * Post-rebase fixes * CommandPermission.is_enabled -> .has_access * update has_access docstring
1 parent 708c57c commit 4937bec

12 files changed

Lines changed: 655 additions & 12 deletions

hikari/api/entity_factory.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,38 @@ def deserialize_command(
988988
the integration.
989989
"""
990990

991+
@abc.abstractmethod
992+
def deserialize_guild_command_permissions(
993+
self, payload: data_binding.JSONObject
994+
) -> commands.GuildCommandPermissions:
995+
"""Parse a raw payload from Discord into guild command permissions object.
996+
997+
Parameters
998+
----------
999+
payload : hikari.internal.data_binding.JSONObject
1000+
The JSON payload to deserialize.
1001+
1002+
Returns
1003+
-------
1004+
hikari.commands.GuildCommandPermissions
1005+
The deserialized guild command permissions object.
1006+
"""
1007+
1008+
@abc.abstractmethod
1009+
def serialize_command_permission(self, permission: commands.CommandPermission) -> data_binding.JSONObject:
1010+
"""Serialize a command permission object to a json serializable dict.
1011+
1012+
Parameters
1013+
----------
1014+
permission: hikari.commands.CommandPermission
1015+
The command permission object to serialize.
1016+
1017+
Returns
1018+
-------
1019+
hikari.internal.data_binding.JSONObject
1020+
The serialized representation of the command permission.
1021+
"""
1022+
9911023
@abc.abstractmethod
9921024
def deserialize_partial_interaction(self, payload: data_binding.JSONObject) -> base_interactions.PartialInteraction:
9931025
"""Parse a raw payload from Discord into a partial interaction object.

hikari/api/rest.py

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6232,6 +6232,7 @@ async def create_application_command(
62326232
guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
62336233
*,
62346234
options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
6235+
default_permission: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
62356236
) -> commands.Command:
62366237
r"""Create an application command.
62376238
@@ -6253,6 +6254,11 @@ async def create_application_command(
62536254
a global command rather than a guild specific one.
62546255
options : hikari.undefined.UndefinedOr[typing.Sequence[hikari.commands.CommandOption]]
62556256
A sequence of up to 10 options for this command.
6257+
default_permission : hikari.undefined.UndefinedOr[builtins.bool]
6258+
Whether this command should be enabled by default (without any
6259+
permissions) when added to a guild.
6260+
6261+
Defaults to `builtins.True`.
62566262
62576263
Returns
62586264
-------
@@ -6454,6 +6460,203 @@ async def delete_application_command(
64546460
If an internal error occurs on Discord while handling the request.
64556461
"""
64566462

6463+
@abc.abstractmethod
6464+
async def fetch_application_guild_commands_permissions(
6465+
self,
6466+
application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
6467+
guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
6468+
) -> typing.Sequence[commands.GuildCommandPermissions]:
6469+
"""Fetch the command permissions registered in a guild.
6470+
6471+
Parameters
6472+
----------
6473+
application: hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialApplication]
6474+
Object or ID of the application to fetch the command permissions for.
6475+
guild : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]]
6476+
Object or ID of the guild to fetch the command permissions for.
6477+
6478+
Returns
6479+
-------
6480+
typing.Sequence[hikari.commands.GuildCommandPermissions]
6481+
Sequence of the guild command permissions set for the specified guild.
6482+
6483+
Raises
6484+
------
6485+
hikari.errors.ForbiddenError
6486+
If you cannot access the provided application's commands or guild.
6487+
hikari.errors.NotFoundError
6488+
If the provided application isn't found.
6489+
hikari.errors.UnauthorizedError
6490+
If you are unauthorized to make the request (invalid/missing token).
6491+
hikari.errors.RateLimitTooLongError
6492+
Raised in the event that a rate limit occurs that is
6493+
longer than `max_rate_limit` when making a request.
6494+
hikari.errors.RateLimitedError
6495+
Usually, Hikari will handle and retry on hitting
6496+
rate-limits automatically. This includes most bucket-specific
6497+
rate-limits and global rate-limits. In some rare edge cases,
6498+
however, Discord implements other undocumented rules for
6499+
rate-limiting, such as limits per attribute. These cannot be
6500+
detected or handled normally by Hikari due to their undocumented
6501+
nature, and will trigger this exception if they occur.
6502+
hikari.errors.InternalServerError
6503+
If an internal error occurs on Discord while handling the request.
6504+
"""
6505+
6506+
@abc.abstractmethod
6507+
async def fetch_application_command_permissions(
6508+
self,
6509+
application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
6510+
guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
6511+
command: snowflakes.SnowflakeishOr[commands.Command],
6512+
) -> commands.GuildCommandPermissions:
6513+
"""Fetch the permissions registered for a specific command in a guild.
6514+
6515+
Parameters
6516+
----------
6517+
application: hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialApplication]
6518+
Object or ID of the application to fetch the command permissions for.
6519+
guild : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]]
6520+
Object or ID of the guild to fetch the command permissions for.
6521+
command: hikari.snowflakes.SnowflakeishOr[hikari.commands.Command]
6522+
Objecr or ID of the command to fetch the command permissions for.
6523+
6524+
Returns
6525+
-------
6526+
hikari.commands.GuildCommandPermissions
6527+
Object of the command permissions set for the specified command.
6528+
6529+
Raises
6530+
------
6531+
hikari.errors.ForbiddenError
6532+
If you cannot access the provided application's commands or guild.
6533+
hikari.errors.NotFoundError
6534+
If the provided application or command isn't found.
6535+
hikari.errors.UnauthorizedError
6536+
If you are unauthorized to make the request (invalid/missing token).
6537+
hikari.errors.RateLimitTooLongError
6538+
Raised in the event that a rate limit occurs that is
6539+
longer than `max_rate_limit` when making a request.
6540+
hikari.errors.RateLimitedError
6541+
Usually, Hikari will handle and retry on hitting
6542+
rate-limits automatically. This includes most bucket-specific
6543+
rate-limits and global rate-limits. In some rare edge cases,
6544+
however, Discord implements other undocumented rules for
6545+
rate-limiting, such as limits per attribute. These cannot be
6546+
detected or handled normally by Hikari due to their undocumented
6547+
nature, and will trigger this exception if they occur.
6548+
hikari.errors.InternalServerError
6549+
If an internal error occurs on Discord while handling the request.
6550+
"""
6551+
6552+
@abc.abstractmethod
6553+
async def set_application_guild_commands_permissions(
6554+
self,
6555+
application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
6556+
guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
6557+
permissions: typing.Mapping[
6558+
snowflakes.SnowflakeishOr[commands.Command], typing.Sequence[commands.CommandPermission]
6559+
],
6560+
) -> typing.Sequence[commands.GuildCommandPermissions]:
6561+
"""Set permissions in a guild for multiple commands.
6562+
6563+
!!! note
6564+
This overwrites any previously set permissions for the specified
6565+
commands.
6566+
6567+
Parameters
6568+
----------
6569+
application: hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialApplication]
6570+
Object or ID of the application to set the command permissions for.
6571+
guild : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]]
6572+
Object or ID of the guild to set the command permissions for.
6573+
permissions : typing.Mapping[hikari.snowflakes.SnowflakeishOr[hikari.commands.Command], typing.Sequence[hikari.commands.CommandPermission]]
6574+
Mapping of objects and/or IDs of commands to sequences of the commands
6575+
to set for the specified guild.
6576+
6577+
!!! warning
6578+
Only a maximum of up to 10 permissions can be set per command.
6579+
6580+
Returns
6581+
-------
6582+
typing.Sequence[hikari.commands.GuildCommandPermissions]
6583+
Sequence of the set guild command permissions.
6584+
6585+
Raises
6586+
------
6587+
hikari.errors.ForbiddenError
6588+
If you cannot access the provided application's commands or guild.
6589+
hikari.errors.NotFoundError
6590+
If the provided application or command isn't found.
6591+
hikari.errors.UnauthorizedError
6592+
If you are unauthorized to make the request (invalid/missing token).
6593+
hikari.errors.RateLimitTooLongError
6594+
Raised in the event that a rate limit occurs that is
6595+
longer than `max_rate_limit` when making a request.
6596+
hikari.errors.RateLimitedError
6597+
Usually, Hikari will handle and retry on hitting
6598+
rate-limits automatically. This includes most bucket-specific
6599+
rate-limits and global rate-limits. In some rare edge cases,
6600+
however, Discord implements other undocumented rules for
6601+
rate-limiting, such as limits per attribute. These cannot be
6602+
detected or handled normally by Hikari due to their undocumented
6603+
nature, and will trigger this exception if they occur.
6604+
hikari.errors.InternalServerError
6605+
If an internal error occurs on Discord while handling the request.
6606+
""" # noqa: E501 - Line too long
6607+
6608+
@abc.abstractmethod
6609+
async def set_application_command_permissions(
6610+
self,
6611+
application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
6612+
guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
6613+
command: snowflakes.SnowflakeishOr[commands.Command],
6614+
permissions: typing.Sequence[commands.CommandPermission],
6615+
) -> commands.GuildCommandPermissions:
6616+
"""Set permissions for a specific command.
6617+
6618+
!!! note
6619+
This overwrites any previously set permissions.
6620+
6621+
Parameters
6622+
----------
6623+
application: hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialApplication]
6624+
Object or ID of the application to set the command permissions for.
6625+
guild : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]]
6626+
Object or ID of the guild to set the command permissions for.
6627+
command : hikari.snowflakes.SnowflakeishOr[hikari.commands.Command]
6628+
Object or ID of the command to set the permissions for.
6629+
permissions : typing.Sequence[hikari.commands.CommandPermission]
6630+
Sequence of up to 10 of the permission objects to set.
6631+
6632+
Returns
6633+
-------
6634+
hikari.commands.GuildCommandPermissions
6635+
Object of the set permissions.
6636+
6637+
Raises
6638+
------
6639+
hikari.errors.ForbiddenError
6640+
If you cannot access the provided application's commands or guild.
6641+
hikari.errors.NotFoundError
6642+
If the provided application or command isn't found.
6643+
hikari.errors.UnauthorizedError
6644+
If you are unauthorized to make the request (invalid/missing token).
6645+
hikari.errors.RateLimitTooLongError
6646+
Raised in the event that a rate limit occurs that is
6647+
longer than `max_rate_limit` when making a request.
6648+
hikari.errors.RateLimitedError
6649+
Usually, Hikari will handle and retry on hitting
6650+
rate-limits automatically. This includes most bucket-specific
6651+
rate-limits and global rate-limits. In some rare edge cases,
6652+
however, Discord implements other undocumented rules for
6653+
rate-limiting, such as limits per attribute. These cannot be
6654+
detected or handled normally by Hikari due to their undocumented
6655+
nature, and will trigger this exception if they occur.
6656+
hikari.errors.InternalServerError
6657+
If an internal error occurs on Discord while handling the request.
6658+
"""
6659+
64576660
@abc.abstractmethod
64586661
def interaction_deferred_builder(
64596662
self, type: typing.Union[base_interactions.ResponseType, int], /

hikari/api/special_endpoints.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,19 @@ def id(self) -> undefined.UndefinedOr[snowflakes.Snowflake]:
914914
The ID of this command if set.
915915
"""
916916

917+
@property
918+
@abc.abstractmethod
919+
def default_permission(self) -> undefined.UndefinedOr[bool]:
920+
"""Whether the command should be enabled by default (without any permissions).
921+
922+
Defaults to `builtins.bool`.
923+
924+
Returns
925+
-------
926+
undefined.UndefinedOr[builtins.bool]
927+
Whether the command should be enabled by default (without any permissions).
928+
"""
929+
917930
@abc.abstractmethod
918931
def set_id(self: _T, id_: undefined.UndefinedOr[snowflakes.Snowflakeish], /) -> _T:
919932
"""Set the ID of this command.
@@ -929,6 +942,21 @@ def set_id(self: _T, id_: undefined.UndefinedOr[snowflakes.Snowflakeish], /) ->
929942
Object of this command builder.
930943
"""
931944

945+
@abc.abstractmethod
946+
def set_default_permission(self: _T, state: undefined.UndefinedOr[bool], /) -> _T:
947+
"""Whether this command should be enabled by default (without any permissions).
948+
949+
Parameters
950+
----------
951+
state : hikari.undefined.UndefinedOr[builtins.bool]
952+
Whether this command should be enabled by default.
953+
954+
Returns
955+
-------
956+
CommandBuilder
957+
Object of this command builder for chained calls.
958+
"""
959+
932960
@abc.abstractmethod
933961
def add_option(self: _T, option: commands.CommandOption) -> _T:
934962
"""Add an option to this command.

0 commit comments

Comments
 (0)