Skip to content

Commit 5a2c071

Browse files
Add logic and abstact method for search members endpoint (#350)
1 parent a93f925 commit 5a2c071

4 files changed

Lines changed: 74 additions & 0 deletions

File tree

hikari/api/rest.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3606,6 +3606,52 @@ def fetch_members(
36063606
itself will not raise anything.
36073607
"""
36083608

3609+
@abc.abstractmethod
3610+
async def search_members(
3611+
self,
3612+
guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
3613+
name: str,
3614+
) -> typing.Sequence[guilds.Member]:
3615+
"""Search the members in a guild by nickname and username.
3616+
3617+
Parameters
3618+
----------
3619+
guild : hikari.snowflakes.SnowflakeishOr[hikari.guilds.PartialGuild]
3620+
The object or ID of the guild to search members in.
3621+
name : str
3622+
The query to match username(s) and nickname(s) against.
3623+
3624+
Returns
3625+
-------
3626+
typing.Sequence[hikari.guilds.Member]
3627+
A sequence of the members who matched the provided `name`.
3628+
3629+
Raises
3630+
------
3631+
hikari.errors.UnauthorizedError
3632+
If you are unauthorized to make the request (invalid/missing token).
3633+
hikari.errors.NotFoundError
3634+
If the guild is not found.
3635+
hikari.errors.RateLimitTooLongError
3636+
Raised in the event that a rate limit occurs that is
3637+
longer than `max_rate_limit` when making a request.
3638+
hikari.errors.RateLimitedError
3639+
Usually, Hikari will handle and retry on hitting
3640+
rate-limits automatically. This includes most bucket-specific
3641+
rate-limits and global rate-limits. In some rare edge cases,
3642+
however, Discord implements other undocumented rules for
3643+
rate-limiting, such as limits per attribute. These cannot be
3644+
detected or handled normally by Hikari due to their undocumented
3645+
nature, and will trigger this exception if they occur.
3646+
hikari.errors.InternalServerError
3647+
If an internal error occurs on Discord while handling the request.
3648+
3649+
!!! note
3650+
Unlike `RESTClient.fetch_members` this endpoint isn't paginated and
3651+
therefore will return all the members in one go rather than needing
3652+
to be asynchronously iterated over.
3653+
"""
3654+
36093655
@abc.abstractmethod
36103656
async def edit_member(
36113657
self,

hikari/impl/rest.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,6 +2000,21 @@ def fetch_members(
20002000
entity_factory=self._entity_factory, request_call=self._request, guild=guild
20012001
)
20022002

2003+
async def search_members(
2004+
self,
2005+
guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],
2006+
name: str,
2007+
) -> typing.Sequence[guilds.Member]:
2008+
route = routes.GET_GUILD_MEMBERS_SEARCH.compile(guild=guild)
2009+
query = data_binding.StringMapBuilder()
2010+
query.put("query", name)
2011+
query.put("limit", 1000)
2012+
raw_response = await self._request(route, query=query)
2013+
response = typing.cast(data_binding.JSONArray, raw_response)
2014+
return data_binding.cast_json_array(
2015+
response, self._entity_factory.deserialize_member, guild_id=snowflakes.Snowflake(guild)
2016+
)
2017+
20032018
async def edit_member(
20042019
self,
20052020
guild: snowflakes.SnowflakeishOr[guilds.PartialGuild],

hikari/internal/routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ def compile_to_file(
367367
GET_GUILD_MEMBERS: typing.Final[Route] = Route(GET, "/guilds/{guild}/members")
368368
DELETE_GUILD_MEMBER: typing.Final[Route] = Route(DELETE, "/guilds/{guild}/members/{user}")
369369

370+
GET_GUILD_MEMBERS_SEARCH: typing.Final[Route] = Route(GET, "/guilds/{guild}/members/search")
371+
370372
PUT_GUILD_MEMBER_ROLE: typing.Final[Route] = Route(PUT, "/guilds/{guild}/members/{user}/roles/{role}")
371373
DELETE_GUILD_MEMBER_ROLE: typing.Final[Route] = Route(DELETE, "/guilds/{guild}/members/{user}/roles/{role}")
372374

tests/hikari/impl/test_rest.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2244,6 +2244,17 @@ async def test_fetch_member(self, rest_client):
22442244
rest_client._request.assert_awaited_once_with(expected_route)
22452245
rest_client._entity_factory.deserialize_member.assert_called_once_with({"id": "789"}, guild_id=123)
22462246

2247+
async def test_search_members(self, rest_client):
2248+
member = StubModel(645234123)
2249+
expected_route = routes.GET_GUILD_MEMBERS_SEARCH.compile(guild=645234123)
2250+
expected_query = {"query": "a name", "limit": "1000"}
2251+
rest_client._request = mock.AsyncMock(return_value=[{"id": "764435"}])
2252+
rest_client._entity_factory.deserialize_member = mock.Mock(return_value=member)
2253+
2254+
assert await rest_client.search_members(StubModel(645234123), "a name") == [member]
2255+
rest_client._entity_factory.deserialize_member.assert_called_once_with({"id": "764435"}, guild_id=645234123)
2256+
rest_client._request.assert_awaited_once_with(expected_route, query=expected_query)
2257+
22472258
async def test_edit_member(self, rest_client):
22482259
expected_route = routes.PATCH_GUILD_MEMBER.compile(guild=123, user=456)
22492260
expected_json = {"nick": "test", "roles": ["654", "321"], "mute": True, "deaf": False, "channel_id": "987"}

0 commit comments

Comments
 (0)