Repository: hikari-py/hikari
Pull request #1190 (2022-06-18 20:56:17)

Remove dollar sign from identify payload
https://github.com/discord/discord-api-docs/commit/6755c355caaf2e1c321dc7de17e1e257d9aa2db5

### Checklist
<!-- Make sure to tick all the following boxes by putting an `x` in between (like this `[x]`) -->
- [x] I have run `nox` and all the pipelines have passed.
- [x] I have made unittests according to the code I have added/modified/deleted.




Patch:
diff --git a/changes/1148.breaking.md b/changes/1148.breaking.md
new file mode 100644
index 00000000..feddb3cc
--- /dev/null
+++ b/changes/1148.breaking.md
@@ -0,0 +1,3 @@
+Removal of all application commands v1 related fields and endpoints.
+ - Discord has completely disabled some endpoints, so we unfortunately can't
+   deprecate them instead of removing them
diff --git a/changes/1148.feature.md b/changes/1148.feature.md
new file mode 100644
index 00000000..fadac43e
--- /dev/null
+++ b/changes/1148.feature.md
@@ -0,0 +1,4 @@
+Implement application commands permission v2.
+ - New `default_member_permissions` and `is_dm_enabled` related fields.
+ - Added `hikari.events.application_events.ApplicationCommandPermissionsUpdate`.
+ - Added `APPLICATION_COMMAND_PERMISSION_UPDATE` audit log entry
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 41d2cd3d..3e499525 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -29,7 +29,7 @@ sphobjinv==2.2.2
 #################
 
 mypy==0.961
-pyright==1.1.254
+pyright==1.1.255
 
 #######################
 # DEPENDENCY CHECKING #
diff --git a/hikari/api/event_factory.py b/hikari/api/event_factory.py
index 91515b1b..31677c13 100644
--- a/hikari/api/event_factory.py
+++ b/hikari/api/event_factory.py
@@ -40,6 +40,7 @@
     from hikari import users as user_models
     from hikari import voices as voices_models
     from hikari.api import shard as gateway_shard
+    from hikari.events import application_events
     from hikari.events import channel_events
     from hikari.events import guild_events
     from hikari.events import interaction_events
@@ -61,6 +62,29 @@ class EventFactory(abc.ABC):
 
     __slots__: typing.Sequence[str] = ()
 
+    ######################
+    # APPLICATION EVENTS #
+    ######################
+
+    @abc.abstractmethod
+    def deserialize_application_command_permission_update_event(
+        self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject
+    ) -> application_events.ApplicationCommandPermissionsUpdateEvent:
+        """Parse a raw payload from Discord into an application command permissions update event object.
+
+        Parameters
+        ----------
+        shard : hikari.api.shard.GatewayShard
+            The shard that emitted this event.
+        payload : hikari.internal.data_binding.JSONObject
+            The dict payload to parse.
+
+        Returns
+        -------
+        hikari.events.application_events.ApplicationCommandPermissionsUpdateEvent
+            The parsed application command permissions update event.
+        """
+
     ##################
     # CHANNEL EVENTS #
     ##################
diff --git a/hikari/api/rest.py b/hikari/api/rest.py
index 062b21bf..9e074b12 100644
--- a/hikari/api/rest.py
+++ b/hikari/api/rest.py
@@ -3275,6 +3275,9 @@ async def add_user_to_guild(
             Requires the `MANAGE_NICKNAMES` permission on the guild.
         nick : hikari.undefined.UndefinedOr[builtins.str]
             Deprecated alias for `nickname`.
+
+            .. deprecated:: 2.0.0.dev106
+                Use `nickname` instead.
         roles : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole]]
             If provided, the roles to add to the user when he joins the guild.
             This may be a collection objects or IDs of existing roles.
@@ -4995,6 +4998,9 @@ async def edit_member(
             Requires the `MANAGE_NICKNAMES` permission.
         nick : hikari.undefined.UndefinedOr[builtins.str]
             Deprecated alias for `nickname`.
+
+            .. deprecated:: 2.0.0.dev104
+                Use `nickname` instead.
         roles : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishSequence[hikari.guilds.PartialRole]]
             If provided, the new roles for the member.
 
