async def get_fighter_names(db_acc, channel): try: data = db_acc.execute( ''' SELECT name AS alias, name FROM fighter.fighter UNION ALL SELECT fa.alias, f.name FROM fighter.fighter_alias fa INNER JOIN fighter.fighter f ON f.id = fa.fighter_id''', {}) fighter_names = { data[i]["alias"]: data[i]["name"] for i in range(0, len(data)) } return fighter_names except dberr.Error as e: print(e) #TODO: add user name await channel.send(DB_ERROR_MSG.format("Unknown")) raise
async def is_registered(db_acc, discord_id, channel): try: return db_acc.execute( ''' SELECT COUNT(1) as registered FROM player WHERE discord_id = %(discord_id)s''', {"discord_id": discord_id})[0]["registered"] > 0 except dberr.Error as e: print(e) await channel.send(DB_ERROR_MSG.format(user.id)) raise
async def player_list(client, message, db_acc): channel = message.channel author = message.author rows = None try: rows = db_acc.execute( ''' SELECT discord_id, switch_tag, switch_code FROM player.player p INNER JOIN player.guild_member g ON p.discord_id = g.player_discord_id WHERE g.guild_id=%(guild_id)s''', {"guild_id": channel.guild.id}) except dberr.Error as e: print(e) await channel.send(DB_ERROR_MSG.format(author.mention)) raise names = '' tags = '' codes = '' for row in rows: # TODO: guild is optional? maybe in PMs? #names += '{:<20}{:<22}\n'.format(message.guild.get_member(int(row[0])).display_name[:20], row[2]) try: names += '{}\n'.format( message.guild.get_member(int(row["discord_id"])).display_name) #tags += '{}\n'.format(row[1]) codes += '{}\n'.format(row["switch_code"]) # Likely player no longer exists in server except Exception as e: print(e) continue embed = discord.Embed(color=embed_color) embed.set_author(name='Players in {}'.format(message.guild)) embed.set_thumbnail(url=channel.guild.icon_url) #embed.add_field(name='{:<45}{:<17}'.format('Name', 'Switch Code'), value='```{}```'.format(names), inline=True) embed.add_field(name='Name', value=names, inline=True) embed.add_field(name='Switch Code', value=codes, inline=True) await channel.send(embed=embed)
async def update(client, message, db_acc): channel = message.channel author = message.author # Tokenize input tokens = message.content.split(' ') if len(tokens) < 3: await channel.send('8!update usage: 8!update <tag|code> <value>') return update_stmt = "SET " val = None if (tokens[1].lower() == "tag"): update_stmt += "switch_tag = %(val)s" val = ' '.join(tokens[2:]) elif (tokens[1].lower() == "code"): if (len(tokens) > 3 or not tokens[2].lower().startswith('sw-')): await channel.send( 'Note: Switch code should look like SW-####-####-####') return val = tokens[2] update_stmt += "switch_code = %(val)s" else: await channel.send( 'Not sure what you\'re trying to do. Remember: 8!update usage: 8!update <tag|code> <value>' ) return try: db_acc.execute_update( ''' UPDATE player ''' + update_stmt + ''' WHERE discord_id = %(discord_id)s''', { "val": val, "discord_id": author.id }) except dberr.Error as e: print(e) await channel.send(DB_ERROR_MSG.format(author.mention)) raise await channel.send('Updated {}\'s profile.'.format(author.mention))
async def find_users_in_guild_by_switch_tag(db_acc, message, test_user_string, confidence_threshold): try: rows = db_acc.execute( ''' SELECT switch_tag, discord_id FROM player p INNER JOIN guild_member g ON p.discord_id = g.player_discord_id WHERE g.guild_id=%(guild_id)s''', {"guild_id": message.guild.id}) except dberr.Error as e: print(e) await message.channel.send(DB_ERROR_MSG.format(message.author.mention)) raise member_dict = {} for row in rows: member_dict[row["switch_tag"]] = row["discord_id"] confidence_list = process.extract(test_user_string, member_dict.keys(), scorer=fuzz.token_sort_ratio) return_list = [] found_exact = False for (tag, confidence) in confidence_list: if tag == test_user_string: found_exact = True return_list.append(member_dict[tag]) elif not found_exact and confidence > confidence_threshold: return_list.append(member_dict[tag]) return return_list
async def send_profile(channel, db_acc, user): params = {"discord_id": user.id} rows = None try: rows = db_acc.execute(''' SELECT switch_tag, switch_code FROM player.player p WHERE p.discord_id = %(discord_id)s''', params ) except dberr.Error as e: print(e) await channel.send(DB_ERROR_MSG.format(user.mention)) raise if rows is None or len(rows) == 0: await channel.send('{} hasn\'t registered yet. Tell them to get on it! (8!register)'.format(user.display_name)) return prof_rec = rows[0] tag = prof_rec["switch_tag"] code = prof_rec["switch_code"] rows = None # get list of fighters used try: rows = db_acc.execute(''' SELECT f.id, f.name, pf.is_main, pf.is_true_main, pf.is_pocket, pf.costume_number FROM fighter.fighter f INNER JOIN player.player_fighter pf ON pf.fighter_id = f.id WHERE pf.player_discord_id = %(discord_id)s ORDER BY CASE WHEN pf.is_true_main THEN 1 ELSE 0 END DESC, CASE WHEN pf.is_main THEN 1 ELSE 0 END DESC, CASE WHEN pf.is_pocket THEN 1 ELSE 0 END DESC, f.name''', { "discord_id": user.id } ) except dberr.Error as e: print(e) await channel.send(DB_ERROR_MSG.format(user.mention)) raise fighters = [ { "name": row["name"], "is_main": row["is_main"], "is_true_main": row["is_true_main"], "is_pocket": row["is_pocket"], "costume_number": row["costume_number"] } for row in rows ] embed = discord.Embed(color=embed_color) embed.set_author(name = user.display_name, icon_url=user.avatar_url) embed.add_field(name='Switch Tag', value=tag, inline=True) embed.add_field(name='Switch Code', value=code, inline=True) # If any fighters were found if(len(rows) > 0): try: #embed.add_field(name='Fighters', value=' ', inline=False) amalgam_url = create_stitched_image(fighters) embed.set_image(url=amalgam_url) embed.set_footer(text='Green "M" means "main"; Red "P" means "pocket"') # If creating the image fails, still post the profile just without the image except Exception as e: print(e) await channel.send(embed=embed)
async def who_plays(client, message, db_acc): channel = message.channel author = message.author tokens = message.content.split(' ') if len(tokens) < 2: await channel.send('8!whoplays usage: 8!whoplays <character>') return # Assume everything after is the fighter name test_fighter_string = ' '.join(tokens[1:]) fighter_name, confidence = await find_fighter(db_acc, channel, test_fighter_string) # Might want to fine tune this later, but 80 seems good if (confidence < 80): await channel.send( 'I\'m really not sure who {} is. Remember: 8!whoplays usage: 8!whoplays <character>' .format(test_fighter_string)) return try: rows = db_acc.execute( ''' SELECT pf.player_discord_id as discord_id FROM player_fighter pf INNER JOIN fighter f ON f.id = pf.fighter_id INNER JOIN guild_member gm ON gm.player_discord_id = pf.player_discord_id WHERE f.name=%(fighter_name)s AND gm.guild_id = %(guild_id)s''', { "fighter_name": fighter_name, "guild_id": channel.guild.id }) # msg = 'The following users play {}:\n\n'.format(fighter_name) msg = '' # Gross but cool list generators to concatenate user names users = [ message.guild.get_member(int(row["discord_id"])) for row in rows ] msg += ', '.join([user.display_name for user in users]) except dberr.Error as e: print(e) await channel.send(DB_ERROR_MSG.format(author.mention)) raise embed = discord.Embed(color=embed_color, description="No one." if msg == '' else msg) # Regex to remove ALL special characters from fighter name, then create url # Example: Pokemon Trainer becomes Pokmon Trainer due to special e embed.set_author(name="{} Players".format(fighter_name), icon_url=fighter_icon_url(fighter_name)) #embed.add_field(name='', value=tag, inline=True) await channel.send(embed=embed)
async def register(client, message, db_acc): channel = message.channel author = message.author record = None # Verify user hasn't registered for this server try: record = db_acc.execute( ''' SELECT COUNT(1) AS registered FROM guild_member WHERE player_discord_id = %(discord_id)s AND guild_id = %(guild_id)s''', { "discord_id": author.id, "guild_id": channel.guild.id })[0] except dberr.Error as e: print(e) await channel.send(DB_ERROR_MSG.format(author.mention)) raise if (record["registered"] > 0): await channel.send( '{}, you\'re already registered in this channel, silly!'.format( author.mention)) return # See if user has been registered at all is_reg = await is_registered(db_acc, author.id, channel) # Tokenize input tokens = message.content.split(' ') # First time registration, wrong number of arguments if (not is_reg and len(tokens) != 3): await channel.send( '8!register usage: 8!register switch_tag switch_code') return # First time registration, wrong switch code format #TODO: use regex to enforce more rigid structure elif (not is_reg and not tokens[2].lower().startswith('sw-')): await channel.send( 'Note: Switch code should look like SW-####-####-####') return # First time registration, correct input elif (not is_reg): tag = tokens[1] code = tokens[2].upper() await channel.send('Registering {} as {} with Switch code {}. Is this good? (Y/N)' \ .format(author.mention, tag, code)) def check(m): return m.author == author and m.channel == channel try: msg = await client.wait_for('message', check=check, timeout=15) if(msg.content.lower() != 'y' and msg.content.lower() != 'yes' \ and msg.content.lower() != '8!y' and msg.content.lower() != '8!yes'): await channel.send('Not registering {}.'.format(author.mention) ) return try: db_acc.execute_update( ''' INSERT INTO player (discord_id, switch_tag, switch_code) VALUES (%(discord_id)s, %(tag)s, %(code)s)''', { "discord_id": author.id, "tag": tag, "code": code }) except dberr.Error as e: print(e) await channel.send(DB_ERROR_MSG.format(author.mention)) raise await channel.send( 'Registered {.author.mention} in the player database!'.format( msg)) if not isinstance(channel, discord.DMChannel): await channel.send( 'Try DMing me to set up the rest of your profile!') except asyncio.TimeoutError: await channel.send( 'Time ran out to confirm. Try again, {}.'.format( author.mention)) return # Already registered or just registered, add them to this channel try: db_acc.execute_update( ''' INSERT INTO guild_member (player_discord_id, guild_id) VALUES (%(discord_id)s, %(guild_id)s)''', { "discord_id": author.id, "guild_id": channel.guild.id }) except dberr.Error as e: print(e) await channel.send(DB_ERROR_MSG.format(author.mention)) raise await channel.send( 'Registered {.author.mention} in this server!'.format(message))
async def i_pocket(client, message, db_acc): channel = message.channel author = message.author tokens = message.content.split(' ') if len(tokens) < 2: await channel.send( '8!ipocket usage: 8!ipocket [add|remove] <character>') return remove_fighter = False # Figure out where the fighter name starts # to determine between 8!ipocket pit and 8!ipocket remove/add pit fighter_name_start_idx = 1 if (tokens[1].lower() == "add"): fighter_name_start_idx = 2 elif (tokens[1].lower() == "remove"): fighter_name_start_idx = 2 remove_fighter = True if not remove_fighter: # First add character, if necessary await i_play(client, message, db_acc, False) # Assume everything after is the fighter name test_fighter_string = ' '.join(tokens[fighter_name_start_idx:]) fighter_name, confidence = await find_fighter(db_acc, channel, test_fighter_string) # Might want to fine tune this later, but 80 seems good if (confidence < 80): await channel.send( 'I\'m really not sure who {} is. Remember: 8!ipocket usage: 8!ipocket [add/remove] <character>' .format(test_fighter_string)) return if (not await is_registered(db_acc, author.id, channel)): await channel.send('Please register with 8!register first!') return # Adding or removing that you pocket this character else: try: db_acc.execute_update( ''' UPDATE player_fighter SET is_main = IF(%(set_pocket)s = 1, 0, is_main), is_pocket = %(set_pocket)s, is_true_main = IF(%(set_pocket)s = 1, 0, is_true_main) WHERE player_discord_id = %(discord_id)s AND fighter_id = (SELECT id FROM fighter WHERE name=%(name)s)''', { "discord_id": author.id, "name": fighter_name, "set_pocket": 0 if remove_fighter else 1 }) except dberr.Error as e: print(e) await channel.send(DB_ERROR_MSG.format(author.mention)) raise if remove_fighter: await channel.send('{0} no longer pockets {1}. If you want ' \ 'to remove this character entirely, use 8!iplay remove {1}'.format(author.mention, fighter_name)) else: await channel.send('I see, so {} pockets {}. {}'.format( author.mention, fighter_name, random_snarky_comment()))
async def i_play(client, message, db_acc, send_message=True): channel = message.channel author = message.author tokens = message.content.split(' ') if len(tokens) < 2: if send_message: await channel.send( '8!iplay usage: 8!iplay [add|remove] <character>') return remove_fighter = False # Figure out where the fighter name starts # to determine between 8!iplay pit and 8!iplay remove/add pit fighter_name_start_idx = 1 if (tokens[1].lower() == "add"): fighter_name_start_idx = 2 elif (tokens[1].lower() == "remove"): fighter_name_start_idx = 2 remove_fighter = True # Assume everything after is the fighter name test_fighter_string = ' '.join(tokens[fighter_name_start_idx:]) fighter_name, confidence = await find_fighter(db_acc, channel, test_fighter_string) # Might want to fine tune this later, but 80 seems good if (confidence < 80): if send_message: await channel.send('I\'m really not sure who {} is. Remember: 8!iplay usage:' \ ' Check 8!help for command usage.'.format(test_fighter_string)) return if (not await is_registered(db_acc, author.id, channel)): if send_message: await channel.send('Please register with 8!register first!') return # Removing that you play this character if (remove_fighter): try: db_acc.execute_update( ''' DELETE FROM player_fighter WHERE player_discord_id = %(discord_id)s AND fighter_id = (SELECT id FROM fighter WHERE name=%(name)s)''', { "discord_id": author.id, "name": fighter_name }) except dberr.Error as e: print(e) if send_message: await channel.send(DB_ERROR_MSG.format(author.mention)) raise if send_message: await channel.send('{} does not play {}, okay.'.format( author.mention, fighter_name)) # Adding that you play this character else: try: db_acc.execute_update( ''' INSERT INTO player_fighter (player_discord_id, fighter_id, is_main, is_true_main) SELECT %(discord_id)s, id as fighter_id, 0, 0 FROM fighter WHERE name=%(name)s''', { "discord_id": author.id, "name": fighter_name }) except dberr.DuplicateKeyError as e: if send_message: await channel.send('I already know you play {}, {}!'.format( fighter_name, author.mention)) return except dberr.Error as e: print(e) if send_message: await channel.send(DB_ERROR_MSG.format(author.mention)) raise if send_message: await channel.send('Okay, noted that {} plays {}. {}'.format( author.mention, fighter_name, random_snarky_comment()))
async def who_plays(client, message, db_acc): channel = message.channel author = message.author tokens = message.content.split(' ') if len(tokens) < 2: await channel.send('8!whoplays usage: 8!whoplays <character>') return # Assume everything after is the fighter name test_fighter_string = ' '.join(tokens[1:]) fighter_name, confidence = await find_fighter(db_acc, channel, test_fighter_string) # Might want to fine tune this later, but 80 seems good if (confidence < 80): await channel.send( 'I\'m really not sure who {} is. Remember: 8!whoplays usage: 8!whoplays <character>' .format(test_fighter_string)) return try: rows = db_acc.execute( ''' SELECT pf.player_discord_id as discord_id FROM player.player_fighter pf INNER JOIN fighter.fighter f ON f.id = pf.fighter_id INNER JOIN player.guild_member gm ON gm.player_discord_id = pf.player_discord_id WHERE f.name=%(fighter_name)s AND gm.guild_id = %(guild_id)s''', { "fighter_name": fighter_name, "guild_id": channel.guild.id }) msg = '' users = [ message.guild.get_member(int(row["discord_id"])) for row in rows ] msg += ', '.join([user.display_name for user in users]) except dberr.Error as e: print(e) await channel.send(DB_ERROR_MSG.format(author.mention)) raise embed = discord.Embed(color=embed_color, description="No one." if msg == '' else msg) embed.set_author(name="{} Players".format(fighter_name), icon_url=fighter_icon_url(fighter_name)) await channel.send(embed=embed)