示例#1
0
    def test_list_categories(self):

        date1 = arrow.get('2014-10-23').datetime
        for i in range(1, 250):
            poll = models.Poll(id=i,
                               date=date1,
                               url="someurl",
                               category="m",
                               title="sometitle",
                               client="someclient")
            db.session.add(poll)
        for i in range(251, 500):
            poll = models.Poll(id=i,
                               date=date1,
                               url="someurl",
                               category="n",
                               title="someothertitle",
                               client="someotherclient")
            db.session.add(poll)
        db.session.commit()

        response = self.app.get('polls/categories/')
        assert response.status_code == 200
        decoded = response.get_data().decode('utf-8')
        response_json = json.loads(decoded)

        assert len(response_json) == 2
        assert "m" in response_json
        assert "n" in response_json
示例#2
0
    def test_get_party_polls(self):

        date1 = arrow.get('2014-10-23').datetime
        date2 = arrow.get('2017-11-24').datetime

        poll1 = models.Poll(id=1,
                            date=date1,
                            url="fe",
                            category="m",
                            title="sometitle",
                            client="someclient")
        poll2 = models.Poll(id=2,
                            date=date2,
                            url="someurl",
                            category="m",
                            title="someothertitle",
                            client="someclient")
        party1 = models.Party(name="somename",
                              code="PAR",
                              colour="col",
                              text_colour="tcol",
                              url="someurl")
        poll_party1 = models.PollParty(score=30)
        poll_party2 = models.PollParty(score=25)
        poll_party1.poll = poll1
        poll_party2.poll = poll2
        party1.polls.append(poll_party1)
        party1.polls.append(poll_party2)

        db.session.add(party1)
        db.session.commit()

        response = self.app.get('/parties/par/polls/')
        decoded = response.get_data().decode("utf-8")
        response_json = json.loads(decoded)

        # Check the party has the 2 given polls
        assert len(response_json) == 2

        # Check the scores are in the response
        assert b"30" in response.get_data()
        assert b"25" in response.get_data()

        # Check the entries are correctly sorted by date
        response_date = arrow.get(response_json[0].get('date')).datetime
        assert response_date == date2

        # Check that trying to access a non-existent page throws 404
        response = self.app.get('/parties/par/polls/2/')
        assert response.status_code == 404
示例#3
0
    def test_get_current_cycle_polls(self):

        date1 = arrow.get('2014-10-23').datetime
        date2 = arrow.get('2017-11-24').datetime

        poll1 = models.Poll(id=1,
                            date=date1,
                            url="fe",
                            category="m",
                            title="sometitle",
                            client="someclient")
        poll2 = models.Poll(id=2,
                            date=date2,
                            url="someurl",
                            category="m",
                            title="someothertitle",
                            client="someclient")

        db.session.add(poll1)
        db.session.add(poll2)
        db.session.commit()

        response = self.app.get('/')
        decoded = response.get_data().decode("utf-8")
        response_json = json.loads(decoded)

        # Check we only get the poll dated after the current cycle
        assert len(response_json['current_polls']) == 1
        assert response_json['current_polls'][0]['title'] == "someothertitle"

        # Test for edge case of poll ON the cycle start
        date3 = arrow.get('2015-05-07').datetime
        poll3 = models.Poll(id=3,
                            date=date3,
                            url="someurl",
                            category='n',
                            title="anothertitle",
                            client="someotherclient")

        db.session.add(poll3)
        db.session.commit()

        response = self.app.get('/')
        decoded = response.get_data().decode("utf-8")
        response_json = json.loads(decoded)

        # Check we get both polls dated after the current cycle
        assert len(response_json['current_polls']) == 2
示例#4
0
    def test_list_parties_for_poll(self):

        date1 = arrow.get('2017-01-01').datetime
        poll1 = models.Poll(id=1,
                            date=date1,
                            url="fe",
                            category="m",
                            title="sometitle",
                            client="someclient")
        party1 = models.Party(name="party1",
                              code="PAR1",
                              colour="col",
                              text_colour="tcol",
                              url="someurl")
        party2 = models.Party(name="party2",
                              code="PAR2",
                              colour="cool",
                              text_colour="tcol",
                              url="someurl1")
        party3 = models.Party(name="party3",
                              code="PAR3",
                              colour="col",
                              text_colour="tcol",
                              url="someurl2")
        pp1 = models.PollParty(score=30)
        pp2 = models.PollParty(score=20)
        pp3 = models.PollParty(score=50)
        pp1.party = party1
        pp2.party = party2
        pp3.party = party3
        poll1.parties.append(pp1)
        poll1.parties.append(pp2)
        poll1.parties.append(pp3)

        db.session.add(poll1)
        db.session.commit()

        # Check the party is there
        response = self.app.get('/polls/id/1/')
        assert response.status_code == 200

        # Check the scores are there
        assert b'30' in response.get_data()
        assert b'20' in response.get_data()
        assert b'50' in response.get_data()

        decoded = response.get_data().decode('utf-8')
        response_json = json.loads(decoded)

        # Check we have the expected number of parties
        assert len(response_json['parties']) == 3

        parties = []
        for party in response_json['parties']:
            parties.append(party.get('code'))

        assert "PAR1" in parties
        assert "PAR2" in parties
        assert "PAR3" in parties
