aboutsummaryrefslogtreecommitdiffstats
path: root/bot/converters.py
diff options
context:
space:
mode:
Diffstat (limited to 'bot/converters.py')
-rw-r--r--bot/converters.py52
1 files changed, 52 insertions, 0 deletions
diff --git a/bot/converters.py b/bot/converters.py
index 8d2ab7eb8..a2e445d74 100644
--- a/bot/converters.py
+++ b/bot/converters.py
@@ -278,3 +278,55 @@ class ISODateTime(Converter):
dt = dt.replace(tzinfo=None)
return dt
+
+
+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 FetchedUser(Converter):
+ """
+ Fetches from the Discord API and returns a `discord.User` or `discord.Object` object, given an ID.
+
+ If the fetching is successful, a `discord.User` object is returned. If it fails and
+ the error doesn't imply the user doesn't exist, then a `discord.Object` is returned
+ via the `user_proxy` function.
+ """
+
+ @staticmethod
+ async def convert(ctx: Context, user_id: str) -> t.Union[discord.User, discord.Object]:
+ """Convert `user_id` to a `discord.User` object, after fetching from the Discord API."""
+ try:
+ user_id = int(user_id)
+ log.trace(f"Fetching user {user_id}...")
+ return await ctx.bot.fetch_user(user_id)
+ except ValueError:
+ log.debug(f"Failed to fetch user {user_id}: could not convert to int.")
+ raise BadArgument(f"The provided argument can't be turned into integer: `{user_id}`")
+ except discord.HTTPException as e:
+ # If the Discord error isn't `Unknown user`, save it in the log and return a proxy instead
+ if e.code != 10013:
+ log.warning(f"Failed to fetch user, returning a proxy instead: status {e.status}")
+ return proxy_user(user_id)
+
+ log.debug(f"Failed to fetch user {user_id}: user does not exist.")
+ raise BadArgument(f"User `{user_id}` does not exist")