async def deleterr(self, ctx, rolename: str): """Deletes a reward role Usage: deleterr rolename""" conn = self.bot.pool try: sql = """SELECT * FROM roles WHERE rolename = $1 AND server_id = $2;""" fetch = await conn.fetch(sql, rolename, ctx.guild.id) if (fetch == []): response = emb.gen_embed_red("Warning!", "This is not a leveling role.") await ctx.send(embed=response) return await ctx.guild.get_role(fetch[0]["role_id"]).delete() await conn.execute("""DELETE FROM roles WHERE rolename = $1;""", rolename) response = emb.gen_embed_cobalt("Well done!", "The role has been deleted.") await ctx.send(embed=response) except Exception as e: log.warning(e) log.error(traceback.format_exc())
async def rewards(self, ctx, *args): """Fetches all the possible rewards for levels Usage: `rewards`""" conn = self.bot.pool try: sql = """SELECT * FROM roles WHERE server_id = $1 ORDER BY level ASC;""" fetch = await conn.fetch(sql, ctx.guild.id) if (fetch == []): response = emb.gen_embed_red("Warning!", """There are no roles yet. You can add roles using 'createrole Name Level (Colour)'.""") await ctx.send(embed=response) return table = [] for fetched in fetch: line = [fetched["rolename"], fetched["level"]] table.append(line) headers = ["Role", "Level"] content = tabulate.tabulate(table, headers, tablefmt="simple", stralign="left", numalign="right") response = emb.gen_embed_cobalt("Roles on this server:", f"```{content}```") await ctx.send(embed=response) except Exception as e: log.warning(e) log.error(traceback.format_exc())
async def on_message(self, message): regex = "^[^\"\'\.\w]" # noqa if re.search(regex, message.content) or message.author.bot: return conn = self.bot.pool guild = message.guild author = message.author time = message.created_at # Try block try: sql = """SELECT * FROM lb WHERE server_id = $1 AND user_id = $2; """ fetch = await conn.fetchrow(sql, guild.id, author.id) # Case 1: First message by user if fetch is None: newxp = random.randint(15, 25) sql = """INSERT INTO lb VALUES ( $1, $2, $3, $4, $5, $6 )""" await conn.execute(sql, guild.id, author.id, time, 1, newxp, 1) string = f"Welcome to the server, {author.name}! \n{author.name} is now level 1." e = emb.gen_embed_cobalt("A new adventure is starting.", string) await message.channel.send(embed=e) return # Case 2: Less than 1 min has elasped since last message. if (time - fetch["last_exp"]).seconds < 60: sql = """UPDATE lb SET msg_amt = $1 WHERE server_id = $2 AND user_id = $3""" await conn.execute(sql, fetch[3]+1, guild.id, author.id) return # Case 3: Awarding new xp. Then, newxp = fetch[4] + random.randint(15, 25) level = fetch[5] # If leveled up call leveling Function if newxp >= level_up(level): newlevel = await leveling_up(message.channel, guild, conn, author, level, newxp) sql = """UPDATE lb SET msg_amt = $1, total_exp = $2, last_exp = $3, level = $4 WHERE server_id = $5 AND user_id = $6""" await conn.execute(sql, fetch[3] + 1, newxp, time, newlevel, guild.id, author.id) # Otherwise, silently add the awarded xp to the database else: sql = """UPDATE lb SET msg_amt = $1, total_exp = $2, last_exp = $3 WHERE server_id = $4 AND user_id = $5""" await conn.execute(sql, fetch[3] + 1, newxp, time, guild.id, author.id) except Exception as e: log.warning(e) log.error(traceback.format_exc())
async def weather(self, ctx): """Generate a random npc `weather`""" # Create embed e = emb.gen_embed_cobalt('Weather Generator', None) # Generate Precipitation precip = [ 'No Precipitation', 'Light rain or snowfall', 'Heavy rain or snowfall' ] precip = np.random.choice(precip, p=[0.6, 0.25, 0.15]) e.add_field(name='Precipitation', value=precip, inline=False) # Generate Temps roll = random.randint(1, 4) temp = [ 'Normal for the season', f'{roll*10} degrees Fahrenheit colder than normal', f'{roll*10} degrees Fahrenheit colder than normal' ] temp = np.random.choice(temp, p=[0.7, 0.15, 0.15]) e.add_field(name='Temperature', value=temp, inline=False) # Generate Wind wind = ['No Wind', 'Light Wind', 'Medium Wind', 'Heavy/Strong Wind'] wind = np.random.choice(wind, p=[0.1, 0.55, 0.2, 0.15]) e.add_field(name='Wind', value=wind, inline=False) # Generate speeds roll = random.randint(1, 6) + random.randint(1, 6) direction = [ 'North', 'North-East', 'East', 'South-East', 'South', 'South-West', 'West', 'North-West' ] if wind == 'Medium Wind': speed = [50, 40, 30, 20, 10, 0, 0, 10, 20, 30, 40, 50] speed = str(speed[roll - 1]) + ' feet' e.add_field(name='Speed', value=speed, inline=False) direction = np.random.choice(direction) e.add_field(name='Direction', value=direction, inline=False) elif wind == 'Heavy/Strong Wind': speed = [110, 100, 90, 80, 70, 60, 60, 70, 80, 90, 100, 110] speed = str(speed[roll - 1]) + ' feet' e.add_field(name='Speed', value=speed, inline=True) direction = np.random.choice(direction) e.add_field(name='Direction', value=direction, inline=False) await ctx.send(embed=e)
async def gnpc(self, ctx, *args): """Generate a random npc `gnpc m/f/t[Optional] race[Optional]`""" sex = None race = None for arg in args: if len(arg) == 1: sex = arg else: race = arg response = npcgen.main(sex, race) response = emb.gen_embed_cobalt('NPC Generator', response) await ctx.send(embed=response)
async def ranking(self, ctx, max: int = 15): """Lists top 15 ranked adventurers on the server Usage: `rank`""" conn = self.bot.pool try: sql = """SELECT * FROM lb WHERE server_id=$1 ORDER BY total_exp DESC;""" fetch = await conn.fetch(sql, ctx.guild.id) except Exception as e: print(e) if fetch == []: e = emb.gen_embed_red("Warning!", "There are no adventurers in this guild.") await ctx.send(embed=e) return rank = 1 table = [] for fetched in fetch: try: line = [rank, ctx.guild.get_member(fetched["user_id"]).name, fetched["level"]] except Exception: sql = """DELETE FROM lb WHERE server_id=$1 and user_id=$2;""" await conn.execute(sql, ctx.guild.id, fetched["user_id"]) log.warning(f"Deleted {fetched['user_id']} from db") continue table.append(line) if rank > max: break else: rank += 1 headers = ["Rank", "Name", "Level"] content = tabulate.tabulate(table, headers, tablefmt="simple", stralign="left", numalign="center") if len(content) > 2000: await ctx.send("Too many entries. Fix coming soon-ish.") else: e = emb.gen_embed_cobalt("Ranking", f"```{content}```") await ctx.send(embed=e)
async def levels(self, ctx, max: int = 10): """Lists the xp required for levels Usage: `levels level`""" string = "" if max < 3: min = max else: min = max - 3 max = max + 3 for i in range(min, max): string += f"To level {i+1}: {level_up(i)} xp\n" e = emb.gen_embed_cobalt("XP requirements by level", string) await ctx.send(embed=e)
async def createrr(self, ctx, rolename: str, level: int, colour: discord.Colour = discord.Colour.default()): """Creates a reward role Usage: `createrr rolename level colour`""" conn = self.bot.pool try: # checking if the role already exists, or if there is another role at that level sql = """SELECT * FROM roles WHERE rolename = $1 AND server_id = $2""" fetch = await conn.fetch(sql, rolename, ctx.guild.id) if (fetch != []): response = emb.gen_embed_red("Warning!", "This rolename already exists.") await ctx.send(embed=response) return fetch = await conn.fetch("""SELECT * FROM roles WHERE level = $1 AND server_id = $2;""", level, ctx.guild.id) if (fetch != []): response = emb.gen_embed_red("Warning!", "There already is a role at this level.") await ctx.send(embed=response) return # Creating a new role in the server # (note: this doesn't check if another role with the same name already exists). role = await ctx.guild.create_role(name=rolename, colour=colour) # creating a new role in the database and linking to the server role by id await conn.execute("""INSERT INTO roles VALUES ( $1, $2, $3, $4 )""", rolename, ctx.guild.id, role.id, level) response = emb.gen_embed_cobalt("Well done!", "New role created!") await ctx.send(embed=response) except Exception as e: log.warning(e) log.error(traceback.format_exc())
async def rank(self, ctx, member: discord.Member = None): """Gets rank on the server Usage: `rank id[Optional]`""" conn = self.bot.pool # Verification if member is None: member = ctx.author try: sql = """SELECT * FROM lb WHERE server_id=$1 AND user_id=$2""" fetch = await conn.fetchrow(sql, ctx.guild.id, member.id) if fetch is None: e = emb.gen_embed_red("", "This adventurer doesn't have any xp on this server.") await ctx.send(embed=e) return xp = fetch[4] level = fetch[5] nxp = level_up(level) missxp = nxp - xp string = f"You are level {level} on this server, with {xp} xp.\n" string += f"You last gained xp {(ctx.message.created_at - fetch[2]).seconds} seconds ago." string += f"\n\n Level {level+1} requires {nxp} xp: You need {missxp} more." e = emb.gen_embed_cobalt(f"{member}", string) e.set_thumbnail(url=member.avatar_url) e.add_field(name="XP", value=f"{xp}/{nxp}", inline=True) e.add_field(name="Level", value=level, inline=True) e.add_field(name="Messages", value=fetch[3], inline=True) await ctx.send(embed=e) except Exception as e: log.warning(e) log.error(traceback.format_exc())
async def giverep(self, ctx, member: discord.Member, rep: int = 1): """ Gives another member rep. (Max of 1) Usage: `giverep "username"/@mention/id rep` """ # Set Varaibles author = ctx.author conn = self.bot.pool roles = ctx.author.roles is_admin = False for role in roles: if role.name == "Admin": is_admin = True # Validation if rep == 0: e = emb.gen_embed_cobalt("Eh?", f"{member.name} was given 0 rep??") await ctx.send(embed=e, delete_after=5) return if member.bot: await ctx.send("`Can't give rep to a bot.`") return if not is_admin and (ctx.author.id == member.id): e = emb.gen_embed_red("Hunh", "Sneakily trying to give yourself xp eh.") await ctx.send(embed=e, delete_after=5) return for elem, user in enumerate(self.cooldown): curr_time = time.time() if user[0] == author.id and (curr_time - user[1]) < 120: e = emb.gen_embed_red("Cooldown", f"Currently in cooldown.") await ctx.send(embed=e, delete_after=5) return elif user[0] == author.id and (curr_time - user[1] > 120): self.cooldown.pop(elem) else: pass if not is_admin and (rep > 1 or rep < 0): e = emb.gen_embed_red("Eh??", f"Unable to give more than 1 rep.") await ctx.send(embed=e, delete_after=5) return try: sql = """INSERT INTO rep (server_id, user_id, rep) VALUES ($1, $2, $3) ON CONFLICT ON CONSTRAINT server_user DO UPDATE SET rep = rep.rep + $3;""" await conn.execute(sql, ctx.guild.id, member.id, rep) e = emb.gen_embed_green("Rep", f"Gave {member.name} {rep} rep.") await ctx.send(embed=e, delete_after=5) await ctx.message.add_reaction('<:tick:741279181895106592>') if not is_admin: curr_time = time.time() self.cooldown.append((author.id, curr_time)) except Exception as e: log.error(traceback.format_exc())
async def toprep(self, ctx, page: int = 1): """ Displays the ranking by reputation. Usage: `toprep (page_num)` """ # Validation if page < 1: return # Variables conn = self.bot.pool try: sql = """SELECT * FROM rep WHERE server_id=$1 ORDER BY rep.rep DESC;""" fetch = await conn.fetch(sql, ctx.guild.id) except Exception as e: log.error(traceback.format_exc()) if fetch is []: message = "No one in this server has reputation points." await ctx.send(message) return table = list() if len(fetch) < (15 * (page - 1)): message = f"Not enough users with rep to display page {page}" await ctx.send(message) return fetch = fetch[15 * (page - 1):] rank = 15 * (page - 1) + 1 for elem, fetched in enumerate(fetch): try: line = [ rank, ctx.guild.get_member(fetched["user_id"]).name, fetched["rep"] ] except Exception: sql = """DELETE FROM rep WHERE server_id=$1 and user_id=$2;""" await conn.execute(sql, ctx.guild.id, fetched["user_id"]) log.warning(f"Deleted {fetched['user_id']} from db") continue table.append(line) rank += 1 if elem > 14: break headers = ["Rank", "Name", "Rep"] content = tabulate.tabulate(table, headers, tablefmt="simple", stralign="left", numalign="center") if len(content) > 2000: await ctx.send("Too many entries. Fix coming soon-ish ") else: e = emb.gen_embed_cobalt("Ranking", f"```{content}```") await ctx.send(embed=e)
async def givexp(self, ctx, member: discord.Member, exp: int): """Gives another member xp Usage: `givexp "username"/@mention/id xp_amt`""" # Validation if exp < 0: e = emb.gen_embed_red("Warning!", "You can't give negative xp.") await ctx.send(embed=e) return if exp == 0: e = emb.gen_embed_cobalt("Eh?", f"{member.name} was given 0 xp. Nothing to write home about...") await ctx.send(embed=e) return # Set connection conn = self.bot.pool try: sql = """SELECT * FROM lb WHERE server_id=$1 AND user_id=$2;""" fetch = await conn.fetchrow(sql, ctx.guild.id, member.id) # If no previous entry if fetch is None: sql = """INSERT INTO lb VALUES ($1, $2, $3, $4, $5, $6)""" await conn.execute(sql, ctx.guild.id, member.id, ctx.message.created_at, 1, 0, 0) string = f"Welcome to this server, {member.name}!\n{member.name} is now level 1." e = emb.gen_embed_green("A new adventure is starting", string) await ctx.send(embed=e) newxp = exp level = 1 else: string = f"{member.name} was given {exp} exp!" e = emb.gen_embed_green("", string) await ctx.send(embed=e) newxp = fetch[4] + exp level = fetch[5] # If threshold reached next level if newxp >= level_up(level): newlevel = await leveling_up(ctx.channel, ctx.guild, conn, member, level, newxp) sql = """UPDATE lb SET total_exp = $1, last_exp = $2, level = $3 WHERE server_id = $4 AND user_id = $5""" await conn.execute(sql, newxp, ctx.message.created_at, newlevel, ctx.guild.id, member.id) else: sql = """UPDATE lb SET total_exp = $1, last_exp = $2 WHERE server_id = $3 AND user_id = $4""" await conn.execute(sql, newxp, ctx.message.created_at, ctx.guild.id, member.id) except Exception as e: log.warning(e) log.error(traceback.format_exc())
async def gletter(self, ctx): """ Creates a letter handout. Asks for a Title(Optional), Content and Signature(Optional). The command has a timeout of 30 secs at each stage.""" from utils import letter_gen as lettergen # noqa # Get variables author = ctx.author def check(message): return author == message.author # Create initial embeds msg = "Let's begin the process. Please type the title on the letter or c to cancel" msg += "\n(Note: Title and Signature can be left empty by typing None.)\n" msg += "(Note: Every section has a 30 secs time limit.)" # Send inital embed e = emb.gen_embed_cobalt('Creating Letter', "") preview = await ctx.send(msg, embed=e) # Getting the title try: title = await self.bot.wait_for('message', timeout=30, check=check) except asyncio.TimeoutError: await ctx.channel.send('Timed out. 👎') return if title.content == 'c': return elif title.content.lower() == 'none': title.content = None else: title.content = str(title.content) # Getting Content msg = 'Next type in the content or enter c to cancel...' e = emb.gen_embed_cobalt('Creating Letter', "") e.set_thumbnail(url=ctx.author.avatar_url) e.add_field(name='Title', value=title.content, inline=False) await preview.edit(content=msg, embed=e) try: content = await self.bot.wait_for('message', timeout=30, check=check) except asyncio.TimeoutError: await ctx.channel.send('Timed out. 👎') return if content.content == 'c': return else: content.content = str(content.content) if len(content.content) > 770: content.content = content.content[:770] val = f'{content.content[:500]}...' val = content.content e.add_field(name='Content', value=val, inline=False) # Getting the signature await preview.edit(content="Next enter the signature", embed=e) try: signature = await self.bot.wait_for('message', timeout=30, check=check) except asyncio.TimeoutError: await ctx.channel.send('Timed out. 👎') return if signature.content == 'c': return elif signature.content.lower() == 'none': signature.content = None else: signature.content = str(signature.content) e.add_field(name='Signature', value=signature.content, inline=False) await preview.edit(content='Generating...', embed=e) async with ctx.typing(): image = lettergen.main(title.content, content.content, signature.content) file = discord.File(filename="circle.png", fp=image) await preview.delete() await ctx.send(file=file)