""" Classes used to handle bot events and errors. *Classes* --------- EventHandler ErrorHandler """ import traceback # Used to get the traceback of errors import discord # Used to init discord.Game and discord.Status, as well # as compare errors to discord errors and as typehints from discord.ext import commands # Used to compare errors with command # errors from discord_slash.context import SlashContext, ComponentContext from gwendolyn.utils.util_functions import decode_id class EventHandler(): """ Handles bot events. *Methods* --------- on_ready() on_slash_command(ctx: discord_slash.context.SlashContext) on_reaction_add(ctx: discord_slash.context.SlashContext) """ def __init__(self, bot): """Initialize the handler.""" self.bot = bot async def on_ready(self): """Log and sets status when it logs in.""" await self.bot.database_funcs.imdb_commands() name = self.bot.user.name userid = str(self.bot.user.id) logged_in_message = f"Logged in as {name}, {userid}" self.bot.log(logged_in_message, level=25) game = discord.Game("Use /help for commands") online_status = discord.Status.online await self.bot.change_presence(activity=game, status=online_status) async def on_slash_command(self, ctx: SlashContext): """Log when a slash command is given.""" if ctx.subcommand_name is not None: subcommand = f" {ctx.subcommand_name} " else: subcommand = " " if ctx.subcommand_group is not None: sub_command_group = f"{ctx.subcommand_group} " else: sub_command_group = "" args = " ".join([str(i) for i in ctx.args]) full_command = f"/{ctx.command}{subcommand}{sub_command_group}{args}" log_message = f"{ctx.author.display_name} ran {full_command}" self.bot.log(log_message, str(ctx.channel_id), level=25) async def on_component(self, ctx: ComponentContext): info = decode_id(ctx.custom_id) self.bot.log(f"Component action with info {info}") channel = ctx.origin_message.channel if info[0].lower() == "plex": if info[1].lower() == "movie": await self.bot.other.plex.add_movie( ctx.origin_message, info[2], not isinstance(channel, discord.DMChannel) ) elif info[1].lower() == "show": await self.bot.other.plex.add_show( ctx.origin_message, info[2], not isinstance(channel, discord.DMChannel) ) elif info[0].lower() == "hangman": if str(ctx.author_id) == info[2]: if info[1].lower() == "guess": await self.bot.games.hangman.guess(ctx, *info[3:]) elif info[1].lower() == "end": await self.bot.games.hangman.stop(ctx, *info[3:]) elif info[0].lower() == "connectfour": connect_four = self.bot.games.connect_four if info[1].lower() == "place" and str(ctx.author_id) == info[2]: params = [ ctx, info[3], int(info[4]), [int(info[5]), int(info[6])], int(info[7]), ctx.author_id, int(info[8]) ] await connect_four.place_piece(*params) if info[1].lower() == "end": if str(ctx.author_id) in [info[2], info[3]]: params = [ ctx, [int(info[2]), int(info[3])], info[4], info[5] ] await connect_four.surrender(*params) class ErrorHandler(): """ Handles errors. *Methods* --------- on_slash_command_error(ctx: discord_slash.context.SlashContext, error: Exception) on_error(method: str) """ def __init__(self, bot): """Initialize the handler.""" self.bot = bot async def on_slash_command_error(self, ctx: SlashContext, error: Exception): """Log when there's a slash command.""" if isinstance(error, commands.CommandNotFound): await ctx.send("That's not a command") elif isinstance(error, discord.errors.NotFound): self.bot.log("Deleted message before I could add all reactions") elif isinstance(error, commands.errors.MissingRequiredArgument): self.bot.log(f"{error}", str(ctx.channel_id)) await ctx.send(self.bot.long_strings["missing parameters"]) else: params = [type(error), error, error.__traceback__] exception = traceback.format_exception(*params) exception_string = "".join(exception) log_messages = [f"exception in /{ctx.name}", f"{exception_string}"] self.bot.log(log_messages, str(ctx.channel_id), 40) if isinstance(error, discord.errors.NotFound): self.bot.log("Context is non-existant", level=40) else: await ctx.send("Something went wrong") async def on_error(self, method: str): """Log when there's an error.""" exception = traceback.format_exc() exception_string = "".join(exception) log_messages = [f"exception in {method}", f"{exception_string}"] self.bot.log(log_messages, level=40)