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
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
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
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
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()
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
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
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
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))