Esempio n. 1
0
async def configure_channel_command(command, db_channel):
    """
    Configure a channel with the given settings.
    If this channel does not yet exit in the DB, then create it.

    :param command: the command used.
    :param db_channel: the corresponding channel entry in the DB.
    """

    # Make sure the user changing the channel settings is an admin
    if not command.author.guild_permissions.administrator:
        msg = 'Only server administrators can change a channel\'s settings.'

        await auxiliary.send_temp_message(msg, command.channel)
        return

    # The ids of the Discord channel and server where the message was sent
    discord_channel_id = command.channel.id
    discord_server_id = command.guild.id

    # Get the list of parameters in the message
    params = auxiliary.parse_command_parameters(command.content)

    # If the command has an invalid number of parameters
    if len(params) != 2:
        return

    # Filter the chosen setting
    delete_commands = False
    delete_all = False

    if params[1] == '-dc':
        delete_commands = True
    elif params[1] == '-da':
        delete_all = True
    elif params[1] == '-ka':
        delete_all = False
        delete_commands = False

    # Create or modify the channel with the correct configurations
    if db_channel is None:
        db_channel = models.Channel(discord_channel_id, discord_server_id,
                                    delete_commands, delete_all)

        config.session.add(db_channel)
    else:
        db_channel.delete_commands = delete_commands
        db_channel.delete_all = delete_all

    config.session.commit()

    print('Channel %s from %s was configured -> %s!' %
          (command.channel.name, command.guild.name, command.content))
Esempio n. 2
0
async def close_poll_command(command, db_channel):
    """
    Close a poll.

    :param command: the command used.
    :param db_channel: the corresponding channel entry in the DB.
    """

    # If the channel does not exist in the DB
    if db_channel is None:
        msg = 'There\'s no poll in this channel for you to close!'

        await auxiliary.send_temp_message(msg, command.channel)
        return

    # Get the list of parameters in the message
    params = auxiliary.parse_command_parameters(command.content)

    # If the command has an invalid number of parameters
    if len(params) != 3:
        msg = 'Invalid parameters in command: **%s**' % command.content

        await auxiliary.send_temp_message(msg, command.channel)
        return

    poll_key = params[1]

    # Split the selected options
    list_options = params[2].split(',')

    # Options are all numbers
    try:
        # Verify if the options are numbers
        selected_options = []

        for o in list_options:
            selected_options.append(int(o))

        # Select the current poll
        poll = config.session.query(
            models.Poll).filter(models.Poll.poll_key == poll_key).first()

        # Edit the message with the poll
        if poll is not None:
            # Only the author can close the poll
            if poll.discord_author_id == command.author.id:
                options = config.session.query(models.Option).filter(models.Option.poll_id == poll.id) \
                    .order_by(models.Option.position).all()

                # Send a private message to all participants in the poll
                await auxiliary.send_closed_poll_message(
                    options, command.guild, poll, command.channel)

                await auxiliary.close_poll(poll, db_channel, selected_options)

                config.session.commit()

                print('Poll %s closed -> %s!' %
                      (poll.poll_key, command.content))
        else:
            msg = 'There\'s no poll with that id for you to close.\nYour command: **%s**' % command.content

            await auxiliary.send_temp_message(msg, command.channel)
    except ValueError:
        pass
