コード例 #1
0
 def test_cascade_delete_bot_and_message_by_id_with_valid_botid_and_no_msgs(
         self):
     bot = MyBot(token='dummy-token', username='******').save()
     self.assertIsNotNone(bot)
     response = self.client.delete(url_for(
         'botapi.delete_bot_and_message_by_id', botid=bot.bot_id),
                                   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.assertTrue(bot.username in json_response['message'])
     self.assertEqual(
         json_response['message'], 'Bot:{uname} and {msgs} logged messages '
         'removed'.format(uname=bot.username, msgs=0))
コード例 #2
0
ファイル: forms.py プロジェクト: hafeezibbad/telegram-bot
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)
コード例 #3
0
    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))
コード例 #4
0
 def test_cascade_delete_bot_and_msgs_by_uname_with_messages(self):
     bot = MyBot(token='dummy-token', username='******').save()
     self.assertIsNotNone(bot)
     Message.generate_fake(10)
     response = self.client.delete(url_for(
         'botapi.delete_bot_and_message_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} and {msgs} logged messages '
         'removed'.format(uname=bot.username, msgs=10))
     self.assertEqual(Message.objects.count(), 0)
     self.assertEqual(MyBot.objects.count(), 0)
コード例 #5
0
    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)
コード例 #6
0
 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))
コード例 #7
0
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
コード例 #8
0
ファイル: forms.py プロジェクト: hafeezibbad/telegram-bot
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')
コード例 #9
0
    def test_get_bot_info(self):
        base_address = 'http://127.0.0.1:5000/web/index'
        # Add a special bot and some expected messages.
        bot = MyBot(bot_id=123456,
                    username='******',
                    token='special-dummy-token',
                    first_name='special',
                    last_name='bot').save()
        for i in range(5):
            Message(bot_id=bot.bot_id, text_content='message' + str(i)).save()

        # navigate to home page
        self.client.get(base_address)
        # Navigate to filtering page
        self.client.find_element_by_link_text('Get-Bot-Info').click()
        self.assertTrue(
            re.search('Get Bot Information', self.client.page_source,
                      re.IGNORECASE))

        self.client.find_element_by_name('choose_bot').send_keys(bot.username)
        self.client.find_element_by_name('submit').click()

        # Redirected to bot information page. Make Assertions.
        self.assertTrue(
            re.search(bot.username, self.client.page_source, re.IGNORECASE))
        self.assertTrue(
            re.search(
                '{fname}\s+{lname}'.format(fname=bot.first_name,
                                           lname=bot.last_name),
                self.client.page_source, re.IGNORECASE))
        self.assertTrue(
            re.search('Token:\s+{token}'.format(token=bot.token),
                      self.client.page_source, re.IGNORECASE))
        msgs = Message.objects(bot_id=bot.bot_id).all()
        for msg in msgs:
            self.assertTrue(msg.text_content in self.client.page_source)
コード例 #10
0
    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)
コード例 #11
0
 def tearDown(self):
     # Drop all collections
     MyBot.drop_collection()
     Message.drop_collection()
     self.app_context.pop()
コード例 #12
0
 def test_stop_bot_never_running_live_bot(self):
     bot = MyBot(token=CONSTANTS.LIVE_BOTS.get(1)).save()
     self.assertIsNotNone(bot)
     self.assertEqual(procedures.stop_bot(botid=bot.bot_id), -2)
コード例 #13
0
 def test_stop_bot_for_test_bot(self):
     bot = MyBot(token='dummy-token', test_bot=True).save()
     self.assertIsNotNone(bot)
     self.assertEqual(procedures.stop_bot(botid=bot.bot_id), -2)
