Repository: hikari-py/hikari
Pull request #1337 (2022-10-28 17:04:23)

Catch UnrecognisedEntityErrors in rest list methods
### Summary
<!-- Small summary of the merge request -->

### Checklist
<!-- Make sure to tick all the following boxes by putting an `x` in between (like this `[x]`) -->
- [ ] I have run `nox` and all the pipelines have passed.
- [ ] I have made unittests according to the code I have added/modified/deleted.

### Related issues
<!--
To mention an issue use `#issue-id` and to mention a merge request use `!merge-request-id`
To close/fix an issue use `Close #issue-id` or `Fix #issue-id` (depending on the merge request)
-->



Patch:
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..6313b56c
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,1 @@
+* text=auto eol=lf
diff --git a/changes/1330.doc.md b/changes/1330.doc.md
new file mode 100644
index 00000000..2a6313d5
--- /dev/null
+++ b/changes/1330.doc.md
@@ -0,0 +1,1 @@
+Support specifying `with_counts` and `with_expiration` in `RESTClient.fetch_invite`
diff --git a/changes/1334.feature.md b/changes/1334.feature.md
new file mode 100644
index 00000000..cd6bbbb0
--- /dev/null
+++ b/changes/1334.feature.md
@@ -0,0 +1,1 @@
+Add `MANAGE_EVENTS` permission to `hikari.Permissions`
diff --git a/changes/1337.bugfix.md b/changes/1337.bugfix.md
new file mode 100644
index 00000000..c84a2e95
--- /dev/null
+++ b/changes/1337.bugfix.md
@@ -0,0 +1,1 @@
+The REST list methods (e.g. `fetch_channels`) no-longer raise `hikari.errors.UnrecognisedEntityError` when they encounter an unknown type.
diff --git a/dev-requirements/flake8.txt b/dev-requirements/flake8.txt
index 472b8d20..be66ef79 100644
--- a/dev-requirements/flake8.txt
+++ b/dev-requirements/flake8.txt
@@ -6,9 +6,9 @@ flake8==5.0.4
 flake8-bandit~=4.1.1                    # runs bandit
 flake8-black==0.3.3                     # runs black
 flake8-broken-line==0.6.0               # forbey "\" linebreaks
-flake8-builtins==2.0.0                  # builtin shadowing checks
+flake8-builtins==2.0.1                  # builtin shadowing checks
 flake8-coding==1.3.2                    # coding magic-comment detection
-flake8-comprehensions==3.10.0           # comprehension checks
+flake8-comprehensions==3.10.1           # comprehension checks
 flake8-docstrings==1.6.0                # pydocstyle support
 flake8-executable==2.1.2                # shebangs
 flake8-fixme==1.1.1                     # "fix me" counter
