178 lines
7.0 KiB
Python
178 lines
7.0 KiB
Python
"""
|
|
Classes used to handle bot events and errors.
|
|
|
|
*Classes*
|
|
---------
|
|
EventHandler
|
|
ErrorHandler
|
|
"""
|
|
import traceback # Used to get the traceback of errors
|
|
import sys # Used to get traceback when the specific error is not
|
|
# available
|
|
|
|
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
|
|
from gwendolyn.utils.util_functions import emoji_to_command
|
|
|
|
|
|
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_reaction_add(self, reaction: discord.Reaction,
|
|
user: discord.User):
|
|
"""Take action if the reaction is on a command message."""
|
|
if not user.bot:
|
|
tests = self.bot.database_funcs
|
|
message = reaction.message
|
|
channel = message.channel
|
|
reacted_message = f"{user.display_name} reacted to a message"
|
|
self.bot.log(reacted_message, str(channel.id))
|
|
plex_data = tests.plex_reaction_test(message)
|
|
# plex_data is a list containing 3 elements: whether it was
|
|
# the add_show/add_movie command message the reaction was to
|
|
# (bool), whether it's a movie (bool) (if false, it's a
|
|
# show), and the imdb ids/names for the for the movies or
|
|
# shows listed in the message (list).
|
|
|
|
reaction_test_parameters = [message, f"#{str(user.id)}"]
|
|
|
|
if tests.connect_four_reaction_test(*reaction_test_parameters):
|
|
column = emoji_to_command(reaction.emoji)
|
|
params = [message, f"#{user.id}", column-1]
|
|
await self.bot.games.connect_four.place_piece(*params)
|
|
|
|
if plex_data[0]:
|
|
plex_functions = self.bot.other.plex
|
|
if plex_data[1]:
|
|
movie_pick = emoji_to_command(reaction.emoji)
|
|
if movie_pick == "none":
|
|
imdb_id = None
|
|
else:
|
|
imdb_id = plex_data[2][movie_pick-1]
|
|
|
|
if isinstance(channel, discord.DMChannel):
|
|
await message.delete()
|
|
await plex_functions.add_movie(message, imdb_id, False)
|
|
else:
|
|
await message.clear_reactions()
|
|
await plex_functions.add_movie(message, imdb_id)
|
|
else:
|
|
show_pick = emoji_to_command(reaction.emoji)
|
|
if show_pick == "none":
|
|
imdb_name = None
|
|
else:
|
|
imdb_name = plex_data[2][show_pick-1]
|
|
|
|
if isinstance(channel, discord.DMChannel):
|
|
await message.delete()
|
|
await plex_functions.add_show(message, imdb_name, False)
|
|
else:
|
|
await message.clear_reactions()
|
|
await plex_functions.add_show(message, imdb_name)
|
|
|
|
elif tests.hangman_reaction_test(*reaction_test_parameters):
|
|
self.bot.log("They reacted to the hangman message")
|
|
if ord(reaction.emoji) in range(127462, 127488):
|
|
# The range is letter-emojis
|
|
guess = chr(ord(reaction.emoji)-127397)
|
|
# Converts emoji to letter
|
|
params = [message, f"#{user.id}", guess]
|
|
await self.bot.games.hangman.guess(*params)
|
|
else:
|
|
self.bot.log("Bot they didn't react with a valid guess")
|
|
|
|
|
|
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 (error code 000)")
|
|
|
|
async def on_error(self, method: str):
|
|
"""Log when there's an error."""
|
|
error_type = sys.exc_info()[0]
|
|
if error_type == discord.errors.NotFound:
|
|
self.bot.log("Deleted message before I could add all reactions")
|
|
else:
|
|
exception = traceback.format_exc()
|
|
|
|
exception_string = "".join(exception)
|
|
log_messages = [f"exception in {method}", f"{exception_string}"]
|
|
self.bot.log(log_messages, level=40)
|