async def get(self, ctx: commands.Context, player: discord.Member = None): '''Displays a user\'s character.''' char = None async with self.bot.connect_pool.acquire() as conn: char = await roller.retrieve_character( conn, player if player is not None else ctx.author) if char is not None: em = boiler.embed_template(char["name"]) em.description = '' for i in range(len(char['classes'])): em.description += "Level {} {}\n".format( char['levels'][i], char['classes'][i]) char_scores = '' for stat, fullname in { "STR": "strength", "DEX": "dexterity", "CON": "constitution", "INT": "intelligence", "WIS": "wisdom", "CHR": "charisma" }.items(): score = char[fullname] modstring = "+ {}".format(roller.mod_from_score( score)) if score > 9 else "- {}".format( abs(roller.mod_from_score(score))) char_scores += "**{0}:** {1!s} ({2})\n".format( stat, score, modstring) em.add_field(name='Stats', value=char_scores) await ctx.send(None, embed=em) else: await roller.no_character(ctx, player)
async def listme(self, ctx: commands.Context): """Lists all roles available with giveme.""" guilddict = await self.get_guild_dict(ctx.guild.id) em = boiler.embed_template("List of Roles", ctx.me.color) em.description = "May not be all-encompassing. Only includes roles a guild moderator has set the status of." send = "" for role_id in guilddict["available"]: role = discord.utils.get(ctx.guild.roles, id=role_id) if role is not None: send += "* {}\n".format(role.name) if send is not "": em.add_field(name="Available roles", value=send, inline=True) send = "" for role_id in guilddict["special"]: role = discord.utils.get(ctx.guild.roles, id=role_id) if role is not None: send += "* {}\n".format(role.name) if send is not "": em.add_field(name="Roles blocked from giveme", value=send, inline=True) if len(em.fields) > 0: await ctx.send(None, embed=em) else: await ctx.send("No roles configured!")
async def listusers(self, ctx: commands.Context, *, role: discord.Role): '''Get a list of users with the role `role`.''' em = boiler.embed_template("Users with role {}".format(role.name)) em.description = "" for m in role.members: em.description += (m.mention + "\n") await ctx.send(None, embed=em)
async def userinfo(self, ctx: commands.Context, user: str): redditor = {} async with aiohttp.ClientSession() as cs: async with cs.get( "https://reddit.com/u/{}/about.json".format(user)) as resp: if 300 > resp.status >= 200: redditor = (await resp.json())["data"] else: return await ctx.send( "Could not fetch information for user `{}`!".format( user)) em = boiler.embed_template( title=redditor["subreddit"]["title"] if redditor["subreddit"] is not None else redditor["name"], color=ctx.me.color, ) em.url = "https://reddit.com/u/{}".format(user) em.set_thumbnail(url=redditor["icon_img"]) em.add_field(name="Post Karma", value=redditor["link_karma"], inline=True) em.add_field(name="Comment Karma", value=redditor["comment_karma"], inline=True) await ctx.send(embed=em)
async def listusers(self, ctx: commands.Context, *, role: discord.Role): """Get a list of users with the role `role`.""" em = boiler.embed_template("Users with role {}".format(role.name), ctx.me.color) em.description = "" for m in role.members: em.description += m.mention + "\n" await ctx.send(embed=em)
async def create_onecall(self, ctx: commands.Context, name: str, race: str, character_classes: boiler.comma_sep, class_levels: boiler.comma_sep, *stats): """Creates a character (long form.)""" # HACK: For some reason character_classes occasionally becomes a string. If it's a string we make it a list instead. if type(character_classes) is str: character_classes = [character_classes] em = boiler.embed_template(name, ctx.me.color) if len(class_levels) != len(character_classes): await ctx.send( "Error in class / level list! {} classes and {} levels given". format(len(character_classes), len(class_levels))) return else: em.description = "" for i in range(len(character_classes)): em.description += "Level {} {}\n".format( class_levels[i], character_classes[i]) s = {} for i in range(len(scores)): s[scores[i]] = roller.to_int(stats[i]) statblock = "" for stat, score in s.items(): modstring = ("+ {}".format(roller.mod_from_score(score)) if score > 9 else "- {}".format( abs(roller.mod_from_score(score)))) statblock += "**{0}:** {1!s} ({2})\n".format( stat, score, modstring) em.add_field(name="Stats", value=statblock) # prepare levels list int_levels = [] for level in class_levels: int_levels.append(roller.to_int(level)) async with ctx.typing(): async with self.bot.connect_pool.acquire() as conn: try: # TODO: optimize with prepared statements somehow? await conn.execute( "INSERT INTO dnd_chars(name, strength, dexterity, constitution, intelligence, wisdom, charisma, race, discord_id, levels, classes) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", name, s["STR"], s["DEX"], s["CON"], s["INT"], s["WIS"], s["CHR"], race, str(ctx.author.id), int_levels, character_classes, ) except asyncpg.UniqueViolationError: await ctx.send( "You already have a character saved, and this command won't overwrite it!\n(All that construction work for nothing...)" ) return await ctx.send(embed=em)
async def purge(self, ctx: commands.Context, amount: int): '''Bulk remove messages.''' async with ctx.typing(): deleted = await ctx.channel.purge(limit=amount + 1) em = boiler.embed_template("Purged {} messages".format(len(deleted))) em.set_footer(text="Requested by {}".format(ctx.author.display_name), icon_url="https://i.imgur.com/2VepakW.png") await ctx.send(None, embed=em, delete_after=5 if len(deleted) <= 5 else None)
async def get_badge(self, ctx: commands.Context): """Get the QR code you use to clock in/out.""" em = boiler.embed_template("", ctx.me.color) em.set_image(url="https://api.qrserver.com/v1/create-qr-code/?data=" + str(ctx.author.id)) em.description = "Here's your badge, {}! [Get it as a vector here.]({})".format( ctx.author.mention, "https://api.qrserver.com/v1/create-qr-code/?data=" + str(ctx.author.id) + "&format=svg", ) await ctx.send(None, embed=em, delete_after=5)
async def devalue(self, ctx: commands.Context, *, source: str): """Evaluates arbitrary Python 3 code blocks.""" env = { # set some shortcuts up "bot": self.bot, "ctx": ctx, "channel": ctx.channel, "author": ctx.author, "guild": ctx.guild, "message": ctx.message, "_": self._last_result, } env.update(globals()) source = self.cleanup_code(source) to_run = "async def func():\n{}".format( textwrap.indent(source, " ") ) # wrap source in async def ret = None output = io.StringIO() try: exec(to_run, env) # executes to_run, defining func() except Exception as e: # sends traceback return await ctx.send( "```py\n{0}: {1}\n```".format(e.__class__.__name__, e) ) func = env["func"] try: with contextlib.redirect_stdout(output): ret = await func() except Exception as e: # failed to run due to exception in func() value = output.getvalue() await ctx.send("```py\n{0}{1}\n```".format(value, traceback.format_exc())) else: # all went well, send result self._last_result = ret em = boiler.embed_template("Result", ctx.me.color) em.description = "Python 3 code evaluation" if output.getvalue() != "": em.add_field( name="Output", value="```\n{}\n```".format(output.getvalue()), inline=False, ) em.add_field( name="Return value", value="```\n{}\n```".format(ret), inline=False ) await ctx.send(None, embed=em)
async def devalue(self, ctx: commands.Context, *, source: str): '''Evaluates arbitrary Python 3 code blocks.''' env = { # set some shortcuts up 'bot': self.bot, 'ctx': ctx, 'channel': ctx.channel, 'author': ctx.author, 'guild': ctx.guild, 'message': ctx.message, '_': self._last_result } env.update(globals()) source = self.cleanup_code(source) to_run = 'async def func():\n{}'.format( textwrap.indent(source, " ")) # wrap source in async def ret = None output = io.StringIO() try: exec(to_run, env) # executes to_run, defining func() except Exception as e: # sends traceback return await ctx.send('```py\n{0}: {1}\n```'.format(e.__class__.__name__, e)) func = env['func'] try: with contextlib.redirect_stdout(output): ret = await func() except Exception as e: # failed to run due to exception in func() value = output.getvalue() await ctx.send('```py\n{0}{1}\n```'.format(value, traceback.format_exc())) else: # all went well, send result self._last_result = ret em = boiler.embed_template("Result") em.description = "Python 3 code evaluation" if (output.getvalue() != ''): em.add_field(name="Output", value='```\n{}\n```'.format( output.getvalue()), inline=False) em.add_field(name="Return value", value='```\n{}\n```'.format(ret), inline=False) await ctx.send(None, embed=em)
async def get_chancreate_defaults(self, ctx: commands.Context): """ Posts the current default permissions for channels created with Lopez. """ g_row = await self.get_guild_data(ctx.guild.id) current = (g_row["default_permission"] if g_row["default_permission"] is not None else {}) if current != {}: readable = {} em = boiler.embed_template("Default permissions for new channels", ctx.guild.me.color) for key, value in current.items(): role = await self.role_converter.convert(ctx, key) permissions = "```\n" for permission, state in value.items(): permissions += "{}: {}\n".format(permission, state) permissions += "```" em.add_field(name=role.name, value=permissions, inline=True) await ctx.send(None, embed=em) else: await ctx.send( "Default permissions for new channels haven't been configured!" )