diff --git a/dev-requirements/pyright.txt b/dev-requirements/pyright.txt
index 3e2d420b..bd16c09e 100644
--- a/dev-requirements/pyright.txt
+++ b/dev-requirements/pyright.txt
@@ -1,1 +1,1 @@
-pyright==1.1.277
+pyright==1.1.278
diff --git a/dev-requirements/slotscheck.txt b/dev-requirements/slotscheck.txt
index 8f35fb09..aca35f68 100644
--- a/dev-requirements/slotscheck.txt
+++ b/dev-requirements/slotscheck.txt
@@ -1,1 +1,1 @@
-slotscheck==0.15.0
+slotscheck==0.16.0
diff --git a/hikari/api/entity_factory.py b/hikari/api/entity_factory.py
index c758c064..361efbc3 100644
--- a/hikari/api/entity_factory.py
+++ b/hikari/api/entity_factory.py
@@ -1227,6 +1227,11 @@ def deserialize_command(
             If `guild_id` is left as `hikari.undefined.UNDEFINED` when
             `"guild_id"` is not present in the passed payload for the payload of
             the integration.
+
+        Raises
+        ------
+        hikari.errors.UnrecognisedEntityError
+            If the command type is unknown.
         """
 
     @abc.abstractmethod
@@ -1609,6 +1614,11 @@ def deserialize_scheduled_event(self, payload: data_binding.JSONObject) -> sched
         -------
         hikari.scheduled_events.ScheduledEvent
             The deserialized scheduled event object.
+
+        Raises
+        ------
+        hikari.errors.UnrecognisedEntityError
+            If the scheduled event type is unknown.
         """
 
     @abc.abstractmethod
@@ -1820,4 +1830,9 @@ def deserialize_webhook(self, payload: data_binding.JSONObject) -> webhook_model
         -------
         hikari.webhooks.PartialWebhook
             The deserialized webhook object.
+
+        Raises
+        ------
+        hikari.errors.UnrecognisedEntityError
+            If the channel type is unknown.
         """
diff --git a/hikari/api/rest.py b/hikari/api/rest.py
index 38e1597e..fea1d4fb 100644
--- a/hikari/api/rest.py
+++ b/hikari/api/rest.py
@@ -2765,7 +2765,9 @@ async def fetch_gateway_bot_info(self) -> sessions.GatewayBotInfo:
         """
 
     @abc.abstractmethod
-    async def fetch_invite(self, invite: typing.Union[invites.InviteCode, str]) -> invites.Invite:
+    async def fetch_invite(
+        self, invite: typing.Union[invites.InviteCode, str], with_counts: bool = True, with_expiration: bool = True
+    ) -> invites.Invite:
         """Fetch an existing invite.
 
         Parameters
@@ -2773,6 +2775,14 @@ async def fetch_invite(self, invite: typing.Union[invites.InviteCode, str]) -> i
         invite : typing.Union[hikari.invites.InviteCode, builtins.str]
             The invite to fetch. This may be an invite object or
             the code of an existing invite.
+        with_counts : builtins.bool
+            Whether the invite should contain the approximate member counts.
+
+            Defaults to `builtins.True`.
+        with_expiration: builtins.bool
+            Whether the invite should contain the expiration date.
+
+            Defaults to `builtins.True`.
 
         Returns
         -------
diff --git a/hikari/impl/.gitattributes b/hikari/impl/.gitattributes
deleted file mode 100644
index fcadb2cf..00000000
--- a/hikari/impl/.gitattributes
+++ /dev/null
@@ -1,1 +0,0 @@
-* text eol=lf
diff --git a/hikari/impl/entity_factory.py b/hikari/impl/entity_factory.py
index 8d31ceda..6e07f4bd 100644
--- a/hikari/impl/entity_factory.py
+++ b/hikari/impl/entity_factory.py
@@ -2560,15 +2560,7 @@ def deserialize_guild_sticker(self, payload: data_binding.JSONObject) -> sticker
     ##################
 
     def _deserialize_action_row(self, payload: data_binding.JSONObject) -> message_models.ActionRowComponent:
-        components: typing.List[message_models.PartialComponent] = []
-
-        for component_payload in payload["components"]:
-            try:
-                components.append(self._deserialize_component(component_payload))
-
-            except errors.UnrecognisedEntityError:
-                pass
-
+        components = data_binding.cast_variants_array(self._deserialize_component, payload["components"])
         return message_models.ActionRowComponent(
             type=message_models.ComponentType(payload["type"]), components=components
         )
@@ -2759,13 +2751,7 @@ def deserialize_partial_message(  # noqa CFQ001 - Function too long
 
         components: undefined.UndefinedOr[typing.List[message_models.PartialComponent]] = undefined.UNDEFINED
         if component_payloads := payload.get("components"):
-            components = []
-            for component_payload in component_payloads:
-                try:
-                    components.append(self._deserialize_component(component_payload))
-
-                except errors.UnrecognisedEntityError:
-                    pass
+            components = data_binding.cast_variants_array(self._deserialize_component, component_payloads)
 
         channel_mentions: undefined.UndefinedOr[
             typing.Dict[snowflakes.Snowflake, channel_models.PartialChannel]
@@ -2873,14 +2859,11 @@ def deserialize_message(
         if interaction_payload := payload.get("interaction"):
             interaction = self._deserialize_message_interaction(interaction_payload)
 
-        components: typing.List[message_models.PartialComponent] = []
         if component_payloads := payload.get("components"):
-            for component_payload in component_payloads:
-                try:
-                    components.append(self._deserialize_component(component_payload))
+            components = data_binding.cast_variants_array(self._deserialize_component, component_payloads)
 
-                except errors.UnrecognisedEntityError:
-                    pass
+        else:
+            components = []
 
         user_mentions = {u.id: u for u in map(self.deserialize_user, payload.get("mentions", ()))}
         role_mention_ids = [snowflakes.Snowflake(i) for i in payload.get("mention_roles", ())]
diff --git a/hikari/impl/rest.py b/hikari/impl/rest.py
index 80f5160e..85c843c5 100644
--- a/hikari/impl/rest.py
+++ b/hikari/impl/rest.py
@@ -1753,7 +1753,7 @@ async def fetch_channel_webhooks(
         route = routes.GET_CHANNEL_WEBHOOKS.compile(channel=channel)
         response = await self._request(route)
         assert isinstance(response, list)
-        return [self._entity_factory.deserialize_webhook(webhook_pl) for webhook_pl in response]
+        return data_binding.cast_variants_array(self._entity_factory.deserialize_webhook, response)
 
     async def fetch_guild_webhooks(
         self,
@@ -1762,7 +1762,7 @@ async def fetch_guild_webhooks(
         route = routes.GET_GUILD_WEBHOOKS.compile(guild=guild)
         response = await self._request(route)
         assert isinstance(response, list)
-        return [self._entity_factory.deserialize_webhook(webhook_payload) for webhook_payload in response]
+        return data_binding.cast_variants_array(self._entity_factory.deserialize_webhook, response)
 
     async def edit_webhook(
         self,
@@ -1982,11 +1982,13 @@ async def fetch_gateway_bot_info(self) -> sessions.GatewayBotInfo:
         assert isinstance(response, dict)
         return self._entity_factory.deserialize_gateway_bot_info(response)
 
-    async def fetch_invite(self, invite: typing.Union[invites.InviteCode, str]) -> invites.Invite:
+    async def fetch_invite(
+        self, invite: typing.Union[invites.InviteCode, str], with_counts: bool = True, with_expiration: bool = True
+    ) -> invites.Invite:
         route = routes.GET_INVITE.compile(invite_code=invite if isinstance(invite, str) else invite.code)
         query = data_binding.StringMapBuilder()
-        query.put("with_counts", True)
-        query.put("with_expiration", True)
+        query.put("with_counts", with_counts)
+        query.put("with_expiration", with_expiration)
         response = await self._request(route, query=query)
         assert isinstance(response, dict)
         return self._entity_factory.deserialize_invite(response)
@@ -2583,9 +2585,9 @@ async def fetch_guild_channels(
         route = routes.GET_GUILD_CHANNELS.compile(guild=guild)
         response = await self._request(route)
         assert isinstance(response, list)
-        channel_sequence = [self._entity_factory.deserialize_channel(channel_payload) for channel_payload in response]
+        channels = data_binding.cast_variants_array(self._entity_factory.deserialize_channel, response)
         # Will always be guild channels unless Discord messes up severely on something!
-        return typing.cast("typing.Sequence[channels_.GuildChannel]", channel_sequence)
+        return typing.cast("typing.Sequence[channels_.GuildChannel]", channels)
 
     async def create_guild_text_channel(
         self,
@@ -3712,6 +3714,19 @@ async def fetch_application_command(
             response, guild_id=snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
         )
 
+    def _deserialize_command_list(
+        self, command_payloads: data_binding.JSONArray, guild_id: typing.Optional[snowflakes.Snowflake]
+    ) -> typing.List[commands.PartialCommand]:
+        command_objs: typing.List[commands.PartialCommand] = []
+        for payload in command_payloads:
+            try:
+                command_objs.append(self._entity_factory.deserialize_command(payload, guild_id=guild_id))
+
+            except errors.UnrecognisedEntityError:
+                pass
+
+        return command_objs
+
     async def fetch_application_commands(
         self,
         application: snowflakes.SnowflakeishOr[guilds.PartialApplication],
@@ -3729,7 +3744,7 @@ async def fetch_application_commands(
         response = await self._request(route, query=query)
         assert isinstance(response, list)
         guild_id = snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
-        return [self._entity_factory.deserialize_command(command, guild_id=guild_id) for command in response]
+        return self._deserialize_command_list(response, guild_id)
 
     async def _create_application_command(
         self,
@@ -3852,7 +3867,7 @@ async def set_application_commands(
         response = await self._request(route, json=[command.build(self._entity_factory) for command in commands])
         assert isinstance(response, list)
         guild_id = snowflakes.Snowflake(guild) if guild is not undefined.UNDEFINED else None
-        return [self._entity_factory.deserialize_command(payload, guild_id=guild_id) for payload in response]
+        return self._deserialize_command_list(response, guild_id)
 
     async def edit_application_command(
         self,
@@ -4123,7 +4138,7 @@ async def fetch_scheduled_events(
         response = await self._request(route, query=query)
 
         assert isinstance(response, list)
-        return [self._entity_factory.deserialize_scheduled_event(event) for event in response]
+        return data_binding.cast_variants_array(self._entity_factory.deserialize_scheduled_event, response)
 
     async def _create_or_edit_scheduled_stage(
         self,
diff --git a/hikari/internal/data_binding.py b/hikari/internal/data_binding.py
index 90017e8d..40b8613e 100644
--- a/hikari/internal/data_binding.py
+++ b/hikari/internal/data_binding.py
@@ -41,6 +41,7 @@
 import aiohttp
 import multidict
 
+from hikari import errors
 from hikari import files
 from hikari import snowflakes
 from hikari import undefined
@@ -50,6 +51,7 @@
     import contextlib
 
     T_co = typing.TypeVar("T_co", covariant=True)
+    T = typing.TypeVar("T")
 
 Headers = typing.Mapping[str, str]
 """Type hint for HTTP headers."""
@@ -392,3 +394,33 @@ def put_snowflake_array(
         """  # noqa: E501 - Line too long
         if values is not undefined.UNDEFINED:
             self[key] = [str(int(value)) for value in values]
+
+
+def cast_variants_array(cast: typing.Callable[[T_co], T], raw_values: typing.Iterable[T_co], /) -> typing.List[T]:
+    """Cast an array of enum variants while ignoring unrecognised variant types.
+
+    Parameters
+    ----------
+    cast : typing.Callable[[T_co], T]
+        Callback to cast each variant to.
+
+        This will ignore any variants which raises
+        `hikari.errors.UnrecognisedEntityError` on cast.
+    raw_values : typing.Iterable[T_co]
+        Iterable of the raw values to cast.
+
+    Returns
+    -------
+    typing.List[T]
+        A list of the casted variants (with any unrecognised types ignored).
+    """
+    results: typing.List[T] = []
+
+    for value in raw_values:
+        try:
+            results.append(cast(value))
+
+        except errors.UnrecognisedEntityError:
+            pass
+
+    return results
diff --git a/hikari/permissions.py b/hikari/permissions.py
index 86808fb6..ef8f06a6 100644
--- a/hikari/permissions.py
+++ b/hikari/permissions.py
@@ -246,6 +246,9 @@ class Permissions(enums.Flag):
         without warning.
     """
 
+    MANAGE_EVENTS = 1 << 33
+    """Allows for creating, editing, and deleting scheduled events	"""
+
     MANAGE_THREADS = 1 << 34
     """Allows for deleting and archiving threads, and viewing all private threads.
 


Test patch:
diff --git a/tests/hikari/impl/test_rest.py b/tests/hikari/impl/test_rest.py
index ea94ca0f..c3d2cd6f 100644
--- a/tests/hikari/impl/test_rest.py
+++ b/tests/hikari/impl/test_rest.py
@@ -1979,7 +1979,6 @@ class StubResponse:
 
         await rest_client._parse_ratelimits(route, response, live_attributes)
 
-        assert live_attributes.still_alive.call_count == 1
         live_attributes.buckets.update_rate_limits.assert_called_once_with(
             compiled_route=route,
             bucket_header="bucket_header",
@@ -2001,7 +2000,7 @@ class StubResponse:
         await rest_client._parse_ratelimits(route, response, live_attributes)
 
         response.json.assert_not_called()
-        assert live_attributes.still_alive.call_count == 0
+        live_attributes.still_alive.assert_not_called()
 
     async def test__parse_ratelimits_when_ratelimited(self, rest_client, exit_exception, live_attributes):
         class StubResponse:
@@ -2016,7 +2015,7 @@ async def json(self):
         with pytest.raises(exit_exception):
             await rest_client._parse_ratelimits(route, StubResponse(), live_attributes)
 
-        assert live_attributes.still_alive.call_count == 0
+        live_attributes.still_alive.assert_not_called()
 
     async def test__parse_ratelimits_when_unexpected_content_type(self, rest_client, live_attributes):
         class StubResponse:
@@ -2032,7 +2031,7 @@ async def read(self):
         with pytest.raises(errors.HTTPResponseError):
             await rest_client._parse_ratelimits(route, StubResponse(), live_attributes)
 
-        assert live_attributes.still_alive.call_count == 0
+        live_attributes.still_alive.assert_not_called()
 
     async def test__parse_ratelimits_when_global_ratelimit(self, rest_client, live_attributes):
         class StubResponse:
@@ -2067,7 +2066,7 @@ async def json(self):
         with pytest.raises(rest._RetryRequest):
             await rest_client._parse_ratelimits(route, StubResponse(), live_attributes)
 
-        assert live_attributes.still_alive.call_count == 0
+        live_attributes.still_alive.assert_not_called()
 
     async def test__parse_ratelimits_when_retry_after_is_close_enough(self, rest_client, live_attributes):
         class StubResponse:
@@ -2085,7 +2084,7 @@ async def json(self):
         with pytest.raises(rest._RetryRequest):
             await rest_client._parse_ratelimits(route, StubResponse(), live_attributes)
 
-        assert live_attributes.still_alive.call_count == 0
+        live_attributes.still_alive.assert_not_called()
 
     async def test__parse_ratelimits_when_retry_after_is_not_close_enough(self, rest_client, live_attributes):
         class StubResponse:
@@ -2101,7 +2100,7 @@ async def json(self):
         with pytest.raises(errors.RateLimitedError):
             await rest_client._parse_ratelimits(route, StubResponse(), live_attributes)
 
-        assert live_attributes.still_alive.call_count == 0
+        live_attributes.still_alive.assert_not_called()
 
     #############
     # Endpoints #
@@ -2929,6 +2928,20 @@ async def test_fetch_channel_webhooks(self, rest_client):
             [mock.call({"id": "456"}), mock.call({"id": "789"})]
         )
 
+    async def test_fetch_channel_webhooks_ignores_unrecognised_webhook_type(self, rest_client):
+        webhook1 = StubModel(456)
+        expected_route = routes.GET_CHANNEL_WEBHOOKS.compile(channel=123)
+        rest_client._request = mock.AsyncMock(return_value=[{"id": "456"}, {"id": "789"}])
+        rest_client._entity_factory.deserialize_webhook = mock.Mock(
+            side_effect=[errors.UnrecognisedEntityError("yeet"), webhook1]
+        )
+
+        assert await rest_client.fetch_channel_webhooks(StubModel(123)) == [webhook1]
+        rest_client._request.assert_awaited_once_with(expected_route)
+        rest_client._entity_factory.deserialize_webhook.assert_has_calls(
+            [mock.call({"id": "456"}), mock.call({"id": "789"})]
+        )
+
     async def test_fetch_guild_webhooks(self, rest_client):
         webhook1 = StubModel(456)
         webhook2 = StubModel(789)
@@ -2943,6 +2956,20 @@ async def test_fetch_guild_webhooks(self, rest_client):
             [mock.call({"id": "456"}), mock.call({"id": "789"})]
         )
 
