diff --git a/BotConfig.py b/BotConfig.py index d1d7734..2100dc8 100644 --- a/BotConfig.py +++ b/BotConfig.py @@ -7,6 +7,7 @@ def create_config(config): 'Status': '', 'Prefix': '?', 'Bot_Mod': '' + 'Error_Users: ''' } config['SQL'] = {'Dialect+Driver': 'mysql+mysqldb', 'Username': '', @@ -51,6 +52,7 @@ class Config: self.prefix = self.config['Discord']['Prefix'] self.dynmap_url = self.config['Minecraft']['Dynmap_Url'] self.bot_mod = self.config['Discord']['Bot_Mod'].split(',') + self.error_users = self.config['Discord']['Error_Users'].split(',') self.count = int(self.config['Logging']['Count']) self.rotation_duration = int(self.config['Logging']['Rotation_Duration']) self.special_name_list = dict(self.config.items('Special Names')) diff --git a/bot.py b/bot.py index b458e79..afad3e6 100644 --- a/bot.py +++ b/bot.py @@ -4,15 +4,14 @@ import logging from discord import Game from discord.ext import commands from discord.utils import oauth_url +from sqlalchemy.exc import OperationalError -from BotConfig import * +from BotConfig import bot_config from BotErrors import * from Commands import Commands from DatabaseModels import Player from MinecraftAccountInfoGrabber import * -from pymysql.err import OperationalError - logger = logging.getLogger(__name__) description = ''' @@ -27,11 +26,7 @@ If have a suggestion or if something is borked, you can PM my ding dong of a cre ''' bad_error_message = 'OOPSIE WOOPSIE!! Uwu We made a fucky wucky!! A wittle fucko boingo! The admins at our ' \ - 'headquarters are working VEWY HAWD to fix this! (Error in command {}: {})' - - -bot = commands.Bot(command_prefix=bot_config.prefix, description=description, case_insensitive=True) -bot_commands = Commands() + 'headquarters are working VEWY HAWD to fix this! (Error in command {})' extensions = ['cogs.Add_Commands', 'cogs.Delete_Commands', @@ -39,6 +34,13 @@ extensions = ['cogs.Add_Commands', 'cogs.Search_Commands', 'cogs.Admin_Commands'] +bot = commands.Bot(command_prefix=bot_config.prefix, description=description, case_insensitive=True) + +try: + bot_commands = Commands() +except OperationalError: + logger.info('Could not connect to MySQL server.') + @bot.event async def on_ready(): @@ -54,7 +56,7 @@ async def on_command(command, ctx): if ctx.invoked_subcommand is None: subcommand = "" else: - subcommand = ":"+ctx.invoked_subcommand + subcommand = ":" + ctx.invoked_subcommand logger.info("User %s, used command %s%s with context: %s", ctx.message.author, command, subcommand, ctx.args) @@ -69,7 +71,7 @@ async def on_command_error(error, ctx): elif isinstance(error, commands.CommandOnCooldown): return elif isinstance(error, commands.UserInputError): - error_str = 'Invalid syntax for **{}** you ding dong:'\ + error_str = 'Invalid syntax for **{}** you ding dong:' \ .format(ctx.invoked_with, ctx.invoked_with) pages = bot.formatter.format_help_for(ctx, ctx.command) @@ -84,23 +86,31 @@ async def on_command_error(error, ctx): elif isinstance(error.original, PlayerNotFound): error_str = 'Make sure to use ?register first you ding dong.' elif isinstance(error.original, EntryNameNotUniqueError): - error_str = 'An entry in the database already has that name ding dong.' + error_str = 'An entry in the database already has that name you ding dong.' elif isinstance(error.original, DatabaseValueError): error_str = 'Use a shorter name or a smaller value, dong ding.' elif isinstance(error.original, NotOnServerError): error_str = 'Command needs to be run on 24CC. Run this command there whoever you are.'.format() elif isinstance(error.original, OperationalError): + await send_error_message('Error connecting to the MySQL server, is it offline?') error_str = 'Database connection issue, looks like some admin has to fix something.'.format() else: + await send_error_message('Geoffrey encountered unhandled exception: {}. Context:'.format(error, ctx.args)) + logger.error("Geoffrey encountered unhandled exception: %s", error) - error_str = bad_error_message.format(ctx.invoked_with, error) + error_str = bad_error_message.format(ctx.invoked_with) await bot.send_message(ctx.message.channel, '{} **Error Running Command:** {}'.format(ctx.message.author.mention, error_str)) +async def send_error_message(msg): + for user_id in bot_config.error_users: + user = await bot.get_user_info(user_id) + await bot.send_message(user, msg) + + async def username_update(): - session = None await bot.wait_until_ready() while not bot.is_closed: session = bot_commands.interface.database.Session() @@ -118,6 +128,7 @@ async def username_update(): logger.info("Username lookup error.") session.rollback() except OperationalError: + await send_error_message('Error connecting to the MySQL server, is it offline?') logger.info("MySQL connection error") finally: session.close() @@ -126,6 +137,7 @@ async def username_update(): def start_bot(): try: + Commands() for extension in extensions: try: bot.load_extension(extension) diff --git a/cogs/Search_Commands.py b/cogs/Search_Commands.py index c9f72f7..46f192c 100644 --- a/cogs/Search_Commands.py +++ b/cogs/Search_Commands.py @@ -15,7 +15,7 @@ class Search_Commands: @commands.command(pass_context=True) @commands.cooldown(5, 60, commands.BucketType.user) - async def find(self, ctx, * args): + async def find(self, ctx, *args): """ Finds all the locations and tunnels matching the search term ?find [Search] @@ -28,10 +28,11 @@ class Search_Commands: result = bot_commands.find(search) - await self.bot.say('{}, The following entries match **{}**:\n{}'.format(ctx.message.author.mention, search, result)) + await self.bot.say( + '{}, The following entries match **{}**:\n{}'.format(ctx.message.author.mention, search, result)) except LocationLookUpError: - await self.bot.say('{}, no matches to **{}** were found in the database.'.format(ctx.message.author.mention, search)) - + await self.bot.say( + '{}, no matches to **{}** were found in the database.'.format(ctx.message.author.mention, search)) @commands.command(pass_context=True) @commands.cooldown(5, 60, commands.BucketType.user) @@ -43,15 +44,15 @@ class Search_Commands: try: result = bot_commands.tunnel(player) - await self.bot.say('{}, **{}** owns the following tunnels: \n{}'.format(ctx.message.author.mention, player, result)) + await self.bot.say( + '{}, **{}** owns the following tunnels: \n{}'.format(ctx.message.author.mention, player, result)) except LocationLookUpError: await self.bot.say('{}, no tunnels for **{}** were found in the database.' - .format(ctx.message.author.mention, player)) - + .format(ctx.message.author.mention, player)) @commands.command(pass_context=True) @commands.cooldown(5, 60, commands.BucketType.user) - async def find_around(self, ctx, x_pos: int, z_pos: int, * args): + async def find_around(self, ctx, x_pos: int, z_pos: int, *args): """ Finds all the locations around a certain point. The radius defaults to 200 blocks if no value is given. @@ -84,10 +85,11 @@ class Search_Commands: ctx.message.author.mention, radius, base_string)) else: await self.bot.say('{}, there are no locations within {} blocks of that point' - .format(ctx.message.author.mention, radius)) + .format(ctx.message.author.mention, radius)) except ValueError: - await self.bot.say('{}, invalid radius, the radius must be a whole number.'.format(ctx.message.author.mention, - radius)) + await self.bot.say( + '{}, invalid radius, the radius must be a whole number.'.format(ctx.message.author.mention, + radius)) except InvalidDimError: await self.bot.say('{}, {} is an invalid dimension.'.format(ctx.message.author.mention, dimension)) @@ -100,13 +102,14 @@ class Search_Commands: """ try: result = bot_commands.selling(item_name) - await self.bot.say('{}, the following shops sell **{}**: \n{}'.format(ctx.message.author.mention, item_name, result)) + await self.bot.say( + '{}, the following shops sell **{}**: \n{}'.format(ctx.message.author.mention, item_name, result)) except ItemNotFound: await self.bot.say('{}, no shop sells **{}**.'.format(ctx.message.author.mention, item_name)) @commands.command(pass_context=True) @commands.cooldown(5, 60, commands.BucketType.user) - async def info(self, ctx, * args): + async def info(self, ctx, *args): """ Displays info about a location. If the location is a shop, it displays the shop's inventory.