aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRapptz <[email protected]>2020-10-17 23:05:22 -0400
committerRapptz <[email protected]>2020-10-17 23:05:22 -0400
commit3daaadafdde40f277af29b2cfd20f4c762ff15ab (patch)
treebc375e08c59ca9f20163f04fb1d239f4cb24cf7d
parentEnsure our own member is never evicted from the cache in any policy. (diff)
downloaddiscord.py-3daaadafdde40f277af29b2cfd20f4c762ff15ab.tar.xz
discord.py-3daaadafdde40f277af29b2cfd20f4c762ff15ab.zip
[commands] Lazily fetch members in discord.Member converters
This makes commands taking members mostly work transparently without much effort from the user.
-rw-r--r--discord/ext/commands/converter.py47
1 files changed, 46 insertions, 1 deletions
diff --git a/discord/ext/commands/converter.py b/discord/ext/commands/converter.py
index f3d7b257..155b1a4e 100644
--- a/discord/ext/commands/converter.py
+++ b/discord/ext/commands/converter.py
@@ -122,13 +122,49 @@ class MemberConverter(IDConverter):
.. versionchanged:: 1.5
Raise :exc:`.MemberNotFound` instead of generic :exc:`.BadArgument`
+
+ .. versionchanged:: 1.5.1
+ This converter now lazily fetches members from the gateway and HTTP APIs,
+ optionally caching the result if :attr:`.MemberCacheFlags.joined` is enabled.
"""
+ async def query_member_named(self, guild, argument):
+ cache = guild._state._member_cache_flags.joined
+ if len(argument) > 5 and argument[-5] == '#':
+ username, _, discriminator = argument.rpartition('#')
+ members = await guild.query_members(username, limit=100, cache=cache)
+ return discord.utils.get(members, name=username, discriminator=discriminator)
+ else:
+ members = await guild.query_members(argument, limit=100, cache=cache)
+ return discord.utils.find(lambda m: m.name == argument or m.nick == argument, members)
+
+ async def query_member_by_id(self, bot, guild, user_id):
+ ws = bot._get_websocket(shard_id=guild.shard_id)
+ cache = guild._state._member_cache_flags.joined
+ if ws.is_ratelimited():
+ # If we're being rate limited on the WS, then fall back to using the HTTP API
+ # So we don't have to wait ~60 seconds for the query to finish
+ try:
+ member = await guild.fetch_member(user_id)
+ except discord.HTTPException:
+ return None
+
+ if cache:
+ guild._add_member(member)
+ return member
+
+ # If we're not being rate limited then we can use the websocket to actually query
+ members = await guild.query_members(limit=1, user_ids=[user_id], cache=cache)
+ if not members:
+ return None
+ return members[0]
+
async def convert(self, ctx, argument):
bot = ctx.bot
match = self._get_id_match(argument) or re.match(r'<@!?([0-9]+)>$', argument)
guild = ctx.guild
result = None
+ user_id = None
if match is None:
# not a mention...
if guild:
@@ -143,7 +179,16 @@ class MemberConverter(IDConverter):
result = _get_from_guilds(bot, 'get_member', user_id)
if result is None:
- raise MemberNotFound(argument)
+ if guild is None:
+ raise MemberNotFound(argument)
+
+ if user_id is not None:
+ result = await self.query_member_by_id(bot, guild, user_id)
+ else:
+ result = await self.query_member_named(guild, argument)
+
+ if not result:
+ raise MemberNotFound(argument)
return result