From 939535d5c7c597741e5b1c5b6f7209aed152d4bc Mon Sep 17 00:00:00 2001 From: dawnofmidnight Date: Wed, 11 Aug 2021 17:34:15 -0400 Subject: fix: update urls in site cog --- bot/exts/info/site.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bot/exts/info/site.py b/bot/exts/info/site.py index fb5b99086..28eb558a6 100644 --- a/bot/exts/info/site.py +++ b/bot/exts/info/site.py @@ -9,7 +9,7 @@ from bot.pagination import LinePaginator log = logging.getLogger(__name__) -PAGES_URL = f"{URLs.site_schema}{URLs.site}/pages" +BASE_URL = f"{URLs.site_schema}{URLs.site}" class Site(Cog): @@ -43,7 +43,7 @@ class Site(Cog): @site_group.command(name="resources", root_aliases=("resources", "resource")) async def site_resources(self, ctx: Context) -> None: """Info about the site's Resources page.""" - learning_url = f"{PAGES_URL}/resources" + learning_url = f"{BASE_URL}/resources" embed = Embed(title="Resources") embed.set_footer(text=f"{learning_url}") @@ -59,7 +59,7 @@ class Site(Cog): @site_group.command(name="tools", root_aliases=("tools",)) async def site_tools(self, ctx: Context) -> None: """Info about the site's Tools page.""" - tools_url = f"{PAGES_URL}/resources/tools" + tools_url = f"{BASE_URL}/resources/tools" embed = Embed(title="Tools") embed.set_footer(text=f"{tools_url}") @@ -74,7 +74,7 @@ class Site(Cog): @site_group.command(name="help") async def site_help(self, ctx: Context) -> None: """Info about the site's Getting Help page.""" - url = f"{PAGES_URL}/resources/guides/asking-good-questions" + url = f"{BASE_URL}/pages/guides/pydis-guides/asking-good-questions/" embed = Embed(title="Asking Good Questions") embed.set_footer(text=url) @@ -90,7 +90,7 @@ class Site(Cog): @site_group.command(name="faq", root_aliases=("faq",)) async def site_faq(self, ctx: Context) -> None: """Info about the site's FAQ page.""" - url = f"{PAGES_URL}/frequently-asked-questions" + url = f"{BASE_URL}/pages/frequently-asked-questions" embed = Embed(title="FAQ") embed.set_footer(text=url) @@ -107,13 +107,13 @@ class Site(Cog): @site_group.command(name="rules", aliases=("r", "rule"), root_aliases=("rules", "rule")) async def site_rules(self, ctx: Context, rules: Greedy[int]) -> None: """Provides a link to all rules or, if specified, displays specific rule(s).""" - rules_embed = Embed(title='Rules', color=Colour.blurple(), url=f'{PAGES_URL}/rules') + rules_embed = Embed(title='Rules', color=Colour.blurple(), url=f'{BASE_URL}/pages/rules') if not rules: # Rules were not submitted. Return the default description. rules_embed.description = ( "The rules and guidelines that apply to this community can be found on" - f" our [rules page]({PAGES_URL}/rules). We expect" + f" our [rules page]({BASE_URL}/pages/rules). We expect" " all members of the community to have read and understood these." ) -- cgit v1.2.3 From 9c199dbbb8683584ef01955197232314eb0cf372 Mon Sep 17 00:00:00 2001 From: TizzySaurus <47674925+TizzySaurus@users.noreply.github.com> Date: Sun, 22 Aug 2021 18:55:45 +0100 Subject: Fix edge-case of `user.joined_at` being `None` in userinfo command. --- bot/exts/info/information.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bot/exts/info/information.py b/bot/exts/info/information.py index 83ca59bea..85d3c0e73 100644 --- a/bot/exts/info/information.py +++ b/bot/exts/info/information.py @@ -257,7 +257,11 @@ class Information(Cog): badges.append(emoji) if on_server: - joined = discord_timestamp(user.joined_at, TimestampFormats.RELATIVE) + if user.joined_at: + joined = discord_timestamp(user.joined_at, TimestampFormats.RELATIVE) + else: + joined = "Unable to get join date" + # The 0 is for excluding the default @everyone role, # and the -1 is for reversing the order of the roles to highest to lowest in hierarchy. roles = ", ".join(role.mention for role in user.roles[:0:-1]) -- cgit v1.2.3 From 73bc01123efb8dbc1e3efb64545b028d21c044d2 Mon Sep 17 00:00:00 2001 From: TizzySaurus <47674925+TizzySaurus@users.noreply.github.com> Date: Wed, 11 Aug 2021 16:41:45 +0100 Subject: Remove converters made redundant by dpy V1.6's UserConverter update --- bot/converters.py | 71 +------------------------------- bot/exts/moderation/infraction/_utils.py | 2 - 2 files changed, 1 insertion(+), 72 deletions(-) diff --git a/bot/converters.py b/bot/converters.py index 595809517..3df613379 100644 --- a/bot/converters.py +++ b/bot/converters.py @@ -439,29 +439,6 @@ class HushDurationConverter(Converter): return duration -def proxy_user(user_id: str) -> discord.Object: - """ - Create a proxy user object from the given id. - - Used when a Member or User object cannot be resolved. - """ - log.trace(f"Attempting to create a proxy user for the user id {user_id}.") - - try: - user_id = int(user_id) - except ValueError: - log.debug(f"Failed to create proxy user {user_id}: could not convert to int.") - raise BadArgument(f"User ID `{user_id}` is invalid - could not convert to an integer.") - - user = discord.Object(user_id) - user.mention = user.id - user.display_name = f"<@{user.id}>" - user.avatar_url_as = lambda static_format: None - user.bot = False - - return user - - class UserMentionOrID(UserConverter): """ Converts to a `discord.User`, but only if a mention or userID is provided. @@ -480,51 +457,6 @@ class UserMentionOrID(UserConverter): raise BadArgument(f"`{argument}` is not a User mention or a User ID.") -class FetchedUser(UserConverter): - """ - Converts to a `discord.User` or, if it fails, a `discord.Object`. - - Unlike the default `UserConverter`, which only does lookups via the global user cache, this - converter attempts to fetch the user via an API call to Discord when the using the cache is - unsuccessful. - - If the fetch also fails and the error doesn't imply the user doesn't exist, then a - `discord.Object` is returned via the `user_proxy` converter. - - The lookup strategy is as follows (in order): - - 1. Lookup by ID. - 2. Lookup by mention. - 3. Lookup by name#discrim - 4. Lookup by name - 5. Lookup via API - 6. Create a proxy user with discord.Object - """ - - async def convert(self, ctx: Context, arg: str) -> t.Union[discord.User, discord.Object]: - """Convert the `arg` to a `discord.User` or `discord.Object`.""" - try: - return await super().convert(ctx, arg) - except BadArgument: - pass - - try: - user_id = int(arg) - log.trace(f"Fetching user {user_id}...") - return await ctx.bot.fetch_user(user_id) - except ValueError: - log.debug(f"Failed to fetch user {arg}: could not convert to int.") - raise BadArgument(f"The provided argument can't be turned into integer: `{arg}`") - except discord.HTTPException as e: - # If the Discord error isn't `Unknown user`, return a proxy instead - if e.code != 10013: - log.info(f"Failed to fetch user, returning a proxy instead: status {e.status}") - return proxy_user(arg) - - log.debug(f"Failed to fetch user {arg}: user does not exist.") - raise BadArgument(f"User `{arg}` does not exist") - - def _snowflake_from_regex(pattern: t.Pattern, arg: str) -> int: """ Extract the snowflake from `arg` using a regex `pattern` and return it as an int. @@ -568,5 +500,4 @@ class Infraction(Converter): Expiry = t.Union[Duration, ISODateTime] -FetchedMember = t.Union[discord.Member, FetchedUser] -UserMention = partial(_snowflake_from_regex, RE_USER_MENTION) +FetchedMember = t.Union[discord.Member, discord.User] diff --git a/bot/exts/moderation/infraction/_utils.py b/bot/exts/moderation/infraction/_utils.py index a4059a6e9..e3fcda730 100644 --- a/bot/exts/moderation/infraction/_utils.py +++ b/bot/exts/moderation/infraction/_utils.py @@ -24,8 +24,6 @@ INFRACTION_ICONS = { RULES_URL = "https://pythondiscord.com/pages/rules" # Type aliases -UserObject = t.Union[discord.Member, discord.User] -UserSnowflake = t.Union[UserObject, discord.Object] Infraction = t.Dict[str, t.Union[str, int, bool]] APPEAL_EMAIL = "appeals@pythondiscord.com" -- cgit v1.2.3 From 17f3750cbe53eeb740795d77c192b5822d086a4b Mon Sep 17 00:00:00 2001 From: TizzySaurus <47674925+TizzySaurus@users.noreply.github.com> Date: Wed, 11 Aug 2021 16:51:28 +0100 Subject: Update to new converters --- bot/exts/fun/duck_pond.py | 3 ++- bot/exts/moderation/infraction/_scheduler.py | 6 +++--- bot/exts/moderation/infraction/_utils.py | 18 ++++++++---------- bot/exts/moderation/infraction/infractions.py | 5 ++--- bot/exts/moderation/infraction/management.py | 16 +++++----------- bot/exts/recruitment/talentpool/_cog.py | 2 +- 6 files changed, 21 insertions(+), 29 deletions(-) diff --git a/bot/exts/fun/duck_pond.py b/bot/exts/fun/duck_pond.py index c78b9c141..a8d927353 100644 --- a/bot/exts/fun/duck_pond.py +++ b/bot/exts/fun/duck_pond.py @@ -8,6 +8,7 @@ from discord.ext.commands import Cog, Context, command from bot import constants from bot.bot import Bot +from bot.converters import FetchedMember from bot.utils.checks import has_any_role from bot.utils.messages import count_unique_users_reaction, send_attachments from bot.utils.webhooks import send_webhook @@ -36,7 +37,7 @@ class DuckPond(Cog): log.exception(f"Failed to fetch webhook with id `{self.webhook_id}`") @staticmethod - def is_staff(member: Union[User, Member]) -> bool: + def is_staff(member: FetchedMember) -> bool: """Check if a specific member or user is staff.""" if hasattr(member, "roles"): for role in member.roles: diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 8286d3635..89869820c 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -13,8 +13,8 @@ from bot import constants from bot.api import ResponseCodeError from bot.bot import Bot from bot.constants import Colours +from bot.converters import FetchedMember from bot.exts.moderation.infraction import _utils -from bot.exts.moderation.infraction._utils import UserSnowflake from bot.exts.moderation.modlog import ModLog from bot.utils import messages, scheduling, time from bot.utils.channel import is_mod_channel @@ -115,7 +115,7 @@ class InfractionScheduler: self, ctx: Context, infraction: _utils.Infraction, - user: UserSnowflake, + user: FetchedMember, action_coro: t.Optional[t.Awaitable] = None, user_reason: t.Optional[str] = None, additional_info: str = "", @@ -264,7 +264,7 @@ class InfractionScheduler: self, ctx: Context, infr_type: str, - user: UserSnowflake, + user: FetchedMember, send_msg: bool = True ) -> None: """ diff --git a/bot/exts/moderation/infraction/_utils.py b/bot/exts/moderation/infraction/_utils.py index e3fcda730..9c3f9d804 100644 --- a/bot/exts/moderation/infraction/_utils.py +++ b/bot/exts/moderation/infraction/_utils.py @@ -7,6 +7,7 @@ from discord.ext.commands import Context from bot.api import ResponseCodeError from bot.constants import Colours, Icons +from bot.converters import FetchedMember from bot.errors import InvalidInfractedUserError log = logging.getLogger(__name__) @@ -43,7 +44,7 @@ INFRACTION_DESCRIPTION_TEMPLATE = ( ) -async def post_user(ctx: Context, user: UserSnowflake) -> t.Optional[dict]: +async def post_user(ctx: Context, user: FetchedMember) -> t.Optional[dict]: """ Create a new user in the database. @@ -51,9 +52,6 @@ async def post_user(ctx: Context, user: UserSnowflake) -> t.Optional[dict]: """ log.trace(f"Attempting to add user {user.id} to the database.") - if not isinstance(user, (discord.Member, discord.User)): - log.debug("The user being added to the DB is not a Member or User object.") - payload = { 'discriminator': int(getattr(user, 'discriminator', 0)), 'id': user.id, @@ -73,7 +71,7 @@ async def post_user(ctx: Context, user: UserSnowflake) -> t.Optional[dict]: async def post_infraction( ctx: Context, - user: UserSnowflake, + user: FetchedMember, infr_type: str, reason: str, expires_at: datetime = None, @@ -81,7 +79,7 @@ async def post_infraction( active: bool = True ) -> t.Optional[dict]: """Posts an infraction to the API.""" - if isinstance(user, (discord.Member, discord.User)) and user.bot: + if isinstance(user, FetchedMember) and user.bot: log.trace(f"Posting of {infr_type} infraction for {user} to the API aborted. User is a bot.") raise InvalidInfractedUserError(user) @@ -116,7 +114,7 @@ async def post_infraction( async def get_active_infraction( ctx: Context, - user: UserSnowflake, + user: FetchedMember, infr_type: str, send_msg: bool = True ) -> t.Optional[dict]: @@ -151,7 +149,7 @@ async def get_active_infraction( async def notify_infraction( - user: UserObject, + user: FetchedMember, infr_type: str, expires_at: t.Optional[str] = None, reason: t.Optional[str] = None, @@ -187,7 +185,7 @@ async def notify_infraction( async def notify_pardon( - user: UserObject, + user: FetchedMember, title: str, content: str, icon_url: str = Icons.user_verified @@ -205,7 +203,7 @@ async def notify_pardon( return await send_private_embed(user, embed) -async def send_private_embed(user: UserObject, embed: discord.Embed) -> bool: +async def send_private_embed(user: FetchedMember, embed: discord.Embed) -> bool: """ A helper method for sending an embed to a user's DMs. diff --git a/bot/exts/moderation/infraction/infractions.py b/bot/exts/moderation/infraction/infractions.py index f19323c7c..dfffb2b20 100644 --- a/bot/exts/moderation/infraction/infractions.py +++ b/bot/exts/moderation/infraction/infractions.py @@ -14,7 +14,6 @@ from bot.converters import Duration, Expiry, FetchedMember from bot.decorators import respect_role_hierarchy from bot.exts.moderation.infraction import _utils from bot.exts.moderation.infraction._scheduler import InfractionScheduler -from bot.exts.moderation.infraction._utils import UserSnowflake from bot.utils.messages import format_user log = logging.getLogger(__name__) @@ -320,7 +319,7 @@ class Infractions(InfractionScheduler, commands.Cog): async def apply_ban( self, ctx: Context, - user: UserSnowflake, + user: FetchedMember, reason: t.Optional[str], purge_days: t.Optional[int] = 0, **kwargs @@ -376,7 +375,7 @@ class Infractions(InfractionScheduler, commands.Cog): await bb_cog.apply_unwatch(ctx, user, bb_reason, send_message=False) @respect_role_hierarchy(member_arg=2) - async def apply_voice_ban(self, ctx: Context, user: UserSnowflake, reason: t.Optional[str], **kwargs) -> None: + async def apply_voice_ban(self, ctx: Context, user: FetchedMember, reason: t.Optional[str], **kwargs) -> None: """Apply a voice ban infraction with kwargs passed to `post_infraction`.""" if await _utils.get_active_infraction(ctx, user, "voice_ban"): return diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index 3094159cd..d1437c635 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -12,7 +12,7 @@ from discord.utils import escape_markdown from bot import constants from bot.bot import Bot -from bot.converters import Expiry, Infraction, Snowflake, UserMention, allowed_strings, proxy_user +from bot.converters import Expiry, FetchedMember, Infraction, allowed_strings from bot.exts.moderation.infraction.infractions import Infractions from bot.exts.moderation.modlog import ModLog from bot.pagination import LinePaginator @@ -201,27 +201,21 @@ class ModManagement(commands.Cog): # region: Search infractions @infraction_group.group(name="search", aliases=('s',), invoke_without_command=True) - async def infraction_search_group(self, ctx: Context, query: t.Union[UserMention, Snowflake, str]) -> None: + async def infraction_search_group(self, ctx: Context, query: t.Union[FetchedMember, str]) -> None: """Searches for infractions in the database.""" - if isinstance(query, int): - await self.search_user(ctx, discord.Object(query)) + if isinstance(query, FetchedMember): + await self.search_user(ctx, query) else: await self.search_reason(ctx, query) @infraction_search_group.command(name="user", aliases=("member", "id")) - async def search_user(self, ctx: Context, user: t.Union[discord.User, proxy_user]) -> None: + async def search_user(self, ctx: Context, user: FetchedMember) -> None: """Search for infractions by member.""" infraction_list = await self.bot.api_client.get( 'bot/infractions/expanded', params={'user__id': str(user.id)} ) - user = self.bot.get_user(user.id) - if not user and infraction_list: - # Use the user data retrieved from the DB for the username. - user = infraction_list[0]["user"] - user = escape_markdown(user["name"]) + f"#{user['discriminator']:04}" - embed = discord.Embed( title=f"Infractions for {user} ({len(infraction_list)} total)", colour=discord.Colour.orange() diff --git a/bot/exts/recruitment/talentpool/_cog.py b/bot/exts/recruitment/talentpool/_cog.py index 80bd48534..9b09c4f7b 100644 --- a/bot/exts/recruitment/talentpool/_cog.py +++ b/bot/exts/recruitment/talentpool/_cog.py @@ -417,7 +417,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): await ctx.message.add_reaction(Emojis.check_mark) @Cog.listener() - async def on_member_ban(self, guild: Guild, user: Union[User, Member]) -> None: + async def on_member_ban(self, guild: Guild, user: Union[FetchedMember]) -> None: """Remove `user` from the talent pool after they are banned.""" await self.unwatch(user.id, "User was banned.") -- cgit v1.2.3 From bb2c20fd5acf998d440c835345132bdaee34fb64 Mon Sep 17 00:00:00 2001 From: TizzySaurus <47674925+TizzySaurus@users.noreply.github.com> Date: Wed, 11 Aug 2021 17:28:13 +0100 Subject: Remove unused imports --- bot/converters.py | 1 - bot/errors.py | 2 +- bot/exts/fun/duck_pond.py | 2 +- bot/exts/recruitment/talentpool/_cog.py | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/bot/converters.py b/bot/converters.py index 3df613379..1cfbd29b8 100644 --- a/bot/converters.py +++ b/bot/converters.py @@ -2,7 +2,6 @@ import logging import re import typing as t from datetime import datetime -from functools import partial from ssl import CertificateError import dateutil.parser diff --git a/bot/errors.py b/bot/errors.py index 5785faa44..d472334d4 100644 --- a/bot/errors.py +++ b/bot/errors.py @@ -1,4 +1,4 @@ -from typing import Hashable, Union +from typing import Hashable from discord import Member, User diff --git a/bot/exts/fun/duck_pond.py b/bot/exts/fun/duck_pond.py index a8d927353..7c09e27f5 100644 --- a/bot/exts/fun/duck_pond.py +++ b/bot/exts/fun/duck_pond.py @@ -3,7 +3,7 @@ import logging from typing import Union import discord -from discord import Color, Embed, Member, Message, RawReactionActionEvent, TextChannel, User, errors +from discord import Color, Embed, Message, RawReactionActionEvent, TextChannel, errors from discord.ext.commands import Cog, Context, command from bot import constants diff --git a/bot/exts/recruitment/talentpool/_cog.py b/bot/exts/recruitment/talentpool/_cog.py index 9b09c4f7b..304bdafba 100644 --- a/bot/exts/recruitment/talentpool/_cog.py +++ b/bot/exts/recruitment/talentpool/_cog.py @@ -6,7 +6,7 @@ from typing import Union import discord from async_rediscache import RedisCache -from discord import Color, Embed, Member, PartialMessage, RawReactionActionEvent, User +from discord import Color, Embed, Member, PartialMessage, RawReactionActionEvent from discord.ext.commands import Cog, Context, group, has_any_role from bot.api import ResponseCodeError -- cgit v1.2.3 From ad873f91aadb7698c3fd73e1e263ad7bc0ca21e9 Mon Sep 17 00:00:00 2001 From: Izan Date: Wed, 11 Aug 2021 18:53:05 +0100 Subject: Rename converter from FetchedMember to MemberOrUser --- bot/converters.py | 2 +- bot/errors.py | 5 ++-- bot/exts/fun/duck_pond.py | 4 +-- bot/exts/info/information.py | 14 +++++----- bot/exts/moderation/infraction/_scheduler.py | 6 ++--- bot/exts/moderation/infraction/_utils.py | 16 ++++++------ bot/exts/moderation/infraction/infractions.py | 34 ++++++++++++------------- bot/exts/moderation/infraction/management.py | 8 +++--- bot/exts/moderation/watchchannels/bigbrother.py | 10 ++++---- bot/exts/recruitment/talentpool/_cog.py | 16 ++++++------ 10 files changed, 58 insertions(+), 57 deletions(-) diff --git a/bot/converters.py b/bot/converters.py index 1cfbd29b8..ff9f6e5d9 100644 --- a/bot/converters.py +++ b/bot/converters.py @@ -499,4 +499,4 @@ class Infraction(Converter): Expiry = t.Union[Duration, ISODateTime] -FetchedMember = t.Union[discord.Member, discord.User] +MemberOrUser = t.Union[discord.Member, discord.User] diff --git a/bot/errors.py b/bot/errors.py index d472334d4..5186aa3bb 100644 --- a/bot/errors.py +++ b/bot/errors.py @@ -1,6 +1,6 @@ from typing import Hashable -from discord import Member, User +from converters import MemberOrUser class LockedResourceError(RuntimeError): @@ -30,7 +30,8 @@ class InvalidInfractedUserError(Exception): `user` -- User or Member which is invalid """ - def __init__(self, user: Union[Member, User], reason: str = "User infracted is a bot."): + def __init__(self, user: MemberOrUser, reason: str = "User infracted is a bot."): + self.user = user self.reason = reason diff --git a/bot/exts/fun/duck_pond.py b/bot/exts/fun/duck_pond.py index 7c09e27f5..0ac985139 100644 --- a/bot/exts/fun/duck_pond.py +++ b/bot/exts/fun/duck_pond.py @@ -8,7 +8,7 @@ from discord.ext.commands import Cog, Context, command from bot import constants from bot.bot import Bot -from bot.converters import FetchedMember +from bot.converters import MemberOrUser from bot.utils.checks import has_any_role from bot.utils.messages import count_unique_users_reaction, send_attachments from bot.utils.webhooks import send_webhook @@ -37,7 +37,7 @@ class DuckPond(Cog): log.exception(f"Failed to fetch webhook with id `{self.webhook_id}`") @staticmethod - def is_staff(member: FetchedMember) -> bool: + def is_staff(member: MemberOrUser) -> bool: """Check if a specific member or user is staff.""" if hasattr(member, "roles"): for role in member.roles: diff --git a/bot/exts/info/information.py b/bot/exts/info/information.py index 167731e64..ff3fb9408 100644 --- a/bot/exts/info/information.py +++ b/bot/exts/info/information.py @@ -12,7 +12,7 @@ from discord.ext.commands import BucketType, Cog, Context, Paginator, command, g from bot import constants from bot.api import ResponseCodeError from bot.bot import Bot -from bot.converters import FetchedMember +from bot.converters import MemberOrUser from bot.decorators import in_whitelist from bot.errors import NonExistentRoleError from bot.pagination import LinePaginator @@ -220,7 +220,7 @@ class Information(Cog): await ctx.send(embed=embed) @command(name="user", aliases=["user_info", "member", "member_info", "u"]) - async def user_info(self, ctx: Context, user: FetchedMember = None) -> None: + async def user_info(self, ctx: Context, user: MemberOrUser = None) -> None: """Returns info about a user.""" if user is None: user = ctx.author @@ -235,7 +235,7 @@ class Information(Cog): embed = await self.create_user_embed(ctx, user) await ctx.send(embed=embed) - async def create_user_embed(self, ctx: Context, user: FetchedMember) -> Embed: + 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)) @@ -307,7 +307,7 @@ class Information(Cog): return embed - async def basic_user_infraction_counts(self, user: FetchedMember) -> Tuple[str, str]: + async def basic_user_infraction_counts(self, user: MemberOrUser) -> Tuple[str, str]: """Gets the total and active infraction counts for the given `member`.""" infractions = await self.bot.api_client.get( 'bot/infractions', @@ -324,7 +324,7 @@ class Information(Cog): return "Infractions", infraction_output - async def expanded_user_infraction_counts(self, user: FetchedMember) -> Tuple[str, str]: + async def expanded_user_infraction_counts(self, user: MemberOrUser) -> Tuple[str, str]: """ Gets expanded infraction counts for the given `member`. @@ -365,7 +365,7 @@ class Information(Cog): return "Infractions", "\n".join(infraction_output) - async def user_nomination_counts(self, user: FetchedMember) -> Tuple[str, str]: + async def user_nomination_counts(self, user: MemberOrUser) -> Tuple[str, str]: """Gets the active and historical nomination counts for the given `member`.""" nominations = await self.bot.api_client.get( 'bot/nominations', @@ -390,7 +390,7 @@ class Information(Cog): return "Nominations", "\n".join(output) - async def user_messages(self, user: FetchedMember) -> Tuple[Union[bool, str], Tuple[str, str]]: + async def user_messages(self, user: MemberOrUser) -> Tuple[Union[bool, str], Tuple[str, str]]: """ Gets the amount of messages for `member`. diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 89869820c..13f59bb76 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -13,7 +13,7 @@ from bot import constants from bot.api import ResponseCodeError from bot.bot import Bot from bot.constants import Colours -from bot.converters import FetchedMember +from bot.converters import MemberOrUser from bot.exts.moderation.infraction import _utils from bot.exts.moderation.modlog import ModLog from bot.utils import messages, scheduling, time @@ -115,7 +115,7 @@ class InfractionScheduler: self, ctx: Context, infraction: _utils.Infraction, - user: FetchedMember, + user: MemberOrUser, action_coro: t.Optional[t.Awaitable] = None, user_reason: t.Optional[str] = None, additional_info: str = "", @@ -264,7 +264,7 @@ class InfractionScheduler: self, ctx: Context, infr_type: str, - user: FetchedMember, + user: MemberOrUser, send_msg: bool = True ) -> None: """ diff --git a/bot/exts/moderation/infraction/_utils.py b/bot/exts/moderation/infraction/_utils.py index 9c3f9d804..fe9815600 100644 --- a/bot/exts/moderation/infraction/_utils.py +++ b/bot/exts/moderation/infraction/_utils.py @@ -7,7 +7,7 @@ from discord.ext.commands import Context from bot.api import ResponseCodeError from bot.constants import Colours, Icons -from bot.converters import FetchedMember +from bot.converters import MemberOrUser from bot.errors import InvalidInfractedUserError log = logging.getLogger(__name__) @@ -44,7 +44,7 @@ INFRACTION_DESCRIPTION_TEMPLATE = ( ) -async def post_user(ctx: Context, user: FetchedMember) -> t.Optional[dict]: +async def post_user(ctx: Context, user: MemberOrUser) -> t.Optional[dict]: """ Create a new user in the database. @@ -71,7 +71,7 @@ async def post_user(ctx: Context, user: FetchedMember) -> t.Optional[dict]: async def post_infraction( ctx: Context, - user: FetchedMember, + user: MemberOrUser, infr_type: str, reason: str, expires_at: datetime = None, @@ -79,7 +79,7 @@ async def post_infraction( active: bool = True ) -> t.Optional[dict]: """Posts an infraction to the API.""" - if isinstance(user, FetchedMember) and user.bot: + if isinstance(user, MemberOrUser) and user.bot: log.trace(f"Posting of {infr_type} infraction for {user} to the API aborted. User is a bot.") raise InvalidInfractedUserError(user) @@ -114,7 +114,7 @@ async def post_infraction( async def get_active_infraction( ctx: Context, - user: FetchedMember, + user: MemberOrUser, infr_type: str, send_msg: bool = True ) -> t.Optional[dict]: @@ -149,7 +149,7 @@ async def get_active_infraction( async def notify_infraction( - user: FetchedMember, + user: MemberOrUser, infr_type: str, expires_at: t.Optional[str] = None, reason: t.Optional[str] = None, @@ -185,7 +185,7 @@ async def notify_infraction( async def notify_pardon( - user: FetchedMember, + user: MemberOrUser, title: str, content: str, icon_url: str = Icons.user_verified @@ -203,7 +203,7 @@ async def notify_pardon( return await send_private_embed(user, embed) -async def send_private_embed(user: FetchedMember, embed: discord.Embed) -> bool: +async def send_private_embed(user: MemberOrUser, embed: discord.Embed) -> bool: """ A helper method for sending an embed to a user's DMs. diff --git a/bot/exts/moderation/infraction/infractions.py b/bot/exts/moderation/infraction/infractions.py index dfffb2b20..48ffbd773 100644 --- a/bot/exts/moderation/infraction/infractions.py +++ b/bot/exts/moderation/infraction/infractions.py @@ -10,7 +10,7 @@ from discord.ext.commands import Context, command from bot import constants from bot.bot import Bot from bot.constants import Event -from bot.converters import Duration, Expiry, FetchedMember +from bot.converters import Duration, Expiry, MemberOrUser from bot.decorators import respect_role_hierarchy from bot.exts.moderation.infraction import _utils from bot.exts.moderation.infraction._scheduler import InfractionScheduler @@ -53,7 +53,7 @@ class Infractions(InfractionScheduler, commands.Cog): # region: Permanent infractions @command() - async def warn(self, ctx: Context, user: FetchedMember, *, reason: t.Optional[str] = None) -> None: + async def warn(self, ctx: Context, user: MemberOrUser, *, reason: t.Optional[str] = None) -> None: """Warn a user for the given reason.""" if not isinstance(user, Member): await ctx.send(":x: The user doesn't appear to be on the server.") @@ -66,7 +66,7 @@ class Infractions(InfractionScheduler, commands.Cog): await self.apply_infraction(ctx, infraction, user) @command() - async def kick(self, ctx: Context, user: FetchedMember, *, reason: t.Optional[str] = None) -> None: + async def kick(self, ctx: Context, user: MemberOrUser, *, reason: t.Optional[str] = None) -> None: """Kick a user for the given reason.""" if not isinstance(user, Member): await ctx.send(":x: The user doesn't appear to be on the server.") @@ -78,7 +78,7 @@ class Infractions(InfractionScheduler, commands.Cog): async def ban( self, ctx: Context, - user: FetchedMember, + user: MemberOrUser, duration: t.Optional[Expiry] = None, *, reason: t.Optional[str] = None @@ -94,7 +94,7 @@ class Infractions(InfractionScheduler, commands.Cog): async def purgeban( self, ctx: Context, - user: FetchedMember, + user: MemberOrUser, duration: t.Optional[Expiry] = None, *, reason: t.Optional[str] = None @@ -110,7 +110,7 @@ class Infractions(InfractionScheduler, commands.Cog): async def voiceban( self, ctx: Context, - user: FetchedMember, + user: MemberOrUser, duration: t.Optional[Expiry] = None, *, reason: t.Optional[str] @@ -128,7 +128,7 @@ class Infractions(InfractionScheduler, commands.Cog): @command(aliases=["mute"]) async def tempmute( self, ctx: Context, - user: FetchedMember, + user: MemberOrUser, duration: t.Optional[Expiry] = None, *, reason: t.Optional[str] = None @@ -162,7 +162,7 @@ class Infractions(InfractionScheduler, commands.Cog): async def tempban( self, ctx: Context, - user: FetchedMember, + user: MemberOrUser, duration: Expiry, *, reason: t.Optional[str] = None @@ -188,7 +188,7 @@ class Infractions(InfractionScheduler, commands.Cog): async def tempvoiceban( self, ctx: Context, - user: FetchedMember, + user: MemberOrUser, duration: Expiry, *, reason: t.Optional[str] @@ -214,7 +214,7 @@ class Infractions(InfractionScheduler, commands.Cog): # region: Permanent shadow infractions @command(hidden=True) - async def note(self, ctx: Context, user: FetchedMember, *, reason: t.Optional[str] = None) -> None: + async def note(self, ctx: Context, user: MemberOrUser, *, reason: t.Optional[str] = None) -> None: """Create a private note for a user with the given reason without notifying the user.""" infraction = await _utils.post_infraction(ctx, user, "note", reason, hidden=True, active=False) if infraction is None: @@ -223,7 +223,7 @@ class Infractions(InfractionScheduler, commands.Cog): await self.apply_infraction(ctx, infraction, user) @command(hidden=True, aliases=['shadowban', 'sban']) - async def shadow_ban(self, ctx: Context, user: FetchedMember, *, reason: t.Optional[str] = None) -> None: + async def shadow_ban(self, ctx: Context, user: MemberOrUser, *, reason: t.Optional[str] = None) -> None: """Permanently ban a user for the given reason without notifying the user.""" await self.apply_ban(ctx, user, reason, hidden=True) @@ -234,7 +234,7 @@ class Infractions(InfractionScheduler, commands.Cog): async def shadow_tempban( self, ctx: Context, - user: FetchedMember, + user: MemberOrUser, duration: Expiry, *, reason: t.Optional[str] = None @@ -260,17 +260,17 @@ class Infractions(InfractionScheduler, commands.Cog): # region: Remove infractions (un- commands) @command() - async def unmute(self, ctx: Context, user: FetchedMember) -> None: + async def unmute(self, ctx: Context, user: MemberOrUser) -> None: """Prematurely end the active mute infraction for the user.""" await self.pardon_infraction(ctx, "mute", user) @command() - async def unban(self, ctx: Context, user: FetchedMember) -> None: + async def unban(self, ctx: Context, user: MemberOrUser) -> None: """Prematurely end the active ban infraction for the user.""" await self.pardon_infraction(ctx, "ban", user) @command(aliases=("uvban",)) - async def unvoiceban(self, ctx: Context, user: FetchedMember) -> None: + async def unvoiceban(self, ctx: Context, user: MemberOrUser) -> None: """Prematurely end the active voice ban infraction for the user.""" await self.pardon_infraction(ctx, "voice_ban", user) @@ -319,7 +319,7 @@ class Infractions(InfractionScheduler, commands.Cog): async def apply_ban( self, ctx: Context, - user: FetchedMember, + user: MemberOrUser, reason: t.Optional[str], purge_days: t.Optional[int] = 0, **kwargs @@ -375,7 +375,7 @@ class Infractions(InfractionScheduler, commands.Cog): await bb_cog.apply_unwatch(ctx, user, bb_reason, send_message=False) @respect_role_hierarchy(member_arg=2) - async def apply_voice_ban(self, ctx: Context, user: FetchedMember, reason: t.Optional[str], **kwargs) -> None: + async def apply_voice_ban(self, ctx: Context, user: MemberOrUser, reason: t.Optional[str], **kwargs) -> None: """Apply a voice ban infraction with kwargs passed to `post_infraction`.""" if await _utils.get_active_infraction(ctx, user, "voice_ban"): return diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index d1437c635..68ebab8ba 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -12,7 +12,7 @@ from discord.utils import escape_markdown from bot import constants from bot.bot import Bot -from bot.converters import Expiry, FetchedMember, Infraction, allowed_strings +from bot.converters import Expiry, MemberOrUser, Infraction, allowed_strings from bot.exts.moderation.infraction.infractions import Infractions from bot.exts.moderation.modlog import ModLog from bot.pagination import LinePaginator @@ -201,15 +201,15 @@ class ModManagement(commands.Cog): # region: Search infractions @infraction_group.group(name="search", aliases=('s',), invoke_without_command=True) - async def infraction_search_group(self, ctx: Context, query: t.Union[FetchedMember, str]) -> None: + async def infraction_search_group(self, ctx: Context, query: t.Union[MemberOrUser, str]) -> None: """Searches for infractions in the database.""" - if isinstance(query, FetchedMember): + if isinstance(query, MemberOrUser): await self.search_user(ctx, query) else: await self.search_reason(ctx, query) @infraction_search_group.command(name="user", aliases=("member", "id")) - async def search_user(self, ctx: Context, user: FetchedMember) -> None: + async def search_user(self, ctx: Context, user: MemberOrUser) -> None: """Search for infractions by member.""" infraction_list = await self.bot.api_client.get( 'bot/infractions/expanded', diff --git a/bot/exts/moderation/watchchannels/bigbrother.py b/bot/exts/moderation/watchchannels/bigbrother.py index c6ee844ef..4ee69ec9b 100644 --- a/bot/exts/moderation/watchchannels/bigbrother.py +++ b/bot/exts/moderation/watchchannels/bigbrother.py @@ -6,7 +6,7 @@ from discord.ext.commands import Cog, Context, group, has_any_role from bot.bot import Bot from bot.constants import Channels, MODERATION_ROLES, Webhooks -from bot.converters import FetchedMember +from bot.converters import MemberOrUser from bot.exts.moderation.infraction._utils import post_infraction from bot.exts.moderation.watchchannels._watchchannel import WatchChannel @@ -60,7 +60,7 @@ class BigBrother(WatchChannel, Cog, name="Big Brother"): @bigbrother_group.command(name='watch', aliases=('w',), root_aliases=('watch',)) @has_any_role(*MODERATION_ROLES) - async def watch_command(self, ctx: Context, user: FetchedMember, *, reason: str) -> None: + async def watch_command(self, ctx: Context, user: MemberOrUser, *, reason: str) -> None: """ Relay messages sent by the given `user` to the `#big-brother` channel. @@ -71,11 +71,11 @@ class BigBrother(WatchChannel, Cog, name="Big Brother"): @bigbrother_group.command(name='unwatch', aliases=('uw',), root_aliases=('unwatch',)) @has_any_role(*MODERATION_ROLES) - async def unwatch_command(self, ctx: Context, user: FetchedMember, *, reason: str) -> None: + async def unwatch_command(self, ctx: Context, user: MemberOrUser, *, reason: str) -> None: """Stop relaying messages by the given `user`.""" await self.apply_unwatch(ctx, user, reason) - async def apply_watch(self, ctx: Context, user: FetchedMember, reason: str) -> None: + async def apply_watch(self, ctx: Context, user: MemberOrUser, reason: str) -> None: """ Add `user` to watched users and apply a watch infraction with `reason`. @@ -125,7 +125,7 @@ class BigBrother(WatchChannel, Cog, name="Big Brother"): await ctx.send(msg) - async def apply_unwatch(self, ctx: Context, user: FetchedMember, reason: str, send_message: bool = True) -> None: + async def apply_unwatch(self, ctx: Context, user: MemberOrUser, reason: str, send_message: bool = True) -> None: """ Remove `user` from watched users and mark their infraction as inactive with `reason`. diff --git a/bot/exts/recruitment/talentpool/_cog.py b/bot/exts/recruitment/talentpool/_cog.py index 304bdafba..5c1a1cd3f 100644 --- a/bot/exts/recruitment/talentpool/_cog.py +++ b/bot/exts/recruitment/talentpool/_cog.py @@ -12,7 +12,7 @@ from discord.ext.commands import Cog, Context, group, has_any_role from bot.api import ResponseCodeError from bot.bot import Bot from bot.constants import Channels, Emojis, Guild, MODERATION_ROLES, Roles, STAFF_ROLES, Webhooks -from bot.converters import FetchedMember +from bot.converters import MemberOrUser from bot.exts.moderation.watchchannels._watchchannel import WatchChannel from bot.exts.recruitment.talentpool._review import Reviewer from bot.pagination import LinePaginator @@ -178,7 +178,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): @nomination_group.command(name='forcewatch', aliases=('fw', 'forceadd', 'fa'), root_aliases=("forcenominate",)) @has_any_role(*MODERATION_ROLES) - async def force_watch_command(self, ctx: Context, user: FetchedMember, *, reason: str = '') -> None: + async def force_watch_command(self, ctx: Context, user: MemberOrUser, *, reason: str = '') -> None: """ Adds the given `user` to the talent pool, from any channel. @@ -188,7 +188,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): @nomination_group.command(name='watch', aliases=('w', 'add', 'a'), root_aliases=("nominate",)) @has_any_role(*STAFF_ROLES) - async def watch_command(self, ctx: Context, user: FetchedMember, *, reason: str = '') -> None: + async def watch_command(self, ctx: Context, user: MemberOrUser, *, reason: str = '') -> None: """ Adds the given `user` to the talent pool. @@ -207,7 +207,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): await self._watch_user(ctx, user, reason) - async def _watch_user(self, ctx: Context, user: FetchedMember, reason: str) -> None: + async def _watch_user(self, ctx: Context, user: MemberOrUser, reason: str) -> None: """Adds the given user to the talent pool.""" if user.bot: await ctx.send(f":x: I'm sorry {ctx.author}, I'm afraid I can't do that. I only watch humans.") @@ -271,7 +271,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): @nomination_group.command(name='history', aliases=('info', 'search')) @has_any_role(*MODERATION_ROLES) - async def history_command(self, ctx: Context, user: FetchedMember) -> None: + async def history_command(self, ctx: Context, user: MemberOrUser) -> None: """Shows the specified user's nomination history.""" result = await self.bot.api_client.get( self.api_endpoint, @@ -300,7 +300,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): @nomination_group.command(name='unwatch', aliases=('end', ), root_aliases=("unnominate",)) @has_any_role(*MODERATION_ROLES) - async def unwatch_command(self, ctx: Context, user: FetchedMember, *, reason: str) -> None: + async def unwatch_command(self, ctx: Context, user: MemberOrUser, *, reason: str) -> None: """ Ends the active nomination of the specified user with the given reason. @@ -323,7 +323,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): @nomination_edit_group.command(name='reason') @has_any_role(*MODERATION_ROLES) - async def edit_reason_command(self, ctx: Context, nomination_id: int, actor: FetchedMember, *, reason: str) -> None: + async def edit_reason_command(self, ctx: Context, nomination_id: int, actor: MemberOrUser, *, reason: str) -> None: """Edits the reason of a specific nominator in a specific active nomination.""" if len(reason) > REASON_MAX_CHARS: await ctx.send(f":x: Maxiumum allowed characters for the reason is {REASON_MAX_CHARS}.") @@ -417,7 +417,7 @@ class TalentPool(WatchChannel, Cog, name="Talentpool"): await ctx.message.add_reaction(Emojis.check_mark) @Cog.listener() - async def on_member_ban(self, guild: Guild, user: Union[FetchedMember]) -> None: + async def on_member_ban(self, guild: Guild, user: Union[MemberOrUser]) -> None: """Remove `user` from the talent pool after they are banned.""" await self.unwatch(user.id, "User was banned.") -- cgit v1.2.3 From 4c8d7754ec1879acf43925f3bc2c998d2890385f Mon Sep 17 00:00:00 2001 From: Izan Date: Wed, 11 Aug 2021 19:08:20 +0100 Subject: Fix import order --- bot/exts/moderation/infraction/management.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index 68ebab8ba..e2755efc5 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -12,7 +12,7 @@ from discord.utils import escape_markdown from bot import constants from bot.bot import Bot -from bot.converters import Expiry, MemberOrUser, Infraction, allowed_strings +from bot.converters import Expiry, Infraction, MemberOrUser, allowed_strings from bot.exts.moderation.infraction.infractions import Infractions from bot.exts.moderation.modlog import ModLog from bot.pagination import LinePaginator -- cgit v1.2.3 From 22268276556d568f6d254fe2715f509c213119e3 Mon Sep 17 00:00:00 2001 From: Izan Date: Wed, 11 Aug 2021 19:14:36 +0100 Subject: Fix import --- bot/errors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/errors.py b/bot/errors.py index 5186aa3bb..08396ec3e 100644 --- a/bot/errors.py +++ b/bot/errors.py @@ -1,6 +1,6 @@ from typing import Hashable -from converters import MemberOrUser +from bot.converters import MemberOrUser class LockedResourceError(RuntimeError): -- cgit v1.2.3 From aa8c455f9ef919cfc21f0a99cae5a878ec57853f Mon Sep 17 00:00:00 2001 From: Izan Date: Wed, 11 Aug 2021 19:56:10 +0100 Subject: Fix isinstance check --- bot/exts/moderation/infraction/_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/moderation/infraction/_utils.py b/bot/exts/moderation/infraction/_utils.py index fe9815600..827623936 100644 --- a/bot/exts/moderation/infraction/_utils.py +++ b/bot/exts/moderation/infraction/_utils.py @@ -79,7 +79,7 @@ async def post_infraction( active: bool = True ) -> t.Optional[dict]: """Posts an infraction to the API.""" - if isinstance(user, MemberOrUser) and user.bot: + if isinstance(user, (discord.Member, discord.User)) and user.bot: log.trace(f"Posting of {infr_type} infraction for {user} to the API aborted. User is a bot.") raise InvalidInfractedUserError(user) -- cgit v1.2.3 From 4e6af7be36da47cdd083ef27e4757f809b09aafd Mon Sep 17 00:00:00 2001 From: Izan Date: Wed, 11 Aug 2021 23:34:19 +0100 Subject: Remove redundant function --- bot/converters.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/bot/converters.py b/bot/converters.py index ff9f6e5d9..37eb91c7f 100644 --- a/bot/converters.py +++ b/bot/converters.py @@ -456,19 +456,6 @@ class UserMentionOrID(UserConverter): raise BadArgument(f"`{argument}` is not a User mention or a User ID.") -def _snowflake_from_regex(pattern: t.Pattern, arg: str) -> int: - """ - Extract the snowflake from `arg` using a regex `pattern` and return it as an int. - - The snowflake is expected to be within the first capture group in `pattern`. - """ - match = pattern.match(arg) - if not match: - raise BadArgument(f"Mention {str!r} is invalid.") - - return int(match.group(1)) - - class Infraction(Converter): """ Attempts to convert a given infraction ID into an infraction. -- cgit v1.2.3 From c90908effae17aba4f656516b306f40c8844bd40 Mon Sep 17 00:00:00 2001 From: Izan Date: Thu, 12 Aug 2021 00:07:11 +0100 Subject: Re-add ability to search infractions of deleted account --- bot/exts/moderation/infraction/management.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index e2755efc5..058bc9db0 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -12,7 +12,7 @@ from discord.utils import escape_markdown from bot import constants from bot.bot import Bot -from bot.converters import Expiry, Infraction, MemberOrUser, allowed_strings +from bot.converters import Expiry, Infraction, MemberOrUser, Snowflake, allowed_strings from bot.exts.moderation.infraction.infractions import Infractions from bot.exts.moderation.modlog import ModLog from bot.pagination import LinePaginator @@ -201,21 +201,24 @@ class ModManagement(commands.Cog): # region: Search infractions @infraction_group.group(name="search", aliases=('s',), invoke_without_command=True) - async def infraction_search_group(self, ctx: Context, query: t.Union[MemberOrUser, str]) -> None: + async def infraction_search_group(self, ctx: Context, query: t.Union[MemberOrUser, Snowflake, str]) -> None: """Searches for infractions in the database.""" - if isinstance(query, MemberOrUser): - await self.search_user(ctx, query) - else: + if isinstance(query, int): + await self.search_user(ctx, discord.Object(query)) + elif isinstance(query, str): await self.search_reason(ctx, query) + else: + await self.search_user(ctx, query) @infraction_search_group.command(name="user", aliases=("member", "id")) - async def search_user(self, ctx: Context, user: MemberOrUser) -> None: + async def search_user(self, ctx: Context, user: t.Union[MemberOrUser, discord.Object]) -> None: """Search for infractions by member.""" infraction_list = await self.bot.api_client.get( 'bot/infractions/expanded', params={'user__id': str(user.id)} ) + user_string = str(user if isinstance(user, (discord.Member, discord.User)) else user.id) embed = discord.Embed( title=f"Infractions for {user} ({len(infraction_list)} total)", colour=discord.Colour.orange() -- cgit v1.2.3 From 9770d2ed7d9b0ce92e0284f9c96d0944e331509c Mon Sep 17 00:00:00 2001 From: Izan Date: Fri, 13 Aug 2021 10:16:17 +0100 Subject: Add missing call to `escape_markdown` --- bot/exts/moderation/infraction/management.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index 058bc9db0..725e8798c 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -218,9 +218,13 @@ class ModManagement(commands.Cog): params={'user__id': str(user.id)} ) - user_string = str(user if isinstance(user, (discord.Member, discord.User)) else user.id) + if isinstance(user, (discord.Member, discord.User)): + user_str = escape_markdown(user.name) + user.discriminator + else: + user_str = str(user.id) + embed = discord.Embed( - title=f"Infractions for {user} ({len(infraction_list)} total)", + title=f"Infractions for {user_str} ({len(infraction_list)} total)", colour=discord.Colour.orange() ) await self.send_infraction_list(ctx, embed, infraction_list) -- cgit v1.2.3 From 39818408bcd9ca2a65d2459a216c81db39c80d18 Mon Sep 17 00:00:00 2001 From: Izan Date: Fri, 13 Aug 2021 10:18:31 +0100 Subject: Remove redundant fetching of user code --- bot/exts/moderation/infraction/_scheduler.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 13f59bb76..3c5e5d3bf 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -165,17 +165,10 @@ class InfractionScheduler: dm_result = f"{constants.Emojis.failmail} " dm_log_text = "\nDM: **Failed**" - # Sometimes user is a discord.Object; make it a proper user. - try: - if not isinstance(user, (discord.Member, discord.User)): - user = await self.bot.fetch_user(user.id) - except discord.HTTPException as e: - log.error(f"Failed to DM {user.id}: could not fetch user (status {e.status})") - else: - # Accordingly display whether the user was successfully notified via DM. - if await _utils.notify_infraction(user, infr_type.replace("_", " ").title(), expiry, user_reason, icon): - dm_result = ":incoming_envelope: " - dm_log_text = "\nDM: Sent" + # Accordingly display whether the user was successfully notified via DM. + if await _utils.notify_infraction(user, infr_type.replace("_", " ").title(), expiry, user_reason, icon): + dm_result = ":incoming_envelope: " + dm_log_text = "\nDM: Sent" end_msg = "" if infraction["actor"] == self.bot.user.id: -- cgit v1.2.3 From 59aeaab40655a3bc91264e24802d2bc6e02d3372 Mon Sep 17 00:00:00 2001 From: Izan Date: Fri, 13 Aug 2021 10:22:02 +0100 Subject: Remove redundant getattr protection --- bot/exts/moderation/infraction/_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/exts/moderation/infraction/_utils.py b/bot/exts/moderation/infraction/_utils.py index 827623936..9d94bca2d 100644 --- a/bot/exts/moderation/infraction/_utils.py +++ b/bot/exts/moderation/infraction/_utils.py @@ -53,10 +53,10 @@ async def post_user(ctx: Context, user: MemberOrUser) -> t.Optional[dict]: log.trace(f"Attempting to add user {user.id} to the database.") payload = { - 'discriminator': int(getattr(user, 'discriminator', 0)), + 'discriminator': int(user.discriminator), 'id': user.id, 'in_guild': False, - 'name': getattr(user, 'name', 'Name unknown'), + 'name': user.name, 'roles': [] } -- cgit v1.2.3 From 36d0ea88dc4ac071778355de948e7f06420f1c41 Mon Sep 17 00:00:00 2001 From: Izan Date: Sat, 14 Aug 2021 09:53:53 +0100 Subject: Attempt to get user from DB when discord.Object passed to search_user --- bot/exts/moderation/infraction/management.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index 725e8798c..b05b051cc 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -219,9 +219,13 @@ class ModManagement(commands.Cog): ) if isinstance(user, (discord.Member, discord.User)): - user_str = escape_markdown(user.name) + user.discriminator + user_str = escape_markdown(str(user)) else: - user_str = str(user.id) + if infraction_list: + user = infraction_list[0]["user"] + user_str = escape_markdown(user["name"]) + f"#{user['discriminator']:04}" + else: + user_str = str(user.id) embed = discord.Embed( title=f"Infractions for {user_str} ({len(infraction_list)} total)", -- cgit v1.2.3 From df23edb837ac1d50821976605208dc51c54f5c6c Mon Sep 17 00:00:00 2001 From: Izan Date: Fri, 20 Aug 2021 09:12:54 +0100 Subject: Update `infraction_search_group` typehint to `UserMentionOrId` --- bot/exts/moderation/infraction/management.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index b05b051cc..9ff30da59 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -12,7 +12,7 @@ from discord.utils import escape_markdown from bot import constants from bot.bot import Bot -from bot.converters import Expiry, Infraction, MemberOrUser, Snowflake, allowed_strings +from bot.converters import Expiry, Infraction, Snowflake, UserMentionOrID, allowed_strings from bot.exts.moderation.infraction.infractions import Infractions from bot.exts.moderation.modlog import ModLog from bot.pagination import LinePaginator @@ -201,7 +201,7 @@ class ModManagement(commands.Cog): # region: Search infractions @infraction_group.group(name="search", aliases=('s',), invoke_without_command=True) - async def infraction_search_group(self, ctx: Context, query: t.Union[MemberOrUser, Snowflake, str]) -> None: + async def infraction_search_group(self, ctx: Context, query: t.Union[UserMentionOrID, Snowflake, str]) -> None: """Searches for infractions in the database.""" if isinstance(query, int): await self.search_user(ctx, discord.Object(query)) @@ -211,7 +211,7 @@ class ModManagement(commands.Cog): await self.search_user(ctx, query) @infraction_search_group.command(name="user", aliases=("member", "id")) - async def search_user(self, ctx: Context, user: t.Union[MemberOrUser, discord.Object]) -> None: + async def search_user(self, ctx: Context, user: t.Union[UserMentionOrID, discord.Object]) -> None: """Search for infractions by member.""" infraction_list = await self.bot.api_client.get( 'bot/infractions/expanded', -- cgit v1.2.3 From 4e158b2a64e6f640847f0f7d2f229c96cecb2c46 Mon Sep 17 00:00:00 2001 From: Izan Date: Sat, 21 Aug 2021 22:07:29 +0100 Subject: Revert `search_user` typehint back to `MemberOrUser` --- bot/exts/moderation/infraction/management.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/exts/moderation/infraction/management.py b/bot/exts/moderation/infraction/management.py index 9ff30da59..641ad0410 100644 --- a/bot/exts/moderation/infraction/management.py +++ b/bot/exts/moderation/infraction/management.py @@ -12,7 +12,7 @@ from discord.utils import escape_markdown from bot import constants from bot.bot import Bot -from bot.converters import Expiry, Infraction, Snowflake, UserMentionOrID, allowed_strings +from bot.converters import Expiry, Infraction, MemberOrUser, Snowflake, UserMentionOrID, allowed_strings from bot.exts.moderation.infraction.infractions import Infractions from bot.exts.moderation.modlog import ModLog from bot.pagination import LinePaginator @@ -211,7 +211,7 @@ class ModManagement(commands.Cog): await self.search_user(ctx, query) @infraction_search_group.command(name="user", aliases=("member", "id")) - async def search_user(self, ctx: Context, user: t.Union[UserMentionOrID, discord.Object]) -> None: + async def search_user(self, ctx: Context, user: t.Union[MemberOrUser, discord.Object]) -> None: """Search for infractions by member.""" infraction_list = await self.bot.api_client.get( 'bot/infractions/expanded', -- cgit v1.2.3 From 9c41f0bf3c9487a01f7b5aca32c8b288b99ac382 Mon Sep 17 00:00:00 2001 From: Izan Date: Sun, 22 Aug 2021 21:48:34 +0100 Subject: Update outdated comment --- bot/exts/moderation/watchchannels/bigbrother.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/moderation/watchchannels/bigbrother.py b/bot/exts/moderation/watchchannels/bigbrother.py index 4ee69ec9b..3aa253fea 100644 --- a/bot/exts/moderation/watchchannels/bigbrother.py +++ b/bot/exts/moderation/watchchannels/bigbrother.py @@ -94,7 +94,7 @@ class BigBrother(WatchChannel, Cog, name="Big Brother"): await ctx.send(f":x: {user} is already being watched.") return - # FetchedUser instances don't have a roles attribute + # discord.User instances don't have a roles attribute if hasattr(user, "roles") and any(role.id in MODERATION_ROLES for role in user.roles): await ctx.send(f":x: I'm sorry {ctx.author}, I'm afraid I can't do that. I must be kind to my masters.") return -- cgit v1.2.3