async def on_raw_reaction_add(self, payload): """ Checks reactions and deletes tracked messages when necessary. """ if payload.user_id == self.bot.user.id: return if payload.emoji.name == CONSTANTS.REACTION_DELETE: is_tracked = False sender_uid = None with SQLCursor(self.db) as cur: cur.execute( "SELECT messid, sender_uid FROM tracked_messages WHERE messid=?", (payload.message_id, )) row = cur.fetchone() if row: is_tracked = True sender_uid = row[1] if is_tracked: reacting_member = self.bot.get_guild( payload.guild_id).get_member(payload.user_id) can_delete = self.bot.get_channel( payload.channel_id).permissions_for( reacting_member).manage_messages if payload.user_id == sender_uid or can_delete: relevant_message = await self.bot.get_channel( payload.channel_id).get_message(payload.message_id) await relevant_message.delete()
async def show_occupants(self, ctx, position=''): pos = position.title() position = position.replace(' ', '_') if position.lower() in self.positions: with SQLCursor(self.db) as cur: cur.execute( 'SELECT description, officer FROM govt_info WHERE position = ?;', (position, )) row = cur.fetchone() if row: plural = False if row[1] is not None and ',' in row[1]: officers = [ str(ctx.message.guild.get_member(int(member_id))) for member_id in row[1].split(',') ] officers = ', '.join(officers) plural = True else: officers = (str( ctx.message.guild.get_member(int(row[1]))) if row[1] is not None and row[1].strip() != '' else 'Vacant') description = row[0] await ctx.message.channel.send( 'The current _{}: _{}_'.format( pos + ('s_ are' if plural else '_ is'), officers)) if description is not None and description.strip() != '': await ctx.message.channel.send( 'Description: \n```{}```'.format(description)) else: await ctx.channel.send( 'Invalid position. Here is a list of valid positions: ' + ', '.join(self.positions).replace('_', ' '))
async def remove(self, ctx, position, user: discord.User): member_id = user.id if ctx.message.author.top_role.name.lower() == 'officer': with SQLCursor(self.db) as cur: cur.execute( 'SELECT officer FROM govt_info WHERE position = ?;', (position, )) row = cur.fetchone() if row: officers = ','.join(row) if row[0] is not None else '' if officers.strip() != '': officers = officers.replace(str(member_id) + ',', '').replace( str(member_id), '') if len(officers.split(',')) == 1: officers = officers.replace(',', '') elif officers[len(officers) - 1:len(officers)] == ',': officers = officers[0:len(officers) - 1] cur.execute( 'UPDATE govt_info SET officer = ? WHERE position = ?;', (officers, position)) await ctx.message.channel.send( 'Successfully removed **{}** from the **{}** position.' .format(str(user), position)) else: await ctx.message.channel.send( 'Hey! You do not have permission to do that.')
async def set(self, ctx, position, user: discord.User): if ctx.message.author.top_role.name.lower() == 'officer': member_id = user.id if position is None or member_id is None: await ctx.message.channel.send( 'Invalid command format, try: `eboard admin set <position> <@User#0000>`' ) else: with SQLCursor(self.db) as cur: cur.execute( 'SELECT officer FROM govt_info WHERE position = ?;', (position, )) row = cur.fetchone() if row: officers = ','.join(row) if row[0] is not None else '' if str(member_id) in officers: return officers += (',' if officers.strip() != '' else '') + '{0}'.format(str(member_id)) else: officers = str(member_id) cur.execute( 'UPDATE govt_info SET officer = ? WHERE position = ?;', (officers, position)) await ctx.message.channel.send( 'Successfully added **{}** to the **{}** position.'. format(str(user), position)) else: await ctx.message.channel.send( 'Hey! You do not have permission to do that.')
async def tally(self, ctx): ''' Get the current goodbot/badbot tally ''' with SQLCursor(self.db) as cur: cur.execute("SELECT vote, tally FROM goodbot_badbot") row = cur.fetchone() await ctx.send("{0}: {1}".format(str(row[0]), str(row[1]))) row = cur.fetchone() await ctx.send("{0}: {1}".format(str(row[0]), str(row[1])))
def vote(self, good): ''' Votes goodbot if good is true, badbot if good is false ''' vote = "good" if good else "bad" with SQLCursor(self.db) as cur: cur.execute("SELECT vote, tally FROM goodbot_badbot WHERE vote=?", (vote,)) row = cur.fetchone() new_tally = row[1] + 1 cur.execute("UPDATE goodbot_badbot SET tally=? WHERE vote=?", (new_tally, vote))
async def query_position(self, position): """Return all of the officers for a corresponding position as a string list separated by commas.""" with SQLCursor(self.db) as cur: cur.execute('SELECT officer FROM govt_info WHERE position=?', (position, )) row = cur.fetchone() if row: return row[0] if not None else ''
def initialize(): ''' Initializes the table with non-null 'vote' positions ''' sql_db = SQLConnection() with SQLCursor(sql_db) as cur: cur.execute("SELECT vote from goodbot_badbot") row = cur.fetchone() for vote in Tally.votes: if row is None or len(row) != len(Tally.votes): cur.execute("INSERT OR IGNORE INTO goodbot_badbot VALUES (?, ?)", (vote, 0))
def initialize(): """Initializes the table with non-null 'position' columns.""" sql_db = SQLConnection() with SQLCursor(sql_db) as cur: cur.execute('SELECT position from govt_info') row = cur.fetchone() for pos in Government.positions: if row is None or len(row) != len(Government.positions): cur.execute( 'INSERT OR IGNORE INTO govt_info (position) VALUES (?);', (pos, ))
async def clear(self, ctx): """Clears all officers from their positions in the SQLite table.""" if ctx.message.author.top_role.name.lower() == 'officer': with SQLCursor(self.db) as cur: cur.execute('UPDATE govt_info SET officer = Null;') await ctx.message.channel.send( 'Successfully cleared all officers from all positions in the SQLite table.' ) else: await ctx.message.channel.send( 'Hey! You do not have permission to do that.')
async def track(message, author=None): """ Marks a message in the database so that it will be automatically deleted if the sender or an admin reacts with the 'trash' emoji """ await message.add_reaction(CONSTANTS.REACTION_DELETE) sql_db = SQLConnection() aid = 0 if author: aid = author.id with SQLCursor(sql_db) as cur: cur.execute( "INSERT INTO tracked_messages (messid, sender_uid, track_time) VALUES (?, ?, ?);", (message.id, aid, message.created_at))
async def on_command_error(self, ctx, error): if type(error) == discord.ext.commands.MissingPermissions: logging.warn( f'{ctx.author} denied permission for command {ctx.message.content}' ) await ctx.message.add_reaction(CONSTANTS.REACTION_DENY) embed = discord.Embed( title='{deny} Insufficient Permissions'.format( deny=CONSTANTS.REACTION_DENY), colour=discord.Colour(CONSTANTS.EMBED_COLOR_ERROR), description="You are not permitted to run the command ``{0}``". format(ctx.message.content)) embed.add_field(name="Reason:", value=str(error)) msg = await ctx.send(content='', embed=embed) await track(msg, ctx.author) else: embed = None if not ctx.command: logging.warn( f'Unknown command {ctx.message.content} by {ctx.author}') embed = self._construct_unknown_command_embed( str(error), ctx.message.content) else: logging.warn( f'Error running the command {ctx.command.name} Error: {type(error)} | {error}' ) embed = self._construct_error_embed(ctx.command.name, str(type(error)), str(error), ctx.message.content) await ctx.message.add_reaction(CONSTANTS.REACTION_ERROR) msg = await ctx.send(content='', embed=embed) await track(msg, ctx.author) if not ctx.command: return await msg.add_reaction(CONSTANTS.REACTION_EXPAND) with SQLCursor(self.db) as cur: bt_string = ''.join( traceback.format_exception(type(error), error, error.__traceback__)) print('{bname} encountered an error:\n{0}'.format( bt_string, bname=CONSTANTS.BOT_NAME)) cur.execute( 'INSERT INTO error_messages (message_id, channel_id, command_name, error_name, error_text, ' 'full_backtrace, full_command_string) VALUES (?,?,?,?,?,?,?);', (msg.id, msg.channel.id, ctx.command.name, str( type(error)), str(error), bt_string, ctx.message.content))
async def on_raw_reaction_remove(self, payload): if payload.user_id == self.bot.user.id: return if payload.emoji.name == CONSTANTS.REACTION_EXPAND: row = None with SQLCursor(self.db) as cur: cur.execute( 'SELECT command_name, error_name, error_text, full_command_string, full_backtrace FROM error_messages WHERE message_id=? AND channel_id=?;', (payload.message_id, payload.channel_id)) row = cur.fetchone() if not row: return to_edit = await self.bot.get_channel( payload.channel_id).get_message(payload.message_id) new_embed = self._construct_error_embed(row[0], row[1], row[2], row[3]) await to_edit.edit(content='{err} Command error {err}'.format( err=CONSTANTS.REACTION_ERROR), embed=new_embed)
async def query_positions(self): """Returns an array of positions and corresponding descriptions.""" values = [{} for _ in range(len(self.positions))] counter = 0 with SQLCursor(self.db) as cur: for pos in self.positions: cur.execute( 'SELECT position, description, officer FROM govt_info WHERE position=?', (pos, )) row = cur.fetchone() if row: values[counter] = { 'position': row[0] if len(row) >= 1 else 'NULL', 'description': row[1] if row[1] is not None else '', 'officer': row[2] if row[2] is not None else 'Vacant' } else: values[counter] = {} counter += 1 return values
async def description(self, ctx, pos='', desc=''): if ctx.message.author.top_role.name.lower() == 'officer': if pos.strip() != '': with SQLCursor(self.db) as cur: cur.execute( 'UPDATE govt_info SET description = ? WHERE position = ?;', (desc, pos)) if desc.strip() == '': await ctx.message.channel.send( 'Successfully cleared the description for position: **{}**' .format(pos)) else: await ctx.message.channel.send( 'Successfully set a description for position: **{}**\n\nThe description is as ' 'follows:\n```{}```'.format(pos, desc)) else: await ctx.message.channel.send( 'Invalid format, try: **eboard admin description <position> \"<desc>\"**' ) else: await ctx.message.channel.send( 'Hey! You do not have permission to do that.')