mirror of
https://github.com/miaowware/qrm2.git
synced 2025-05-24 10:22:28 -04:00
Better command error handling
- Added handling for all subclasses of CommandError - Added more emojis - Renamed some emojis - debug_mode -> bot.qrm.debug_mode Fixes #22 Co-authored-by: Abigail Gold <dev@kb6.ee>
This commit is contained in:
parent
70505f10f6
commit
0615df0829
@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
### Added
|
### Added
|
||||||
- Flag emojis to commands with countries.
|
- Flag emojis to commands with countries.
|
||||||
- Image attribution and description to "image" commands.
|
- Image attribution and description to "image" commands.
|
||||||
|
- Better user-facing command error handling.
|
||||||
- New key in options.py: pika.
|
- New key in options.py: pika.
|
||||||
|
|
||||||
|
|
||||||
|
13
common.py
13
common.py
@ -42,8 +42,12 @@ cat = SimpleNamespace(lookup='Information Lookup',
|
|||||||
study='Exam Study',
|
study='Exam Study',
|
||||||
weather='Land and Space Weather')
|
weather='Land and Space Weather')
|
||||||
|
|
||||||
emojis = SimpleNamespace(good='✅',
|
emojis = SimpleNamespace(check_mark='✅',
|
||||||
bad='❌')
|
x='❌',
|
||||||
|
warning='⚠️',
|
||||||
|
question='❓',
|
||||||
|
no_entry='⛔',
|
||||||
|
bangbang='‼️')
|
||||||
|
|
||||||
paths = SimpleNamespace(data=Path("./data/"),
|
paths = SimpleNamespace(data=Path("./data/"),
|
||||||
resources=Path("./resources/"),
|
resources=Path("./resources/"),
|
||||||
@ -106,7 +110,7 @@ def error_embed_factory(ctx: commands.Context, exception: Exception, debug_mode:
|
|||||||
else:
|
else:
|
||||||
fmtd_ex = traceback.format_exception_only(exception.__class__, exception)
|
fmtd_ex = traceback.format_exception_only(exception.__class__, exception)
|
||||||
embed = embed_factory(ctx)
|
embed = embed_factory(ctx)
|
||||||
embed.title = "Error"
|
embed.title = "⚠️ Error"
|
||||||
embed.description = "```\n" + '\n'.join(fmtd_ex) + "```"
|
embed.description = "```\n" + '\n'.join(fmtd_ex) + "```"
|
||||||
embed.colour = colours.bad
|
embed.colour = colours.bad
|
||||||
return embed
|
return embed
|
||||||
@ -124,5 +128,4 @@ async def add_react(msg: discord.Message, react: str):
|
|||||||
async def check_if_owner(ctx: commands.Context):
|
async def check_if_owner(ctx: commands.Context):
|
||||||
if ctx.author.id in opt.owners_uids:
|
if ctx.author.id in opt.owners_uids:
|
||||||
return True
|
return True
|
||||||
await add_react(ctx.message, emojis.bad)
|
raise commands.NotOwner
|
||||||
return False
|
|
||||||
|
58
main.py
58
main.py
@ -8,6 +8,9 @@ This file is part of discord-qrm2 and is released under the terms of the GNU
|
|||||||
General Public License, version 2.
|
General Public License, version 2.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
from datetime import time, datetime
|
from datetime import time, datetime
|
||||||
import random
|
import random
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
@ -42,6 +45,8 @@ bot = commands.Bot(command_prefix=opt.prefix,
|
|||||||
bot.qrm = SimpleNamespace()
|
bot.qrm = SimpleNamespace()
|
||||||
bot.qrm.session = aiohttp.ClientSession(headers={'User-Agent': f'discord-qrm2/{info.release}'})
|
bot.qrm.session = aiohttp.ClientSession(headers={'User-Agent': f'discord-qrm2/{info.release}'})
|
||||||
|
|
||||||
|
bot.qrm.debug_mode = debug_mode
|
||||||
|
|
||||||
|
|
||||||
# --- Commands ---
|
# --- Commands ---
|
||||||
|
|
||||||
@ -51,7 +56,7 @@ async def _restart_bot(ctx: commands.Context):
|
|||||||
"""Restarts the bot."""
|
"""Restarts the bot."""
|
||||||
await bot.qrm.session.close()
|
await bot.qrm.session.close()
|
||||||
global exit_code
|
global exit_code
|
||||||
await cmn.add_react(ctx.message, cmn.emojis.good)
|
await cmn.add_react(ctx.message, cmn.emojis.check_mark)
|
||||||
print(f"[**] Restarting! Requested by {ctx.author}.")
|
print(f"[**] Restarting! Requested by {ctx.author}.")
|
||||||
exit_code = 42 # Signals to the wrapper script that the bot needs to be restarted.
|
exit_code = 42 # Signals to the wrapper script that the bot needs to be restarted.
|
||||||
await bot.logout()
|
await bot.logout()
|
||||||
@ -63,7 +68,7 @@ async def _shutdown_bot(ctx: commands.Context):
|
|||||||
"""Shuts down the bot."""
|
"""Shuts down the bot."""
|
||||||
await bot.qrm.session.close()
|
await bot.qrm.session.close()
|
||||||
global exit_code
|
global exit_code
|
||||||
await cmn.add_react(ctx.message, cmn.emojis.good)
|
await cmn.add_react(ctx.message, cmn.emojis.check_mark)
|
||||||
print(f"[**] Shutting down! Requested by {ctx.author}.")
|
print(f"[**] Shutting down! Requested by {ctx.author}.")
|
||||||
exit_code = 0 # Signals to the wrapper script that the bot should not be restarted.
|
exit_code = 0 # Signals to the wrapper script that the bot should not be restarted.
|
||||||
await bot.logout()
|
await bot.logout()
|
||||||
@ -92,9 +97,9 @@ async def _extctl_list(ctx: commands.Context):
|
|||||||
async def _extctl_load(ctx: commands.Context, extension: str):
|
async def _extctl_load(ctx: commands.Context, extension: str):
|
||||||
try:
|
try:
|
||||||
bot.load_extension(ext_dir + "." + extension)
|
bot.load_extension(ext_dir + "." + extension)
|
||||||
await cmn.add_react(ctx.message, cmn.emojis.good)
|
await cmn.add_react(ctx.message, cmn.emojis.check_mark)
|
||||||
except commands.ExtensionError as ex:
|
except commands.ExtensionError as ex:
|
||||||
embed = cmn.error_embed_factory(ctx, ex, debug_mode)
|
embed = cmn.error_embed_factory(ctx, ex, bot.qrm.debug_mode)
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
|
|
||||||
@ -106,9 +111,9 @@ async def _extctl_reload(ctx: commands.Context, extension: str):
|
|||||||
await cmn.add_react(ctx.message, pika)
|
await cmn.add_react(ctx.message, pika)
|
||||||
try:
|
try:
|
||||||
bot.reload_extension(ext_dir + "." + extension)
|
bot.reload_extension(ext_dir + "." + extension)
|
||||||
await cmn.add_react(ctx.message, cmn.emojis.good)
|
await cmn.add_react(ctx.message, cmn.emojis.check_mark)
|
||||||
except commands.ExtensionError as ex:
|
except commands.ExtensionError as ex:
|
||||||
embed = cmn.error_embed_factory(ctx, ex, debug_mode)
|
embed = cmn.error_embed_factory(ctx, ex, bot.qrm.debug_mode)
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
|
|
||||||
@ -116,9 +121,9 @@ async def _extctl_reload(ctx: commands.Context, extension: str):
|
|||||||
async def _extctl_unload(ctx: commands.Context, extension: str):
|
async def _extctl_unload(ctx: commands.Context, extension: str):
|
||||||
try:
|
try:
|
||||||
bot.unload_extension(ext_dir + "." + extension)
|
bot.unload_extension(ext_dir + "." + extension)
|
||||||
await cmn.add_react(ctx.message, cmn.emojis.good)
|
await cmn.add_react(ctx.message, cmn.emojis.check_mark)
|
||||||
except commands.ExtensionError as ex:
|
except commands.ExtensionError as ex:
|
||||||
embed = cmn.error_embed_factory(ctx, ex, debug_mode)
|
embed = cmn.error_embed_factory(ctx, ex, bot.qrm.debug_mode)
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
|
|
||||||
@ -146,6 +151,37 @@ async def on_message(message):
|
|||||||
await bot.process_commands(message)
|
await bot.process_commands(message)
|
||||||
|
|
||||||
|
|
||||||
|
@bot.event
|
||||||
|
async def on_command_error(ctx: commands.Context, err: commands.CommandError):
|
||||||
|
if isinstance(err, commands.UserInputError):
|
||||||
|
await cmn.add_react(ctx.message, cmn.emojis.warning)
|
||||||
|
await ctx.send_help(ctx.command)
|
||||||
|
elif isinstance(err, commands.CommandNotFound) and not ctx.invoked_with.startswith("?"):
|
||||||
|
await cmn.add_react(ctx.message, cmn.emojis.question)
|
||||||
|
elif isinstance(err, commands.CheckFailure):
|
||||||
|
# Add handling of other subclasses of CheckFailure as needed.
|
||||||
|
if isinstance(err, commands.NotOwner):
|
||||||
|
await cmn.add_react(ctx.message, cmn.emojis.no_entry)
|
||||||
|
else:
|
||||||
|
await cmn.add_react(ctx.message, cmn.emojis.x)
|
||||||
|
elif isinstance(err, commands.DisabledCommand):
|
||||||
|
await cmn.add_react(ctx.message, cmn.emojis.bangbang)
|
||||||
|
elif isinstance(err, (commands.CommandInvokeError, commands.ConversionError)):
|
||||||
|
# Emulating discord.py's default beaviour.
|
||||||
|
print('Ignoring exception in command {}:'.format(ctx.command), file=sys.stderr)
|
||||||
|
traceback.print_exception(type(err), err, err.__traceback__, file=sys.stderr)
|
||||||
|
|
||||||
|
embed = cmn.error_embed_factory(ctx, err.original, bot.qrm.debug_mode)
|
||||||
|
embed.description += f"\n`{type(err).__name__}`"
|
||||||
|
await cmn.add_react(ctx.message, cmn.emojis.warning)
|
||||||
|
await ctx.send(embed=embed)
|
||||||
|
else:
|
||||||
|
# Emulating discord.py's default beaviour. (safest bet)
|
||||||
|
print('Ignoring exception in command {}:'.format(ctx.command), file=sys.stderr)
|
||||||
|
traceback.print_exception(type(err), err, err.__traceback__, file=sys.stderr)
|
||||||
|
await cmn.add_react(ctx.message, cmn.emojis.warning)
|
||||||
|
|
||||||
|
|
||||||
# --- Tasks ---
|
# --- Tasks ---
|
||||||
|
|
||||||
@tasks.loop(minutes=5)
|
@tasks.loop(minutes=5)
|
||||||
@ -194,19 +230,19 @@ try:
|
|||||||
|
|
||||||
except discord.LoginFailure as ex:
|
except discord.LoginFailure as ex:
|
||||||
# Miscellaneous authentications errors: borked token and co
|
# Miscellaneous authentications errors: borked token and co
|
||||||
if debug_mode:
|
if bot.qrm.debug_mode:
|
||||||
raise
|
raise
|
||||||
raise SystemExit("Error: Failed to authenticate: {}".format(ex))
|
raise SystemExit("Error: Failed to authenticate: {}".format(ex))
|
||||||
|
|
||||||
except discord.ConnectionClosed as ex:
|
except discord.ConnectionClosed as ex:
|
||||||
# When the connection to the gateway (websocket) is closed
|
# When the connection to the gateway (websocket) is closed
|
||||||
if debug_mode:
|
if bot.qrm.debug_mode:
|
||||||
raise
|
raise
|
||||||
raise SystemExit("Error: Discord gateway connection closed: [Code {}] {}".format(ex.code, ex.reason))
|
raise SystemExit("Error: Discord gateway connection closed: [Code {}] {}".format(ex.code, ex.reason))
|
||||||
|
|
||||||
except ConnectionResetError as ex:
|
except ConnectionResetError as ex:
|
||||||
# More generic connection reset error
|
# More generic connection reset error
|
||||||
if debug_mode:
|
if bot.qrm.debug_mode:
|
||||||
raise
|
raise
|
||||||
raise SystemExit("ConnectionResetError: {}".format(ex))
|
raise SystemExit("ConnectionResetError: {}".format(ex))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user