Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add new voice endpoints #2016

Merged
merged 9 commits into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/2016.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added new voice endpoints (`fetch_my_voice_state` and `fetch_voice_state`)
davfsa marked this conversation as resolved.
Show resolved Hide resolved
58 changes: 58 additions & 0 deletions hikari/api/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,64 @@ async def delete_channel(
If an internal error occurs on Discord while handling the request.
"""

@abc.abstractmethod
async def fetch_my_voice_state(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> voices.VoiceState:
"""Fetch the current user's voice state.

Parameters
----------
guild
The guild to fetch the state from. This may be the object or the ID.

Raises
------
hikari.errors.UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
hikari.errors.NotFoundError
If the channel, message or voice state is not found.
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.InternalServerError
If an internal error occurs on Discord while handling the request.

Returns
-------
voices.VoiceState
The current user's voice state.
"""

@abc.abstractmethod
async def fetch_voice_state(
self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild], user: snowflakes.SnowflakeishOr[users.PartialUser]
) -> voices.VoiceState:
"""Fetch the current user's voice state.

Parameters
----------
guild
The guild to fetch the state from. This may be the object or the ID.
user
The user to fetch the state for. This may be the object or the ID.

Raises
------
hikari.errors.UnauthorizedError
If you are unauthorized to make the request (invalid/missing token).
hikari.errors.NotFoundError
If the channel, message or voice state is not found.
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.InternalServerError
If an internal error occurs on Discord while handling the request.

Returns
-------
voices.VoiceState
The user's voice state.
"""

@abc.abstractmethod
async def edit_my_voice_state(
self,
Expand Down
18 changes: 18 additions & 0 deletions hikari/impl/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1149,6 +1149,24 @@ async def delete_channel(
assert isinstance(response, dict)
return self._entity_factory.deserialize_channel(response)

async def fetch_my_voice_state(self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild]) -> voices.VoiceState:
route = routes.GET_MY_GUILD_VOICE_STATE.compile(guild=guild)

response = await self._request(route)

assert isinstance(response, dict)
return self._entity_factory.deserialize_voice_state(response)

async def fetch_voice_state(
self, guild: snowflakes.SnowflakeishOr[guilds.PartialGuild], user: snowflakes.SnowflakeishOr[users.PartialUser]
) -> voices.VoiceState:
route = routes.GET_GUILD_VOICE_STATE.compile(guild=guild, user=user)

response = await self._request(route)

assert isinstance(response, dict)
return self._entity_factory.deserialize_voice_state(response)

async def edit_my_voice_state(
self,
guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
Expand Down
3 changes: 3 additions & 0 deletions hikari/internal/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,9 @@ def compile_to_file(

GET_GUILD_VANITY_URL: typing.Final[Route] = Route(GET, "/guilds/{guild}/vanity-url")

GET_GUILD_VOICE_STATE: typing.Final[Route] = Route(GET, "/guilds/{guild}/voice-states/{user}")
GET_MY_GUILD_VOICE_STATE: typing.Final[Route] = Route(GET, "/guilds/{guild}/voice-states/@me")

PATCH_GUILD_VOICE_STATE: typing.Final[Route] = Route(PATCH, "/guilds/{guild}/voice-states/{user}")
PATCH_MY_GUILD_VOICE_STATE: typing.Final[Route] = Route(PATCH, "/guilds/{guild}/voice-states/@me")

Expand Down
80 changes: 80 additions & 0 deletions tests/hikari/impl/test_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2269,6 +2269,86 @@ async def test_edit_my_voice_state_when_revoking_speak_request(self, rest_client
expected_route, json={"channel_id": "999", "suppress": True, "request_to_speak_timestamp": None}
)

async def test_fetch_my_voice_state(self, rest_client):
expected_route = routes.GET_MY_GUILD_VOICE_STATE.compile(guild=5454)

expected_json = {
"guild_id": "5454",
"channel_id": "3940568093485",
"user_id": "237890809345627",
"member": {
"nick": "foobarbaz",
"roles": ["11111", "22222", "33333", "44444"],
"joined_at": "2015-04-26T06:26:56.936000+00:00",
"premium_since": "2019-05-17T06:26:56.936000+00:00",
"avatar": "estrogen",
"deaf": False,
"mute": True,
"pending": False,
"communication_disabled_until": "2021-10-18T06:26:56.936000+00:00",
},
"session_id": "39405894b9058guhfguh43t9g",
"deaf": False,
"mute": True,
"self_deaf": False,
"self_mute": True,
"self_stream": False,
"self_video": True,
"suppress": False,
"request_to_speak_timestamp": "2021-04-17T10:11:19.970105+00:00",
}

rest_client._request = mock.AsyncMock(return_value=expected_json)

with mock.patch.object(
rest_client._entity_factory, "deserialize_voice_state", return_value=mock.Mock()
) as patched_deserialize_voice_state:
await rest_client.fetch_my_voice_state(StubModel(5454))

patched_deserialize_voice_state.assert_called_once_with(expected_json)

rest_client._request.assert_awaited_once_with(expected_route)

async def test_fetch_voice_state(self, rest_client):
expected_route = routes.GET_GUILD_VOICE_STATE.compile(guild=5454, user=1234567890)

expected_json = {
"guild_id": "5454",
"channel_id": "3940568093485",
"user_id": "1234567890",
"member": {
"nick": "foobarbaz",
"roles": ["11111", "22222", "33333", "44444"],
"joined_at": "2015-04-26T06:26:56.936000+00:00",
"premium_since": "2019-05-17T06:26:56.936000+00:00",
"avatar": "estrogen",
"deaf": False,
"mute": True,
"pending": False,
"communication_disabled_until": "2021-10-18T06:26:56.936000+00:00",
},
"session_id": "39405894b9058guhfguh43t9g",
"deaf": False,
"mute": True,
"self_deaf": False,
"self_mute": True,
"self_stream": False,
"self_video": True,
"suppress": False,
"request_to_speak_timestamp": "2021-04-17T10:11:19.970105+00:00",
}

rest_client._request = mock.AsyncMock(return_value=expected_json)

with mock.patch.object(
rest_client._entity_factory, "deserialize_voice_state", return_value=mock.Mock()
) as patched_deserialize_voice_state:
await rest_client.fetch_voice_state(StubModel(5454), StubModel(1234567890))

patched_deserialize_voice_state.assert_called_once_with(expected_json)

rest_client._request.assert_awaited_once_with(expected_route)

async def test_edit_my_voice_state_when_providing_datetime_for_request_to_speak(self, rest_client):
rest_client._request = mock.AsyncMock()
expected_route = routes.PATCH_MY_GUILD_VOICE_STATE.compile(guild=5421)
Expand Down