+    async def test_fetch_guild_webhooks_ignores_unrecognised_webhook_types(self, rest_client):
+        webhook1 = StubModel(456)
+        expected_route = routes.GET_GUILD_WEBHOOKS.compile(guild=123)
+        rest_client._request = mock.AsyncMock(return_value=[{"id": "456"}, {"id": "789"}])
+        rest_client._entity_factory.deserialize_webhook = mock.Mock(
+            side_effect=[errors.UnrecognisedEntityError("meow meow"), webhook1]
+        )
+
+        assert await rest_client.fetch_guild_webhooks(StubModel(123)) == [webhook1]
+        rest_client._request.assert_awaited_once_with(expected_route)
+        rest_client._entity_factory.deserialize_webhook.assert_has_calls(
+            [mock.call({"id": "456"}), mock.call({"id": "789"})]
+        )
+
     async def test_edit_webhook(self, rest_client):
         webhook = StubModel(456)
         expected_route = routes.PATCH_WEBHOOK_WITH_TOKEN.compile(webhook=123, token="token")
@@ -3442,10 +3469,9 @@ async def test_fetch_invite(self, rest_client):
         rest_client._request = mock.AsyncMock(return_value={"code": "Jx4cNGG"})
         rest_client._entity_factory.deserialize_invite = mock.Mock(return_value=return_invite)
 
