async def start_challonge(command, msg, channel, guild): # Base url to access Challonge's API try: tour_url = get_chal_tour_id(read_db('channel', 'bracket', channel.id)) # Grab tour_url from bracket command except: raise Exception(bold("Challonge") + ": Bracket link is missing. Try setting the bracket command") subdomain = read_db('guild', 'challonge', guild) # Server's subdomain with Challonge # Properly add the subdomain to the bracket url if subdomain: tour_url = subdomain + '-' + tour_url # Get the participants for the tournament parts_get = requests_get(base_url + tour_url + "/participants.json", headers={"User-Agent":"Lizard-BOT"}, auth=(chal_user, api_key)) # Check the status codes # Anything but a 200 is bad if '200' in str(parts_get.status_code): return parts_get.json(), tour_url # 404 usually means a bad bracket link elif '404' in str(parts_get.status_code): raise Exception(bold("Challonge") + ": Lizard-BOT can not find tournament: " + tour_url) # Challonge error # Usually a 5xx error else: print(parts_get.text) # Print raw text to console raise Exception(bold("Challonge") + ": Unknown Challonge error for <" + tour_url + "> initializing connection to Challonge")
async def help_lizard(command, msg, user, channel, *args, **kwargs): # Message should only have two args at most if len(msg.split(' ')) > 2: raise Exception( bold("Help_Lizard") + ": Too many arguments. " + await help_lizard('', '', '', '')) help_commands = kwargs.get( 'help', False) # Get all the commands for the help message split = msg.lower().split(' ') cmd = ' '.join(split[0:2]) if len(split) > 1 else split[0] # Probably internal query from another command if not help_commands: return "For more information about the bot and its commands: <https://github.com/lizardman301/Lizard-bot-rsf>" # No command specified elif not split[0]: return ('Allows you to get help on a command. ' '\nThe available commands are ```%s```' % ', '.join(list(help_commands.keys()))) # Return the help message elif cmd in help_commands.keys(): return help_commands[cmd] # Invalid argument else: raise Exception( bold("Help_Lizard") + ": Invalid command: " + bold(cmd) + ". Ensure you are using the full command name." '\nThe available commands are ```%s```' % ', '.join(list(help_commands.keys())))
async def stats(command, msg, user, channel, *args, **kwargs): cmd = msg.split(' ')[0].lower() if msg.split(' ')[0] else '' func_map = kwargs['func_map'] if cmd else [] if len(msg.split(' ')) > 1: raise Exception( bold("Stats") + ": Too many arguments. " + await help_lizard('', '', '', '')) elif cmd and cmd not in ['challonge', 'edit'] and cmd not in func_map: raise Exception( bold("Stats") + ": Invalid Subcommand. " + await help_lizard('', '', '', '')) stats = read_stat(cmd, func_map) embed = Embed(title="Stats!", colour=Colour(0x0fa1dc)) embed.set_author( name="Lizard-BOT", url="https://github.com/lizardman301/Lizard-bot-rsf", icon_url= "https://raw.githubusercontent.com/lizardman301/Lizard-bot-rsf/master/doc/assets/images/cmface.png" ) embed.set_footer(text="People use this bot? Wild.") for stat in stats: embed.add_field(name=stat, value=stats[stat]) try: await channel.send(embed=embed) except: raise Exception( bold("Stats") + ": Error sending embed to chat. Give Lizard-BOT the permission: " + bold("Embed Links")) return ''
async def challonge_seeding(command, msg, user, channel, *args, **kwargs): if len(msg.split(' ')) > 1: raise Exception(bold("Challonge_Seeding") + ": Too many arguments. " + await help_lizard('','','','')) async with channel.typing(): parts, tour_url = await start_challonge(command, msg, channel, kwargs['guild']) # If there is no message, seed whole bracket msg # Else, grab the first param try: if not msg: seed_num = 0 # Error on negative number elif int(msg.split(' ')[-1]) <= 0: raise else: seed_num = int(msg.split(' ')[-1]) except: raise Exception(bold("Challonge_Seeding") + ": Seeding number must be a positive integer or 0 for everybody") # Get Google Sheets ID sheet_id = read_db('channel', 'seeding', channel.id) # If seeding hasn't been set, inform user if not sheet_id: raise Exception(bold("Challonge_Seeding") + ": There is no seeding sheet for this channel. Please view <https://github.com/lizardman301/Lizard-bot-rsf/blob/master/doc/seeding_with_sheets.md> for a walkthrough") # Grab what the seeds were seeds = seeding(sheet_id, parts, base_url + tour_url, seed_num) # Seeding takes place in different method await channel.send("**SEEDING:**\n {0}".format(',\n'.join(escape_markdown(pformat(seeds))[1:-1].split(', ')))) # Final message that seeding is complete return bold("SEEDING IS NOW COMPLETE!\nPLEASE REFRESH YOUR BRACKETS\nWAIT FOR THE ROUND 1 ANNOUNCEMENT TO START PLAYING")
async def edit_tos(command, msg, user, channel, *args, **kwargs): editable_command = command.split(' ')[1] params = msg.split(' ') mentions = kwargs['mentions'] channel_mentions = kwargs['channel_mentions'] params, command_channels = channel_processing(params, channel_mentions) if (not mentions and params[0]): raise Exception( bold("Edit") + ": Invalid user mention. Try @'ing somebody") # Remove the bot pinging TOs on the confirmation message mentions_pingless = pings_b_gone(mentions) db_message = ' '.join( mentions_pingless.values()) # Put mention values into the database channel_message = ' '.join( mentions_pingless.keys()) # Send usernames back to the channel if command_channels: # For each channel, save the setting for chnl in command_channels: # We have to double check that the channel is in the DB if settings_exist(kwargs['guild'], chnl): save_db( 'channel', editable_command, db_message, chnl ) # Save the new message to the proper setting in a given channel return "All listed channels had the {0} updated to {1}".format( bold(editable_command), bold(channel_message)) else: save_db( 'channel', editable_command, db_message, channel.id ) # Save the new message to the proper setting in a given channel return "The new {0} is: {1}".format( bold(editable_command), bold(channel_message)) # Print the new message for a given setting
async def edit_botrole(command, msg, user, channel, *args, **kwargs): editable_command = 'botrole' role_mentions = kwargs['role_mentions'] default_role = kwargs['guild_default_role'] # Rejoin the rest of the parameters with spaces db_message = msg # The message we send to the Database channel_message = msg # The message that gets sent if not role_mentions or len(role_mentions) > 1: # Allow @everyone to be a botrole if not msg: db_message = str(default_role.id) channel_message = default_role.name else: raise Exception( bold("Edit") + " : Too few/many role mentions for botrole. Try again with only one role mentioned" ) elif role_mentions: db_message = str(role_mentions[0].id) channel_message = role_mentions[0].name save_db('guild', editable_command, db_message, kwargs['guild']) return "The new {0} is: {1}".format( bold(editable_command), bold(channel_message)) # Print the new message for a given setting
async def edit_prefix(command, msg, user, channel, *args, **kwargs): editable_command = command.split(' ')[1] # Check if prefix is a singular character if not len(msg) == 1: raise Exception( bold("Edit") + ": Lizard-BOT prefix must be a singular character.") save_db('guild', editable_command, msg, kwargs['guild']) return "The new {0} is: {1}".format( bold(editable_command), bold(msg)) # Print the new message for a given setting
async def edit_challonge(command, msg, user, channel, *args, **kwargs): editable_command = command.split(' ')[1] # Check if prefix is a singular character if len(msg) > 60: raise Exception( bold("Edit") + ": Challonge Subdomain is too long. Are you sure that is a challonge subdomain?" ) save_db('guild', editable_command, msg, kwargs['guild']) return "The new {0} is: {1}".format( bold(editable_command), bold(msg)) # Print the new message for a given setting
async def round_lizard(command, msg, user, channel, *args, **kwargs): # Message must be less than 50 characters if len(msg) > 50: raise Exception( bold("Round_Lizard") + ": Custom round number must be less then 50 characters") save_db('channel', 'round', msg, channel.id) try: return await status('status', msg, user, channel) except: raise Exception( bold("Round_Lizard") + ": Round message includes invalid {}. Please correct the status message to include only {0}" )
async def status(command, msg, user, channel, *args, **kwargs): currentRound = read_db('channel', 'round', channel.id) if currentRound: # Read the status message for a channel and make it bold # Currently the message must have {0} so it can fill in the current round try: message = read_db('channel', 'status', channel.id) return bold(message.format(currentRound)) except: raise Exception( bold("Status") + ": Round message includes invalid {}. Please correct the status message to include only {0}" ) return bold( "Tournament has not begun. Please wait for the TOs to start Round 1!")
async def remind(command, msg, user, channel, *args, **kwargs): params = msg.split(' ') try: time = int(params[0]) # time is in minutes # Time must be positive if time < 1: raise except: raise Exception( bold("Remind") + ": Invalid time. Please try again with a positive whole value for minutes" ) reason = "" #specific reason if provided if len(params) > 1: reason = " ".join(params[1:]) if len(reason) > 1900: raise Exception( bold("Remind") + ": Message is too long to be sent back through Discord. Shorten your message to 1900 characters or less" ) if reason: formatted_msg = "OK! I will ping you in {0} minutes to remind you about \"{1}\"".format( time, reason) else: formatted_msg = "OK! I will ping you in {0} minutes to remind you about something.".format( time) # sends message back to confirm reminder await channel.send(formatted_msg) # wait message time await asyncio_sleep(60 * time) if reason: formatted_msg = bold( "{0}: It has been {1} minutes, don't forget \"{2}\"!").format( user.mention, time, reason) else: formatted_msg = bold( "{0}: It has been {1} minutes, you have been reminded!".format( user.mention, time)) await channel.send(formatted_msg)
async def botrole(command, msg, user, channel, *args, **kwargs): botrole = read_db('guild', 'botrole', kwargs['guild']) try: botrole_name = channel.guild.get_role(botrole).name except: botrole_name = 'everyone' # Pull the role name from the guild's roles return "The bot role is {0}".format(bold(botrole_name))
async def disable(command, msg, user, channel, *args, **kwargs): params = msg.lower().split(' ') if len(msg.split(' ')) > 2: raise Exception( bold("Disable") + ": Too many arguments. " + await help_lizard('', '', '', '')) to_disable = ' '.join(params[0:2]) # could be expanded to do more if not to_disable: # No command provided raise Exception(bold("Disable") + ": No command provided") elif to_disable == "list": # Optional arg to list disabled commands current_list = read_disable(kwargs['guild']) return "Current disabled commands are: **{0}**".format( ", ".join(current_list)) try: # get the actual function name function_name = kwargs['func_map'][to_disable].__name__ except: # Not a valid command in the first place, don't disable raise Exception( bold("Disable") + ": That is not a command in Lizard-BOT and cannot be disabled") try: # Disable function name current_list = set_disable(kwargs['guild'], function_name) except Exception as e: if str(e) == "Command already disabled.": raise Exception( bold("Disable") + ": Cannot disable an already disabled command") elif str(e) == "Cannot disable important command.": raise Exception( bold("Disable") + ": Cannot disable an essential command") return "{0} has been disabled. Current disabled commands are: **{1}**".format( to_disable, ", ".join(current_list))
async def challonge_checkin(command, msg, user, channel, *args, **kwargs): # checkin takes no arguments if msg: raise Exception(bold("Challonge_Checkin") + ": Too many arguments. " + await help_lizard('','','','')) # Do a fancy "Lizard-BOT is typing..." message as we query Challonge async with channel.typing(): # Grab the participants and tournament url parts, tour_url = await start_challonge(command, msg, channel, kwargs['guild']) # Get the users that aren't checked in or in Discord not_checked_in_parts, not_discord_parts = checkin(parts, get_users(kwargs['guild_members'])) # Message showing who is not checked in and who is not in the Discord return"**NOT CHECKED IN:** {0}\n**NOT IN DISCORD:** {1}\n".format(', '.join(not_checked_in_parts), ', '.join(not_discord_parts)) + await not_in_discord(0,0,0,0)
async def edit_seeding(command, msg, user, channel, *args, **kwargs): editable_command = command.split(' ')[1] params = msg.split(' ') channel_mentions = kwargs['channel_mentions'] params, command_channels = channel_processing(params, channel_mentions) # Rejoin the rest of the parameters with spaces message = ' '.join(params) # The message we send to the Database # Check if the Sheets ID matches what Google specified reg = re_compile('[a-zA-Z0-9-_]+') if not message: message = '' elif not reg.fullmatch(params[0]) or len(params[0]) > 80: raise Exception( bold("Edit") + ": Invalid Sheets spreadsheet ID. Please view <https://github.com/lizardman301/Lizard-bot-rsf/blob/master/doc/seeding_with_sheets.md> for a walkthrough" ) if command_channels: # For each channel, save the setting for chnl in command_channels: # We have to double check that the channel is in the DB if settings_exist(kwargs['guild'], chnl): save_db( 'channel', editable_command, message, chnl ) # Save the new message to the proper setting in a given channel return "All listed channels had the {0} updated to {1}".format( bold(editable_command), bold(message)) else: save_db( 'channel', editable_command, message, channel.id ) # Save the new message to the proper setting in a given channel return "The new {0} is: {1}".format( bold(editable_command), bold(message)) # Print the new message for a given setting
async def randomselect(command, msg, user, channel, *args, **kwargs): if len(msg.split(' ')) > 2: raise Exception( bold("RandomSelect") + ": Too many arguments. " + await help_lizard('', '', '', '')) # Start with randomselect basis to get characters random_type = '' game = msg.split(' ')[-1].lower() if msg.split(' ')[0].lower() != '': random_type = msg.split(' ')[0].lower() if random_type == "char" or (random_type == game and random_type != 'stage'): random_type = "character" if random_type == "character": if game in ["character", "char"]: # No game to be found so default to sfv game = 'sfv' elif msg.split(' ')[-1].lower() != '': game = msg.split(' ')[-1].lower() elif msg.split(' ')[-1].lower() == '': # No game to be found so default to sfv game = 'sfv' try: data, games = get_randomselect_data(game, random_type=random_type) except: raise Exception( bold("RandomSelect") + ": Invalid parameters. " + await help_lizard('', '', '', '')) if not data: raise Exception( bold("RandomSelect") + ": Invalid game: {0}. Valid games are: {1}".format( bold(game), bold(', '.join(games)))) if random_type == "stage": return "{0} Your randomly selected stage is: {1}".format( user.mention, bold(random_choice(data))) return "{0} Your randomly selected character is: {1}".format( user.mention, bold(random_choice(data)))
async def challonge_here(command, msg, user, channel, *args, **kwargs): here_parts = {} # Stores active participants # if not enough arguments, we end early if not msg: raise Exception(bold("Challonge_Here") + ": Not enough arguments. Please provide a user to checkin.") async with channel.typing(): parts, tour_url = await start_challonge(command, msg, channel, kwargs['guild']) # Get all the participants and the tournament URL for part in parts: # Grab every participant and get the useful information (display name and id number) here_parts.update({part['participant']['display_name'].lower():part['participant']['id']}) # Check to make sure that participant exists in tourney try: checkin_id = str(here_parts[msg.lower()]) except KeyError: # Tell the messenger that the user is not in the tournament raise Exception(bold("Challonge_Here") + ": Lizard-BOT cannot find {0} in the tournament.".format(bold(msg))) # Send the check in request to Challonge checkin_post = requests_post(base_url + tour_url + "/participants/" + checkin_id +"/check_in.json", headers={"User-Agent":"Lizard-BOT"}, auth=(chal_user, api_key)) # Check to make sure we get a good response if '200' in str(checkin_post.status_code): # Good response. Return that the score was updated return "Checked in: {0}".format(bold(msg)) elif '401' in str(checkin_post.status_code): # Permission error raise Exception(bold("Challonge_Here") + ": Lizard-BOT does not have access to the tournament") elif '422' in str(checkin_post.status_code): # Checkin period not running raise Exception(bold("Challonge_Here") + ": The check-in window hasn't started or is over for the tournament") else: # Some other challonge error. Print it to console and error with appropriate message print(checkin_post.text) raise Exception(bold("Challonge_Here") + ": Unknown Challonge error for <" + tour_url + "> while checking in: " + msg) # Message showing who is not checked in and who is not in the Discord return
async def enable(command, msg, user, channel, *args, **kwargs): params = msg.lower().split(' ') if len(msg.split(' ')) > 2: raise Exception( bold("Enable") + ": Too many arguments. " + await help_lizard('', '', '', '')) to_enable = ' '.join(params[0:2]) # could be expanded to do more if not to_enable: # No command provided raise Exception(bold("Enable") + ": No command provided") try: function_name = kwargs['func_map'][to_enable].__name__ except: # Check if command is in the disable list, if so return that name # Used for commands that were disabled but changed in an update disable_list = read_disable(kwargs['guild']) if to_enable in disable_list: function_name = to_enable else: raise Exception( bold("Enable") + ": " + bold(to_enable) + " is not a command in Lizard-BOT and cannot be enabled") try: return "{0} has been enabled. Current disabled commands are: **{1}**".format( to_enable, ', '.join(set_enable(kwargs['guild'], function_name))) except Exception as e: if str(e) == "Command is not disabled.": raise Exception( bold("Enable") + ": Cannot enable a command that is not disabled.") elif str(e) == "There is nothing disabled.": raise Exception( bold("Enable") + ": There is currently nothing disabled.")
async def edit_channel_strings(command, msg, user, channel, *args, **kwargs): editable_command = command.split(' ')[1] params = msg.split(' ') channel_mentions = kwargs['channel_mentions'] params, command_channels = channel_processing(params, channel_mentions) # Rejoin the rest of the parameters with spaces message = ' '.join(params) # The message we send to the Database # Check if the status message contains {0} if editable_command in ['status'] and not message.count('{0}') > 0: raise Exception( bold("Edit") + ": Status message must include {0} to substitute the round number") elif len(message) > 1945: raise Exception( bold("Edit") + ": Message is too long to be stored. Shorten your message to 1945 characters or less" ) if command_channels: # For each channel, save the setting for chnl in command_channels: # We have to double check that the channel is in the DB if settings_exist(kwargs['guild'], chnl): save_db( 'channel', editable_command, message, chnl ) # Save the new message to the proper setting in a given channel return "All listed channels had the {0} updated to {1}".format( bold(editable_command), bold(message)) else: save_db( 'channel', editable_command, message, channel.id ) # Save the new message to the proper setting in a given channel return "The new {0} is: {1}".format( bold(editable_command), bold(message)) # Print the new message for a given setting
async def not_in_discord(command, msg, user, channel, *args, **kwargs): # Static message for why a user would be reported as not in Discord for a Challonge tournament return bold( "Your Discord nickname must match your challonge. If it does *NOT*, you will show as *NOT IN DISCORD*" )
async def coin_flip(command, msg, user, channel, *args, **kwargs): # Randomize the list for coin flip return "The coin landed on: {0}".format( bold(random_choice(["Heads", "Tails"])))
async def draw(command, msg, user, channel, *args, **kwargs): full_msg = kwargs['full_msg'] char_num = 7 client = kwargs['client'] unicode_reactions = ["1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣"] player1 = user if len(msg.split(' ')) > 2: raise Exception( bold("Draw") + ": Too many arguments. " + await help_lizard('', '', '', '')) # No mention or too many, Raise exception elif not full_msg.mentions or len(full_msg.mentions) > 1: raise Exception( bold("Draw") + ": You must mention exactly one user to draw against.") player2 = full_msg.mentions[0] if player1 == player2: raise Exception( bold("Draw") + ": You are not allowed to draw against yourself.") # Start with randomselect basis to get characters try: game = msg.split(' ')[1].lower() except: # No game to be found so default to sfv game = 'sfv' chars, games = get_randomselect_data(game) if not chars: raise Exception( bold("Draw") + ": Invalid game: {0}. Valid games are: {1}".format( bold(game), bold(', '.join(games)))) if len(chars) < char_num: # If we have a game with an amount of characters less than the number of cards drawn, it will never create a list raise Exception( bold("Draw") + ": Invalid game: {0}. The game selected has too few characters to function with this command." .format(bold(game))) # Initial accept embed accept_embed = Embed(title="Card Draw", colour=Colour(0x0fa1dc)) accept_embed.set_footer( text="Do you agree to a draw, {0}?".format(player2.display_name)) try: accept_msg = await channel.send(embed=accept_embed) except: raise Exception( bold("Draw") + ": Error sending embed to chat. Give Lizard-BOT the permission: " + bold("Embed Links")) await accept_msg.add_reaction('❌') await accept_msg.add_reaction('✅') try: # Wait for the reaction from the correct user # lambda function check for the correct reaction and the correct user reaction, user = await client.wait_for( 'reaction_add', timeout=60.0, check=lambda reaction, user: user == player2 and (str(reaction.emoji) == '✅' or str(reaction.emoji) == '❌' ) and reaction.message == accept_msg) if str(reaction.emoji) == '❌': raise Exception() except: await accept_msg.delete() raise Exception(bold("Draw") + ": The draw was not accepted.") # if we got here, draw was accepted # randomly choose player order order = random_choice( [[player1, player2, player1, player2, player2, player1], [player2, player1, player2, player1, player1, player2]]) # declare an Array of 0s to mark all cards as not picked # -1 means a card ban, 1 means a card draw picks = [0] * char_num #create new embed card_embed = Embed(title="Card Draw", colour=Colour(0x0fa1dc)) # Declare list and fill with the amount of random characters # Make it so that it has to be all different characters characters_list = [] while len(characters_list) < char_num: new_char = random_choice(chars) # Only add to the list if it is a new character if not new_char in characters_list: characters_list.append(new_char) # Add characters to ban for i, c in enumerate(characters_list): card_embed.add_field(name="Char {0}".format(i + 1), value=c, inline=True) await accept_msg.delete() try: game_msg = await channel.send(embed=card_embed) except: raise Exception( bold("Draw") + ": Error sending embed to chat. Give Lizard-BOT the permission: " + bold("Embed Links")) # Add reactions for pick/ban purposes for reaction in unicode_reactions: await game_msg.add_reaction(reaction) # Create lists for the picked characters p1_chars = [] p2_chars = [] for it, player in enumerate(order): user_to_check = None msg_to_check = None reaction_read = None reaction_read_emoji = None number = None # first two are bans if it < 2: card_embed.set_footer(text="{0}, select a character to ban.". format(player.display_name)) await game_msg.edit(embed=card_embed) while not (user_to_check == player) or not ( msg_to_check == game_msg ) or reaction_read_emoji not in unicode_reactions: try: reaction_read, user_to_check = await client.wait_for( 'reaction_add', timeout=60.0) msg_to_check = reaction_read.message if not (msg_to_check == game_msg and user_to_check == player): continue reaction_read_emoji = reaction_read.emoji number = unicode_reactions.index(reaction_read_emoji) if picks[number] != 0: # already banned, set as None to make it fail reaction_read_emoji = None card_embed.set_footer( text= "{0}, that character is already banned, please choose another." .format(player.display_name)) await game_msg.edit(embed=card_embed) except Exception as ex: if type(ex).__name__ == "TimeoutError": await game_msg.delete() raise Exception( bold("Draw") + ": {0} failed to ban a character.".format( player.display_name)) else: # As of right now, if something else goes wrong its because a reaction its not expecting was sent, go to the next loop continue # mark character as banned picks[number] = -1 # Strikethrough char on embed card_embed.set_field_at(number, name="Char {0}".format(number + 1), value="~~{0}~~".format( characters_list[number])) else: card_embed.set_footer(text="{0}, select a character to pick.". format(player.display_name)) if it == 4: # Remind them gently they get to pick another character in a row if they are the 2nd player card_embed.set_footer( text="{0}, select another character to pick.".format( player.display_name)) await game_msg.edit(embed=card_embed) while not (user_to_check == player) or not ( msg_to_check == game_msg ) or reaction_read_emoji not in unicode_reactions: try: reaction_read, user_to_check = await client.wait_for( 'reaction_add', timeout=60.0) msg_to_check = reaction_read.message if not (msg_to_check == game_msg and user_to_check == player): continue reaction_read_emoji = reaction_read.emoji number = unicode_reactions.index(reaction_read_emoji) if picks[number] == -1: # already banned, set as None to make it fail reaction_read_emoji = None card_embed.set_footer( text= "{0}, that character is already banned, please choose another." .format(player.display_name)) await game_msg.edit(embed=card_embed) elif picks[number] == 1: # already banned, set as None to make it fail reaction_read_emoji = None card_embed.set_footer( text= "{0}, that character is already chosen, please choose another." .format(player.display_name)) await game_msg.edit(embed=card_embed) except Exception as ex: if type(ex).__name__ == "TimeoutError": await game_msg.delete() raise Exception( bold("Draw") + ": {0} failed to choose a character.".format( player.display_name)) else: # As of right now, if something else goes wrong its because a reaction its not expecting was sent, go to the next loop continue # mark character as picked picks[number] = 1 # edit embed to bold character card_embed.set_field_at(number, name="Char {0}".format(number + 1), value="__" + bold(characters_list[number]) + "__") # assign character chosen to if player == player1: p1_chars.append(characters_list[number]) else: p2_chars.append(characters_list[number]) # create new embed chosen_embed = Embed(title="Final Picks", colour=Colour(0x0fa1dc)) chosen_embed.add_field(name=player1.display_name, value=", ".join(p1_chars)) chosen_embed.add_field(name=player2.display_name, value=", ".join(p2_chars)) await game_msg.delete() await channel.send(embed=chosen_embed) return "Card draw finished"
async def challonge_report(command, msg, user, channel, *args, **kwargs): match_parts = {} # Stores active participants matches = [] # Stores all the match elements at their root [match_obj, etc] instead of {'match': match_obj, etc} params = msg.split(' ') # grab the info from the user winner_name = ' '.join(params[1:]) # First parameter should be the score. Everything else is the match winner's name # if not enough arguments, we end early if len(params) < 2: raise Exception(bold("Challonge_Report") + ": Not enough arguments. Please provide a score and a winner.") async with channel.typing(): parts, tour_url = await start_challonge(command, msg, channel, kwargs['guild']) # Get all the participants and the tournament URL match_get = requests_get(base_url + tour_url + "/matches.json", headers={"User-Agent":"Lizard-BOT"}, auth=(chal_user, api_key), params={'state':'open'}) # Grab all the active matches for the tournament # If we get a good response and there are matches (aka the tournament has been started) if '200' in str(match_get.status_code) and match_get.json(): # Grab every participant and get the useful information (display name and id number) # Originally grabbed every checked in participant but this caused issues with tournies who had no check in for part in parts: match_parts.update({part['participant']['display_name'].lower():part['participant']['id']}) # Adjust the root of the match information and put it in an array for match in match_get.json(): m = match['match'] matches.append(m) else: # Error out if there are no active matches or if we can't get a good call to Challonge raise Exception(bold("Challonge_Report") + ": Error fetching matches for <{0}>. Is the tournament started?".format(tour_url)) # Check to make sure the given winner is in the bracket if winner_name.lower() not in match_parts: raise Exception(bold("Challonge_Report") + ": {0} is not in the tournament".format(bold(winner_name))) # Go through every active match to find one with the winner in it for match in matches: # Check to see if the winner is in the current match that is being looped if not (match['player1_id'] == match_parts[winner_name.lower()] or match['player2_id'] == match_parts[winner_name.lower()]): # Check if we went through every match if match == matches[-1]: # Error out that the player wasn't in any active match raise Exception(bold("Challonge_Report") + ": User: {0} does not have an open match to report".format(winner_name)) continue scores = params[0].split('-') # First parameter should be the score # Check that the score was given in the proper format if not len(scores) == 2: # Error out and show what a score should look like raise Exception(bold("Challonge_Report") + ": {0} is not a valid score. Example score: 2-0".format(bold(params[0]))) try: # Check to see if we need to reverse the score since it has to be p1-p2 # So if the winner is p1 and the score is p2-p1, reverse the order to be p1-p2 # Or if the winner is p2 and the score is p2-p1, reverse the order to be p1-p2 if (match['player1_id'] == match_parts[winner_name.lower()] and int(scores[1]) > int(scores[0])) or (match['player2_id'] == match_parts[winner_name.lower()] and int(scores[0]) > int(scores[1])): scores.reverse() except: # Error out if unable to convert each score into an int e.g. a-b raise Exception(bold("Challonge_Report") + ": {0} is not a valid score. Example score: 2-0".format(bold(params[0]))) # Time to send out the winner and the score match_put = requests_put(base_url + tour_url + "/matches/" + str(match['id']) +".json", headers={"User-Agent":"Lizard-BOT"}, auth=(chal_user, api_key), params={'match[winner_id]':match_parts[winner_name.lower()], 'match[scores_csv]':'-'.join(scores)}) # Check to make sure we get a good response if '200' in str(match_put.status_code): # Good response. Return that the score was updated return "Lizard-BOT reported {0} won {1}!".format(bold(winner_name), bold('-'.join(scores))) elif '401' in str(match_put.status_code): # Permission error raise Exception(bold("Challonge_Report") + ": Lizard-BOT does not have access to the tournament") else: # Some other challonge error. Print it to console and error with appropriate message print(match_put.text) raise Exception(bold("Challonge_Report") + ": Unknown Challonge error for <" + tour_url + "> while submitting a match")
async def refresh(command, msg, user, channel, *args, **kwargs): # Static message to yell at users to refresh return bold( "REFRESH YOUR BRACKETS\nREFRESH YOUR BRACKETS\nREFRESH YOUR BRACKETS\nREFRESH YOUR BRACKETS" )