@@ -6808,77 +6814,6 @@ async def fetch_application_commands(
             If an internal error occurs on Discord while handling the request.
         """
 
-    @abc.abstractmethod
-    async def create_application_command(
-        self,
-        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
-        name: str,
-        description: str,
-        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
-        *,
-        options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
-        default_permission: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
-    ) -> commands.SlashCommand:
-        r"""Create an application slash command.
-
-        .. deprecated:: 2.0.0.dev106
-            Use `RESTClient.create_slash_command` instead.
-
-        Parameters
-        ----------
-        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
-            Unicode mode and be lowercase.
-        description : builtins.str
-            The description to set for the command.
-            This should be inclusively between 1-100 characters in length.
-        guild : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
-            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.
-
-        Other Parameters
-        ----------------
-        options : hikari.undefined.UndefinedOr[typing.Sequence[hikari.commands.CommandOption]]
-            A sequence of up to 10 options for this command.
-        default_permission : hikari.undefined.UndefinedOr[builtins.bool]
-            Whether this command should be enabled by default (without any
-            permissions) when added to a guild.
-
-            Defaults to `builtins.True`.
-
-        Returns
-        -------
-        hikari.commands.SlashCommand
-            Object of the created command.
-
-        Raises
-        ------
-        hikari.errors.ForbiddenError
-            If you cannot access the provided application's commands.
-        hikari.errors.NotFoundError
-            If the provided application isn't found.
-        hikari.errors.BadRequestError
-            If any of the fields that are passed have an invalid value.
-        hikari.errors.UnauthorizedError
-            If you are unauthorized to make the request (invalid/missing token).
-        hikari.errors.RateLimitTooLongError
-            Raised in the event that a rate limit occurs that is
-            longer than `max_rate_limit` when making a request.
-        hikari.errors.RateLimitedError
-            Usually, Hikari will handle and retry on hitting
-            rate-limits automatically. This includes most bucket-specific
-            rate-limits and global rate-limits. In some rare edge cases,
-            however, Discord implements other undocumented rules for
-            rate-limiting, such as limits per attribute. These cannot be
-            detected or handled normally by Hikari due to their undocumented
-            nature, and will trigger this exception if they occur.
-        hikari.errors.InternalServerError
-            If an internal error occurs on Discord while handling the request.
-        """
-
     @abc.abstractmethod
     async def create_slash_command(
         self,
@@ -6888,7 +6823,10 @@ async def create_slash_command(
         *,
         guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
         options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
-        default_permission: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
+        default_member_permissions: typing.Union[
+            undefined.UndefinedType, int, permissions_.Permissions
+        ] = undefined.UNDEFINED,
+        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
     ) -> commands.SlashCommand:
         r"""Create an application command.
 
@@ -6911,11 +6849,15 @@ 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.
-        default_permission : hikari.undefined.UndefinedOr[builtins.bool]
-            Whether this command should be enabled by default (without any
-            permissions) when added to a guild.
+        default_member_permissions : typing.Union[hikari.undefined.UndefinedType, int, hikari.permissions.Permissions]
+            Member permissions necessary to utilize this command by default.
+
+            If `0`, then it will be available for all members. Note that this doesn't affect
+            administrators of the guild and overwrites.
+        dm_enabled : hikari.undefined.UndefinedOr[builtins.bool]
+            Whether this command is enabled in DMs with the bot.
 
-            Defaults to `builtins.True`.
+            This can only be applied to non-guild commands.
 
         Returns
         -------
@@ -6955,7 +6897,10 @@ async def create_context_menu_command(
         name: str,
         *,
         guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
-        default_permission: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
+        default_member_permissions: typing.Union[
+            undefined.UndefinedType, int, permissions_.Permissions
+        ] = undefined.UNDEFINED,
+        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
     ) -> commands.ContextMenuCommand:
         r"""Create an application command.
 
@@ -6977,11 +6922,15 @@ 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.
-        default_permission : hikari.undefined.UndefinedOr[builtins.bool]
-            Whether this command should be enabled by default (without any
-            permissions) when added to a guild.
+        default_member_permissions : typing.Union[hikari.undefined.UndefinedType, int, hikari.permissions.Permissions]
+            Member permissions necessary to utilize this command by default.
+
+            If `0`, then it will be available for all members. Note that this doesn't affect
+            administrators of the guild and overwrites.
+        dm_enabled : hikari.undefined.UndefinedOr[builtins.bool]
+            Whether this command is enabled in DMs with the bot.
 
-            Defaults to `builtins.True`.
+            This can only be applied to non-guild commands.
 
         Returns
         -------
@@ -7081,6 +7030,10 @@ async def edit_application_command(
         name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
         description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
         options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
+        default_member_permissions: typing.Union[
+            undefined.UndefinedType, int, permissions_.Permissions
+        ] = undefined.UNDEFINED,
+        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
     ) -> commands.PartialCommand:
         """Edit a registered application command.
 
@@ -7106,6 +7059,15 @@ async def edit_application_command(
         options : hikari.undefined.UndefinedOr[typing.Sequence[hikari.commands.CommandOption]]
             A sequence of up to 10 options to set for this command. Leave this as
             `hikari.undefined.UNDEFINED` to not change.
+        default_member_permissions : typing.Union[hikari.undefined.UndefinedType, int, hikari.permissions.Permissions]
+            Member permissions necessary to utilize this command by default.
+
+            If `0`, then it will be available for all members. Note that this doesn't affect
+            administrators of the guild and overwrites.
+        dm_enabled : hikari.undefined.UndefinedOr[builtins.bool]
+            Whether this command is enabled in DMs with the bot.
+
+            This can only be applied to non-guild commands.
 
         Returns
         -------
@@ -7272,62 +7234,7 @@ async def fetch_application_command_permissions(
             If an internal error occurs on Discord while handling the request.
         """
 
-    @abc.abstractmethod
-    async def set_application_guild_commands_permissions(
-        self,
-        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
-        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
-        permissions: typing.Mapping[
-            snowflakes.SnowflakeishOr[commands.PartialCommand], typing.Sequence[commands.CommandPermission]
-        ],
-    ) -> typing.Sequence[commands.GuildCommandPermissions]:
-        """Set permissions in a guild for multiple commands.
-
-        !!! note
-            This overwrites any previously set permissions for the specified
-            commands.
-
-        Parameters
-        ----------
-        application: hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialApplication]
-            Object or ID of the application to set the command permissions for.
-        guild : hikari.undefined.UndefinedOr[hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]]
-            Object or ID of the guild to set the command permissions for.
-        permissions : typing.Mapping[hikari.snowflakes.SnowflakeishOr[hikari.commands.PartialCommand], typing.Sequence[hikari.commands.CommandPermission]]
-            Mapping of objects and/or IDs of commands to sequences of the commands
-            to set for the specified guild.
-
-            !!! warning
-                Only a maximum of up to 10 permissions can be set per command.
-
-        Returns
-        -------
-        typing.Sequence[hikari.commands.GuildCommandPermissions]
-            Sequence of the set guild command permissions.
-
-        Raises
-        ------
-        hikari.errors.ForbiddenError
-            If you cannot access the provided application's commands or guild.
-        hikari.errors.NotFoundError
-            If the provided application or command isn't found.
-        hikari.errors.UnauthorizedError
-            If you are unauthorized to make the request (invalid/missing token).
-        hikari.errors.RateLimitTooLongError
-            Raised in the event that a rate limit occurs that is
-            longer than `max_rate_limit` when making a request.
-        hikari.errors.RateLimitedError
-            Usually, Hikari will handle and retry on hitting
-            rate-limits automatically. This includes most bucket-specific
-            rate-limits and global rate-limits. In some rare edge cases,
-            however, Discord implements other undocumented rules for
-            rate-limiting, such as limits per attribute. These cannot be
-            detected or handled normally by Hikari due to their undocumented
-            nature, and will trigger this exception if they occur.
-        hikari.errors.InternalServerError
-            If an internal error occurs on Discord while handling the request.
-        """  # noqa: E501 - Line too long
-
+    # THIS IS AN OAUTH2 FLOW ONLY
     @abc.abstractmethod
     async def set_application_command_permissions(
         self,
@@ -7338,6 +7245,12 @@ async def set_application_command_permissions(
     ) -> commands.GuildCommandPermissions:
         """Set permissions for a specific command.
 
+        !!! note
+            This requires the `access_token` to have the
+            `hikari.applications.OAuth2Scope.APPLICATIONS_COMMANDS_PERMISSION_UPDATE`
+            scope enabled along with the authorization of a Bot which has `MANAGE_INVITES`
+            permission within the target guild.
+
         !!! note
             This overwrites any previously set permissions.
 
diff --git a/hikari/api/special_endpoints.py b/hikari/api/special_endpoints.py
index 9a6378c8..51aec7a1 100644
--- a/hikari/api/special_endpoints.py
+++ b/hikari/api/special_endpoints.py
@@ -977,15 +977,19 @@ def id(self) -> undefined.UndefinedOr[snowflakes.Snowflake]:
 
     @property
     @abc.abstractmethod
-    def default_permission(self) -> undefined.UndefinedOr[bool]:
-        """Whether the command should be enabled by default (without any permissions).
+    def default_member_permissions(self) -> typing.Union[undefined.UndefinedType, permissions_.Permissions, int]:
+        """Member permissions necessary to utilize this command by default.
 
-        Defaults to `builtins.bool`.
+        If `0`, then it will be available for all members. Note that this doesn't affect
+        administrators of the guild and overwrites.
+        """
 
-        Returns
-        -------
-        undefined.UndefinedOr[builtins.bool]
-            Whether the command should be enabled by default (without any permissions).
+    @property
+    @abc.abstractmethod
+    def is_dm_enabled(self) -> undefined.UndefinedOr[bool]:
+        """Whether this command is enabled in DMs with the bot.
+
+        Only applicable to globally-scoped commands.
         """
 
     @abc.abstractmethod
@@ -1004,13 +1008,33 @@ def set_id(self: _T, id_: undefined.UndefinedOr[snowflakes.Snowflakeish], /) ->
         """
 
     @abc.abstractmethod
-    def set_default_permission(self: _T, state: undefined.UndefinedOr[bool], /) -> _T:
-        """Whether this command should be enabled by default (without any permissions).
+    def set_default_member_permissions(
+        self: _T, default_member_permissions: typing.Union[undefined.UndefinedType, int, permissions_.Permissions], /
+    ) -> _T:
+        """Set the member permissions necessary to utilize this command by default.
+
+        Parameters
+        ----------
+        default_member_permissions : hikari.undefined.UndefinedOr[builtins.bool]
+            The default member permissions to utilize this command by default.
+
+            If `0`, then it will be available for all members. Note that this doesn't affect
+            administrators of the guild and overwrites.
+
+        Returns
+        -------
+        CommandBuilder
+            Object of this command builder for chained calls.
+        """
+
+    @abc.abstractmethod
+    def set_is_dm_enabled(self: _T, state: undefined.UndefinedOr[bool], /) -> _T:
+        """Set whether this command will be enabled in DMs with the bot.
 
         Parameters
         ----------
         state : hikari.undefined.UndefinedOr[builtins.bool]
-            Whether this command should be enabled by default.
+            Whether this command is enabled in DMs with the bot.
 
         Returns
         -------
diff --git a/hikari/applications.py b/hikari/applications.py
index 3a74ff49..d8a05701 100644
--- a/hikari/applications.py
+++ b/hikari/applications.py
@@ -137,7 +137,7 @@ class OAuth2Scope(str, enums.Enum):
     """
 
     APPLICATIONS_COMMANDS = "applications.commands"
-    """Allows your application's (slash) commands to be used in a guild.
+    """Allows your application's commands to be used in a guild.
 
     This is used in Discord's special Bot Authorization Flow like
     `OAuth2Scope.BOT` in-order to join an application into a guild as an
@@ -145,7 +145,10 @@ class OAuth2Scope(str, enums.Enum):
     """
 
     APPLICATIONS_COMMANDS_UPDATE = "applications.commands.update"
-    """Allows your application to update it's (slash) commands via a bearer token."""
+    """Allows your application to update its commands via a bearer token."""
+
+    APPLICATIONS_COMMANDS_PERMISSION_UPDATE = "applications.commands.permissions.update"
+    """Allows your application to update its commands permissions via a bearer token."""
 
     APPLICATIONS_ENTITLEMENTS = "applications.entitlements"
     """Enables reading entitlements for a user's applications."""
diff --git a/hikari/audit_logs.py b/hikari/audit_logs.py
index f39c888f..befe6ecc 100644
--- a/hikari/audit_logs.py
+++ b/hikari/audit_logs.py
@@ -101,6 +101,7 @@ class AuditLogChangeKey(str, enums.Enum):
     PERMISSIONS = "permissions"
     USER_LIMIT = "user_limit"
     COLOR = "color"
+    COMMAND_ID = "command_id"
     HOIST = "hoist"
     MENTIONABLE = "mentionable"
     ALLOW = "allow"
@@ -194,6 +195,10 @@ class AuditLogEventType(int, enums.Enum):
     STICKER_CREATE = 90
     STICKER_UPDATE = 91
     STICKER_DELETE = 92
+    GUILD_SCHEDULED_EVENT_CREATE = 100
+    GUILD_SCHEDULED_EVENT_UPDATE = 101
+    GUILD_SCHEDULED_EVENT_DELETE = 102
+    APPLICATION_COMMAND_PERMISSION_UPDATE = 121
 
 
 @attr.define(hash=False, kw_only=True, weakref_slot=False)
diff --git a/hikari/commands.py b/hikari/commands.py
index 618a06ab..f13f121e 100644
--- a/hikari/commands.py
+++ b/hikari/commands.py
@@ -40,6 +40,7 @@
 
 import attr
 
+from hikari import permissions
 from hikari import snowflakes
 from hikari import traits
 from hikari import undefined
@@ -208,13 +209,15 @@ class PartialCommand(snowflakes.Unique):
         lowercase.
     """
 
-    default_permission: bool = attr.field(eq=False, hash=False, repr=True)
-    """Whether the command is enabled by default when added to a guild.
+    default_member_permissions: permissions.Permissions = attr.field(eq=False, hash=False, repr=True)
+    """Member permissions necessary to utilize this command by default.
 
-    Defaults to `builtins.True`. This behaviour is overridden by command
-    permissions.
+    This excludes administrators of the guild and overwrites.
     """
 
+    is_dm_enabled: bool = attr.field(eq=False, hash=False, repr=True)
+    """Whether this command is enabled in DMs with the bot."""
+
     guild_id: typing.Optional[snowflakes.Snowflake] = attr.field(eq=False, hash=False, repr=False)
     """ID of the guild this command is in.
 
@@ -473,6 +476,9 @@ class CommandPermissionType(int, enums.Enum):
     USER = 2
     """A command permission which toggles access for a specific user."""
 
+    CHANNEL = 3
+    """A command permission which toggles access in a specific channel."""
+
 
 @attr_extensions.with_copy
 @attr.define(kw_only=True, weakref_slot=False)
@@ -480,7 +486,13 @@ class CommandPermission:
     """Representation of a permission which enables or disables a command for a user or role."""
 
     id: snowflakes.Snowflake = attr.field(converter=snowflakes.Snowflake)
-    """Id of the role or user this permission changes the permission's state for."""
+    """ID of the role or user this permission changes the permission's state for.
+
+    There are some special constants for this field:
+
+    * If equals to `guild_id`, then it applies to all members in a guild.
+    * If equals to (`guild_id` - 1), then it applies to all channels in a guild.
+    """
 
     type: typing.Union[CommandPermissionType, int] = attr.field(converter=CommandPermissionType)
     """The entity this permission overrides the command's state for."""
@@ -494,6 +506,14 @@ class CommandPermission:
 class GuildCommandPermissions:
     """Representation of the permissions set for a command within a guild."""
 
+    id: snowflakes.Snowflake = attr.field()
+    """ID of the entity these permissions apply to.
+
+    This may be the ID of a specific command or the application ID. When this is equal
+    to `application_id`, the permissions apply to all commands that do not contain
+    explicit overwrites.
+    """
+
     application_id: snowflakes.Snowflake = attr.field()
     """ID of the application the relevant command belongs to."""
 
@@ -504,4 +524,4 @@ class GuildCommandPermissions:
     """ID of the guild these permissions are in."""
 
     permissions: typing.Sequence[CommandPermission] = attr.field()
-    """Sequence of up to (and including) 10 of the command permissions set in this guild."""
+    """Sequence of up to (and including) 100 of the command permissions set in this guild."""
diff --git a/hikari/events/__init__.py b/hikari/events/__init__.py
index 5f4c5ce3..2e858ab8 100644
--- a/hikari/events/__init__.py
+++ b/hikari/events/__init__.py
@@ -24,6 +24,7 @@
 
 from __future__ import annotations
 
+from hikari.events.application_events import *
 from hikari.events.base_events import Event
 from hikari.events.base_events import ExceptionEvent
 from hikari.events.channel_events import *
diff --git a/hikari/events/__init__.pyi b/hikari/events/__init__.pyi
index d0009472..2bd26128 100644
--- a/hikari/events/__init__.pyi
+++ b/hikari/events/__init__.pyi
@@ -1,6 +1,7 @@
 # DO NOT MANUALLY EDIT THIS FILE!
 # This file was automatically generated by `nox -s generate-stubs`
 
+from hikari.events.application_events import *
 from hikari.events.base_events import Event as Event
 from hikari.events.base_events import ExceptionEvent as ExceptionEvent
 from hikari.events.channel_events import *
diff --git a/hikari/events/application_events.py b/hikari/events/application_events.py
new file mode 100644
index 00000000..0d9b454d
--- /dev/null
+++ b/hikari/events/application_events.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+# cython: language_level=3
+# Copyright (c) 2020 Nekokatt
+# Copyright (c) 2021-present davfsa
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+"""Events fired for application related changes."""
+from __future__ import annotations
+
+__all__: typing.Sequence[str] = ("ApplicationCommandPermissionsUpdateEvent",)
+
+import typing
+
+import attr
+
+from hikari.events import shard_events
+from hikari.internal import attr_extensions
+
+if typing.TYPE_CHECKING:
+    from hikari import commands
+    from hikari import traits
+    from hikari.api import shard as gateway_shard
+
+
+@attr_extensions.with_copy
+@attr.define(kw_only=True, weakref_slot=False)
+class ApplicationCommandPermissionsUpdateEvent(shard_events.ShardEvent):
+    """Event fired when permissions for an application command are updated."""
+
+    app: traits.RESTAware = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
+    # <<inherited docstring from Event>>.
+
+    shard: gateway_shard.GatewayShard = attr.field(metadata={attr_extensions.SKIP_DEEP_COPY: True})
+    # <<inherited docstring from ShardEvent>>.
+
+    permissions: commands.GuildCommandPermissions = attr.field(repr=False)
+    """The updated application command permissions."""
diff --git a/hikari/impl/entity_factory.py b/hikari/impl/entity_factory.py
index bee6eff4..eefc296f 100644
--- a/hikari/impl/entity_factory.py
+++ b/hikari/impl/entity_factory.py
@@ -424,6 +424,7 @@ def __init__(self, app: traits.RESTAware) -> None:
             audit_log_models.AuditLogChangeKey.APPLICATION_ID: snowflakes.Snowflake,
             audit_log_models.AuditLogChangeKey.PERMISSIONS: _with_int_cast(permission_models.Permissions),
             audit_log_models.AuditLogChangeKey.COLOR: color_models.Color,
+            audit_log_models.AuditLogChangeKey.COMMAND_ID: snowflakes.Snowflake,
             audit_log_models.AuditLogChangeKey.ALLOW: _with_int_cast(permission_models.Permissions),
             audit_log_models.AuditLogChangeKey.DENY: _with_int_cast(permission_models.Permissions),
             audit_log_models.AuditLogChangeKey.CHANNEL_ID: snowflakes.Snowflake,
@@ -1774,6 +1775,14 @@ def deserialize_slash_command(
         if raw_options := payload.get("options"):
             options = [self._deserialize_command_option(option) for option in raw_options]
 
+        # 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"]
+        if default_member_permissions == 0:
+            default_member_permissions = permission_models.Permissions.ADMINISTRATOR
+        else:
+            default_member_permissions = permission_models.Permissions(default_member_permissions or 0)
+
         return commands.SlashCommand(
             app=self._app,
             id=snowflakes.Snowflake(payload["id"]),
@@ -1782,7 +1791,8 @@ def deserialize_slash_command(
             name=payload["name"],
             description=payload["description"],
             options=options,
-            default_permission=payload.get("default_permission", True),
+            default_member_permissions=default_member_permissions,
+            is_dm_enabled=payload.get("dm_permission", False),
             guild_id=guild_id,
             version=snowflakes.Snowflake(payload["version"]),
         )
@@ -1797,13 +1807,22 @@ 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
 
+        # 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"]
+        if default_member_permissions == 0:
+            default_member_permissions = permission_models.Permissions.ADMINISTRATOR
+        else:
+            default_member_permissions = permission_models.Permissions(default_member_permissions or 0)
+
         return commands.ContextMenuCommand(
             app=self._app,
             id=snowflakes.Snowflake(payload["id"]),
             type=commands.CommandType(payload["type"]),
             application_id=snowflakes.Snowflake(payload["application_id"]),
             name=payload["name"],
-            default_permission=payload.get("default_permission", True),
+            default_member_permissions=default_member_permissions,
+            is_dm_enabled=payload.get("dm_permission", False),
             guild_id=guild_id,
             version=snowflakes.Snowflake(payload["version"]),
         )
@@ -1834,6 +1853,7 @@ def deserialize_guild_command_permissions(
             for perm in payload["permissions"]
         ]
         return commands.GuildCommandPermissions(
+            id=snowflakes.Snowflake(payload["id"]),
             application_id=snowflakes.Snowflake(payload["application_id"]),
             command_id=snowflakes.Snowflake(payload["id"]),
             guild_id=snowflakes.Snowflake(payload["guild_id"]),
diff --git a/hikari/impl/event_factory.py b/hikari/impl/event_factory.py
index 49715d3b..5489f0ff 100644
--- a/hikari/impl/event_factory.py
+++ b/hikari/impl/event_factory.py
@@ -38,6 +38,7 @@
 from hikari import undefined
 from hikari import users as user_models
 from hikari.api import event_factory
+from hikari.events import application_events
 from hikari.events import channel_events
 from hikari.events import guild_events
 from hikari.events import interaction_events
@@ -73,6 +74,18 @@ class EventFactoryImpl(event_factory.EventFactory):
     def __init__(self, app: traits.RESTAware) -> None:
         self._app = app
 
+    ######################
+    # APPLICATION EVENTS #
+    ######################
+
+    def deserialize_application_command_permission_update_event(
+        self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject
+    ) -> application_events.ApplicationCommandPermissionsUpdateEvent:
+        permissions = self._app.entity_factory.deserialize_guild_command_permissions(payload)
+        return application_events.ApplicationCommandPermissionsUpdateEvent(
+            app=self._app, shard=shard, permissions=permissions
+        )
+
     ##################
     # CHANNEL EVENTS #
     ##################
diff --git a/hikari/impl/event_manager.py b/hikari/impl/event_manager.py
index e635df2c..28467fab 100644
--- a/hikari/impl/event_manager.py
+++ b/hikari/impl/event_manager.py
@@ -37,6 +37,7 @@
 from hikari import presences as presences_
 from hikari import snowflakes
 from hikari.api import config
+from hikari.events import application_events
 from hikari.events import channel_events
 from hikari.events import guild_events
 from hikari.events import interaction_events
@@ -129,6 +130,12 @@ async def on_resumed(self, shard: gateway_shard.GatewayShard, _: data_binding.JS
         """See https://discord.com/developers/docs/topics/gateway#resumed for more info."""
         await self.dispatch(self._event_factory.deserialize_resumed_event(shard))
 
+    @event_manager_base.filtered(application_events.ApplicationCommandPermissionsUpdateEvent)
+    async def on_application_command_permissions_update(
+        self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject
+    ) -> None:
+        await self.dispatch(self._event_factory.deserialize_application_command_permission_update_event(shard, payload))
+
     @event_manager_base.filtered(channel_events.GuildChannelCreateEvent, config.CacheComponents.GUILD_CHANNELS)
     async def on_channel_create(self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject) -> None:
         """See https://discord.com/developers/docs/topics/gateway#channel-create for more info."""
@@ -399,16 +406,16 @@ async def on_integration_create(self, shard: gateway_shard.GatewayShard, payload
         event = self._event_factory.deserialize_integration_create_event(shard, payload)
         await self.dispatch(event)
 
-    @event_manager_base.filtered(guild_events.IntegrationDeleteEvent)
-    async def on_integration_delete(self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject) -> None:
-        event = self._event_factory.deserialize_integration_delete_event(shard, payload)
-        await self.dispatch(event)
-
     @event_manager_base.filtered(guild_events.IntegrationUpdateEvent)
     async def on_integration_update(self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject) -> None:
         event = self._event_factory.deserialize_integration_update_event(shard, payload)
         await self.dispatch(event)
 
+    @event_manager_base.filtered(guild_events.IntegrationDeleteEvent)
+    async def on_integration_delete(self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject) -> None:
+        event = self._event_factory.deserialize_integration_delete_event(shard, payload)
+        await self.dispatch(event)
+
     @event_manager_base.filtered(member_events.MemberCreateEvent, config.CacheComponents.MEMBERS)
     async def on_guild_member_add(self, shard: gateway_shard.GatewayShard, payload: data_binding.JSONObject) -> None:
         """See https://discord.com/developers/docs/topics/gateway#guild-member-add for more info."""
diff --git a/hikari/impl/rest.py b/hikari/impl/rest.py
index ec3af346..fac326f6 100644
--- a/hikari/impl/rest.py
+++ b/hikari/impl/rest.py
@@ -3174,7 +3174,10 @@ async def _create_application_command(
         *,
         guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
         options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
-        default_permission: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
+        default_member_permissions: typing.Union[
+            undefined.UndefinedType, int, permissions_.Permissions
+        ] = undefined.UNDEFINED,
+        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
     ) -> data_binding.JSONObject:
         if guild is undefined.UNDEFINED:
             route = routes.POST_APPLICATION_COMMAND.compile(application=application)
@@ -3187,32 +3190,15 @@ 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("default_permission", default_permission)
+        # 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)
+        body.put("dm_permission", dm_enabled)
 
         response = await self._request(route, json=body)
         assert isinstance(response, dict)
         return response
 
-    @deprecation.deprecated("2.0.0.dev106", "create_slash_command")
-    async def create_application_command(
-        self,
-        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
-        name: str,
-        description: str,
-        guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
-        *,
-        options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
-        default_permission: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
-    ) -> commands.SlashCommand:
-        return await self.create_slash_command(
-            application=application,
-            name=name,
-            description=description,
-            guild=guild,
-            options=options,
-            default_permission=default_permission,
-        )
-
     async def create_slash_command(
         self,
         application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
@@ -3221,7 +3207,10 @@ async def create_slash_command(
         *,
         guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
         options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
-        default_permission: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
+        default_member_permissions: typing.Union[
+            undefined.UndefinedType, int, permissions_.Permissions
+        ] = undefined.UNDEFINED,
+        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
     ) -> commands.SlashCommand:
         response = await self._create_application_command(
             application=application,
@@ -3230,7 +3219,8 @@ async def create_slash_command(
             description=description,
             guild=guild,
             options=options,
-            default_permission=default_permission,
+            default_member_permissions=default_member_permissions,
+            dm_enabled=dm_enabled,
         )
         return self._entity_factory.deserialize_slash_command(
             response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
@@ -3243,14 +3233,18 @@ async def create_context_menu_command(
         name: str,
         *,
         guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
-        default_permission: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
+        default_member_permissions: typing.Union[
+            undefined.UndefinedType, int, permissions_.Permissions
+        ] = undefined.UNDEFINED,
+        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
     ) -> commands.ContextMenuCommand:
         response = await self._create_application_command(
             application=application,
             type=type,
             name=name,
             guild=guild,
-            default_permission=default_permission,
+            default_member_permissions=default_member_permissions,
+            dm_enabled=dm_enabled,
         )
         return self._entity_factory.deserialize_context_menu_command(
             response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
@@ -3282,6 +3276,10 @@ async def edit_application_command(
         name: undefined.UndefinedOr[str] = undefined.UNDEFINED,
         description: undefined.UndefinedOr[str] = undefined.UNDEFINED,
         options: undefined.UndefinedOr[typing.Sequence[commands.CommandOption]] = undefined.UNDEFINED,
+        default_member_permissions: typing.Union[
+            undefined.UndefinedType, int, permissions_.Permissions
+        ] = undefined.UNDEFINED,
+        dm_enabled: undefined.UndefinedOr[bool] = undefined.UNDEFINED,
     ) -> commands.PartialCommand:
         if guild is undefined.UNDEFINED:
             route = routes.PATCH_APPLICATION_COMMAND.compile(application=application, command=command)
@@ -3295,6 +3293,10 @@ async def edit_application_command(
         body.put("name", name)
         body.put("description", description)
         body.put_array("options", options, conversion=self._entity_factory.serialize_command_option)
+        # 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)
+        body.put("dm_permission", dm_enabled)
 
         response = await self._request(route, json=body)
         assert isinstance(response, dict)
@@ -3341,27 +3343,6 @@ async def fetch_application_command_permissions(
         assert isinstance(response, dict)
         return self._entity_factory.deserialize_guild_command_permissions(response)
 
-    async def set_application_guild_commands_permissions(
-        self,
-        application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
-        guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
-        permissions: typing.Mapping[
-            snowflakes.SnowflakeishOr[commands.PartialCommand], typing.Sequence[commands.CommandPermission]
-        ],
-    ) -> typing.Sequence[commands.GuildCommandPermissions]:
-        route = routes.PUT_APPLICATION_GUILD_COMMANDS_PERMISSIONS.compile(application=application, guild=guild)
-        body = [
-            {
-                "id": str(snowflakes.Snowflake(command)),
-                "permissions": [self._entity_factory.serialize_command_permission(permission) for permission in perms],
-            }
-            for command, perms in permissions.items()
-        ]
-        response = await self._request(route, json=body)
-
-        assert isinstance(response, list)
-        return [self._entity_factory.deserialize_guild_command_permissions(payload) for payload in response]
-
     async def set_application_command_permissions(
         self,
         application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
diff --git a/hikari/impl/shard.py b/hikari/impl/shard.py
index 8b7aa3b0..9c681fde 100644
--- a/hikari/impl/shard.py
+++ b/hikari/impl/shard.py
@@ -716,9 +716,9 @@ async def _identify(self) -> None:
                 "compress": False,
                 "large_threshold": self._large_threshold,
                 "properties": {
-                    "$os": f"{platform.system()} {platform.architecture()[0]}",
-                    "$browser": f"hikari ({about.__version__}, aiohttp {aiohttp.__version__})",
-                    "$device": f"hikari {about.__version__}",
+                    "os": f"{platform.system()} {platform.architecture()[0]}",
+                    "browser": f"hikari ({about.__version__}, aiohttp {aiohttp.__version__})",
+                    "device": f"hikari {about.__version__}",
                 },
                 "shard": [self._shard_id, self._shard_count],
             },
diff --git a/hikari/impl/special_endpoints.py b/hikari/impl/special_endpoints.py
index b14c92e6..fc8cc2d4 100644
--- a/hikari/impl/special_endpoints.py
+++ b/hikari/impl/special_endpoints.py
@@ -1091,15 +1091,22 @@ class CommandBuilder(special_endpoints.CommandBuilder):
     _name: str = attr.field()
 
     _id: undefined.UndefinedOr[snowflakes.Snowflake] = attr.field(default=undefined.UNDEFINED, kw_only=True)
-    _default_permission: undefined.UndefinedOr[bool] = attr.field(default=undefined.UNDEFINED, kw_only=True)
+    _default_member_permissions: typing.Union[undefined.UndefinedType, int, permissions_.Permissions] = attr.field(
+        default=undefined.UNDEFINED, kw_only=True
+    )
+    _is_dm_enabled: undefined.UndefinedOr[bool] = attr.field(default=undefined.UNDEFINED, kw_only=True)
 
     @property
     def id(self) -> undefined.UndefinedOr[snowflakes.Snowflake]:
         return self._id
 
     @property
-    def default_permission(self) -> undefined.UndefinedOr[bool]:
-        return self._default_permission
+    def default_member_permissions(self) -> typing.Union[undefined.UndefinedType, permissions_.Permissions, int]:
+        return self._default_member_permissions
+
+    @property
+    def is_dm_enabled(self) -> undefined.UndefinedOr[bool]:
+        return self._is_dm_enabled
 
     @property
     def name(self) -> str:
@@ -1109,8 +1116,16 @@ def set_id(self: _CommandBuilderT, id_: undefined.UndefinedOr[snowflakes.Snowfla
         self._id = snowflakes.Snowflake(id_) if id_ is not undefined.UNDEFINED else undefined.UNDEFINED
         return self
 
-    def set_default_permission(self: _CommandBuilderT, state: undefined.UndefinedOr[bool], /) -> _CommandBuilderT:
-        self._default_permission = state
+    def set_default_member_permissions(
+        self: _CommandBuilderT,
+        default_member_permissions: typing.Union[undefined.UndefinedType, int, permissions_.Permissions],
+        /,
+    ) -> _CommandBuilderT:
+        self._default_member_permissions = default_member_permissions
+        return self
+
+    def set_is_dm_enabled(self: _CommandBuilderT, state: undefined.UndefinedOr[bool], /) -> _CommandBuilderT:
+        self._is_dm_enabled = state
         return self
 
     def build(self, _: entity_factory_.EntityFactory, /) -> typing.MutableMapping[str, typing.Any]:
@@ -1118,7 +1133,8 @@ def build(self, _: entity_factory_.EntityFactory, /) -> typing.MutableMapping[st
         data["name"] = self._name
         data["type"] = self.type
         data.put_snowflake("id", self._id)
-        data.put("default_permission", self._default_permission)
+        data.put("default_member_permissions", self._default_member_permissions)
+        data.put("dm_permission", self._is_dm_enabled)
         return data
 
 
@@ -1169,8 +1185,9 @@ async def create(
             self._name,
             self._description,
             guild=guild,
-            default_permission=self._default_permission,
             options=self._options,
+            default_member_permissions=self._default_member_permissions,
+            dm_enabled=self._is_dm_enabled,
         )
 
 
@@ -1196,7 +1213,12 @@ async def create(
         guild: undefined.UndefinedOr[snowflakes.SnowflakeishOr[guilds.PartialGuild]] = undefined.UNDEFINED,
     ) -> commands.ContextMenuCommand:
         return await rest.create_context_menu_command(
-            application, self._type, self._name, guild=guild, default_permission=self._default_permission
+            application,
+            self._type,
+            self._name,
+            guild=guild,
+            default_member_permissions=self._default_member_permissions,
+            dm_enabled=self._is_dm_enabled,
         )
 
 


Test patch:
diff --git a/tests/hikari/impl/test_entity_factory.py b/tests/hikari/impl/test_entity_factory.py
index b8e449ff..c5fcfe0c 100644
--- a/tests/hikari/impl/test_entity_factory.py
+++ b/tests/hikari/impl/test_entity_factory.py
@@ -1763,6 +1763,51 @@ def test_deserialize_channel_handles_unknown_channel_type(self, entity_factory_i
         with pytest.raises(errors.UnrecognisedEntityError):
             entity_factory_impl.deserialize_channel({"type": -9999999999})
 
+    @pytest.mark.parametrize(
+        ("type_", "fn"),
+        [
+            (0, "deserialize_guild_text_channel"),
+            (2, "deserialize_guild_voice_channel"),
+            (4, "deserialize_guild_category"),
+            (5, "deserialize_guild_news_channel"),
+            (13, "deserialize_guild_stage_channel"),
+        ],
+    )
+    def test_deserialize_channel_when_guild(self, mock_app, type_, fn):
+        payload = {"type": type_}
+
+        with mock.patch.object(entity_factory.EntityFactoryImpl, fn) as expected_fn:
+            # We need to instantiate it after the mock so that the functions that are stored in the dicts
+            # are the ones we mock
+            entity_factory_impl = entity_factory.EntityFactoryImpl(app=mock_app)
+
+            assert entity_factory_impl.deserialize_channel(payload, guild_id=123) is expected_fn.return_value
+
+        expected_fn.assert_called_once_with(payload, guild_id=123)
+
+    @pytest.mark.parametrize(
+        ("type_", "fn"),
+        [
+            (1, "deserialize_dm"),
+            (3, "deserialize_group_dm"),
+        ],
+    )
+    def test_deserialize_channel_when_dm(self, mock_app, type_, fn):
+        payload = {"type": type_}
+
+        with mock.patch.object(entity_factory.EntityFactoryImpl, fn) as expected_fn:
+            # We need to instantiate it after the mock so that the functions that are stored in the dicts
+            # are the ones we mock
+            entity_factory_impl = entity_factory.EntityFactoryImpl(app=mock_app)
+
+            assert entity_factory_impl.deserialize_channel(payload, guild_id=123123123) is expected_fn.return_value
+
+        expected_fn.assert_called_once_with(payload)
+
+    def test_deserialize_channel_when_unknown_type(self, entity_factory_impl):
+        with pytest.raises(errors.UnrecognisedEntityError):
+            entity_factory_impl.deserialize_channel({"type": -111})
+
     ################
     # EMBED MODELS #
     ################
@@ -3096,7 +3141,7 @@ def test_deserialize_gateway_guild_ignores_unrecognised_channels(self, entity_fa
     ######################
 
     @pytest.fixture()
-    def command_payload(self):
+    def slash_command_payload(self):
         return {
             "id": "1231231231",
             "application_id": "12354123",
@@ -3104,7 +3149,8 @@ def command_payload(self):
             "type": 1,
             "name": "good name",
             "description": "very good description",
-            "default_permission": False,
+            "default_member_permissions": 8,
+            "dm_permission": True,
             "options": [
                 {
                     "type": 1,
@@ -3127,8 +3173,8 @@ def command_payload(self):
             "version": "123321123",
         }
 
-    def test_deserialize_command(self, entity_factory_impl, mock_app, command_payload):
-        command = entity_factory_impl.deserialize_command(payload=command_payload)
+    def test_deserialize_slash_command(self, entity_factory_impl, mock_app, slash_command_payload):
+        command = entity_factory_impl.deserialize_slash_command(payload=slash_command_payload)
 
         assert command.app is mock_app
         assert command.id == 1231231231
@@ -3136,7 +3182,8 @@ def test_deserialize_command(self, entity_factory_impl, mock_app, command_payloa
         assert command.guild_id == 49949494
         assert command.name == "good name"
         assert command.description == "very good description"
-        assert command.default_permission is False
+        assert command.default_member_permissions == permission_models.Permissions.ADMINISTRATOR
+        assert command.is_dm_enabled is True
         assert command.version == 123321123
 
         # CommandOption
@@ -3176,22 +3223,24 @@ def test_deserialize_command(self, entity_factory_impl, mock_app, command_payloa
         assert isinstance(option, commands.CommandOption)
         assert isinstance(command, commands.SlashCommand)
 
-    def test_deserialize_command_with_passed_through_guild_id(self, entity_factory_impl):
+    def test_deserialize_slash_command_with_passed_through_guild_id(self, entity_factory_impl):
         payload = {
             "id": "1231231231",
+            "guild_id": "987654321",
             "application_id": "12354123",
             "type": 1,
             "name": "good name",
             "description": "very good description",
             "options": [],
+            "default_member_permissions": 0,
             "version": "123312",
         }
 
-        command = entity_factory_impl.deserialize_command(payload, guild_id=123123)
+        command = entity_factory_impl.deserialize_slash_command(payload, guild_id=123123)
 
         assert command.guild_id == 123123
 
-    def test_deserialize_command_with_null_and_unset_values(self, entity_factory_impl):
+    def test_deserialize_slash_command_with_null_and_unset_values(self, entity_factory_impl):
         payload = {
             "id": "1231231231",
             "application_id": "12354123",
@@ -3200,15 +3249,49 @@ def test_deserialize_command_with_null_and_unset_values(self, entity_factory_imp
             "name": "good name",
             "description": "very good description",
             "options": [],
+            "default_member_permissions": 0,
             "version": "43123",
         }
 
-        command = entity_factory_impl.deserialize_command(payload)
+        command = entity_factory_impl.deserialize_slash_command(payload)
 
         assert command.options is None
-        assert command.default_permission is True
+        assert command.is_dm_enabled is False
         assert isinstance(command, commands.SlashCommand)
 
+    def test_deserialize_slash_command_standardizes_default_member_permissions(
+        self, entity_factory_impl, slash_command_payload
+    ):
+        slash_command_payload["default_member_permissions"] = 0
+
+        command = entity_factory_impl.deserialize_slash_command(slash_command_payload)
+
+        assert command.default_member_permissions == permission_models.Permissions.ADMINISTRATOR
+
+    @pytest.mark.parametrize(
+        ("type_", "fn"),
+        [
+            (1, "deserialize_slash_command"),
+            (2, "deserialize_context_menu_command"),
+            (3, "deserialize_context_menu_command"),
+        ],
+    )
+    def test_deserialize_command(self, mock_app, type_, fn):
+        payload = {"type": type_}
+
+        with mock.patch.object(entity_factory.EntityFactoryImpl, fn) as expected_fn:
+            # We need to instantiate it after the mock so that the functions that are stored in the dicts
+            # are the ones we mock
+            entity_factory_impl = entity_factory.EntityFactoryImpl(app=mock_app)
+
+            assert entity_factory_impl.deserialize_command(payload, guild_id=123) is expected_fn.return_value
+
+        expected_fn.assert_called_once_with(payload, guild_id=123)
+
+    def test_deserialize_command_when_unknown_type(self, entity_factory_impl):
+        with pytest.raises(errors.UnrecognisedEntityError):
+            entity_factory_impl.deserialize_command({"type": -111})
+
     @pytest.fixture()
     def guild_command_permissions_payload(self):
         return {
@@ -3309,7 +3392,7 @@ def test__deserialize_interaction_member(self, entity_factory_impl, interaction_
         assert isinstance(member, base_interactions.InteractionMember)
 
     def test__deserialize_interaction_member_when_guild_id_already_in_roles_doesnt_duplicate(
-        self, entity_factory_impl, interaction_member_payload, user_payload
+        self, entity_factory_impl, interaction_member_payload
     ):
         interaction_member_payload["roles"] = [
             582345963851743243,
@@ -3328,9 +3411,7 @@ def test__deserialize_interaction_member_when_guild_id_already_in_roles_doesnt_d
             43123123,
         ]
 
-    def test__deserialize_interaction_member_with_unset_fields(
-        self, entity_factory_impl, interaction_member_payload, user_payload
-    ):
+    def test__deserialize_interaction_member_with_unset_fields(self, entity_factory_impl, interaction_member_payload):
         del interaction_member_payload["premium_since"]
         del interaction_member_payload["avatar"]
         del interaction_member_payload["communication_disabled_until"]
@@ -3341,9 +3422,7 @@ def test__deserialize_interaction_member_with_unset_fields(
         assert member.premium_since is None
         assert member.raw_communication_disabled_until is None
 
-    def test__deserialize_interaction_member_with_passed_user(
-        self, entity_factory_impl, interaction_member_payload, user_payload
-    ):
+    def test__deserialize_interaction_member_with_passed_user(self, entity_factory_impl, interaction_member_payload):
         mock_user = object()
         member = entity_factory_impl._deserialize_interaction_member(
             interaction_member_payload, guild_id=43123123, user=mock_user
@@ -3507,17 +3586,41 @@ def test_deserialize_command_interaction(
 
         assert isinstance(interaction, command_interactions.CommandInteraction)
 
+    @pytest.fixture()
+    def context_menu_command_interaction_payload(self, interaction_member_payload, user_payload):
+        return {
+            "id": "3490190239012093",
+            "type": 4,
+            "guild_id": "43123123",
+            "data": {
+                "id": "43123123",
+                "name": "okokokok",
+                "type": 2,
+                "target_id": "115590097100865541",
+                "resolved": {
+                    "users": {
+                        "115590097100865541": user_payload,
+                    }
+                },
+            },
+            "channel_id": "49949494",
+            "member": interaction_member_payload,
+            "token": "moe cat girls",
+            "locale": "es-ES",
+            "guild_locale": "en-US",
+            "version": 69420,
+            "application_id": "76234234",
+        }
+
     def test_deserialize_command_interaction_with_context_menu_field(
-        self,
-        entity_factory_impl,
-        context_menu_command_interaction_payload,
+        self, entity_factory_impl, context_menu_command_interaction_payload
     ):
         interaction = entity_factory_impl.deserialize_command_interaction(context_menu_command_interaction_payload)
         assert interaction.target_id == 115590097100865541
         assert isinstance(interaction, command_interactions.CommandInteraction)
 
     def test_deserialize_command_interaction_with_null_attributes(
-        self, entity_factory_impl, mock_app, command_interaction_payload, user_payload
+        self, entity_factory_impl, command_interaction_payload, user_payload
     ):
         del command_interaction_payload["guild_id"]
         del command_interaction_payload["member"]
@@ -3611,7 +3714,7 @@ def test_deserialize_autocomplete_interaction(
         assert isinstance(interaction, command_interactions.AutocompleteInteraction)
 
     def test_deserialize_autocomplete_interaction_with_null_fields(
-        self, entity_factory_impl, user_payload, mock_app, autocomplete_interaction_payload
+        self, entity_factory_impl, user_payload, autocomplete_interaction_payload
     ):
         del autocomplete_interaction_payload["guild_locale"]
         del autocomplete_interaction_payload["guild_id"]
@@ -3623,86 +3726,41 @@ def test_deserialize_autocomplete_interaction_with_null_fields(
         assert interaction.user == entity_factory_impl.deserialize_user(user_payload)
         assert interaction.guild_locale is None
 
-    def test_deserialize_interaction_returns_expected_type(
-        self, entity_factory_impl, command_interaction_payload, component_interaction_payload
-    ):
-        for payload, expected_type in [
-            (command_interaction_payload, command_interactions.CommandInteraction),
-            (component_interaction_payload, component_interactions.ComponentInteraction),
-        ]:
-            assert type(entity_factory_impl.deserialize_interaction(payload)) is expected_type
+    @pytest.mark.parametrize(
+        ("type_", "fn"),
+        [
+            (2, "deserialize_command_interaction"),
+            (3, "deserialize_component_interaction"),
+            (4, "deserialize_autocomplete_interaction"),
+        ],
+    )
+    def test_deserialize_interaction(self, mock_app, type_, fn):
+        payload = {"type": type_}
+
+        with mock.patch.object(entity_factory.EntityFactoryImpl, fn) as expected_fn:
+            # We need to instantiate it after the mock so that the functions that are stored in the dicts
+            # are the ones we mock
+            entity_factory_impl = entity_factory.EntityFactoryImpl(app=mock_app)
+
+            assert entity_factory_impl.deserialize_interaction(payload) is expected_fn.return_value
+
+        expected_fn.assert_called_once_with(payload)
 
     def test_deserialize_interaction_handles_unknown_type(self, entity_factory_impl):
         with pytest.raises(errors.UnrecognisedEntityError):
             entity_factory_impl.deserialize_interaction({"type": -999})
 
-    def test_serialize_command_option_with_channel_type(self, entity_factory_impl):
+    def test_serialize_command_option(self, entity_factory_impl):
         option = commands.CommandOption(
             type=commands.OptionType.INTEGER,
             name="a name",
             description="go away",
             is_required=True,
-            channel_types=[channel_models.ChannelType.GUILD_STAGE, channel_models.ChannelType.GUILD_TEXT, 100],
-        )
-
-        result = entity_factory_impl.serialize_command_option(option)
-
-        assert result == {
-            "type": 4,
-            "name": "a name",
-            "description": "go away",
-            "required": True,
-            "channel_types": [13, 0, 100],
-        }
-
-    def test_serialize_command_option_with_min_and_max_value(self, entity_factory_impl):
-        option = commands.CommandOption(
-            type=commands.OptionType.FLOAT,
-            name="a name",
-            description="go away",
-            is_required=True,
+            autocomplete=True,
             min_value=1.2,
             max_value=9.999,
-        )
-
-        result = entity_factory_impl.serialize_command_option(option)
-
-        assert result == {
-            "type": 10,
-            "name": "a name",
-            "description": "go away",
-            "required": True,
-            "min_value": 1.2,
-            "max_value": 9.999,
-        }
-
-    def test_serialize_command_option_with_choices(self, entity_factory_impl):
-        option = commands.CommandOption(
-            type=commands.OptionType.INTEGER,
-            name="a name",
-            description="go away",
-            is_required=True,
+            channel_types=[channel_models.ChannelType.GUILD_STAGE, channel_models.ChannelType.GUILD_TEXT, 100],
             choices=[commands.CommandChoice(name="a", value="choice")],
-            options=None,
-        )
-
-        result = entity_factory_impl.serialize_command_option(option)
-
-        assert result == {
-            "type": 4,
-            "name": "a name",
-            "description": "go away",
-            "required": True,
-            "choices": [{"name": "a", "value": "choice"}],
-        }
-
-    def test_serialize_command_option_with_options(self, entity_factory_impl):
-        option = commands.CommandOption(
-            type=commands.OptionType.SUB_COMMAND,
-            name="a name",
-            description="go away",
-            is_required=True,
-            choices=None,
             options=[
                 commands.CommandOption(
                     type=commands.OptionType.STRING,
@@ -3718,10 +3776,15 @@ def test_serialize_command_option_with_options(self, entity_factory_impl):
         result = entity_factory_impl.serialize_command_option(option)
 
         assert result == {
-            "type": 1,
+            "type": 4,
             "name": "a name",
             "description": "go away",
             "required": True,
+            "channel_types": [13, 0, 100],
+            "min_value": 1.2,
+            "max_value": 9.999,
+            "autocomplete": True,
+            "choices": [{"name": "a", "value": "choice"}],
             "options": [
                 {
                     "type": 3,
@@ -3733,51 +3796,6 @@ def test_serialize_command_option_with_options(self, entity_factory_impl):
             ],
         }
 
-    def test_serialize_command_option_with_autocomplete(self, entity_factory_impl):
-        option = commands.CommandOption(
-            type=commands.OptionType.STRING,
-            name="a name",
-            description="go away",
-            is_required=True,
-            autocomplete=True,
-        )
-
-        result = entity_factory_impl.serialize_command_option(option)
-
-        assert result == {
-            "type": 3,
-            "name": "a name",
-            "description": "go away",
-            "required": True,
-            "autocomplete": True,
-        }
-
-    @pytest.fixture()
-    def context_menu_command_interaction_payload(self, interaction_member_payload, user_payload):
-        return {
-            "id": "3490190239012093",
-            "type": 4,
-            "guild_id": "43123123",
-            "data": {
-                "id": "43123123",
-                "name": "okokokok",
-                "type": 2,
-                "target_id": "115590097100865541",
-                "resolved": {
-                    "users": {
-                        "115590097100865541": user_payload,
-                    }
-                },
-            },
-            "channel_id": "49949494",
-            "member": interaction_member_payload,
-            "token": "moe cat girls",
-            "locale": "es-ES",
-            "guild_locale": "en-US",
-            "version": 69420,
-            "application_id": "76234234",
-        }
-
     @pytest.fixture()
     def context_menu_command_payload(self):
         return {
@@ -3786,16 +3804,13 @@ def context_menu_command_payload(self):
             "guild_id": "49949494",
             "type": 2,
             "name": "good name",
-            "default_permission": False,
+            "default_member_permissions": 8,
+            "dm_permission": True,
             "version": "123321123",
         }
 
-    def test_deserialize_context_menu_command(
-        self,
-        entity_factory_impl,
-        context_menu_command_payload,
-    ):
-        command = entity_factory_impl.deserialize_command(context_menu_command_payload)
+    def test_deserialize_context_menu_command(self, entity_factory_impl, context_menu_command_payload):
+        command = entity_factory_impl.deserialize_context_menu_command(context_menu_command_payload)
         assert isinstance(command, commands.ContextMenuCommand)
 
         assert command.id == 1231231231
@@ -3803,19 +3818,28 @@ def test_deserialize_context_menu_command(
         assert command.guild_id == 49949494
         assert command.type == commands.CommandType.USER
         assert command.name == "good name"
-        assert command.default_permission is False
+        assert command.default_member_permissions == permission_models.Permissions.ADMINISTRATOR
+        assert command.is_dm_enabled is True
         assert command.version == 123321123
 
-    def test_unknown_command_type(
-        self,
-        entity_factory_impl,
-        command_payload,
+    def test_deserialize_context_menu_command_with_with_null_and_unset_values(
+        self, entity_factory_impl, context_menu_command_payload
     ):
-        payload = command_payload.copy()
-        payload["type"] = 4
+        del context_menu_command_payload["dm_permission"]
 
-        with pytest.raises(errors.UnrecognisedEntityError):
-            entity_factory_impl.deserialize_command(payload)
+        command = entity_factory_impl.deserialize_context_menu_command(context_menu_command_payload)
+        assert isinstance(command, commands.ContextMenuCommand)
+
+        assert command.is_dm_enabled is False
+
+    def test_deserialize_context_menu_command_default_member_permissions(
+        self, entity_factory_impl, context_menu_command_payload
+    ):
+        context_menu_command_payload["default_member_permissions"] = 0
+
+        command = entity_factory_impl.deserialize_context_menu_command(context_menu_command_payload)
+
+        assert command.default_member_permissions == permission_models.Permissions.ADMINISTRATOR
 
     @pytest.fixture()
     def component_interaction_payload(self, interaction_member_payload, message_payload):
@@ -4415,13 +4439,25 @@ def test__deserialize_select_menu_partial(self, entity_factory_impl):
         assert menu.max_values == 1
         assert menu.is_disabled is False
 
-    def test__deserialize_component(self, entity_factory_impl, action_row_payload, button_payload, select_menu_payload):
-        for expected_type, payload in [
-            (message_models.ActionRowComponent, action_row_payload),
-            (message_models.ButtonComponent, button_payload),
-            (message_models.SelectMenuComponent, select_menu_payload),
-        ]:
-            assert type(entity_factory_impl._deserialize_component(payload)) is expected_type
+    @pytest.mark.parametrize(
+        ("type_", "fn"),
+        [
+            (1, "_deserialize_action_row"),
+            (2, "_deserialize_button"),
+            (3, "_deserialize_select_menu"),
+        ],
+    )
+    def test__deserialize_component(self, mock_app, type_, fn):
+        payload = {"type": type_}
+
+        with mock.patch.object(entity_factory.EntityFactoryImpl, fn) as expected_fn:
+            # We need to instantiate it after the mock so that the functions that are stored in the dicts
+            # are the ones we mock
+            entity_factory_impl = entity_factory.EntityFactoryImpl(app=mock_app)
+
+            assert entity_factory_impl._deserialize_component(payload) is expected_fn.return_value
+
+        expected_fn.assert_called_once_with(payload)
 
     def test__deserialize_component_handles_unknown_type(self, entity_factory_impl):
         with pytest.raises(errors.UnrecognisedEntityError):
@@ -5908,16 +5944,25 @@ def test_deserialize_application_webhook_without_optional_fields(
 
         assert webhook.avatar_hash is None
 
-    def test_deserialize_webhook(
-        self, entity_factory_impl, incoming_webhook_payload, follower_webhook_payload, application_webhook_payload
-    ):
-        for expected_type, payload in [
-            (webhook_models.IncomingWebhook, incoming_webhook_payload),
-            (webhook_models.ChannelFollowerWebhook, follower_webhook_payload),
-            (webhook_models.ApplicationWebhook, application_webhook_payload),
-        ]:
-            result = entity_factory_impl.deserialize_webhook(payload)
-            assert isinstance(result, expected_type)
+    @pytest.mark.parametrize(
+        ("type_", "fn"),
+        [
+            (1, "deserialize_incoming_webhook"),
+            (2, "deserialize_channel_follower_webhook"),
+            (3, "deserialize_application_webhook"),
+        ],
+    )
+    def test_deserialize_webhook(self, mock_app, type_, fn):
+        payload = {"type": type_}
+
+        with mock.patch.object(entity_factory.EntityFactoryImpl, fn) as expected_fn:
+            # We need to instantiate it after the mock so that the functions that are stored in the dicts
+            # are the ones we mock
+            entity_factory_impl = entity_factory.EntityFactoryImpl(app=mock_app)
+
+            assert entity_factory_impl.deserialize_webhook(payload) is expected_fn.return_value
+
+        expected_fn.assert_called_once_with(payload)
 
     def test_deserialize_webhook_for_unexpected_webhook_type(self, entity_factory_impl):
         with pytest.raises(errors.UnrecognisedEntityError):
diff --git a/tests/hikari/impl/test_event_factory.py b/tests/hikari/impl/test_event_factory.py
index 1cf46829..e269c9d0 100644
--- a/tests/hikari/impl/test_event_factory.py
+++ b/tests/hikari/impl/test_event_factory.py
@@ -29,6 +29,7 @@
 from hikari import traits
 from hikari import undefined
 from hikari import users as user_models
+from hikari.events import application_events
 from hikari.events import channel_events
 from hikari.events import guild_events
 from hikari.events import interaction_events
@@ -58,13 +59,28 @@ def mock_shard(self):
     def event_factory(self, mock_app):
         return event_factory_.EventFactoryImpl(mock_app)
 
+    ######################
+    # APPLICATION EVENTS #
+    ######################
+
+    def test_deserialize_application_command_permission_update_event(self, event_factory, mock_app, mock_shard):
+        mock_payload = object()
+
+        event = event_factory.deserialize_application_command_permission_update_event(mock_shard, mock_payload)
+
+        mock_app.entity_factory.deserialize_guild_command_permissions.assert_called_once_with(mock_payload)
+        assert isinstance(event, application_events.ApplicationCommandPermissionsUpdateEvent)
+        assert event.app is mock_app
+        assert event.shard is mock_shard
+        assert event.permissions is mock_app.entity_factory.deserialize_guild_command_permissions.return_value
+
     ##################
     # CHANNEL EVENTS #
     ##################
 
     def test_deserialize_guild_channel_create_event(self, event_factory, mock_app, mock_shard):
         mock_app.entity_factory.deserialize_channel.return_value = mock.Mock(spec=channel_models.GuildChannel)
-        mock_payload = mock.Mock(app=mock_app)
+        mock_payload = object()
 
         event = event_factory.deserialize_guild_channel_create_event(mock_shard, mock_payload)
 
diff --git a/tests/hikari/impl/test_event_manager.py b/tests/hikari/impl/test_event_manager.py
index 351b3787..b82e6c49 100644
--- a/tests/hikari/impl/test_event_manager.py
+++ b/tests/hikari/impl/test_event_manager.py
@@ -147,6 +147,17 @@ async def test_on_resumed(self, event_manager_impl, shard, event_factory):
         event_factory.deserialize_resumed_event.assert_called_once_with(shard)
         event_manager_impl.dispatch.assert_awaited_once_with(event_factory.deserialize_resumed_event.return_value)
 
+    @pytest.mark.asyncio()
+    async def test_on_application_command_permissions_update(self, event_manager_impl, shard, event_factory):
+        payload = {}
+
+        await event_manager_impl.on_application_command_permissions_update(shard, payload)
+
+        event_factory.deserialize_application_command_permission_update_event.assert_called_once_with(shard, payload)
+        event_manager_impl.dispatch.assert_awaited_once_with(
+            event_factory.deserialize_application_command_permission_update_event.return_value
+        )
+
     @pytest.mark.asyncio()
     async def test_on_channel_create_stateful(self, event_manager_impl, shard, event_factory):
         payload = {}
diff --git a/tests/hikari/impl/test_rest.py b/tests/hikari/impl/test_rest.py
index 21ef655a..be1e20ae 100644
--- a/tests/hikari/impl/test_rest.py
+++ b/tests/hikari/impl/test_rest.py
@@ -4754,33 +4754,33 @@ async def test_fetch_application_commands_without_guild(self, rest_client):
         rest_client._request.assert_awaited_once_with(expected_route)
         rest_client._entity_factory.deserialize_command.assert_called_once_with({"id": "34512312"}, guild_id=None)
 
-    async def test_create_application_command_with_optionals(self, rest_client: rest.RESTClientImpl):
+    async def test__create_application_command_with_optionals(self, rest_client: rest.RESTClientImpl):
         expected_route = routes.POST_APPLICATION_GUILD_COMMAND.compile(application=4332123, guild=653452134)
         rest_client._request = mock.AsyncMock(return_value={"id": "29393939"})
         mock_option = object()
 
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", category=DeprecationWarning)
-            result = await rest_client.create_application_command(
-                application=StubModel(4332123),
-                guild=StubModel(653452134),
-                name="okokok",
-                description="not ok anymore",
-                options=[mock_option],
-            )
+        result = await rest_client._create_application_command(
+            application=StubModel(4332123),
+            type=100,
+            name="okokok",
+            description="not ok anymore",
+            guild=StubModel(653452134),
+            options=[mock_option],
+            default_member_permissions=permissions.Permissions.ADMINISTRATOR,
+            dm_enabled=False,
+        )
 
-        assert result is rest_client._entity_factory.deserialize_slash_command.return_value
+        assert result is rest_client._request.return_value
         rest_client._entity_factory.serialize_command_option.assert_called_once_with(mock_option)
-        rest_client._entity_factory.deserialize_slash_command.assert_called_once_with(
-            rest_client._request.return_value, guild_id=653452134
-        )
         rest_client._request.assert_awaited_once_with(
             expected_route,
             json={
-                "type": 1,
+                "type": 100,
                 "name": "okokok",
                 "description": "not ok anymore",
                 "options": [rest_client._entity_factory.serialize_command_option.return_value],
+                "default_member_permissions": 8,
+                "dm_permission": False,
             },
         )
 
@@ -4788,47 +4788,102 @@ async def test_create_application_command_without_optionals(self, rest_client: r
         expected_route = routes.POST_APPLICATION_COMMAND.compile(application=4332123)
         rest_client._request = mock.AsyncMock(return_value={"id": "29393939"})
 
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore", category=DeprecationWarning)
-            result = await rest_client.create_application_command(
-                StubModel(4332123),
-                name="okokok",
-                description="not ok anymore",
-            )
-
-        assert result is rest_client._entity_factory.deserialize_slash_command.return_value
-        rest_client._entity_factory.deserialize_slash_command.assert_called_once_with(
-            rest_client._request.return_value, guild_id=None
+        result = await rest_client._create_application_command(
+            application=StubModel(4332123), type=100, name="okokok", description="not ok anymore"
         )
+
+        assert result is rest_client._request.return_value
         rest_client._request.assert_awaited_once_with(
-            expected_route, json={"type": 1, "name": "okokok", "description": "not ok anymore"}
+            expected_route,
+            json={
+                "type": 100,
+                "name": "okokok",
+                "description": "not ok anymore",
+            },
         )
 
-    async def test_create_slash_command(self, rest_client: rest.RESTClientImpl):
+    async def test__create_application_command_standardizes_default_member_permissions(
+        self, rest_client: rest.RESTClientImpl
+    ):
         expected_route = routes.POST_APPLICATION_COMMAND.compile(application=4332123)
         rest_client._request = mock.AsyncMock(return_value={"id": "29393939"})
 
-        result = await rest_client.create_slash_command(StubModel(4332123), "okokok", "not ok anymore")
+        result = await rest_client._create_application_command(
+            application=StubModel(4332123),
+            type=100,
+            name="okokok",
+            description="not ok anymore",
+            default_member_permissions=permissions.Permissions.NONE,
+        )
+
+        assert result is rest_client._request.return_value
+        rest_client._request.assert_awaited_once_with(
+            expected_route,
+            json={
+                "type": 100,
+                "name": "okokok",
+                "description": "not ok anymore",
+                "default_member_permissions": None,
+            },
+        )
+
+    async def test_create_slash_command(self, rest_client: rest.RESTClientImpl):
+        rest_client._create_application_command = mock.AsyncMock()
+        mock_options = object()
+        mock_application = StubModel(4332123)
+        mock_guild = StubModel(123123123)
+
+        result = await rest_client.create_slash_command(
+            mock_application,
+            "okokok",
+            "not ok anymore",
+            guild=mock_guild,
+            options=mock_options,
+            default_member_permissions=permissions.Permissions.ADMINISTRATOR,
+            dm_enabled=False,
+        )
 
         assert result is rest_client._entity_factory.deserialize_slash_command.return_value
         rest_client._entity_factory.deserialize_slash_command.assert_called_once_with(
-            rest_client._request.return_value, guild_id=None
+            rest_client._create_application_command.return_value, guild_id=123123123
         )
-        rest_client._request.assert_awaited_once_with(
-            expected_route, json={"type": 1, "name": "okokok", "description": "not ok anymore"}
+        rest_client._create_application_command.assert_awaited_once_with(
+            application=mock_application,
+            type=commands.CommandType.SLASH,
+            name="okokok",
+            description="not ok anymore",
+            guild=mock_guild,
+            options=mock_options,
+            default_member_permissions=permissions.Permissions.ADMINISTRATOR,
+            dm_enabled=False,
         )
 
     async def test_create_context_menu_command(self, rest_client: rest.RESTClientImpl):
-        expected_route = routes.POST_APPLICATION_COMMAND.compile(application=4332123)
-        rest_client._request = mock.AsyncMock(return_value={"id": "29393939"})
+        rest_client._create_application_command = mock.AsyncMock()
+        mock_application = StubModel(4332123)
+        mock_guild = StubModel(123123123)
 
-        result = await rest_client.create_context_menu_command(StubModel(4332123), 2, "okokok")
+        result = await rest_client.create_context_menu_command(
+            mock_application,
+            commands.CommandType.USER,
+            "okokok",
+            guild=mock_guild,
+            default_member_permissions=permissions.Permissions.ADMINISTRATOR,
+            dm_enabled=False,
+        )
 
         assert result is rest_client._entity_factory.deserialize_context_menu_command.return_value
         rest_client._entity_factory.deserialize_context_menu_command.assert_called_once_with(
-            rest_client._request.return_value, guild_id=None
+            rest_client._create_application_command.return_value, guild_id=123123123
+        )
+        rest_client._create_application_command.assert_awaited_once_with(
+            application=mock_application,
+            type=commands.CommandType.USER,
+            name="okokok",
+            guild=mock_guild,
+            default_member_permissions=permissions.Permissions.ADMINISTRATOR,
+            dm_enabled=False,
         )
-        rest_client._request.assert_awaited_once_with(expected_route, json={"type": 2, "name": "okokok"})
 
     async def test_set_application_commands_with_guild(self, rest_client):
         expected_route = routes.PUT_APPLICATION_GUILD_COMMANDS.compile(application=4321231, guild=6543234)
@@ -4870,6 +4925,8 @@ async def test_edit_application_command_with_optionals(self, rest_client):
             name="ok sis",
             description="cancelled",
             options=[mock_option],
+            default_member_permissions=permissions.Permissions.BAN_MEMBERS,
+            dm_enabled=True,
         )
 
         assert result is rest_client._entity_factory.deserialize_command.return_value
@@ -4882,6 +4939,8 @@ async def test_edit_application_command_with_optionals(self, rest_client):
                 "name": "ok sis",
                 "description": "cancelled",
                 "options": [rest_client._entity_factory.serialize_command_option.return_value],
+                "default_member_permissions": 4,
+                "dm_permission": True,
             },
         )
         rest_client._entity_factory.serialize_command_option.assert_called_once_with(mock_option)
@@ -4901,6 +4960,27 @@ async def test_edit_application_command_without_optionals(self, rest_client):
         )
         rest_client._request.assert_awaited_once_with(expected_route, json={})
 
+    async def test_edit_application_command_standardizes_default_member_permissions(
+        self, rest_client: rest.RESTClientImpl
+    ):
+        expected_route = routes.PATCH_APPLICATION_COMMAND.compile(application=1235432, command=3451231)
+        rest_client._request = mock.AsyncMock(return_value={"id": "94594994"})
+
+        result = await rest_client.edit_application_command(
+            StubModel(1235432),
+            StubModel(3451231),
+            default_member_permissions=permissions.Permissions.NONE,
+        )
+
+        assert result is rest_client._entity_factory.deserialize_command.return_value
+        rest_client._entity_factory.deserialize_command.assert_called_once_with(
+            rest_client._request.return_value, guild_id=None
+        )
+        rest_client._request.assert_awaited_once_with(
+            expected_route,
+            json={"default_member_permissions": None},
+        )
+
     async def test_delete_application_command_with_guild(self, rest_client):
         expected_route = routes.DELETE_APPLICATION_GUILD_COMMAND.compile(
             application=312312, command=65234323, guild=5421312
@@ -4943,29 +5023,6 @@ async def test_fetch_application_command_permissions(self, rest_client):
         rest_client._entity_factory.deserialize_guild_command_permissions.assert_called_once_with(mock_command_payload)
         rest_client._request.assert_awaited_once_with(expected_route)
 
-    async def test_set_application_guild_commands_permissions(self, rest_client):
-        expected_route = routes.PUT_APPLICATION_GUILD_COMMANDS_PERMISSIONS.compile(application=321123, guild=542123)
-        mock_command_payload = object()
-        mock_permission = object()
-        rest_client._request = mock.AsyncMock(return_value=[mock_command_payload])
-
-        result = await rest_client.set_application_guild_commands_permissions(
-            321123, 542123, {564123123: [mock_permission]}
-        )
-
-        assert result == [rest_client._entity_factory.deserialize_guild_command_permissions.return_value]
-        rest_client._entity_factory.serialize_command_permission.assert_called_once_with(mock_permission)
-        rest_client._entity_factory.deserialize_guild_command_permissions.assert_called_once_with(mock_command_payload)
-        rest_client._request.assert_awaited_once_with(
-            expected_route,
-            json=[
-                {
-                    "id": "564123123",
-                    "permissions": [rest_client._entity_factory.serialize_command_permission.return_value],
-                }
-            ],
-        )
-
     async def test_set_application_command_permissions(self, rest_client):
         route = routes.PUT_APPLICATION_COMMAND_PERMISSIONS.compile(application=2321, guild=431, command=666666)
         mock_permission = object()
diff --git a/tests/hikari/impl/test_shard.py b/tests/hikari/impl/test_shard.py
index 18d3f1fc..b964581d 100644
--- a/tests/hikari/impl/test_shard.py
+++ b/tests/hikari/impl/test_shard.py
@@ -1115,9 +1115,9 @@ async def test__identify(self, client):
                 "compress": False,
                 "large_threshold": 123,
                 "properties": {
-                    "$os": "Potato PC ARM64",
-                    "$browser": "hikari (v1.0.0, aiohttp v0.0.1)",
-                    "$device": "hikari v1.0.0",
+                    "os": "Potato PC ARM64",
+                    "browser": "hikari (v1.0.0, aiohttp v0.0.1)",
+                    "device": "hikari v1.0.0",
                 },
                 "shard": [0, 1],
                 "intents": 131071,
diff --git a/tests/hikari/impl/test_special_endpoints.py b/tests/hikari/impl/test_special_endpoints.py
index 971dc1b3..aecbf662 100644
--- a/tests/hikari/impl/test_special_endpoints.py
+++ b/tests/hikari/impl/test_special_endpoints.py
@@ -27,6 +27,7 @@
 from hikari import emojis
 from hikari import files
 from hikari import messages
+from hikari import permissions
 from hikari import snowflakes
 from hikari import undefined
 from hikari.impl import special_endpoints
@@ -657,10 +658,17 @@ def test_id_property(self):
 
         assert builder.id == 3212123
 
-    def test_default_permission(self):
-        builder = special_endpoints.SlashCommandBuilder("oksksksk", "kfdkodfokfd").set_default_permission(True)
+    def test_default_member_permissions(self):
+        builder = special_endpoints.SlashCommandBuilder("oksksksk", "kfdkodfokfd").set_default_member_permissions(
+            permissions.Permissions.ADMINISTRATOR
+        )
+
+        assert builder.default_member_permissions == permissions.Permissions.ADMINISTRATOR
+
+    def test_is_dm_enabled(self):
+        builder = special_endpoints.SlashCommandBuilder("oksksksk", "kfdkodfokfd").set_is_dm_enabled(True)
 
-        assert builder.default_permission is True
+        assert builder.is_dm_enabled is True
 
     def test_build_with_optional_data(self):
         mock_entity_factory = mock.Mock()
@@ -669,7 +677,8 @@ def test_build_with_optional_data(self):
             special_endpoints.SlashCommandBuilder("we are number", "one")
             .add_option(mock_option)
             .set_id(3412312)
-            .set_default_permission(False)
+            .set_default_member_permissions(permissions.Permissions.ADMINISTRATOR)
+            .set_is_dm_enabled(True)
         )
 
         result = builder.build(mock_entity_factory)
@@ -679,7 +688,8 @@ def test_build_with_optional_data(self):
             "name": "we are number",
             "description": "one",
             "type": 1,
-            "default_permission": False,
+            "dm_permission": True,
+            "default_member_permissions": 8,
             "options": [mock_entity_factory.serialize_command_option.return_value],
             "id": "3412312",
         }
@@ -696,8 +706,8 @@ async def test_create(self):
         builder = (
             special_endpoints.SlashCommandBuilder("we are number", "one")
             .add_option(mock.Mock())
-            .set_id(3412312)
-            .set_default_permission(False)
+            .set_default_member_permissions(permissions.Permissions.BAN_MEMBERS)
+            .set_is_dm_enabled(True)
         )
         mock_rest = mock.AsyncMock()
 
@@ -709,13 +719,18 @@ async def test_create(self):
             builder.name,
             builder.description,
             guild=undefined.UNDEFINED,
-            default_permission=builder.default_permission,
             options=builder.options,
+            default_member_permissions=permissions.Permissions.BAN_MEMBERS,
+            dm_enabled=True,
         )
 
     @pytest.mark.asyncio()
     async def test_create_with_guild(self):
-        builder = special_endpoints.SlashCommandBuilder("we are number", "one")
+        builder = (
+            special_endpoints.SlashCommandBuilder("we are number", "one")
+            .set_default_member_permissions(permissions.Permissions.BAN_MEMBERS)
+            .set_is_dm_enabled(True)
+        )
         mock_rest = mock.AsyncMock()
 
         result = await builder.create(mock_rest, 54455445, guild=54123123321)
@@ -726,8 +741,9 @@ async def test_create_with_guild(self):
             builder.name,
             builder.description,
             guild=54123123321,
-            default_permission=builder.default_permission,
             options=builder.options,
+            default_member_permissions=permissions.Permissions.BAN_MEMBERS,
+            dm_enabled=True,
         )
 
 
@@ -736,7 +752,8 @@ def test_build_with_optional_data(self):
         builder = (
             special_endpoints.ContextMenuCommandBuilder(commands.CommandType.USER, "we are number")
             .set_id(3412312)
-            .set_default_permission(False)
+            .set_default_member_permissions(permissions.Permissions.ADMINISTRATOR)
+            .set_is_dm_enabled(True)
         )
 
         result = builder.build(mock.Mock())
@@ -744,7 +761,8 @@ def test_build_with_optional_data(self):
         assert result == {
             "name": "we are number",
             "type": 2,
-            "default_permission": False,
+            "dm_permission": True,
+            "default_member_permissions": 8,
             "id": "3412312",
         }
 
@@ -759,8 +777,8 @@ def test_build_without_optional_data(self):
     async def test_create(self):
         builder = (
             special_endpoints.ContextMenuCommandBuilder(commands.CommandType.USER, "we are number")
-            .set_id(3412312)
-            .set_default_permission(False)
+            .set_default_member_permissions(permissions.Permissions.BAN_MEMBERS)
+            .set_is_dm_enabled(True)
         )
         mock_rest = mock.AsyncMock()
 
@@ -772,12 +790,17 @@ async def test_create(self):
             builder.type,
             builder.name,
             guild=undefined.UNDEFINED,
-            default_permission=builder.default_permission,
+            default_member_permissions=permissions.Permissions.BAN_MEMBERS,
+            dm_enabled=True,
         )
 
     @pytest.mark.asyncio()
     async def test_create_with_guild(self):
-        builder = special_endpoints.ContextMenuCommandBuilder(commands.CommandType.MESSAGE, "we are number")
+        builder = (
+            special_endpoints.ContextMenuCommandBuilder(commands.CommandType.USER, "we are number")
+            .set_default_member_permissions(permissions.Permissions.BAN_MEMBERS)
+            .set_is_dm_enabled(True)
+        )
         mock_rest = mock.AsyncMock()
 
         result = await builder.create(mock_rest, 4444444, guild=765234123)
@@ -788,7 +811,8 @@ async def test_create_with_guild(self):
             builder.type,
             builder.name,
             guild=765234123,
-            default_permission=builder.default_permission,
+            default_member_permissions=permissions.Permissions.BAN_MEMBERS,
+            dm_enabled=True,
         )
 
 
diff --git a/tests/hikari/test_commands.py b/tests/hikari/test_commands.py
index 19b4861d..76117ec9 100644
--- a/tests/hikari/test_commands.py
+++ b/tests/hikari/test_commands.py
@@ -43,7 +43,8 @@ def mock_command(self, mock_app):
             type=commands.CommandType.SLASH,
             application_id=snowflakes.Snowflake(65234123),
             name="Name",
-            default_permission=False,
+            default_member_permissions=None,
+            is_dm_enabled=False,
             guild_id=snowflakes.Snowflake(31231235),
             version=snowflakes.Snowflake(43123123),
         )