-        assert await rest_client.fetch_invite(input_invite) == return_invite
-
+        assert await rest_client.fetch_invite(input_invite, with_counts=True, with_expiration=False) == return_invite
         rest_client._request.assert_awaited_once_with(
-            expected_route, query={"with_counts": "true", "with_expiration": "true"}
+            expected_route, query={"with_counts": "true", "with_expiration": "false"}
         )
         rest_client._entity_factory.deserialize_invite.assert_called_once_with({"code": "Jx4cNGG"})
 
@@ -4106,6 +4132,21 @@ async def test_fetch_guild_channels(self, rest_client):
             [mock.call({"id": "456"}), mock.call({"id": "789"})]
         )
 
+    async def test_fetch_guild_channels_ignores_unknown_channel_type(self, rest_client):
+        channel1 = StubModel(456)
+        expected_route = routes.GET_GUILD_CHANNELS.compile(guild=123)
+        rest_client._request = mock.AsyncMock(return_value=[{"id": "456"}, {"id": "789"}])
+        rest_client._entity_factory.deserialize_channel = mock.Mock(
+            side_effect=[errors.UnrecognisedEntityError("echelon"), channel1]
+        )
+
+        assert await rest_client.fetch_guild_channels(StubModel(123)) == [channel1]
+
+        rest_client._request.assert_awaited_once_with(expected_route)
+        rest_client._entity_factory.deserialize_channel.assert_has_calls(
+            [mock.call({"id": "456"}), mock.call({"id": "789"})]
+        )
+
     async def test_create_guild_text_channel(self, rest_client: rest.RESTClientImpl):
         guild = StubModel(123)
         category_channel = StubModel(789)
