예제 #1
0
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")
예제 #2
0
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())))
예제 #3
0
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 ''
예제 #4
0
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")
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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
예제 #8
0
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
예제 #9
0
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}"
        )
예제 #10
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!")
예제 #11
0
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)
예제 #12
0
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))
예제 #13
0
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))
예제 #14
0
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)
예제 #15
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
예제 #16
0
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)))
예제 #17
0
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 
예제 #18
0
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.")
예제 #19
0
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
예제 #20
0
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*"
    )
예제 #21
0
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"])))
예제 #22
0
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"
예제 #23
0
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")
예제 #24
0
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"
    )