def add_bot(): """ This function renders the add_bot form where user can add a new bot to database by providing token for the bot. :return: .../addbot """ form = AddBotForm() if form.validate_on_submit(): bot = MyBot.objects(token=form.token.data).first() if bot is not None: # Duplicate token user for adding bot. flash('Another bot Bot:{username} is already registered with ' 'given token.'.format(username=bot.username)) # Redirect user to Bot's homepage. return redirect(url_for('web_ui.bot_info', botid=bot.bot_id)) if form.is_test_bot.data: # if requested token is for a testbot. status = procedures.add_bot(token=form.token.data, testing=True) web_logger.info('New testbot bot:{uname} added by web api.'.format( uname=status[0])) flash('Testbot Bot:{username} successfully added to ' 'database.'.format(username=status[0])) return redirect( url_for('web_ui.bot_info', botid=MyBot.objects( username__iexact=status[0]).first().bot_id)) else: try: # Add the bot. status = procedures.add_bot(token=form.token.data, testing=False) # Redirect to bot info page. if status[1]: web_logger.info( 'New live bot:{uname} added by web api and ' 'started polling.'.format(uname=status[0])) flash('New bot:{username} successfully added and ' 'started polling.'.format(username=status[0])) return redirect( url_for( 'web_ui.bot_info', botid=MyBot.objects( username__iexact=status[0]).first().bot_id)) else: # Redirect to Edit bot page to start polling again. web_logger.info( 'New live bot:{uname} added by web api and ' 'did not start polling.'.format(uname=status[0])) flash('New bot:{username} successfully added but ' 'did not start polling.'.format(username=status[0])) return redirect( url_for( 'web_ui.edit_bot', bot_choice=MyBot.objects( username__iexact=status[0]).first().bot_id)) except Exception as e: web_logger.error( 'Error:{msg} during adding new bot.'.format(msg=e.message)) return render_template('500.html', error_message=e.message) return render_template('add_bot.html', form=form)
def get_bot_info(bot_choice=0): """ This function renders the page showing a DropDown field listing all Bots in the database. Upon selection the user is redirected to bot's own information page. :param bot_choice: initial choice for the bot (default=0, no choice) :return: .../getbotinfo """ form = GetBot(choose_bot=bot_choice) # Populate the initial set of choices for Bot DropDownList. form.choose_bot.choices = [('#', 'Select')] + \ list(MyBot.objects().values_list( 'username', 'username')) if form.validate_on_submit(): # Redirect to bot_info page. bot = MyBot.objects(username__iexact=form.choose_bot.data).first() if bot is not None: web_logger.info('Successfully redirected user to bot_info page ' 'for bot:{uname}'.format(uname=bot.username)) return redirect(url_for('.bot_info', page=1, botid=bot.bot_id)) else: web_logger.info('Web request to get info for a non existing bot ' 'with ID:{bid}'.format(bid=form.choose_bot.data)) return render_template('404.html', message='Invalid bot ID used.') return render_template('get_bot_info.html', form=form)
def test_start_livebot_with_valid_botid(self): bot = MyBot(token=CONSTANTS.LIVE_BOTS.get(1)).save() self.assertIsNotNone(bot) self.assertEqual(procedures.start_bot(botid=bot.bot_id), 1) bot = MyBot.objects(bot_id=bot.bot_id).first() self.assertTrue(bot.state) # Otherwise unittests doesn't end. self.assertEqual(procedures.stop_bot(botid=bot.bot_id), 1) bot = MyBot.objects(bot_id=bot.bot_id).first() self.assertFalse(bot.state)
def test_add_valid_bot(self): base_address = 'http://127.0.0.1:5000/web/index' # navigate to home page self.client.get(base_address) # Navigate to filtering page self.client.find_element_by_link_text('New-bot').click() self.assertTrue( re.search('Add a new Bot', self.client.page_source, re.IGNORECASE)) # add a test bot self.client.find_element_by_name('token')\ .send_keys(CONSTANTS.LIVE_BOTS.get(1)) self.client.find_element_by_name('submit').click() bot = MyBot.objects(token=CONSTANTS.LIVE_BOTS.get(1)).first() self.assertIsNotNone(bot) self.assertTrue(bot.state) # Assertions. self.assertTrue( re.search('Bot\s+{uname}'.format(uname=bot.username), self.client.page_source, re.IGNORECASE)) self.assertTrue( re.search( 'Bot\s+name:\s+{fname}\s+{lname}'.format(fname=bot.first_name, lname=bot.last_name), self.client.page_source, re.IGNORECASE)) self.assertTrue( re.search('ID:\s+{botid}'.format(botid=bot.bot_id), self.client.page_source, re.IGNORECASE)) self.assertTrue( re.search('token:\s+{token}'.format(token=bot.token), self.client.page_source, re.IGNORECASE)) self.assertTrue('New bot:{uname} successfully added and started ' 'polling.'.format( uname=bot.username) in self.client.page_source) # Force disable live bot from polling. self.assertEqual(procedures.stop_bot(botid=bot.bot_id), 1)
def bot_info(botid): """ This function renders the page showing bot information including username, token, ID and messages logged by the bot. :param botid: ID of the bot whose information is requested. :return: .../bot_info """ page = request.args.get('page', 1, type=int) bot = MyBot.objects(bot_id=botid).first() if bot is None: # Requested bot not found, redirect to selection page for choosing # another bot. web_logger.warn('Web request to get bot info with ID:{bid} which does ' 'not exist in database.'.format(bid=botid)) flash('Requested bot with ID:{bid} does not exist in the ' 'database.'.format(bid=botid)) return redirect(url_for('.get_bot_info', bot_choice=0)) msgs = procedures.filter_messages(botid=botid) pagination = msgs.paginate( page, error_out=False, per_page=current_app.config['MESSAGES_PER_PAGE']) return render_template('botinfo.html', bot=bot, messages=pagination.items, pagination=pagination)
def test_start_livebot_with_valid_username(self): bot = Bot(token=CONSTANTS.LIVE_BOTS.get(1)).get_me() mybot = MyBot(token=CONSTANTS.LIVE_BOTS.get(1), bot_id=bot.id, username=bot.username, first_name=bot.first_name, last_name=bot.last_name).save() self.assertIsNotNone(mybot) self.assertEqual(procedures.start_bot(username=str(mybot.username)), 1) mybot = MyBot.objects(bot_id=mybot.bot_id).first() self.assertTrue(mybot.state) # Otherwise unittests doesn't end. self.assertEqual(procedures.stop_bot(botid=mybot.bot_id), 1) mybot = MyBot.objects(bot_id=mybot.bot_id).first() self.assertFalse(mybot.state)
def test_add_test_bot(self): base_address = 'http://127.0.0.1:5000/web/index' # navigate to home page self.client.get(base_address) # Navigate to filtering page self.client.find_element_by_link_text('New-bot').click() self.assertTrue( re.search('Add a new Bot', self.client.page_source, re.IGNORECASE)) # add a test bot self.client.find_element_by_name('token').send_keys('dummy-bot-token') self.client.find_element_by_name('is_test_bot').click() self.client.find_element_by_name('submit').click() bot = MyBot.objects(token='dummy-bot-token').first() self.assertIsNotNone(bot) self.assertFalse(bot.state) # Assertions. self.assertTrue( re.search('Bot\s+{uname}'.format(uname=bot.username), self.client.page_source, re.IGNORECASE)) self.assertTrue( re.search('Bot\s+name:\s+test\s+bot', self.client.page_source, re.IGNORECASE)) self.assertTrue( re.search('ID:\s+{botid}'.format(botid=bot.bot_id), self.client.page_source, re.IGNORECASE)) self.assertTrue( re.search('token:\s+{token}'.format(token=bot.token), self.client.page_source, re.IGNORECASE)) self.assertTrue('Testbot Bot:{uname} successfully added to ' 'database'.format( uname=bot.username) in self.client.page_source)
def test_cascade_delete_bot_and_message_by_uname_with_multiple_valid_botid( self): bot1 = MyBot(token='dummy-token1', username='******').save() bot2 = MyBot(token='dummy-token2', username='******').save() self.assertEqual(MyBot.objects.count(), 2) response = self.client.delete(url_for( 'botapi.delete_bot_and_message_by_uname', username=bot1.username), headers=self.get_api_headers()) self.assertEqual(response.status_code, 200) json_response = json.loads(response.data.decode('utf-8')) self.assertEqual(json_response['status'], 'success') self.assertEqual( json_response['message'], 'Bot:{uname} and {msgs} logged messages ' 'removed'.format(uname=bot1.username, msgs=0)) self.assertEqual(MyBot.objects.count(), 1) self.assertIsNone(MyBot.objects(username=bot1.username).first()) self.assertIsNotNone(MyBot.objects(username=bot2.username).first())
def test_start_stop_all_with_test_bots(self): bot = MyBot(token='dummy-token', test_bot=True).save() self.assertIsNotNone(bot) started = procedures.start_all() self.assertTrue(bot.bot_id not in started) self.assertEqual(len(started), MyBot.objects(test_bot=False).count()) stopped = procedures.stop_all() self.assertTrue(bot.bot_id not in stopped)
def test_stopbot_previously_running_now_stopped_live_bot(self): bot = MyBot(token=CONSTANTS.LIVE_BOTS.get(1)).save() self.assertIsNotNone(bot) self.assertEqual(procedures.start_bot(botid=bot.bot_id), 1) self.assertEqual(procedures.stop_bot(botid=bot.bot_id), 1) bot = MyBot.objects(token=bot.token).first() self.assertFalse(bot.state) self.assertEqual(procedures.stop_bot(botid=bot.bot_id), -2)
def test_start_stop_all_with_valid_bots(self): bot = MyBot(token=CONSTANTS.LIVE_BOTS.get(1)).save() self.assertIsNotNone(bot) started = procedures.start_all() self.assertTrue(bot.bot_id in started) self.assertEqual(len(started), MyBot.objects(test_bot=False).count()) stopped = procedures.stop_all() self.assertTrue(len(stopped), len(started)) self.assertTrue(bot.bot_id in stopped)
def filtering(): """ This function displays the form for getting filtering criteria from the user and redirects user to the page containing filtered messages. :return: ../filtered_messages """ form = FilteringForm(time_int_field='', text_field='', fn_ln_field='', bot_field=0, time_field=0, username_field='') # Populate form fields initially. form.bot_field.choices = [(0, 'Select an option')] + list( MyBot.objects().all().values_list('bot_id', 'username')) form.username_field.choices = \ [('#', 'Select')] + \ list(Message.objects(sender_username__nin=['unknown', '']) .values_list('sender_username', 'sender_username')) if form.validate_on_submit(): # Get filtering criteria from the submitted form. try: if int(form.time_field.data) > 0: time_offset = form.time_field.data elif int(form.time_int_field.data) > 0: time_offset = form.time_int_field.data else: time_offset = int(time.time()) / 60 # Redirect to page showing filtered message. web_logger.info('User redirected to filtered messages page with ' 'given criteria: botid:{bid},time_off:{tim},' 'text:{txt},username:{uname},name:{name}'.format( bid=form.bot_field.data, tim=time_offset, txt=form.text_field.data, uname=form.username_field.data, name=form.fn_ln_field.data)) return redirect( url_for('.filtered_messages', botid=int(form.bot_field.data) if form.bot_field.data != '' else '#', time_off=time_offset, text=form.text_field.data if form.text_field.data != '' else '#', username=form.username_field.data, name=form.fn_ln_field.data if form.fn_ln_field.data != '' else '#')) except Exception as e: web_logger.error('Error:{msg} during redirecting user to filtered' ' messages page.'.format(msg=e.message)) return render_template('500.html', error_message=e.message) return render_template('filtering.html', form=form)
def test_add_testbot_valid_token(self): status = procedures.add_bot(token='dummy_token', testing=True) self.assertIsNotNone(status[0]) self.assertFalse(status[1]) self.assertTrue('testbot-' in status[0]) bot = MyBot.objects(username=status[0]).first() self.assertIsNotNone(bot) self.assertTrue(bot.test_bot) self.assertEqual(bot.first_name, 'test') self.assertEqual(bot.last_name, 'bot')
def test_add_livebot_with_duplicate_token(self): live_token = CONSTANTS.LIVE_BOTS.get(1) # Add a live bot with valid token. MyBot(token=live_token).save() self.assertIsNotNone(MyBot.objects(token=live_token).first()) self.assertEqual(MyBot.objects.count(), 1) with self.assertRaises(ValueError) as e: procedures.add_bot(token=live_token) self.assertEqual( str(e.exception), 'Bot with given token{tokn} is already present in ' 'database.'.format(tokn=live_token))
def test_start_bot_for_live_bot_valid_botid_wildcard_username(self): self.assertTrue( procedures.add_bot(token=CONSTANTS.LIVE_BOTS.get(1), testing=False)[1]) bot = MyBot.objects(token=CONSTANTS.LIVE_BOTS.get(1)).first() self.assertIsNotNone(bot) # Stop bot from polling. self.assertEqual(procedures.stop_bot(botid=bot.bot_id), 1) response = self.client.put(url_for('botapi.start_bot', botid=bot.bot_id, username='******'), headers=self.get_api_headers()) json_response = json.loads(response.data.decode('utf-8')) self.assertEqual(response.status_code, 200) self.assertEqual( json_response['message'], "Polling started for bot {name}".format(name=bot.bot_id)) bot = MyBot.objects(token=CONSTANTS.LIVE_BOTS.get(1)).first() self.assertTrue(bot.state) self.assertEqual(procedures.stop_bot(botid=bot.bot_id), 1)
def test_add_testbot_with_duplicate_token(self): bad_token = 'dummy-token' # Add a test bot with bad token. MyBot(token=bad_token, test_bot=True).save() self.assertIsNotNone(MyBot.objects(token=bad_token).first()) self.assertEqual(MyBot.objects.count(), 1) with self.assertRaises(ValueError) as e: procedures.add_bot(token=bad_token, testing=True) self.assertEqual( str(e.exception), 'Bot with given token{tokn} is already present in ' 'database.'.format(tokn=bad_token))
def test_start_stop_all_with_test_and_live_bots(self): bot1 = MyBot(token='dummy-token', test_bot=True, username='******').save() bot2 = MyBot(token=CONSTANTS.LIVE_BOTS.get(1), username='******').save() self.assertIsNotNone(bot1) self.assertIsNotNone(bot2) started = procedures.start_all() self.assertTrue(bot2.bot_id in started) self.assertTrue(bot1.bot_id not in started) self.assertEqual(len(started), MyBot.objects(test_bot=False).count()) stopped = procedures.stop_all() self.assertTrue(bot2.bot_id in stopped)
def test_stopbot_valid_running_bot_using_valid_botid(self): bot = Bot(token=CONSTANTS.LIVE_BOTS.get(1)).get_me() mybot = MyBot(token=CONSTANTS.LIVE_BOTS.get(1), bot_id=bot.id, username=bot.username, first_name=bot.first_name, last_name=bot.last_name).save() self.assertIsNotNone(mybot) self.assertEqual(procedures.start_bot(botid=mybot.bot_id), 1) self.assertEqual(procedures.stop_bot(botid=mybot.bot_id), 1) mybot = MyBot.objects(bot_id=mybot.bot_id).first() self.assertFalse(mybot.state)
def test_add_testbot_using_invlid_token_type_and_test_flag(self): response = self.client.post(url_for('botapi.add_bot', token=1234, test=1), headers=self.get_api_headers()) json_response = json.loads(response.data.decode('utf-8')) self.assertEqual(response.status_code, 400) bot = MyBot.objects(token='1', test_bot=True).first() self.assertIsNone(bot) self.assertEqual( json_response['message'], "String expected for token in URL. Integer provided.")
def test_add_livebot_with_dummy_token(self): response = self.client.post(url_for('botapi.add_bot', token='dummy-token', test=0), headers=self.get_api_headers()) json_response = json.loads(response.data.decode('utf-8')) self.assertEqual(response.status_code, 400) self.assertIsNone(MyBot.objects(token='dummy-token').first()) self.assertEqual( json_response['message'], "Unable to add Bot. Reason:{reason}".format( reason='Invalid token:{tokn} used for adding live bot.'.format( tokn='dummy-token')))
def test_delete_bot_using_valid_uname(self): bot = MyBot(token='dummy_token', username='******').save() self.assertIsNotNone(bot) response = self.client.delete(url_for( 'botapi.delete_only_bot_by_uname', username=bot.username), headers=self.get_api_headers()) self.assertEqual(response.status_code, 200) json_response = json.loads(response.data.decode('utf-8')) self.assertEqual(json_response['status'], 'success') self.assertEqual( json_response['message'], 'Bot:{uname} successfully removed'.format(uname=bot.username)) self.assertEqual(MyBot.objects.count(), 0) self.assertIsNone(MyBot.objects(username=bot.username).first())
def test_add_testbot_using_dummy_token_and_test_flag(self): response = self.client.post(url_for('botapi.add_bot', token='dummy-token', test=1), headers=self.get_api_headers()) json_response = json.loads(response.data.decode('utf-8')) self.assertEqual(response.status_code, 201) self.assertEqual(json_response['status'], 'ok') bot = MyBot.objects(token='dummy-token', test_bot=True).first() self.assertIsNotNone(bot) self.assertEqual( json_response['message'], "Bot:{name} successfully added to database but could not start " "polling.".format(name=bot.username))
class EditBot(FlaskForm): """ Flask form for editing a bot status i.e. enable/disable polling for the bot. """ choose_bot = SelectField( 'Choose Bot', coerce=str, choices=[('#', 'Select')] + list(MyBot.objects().values_list('username', 'username'))) status_field = StringField('Status') toggle = SubmitField() def __init__(self, *args, **kwargs): super(EditBot, self).__init__(*args, **kwargs) read_only(self.status_field)
def test_add_livebot_with_valid_token(self): response = self.client.post(url_for('botapi.add_bot', token=CONSTANTS.LIVE_BOTS.get(1), test=0), headers=self.get_api_headers()) json_response = json.loads(response.data.decode('utf-8')) self.assertEqual(response.status_code, 201) bot = MyBot.objects(token=CONSTANTS.LIVE_BOTS.get(1)).first() self.assertIsNotNone(bot) # Live bot is polling, stop it from polling. self.assertTrue(bot.state) self.assertEqual(procedures.stop_bot(botid=bot.bot_id), 1) self.assertEqual( json_response['message'], "Bot:{name} successfully added to database and started " "polling.".format(name=bot.username))
def test_add_livebot_with_valid_token(self): status = procedures.add_bot(token=CONSTANTS.LIVE_BOTS.get(1)) # Get bot information from Telegram API. bot = Bot(token=CONSTANTS.LIVE_BOTS.get(1)).get_me() self.assertIsNotNone(status[0]) self.assertEqual(status[0], bot.username) self.assertTrue(status[1]) mybot = MyBot.objects(username=status[0]).first() self.assertIsNotNone(mybot) self.assertFalse(mybot.test_bot) self.assertEqual(mybot.first_name, bot.first_name) self.assertEqual(mybot.last_name, mybot.last_name) self.assertEqual(mybot.username, bot.username) # Otherwise unittests doesn't end. self.assertEqual(procedures.stop_bot(mybot.bot_id), 1)
def test_testbot_creation(self): # Add a dummy bot MyBot(username='******', first_name='test', last_name='bot', token='dummy-token', test_bot=True).save() # Retrieve the bot bot = MyBot.objects(token='dummy-token').first() self.assertIsNotNone(bot) self.assertEqual(bot.username, 'testbot') self.assertEqual(bot.first_name, 'test') self.assertEqual(bot.last_name, 'bot') self.assertEqual(bot.token, 'dummy-token') self.assertFalse(bot.state) self.assertTrue(bot.test_bot)
def start_all(): """ This function starts all bots in the database. :return started_bots: List of bot IDs for bots which successfully started polling. """ # Get all non-test (i.e. live) bots. bots = MyBot.objects(test_bot=False).all() started_bots = [] # Start all non test bots registered in the database. for bot in bots: try: if start_bot(botid=bot.bot_id) > 0: started_bots.append(bot.bot_id) except (ValueError, Exception): pass # Skip if some bot is not started. proc_logger.info('Successfully started polling for {count} bots out of ' '{total} live bots registered in the database.'.format( count=len(started_bots), total=len(bots))) return started_bots
class FilteringForm(FlaskForm): """ FlaskForm for setting up form for filtering logged messages. :parameter bot_field: Drop-down list containing all bots in the databases. :parameter time_field: Drop-down list for choosing time for filtering. :parameter time_int_field: Input field for getting time (in minutes) for filtering. :parameter text_field: Input field for entering text for filtering. :parameter username_field: Usernames of all users from which messages were recieved. :parameter name_field: (Partial) name for sender's firstname, lastname. """ bot_field = SelectField( 'Choose Bot', coerce=int, choices=[(0, 'Select an option')] + list(MyBot.objects().all().values_list('bot_id', 'username'))) time_field = SelectField('Time', coerce=int, choices=[(0, 'Choose'), (10, '10 minutes'), (30, '30 minutes'), (60, '60 minutes')]) time_int_field = IntegerField( 'Enter time (in Minutes)', validators=[ NumberRange(0, int(time.time()) / 60, message="Please enter valid time or 0.") ]) text_field = StringField('Text (contains)') username_field = SelectField( 'Sender username', coerce=str, choices=[('#', 'Select')] + list( Message.objects(sender_username__nin=['unknown', '']).values_list( 'sender_username', 'sender_username'))) fn_ln_field = StringField('First name/ Last name (contains)') submit = SubmitField('Filter')
def test_edit_valid_bot(self): base_address = 'http://127.0.0.1:5000/web/index' # navigate to home page self.client.get(base_address) # Navigate to filering page self.client.find_element_by_link_text('Edit-Bot').click() self.assertTrue( re.search('Toggle\s+\(Enable/\s+Disable\)\s+Bot', self.client.page_source, re.IGNORECASE)) # add a test bot self.assertTrue(procedures.add_bot(token=CONSTANTS.LIVE_BOTS.get(1))) bot = MyBot.objects(token=CONSTANTS.LIVE_BOTS.get(1), test_bot=False).first() self.assertIsNotNone(bot) self.assertTrue(bot.state) # self.client.find_elements_by_name('status_field').send_keys('tomato') self.client.find_element_by_name('choose_bot').send_keys( bot.username.lower()) self.client.find_element_by_name('toggle').click() # check for success self.assertTrue('Bot:{uname} successfully stopped polling'.format( uname=bot.username) in self.client.page_source) self.assertTrue('Disabled' in self.client.page_source) # Enable the bot self.client.find_element_by_name('choose_bot').send_keys(bot.username) self.client.find_element_by_name('toggle').click() # check for success self.assertTrue('Bot:{uname} successfully started polling'.format( uname=bot.username) in self.client.page_source) self.assertTrue('Enabled' in self.client.page_source) # Force disable live bot from polling. self.assertEqual(procedures.stop_bot(botid=bot.bot_id), 1)
def test_live_bot_creation(self): MyBot(token=CONSTANTS.LIVE_BOTS.get(1)).save() bot = MyBot.objects(token=CONSTANTS.LIVE_BOTS.get(1)).first() self.assertIsNotNone(bot) self.assertFalse(bot.test_bot) self.assertFalse(bot.state)