@@ -5264,6 +5305,23 @@ async def test_fetch_application_commands_without_guild(self, rest_client):
         rest_client._request.assert_awaited_once_with(expected_route, query={"with_localizations": "true"})
         rest_client._entity_factory.deserialize_command.assert_called_once_with({"id": "34512312"}, guild_id=None)
 
+    async def test_fetch_application_commands_ignores_unknown_command_types(self, rest_client):
+        mock_command = mock.Mock()
+        expected_route = routes.GET_APPLICATION_GUILD_COMMANDS.compile(application=54123, guild=432234)
+        rest_client._entity_factory.deserialize_command.side_effect = [
+            errors.UnrecognisedEntityError("eep"),
+            mock_command,
+        ]
+        rest_client._request = mock.AsyncMock(return_value=[{"id": "541234"}, {"id": "553234"}])
+
+        result = await rest_client.fetch_application_commands(StubModel(54123), StubModel(432234))
+
+        assert result == [mock_command]
+        rest_client._request.assert_awaited_once_with(expected_route, query={"with_localizations": "true"})
+        rest_client._entity_factory.deserialize_command.assert_has_calls(
+            [mock.call({"id": "541234"}, guild_id=432234), mock.call({"id": "553234"}, guild_id=432234)]
+        )
+
     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"})
