async def servInfo(self, ctx, server: int): out = '' page = None if server < 9999: page = server if page: # grab all server info all_servers = self.bot.guilds members = sum(len(g.members) for g in all_servers) out += f"I am in {len(all_servers)} servers, with {members} members." for s in sorted(all_servers, key=lambda k: len(k.members), reverse=True): out += "\n{} ({}, {} members, {} bot)".format( s.name, s.id, len(s.members), sum(1 for m in s.members if m.bot)) else: # grab one server info guild = self.bot.get_guild(server) user = None if not guild: channel = self.bot.get_channel(server) if not channel: user = self.bot.get_user(server) else: guild = channel.guild if (not guild) and (not user): return await ctx.send("Not found.") if user: return await ctx.send("{} - {}".format(str(user), user.id)) else: try: invite = (await next(c for c in guild.channels if isinstance(c, discord.TextChannel) ).create_invite()).url except: invite = None if invite: out += "\n\n**{} ({}, {})**".format( guild.name, guild.id, invite) else: out += "\n\n**{} ({})**".format(guild.name, guild.id) out += "\n{} members, {} bot".format( len(guild.members), sum(1 for m in guild.members if m.bot)) for c in guild.channels: out += '\n|- {} ({})'.format(c.name, c.id) out = discord_trim(out) if page is None: for m in out: await ctx.send(m) else: await ctx.send(out[page - 1])
async def on_command_error(error, ctx): if isinstance(error, commands.CommandNotFound): return print("Error caused by message: `{}`".format(ctx.message.content)) traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr) tb = ''.join( traceback.format_exception(type(error), error, error.__traceback__)) if isinstance(error, commands.CheckFailure): await bot.send_message( ctx.message.channel, "Error: Either you do not have the permissions to run this command or the command is disabled." ) return elif isinstance(error, (commands.MissingRequiredArgument, commands.BadArgument, commands.NoPrivateMessage)): await bot.send_message( ctx.message.channel, "Error: " + str(error) + "\nUse `.help " + ctx.command.qualified_name + "` for help.") elif bot.mask & coreCog.debug_mask: await bot.send_message( ctx.message.channel, "Error: " + str(error) + "\nThis incident has been reported to the developer.") try: await bot.send_message( bot.owner, "Error in channel {} ({}), server {} ({}): {}\nCaused by message: `{}`" .format(ctx.message.channel, ctx.message.channel.id, ctx.message.server, ctx.message.server.id, repr(error), ctx.message.content)) except AttributeError: await bot.send_message( bot.owner, "Error in PM with {} ({}): {}\nCaused by message: `{}`".format( ctx.message.author.mention, str(ctx.message.author), repr(error), ctx.message.content)) for o in discord_trim(tb): await bot.send_message(bot.owner, o) else: await bot.send_message(ctx.message.channel, "Error: " + str(error))
async def debug_roll(self, ctx, *, rollStr: str): adv = 0 self.bot.db.incr('dice_rolled_life') if re.search('(^|\s+)(adv|dis)(\s+|$)', rollStr) is not None: adv = 1 if re.search('(^|\s+)adv(\s+|$)', rollStr) is not None else -1 rollStr = re.sub('(adv|dis)(\s+|$)', '', rollStr) res = roll(rollStr, adv=adv, debug=True) out = res.result try: await self.bot.delete_message(ctx.message) except: pass outStr = ctx.message.author.mention + ' :game_die:\n' + out if len(outStr) > 1999: await self.bot.say( ctx.message.author.mention + ' :game_die:\n[Output truncated due to length]\n**Result:** ' + str(res.plain)) else: await self.bot.say(outStr) debug = "" for p in res.raw_dice.parts: if isinstance(p, SingleDiceGroup): debug += "SingleDiceGroup:\nnum_dice={0.num_dice}, max_value={0.max_value}, annotation={0.annotation}, operators={0.operators}".format( p) + \ "\nrolled={}\n\n".format(', '.join(repr(r) for r in p.rolled)) elif isinstance(p, Constant): debug += "Constant:\nvalue={0.value}, annotation={0.annotation}\n\n".format( p) elif isinstance(p, Operator): debug += "Operator:\nop={0.op}, annotation={0.annotation}\n\n".format( p) else: debug += "Comment:\ncomment={0.comment}\n\n".format(p) for t in discord_trim(debug): await self.bot.say(t)
async def on_command_error(ctx, error): if isinstance(error, commands.CommandNotFound): return log.debug("Error caused by message: `{}`".format(ctx.message.content)) log.debug('\n'.join( traceback.format_exception(type(error), error, error.__traceback__))) if isinstance(error, AvraeException): return await ctx.send(str(error)) tb = ''.join( traceback.format_exception(type(error), error, error.__traceback__)) if isinstance(error, (commands.MissingRequiredArgument, commands.BadArgument, commands.NoPrivateMessage, ValueError)): return await ctx.send("Error: " + str(error) + f"\nUse `{ctx.prefix}help " + ctx.command.qualified_name + "` for help.") elif isinstance(error, commands.CheckFailure): return await ctx.send("Error: You are not allowed to run this command." ) elif isinstance(error, commands.CommandOnCooldown): return await ctx.send( "This command is on cooldown for {:.1f} seconds.".format( error.retry_after)) elif isinstance(error, CommandInvokeError): original = error.original if isinstance(original, EvaluationError): # PM an alias author tiny traceback e = original.original if not isinstance(e, AvraeException): tb = f"```py\nError when parsing expression {original.expression}:\n" \ f"{''.join(traceback.format_exception(type(e), e, e.__traceback__, limit=0, chain=False))}\n```" try: await ctx.author.send(tb) except Exception as e: log.info(f"Error sending traceback: {e}") if isinstance(original, AvraeException): return await ctx.send(str(original)) if isinstance(original, Forbidden): try: return await ctx.author.send( f"Error: I am missing permissions to run this command. " f"Please make sure I have permission to send messages to <#{ctx.channel.id}>." ) except: try: return await ctx.send( f"Error: I cannot send messages to this user.") except: return if isinstance(original, NotFound): return await ctx.send( "Error: I tried to edit or delete a message that no longer exists." ) if isinstance(original, ValueError) and str(original) in ( "No closing quotation", "No escaped character"): return await ctx.send("Error: No closing quotation.") if isinstance(original, (ClientResponseError, InvalidArgument, asyncio.TimeoutError, ClientOSError)): return await ctx.send("Error in Discord API. Please try again.") if isinstance(original, HTTPException): if original.response.status == 400: return await ctx.send( "Error: Message is too long, malformed, or empty.") if original.response.status == 500: return await ctx.send( "Error: Internal server error on Discord's end. Please try again." ) if isinstance(original, OverflowError): return await ctx.send( f"Error: A number is too large for me to store.") error_msg = gen_error_message() await ctx.send( f"Error: {str(error)}\nUh oh, that wasn't supposed to happen! " f"Please join <http://support.avrae.io> and tell the developer that {error_msg}!" ) try: await bot.owner.send( f"**{error_msg}**\n" \ + "Error in channel {} ({}), server {} ({}): {}\nCaused by message: `{}`".format( ctx.channel, ctx.channel.id, ctx.guild, ctx.guild.id, repr(error), ctx.message.content)) except AttributeError: await bot.owner.send(f"**{error_msg}**\n" \ + "Error in PM with {} ({}), shard 0: {}\nCaused by message: `{}`".format( ctx.author.mention, str(ctx.author), repr(error), ctx.message.content)) for o in discord_trim(tb): await bot.owner.send(o) log.error("Error caused by message: `{}`".format(ctx.message.content)) traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr)
async def on_command_error(ctx, error): if isinstance(error, commands.CommandNotFound): return log.debug("Error caused by message: `{}`".format(ctx.message.content)) log.debug('\n'.join(traceback.format_exception(type(error), error, error.__traceback__))) if isinstance(error, AvraeException): return await ctx.send(str(error)) tb = ''.join(traceback.format_exception(type(error), error, error.__traceback__)) if isinstance(error, (commands.MissingRequiredArgument, commands.BadArgument, commands.NoPrivateMessage, ValueError)): return await ctx.send("Error: " + str( error) + f"\nUse `{ctx.prefix}help " + ctx.command.qualified_name + "` for help.") elif isinstance(error, commands.CheckFailure): return await ctx.send("Error: You are not allowed to run this command.") elif isinstance(error, commands.CommandOnCooldown): return await ctx.send("This command is on cooldown for {:.1f} seconds.".format(error.retry_after)) elif isinstance(error, CommandInvokeError): original = error.original if isinstance(original, EvaluationError): # PM an alias author tiny traceback e = original.original if not isinstance(e, AvraeException): tb = f"```py\n{''.join(traceback.format_exception(type(e), e, e.__traceback__, limit=0, chain=False))}\n```" try: await ctx.author.send(tb) except Exception as e: log.info(f"Error sending traceback: {e}") if isinstance(original, AvraeException): return await ctx.send(str(original)) if isinstance(original, Forbidden): try: return await ctx.author.send( f"Error: I am missing permissions to run this command. " f"Please make sure I have permission to send messages to <#{ctx.channel.id}>." ) except: try: return await ctx.send(f"Error: I cannot send messages to this user.") except: return if isinstance(original, NotFound): return await ctx.send("Error: I tried to edit or delete a message that no longer exists.") if isinstance(original, ValueError) and str(original) in ("No closing quotation", "No escaped character"): return await ctx.send("Error: No closing quotation.") if isinstance(original, AttributeError) and str(original) in ("'NoneType' object has no attribute 'name'",): return await ctx.send("Error in Discord API. Please try again.") if isinstance(original, (ClientResponseError, InvalidArgument, asyncio.TimeoutError)): return await ctx.send("Error in Discord API. Please try again.") if isinstance(original, HTTPException): if original.response.status == 400: return await ctx.send("Error: Message is too long, malformed, or empty.") if original.response.status == 500: return await ctx.send("Error: Internal server error on Discord's end. Please try again.") if isinstance(original, redis.ResponseError): await ctx.send( "Error: I am having an issue writing to my database. Please report this to the dev!") return await bot.owner.send(f"Database error!\n{repr(original)}") if isinstance(original, OverflowError): return await ctx.send( f"Error: A number is too large for me to store. " f"This generally means you've done something terribly wrong.") error_msg = gen_error_message() await ctx.send( f"Error: {str(error)}\nUh oh, that wasn't supposed to happen! " f"Please ignore this and tell the developer that {error_msg}!") try: await bot.owner.send( f"**{error_msg}**\n" \ + "Error in channel {} ({}), server {} ({}): {}\nCaused by message: `{}`".format( ctx.channel, ctx.channel.id, ctx.guild, ctx.guild.id, repr(error), ctx.message.content)) await ctx.send("Try again. The goblins should have been murdered. If they haven't harrass the developers. They'll love that") process = ["sudo", "systemctl", "restart", "mongodb"] subprocess.run(process) except AttributeError: await bot.owner.send(f"**{error_msg}**\n" \ + "Error in PM with {} ({}), shard 0: {}\nCaused by message: `{}`".format( ctx.author.mention, str(ctx.author), repr(error), ctx.message.content)) for o in discord_trim(tb): await bot.owner.send(o) log.error("Error caused by message: `{}`".format(ctx.message.content)) traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr)
async def servInfo(self, server: str = None): out = '' page = None num_shards = int(getattr(self.bot, 'shard_count', 1)) if len(server) < 3: page = int(server) server = None req = self.request_server_info(server) for _ in range(300): # timeout after 30 sec if len(self.requests[req]) >= num_shards: break else: await asyncio.sleep(0.1) data = self.requests[req] del self.requests[req] for shard in range(num_shards): if str(shard) not in data: out += '\nMissing data from shard {}'.format(shard) if server is None: # grab all server info all_servers = [] for _shard, _data in data.items(): for s in _data: s['shard'] = _shard all_servers += _data out += f"I am in {len(all_servers)} servers, with {sum(s['members'] for s in all_servers)} members." for s in sorted(all_servers, key=lambda k: k['members'], reverse=True): out += "\n{} ({}, {} members, {} bot, shard {})".format( s['name'], s['id'], s['members'], s['bots'], s['shard']) else: # grab one server info try: _data = next( (s, d) for s, d in data.items() if d is not None) # here we assume only one shard will reply shard = _data[0] data = _data[1] except StopIteration: return await self.bot.say("Not found.") if data.get('private_message'): return await self.bot.say("{} - {} - Shard 0".format( data['name'], data['user'])) else: if data.get('invite'): out += "\n\n**{} ({}, {}, shard {})**".format( data['name'], data['id'], data['invite'], shard) else: out += "\n\n**{} ({}, shard {})**".format( data['name'], data['id'], shard) out += "\n{} members, {} bot".format(data['members'], data['bots']) for c in data['channels']: out += '\n|- {} ({})'.format(c['name'], c['id']) out = discord_trim(out) if page is None: for m in out: await self.bot.say(m) else: await self.bot.say(out[page - 1])
async def on_command_error(error, ctx): if isinstance(error, commands.CommandNotFound): return log.debug("Error caused by message: `{}`".format(ctx.message.content)) log.debug('\n'.join( traceback.format_exception(type(error), error, error.__traceback__))) if isinstance(error, AvraeException): return await bot.send_message(ctx.message.channel, str(error)) tb = ''.join( traceback.format_exception(type(error), error, error.__traceback__)) if isinstance(error, commands.CheckFailure): await bot.send_message( ctx.message.channel, "Error: Either you do not have the permissions to run this command, the command is disabled, or something went wrong internally." ) return elif isinstance(error, (commands.MissingRequiredArgument, commands.BadArgument, commands.NoPrivateMessage, ValueError)): return await bot.send_message( ctx.message.channel, "Error: " + str(error) + "\nUse `!help " + ctx.command.qualified_name + "` for help.") elif isinstance(error, commands.CommandOnCooldown): return await bot.send_message( ctx.message.channel, "This command is on cooldown for {:.1f} seconds.".format( error.retry_after)) elif isinstance(error, CommandInvokeError): original = error.original if isinstance(original, EvaluationError): # PM an alias author tiny traceback e = original.original if not isinstance(e, AvraeException): tb = f"```py\n{''.join(traceback.format_exception(type(e), e, e.__traceback__, limit=0, chain=False))}\n```" try: await bot.send_message(ctx.message.author, tb) except Exception as e: log.info(f"Error sending traceback: {e}") if isinstance(original, AvraeException): return await bot.send_message(ctx.message.channel, str(original)) if isinstance(original, Forbidden): try: return await bot.send_message( ctx.message.author, "Error: I am missing permissions to run this command. Please make sure I have permission to send messages to <#{}>." .format(ctx.message.channel.id)) except: try: return await bot.send_message( ctx.message.channel, f"Error: I cannot send messages to this user.") except: return if isinstance(original, NotFound): return await bot.send_message( ctx.message.channel, "Error: I tried to edit or delete a message that no longer exists." ) if isinstance(original, ValueError) and str(original) in ( "No closing quotation", "No escaped character"): return await bot.send_message(ctx.message.channel, "Error: No closing quotation.") if isinstance(original, AttributeError) and str(original) in ( "'NoneType' object has no attribute 'name'", ): return await bot.send_message( ctx.message.channel, "Error in Discord API. Please try again.") if isinstance(original, (ClientResponseError, InvalidArgument)): return await bot.send_message( ctx.message.channel, "Error in Discord API. Please try again.") if isinstance(original, HTTPException): if original.response.status == 400: return await bot.send_message( ctx.message.channel, "Error: Message is too long, malformed, or empty.") if original.response.status == 500: return await bot.send_message( ctx.message.channel, "Error: Internal server error on Discord's end. Please try again." ) if isinstance(original, redis.ResponseError): await bot.send_message( ctx.message.channel, "Error: I am having an issue writing to my database. Please report this to the dev!" ) return await bot.send_message( bot.owner, f"Database error!\n{repr(original)}") error_msg = gen_error_message() await bot.send_message( ctx.message.channel, f"Error: {str(error)}\nUh oh, that wasn't supposed to happen! " f"Please join <https://support.avrae.io> and tell the developer that {error_msg}!" ) try: await bot.send_message(bot.owner, f"**{error_msg}**\n" \ + "Error in channel {} ({}), server {} ({}), shard {}: {}\nCaused by message: `{}`".format( ctx.message.channel, ctx.message.channel.id, ctx.message.server, ctx.message.server.id, getattr(bot, 'shard_id', 0), repr(error), ctx.message.content)) except AttributeError: await bot.send_message(bot.owner, f"**{error_msg}**\n" \ + "Error in PM with {} ({}), shard 0: {}\nCaused by message: `{}`".format( ctx.message.author.mention, str(ctx.message.author), repr(error), ctx.message.content)) for o in discord_trim(tb): await bot.send_message(bot.owner, o) log.error("Error caused by message: `{}`".format(ctx.message.content)) traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr)
async def on_command_error(self, ctx, error): owner = self.bot.get_user(GG.OWNER) if isinstance(error, commands.CommandNotFound): return log.debug("Error caused by message: `{}`".format(ctx.message.content)) log.debug('\n'.join( traceback.format_exception(type(error), error, error.__traceback__))) if isinstance(error, FeCrawlerException): return await ctx.send(str(error)) tb = ''.join( traceback.format_exception(type(error), error, error.__traceback__)) if isinstance(error, (commands.MissingRequiredArgument, commands.BadArgument, commands.NoPrivateMessage, ValueError)): return await ctx.send("Error: " + str(error) + f"\nUse `{ctx.prefix}oldhelp " + ctx.command.qualified_name + "` for help.") elif isinstance(error, commands.CheckFailure): return await ctx.send( "Error: You are not allowed to run this command.") elif isinstance(error, commands.CommandOnCooldown): return await ctx.send( "This command is on cooldown for {:.1f} seconds.".format( error.retry_after)) elif isinstance(error, UnexpectedQuoteError): return await ctx.send( f"Error: You either gave me a command that requires quotes, and you forgot one.\n" f"Or you have used the characters that are used to define what's optional and required (<> and [])\n" f"Please check the ``!help`` command for proper usage of my commands." ) elif isinstance(error, ExpectedClosingQuoteError): return await ctx.send( f"Error: You gave me a command that requires quotes, and you forgot one at the end." ) elif isinstance(error, CommandInvokeError): original = error.original if isinstance( original, EvaluationError): # PM an alias author tiny traceback e = original.original if not isinstance(e, FeCrawlerException): tb = f"```py\nError when parsing expression {original.expression}:\n" \ f"{''.join(traceback.format_exception(type(e), e, e.__traceback__, limit=0, chain=False))}\n```" try: await ctx.author.send(tb) except Exception as e: log.info(f"Error sending traceback: {e}") if isinstance(original, FeCrawlerException): return await ctx.send(str(original)) if isinstance(original, Forbidden): try: return await ctx.author.send( f"Error: I am missing permissions to run this command. " f"Please make sure I have permission to send messages to <#{ctx.channel.id}>." ) except: try: return await ctx.send( f"Error: I cannot send messages to this user.") except: return if isinstance(original, NotFound): return await ctx.send( "Error: I tried to edit or delete a message that no longer exists." ) if isinstance(original, ValueError) and str(original) in ( "No closing quotation", "No escaped character"): return await ctx.send("Error: No closing quotation.") if isinstance(original, (ClientResponseError, InvalidArgument, asyncio.TimeoutError, ClientOSError)): return await ctx.send("Error in Discord API. Please try again." ) if isinstance(original, HTTPException): if original.response.status == 400: return await ctx.send( "Error: Message is too long, malformed, or empty.") if original.response.status == 500: return await ctx.send( "Error: Internal server error on Discord's end. Please try again." ) if original.response.status == 503: return await ctx.send( "Error: Connecting failure on Discord's end. (Service unavailable). Please check https://status.discordapp.com for the status of the Discord Service, and try again later." ) if isinstance(original, OverflowError): return await ctx.send( f"Error: A number is too large for me to store.") if isinstance(original, SearchException): return await ctx.send( f"Search Timed out, please try the command again.") if isinstance(original, KeyError): if str(original) == "'content-type'": return await ctx.send( f"The command errored on Discord's side. I can't do anything about this, Sorry.\nPlease check https://status.discordapp.com for the status on the Discord API, and try again later." ) error_msg = gen_error_message() await ctx.send( f"Error: {str(error)}\nUh oh, that wasn't supposed to happen! " f"Please join the 5eCrawler Support Discord (!support) and tell the developer that: **{error_msg}!**" ) if not self.bot.testing: try: await owner.send( f"**{error_msg}**\n" \ + "Error in channel {} ({}), server {} ({}): {}\nCaused by message: `{}`".format( ctx.channel, ctx.channel.id, ctx.guild, ctx.guild.id, repr(error), ctx.message.content)) except AttributeError: await owner.send(f"**{error_msg}**\n" \ + "Error in PM with {} ({}), shard 0: {}\nCaused by message: `{}`".format( ctx.author.mention, str(ctx.author), repr(error), ctx.message.content)) for o in discord_trim(tb): await owner.send(o) log.error("Error caused by message: `{}`".format(ctx.message.content))