[commands] Lazily fetch members in discord.Member converters
This makes commands taking members mostly work transparently without much effort from the user.
This commit is contained in:
		| @@ -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 | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user