コード例 #14
0
def stop_bot(botid=None, username=None):
    """
    This function stops a bot from polling for new message updates.
    :param botid:  ID of the bot for which start polling request is made.
    :param username: Username of the bot for which start polling request is
    made.
    :return Integer: -1 = Bot with requested username/bot ID not found in DB.
    1 = successfully stopped the bot for polling.
    0 = Unable to stop the bot for polling. Internal Error.
    -2 = The requested bot never started polling in the first place.
    """
    if username is None and botid is None:
        raise ValueError('No botid/username provided with stop bot request.')
    elif botid is not None and type(botid) is not int:
        raise ValueError('Integer value expected for stop in start bot '
                         'request.')
    elif username is not None and type(username) is not str:
        raise ValueError('String value expected for username in stop bot '
                         'request.')
    bot = MyBot.objects(bot_id=botid or 0).first() or \
        MyBot.objects(username__iexact=username or '').first()
    if bot is None:
        proc_logger.error('No bot found with ID:{id} or Username:{uname} for '
                          'starting the polling.'.format(id=botid,
                                                         uname=username))
        return -1
    if bot.state:
        try:
            if bot.bot_id in running_bots.keys():
                updater = running_bots.get(bot.bot_id)  # Find bot from dict.
                updater.stop()  # Stop bot
                bot.state = False  # Update bot state to STOP.
                bot.save()
                proc_logger.info(
                    'Successfully stopped polling for live bot with id:{id} '
                    'or username:{uname}'.format(id=botid, uname=username))
                return 1  # Bot stopped successfully.
            else:
                updater = Updater(token=bot.token)  # Get bot Updater
                dispatcher = updater.dispatcher

                start_handler = CommandHandler('start', start)  # Add Handlers.
                dispatcher.add_handler(start_handler)

                log_handler = MessageHandler([Filters.text], log_message)
                dispatcher.add_handler(log_handler)

                updater.stop()  # Start polling.
                running_bots[bot.bot_id] = updater  # Add to dictionary.
                bot.state = False  # Update bot state.
                bot.save()
                proc_logger.info(
                    'Successfully added and started polling for live bot '
                    'with id:{id} or username:{uname}'.format(id=botid,
                                                              uname=username))
                return 1
        except (KeyError, Exception):
            proc_logger.critical('Unable to start polling for bot registered '
                                 'with ID:{id} or username:{uname}.'
                                 ''.format(id=botid, uname=username))
            return 0  # Unable to stop bot.
    proc_logger.error('Cannot start/stop polling for test-bot with ID:{id} '
                      'or username:{uname}'.format(id=botid, uname=username))
    return -2  # Bot not polling already.
コード例 #15
0
def start_bot(botid=None, username=None):
    """
    This function starts polling for a newly added bot. It gets an updater
    object for a valid (i.e. not test) bot and associated dispatcher. It adds
    handlers for responding to /start command and text messages to the
    dispatcher.
    :param botid:  ID of the bot for which start polling request is made.
    :param username: Username of the bot for which start polling request is
    made.
    :return integer: -1 = Unable to find bot with given username/ID in the DB.
    -2 = The requested bot is a testbot, live polling is not available for a
    test bot.
     1 = Successfully started polling for the requested bot.
     0 = Internal error, unable to start polling for the requested bot.
    :except ValueError: If neither Bot ID nor Username is provided.
    """
    if username is None and botid is None:
        raise ValueError('No botid/username provided with start bot request.')
    elif botid is not None and type(botid) is not int:
        raise ValueError('Integer value expected for botid in start bot '
                         'request.')
    elif username is not None and type(username) is not str:
        raise ValueError('String value expected for username in start bot '
                         'request.')
    # Find the requested Bot in database.
    bot = MyBot.objects(bot_id=botid or 0).first() or \
        MyBot.objects(username__iexact=username or '').first()
    if bot is None:  # Requested bot not found in DB.
        proc_logger.error('No bot found with ID:{id} or Username:{uname} for '
                          'starting the polling.'.format(id=botid,
                                                         uname=username))
        return -1
    if bot.test_bot:  # Requested bot is testbot.
        proc_logger.error('Cannot start polling for test-bot with ID:{id} '
                          'or username:{uname}'.format(id=botid,
                                                       uname=username))
        return -2
    if bot.bot_id in running_bots.keys():  # Bot found and previously ran once.
        updater = running_bots.get(bot.bot_id)  # Retrieve updater from dict.
        updater.start_polling()
        bot.state = True
        bot.save()
        proc_logger.info('Successfully started polling for live bot with id:'
                         '{id} or username:{uname}'.format(id=botid,
                                                           uname=username))
        return 1  # Started running requested bot.
    try:
        updater = Updater(token=bot.token)  # Get bot Updater
        dispatcher = updater.dispatcher

        start_handler = CommandHandler('start', start)  # Add Handlers.
        dispatcher.add_handler(start_handler)

        log_handler = MessageHandler([Filters.text], log_message)
        dispatcher.add_handler(log_handler)

        updater.start_polling()  # Start polling.
        running_bots[bot.bot_id] = updater  # Add to dictionary.
        bot.state = True  # Update bot state.
        bot.save()
        proc_logger.info('Successfully added and started polling for live bot '
                         'with id:{id} or username:{uname}'.format(
                             id=botid, uname=username))
        return 1
    except InvalidToken:
        proc_logger.error('Unable to start polling for bot registered with ID:'
                          '{id} or username:{uname}.'.format(id=botid,
                                                             uname=username))
        raise ValueError('Bot:{uname} registered with bad token can not be '
                         'started.'.format(uname=bot.username))
