From a36e95c286b9a4eb743a873fa82d33a6b543ee88 Mon Sep 17 00:00:00 2001 From: Michael H Date: Sat, 21 Dec 2019 01:15:34 -0500 Subject: [PATCH] Remove a large amount of `fetch_user` calls (#3075) * Non-audio changes * address Flame's feedback --- changelog.d/2964.enhance.rst | 1 + changelog.d/2964.misc.rst | 3 ++ redbot/cogs/mod/kickban.py | 36 ++++++++++++++--------- redbot/cogs/warnings/warnings.py | 9 ++---- redbot/core/core_commands.py | 50 +++++++++++++++++++++----------- redbot/core/modlog.py | 16 ++-------- 6 files changed, 65 insertions(+), 50 deletions(-) create mode 100644 changelog.d/2964.enhance.rst create mode 100644 changelog.d/2964.misc.rst diff --git a/changelog.d/2964.enhance.rst b/changelog.d/2964.enhance.rst new file mode 100644 index 000000000..1c1adbea1 --- /dev/null +++ b/changelog.d/2964.enhance.rst @@ -0,0 +1 @@ +Red takes less time to fetch cases, unban members, and list warnings. \ No newline at end of file diff --git a/changelog.d/2964.misc.rst b/changelog.d/2964.misc.rst new file mode 100644 index 000000000..b1fb9fe2a --- /dev/null +++ b/changelog.d/2964.misc.rst @@ -0,0 +1,3 @@ +Red no longer uses bot.fetch_user in core + - This is a 1/1s global ratelimit + - It really really really should be avoided. \ No newline at end of file diff --git a/redbot/cogs/mod/kickban.py b/redbot/cogs/mod/kickban.py index 417e40eff..37182518c 100644 --- a/redbot/cogs/mod/kickban.py +++ b/redbot/cogs/mod/kickban.py @@ -122,14 +122,23 @@ class KickBanMixin(MixinMeta): member = namedtuple("Member", "id guild") while self == self.bot.get_cog("Mod"): for guild in self.bot.guilds: + if not guild.me.guild_permissions.ban_members: + continue + try: + banned_users = {b.user.id: b.user for b in (await guild.bans())} + except discord.HTTPException: + continue + async with self.settings.guild(guild).current_tempbans() as guild_tempbans: for uid in guild_tempbans.copy(): + user = banned_users.get(uid, None) + if not user: + continue unban_time = datetime.utcfromtimestamp( await self.settings.member(member(uid, guild)).banned_until() ) if datetime.utcnow() > unban_time: # Time to unban the user - user = await self.bot.fetch_user(uid) - queue_entry = (guild.id, user.id) + queue_entry = (guild.id, uid) try: await guild.unban(user, reason=_("Tempban finished")) guild_tempbans.remove(uid) @@ -137,7 +146,7 @@ class KickBanMixin(MixinMeta): # 50013: Missing permissions error code or 403: Forbidden status if e.code == 50013 or e.status == 403: log.info( - f"Failed to unban {user}({user.id}) user from " + f"Failed to unban ({uid}) user from " f"{guild.name}({guild.id}) guild due to permissions" ) break # skip the rest of this guild @@ -334,15 +343,13 @@ class KickBanMixin(MixinMeta): else: banned.append(user_id) - user_info = await self.bot.fetch_user(user_id) - try: await modlog.create_case( self.bot, guild, ctx.message.created_at, "hackban", - user_info, + user_id, author, reason, until=None, @@ -551,18 +558,14 @@ class KickBanMixin(MixinMeta): click the user and select 'Copy ID'.""" guild = ctx.guild author = ctx.author - try: - user = await self.bot.fetch_user(user_id) - except discord.errors.NotFound: - await ctx.send(_("Couldn't find a user with that ID!")) - return audit_reason = get_audit_reason(ctx.author, reason) bans = await guild.bans() bans = [be.user for be in bans] - if user not in bans: + user = discord.utils.get(bans, id=user_id) + if not user: await ctx.send(_("It seems that user isn't banned!")) return - queue_entry = (guild.id, user.id) + queue_entry = (guild.id, user_id) try: await guild.unban(user, reason=audit_reason) except discord.HTTPException: @@ -586,6 +589,13 @@ class KickBanMixin(MixinMeta): await ctx.send(_("Unbanned that user from this server")) if await self.settings.guild(guild).reinvite_on_unban(): + user = ctx.bot.get_user(user_id) + if not user: + await ctx.send( + _("I don't share another server with this user. I can't reinvite them.") + ) + return + invite = await self.get_invite_for_reinvite(ctx) if invite: try: diff --git a/redbot/cogs/warnings/warnings.py b/redbot/cogs/warnings/warnings.py index a871ae62f..515c1c13c 100644 --- a/redbot/cogs/warnings/warnings.py +++ b/redbot/cogs/warnings/warnings.py @@ -374,13 +374,8 @@ class Warnings(commands.Cog): await ctx.send(_("That user has no warnings!")) else: for key in user_warnings.keys(): - mod = ctx.guild.get_member(user_warnings[key]["mod"]) - if mod is None: - mod = discord.utils.get( - self.bot.get_all_members(), id=user_warnings[key]["mod"] - ) - if mod is None: - mod = await self.bot.fetch_user(user_warnings[key]["mod"]) + mod_id = user_warnings[key]["mod"] + mod = ctx.bot.get_user(mod_id) or _("Unknown Moderator ({})").format(mod_id) msg += _( "{num_points} point warning {reason_name} issued by {user} for " "{description}\n" diff --git a/redbot/core/core_commands.py b/redbot/core/core_commands.py index 53e95e836..c3a6c1875 100644 --- a/redbot/core/core_commands.py +++ b/redbot/core/core_commands.py @@ -1687,13 +1687,14 @@ class Core(commands.Cog, CoreLogic): pass @whitelist.command(name="add") - async def whitelist_add(self, ctx, user: discord.User): + async def whitelist_add(self, ctx, *, user: Union[discord.Member, int]): """ Adds a user to the whitelist. """ + uid = getattr(user, "id", user) async with ctx.bot._config.whitelist() as curr_list: - if user.id not in curr_list: - curr_list.append(user.id) + if uid not in curr_list: + curr_list.append(uid) await ctx.send(_("User added to whitelist.")) @@ -1712,16 +1713,16 @@ class Core(commands.Cog, CoreLogic): await ctx.send(box(page)) @whitelist.command(name="remove") - async def whitelist_remove(self, ctx: commands.Context, *, user: discord.User): + async def whitelist_remove(self, ctx: commands.Context, *, user: Union[discord.Member, int]): """ Removes user from whitelist. """ removed = False - + uid = getattr(user, "id", user) async with ctx.bot._config.whitelist() as curr_list: - if user.id in curr_list: + if uid in curr_list: removed = True - curr_list.remove(user.id) + curr_list.remove(uid) if removed: await ctx.send(_("User has been removed from whitelist.")) @@ -1745,7 +1746,7 @@ class Core(commands.Cog, CoreLogic): pass @blacklist.command(name="add") - async def blacklist_add(self, ctx: commands.Context, *, user: discord.User): + async def blacklist_add(self, ctx: commands.Context, *, user: Union[discord.Member, int]): """ Adds a user to the blacklist. """ @@ -1753,9 +1754,10 @@ class Core(commands.Cog, CoreLogic): await ctx.send(_("You cannot blacklist an owner!")) return + uid = getattr(user, "id", user) async with ctx.bot._config.blacklist() as curr_list: - if user.id not in curr_list: - curr_list.append(user.id) + if uid not in curr_list: + curr_list.append(uid) await ctx.send(_("User added to blacklist.")) @@ -1774,16 +1776,17 @@ class Core(commands.Cog, CoreLogic): await ctx.send(box(page)) @blacklist.command(name="remove") - async def blacklist_remove(self, ctx: commands.Context, *, user: discord.User): + async def blacklist_remove(self, ctx: commands.Context, *, user: Union[discord.Member, int]): """ Removes user from blacklist. """ removed = False + uid = getattr(user, "id", user) async with ctx.bot._config.blacklist() as curr_list: - if user.id in curr_list: + if uid in curr_list: removed = True - curr_list.remove(user.id) + curr_list.remove(uid) if removed: await ctx.send(_("User has been removed from blacklist.")) @@ -1809,12 +1812,16 @@ class Core(commands.Cog, CoreLogic): @localwhitelist.command(name="add") async def localwhitelist_add( - self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role] + self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role, int] ): """ Adds a user or role to the whitelist. """ user = isinstance(user_or_role, discord.Member) + if isinstance(user_or_role, int): + user_or_role = discord.Object(id=user_or_role) + user = True + async with ctx.bot._config.guild(ctx.guild).whitelist() as curr_list: if user_or_role.id not in curr_list: curr_list.append(user_or_role.id) @@ -1840,12 +1847,15 @@ class Core(commands.Cog, CoreLogic): @localwhitelist.command(name="remove") async def localwhitelist_remove( - self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role] + self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role, int] ): """ Removes user or role from whitelist. """ user = isinstance(user_or_role, discord.Member) + if isinstance(user_or_role, int): + user_or_role = discord.Object(id=user_or_role) + user = True removed = False async with ctx.bot._config.guild(ctx.guild).whitelist() as curr_list: @@ -1883,12 +1893,15 @@ class Core(commands.Cog, CoreLogic): @localblacklist.command(name="add") async def localblacklist_add( - self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role] + self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role, int] ): """ Adds a user or role to the blacklist. """ user = isinstance(user_or_role, discord.Member) + if isinstance(user_or_role, int): + user_or_role = discord.Object(id=user_or_role) + user = True if user and await ctx.bot.is_owner(user_or_role): await ctx.send(_("You cannot blacklist an owner!")) @@ -1919,13 +1932,16 @@ class Core(commands.Cog, CoreLogic): @localblacklist.command(name="remove") async def localblacklist_remove( - self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role] + self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role, int] ): """ Removes user or role from blacklist. """ removed = False user = isinstance(user_or_role, discord.Member) + if isinstance(user_or_role, int): + user_or_role = discord.Object(id=user_or_role) + user = True async with ctx.bot._config.guild(ctx.guild).blacklist() as curr_list: if user_or_role.id in curr_list: diff --git a/redbot/core/modlog.py b/redbot/core/modlog.py index fcdbc593a..7ad4c786a 100644 --- a/redbot/core/modlog.py +++ b/redbot/core/modlog.py @@ -304,7 +304,7 @@ class Case: ) if isinstance(self.user, int): - user = f"Deleted User#0000 ({self.user})" + user = f"[Unknown or Deleted User] ({self.user})" avatar_url = None else: user = escape_spoilers( @@ -448,12 +448,7 @@ class Case: if user_id is None: user_object = None else: - user_object = bot.get_user(user_id) - if user_object is None: - try: - user_object = await bot.fetch_user(user_id) - except discord.NotFound: - user_object = user_id + user_object = bot.get_user(user_id) or user_id user_objects[user_key] = user_object channel = kwargs.get("channel") or guild.get_channel(data["channel"]) or data["channel"] @@ -687,12 +682,7 @@ async def get_cases_for_member( member_id = member.id if not member: - member = bot.get_user(member_id) - if not member: - try: - member = await bot.fetch_user(member_id) - except discord.NotFound: - member = member_id + member = bot.get_user(member_id) or member_id try: modlog_channel = await get_modlog_channel(guild)