diff options
| author | 2021-10-03 14:38:17 +0100 | |
|---|---|---|
| committer | 2021-10-03 14:38:17 +0100 | |
| commit | 5f657a0418b55968924a1119342a8e0ea0e0d550 (patch) | |
| tree | 38b8146e90eddaddfea4fb485a70d6a30b558987 | |
| parent | python-news escape fixes (#1822) (diff) | |
| parent | Merge branch 'main' into add-get-or-fetch-util (diff) | |
Merge pull request #1837 from python-discord/add-get-or-fetch-util
Add get or fetch util
Diffstat (limited to '')
| -rw-r--r-- | bot/exts/backend/sync/_syncers.py | 3 | ||||
| -rw-r--r-- | bot/exts/events/code_jams/_cog.py | 7 | ||||
| -rw-r--r-- | bot/exts/filters/token_remover.py | 7 | ||||
| -rw-r--r-- | bot/exts/help_channels/_channel.py | 4 | ||||
| -rw-r--r-- | bot/exts/help_channels/_cog.py | 10 | ||||
| -rw-r--r-- | bot/exts/info/information.py | 9 | ||||
| -rw-r--r-- | bot/exts/moderation/infraction/infractions.py | 5 | ||||
| -rw-r--r-- | bot/exts/moderation/infraction/management.py | 3 | ||||
| -rw-r--r-- | bot/exts/moderation/infraction/superstarify.py | 3 | ||||
| -rw-r--r-- | bot/exts/moderation/stream.py | 23 | ||||
| -rw-r--r-- | bot/exts/moderation/watchchannels/_watchchannel.py | 5 | ||||
| -rw-r--r-- | bot/exts/recruitment/talentpool/_cog.py | 9 | ||||
| -rw-r--r-- | bot/exts/recruitment/talentpool/_review.py | 3 | ||||
| -rw-r--r-- | bot/exts/utils/reminders.py | 18 | ||||
| -rw-r--r-- | bot/utils/channel.py | 2 | ||||
| -rw-r--r-- | bot/utils/members.py | 24 | ||||
| -rw-r--r-- | pyproject.toml | 3 | ||||
| -rw-r--r-- | tests/bot/exts/backend/sync/test_users.py | 5 | ||||
| -rw-r--r-- | tests/bot/exts/filters/test_token_remover.py | 13 | ||||
| -rw-r--r-- | tests/bot/exts/moderation/infraction/test_infractions.py | 3 | 
20 files changed, 100 insertions, 59 deletions
| diff --git a/bot/exts/backend/sync/_syncers.py b/bot/exts/backend/sync/_syncers.py index c9f2d2da8..50016df0c 100644 --- a/bot/exts/backend/sync/_syncers.py +++ b/bot/exts/backend/sync/_syncers.py @@ -9,6 +9,7 @@ from more_itertools import chunked  import bot  from bot.api import ResponseCodeError +from bot.utils.members import get_or_fetch_member  log = logging.getLogger(__name__) @@ -156,7 +157,7 @@ class UserSyncer(Syncer):                  if db_user[db_field] != guild_value:                      updated_fields[db_field] = guild_value -            if guild_user := guild.get_member(db_user["id"]): +            if guild_user := await get_or_fetch_member(guild, db_user["id"]):                  seen_guild_users.add(guild_user.id)                  maybe_update("name", guild_user.name) diff --git a/bot/exts/events/code_jams/_cog.py b/bot/exts/events/code_jams/_cog.py index e099f7dfa..7b0831ab4 100644 --- a/bot/exts/events/code_jams/_cog.py +++ b/bot/exts/events/code_jams/_cog.py @@ -11,6 +11,7 @@ from discord.ext import commands  from bot.bot import Bot  from bot.constants import Emojis, Roles  from bot.exts.events.code_jams import _channels +from bot.utils.members import get_or_fetch_member  from bot.utils.services import send_to_paste_service  log = logging.getLogger(__name__) @@ -59,7 +60,7 @@ class CodeJams(commands.Cog):              reader = csv.DictReader(csv_file.splitlines())              for row in reader: -                member = ctx.guild.get_member(int(row["Team Member Discord ID"])) +                member = await get_or_fetch_member(ctx.guild, int(row["Team Member Discord ID"]))                  if member is None:                      log.trace(f"Got an invalid member ID: {row['Team Member Discord ID']}") @@ -69,8 +70,8 @@ class CodeJams(commands.Cog):              team_leaders = await ctx.guild.create_role(name="Code Jam Team Leaders", colour=TEAM_LEADERS_COLOUR) -            for team_name, members in teams.items(): -                await _channels.create_team_channel(ctx.guild, team_name, members, team_leaders) +            for team_name, team_members in teams.items(): +                await _channels.create_team_channel(ctx.guild, team_name, team_members, team_leaders)              await _channels.create_team_leader_channel(ctx.guild, team_leaders)              await ctx.send(f"{Emojis.check_mark} Created Code Jam with {len(teams)} teams.") diff --git a/bot/exts/filters/token_remover.py b/bot/exts/filters/token_remover.py index 93f1f3c33..6c86ff849 100644 --- a/bot/exts/filters/token_remover.py +++ b/bot/exts/filters/token_remover.py @@ -11,6 +11,7 @@ from bot import utils  from bot.bot import Bot  from bot.constants import Channels, Colours, Event, Icons  from bot.exts.moderation.modlog import ModLog +from bot.utils.members import get_or_fetch_member  from bot.utils.messages import format_user  log = logging.getLogger(__name__) @@ -99,7 +100,7 @@ class TokenRemover(Cog):          await msg.channel.send(DELETION_MESSAGE_TEMPLATE.format(mention=msg.author.mention))          log_message = self.format_log_message(msg, found_token) -        userid_message, mention_everyone = self.format_userid_log_message(msg, found_token) +        userid_message, mention_everyone = await self.format_userid_log_message(msg, found_token)          log.debug(log_message)          # Send pretty mod log embed to mod-alerts @@ -116,7 +117,7 @@ class TokenRemover(Cog):          self.bot.stats.incr("tokens.removed_tokens")      @classmethod -    def format_userid_log_message(cls, msg: Message, token: Token) -> t.Tuple[str, bool]: +    async def format_userid_log_message(cls, msg: Message, token: Token) -> t.Tuple[str, bool]:          """          Format the portion of the log message that includes details about the detected user ID. @@ -128,7 +129,7 @@ class TokenRemover(Cog):          Returns a tuple of (log_message, mention_everyone)          """          user_id = cls.extract_user_id(token.user_id) -        user = msg.guild.get_member(user_id) +        user = await get_or_fetch_member(msg.guild, user_id)          if user:              return KNOWN_USER_LOG_MESSAGE.format( diff --git a/bot/exts/help_channels/_channel.py b/bot/exts/help_channels/_channel.py index 0846b28c8..f1bcea171 100644 --- a/bot/exts/help_channels/_channel.py +++ b/bot/exts/help_channels/_channel.py @@ -10,7 +10,7 @@ from arrow import Arrow  import bot  from bot import constants  from bot.exts.help_channels import _caches, _message -from bot.utils.channel import try_get_channel +from bot.utils.channel import get_or_fetch_channel  log = logging.getLogger(__name__) @@ -133,7 +133,7 @@ async def move_to_bottom(channel: discord.TextChannel, category_id: int, **optio      options should be avoided, as it may interfere with the category move we perform.      """      # Get a fresh copy of the category from the bot to avoid the cache mismatch issue we had. -    category = await try_get_channel(category_id) +    category = await get_or_fetch_channel(category_id)      payload = [{"id": c.id, "position": c.position} for c in category.channels] diff --git a/bot/exts/help_channels/_cog.py b/bot/exts/help_channels/_cog.py index 8612f9866..7c39bc132 100644 --- a/bot/exts/help_channels/_cog.py +++ b/bot/exts/help_channels/_cog.py @@ -14,7 +14,7 @@ from bot import constants  from bot.bot import Bot  from bot.constants import Channels, RedirectOutput  from bot.exts.help_channels import _caches, _channel, _message, _name, _stats -from bot.utils import channel as channel_utils, lock, scheduling +from bot.utils import channel as channel_utils, lock, members, scheduling  log = logging.getLogger(__name__) @@ -278,13 +278,13 @@ class HelpChannels(commands.Cog):          log.trace("Getting the CategoryChannel objects for the help categories.")          try: -            self.available_category = await channel_utils.try_get_channel( +            self.available_category = await channel_utils.get_or_fetch_channel(                  constants.Categories.help_available              ) -            self.in_use_category = await channel_utils.try_get_channel( +            self.in_use_category = await channel_utils.get_or_fetch_channel(                  constants.Categories.help_in_use              ) -            self.dormant_category = await channel_utils.try_get_channel( +            self.dormant_category = await channel_utils.get_or_fetch_channel(                  constants.Categories.help_dormant              )          except discord.HTTPException: @@ -434,7 +434,7 @@ class HelpChannels(commands.Cog):          await _caches.claimants.delete(channel.id)          await _caches.session_participants.delete(channel.id) -        claimant = self.bot.get_guild(constants.Guild.id).get_member(claimant_id) +        claimant = await members.get_or_fetch_member(self.bot.get_guild(constants.Guild.id), claimant_id)          if claimant is None:              log.info(f"{claimant_id} left the guild during their help session; the cooldown role won't be removed")          else: diff --git a/bot/exts/info/information.py b/bot/exts/info/information.py index be67910a6..c60fd2127 100644 --- a/bot/exts/info/information.py +++ b/bot/exts/info/information.py @@ -19,6 +19,7 @@ from bot.errors import NonExistentRoleError  from bot.pagination import LinePaginator  from bot.utils.channel import is_mod_channel, is_staff_channel  from bot.utils.checks import cooldown_with_role_bypass, has_no_roles_check, in_whitelist_check +from bot.utils.members import get_or_fetch_member  from bot.utils.time import TimestampFormats, discord_timestamp, humanize_delta  log = logging.getLogger(__name__) @@ -46,13 +47,13 @@ class Information(Cog):      @staticmethod      def join_role_stats(role_ids: list[int], guild: Guild, name: Optional[str] = None) -> dict[str, int]:          """Return a dictionary with the number of `members` of each role given, and the `name` for this joined group.""" -        members = 0 +        member_count = 0          for role_id in role_ids:              if (role := guild.get_role(role_id)) is not None: -                members += len(role.members) +                member_count += len(role.members)              else:                  raise NonExistentRoleError(role_id) -        return {name or role.name.title(): members} +        return {name or role.name.title(): member_count}      @staticmethod      def get_member_counts(guild: Guild) -> dict[str, int]: @@ -244,7 +245,7 @@ class Information(Cog):      async def create_user_embed(self, ctx: Context, user: MemberOrUser) -> Embed:          """Creates an embed containing information on the `user`.""" -        on_server = bool(ctx.guild.get_member(user.id)) +        on_server = bool(await get_or_fetch_member(ctx.guild, user.id))          created = discord_timestamp(user.created_at, TimestampFormats.RELATIVE) diff --git a/bot/exts/moderation/infraction/infractions.py b/bot/exts/moderation/infraction/infractions.py index eaba97703..b58b09250 100644 --- a/bot/exts/moderation/infraction/infractions.py +++ b/bot/exts/moderation/infraction/infractions.py @@ -14,6 +14,7 @@ from bot.converters import Duration, Expiry, MemberOrUser, UnambiguousMemberOrUs  from bot.decorators import respect_role_hierarchy  from bot.exts.moderation.infraction import _utils  from bot.exts.moderation.infraction._scheduler import InfractionScheduler +from bot.utils.members import get_or_fetch_member  from bot.utils.messages import format_user  log = logging.getLogger(__name__) @@ -422,7 +423,7 @@ class Infractions(InfractionScheduler, commands.Cog):          notify: bool = True      ) -> t.Dict[str, str]:          """Remove a user's muted role, optionally DM them a notification, and return a log dict.""" -        user = guild.get_member(user_id) +        user = await get_or_fetch_member(guild, user_id)          log_text = {}          if user: @@ -470,7 +471,7 @@ class Infractions(InfractionScheduler, commands.Cog):          notify: bool = True      ) -> t.Dict[str, str]:          """Optionally DM the user a pardon notification and return a log dict.""" -        user = guild.get_member(user_id) +        user = await get_or_fetch_member(guild, user_id)          log_text = {}          if user: diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index d72cf8f89..0cb2a8b60 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -19,6 +19,7 @@ from bot.exts.moderation.modlog import ModLog  from bot.pagination import LinePaginator  from bot.utils import messages, time  from bot.utils.channel import is_mod_channel +from bot.utils.members import get_or_fetch_member  from bot.utils.time import humanize_delta, until_expiration  log = logging.getLogger(__name__) @@ -190,7 +191,7 @@ class ModManagement(commands.Cog):          # Get information about the infraction's user          user_id = new_infraction['user'] -        user = ctx.guild.get_member(user_id) +        user = await get_or_fetch_member(ctx.guild, user_id)          if user:              user_text = messages.format_user(user) diff --git a/bot/exts/moderation/infraction/superstarify.py b/bot/exts/moderation/infraction/superstarify.py index 05a2bbe10..aa2fd367b 100644 --- a/bot/exts/moderation/infraction/superstarify.py +++ b/bot/exts/moderation/infraction/superstarify.py @@ -14,6 +14,7 @@ from bot.bot import Bot  from bot.converters import Duration, Expiry  from bot.exts.moderation.infraction import _utils  from bot.exts.moderation.infraction._scheduler import InfractionScheduler +from bot.utils.members import get_or_fetch_member  from bot.utils.messages import format_user  from bot.utils.time import format_infraction @@ -198,7 +199,7 @@ class Superstarify(InfractionScheduler, Cog):              return          guild = self.bot.get_guild(constants.Guild.id) -        user = guild.get_member(infraction["user"]) +        user = await get_or_fetch_member(guild, infraction["user"])          # Don't bother sending a notification if the user left the guild.          if not user: diff --git a/bot/exts/moderation/stream.py b/bot/exts/moderation/stream.py index b5bd62a71..a179a9acc 100644 --- a/bot/exts/moderation/stream.py +++ b/bot/exts/moderation/stream.py @@ -16,6 +16,7 @@ from bot.constants import (  from bot.converters import Expiry  from bot.pagination import LinePaginator  from bot.utils import scheduling +from bot.utils.members import get_or_fetch_member  from bot.utils.time import discord_timestamp, format_infraction_with_duration  log = logging.getLogger(__name__) @@ -47,23 +48,17 @@ class Stream(commands.Cog):          """Reload outstanding tasks from redis on startup, delete the task if the member has since left the server."""          await self.bot.wait_until_guild_available()          items = await self.task_cache.items() +        guild = self.bot.get_guild(Guild.id)          for key, value in items: -            member = self.bot.get_guild(Guild.id).get_member(key) +            member = await get_or_fetch_member(guild, key)              if not member: -                # Member isn't found in the cache -                try: -                    member = await self.bot.get_guild(Guild.id).fetch_member(key) -                except discord.errors.NotFound: -                    log.debug( -                        f"Member {key} left the guild before we could schedule " -                        "the revoking of their streaming permissions." -                    ) -                    await self.task_cache.delete(key) -                    continue -                except discord.HTTPException: -                    log.exception(f"Exception while trying to retrieve member {key} from Discord.") -                    continue +                log.debug( +                    "User with ID %d left the guild before their streaming permissions could be revoked.", +                    key +                ) +                await self.task_cache.delete(key) +                continue              revoke_time = Arrow.utcfromtimestamp(value)              log.debug(f"Scheduling {member} ({member.id}) to have streaming permission revoked at {revoke_time}") diff --git a/bot/exts/moderation/watchchannels/_watchchannel.py b/bot/exts/moderation/watchchannels/_watchchannel.py index a42e1f518..3fafd097b 100644 --- a/bot/exts/moderation/watchchannels/_watchchannel.py +++ b/bot/exts/moderation/watchchannels/_watchchannel.py @@ -19,6 +19,7 @@ from bot.exts.filters.webhook_remover import WEBHOOK_URL_RE  from bot.exts.moderation.modlog import ModLog  from bot.pagination import LinePaginator  from bot.utils import CogABCMeta, messages, scheduling +from bot.utils.members import get_or_fetch_member  from bot.utils.time import get_time_delta  log = logging.getLogger(__name__) @@ -281,7 +282,7 @@ class WatchChannel(metaclass=CogABCMeta):          user_id = msg.author.id          guild = self.bot.get_guild(GuildConfig.id) -        actor = guild.get_member(self.watched_users[user_id]['actor']) +        actor = await get_or_fetch_member(guild, self.watched_users[user_id]['actor'])          actor = actor.display_name if actor else self.watched_users[user_id]['actor']          inserted_at = self.watched_users[user_id]['inserted_at'] @@ -355,7 +356,7 @@ class WatchChannel(metaclass=CogABCMeta):          list_data["info"] = {}          for user_id, user_data in watched_iter: -            member = ctx.guild.get_member(user_id) +            member = await get_or_fetch_member(ctx.guild, user_id)              line = f"• `{user_id}`"              if member:                  line += f" ({member.name}#{member.discriminator})" diff --git a/bot/exts/recruitment/talentpool/_cog.py b/bot/exts/recruitment/talentpool/_cog.py index aaafff973..38d7cfca1 100644 --- a/bot/exts/recruitment/talentpool/_cog.py +++ b/bot/exts/recruitment/talentpool/_cog.py @@ -16,6 +16,7 @@ from bot.converters import MemberOrUser  from bot.exts.recruitment.talentpool._review import Reviewer  from bot.pagination import LinePaginator  from bot.utils import scheduling, time +from bot.utils.members import get_or_fetch_member  from bot.utils.time import get_time_delta  AUTOREVIEW_ENABLED_KEY = "autoreview_enabled" @@ -175,7 +176,7 @@ class TalentPool(Cog, name="Talentpool"):          lines = []          for user_id, user_data in nominations: -            member = ctx.guild.get_member(user_id) +            member = await get_or_fetch_member(ctx.guild, user_id)              line = f"• `{user_id}`"              if member:                  line += f" ({member.name}#{member.discriminator})" @@ -314,7 +315,7 @@ class TalentPool(Cog, name="Talentpool"):              title=f"Nominations for {user.display_name} `({user.id})`",              color=Color.blue()          ) -        lines = [self._nomination_to_string(nomination) for nomination in result] +        lines = [await self._nomination_to_string(nomination) for nomination in result]          await LinePaginator.paginate(              lines,              ctx=ctx, @@ -495,13 +496,13 @@ class TalentPool(Cog, name="Talentpool"):          return True -    def _nomination_to_string(self, nomination_object: dict) -> str: +    async def _nomination_to_string(self, nomination_object: dict) -> str:          """Creates a string representation of a nomination."""          guild = self.bot.get_guild(Guild.id)          entries = []          for site_entry in nomination_object["entries"]:              actor_id = site_entry["actor"] -            actor = guild.get_member(actor_id) +            actor = await get_or_fetch_member(guild, actor_id)              reason = site_entry["reason"] or "*None*"              created = time.format_infraction(site_entry["inserted_at"]) diff --git a/bot/exts/recruitment/talentpool/_review.py b/bot/exts/recruitment/talentpool/_review.py index f4aa73e75..14a8dd4c0 100644 --- a/bot/exts/recruitment/talentpool/_review.py +++ b/bot/exts/recruitment/talentpool/_review.py @@ -16,6 +16,7 @@ from discord.ext.commands import Context  from bot.api import ResponseCodeError  from bot.bot import Bot  from bot.constants import Channels, Colours, Emojis, Guild +from bot.utils.members import get_or_fetch_member  from bot.utils.messages import count_unique_users_reaction, pin_no_system_message  from bot.utils.scheduling import Scheduler  from bot.utils.time import get_time_delta, time_since @@ -111,7 +112,7 @@ class Reviewer:              return "", None          guild = self.bot.get_guild(Guild.id) -        member = guild.get_member(user_id) +        member = await get_or_fetch_member(guild, user_id)          if not member:              return ( diff --git a/bot/exts/utils/reminders.py b/bot/exts/utils/reminders.py index 1030357fd..95f3661af 100644 --- a/bot/exts/utils/reminders.py +++ b/bot/exts/utils/reminders.py @@ -19,6 +19,7 @@ from bot.pagination import LinePaginator  from bot.utils import scheduling  from bot.utils.checks import has_any_role_check, has_no_roles_check  from bot.utils.lock import lock_arg +from bot.utils.members import get_or_fetch_member  from bot.utils.messages import send_denial  from bot.utils.scheduling import Scheduler  from bot.utils.time import TimestampFormats, discord_timestamp @@ -136,11 +137,12 @@ class Reminders(Cog):              await send_denial(ctx, f"You can't mention other {disallowed_mentions} in your reminder!")              return False -    def get_mentionables(self, mention_ids: t.List[int]) -> t.Iterator[Mentionable]: +    async def get_mentionables(self, mention_ids: t.List[int]) -> t.Iterator[Mentionable]:          """Converts Role and Member ids to their corresponding objects if possible."""          guild = self.bot.get_guild(Guild.id)          for mention_id in mention_ids: -            if mentionable := (guild.get_member(mention_id) or guild.get_role(mention_id)): +            member = await get_or_fetch_member(guild, mention_id) +            if mentionable := (member or guild.get_role(mention_id)):                  yield mentionable      def schedule_reminder(self, reminder: dict) -> None: @@ -194,9 +196,9 @@ class Reminders(Cog):          embed.description = f"Here's your reminder: {reminder['content']}"          # Here the jump URL is in the format of base_url/guild_id/channel_id/message_id -        additional_mentions = ' '.join( -            mentionable.mention for mentionable in self.get_mentionables(reminder["mentions"]) -        ) +        additional_mentions = ' '.join([ +            mentionable.mention async for mentionable in self.get_mentionables(reminder["mentions"]) +        ])          jump_url = reminder.get("jump_url")          embed.description += f"\n[Jump back to when you created the reminder]({jump_url})" @@ -337,10 +339,10 @@ class Reminders(Cog):              remind_datetime = isoparse(remind_at).replace(tzinfo=None)              time = discord_timestamp(remind_datetime, TimestampFormats.RELATIVE) -            mentions = ", ".join( +            mentions = ", ".join([                  # Both Role and User objects have the `name` attribute -                mention.name for mention in self.get_mentionables(mentions) -            ) +                mention.name async for mention in self.get_mentionables(mentions) +            ])              mention_string = f"\n**Mentions:** {mentions}" if mentions else ""              text = textwrap.dedent(f""" diff --git a/bot/utils/channel.py b/bot/utils/channel.py index 72603c521..6d2356679 100644 --- a/bot/utils/channel.py +++ b/bot/utils/channel.py @@ -53,7 +53,7 @@ def is_in_category(channel: discord.TextChannel, category_id: int) -> bool:      return getattr(channel, "category_id", None) == category_id -async def try_get_channel(channel_id: int) -> discord.abc.GuildChannel: +async def get_or_fetch_channel(channel_id: int) -> discord.abc.GuildChannel:      """Attempt to get or fetch a channel and return it."""      log.trace(f"Getting the channel {channel_id}.") diff --git a/bot/utils/members.py b/bot/utils/members.py new file mode 100644 index 000000000..302fe6d63 --- /dev/null +++ b/bot/utils/members.py @@ -0,0 +1,24 @@ +import logging +import typing as t + +import discord + +log = logging.getLogger(__name__) + + +async def get_or_fetch_member(guild: discord.Guild, member_id: int) -> t.Optional[discord.Member]: +    """ +    Attempt to get a member from cache; on failure fetch from the API. + +    Return `None` to indicate the member could not be found. +    """ +    if member := guild.get_member(member_id): +        log.trace("%s retrieved from cache.", member) +    else: +        try: +            member = await guild.fetch_member(member_id) +        except discord.errors.NotFound: +            log.trace("Failed to fetch %d from API.", member_id) +            return None +        log.trace("%s fetched from API.", member) +    return member diff --git a/pyproject.toml b/pyproject.toml index 23cbba19b..4431a41c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,7 +62,8 @@ precommit = "pre-commit install"  build = "docker build -t ghcr.io/python-discord/bot:latest -f Dockerfile ."  push = "docker push ghcr.io/python-discord/bot:latest"  test-nocov = "pytest -n auto" -test = "pytest -n auto --cov-report= --cov" +test = "pytest -n auto --cov-report= --cov --ff" +retest = "pytest -n auto --cov-report= --cov --lf"  html = "coverage html"  report = "coverage report" diff --git a/tests/bot/exts/backend/sync/test_users.py b/tests/bot/exts/backend/sync/test_users.py index 27932be95..88f1b2f52 100644 --- a/tests/bot/exts/backend/sync/test_users.py +++ b/tests/bot/exts/backend/sync/test_users.py @@ -1,6 +1,8 @@  import unittest  from unittest import mock +from discord.errors import NotFound +  from bot.exts.backend.sync._syncers import UserSyncer, _Diff  from tests import helpers @@ -134,6 +136,7 @@ class UserSyncerDiffTests(unittest.IsolatedAsyncioTestCase):              self.get_mock_member(fake_user()),              None          ] +        guild.fetch_member.side_effect = NotFound(mock.Mock(status=404), "Not found")          actual_diff = await UserSyncer._get_diff(guild)          expected_diff = ([], [{"id": 63, "in_guild": False}], None) @@ -158,6 +161,7 @@ class UserSyncerDiffTests(unittest.IsolatedAsyncioTestCase):              self.get_mock_member(updated_user),              None          ] +        guild.fetch_member.side_effect = NotFound(mock.Mock(status=404), "Not found")          actual_diff = await UserSyncer._get_diff(guild)          expected_diff = ([new_user], [{"id": 55, "name": "updated"}, {"id": 63, "in_guild": False}], None) @@ -177,6 +181,7 @@ class UserSyncerDiffTests(unittest.IsolatedAsyncioTestCase):              self.get_mock_member(fake_user()),              None          ] +        guild.fetch_member.side_effect = NotFound(mock.Mock(status=404), "Not found")          actual_diff = await UserSyncer._get_diff(guild)          expected_diff = ([], [], None) diff --git a/tests/bot/exts/filters/test_token_remover.py b/tests/bot/exts/filters/test_token_remover.py index 51feae9cb..05e790723 100644 --- a/tests/bot/exts/filters/test_token_remover.py +++ b/tests/bot/exts/filters/test_token_remover.py @@ -295,20 +295,21 @@ class TokenRemoverTests(unittest.IsolatedAsyncioTestCase):          )      @autospec("bot.exts.filters.token_remover", "UNKNOWN_USER_LOG_MESSAGE") -    def test_format_userid_log_message_unknown(self, unknown_user_log_message): +    async def test_format_userid_log_message_unknown(self, unknown_user_log_message,):          """Should correctly format the user ID portion when the actual user it belongs to is unknown."""          token = Token("NDcyMjY1OTQzMDYyNDEzMzMy", "XsySD_", "s45jqDV_Iisn-symw0yDRrk_jf4")          unknown_user_log_message.format.return_value = " Partner"          msg = MockMessage(id=555, content="hello world")          msg.guild.get_member.return_value = None +        msg.guild.fetch_member.side_effect = NotFound(mock.Mock(status=404), "Not found") -        return_value = TokenRemover.format_userid_log_message(msg, token) +        return_value = await TokenRemover.format_userid_log_message(msg, token)          self.assertEqual(return_value, (unknown_user_log_message.format.return_value, False))          unknown_user_log_message.format.assert_called_once_with(user_id=472265943062413332)      @autospec("bot.exts.filters.token_remover", "KNOWN_USER_LOG_MESSAGE") -    def test_format_userid_log_message_bot(self, known_user_log_message): +    async def test_format_userid_log_message_bot(self, known_user_log_message):          """Should correctly format the user ID portion when the ID belongs to a known bot."""          token = Token("NDcyMjY1OTQzMDYyNDEzMzMy", "XsySD_", "s45jqDV_Iisn-symw0yDRrk_jf4")          known_user_log_message.format.return_value = " Partner" @@ -316,7 +317,7 @@ class TokenRemoverTests(unittest.IsolatedAsyncioTestCase):          msg.guild.get_member.return_value.__str__.return_value = "Sam"          msg.guild.get_member.return_value.bot = True -        return_value = TokenRemover.format_userid_log_message(msg, token) +        return_value = await TokenRemover.format_userid_log_message(msg, token)          self.assertEqual(return_value, (known_user_log_message.format.return_value, True)) @@ -327,12 +328,12 @@ class TokenRemoverTests(unittest.IsolatedAsyncioTestCase):          )      @autospec("bot.exts.filters.token_remover", "KNOWN_USER_LOG_MESSAGE") -    def test_format_log_message_user_token_user(self, user_token_message): +    async def test_format_log_message_user_token_user(self, user_token_message):          """Should correctly format the user ID portion when the ID belongs to a known user."""          token = Token("NDY3MjIzMjMwNjUwNzc3NjQx", "XsySD_", "s45jqDV_Iisn-symw0yDRrk_jf4")          user_token_message.format.return_value = "Partner" -        return_value = TokenRemover.format_userid_log_message(self.msg, token) +        return_value = await TokenRemover.format_userid_log_message(self.msg, token)          self.assertEqual(return_value, (user_token_message.format.return_value, True))          user_token_message.format.assert_called_once_with( diff --git a/tests/bot/exts/moderation/infraction/test_infractions.py b/tests/bot/exts/moderation/infraction/test_infractions.py index f844a9181..aeff734dc 100644 --- a/tests/bot/exts/moderation/infraction/test_infractions.py +++ b/tests/bot/exts/moderation/infraction/test_infractions.py @@ -3,6 +3,8 @@ import textwrap  import unittest  from unittest.mock import ANY, AsyncMock, MagicMock, Mock, patch +from discord.errors import NotFound +  from bot.constants import Event  from bot.exts.moderation.infraction import _utils  from bot.exts.moderation.infraction.infractions import Infractions @@ -195,6 +197,7 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):      async def test_voice_unban_user_not_found(self):          """Should include info to return dict when user was not found from guild."""          self.guild.get_member.return_value = None +        self.guild.fetch_member.side_effect = NotFound(Mock(status=404), "Not found")          result = await self.cog.pardon_voice_ban(self.user.id, self.guild)          self.assertEqual(result, {"Info": "User was not found in the guild."}) | 