コード例 #16
0
 def test_generate_fake_message(self):
     MyBot.generate_fake(1)  # Generate a fake bot to associate messages.
     Message.generate_fake(10)
     msgs = Message.objects.all()
     self.assertEqual(len(msgs), 10)
コード例 #17
0
 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)
コード例 #18
0
def edit_bot(bot_choice=0):
    """
    This function renders the page for Editing the bot. Editing the bot
    allows to enable/disable polling of the bot.
    :param bot_choice: Initial choice for selected bot.
    :return: .../editbot
    """
    form = EditBot(choose_bot=bot_choice, toggle='Toggle (Enable/Disable)')

    # Populate the initial set of choices for Bot DropDownList.
    form.choose_bot.choices = [(0, 'Select')] + \
                              list(MyBot.objects().values_list(
                                  'username', 'username'))

    if form.validate_on_submit():
        # Get list of bots
        bot = MyBot.objects(username__iexact=form.choose_bot.data).first()
        if bot is None:
            # Redirect to same page because no option selected.
            flash('Please select an option and then press submit.')
            return render_template('edit_bot.html', form=form)
        if bot.test_bot:
            # Redirect to same page because testbot cannot be started.
            web_logger.info('Attempt to start polling for a test bot bot:'
                            '{uname} via web api.'.format(uname=bot.username))
            flash('Testbot Bot:{username} attempt to start polling '
                  'failed.'.format(username=bot.username))
            form.status_field.data = 'Cannot be enabled.'
            return render_template('edit_bot.html', form=form)
        if not bot.state:
            # Bot is not polling currently, start polling.
            status = procedures.start_bot(botid=bot.bot_id,
                                          username=str(bot.username))
            if status == 1:
                web_logger.info('Bot:{uname} successfully started polling via '
                                'web api.'.format(uname=bot.username))
                flash('Bot:{username} successfully started polling.'.format(
                    username=bot.username))
                form.status_field.data = 'Enabled'
            elif status == 0:
                web_logger.info('Bot:{uname} could not start polling via '
                                'web api.'.format(uname=bot.username))
                flash('Failed to enable Bot:{username} for polling'.format(
                    username=bot.username))
                form.status_field.data = 'Failed to enable.'
                form.toggle = 'Enable'
        elif bot.state:
            # Bot is polling currently, stop polling.
            status = procedures.stop_bot(botid=bot.bot_id,
                                         username=str(bot.username))
            if status == 1:
                web_logger.info('Bot:{uname} successfully stopped polling via '
                                'web api.'.format(uname=bot.username))
                flash('Bot:{username} successfully stopped polling.'.format(
                    username=bot.username))
                form.status_field.data = 'Disabled'
            elif status == 0:
                web_logger.info('Bot:{uname} could not stop polling via '
                                'web api.'.format(uname=bot.username))
                flash('Failed to disable Bot:{username} for polling'.format(
                    username=bot.username))
                form.status_field.data = 'Failed to disable.'
        return render_template('edit_bot.html', form=form)
    # Responding to get Request
    return render_template('edit_bot.html', form=form)