mirror of
				https://github.com/miaowware/qrm2.git
				synced 2025-10-31 11:20:19 -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 | ||||
| - Flag emojis to commands with countries. | ||||
| - Image attribution and description to "image" commands. | ||||
| - Better user-facing command error handling. | ||||
| - New key in options.py: pika. | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										13
									
								
								common.py
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								common.py
									
									
									
									
									
								
							| @ -42,8 +42,12 @@ cat = SimpleNamespace(lookup='Information Lookup', | ||||
|                       study='Exam Study', | ||||
|                       weather='Land and Space Weather') | ||||
| 
 | ||||
| emojis = SimpleNamespace(good='✅', | ||||
|                          bad='❌') | ||||
| emojis = SimpleNamespace(check_mark='✅', | ||||
|                          x='❌', | ||||
|                          warning='⚠️', | ||||
|                          question='❓', | ||||
|                          no_entry='⛔', | ||||
|                          bangbang='‼️') | ||||
| 
 | ||||
| paths = SimpleNamespace(data=Path("./data/"), | ||||
|                         resources=Path("./resources/"), | ||||
| @ -106,7 +110,7 @@ def error_embed_factory(ctx: commands.Context, exception: Exception, debug_mode: | ||||
|     else: | ||||
|         fmtd_ex = traceback.format_exception_only(exception.__class__, exception) | ||||
|     embed = embed_factory(ctx) | ||||
|     embed.title = "Error" | ||||
|     embed.title = "⚠️ Error" | ||||
|     embed.description = "```\n" + '\n'.join(fmtd_ex) + "```" | ||||
|     embed.colour = colours.bad | ||||
|     return embed | ||||
| @ -124,5 +128,4 @@ async def add_react(msg: discord.Message, react: str): | ||||
| async def check_if_owner(ctx: commands.Context): | ||||
|     if ctx.author.id in opt.owners_uids: | ||||
|         return True | ||||
|     await add_react(ctx.message, emojis.bad) | ||||
|     return False | ||||
|     raise commands.NotOwner | ||||
|  | ||||
							
								
								
									
										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. | ||||
| """ | ||||
| 
 | ||||
| 
 | ||||
| import sys | ||||
| import traceback | ||||
| from datetime import time, datetime | ||||
| import random | ||||
| from types import SimpleNamespace | ||||
| @ -42,6 +45,8 @@ bot = commands.Bot(command_prefix=opt.prefix, | ||||
| bot.qrm = SimpleNamespace() | ||||
| bot.qrm.session = aiohttp.ClientSession(headers={'User-Agent': f'discord-qrm2/{info.release}'}) | ||||
| 
 | ||||
| bot.qrm.debug_mode = debug_mode | ||||
| 
 | ||||
| 
 | ||||
| # --- Commands --- | ||||
| 
 | ||||
| @ -51,7 +56,7 @@ async def _restart_bot(ctx: commands.Context): | ||||
|     """Restarts the bot.""" | ||||
|     await bot.qrm.session.close() | ||||
|     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}.") | ||||
|     exit_code = 42  # Signals to the wrapper script that the bot needs to be restarted. | ||||
|     await bot.logout() | ||||
| @ -63,7 +68,7 @@ async def _shutdown_bot(ctx: commands.Context): | ||||
|     """Shuts down the bot.""" | ||||
|     await bot.qrm.session.close() | ||||
|     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}.") | ||||
|     exit_code = 0  # Signals to the wrapper script that the bot should not be restarted. | ||||
|     await bot.logout() | ||||
| @ -92,9 +97,9 @@ async def _extctl_list(ctx: commands.Context): | ||||
| async def _extctl_load(ctx: commands.Context, extension: str): | ||||
|     try: | ||||
|         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: | ||||
|         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) | ||||
| 
 | ||||
| 
 | ||||
| @ -106,9 +111,9 @@ async def _extctl_reload(ctx: commands.Context, extension: str): | ||||
|             await cmn.add_react(ctx.message, pika) | ||||
|     try: | ||||
|         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: | ||||
|         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) | ||||
| 
 | ||||
| 
 | ||||
| @ -116,9 +121,9 @@ async def _extctl_reload(ctx: commands.Context, extension: str): | ||||
| async def _extctl_unload(ctx: commands.Context, extension: str): | ||||
|     try: | ||||
|         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: | ||||
|         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) | ||||
| 
 | ||||
| 
 | ||||
| @ -146,6 +151,37 @@ async def on_message(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.loop(minutes=5) | ||||
| @ -194,19 +230,19 @@ try: | ||||
| 
 | ||||
| except discord.LoginFailure as ex: | ||||
|     # Miscellaneous authentications errors: borked token and co | ||||
|     if debug_mode: | ||||
|     if bot.qrm.debug_mode: | ||||
|         raise | ||||
|     raise SystemExit("Error: Failed to authenticate: {}".format(ex)) | ||||
| 
 | ||||
| except discord.ConnectionClosed as ex: | ||||
|     # When the connection to the gateway (websocket) is closed | ||||
|     if debug_mode: | ||||
|     if bot.qrm.debug_mode: | ||||
|         raise | ||||
|     raise SystemExit("Error: Discord gateway connection closed: [Code {}] {}".format(ex.code, ex.reason)) | ||||
| 
 | ||||
| except ConnectionResetError as ex: | ||||
|     # More generic connection reset error | ||||
|     if debug_mode: | ||||
|     if bot.qrm.debug_mode: | ||||
|         raise | ||||
|     raise SystemExit("ConnectionResetError: {}".format(ex)) | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user