Files
Gwendolyn/gwendolyn/utils/event_handlers.py
2022-01-28 11:33:47 +01:00

166 lines
5.9 KiB
Python

"""
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
from gwendolyn.exceptions import InvalidInteraction
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):
"""Handle component interaction."""
info = decode_id(ctx.custom_id)
self.bot.log(f"Component action with info {info}")
channel = ctx.channel
author = str(ctx.author_id)
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)
)
return
elif info[1].lower() == "show":
await self.bot.other.plex.add_show(
ctx.origin_message,
info[2],
not isinstance(channel, discord.DMChannel)
)
else:
raise InvalidInteraction(ctx.custom_id, info)
elif info[0].lower() == "hangman" and author == 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:])
else:
raise InvalidInteraction(ctx.custom_id, info)
elif info[0].lower() == "connectfour":
connect_four = self.bot.games.connect_four
if info[1].lower() == "place" and author == info[2]:
await connect_four.place_piece(
ctx,
info[3],
int(info[4]),
[int(info[5]), int(info[6])],
int(info[7]),
ctx.author_id,
int(info[8])
)
elif info[1].lower() == "end" and author in [info[2], info[3]]:
await connect_four.surrender(
ctx, [int(info[2]), int(info[3])], info[4], info[5]
)
else:
raise InvalidInteraction(ctx.custom_id, info)
elif info[0].lower() == "blackjack":
await self.bot.games.blackjack.decode_interaction(ctx, info[1:])
else:
raise InvalidInteraction(ctx.custom_id, info)
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)