@@ -5427,6 +5485,30 @@ async def test_set_application_commands_without_guild(self, rest_client):
         rest_client._request.assert_awaited_once_with(expected_route, json=[mock_command_builder.build.return_value])
         mock_command_builder.build.assert_called_once_with(rest_client._entity_factory)
 
+    async def test_set_application_commands_without_guild_handles_unknown_command_types(self, rest_client):
+        mock_command = mock.Mock()
+        expected_route = routes.PUT_APPLICATION_GUILD_COMMANDS.compile(application=532123123, guild=453123)
+        rest_client._entity_factory.deserialize_command.side_effect = [
+            errors.UnrecognisedEntityError("meow"),
+            mock_command,
+        ]
+        rest_client._request = mock.AsyncMock(return_value=[{"id": "435765"}, {"id": "4949493933"}])
+        mock_command_builder = mock.Mock()
+
+        result = await rest_client.set_application_commands(
+            StubModel(532123123), [mock_command_builder], StubModel(453123)
+        )
+
+        assert result == [mock_command]
+        rest_client._entity_factory.deserialize_command.assert_has_calls(
+            [
+                mock.call({"id": "435765"}, guild_id=453123),
+                mock.call({"id": "4949493933"}, guild_id=453123),
+            ]
+        )
+        rest_client._request.assert_awaited_once_with(expected_route, json=[mock_command_builder.build.return_value])
+        mock_command_builder.build.assert_called_once_with(rest_client._entity_factory)
+
     async def test_edit_application_command_with_optionals(self, rest_client):
         expected_route = routes.PATCH_APPLICATION_GUILD_COMMAND.compile(
             application=1235432, guild=54123, command=3451231
@@ -5800,6 +5882,25 @@ async def test_fetch_scheduled_events(self, rest_client: rest.RESTClientImpl):
         )
         rest_client._request.assert_awaited_once_with(expected_route, query={"with_user_count": "true"})
 