示例#5
0
    def test_get_company_polls(self):

        date1 = arrow.get('2014-10-23').datetime
        date2 = arrow.get('2017-11-24').datetime

        poll1 = models.Poll(id=1,
                            date=date1,
                            url="fe",
                            category="m",
                            title="sometitle",
                            client="someclient")
        poll2 = models.Poll(id=2,
                            date=date2,
                            url="someurl",
                            category="m",
                            title="someothertitle",
                            client="someclient")
        company = models.Company(code="COM",
                                 name="Company",
                                 url="someurl",
                                 canonical="company")
        company.company_polls.append(poll1)
        company.company_polls.append(poll2)
        db.session.add(company)
        db.session.commit()

        # Check we get a response
        response = self.app.get('/companies/company/polls/')
        assert response.status_code == 200

        # Check we get two polls for the company
        decoded = response.get_data().decode('utf-8')
        response_json = json.loads(decoded)
        assert len(response_json['polls']) == 2

        # Check they are sorted by date
        response_date = arrow.get(
            response_json['polls'][0].get('date')).datetime
        assert response_date == date2

        # Check the two polls are the ones we defined
        assert b"someothertitle" in response.get_data()
        assert b"sometitle" in response.get_data()
示例#6
0
    def test_get_specific_poll(self):

        date1 = arrow.get('2014-10-23').datetime
        date2 = arrow.get('2017-11-24').datetime

        poll1 = models.Poll(id=1,
                            date=date1,
                            url="fe",
                            category="m",
                            title="sometitle",
                            client="someclient")
        poll2 = models.Poll(id=2,
                            date=date2,
                            url="someurl",
                            category="m",
                            title="someothertitle",
                            client="someclient")

        db.session.add(poll1)
        db.session.add(poll2)
        db.session.commit()

        response = self.app.get('/polls/id/1/')
        assert response.status_code == 200
        decoded = response.get_data().decode('utf-8')
        response_json = json.loads(decoded)
        assert response_json['title'] == "sometitle"

        response = self.app.get('/polls/id/2/')
        assert response.status_code == 200
        decoded = response.get_data().decode('utf-8')
        response_json = json.loads(decoded)
        assert response_json['title'] == "someothertitle"

        response = self.app.get('/polls/id/3/')
        assert response.status_code == 404
示例#7
0
    def test_pagination_polls(self):

        date1 = arrow.get('2017-01-01').datetime

        for i in range(1, 500):
            poll = models.Poll(id=i,
                               date=date1,
                               url="someurl",
                               category="m",
                               title="sometitle",
                               client="someclient")
            db.session.add(poll)
        db.session.commit()

        response_page1 = self.app.get('/polls/')
        decoded_page1 = response_page1.get_data().decode('utf-8')
        response_json_page1 = json.loads(decoded_page1)

        # Check we only get 50 responses on page 1
        assert len(response_json_page1['polls']) == 50

        response_page2 = self.app.get('/polls/2/')
        decoded_page2 = response_page2.get_data().decode('utf-8')
        response_json_page2 = json.loads(decoded_page2)

        # Check we only get 50 responses on page 2
        assert len(response_json_page2['polls']) == 50

        # Check the top items of each page are not the same
        top_poll1 = response_json_page1['polls'][0]
        top_poll2 = response_json_page2['polls'][0]

        assert top_poll1 != top_poll2

        # Check that going a page too far returns an error
        response_over_max = self.app.get('/polls/11/')
        assert response_over_max.status_code == 404
示例#8
0
async def create_poll(reply: discord.message.Message,
                      db_channel: models.Channel):
    """
    Create a poll from the reply and send a new message asking for the options.

    :param reply: the reply.
    :param db_channel: the DB channel in which it was answered.
    """

    # Create a new poll
    poll_key = reply.content.split()[0] + str(random.getrandbits(8))

    new_poll = models.Poll(poll_key, reply.author.id, reply.content, False,
                           False, False, False, db_channel.id, reply.guild.id)

    config.session.add(new_poll)
    config.session.commit()

    # Send the message
    msg = header % ('add_options)(poll_key:%s)' % poll_key) \
          + '\nReply to this message with the options of the poll, separated by comma (,).\n' \
            'Or use the 📆 reaction to add weekdays as options.'

    message = await reply.channel.send(msg)

    # Add the calendar reaction
    await message.add_reaction('📆')

    # Wait for 300 seconds
    await asyncio.sleep(300)

    # Delete this message
    try:
        await message.delete()
    except discord.errors.NotFound:
        pass
