aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Chris Lovering <[email protected]>2021-09-20 14:30:39 +0100
committerGravatar Chris Lovering <[email protected]>2021-09-29 20:55:40 +0100
commit15a8e7e8f8b5682838613a035012a49f5be5034e (patch)
tree6e90fb78fe107f73474126f552037b8043754458
parentAdd get_or_fetch_member util (diff)
Migrate all Guild.get_member calls to get_or_fetch_member
This protects us against the guild cache not being fully populated with members.
-rw-r--r--bot/exts/backend/sync/_syncers.py3
-rw-r--r--bot/exts/events/code_jams/_cog.py7
-rw-r--r--bot/exts/filters/token_remover.py7
-rw-r--r--bot/exts/help_channels/_cog.py4
-rw-r--r--bot/exts/info/information.py9
-rw-r--r--bot/exts/moderation/infraction/infractions.py5
-rw-r--r--bot/exts/moderation/infraction/management.py3
-rw-r--r--bot/exts/moderation/infraction/superstarify.py3
-rw-r--r--bot/exts/moderation/stream.py23
-rw-r--r--bot/exts/moderation/watchchannels/_watchchannel.py5
-rw-r--r--bot/exts/recruitment/talentpool/_cog.py9
-rw-r--r--bot/exts/recruitment/talentpool/_review.py3
-rw-r--r--bot/exts/utils/reminders.py18
13 files changed, 53 insertions, 46 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/_cog.py b/bot/exts/help_channels/_cog.py
index 8612f9866..a64ceac3a 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__)
@@ -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"""