+    async def test_fetch_scheduled_events_handles_unrecognised_events(self, rest_client: rest.RESTClientImpl):
+        mock_event = mock.Mock()
+        rest_client._entity_factory.deserialize_scheduled_event.side_effect = [
+            errors.UnrecognisedEntityError("evil laugh"),
+            mock_event,
+        ]
+        expected_route = routes.GET_GUILD_SCHEDULED_EVENTS.compile(guild=65234123)
+        rest_client._request = mock.AsyncMock(
+            return_value=[{"id": "432234", "type": "1"}, {"id": "4939394", "type": "494949"}]
+        )
+
+        result = await rest_client.fetch_scheduled_events(StubModel(65234123))
+
+        assert result == [mock_event]
+        rest_client._entity_factory.deserialize_scheduled_event.assert_has_calls(
+            [mock.call({"id": "432234", "type": "1"}), mock.call({"id": "4939394", "type": "494949"})]
+        )
+        rest_client._request.assert_awaited_once_with(expected_route, query={"with_user_count": "true"})
+
     async def test_create_stage_event(self, rest_client: rest.RESTClientImpl, file_resource_patch):
         expected_route = routes.POST_GUILD_SCHEDULED_EVENT.compile(guild=123321)
         rest_client._request = mock.AsyncMock(return_value={"id": "494949", "name": "MEOsdasdWWWWW"})
diff --git a/tests/hikari/test_permissions.py b/tests/hikari/test_permissions.py
index 912f466e..fd96424b 100644
--- a/tests/hikari/test_permissions.py
+++ b/tests/hikari/test_permissions.py
@@ -27,4 +27,4 @@ def test_all_permissions(self):
         all_perms = permissions.Permissions.all_permissions()
 
         assert isinstance(all_perms, permissions.Permissions)
-        assert all_perms == 2190433320959
+        assert all_perms == 2199023255551