async def events(self, ctx): """Provides debug informatioo about the events run by the bot.""" counters = ctx.bot.bot_counters columns = ('Event', '# Dispatched', '# Run', 'Total Runtime', 'Average Time') keys = set() for key in ('events_dispatched', 'events_run', 'event_total_runtime'): keys.update(counters[key].keys()) table = texttable.Texttable() table.set_deco(texttable.Texttable.HEADER | texttable.Texttable.VLINES) table.set_cols_align(["r"] * len(columns)) table.set_cols_valign(["t"] + ["i"] * (len(columns) - 1)) table.header(columns) for key in sorted(keys): runtime = counters['event_total_runtime'][key] run_count = counters['events_run'][key] avg_runtime = runtime / run_count if run_count else "N/A" table.add_row([ key, counters['events_dispatched'][key], run_count, runtime, avg_runtime ]) output = await hastebin.str_or_hastebin_link(ctx.bot, table.draw()) await ctx.send(format.multiline_code(output))
async def search_user(self, ctx, regex): """Searches the users the bot can see for matches""" regex = re.compile(regex) usernames = ctx.session.query(models.Usernames).all() # Deduplicate entries users = {u.id: u for u in usernames if regex_multi_attr_match(regex, u, self.USER_CRITERIA)} users = (f'{u.id}: {u.name}#{u.discriminator}' for _, u in users.items()) await ctx.send(format.multiline_code(format.vertical_list(users)))
def make_whois_embed(ctx, user): now = datetime.utcnow() description = [] guild_count = _get_guild_count(ctx, user) if guild_count > 1: count = format.bold(str(guild_count)) description.append(f'Seen on {count} servers.') usernames = _get_extra_usernames(ctx, user) if len(usernames) > 0: output = reversed([_to_username_line(un) for un in usernames]) description.append(format.multiline_code(format.vertical_list(output))) description = None if len(description) <= 0 else '\n'.join(description) embed = discord.Embed( title=f'{user.name}#{user.discriminator} ({user.id})', color=user.color, description=description) embed.set_thumbnail(url=str(user.avatar_url or user.default_avatar_url)) embed.set_footer(text=hex(user.id)) _add_time_field(embed, 'Created At', user.created_at, now) try: _add_time_field(embed, 'Joined On', user.joined_at, now) except AttributeError: pass try: if user.premium_since is not None: _add_time_field(embed, 'Boosting Since', user.premium_since, now) except AttributeError: pass try: if len(user.roles) > 1: roles = reversed([r for r in user.roles if r.name != '@everyone']) roles = format.code_list(r.name for r in roles) embed.add_field(name='Roles', value=roles) except AttributeError: pass return embed
async def roll(self, ctx, *dice: die): """ Rolls some dice Example usages: ~roll 3d6 ~roll 3d6 2d8 ~roll 3d6+5 ~roll 3d6-5 ~roll 3d6*5 ~roll 3d6/5 ~roll 3d6^5 """ total_count = sum(d.count for d in dice) if total_count > 150: await ctx.send('Cannot roll more than 150 dice at once.') return if any(d.modifier < 0 or d.modifier > 99 for d in dice): await ctx.send('Any modifier must be in the range of 0-99.') return rolls = [] total = 0 for die in dice: dice_rolls = list(random.randint(die.min, die.max) for x in range(die.count)) rolls.extend(dice_rolls) sub_total = sum(dice_rolls) logging.info(die.mod_type) sub_total = { "+": lambda x: x + die.modifier, "-": lambda x: x - die.modifier, "/": lambda x: x / die.modifier, "*": lambda x: x * die.modifier, "x": lambda x: x * die.modifier, "^": lambda x: x ** die.modifier, }.get(die.mod_type, lambda x: x)(sub_total) total += sub_total rolls.sort() resp = [f"Rolled a total of `{total}` from {len(rolls)} rolls:"] resp.append(format.multiline_code( format.comma_list(str(r) for r in rolls))) await ctx.send('\n'.join(resp))
async def stats(self, ctx): """Provides statistics for each shard of the bot.""" output = [] latencies = dict(ctx.bot.latencies) columns = ('Shard', 'Guilds', 'Total Members', 'Loaded Members', 'Music', 'Messages', 'Latency') shard_stats = {shard_id: Owner.get_shard_stats(ctx, shard_id) for shard_id in latencies.keys()} table = texttable.Texttable() table.set_deco(texttable.Texttable.HEADER | texttable.Texttable.VLINES) table.set_cols_align(["r"] * len(columns)) table.set_cols_valign(["t"] + ["i"] * (len(columns) - 1)) table.header(columns) for shard_id, stats in sorted(shard_stats.items()): stats['Latency'] = latencies.get(shard_id) or 'N/A' table.add_row([shard_id] + [stats[key] for key in columns[1:]]) output.append(table.draw()) output.append('') output.append(f'discord.py: {discord.__version__}') await ctx.send(format.multiline_code(format.vertical_list(output)))
async def search_guild(self, ctx, regex): """Searches the servers the bot is on for matches.""" regex = re.compile(regex) guilds = (f'{g.id}: {g.name}' for g in ctx.bot.guilds if regex_multi_attr_match(regex, g, self.GUILD_CRITERIA)) await ctx.send(format.multiline_code(format.vertical_list(guilds)))
async def send_error(self, error, msg=''): trace_str = self._get_traceback(error) trace_str = await hastebin.str_or_hastebin_link(self.bot, trace_str) await self.send_log(f"`{msg}`\n" +format.multiline_code(trace_str))
def traceback_to_embed(keep_end=False): text = format.multiline_code(traceback.format_exc()) return text_to_embed(text, keep_end=keep_end)