Esempio n. 3
0
async def edit_poll_command(command, db_channel):
    """
    Edit a poll.

    :param command: the command used.
    :param db_channel: the corresponding channel entry in the DB.
    """

    # If the channel does not exist in the DB
    if db_channel is None:
        msg = 'There\'s no poll in this channel for you to edit!'

        await auxiliary.send_temp_message(msg, command.channel)
        return

    # Get the list of parameters in the message
    params = auxiliary.parse_command_parameters(command.content)

    add = False
    remove = False
    lock = False
    unlock = False

    multiple_options = False
    only_numbers = False
    new_options = False
    allow_external = False

    poll_params = []

    # Filter the available options for polls
    for i in range(len(params)):
        if i == 0:
            continue

        if params[i] == '-add':
            add = True
            remove = False
            lock = False
            unlock = False
        elif params[i] == '-rm':
            remove = True
            add = False
            lock = False
            unlock = False
        elif params[i] == '-lock':
            remove = False
            add = False
            lock = True
            unlock = False
        elif params[i] == '-unlock':
            remove = False
            add = False
            lock = False
            unlock = True
        elif params[i].startswith('-'):
            if params[i].__contains__('m'):
                multiple_options = True
            if params[i].__contains__('o'):
                only_numbers = True
            if params[i].__contains__('n'):
                new_options = True
            if params[i].__contains__('e'):
                allow_external = True
        else:
            # Add all non configuration parameters, ignoring quotation marks
            poll_params.append(params[i].replace('"', ''))

    # If the command has an invalid number of parameters
    if (len(poll_params) < 2 and (add or remove or lock or unlock)) or \
            (len(poll_params) < 1 and not add and not remove and not lock and not unlock):
        msg = 'Invalid parameters in command: **%s**' % command.content

        await auxiliary.send_temp_message(msg, command.channel)
        return

    poll_key = poll_params[0]

    # Select the current poll
    poll = config.session.query(
        models.Poll).filter(models.Poll.poll_key == poll_key).first()

    # If no poll was found with that id
    if poll is None:
        msg = 'There\'s no poll with that id for you to edit.\nYour command: **%s**' % command.content

        await auxiliary.send_temp_message(msg, command.channel)
        return

    # Only the author can edit
    if poll.discord_author_id != command.author.id:
        msg = 'Only the author of a poll can edit it!'

        await auxiliary.send_temp_message(msg, command.channel)
        return

    edited = ''

    # Get all options available in the poll
    db_options = config.session.query(models.Option).filter(models.Option.poll_id == poll.id) \
        .order_by(models.Option.position).all()

    # Add the new options
    if add:
        new_options = poll_params[1:]

        options = []

        edited = 'new options added %s' % new_options

        # Create the options
        for option in new_options:
            options.append(
                models.Option(poll.id,
                              len(db_options) + len(options) + 1, option))

        config.session.add_all(options)

        # Get the message corresponding to the poll
        c = config.client.get_channel(db_channel.discord_id)
        discord_poll_msg = await c.fetch_message(poll.discord_message_id)

        # Add a reaction for each new option
        emoji = chr(ord(u'\u0031') + len(db_options))

        # Max number of reactions that can be added
        num_react = min(9, len(db_options) + len(options))

        for i in range(max(0, num_react - len(db_options))):
            await discord_poll_msg.add_reaction(emoji + u'\u20E3')
            emoji = chr(ord(emoji) + 1)

        db_options.extend(options)
    # Remove, lock or unlock options
    elif remove or lock or unlock:
        rm_options = poll_params[1]

        # Option is a number
        try:
            # Verify if the options are numbers
            selected_options = []

            for o in rm_options.split(','):
                selected_options.append(int(o))

            # Removes duplicates in the list
            selected_options = list(set(selected_options))

            if remove:
                options = config.session.query(models.Option) \
                    .filter(models.Option.poll_id == poll.id) \
                    .filter(models.Option.position.in_(selected_options)) \
                    .all()

                num_reactions = max(10 - len(db_options) - len(options), 0)

                edited = 'options removed %s' % options

                for option in options:
                    config.session.delete(option)

                # Get the message corresponding to the poll
                c = config.client.get_channel(db_channel.discord_id)
                discord_poll_msg = await c.fetch_message(
                    poll.discord_message_id)

                db_options = config.session.query(models.Option).filter(models.Option.poll_id == poll.id) \
                    .order_by(models.Option.position).all()

                for i in range(num_reactions):
                    emoji = chr(ord(u'\u0031') + len(db_options) + i)

                    await auxiliary.remove_reaction(discord_poll_msg, emoji)

                # Update the positions
                pos = 1

                for option in db_options:
                    option.position = pos
                    pos += 1

            elif lock or unlock:
                if lock:
                    edited = 'options %s locked' % selected_options
                else:
                    edited = 'options %s unlocked' % selected_options

                for option in selected_options:
                    num_options = len(db_options)

                    # If it is a valid option
                    if 0 < option <= num_options:
                        if lock:
                            db_options[option - 1].locked = True
                        elif unlock:
                            db_options[option - 1].locked = False

        # Option is not a number
        except ValueError:
            pass
    else:
        # Edit poll question
        if len(poll_params) > 1:
            poll.question = poll_params[1]

            edited = 'question is now %s' % poll.question
        # Edit poll settings
        else:
            poll.multiple_options = multiple_options
            poll.only_numbers = only_numbers
            poll.new_options = new_options
            poll.allow_external = allow_external

            edited = 'settings multiple_options=%r, only_numbers=%r, new_options=%r, allow_external=%r changed' \
                     % (multiple_options, only_numbers, new_options, allow_external)

    # Edit message
    c = config.client.get_channel(db_channel.discord_id)

    try:
        m = await c.fetch_message(poll.discord_message_id)

        await m.edit(content=auxiliary.create_message(poll, db_options))
    except discord.errors.NotFound:
        config.session.delete(poll)

    config.session.commit()

    print('Poll %s was edited for %s -> %s!' %
          (poll.poll_key, edited, command.content))