Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Application Command Localizations #1141

Merged
merged 45 commits into from
Aug 20, 2022
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
63e818b
Initial implementation of Application Command Localizations
mrsrmn Apr 21, 2022
efe16cf
`nox` fixes
mrsrmn Apr 22, 2022
f45fd94
Fixed docstrings
mrsrmn Apr 22, 2022
ae01c6c
Quick fixes
mrsrmn Apr 22, 2022
0205d26
Fixes docstrings, again
mrsrmn Apr 22, 2022
b37d814
Resolve requests & fix bugs
mrsrmn Apr 23, 2022
3aaebea
`nox` fixes and missing tests
mrsrmn Apr 23, 2022
565cdf1
Cast `name_localizations` and `description_localizations` to `locales…
mrsrmn Apr 24, 2022
d8e1818
Make the requested changes
mrsrmn May 1, 2022
afadf6b
Merge branch 'master' into master
mrsrmn May 1, 2022
69536e4
Update documented regex for `name`
mrsrmn May 1, 2022
670f2c6
Add `1141.feature.md`
mrsrmn May 2, 2022
c56db09
Factory `name_localizations` and `description_localizations` to `dict`
mrsrmn May 3, 2022
f90aa11
Add `with_localizations` to `RESTClient.fetch_application_commands`
mrsrmn May 3, 2022
5c91802
Make tests pass
mrsrmn May 3, 2022
ccf93ec
Remove `with_localizations` from `fetch_application_commands` and set…
mrsrmn May 3, 2022
f830666
Resolve requests
mrsrmn May 3, 2022
17f0c23
Remove return types on docstrings
mrsrmn May 3, 2022
2c7823e
Merge branch 'hikari-py:master' into master
mrsrmn May 4, 2022
e9f92c6
Merge branch 'master' into master
mrsrmn May 22, 2022
7d4cf7d
Make requested changes
mrsrmn May 22, 2022
f6b10cc
Merge branch 'master' of https://github.com/MakufonSkifto/hikari
mrsrmn May 22, 2022
e14cab6
nox fixes
mrsrmn May 22, 2022
88d5e79
Merge remote-tracking branch 'origin/master'
mrsrmn May 28, 2022
61ee780
Requested changes
mrsrmn May 28, 2022
77d6bc3
Resolve requests
mrsrmn Jun 1, 2022
ad424c1
Grammar fix
mrsrmn Jun 1, 2022
a8f80db
Grammar v2
mrsrmn Jun 1, 2022
275e4e6
Merge branch 'master' into master
mrsrmn Jun 22, 2022
115c645
Merge branch 'master' into master
mrsrmn Jul 1, 2022
f0a86c2
resolve stuff
mrsrmn Jul 1, 2022
d0881eb
make all nox sessions pass
mrsrmn Jul 1, 2022
278206d
resolve conversations
mrsrmn Jul 1, 2022
341edef
Merge branch 'master' into master
mrsrmn Jul 1, 2022
64d0066
Merge branch 'master' into master
mrsrmn Jul 5, 2022
e7c2a6d
resolve conversations v2
mrsrmn Jul 6, 2022
65a52a8
Merge branch 'master' into master
mrsrmn Jul 12, 2022
eb368e8
Merge branch 'master' into master
mrsrmn Jul 14, 2022
dbbd8d1
Merge branch 'master' into master
davfsa Jul 15, 2022
c615513
Merge branch 'master' into master
mrsrmn Jul 17, 2022
13f52ca
Merge branch 'master' into master
mrsrmn Jul 22, 2022
877f8d7
Merge branch 'master' into master
mrsrmn Jul 26, 2022
aa00fa5
Merge branch 'master' into master
mrsrmn Aug 10, 2022
f2c9514
Merge branch 'master' into master
mrsrmn Aug 13, 2022
f3ed382
Merge branch 'master' into master
mrsrmn Aug 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/1141.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support for Application Command Localizations.
23 changes: 19 additions & 4 deletions hikari/api/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6656,7 +6656,7 @@ def command_builder(self, name: str, description: str) -> special_endpoints.Slas
Parameters
----------
name : builtins.str
The command's name. This should match the regex `^[\w-]{1,32}$` in
The command's name. This should match the regex `^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$` in
Unicode mode and be lowercase.
description : builtins.str
The description to set for the command.
Expand All @@ -6679,7 +6679,7 @@ def slash_command_builder(
Parameters
----------
name : builtins.str
The command's name. This should match the regex `^[\w-]{1,32}$` in
The command's name. This should match the regex `^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$` in
Unicode mode and be lowercase.
description : builtins.str
The description to set for the command if this is a slash command.
Expand Down Expand Up @@ -6823,6 +6823,12 @@ async def create_slash_command(
*,
guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
name_localizations: undefined.UndefinedOr[
typing.Mapping[typing.Union[locales.Locale, str], str]
] = undefined.UNDEFINED,
description_localizations: undefined.UndefinedOr[
typing.Mapping[typing.Union[locales.Locale, str], str]
] = undefined.UNDEFINED,
mrsrmn marked this conversation as resolved.
Show resolved Hide resolved
default_member_permissions: typing.Union[
undefined.UndefinedType, int, permissions_.Permissions
] = undefined.UNDEFINED,
Expand All @@ -6835,7 +6841,7 @@ async def create_slash_command(
application: hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialApplication]
Object or ID of the application to create a command for.
name : builtins.str
The command's name. This should match the regex `^[\w-]{1,32}$` in
The command's name. This should match the regex `^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$` in
Unicode mode and be lowercase.
description : builtins.str
The description to set for the command.
Expand All @@ -6849,6 +6855,10 @@ async def create_slash_command(
a global command rather than a guild specific one.
options : hikari.undefined.UndefinedOr[typing.Sequence[hikari.commands.CommandOption]]
A sequence of up to 10 options for this command.
name_localizations : hikari.undefined.UndefinedOr[typing.Mapping[typing.Union[hikari.locales.Locale, str], str]]
The name localizations for this command.
description_localizations : hikari.undefined.UndefinedOr[typing.Mapping[typing.Union[hikari.locales.Locale, str], str]]
The name localizations for this command.
default_member_permissions : typing.Union[hikari.undefined.UndefinedType, int, hikari.permissions.Permissions]
Member permissions necessary to utilize this command by default.

Expand Down Expand Up @@ -6897,6 +6907,9 @@ async def create_context_menu_command(
name: str,
*,
guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
name_localizations: undefined.UndefinedOr[
typing.Mapping[typing.Union[locales.Locale, str], str]
] = undefined.UNDEFINED,
default_member_permissions: typing.Union[
undefined.UndefinedType, int, permissions_.Permissions
] = undefined.UNDEFINED,
Expand All @@ -6913,7 +6926,7 @@ async def create_context_menu_command(

Only USER and MESSAGE are valid here.
name : builtins.str
The command's name. This should match the regex `^[\w-]{1,32}$` in
The command's name. This should match the regex `^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$` in
Unicode mode and be lowercase.

Other Parameters
Expand All @@ -6922,6 +6935,8 @@ async def create_context_menu_command(
Object or ID of the specific guild this should be made for.
If left as `hikari.undefined.UNDEFINED` then this call will create
a global command rather than a guild specific one.
name_localizations : hikari.undefined.UndefinedOr[typing.Mapping[typing.Union[hikari.locales.Locale, str], str]]
The name localizations for this command.
default_member_permissions : typing.Union[hikari.undefined.UndefinedType, int, hikari.permissions.Permissions]
Member permissions necessary to utilize this command by default.

Expand Down
53 changes: 51 additions & 2 deletions hikari/api/special_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
from hikari import emojis
from hikari import files
from hikari import guilds
from hikari import locales
from hikari import messages
from hikari import permissions as permissions_
from hikari import snowflakes
Expand Down Expand Up @@ -944,7 +945,7 @@ def name(self) -> str:
r"""Name to set for this command.

!!! warning
This should match the regex `^[\w-]{1,32}$` in Unicode mode
This should match the regex `^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$` in Unicode mode
and must be lowercase.

Returns
Expand Down Expand Up @@ -992,6 +993,11 @@ def is_dm_enabled(self) -> undefined.UndefinedOr[bool]:
Only applicable to globally-scoped commands.
"""

@property
@abc.abstractmethod
def name_localizations(self) -> typing.Mapping[typing.Union[locales.Locale, str], str]:
"""Name localizations set for this command."""

@abc.abstractmethod
def set_id(self: _T, id_: undefined.UndefinedOr[snowflakes.Snowflakeish], /) -> _T:
"""Set the ID of this command.
Expand Down Expand Up @@ -1024,7 +1030,7 @@ def set_default_member_permissions(
Returns
-------
CommandBuilder
Object of this command builder for chained calls.
Object of this command builder.
"""

@abc.abstractmethod
Expand All @@ -1042,6 +1048,23 @@ def set_is_dm_enabled(self: _T, state: undefined.UndefinedOr[bool], /) -> _T:
Object of this command builder for chained calls.
"""

@abc.abstractmethod
def set_name_localizations(
self: _T, name_localizations: typing.Mapping[typing.Union[locales.Locale, str], str], /
) -> _T:
"""Set the name localizations for this command.

Parameters
----------
name_localizations : hikari.undefined.UndefinedOr[typing.Mapping[typing.Union[hikari.locales.Locale, str], str]]
The name localizations to set for this command.

Returns
-------
CommandBuilder
Object of this command builder.
"""

@abc.abstractmethod
def build(self, entity_factory: entity_factory_.EntityFactory, /) -> typing.MutableMapping[str, typing.Any]:
"""Build a JSON object from this builder.
Expand Down Expand Up @@ -1108,6 +1131,32 @@ def description(self) -> str:
The description to set for this command.
"""

@property
@abc.abstractmethod
def description_localizations(
self,
) -> typing.Mapping[typing.Union[locales.Locale, str], str]:
"""Command's localised descriptions."""

@abc.abstractmethod
def set_description_localizations(
self: _T,
description_localizations: typing.Mapping[typing.Union[locales.Locale, str], str],
/,
) -> _T:
"""Set the localised descriptions for this command.

Parameters
----------
description_localizations : hikari.undefined.UndefinedOr[typing.Mapping[typing.Union[hikari.locales.Locale, str], str]]
The description localizations to set for this command.

Returns
-------
CommandBuilder
Object of this command builder.
"""

@property
@abc.abstractmethod
def options(self) -> typing.Sequence[commands.CommandOption]:
Expand Down
17 changes: 15 additions & 2 deletions hikari/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
if typing.TYPE_CHECKING:
from hikari import channels
from hikari import guilds
from hikari import locales


class CommandType(int, enums.Enum):
Expand Down Expand Up @@ -133,7 +134,7 @@ class CommandOption:
r"""The command option's name.

!!! note
This will match the regex `^[\w-]{1,32}$` in Unicode mode and will be
This will match the regex `^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$` in Unicode mode and will be
lowercase.
mrsrmn marked this conversation as resolved.
Show resolved Hide resolved
"""

Expand Down Expand Up @@ -183,6 +184,12 @@ class CommandOption:
and `builtins.float` if the type is `hikari.commands.OptionType.FLOAT`.
"""

name_localizations: typing.Mapping[typing.Union[locales.Locale, str], str] = attr.field(factory=dict)
"""A set of name localizations for this option."""

description_localizations: typing.Mapping[typing.Union[locales.Locale, str], str] = attr.field(factory=dict)
"""A set of description localizations for this option"""


@attr_extensions.with_copy
@attr.define(hash=True, kw_only=True, weakref_slot=False)
Expand All @@ -205,7 +212,7 @@ class PartialCommand(snowflakes.Unique):
r"""The command's name.

!!! note
This will match the regex `^[\w-]{1,32}$` in Unicode mode and will be
This will match the regex `^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$` in Unicode mode and will be
lowercase.
"""

Expand All @@ -227,6 +234,12 @@ class PartialCommand(snowflakes.Unique):
version: snowflakes.Snowflake = attr.field(eq=False, hash=False, repr=True)
"""Auto-incrementing version identifier updated during substantial record changes."""

name_localizations: typing.Mapping[typing.Union[locales.Locale, str], str] = attr.field(factory=dict)
"""A set of name localizations for this command"""

description_localizations: typing.Mapping[typing.Union[locales.Locale, str], str] = attr.field(factory=dict)
"""A set of description localizations for this command"""

async def fetch_self(self) -> PartialCommand:
"""Fetch an up-to-date version of this command object.

Expand Down
41 changes: 41 additions & 0 deletions hikari/impl/entity_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -1771,6 +1771,20 @@ def _deserialize_command_option(self, payload: data_binding.JSONObject) -> comma
if raw_channel_types := payload.get("channel_types"):
channel_types = [channel_models.ChannelType(channel_type) for channel_type in raw_channel_types]

name_localizations: typing.Mapping[str, str]
if raw_name_localizations := payload.get("name_localizations"):
name_localizations = {locales.Locale(k): raw_name_localizations[k] for k in raw_name_localizations}
else:
name_localizations = {}

description_localizations: typing.Mapping[str, str]
if raw_description_localizations := payload.get("description_localizations"):
description_localizations = {
locales.Locale(k): raw_description_localizations[k] for k in raw_description_localizations
mrsrmn marked this conversation as resolved.
Show resolved Hide resolved
}
else:
description_localizations = {}

return commands.CommandOption(
type=commands.OptionType(payload["type"]),
name=payload["name"],
Expand All @@ -1782,6 +1796,8 @@ def _deserialize_command_option(self, payload: data_binding.JSONObject) -> comma
autocomplete=payload.get("autocomplete", False),
min_value=payload.get("min_value"),
max_value=payload.get("max_value"),
name_localizations=name_localizations,
description_localizations=description_localizations,
)

def deserialize_slash_command(
Expand All @@ -1798,6 +1814,20 @@ def deserialize_slash_command(
if raw_options := payload.get("options"):
options = [self._deserialize_command_option(option) for option in raw_options]

name_localizations: typing.Mapping[typing.Union[locales.Locale, str], str]
if raw_name_localizations := payload.get("name_localizations"):
name_localizations = {locales.Locale(k): raw_name_localizations[k] for k in raw_name_localizations}
else:
name_localizations = {}

description_localizations: typing.Mapping[typing.Union[locales.Locale, str], str]
if raw_description_localizations := payload.get("description_localizations"):
description_localizations = {
locales.Locale(k): raw_description_localizations[k] for k in raw_description_localizations
}
else:
description_localizations = {}

# Discord considers 0 the same thing as ADMINISTRATORS, but we make it nicer to work with
# by setting it correctly.
default_member_permissions = payload["default_member_permissions"]
Expand All @@ -1818,6 +1848,8 @@ def deserialize_slash_command(
is_dm_enabled=payload.get("dm_permission", False),
guild_id=guild_id,
version=snowflakes.Snowflake(payload["version"]),
name_localizations=name_localizations,
description_localizations=description_localizations,
)

def deserialize_context_menu_command(
Expand All @@ -1830,6 +1862,12 @@ def deserialize_context_menu_command(
raw_guild_id = payload["guild_id"]
guild_id = snowflakes.Snowflake(raw_guild_id) if raw_guild_id is not None else None

name_localizations: typing.Mapping[typing.Union[locales.Locale, str], str]
if raw_name_localizations := payload.get("name_localizations"):
name_localizations = {locales.Locale(k): raw_name_localizations[k] for k in raw_name_localizations}
else:
name_localizations = {}

# Discord considers 0 the same thing as ADMINISTRATORS, but we make it nicer to work with
# by setting it correctly.
default_member_permissions = payload["default_member_permissions"]
Expand All @@ -1848,6 +1886,7 @@ def deserialize_context_menu_command(
is_dm_enabled=payload.get("dm_permission", False),
guild_id=guild_id,
version=snowflakes.Snowflake(payload["version"]),
name_localizations=name_localizations,
)

def deserialize_command(
Expand Down Expand Up @@ -2151,6 +2190,8 @@ def serialize_command_option(self, option: commands.CommandOption) -> data_bindi
"name": option.name,
"description": option.description,
"required": option.is_required,
"name_localizations": option.name_localizations,
"description_localizations": option.description_localizations,
}

if option.channel_types is not None:
Expand Down
26 changes: 25 additions & 1 deletion hikari/impl/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3182,7 +3182,10 @@ async def fetch_application_commands(
else:
route = routes.GET_APPLICATION_GUILD_COMMANDS.compile(application=application, guild=guild)

response = await self._request(route)
query = data_binding.StringMapBuilder()
query.put("with_localizations", True)

response = await self._request(route, query=query)
assert isinstance(response, list)
guild_id = snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
return [self._entity_factory.deserialize_command(command, guild_id=guild_id) for command in response]
Expand All @@ -3196,6 +3199,12 @@ async def _create_application_command(
*,
guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
name_localizations: undefined.UndefinedOr[
typing.Mapping[typing.Union[locales.Locale, str], str]
] = undefined.UNDEFINED,
description_localizations: undefined.UndefinedOr[
typing.Mapping[typing.Union[locales.Locale, str], str]
] = undefined.UNDEFINED,
mrsrmn marked this conversation as resolved.
Show resolved Hide resolved
default_member_permissions: typing.Union[
undefined.UndefinedType, int, permissions_.Permissions
] = undefined.UNDEFINED,
Expand All @@ -3212,6 +3221,9 @@ async def _create_application_command(
body.put("description", description)
body.put("type", type)
body.put_array("options", options, conversion=self._entity_factory.serialize_command_option)
body.put("name_localizations", name_localizations)
body.put("description_localizations", description_localizations)

# Discord has some funky behaviour around what 0 means. They consider it to be the same as ADMINISTRATOR,
# but we consider it to be the same as None for developer sanity reasons
body.put("default_member_permissions", None if default_member_permissions == 0 else default_member_permissions)
Expand All @@ -3229,6 +3241,12 @@ async def create_slash_command(
*,
guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
name_localizations: undefined.UndefinedOr[
typing.Mapping[typing.Union[locales.Locale, str], str]
] = undefined.UNDEFINED,
description_localizations: undefined.UndefinedOr[
typing.Mapping[typing.Union[locales.Locale, str], str]
] = undefined.UNDEFINED,
mrsrmn marked this conversation as resolved.
Show resolved Hide resolved
default_member_permissions: typing.Union[
undefined.UndefinedType, int, permissions_.Permissions
] = undefined.UNDEFINED,
Expand All @@ -3241,6 +3259,8 @@ async def create_slash_command(
description=description,
guild=guild,
options=options,
name_localizations=name_localizations,
description_localizations=description_localizations,
default_member_permissions=default_member_permissions,
dm_enabled=dm_enabled,
)
Expand All @@ -3255,6 +3275,9 @@ async def create_context_menu_command(
name: str,
*,
guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
name_localizations: undefined.UndefinedOr[
typing.Mapping[typing.Union[locales.Locale, str], str]
] = undefined.UNDEFINED,
mrsrmn marked this conversation as resolved.
Show resolved Hide resolved
default_member_permissions: typing.Union[
undefined.UndefinedType, int, permissions_.Permissions
] = undefined.UNDEFINED,
Expand All @@ -3265,6 +3288,7 @@ async def create_context_menu_command(
type=type,
name=name,
guild=guild,
name_localizations=name_localizations,
default_member_permissions=default_member_permissions,
dm_enabled=dm_enabled,
)
Expand Down
Loading