示例#9
0
async def create_poll_command(command, db_channel):
    """
    Create a new poll.

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

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

    # Create channel if it does not already exist
    if db_channel is None:
        db_channel = auxiliary.create_channel(command)

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

    weekly = False
    pt = False
    day_param_pos = -1
    day_param_poll_pos = -1

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

    # Confirmation is necessary when there is a need to close a poll before this one is created
    confirmation = False

    poll_params = []

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

        if params[i] == '-weekly':
            weekly = True
            pt = False
            day_param_pos = i + 1
            day_param_poll_pos = len(poll_params)
        elif params[i] == '-weekly_pt':
            weekly = True
            pt = True
            day_param_pos = i + 1
            day_param_poll_pos = len(poll_params)
        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
            if params[i].__contains__('y'):
                confirmation = 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:
        msg = 'Invalid parameters in command: **%s**' % command.content

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

    # Get the poll with this id
    poll = config.session.query(
        models.Poll).filter(models.Poll.poll_key == poll_params[0]).first()

    # If a poll with the same id already exists, delete it
    if poll is not None:
        if poll.discord_author_id == command.author.id:
            # Confirmation required before deleting a poll
            if confirmation:
                await auxiliary.delete_poll(poll, db_channel,
                                            command.author.id)
            else:
                msg = 'A poll with that id already exists add **-y** to your command to confirm the deletion of the ' \
                      'previous poll.\nYour command: **%s**' % command.content

                await auxiliary.send_temp_message(msg, command.channel)
                return
        else:
            msg = 'A poll with that id already exists and you cannot close it because you are not its author!'

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

    num_polls = config.session.query(models.Poll).filter(
        models.Poll.discord_server_id == discord_server_id).count()

    # Limit the number of polls per server
    if num_polls >= config.POLL_LIMIT_SERVER:
        polls = config.session.query(models.Poll).filter(models.Poll.discord_server_id == discord_server_id) \
            .filter(models.Poll.discord_author_id == command.author.id).all()

        msg = 'The server you\'re in has reached its poll limit, creating another poll is not possible.'

        if len(polls) == 0:
            msg += 'Ask the authors of other polls to delete them.\nYour command: **%s**' % command.content

        else:
            msg += 'Delete one of your polls before continuing.\nList of your polls in this server:'

            for p in polls:
                msg += '\n%s - !poll_delete %s' % (p.poll_key, p.poll_key)

            msg += '\nYour command: **%s**' % command.content

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

    # Create the new poll
    new_poll = models.Poll(poll_params[0], command.author.id, poll_params[1],
                           multiple_options, only_numbers, new_options,
                           allow_external, db_channel.id, discord_server_id)

    config.session.add(new_poll)

    # Send a private message to each member in the server
    for m in command.channel.members:
        if m != config.client.user and m.id != new_poll.discord_author_id:
            try:
                await m.send('A new poll (%s) has been created in %s!' %
                             (new_poll.poll_key, command.channel.mention))
            except (discord.errors.Forbidden, discord.errors.HTTPException):
                pass

    # Necessary for the options to get the poll id
    config.session.flush()

    options = []

    # Get the current dates
    start_date = datetime.datetime.today()

    num_options = max(6 - start_date.weekday(), 0)
    end_date = start_date + datetime.timedelta(days=num_options)

    # Calculate the date interval for the options
    if weekly and day_param_poll_pos < len(poll_params):
        try:
            days = params[day_param_pos].split(',')

            starting_day = int(days[0])
            start_date = auxiliary.date_given_day(start_date, starting_day)

            if len(days) > 1:
                end_day = int(days[1])
                end_date = auxiliary.date_given_day(start_date, end_day)

            # Remove this option
            poll_params.remove(poll_params[day_param_poll_pos])
        except ValueError:
            pass

    # Create the options
    if len(poll_params[2:]) != 0 or weekly:
        # Add days of the week as options
        if weekly:
            weekly_options = auxiliary.create_weekly_options(start_date,
                                                             end_date,
                                                             pt=pt)

            for option in weekly_options:
                options.append(
                    models.Option(new_poll.id,
                                  len(options) + 1, option))

        for option in poll_params[2:]:
            options.append(models.Option(new_poll.id,
                                         len(options) + 1, option))

    # If no options were provided, then create the default Yes and No
    else:
        options.append(models.Option(new_poll.id, 1, 'Yes'))
        options.append(models.Option(new_poll.id, 2, 'No'))

    config.session.add_all(options)

    # Create the message with the poll
    msg = await command.channel.send(
        auxiliary.create_message(new_poll, options))

    new_poll.discord_message_id = msg.id

    # Add a reaction for each option
    await auxiliary.add_options_reactions(msg, options)

    config.session.commit()

    print('Poll %s created -> %s!' % (new_poll.poll_key, command.content))