async def sql(self, ctx, *, query): query = self.cleanup_code(query) is_multistatement = query.count(';') > 1 if is_multistatement: # fetch does not support multiple statements strategy = self.bot.db.execute else: strategy = self.bot.db.fetch try: results = await strategy(query) except Exception as e: return await ctx.send(f'```py\n{utils.format_exception(e)}\n```') rows = len(results) if is_multistatement or rows == 0: return await ctx.message.add_reaction(blobs.BLOB_TICK) headers = list(results[0].keys()) table = utils.TabularData() table.set_columns(headers) table.add_rows(list(r.values()) for r in results) render = table.render() fmt = f'```\n{render}\n```' if len(fmt) > 2000: fp = io.BytesIO(fmt.encode('utf-8')) await ctx.send('Too many results...', file=discord.File(fp, 'results.txt')) else: await ctx.send(fmt) await ctx.message.add_reaction(blobs.BLOB_TICK)
async def sql(self, ctx, *, query: str): """Run some SQL.""" query = self.cleanup_code(query) is_multistatement = query.count(';') > 1 if is_multistatement: strategy = ctx.pool.execute else: strategy = ctx.pool.fetch try: start = time.perf_counter() results = await strategy(query) dt = (time.perf_counter() - start) * 1000.0 except Exception: return await ctx.send(f'```py\n{traceback.format_exc()}\n```') rows = len(results) if is_multistatement or rows == 0: return await ctx.send(f'`{dt:.2f}ms: {results}`') headers = list(results[0].keys()) table = utils.TabularData() table.set_columns(headers) table.add_rows(list(r.values()) for r in results) render = table.render() fmt = f'```\n{render}\n```\n*Returned {utils.plural("row", rows)} in {dt:.2f}ms*' if len(fmt) > 2000: fp = io.BytesIO(fmt.encode('utf-8')) await ctx.send('Too many results...', file=discord.File(fp, 'results.txt')) else: await ctx.send(fmt)
async def handlerrrrr(self, ctx, exc=None): exc = getattr(exc, "original", exc) if isinstance(exc, commands.CommandNotFound): return table = utils.TabularData() table.set_columns(HEADERS) clean = ctx.message.clean_content.replace("\n", "\\n") log.error(f"[{ctx.message.created_at}] {ctx.guild} / {ctx.author}: {clean} |" f" {(type(exc).__name__ + ': ' + str(exc)) if exc else ''}")
async def experience(self, ctx, count: int = 20): """Same as the regular command, but sorted by Experience points.""" headers = ["Name", "Owner", "Experience", "Level"] table = utils.TabularData() table.set_columns(headers) table.add_rows([[p.name, str(p.owner), p.exp, p.level] for p in sorted(self.players, key=lambda m: m.exp, reverse=True) if p.owner.id != 455289384187592704][:count]) try: await ctx.send(f"```\n{table.render()}```") except discord.HTTPException: await ctx.send("Count too large.")
async def _global(self, ctx, count: int = 20): """Same as the regular command, but shows the global leaderboard.""" headers = ["Name", "Owner", "Level", "Total Caught"] table = utils.TabularData() table.set_columns(headers) table.add_rows([[p.name, str(p.owner), p.level, sum(p.raw_compendium_data)] for p in sorted(self.players, key=lambda m: sum(m.raw_compendium_data), reverse=True) if p.owner.id != 455289384187592704][:count]) try: await ctx.send(f"```\n{table.render()}\n```") except discord.HTTPException: await ctx.send("Count too large.")
async def leaderboard(self, ctx, count: int = 20): """Views the top 20 players in your server. Try to reach the top of the leaderboard!""" headers = ["Name", "Owner", "Level", "Total Caught"] table = utils.TabularData() table.set_columns(headers) table.add_rows([[p.name, str(p.owner), p.level, sum(p.raw_compendium_data)] for p in sorted( filter(lambda m: m.owner in ctx.guild.members and m.owner.id != 455289384187592704, self.players), key=lambda m: sum(m.raw_compendium_data), reverse=True)][:count]) try: await ctx.send(f"```\n{table.render()}\n```") except discord.HTTPException: await ctx.send("Count too large.")
async def activejobs(self, ctx): table = utils.TabularData() table.set_columns(["owner", "ttl", "type"]) for p in self.bot.player_manager.players: if await p.is_travelling(): table.add_row([ str(p.owner), await self.bot.redis.ttl(f"travelling_{p.owner.id}"), "travelling" ]) elif await p.is_exploring(): table.add_row([ str(p.owner), await self.bot.redis.ttl(f"exploring_{p.owner.id}"), "exploring" ]) await ctx.send(f"```\n{table.render()}\n```")
def format(self): fin = [ e.name for e in sorted(self._bot.enemy_manager.enemies, key=lambda e: e.id) if self.is_enemy_recorded(e) ] table = utils.TabularData() headers = fin[:2] rest = fin[2:] table.set_columns(headers) if rest: chunks = [ rest[x:x + 2] if len(rest[x:x + 2]) == 2 else [rest[x], ''] for x in range(0, len(rest), 2) ] table.add_rows(chunks) return table.render()
async def xc2pull(self, ctx, blade: str, luck: int, idea_level: int, core: str = 'Common'): """Shows chances for pulling a blade in Xenoblade Chronicles 2.""" cores = { 'legendary': 3, 'rare': 1.5, 'common': 1 } try: core_multiplier = cores[core.lower()] except KeyError: return await ctx.send('Invalid core.') luck_multiplier = max(math.sqrt(luck) * 0.01 * 1.3 + 0.95, 1) idea_multiplier = 1 + 0.05 * idea_level query = """ SELECT seed, (probability * ROUND($2::numeric * $3 * $4, 2))::float || '%' FROM xeno2.blade_chances WHERE LOWER(blade)=$1; """ results = await ctx.pool.fetch(query, blade.lower(), core_multiplier, luck_multiplier, idea_multiplier) if not results: return await ctx.send('This is not a pullable Blade.') table = utils.TabularData() table.set_columns(('Seed', 'Probability')) table.add_rows(list(r.values()) for r in results) render = table.render() await ctx.send(f'```\n{render}\n```')
async def mv(self, ctx, *, weapon: str.lower): """Shows the motion values for weapons.""" transformations = { 'gs': 'great sword', 'great sword': 'great sword', 'greatsword': 'great sword', 'ls': 'long sword', 'long sword': 'long sword', 'longsword': 'long sword', 'sns': 'sword and shield', 's&s': 'sword and shield', 'sword and shield': 'sword and shield', 'sword & shield': 'sword and shield', 'sword&shield': 'sword and shield', 'sword n shield': 'sword and shield', 'sword \'n\' shield': 'sword and shield', 'dbs': 'dual blades', 'db': 'dual blades', 'dual blades': 'dual blades', 'dualblades': 'dual blades', 'dual blade': 'dual blades', 'dualblade': 'dual blades', 'duals': 'dual blades', 'hammer': 'hammer', 'hh': 'hunting horn', 'horn': 'hunting horn', 'hunting horn': 'hunting horn', 'huntinghorn': 'hunting horn', 'lance': 'lance', 'gl': 'gunlance', 'gunlance': 'gunlance', 'gun lance': 'gunlance', 'sa': 'switch axe', 'axe': 'switch axe', 'switch axe': 'switch axe', 'switchaxe': 'switch axe', 'cb': 'charge blade', 'charge blade': 'charge blade', 'chargeblade': 'charge blade', 'ig': 'insect glaive', 'glaive': 'insect glaive', 'insect glaive': 'insect glaive', 'insectglaive': 'insect glaive', 'lbg': 'light bowgun', 'light bowgun': 'light bowgun', 'light bow gun': 'light bowgun', 'lightbow gun': 'light bowgun', 'lighbowgun': 'light bowgun', 'hbg': 'heavy bowgun', 'heavy bowgun': 'heavy bowgun', 'heavy bow gun': 'heavy bowgun', 'heavybow gun': 'heavy bowgun', 'heavybowgun': 'heavy bowgun', 'bow': 'bow', 'shot': 'shot', 'shots': 'shot', 'bullet': 'shot', 'bullets': 'shot', 'ammo': 'shot', 'ammos': 'shot' } weapon = transformations.get(weapon) if weapon is None: return await ctx.send('Weapon not found.') weapon_values = self.motion_values[weapon] table = utils.TabularData() table.set_columns(['Move', 'Damage Type', 'Motion Value/Stun/Exhaust']) for move, data in weapon_values.items(): table.add_row([ move, data['Damage Type'], f"{data['Motion Value']}/{data['Stun']}/{data['Exhaust']}" ]) render = table.render() paginator = commands.Paginator() for line in render.split('\n'): paginator.add_line(line) for p in paginator.pages: await ctx.send(p)