Exemplo n.º 1
0
    def test_error_handler(self):
        class CallbackContext(object):
            error = "error msg"

        self.assertIsNone(error_callback(Update("0"), CallbackContext()))
Exemplo n.º 2
0
def callback_query(bot):
    return Update(0,
                  callback_query=CallbackQuery(2,
                                               User(1, '', False),
                                               None,
                                               data='test data'))
Exemplo n.º 3
0
def false_update(request):
    return Update(update_id=2, **request.param)
Exemplo n.º 4
0
class TestDispatcher(object):
    message_update = Update(1,
                            message=Message(1,
                                            User(1, '', False),
                                            None,
                                            Chat(1, ''),
                                            text='Text'))
    received = None
    count = 0

    @pytest.fixture(autouse=True, name='reset')
    def reset_fixture(self):
        self.reset()

    def reset(self):
        self.received = None
        self.count = 0

    def error_handler(self, bot, update, error):
        self.received = error.message

    def error_handler_raise_error(self, bot, update, error):
        raise Exception('Failing bigly')

    def callback_increase_count(self, bot, update):
        self.count += 1

    def callback_set_count(self, count):
        def callback(bot, update):
            self.count = count

        return callback

    def callback_raise_error(self, bot, update):
        raise TelegramError(update.message.text)

    def callback_if_not_update_queue(self, bot, update, update_queue=None):
        if update_queue is not None:
            self.received = update.message

    def callback_context(self, update, context):
        if (isinstance(context, CallbackContext)
                and isinstance(context.bot, Bot)
                and isinstance(context.update_queue, Queue)
                and isinstance(context.job_queue, JobQueue)
                and isinstance(context.error, TelegramError)):
            self.received = context.error.message

    def test_one_context_per_update(self, cdp):
        def one(update, context):
            if update.message.text == 'test':
                context.my_flag = True

        def two(update, context):
            if update.message.text == 'test':
                if not hasattr(context, 'my_flag'):
                    pytest.fail()
            else:
                if hasattr(context, 'my_flag'):
                    pytest.fail()

        cdp.add_handler(MessageHandler(Filters.regex('test'), one), group=1)
        cdp.add_handler(MessageHandler(None, two), group=2)
        u = Update(1, Message(1, None, None, None, text='test'))
        cdp.process_update(u)
        u.message.text = 'something'
        cdp.process_update(u)

    def test_error_handler(self, dp):
        dp.add_error_handler(self.error_handler)
        error = TelegramError('Unauthorized.')
        dp.update_queue.put(error)
        sleep(.1)
        assert self.received == 'Unauthorized.'

        # Remove handler
        dp.remove_error_handler(self.error_handler)
        self.reset()

        dp.update_queue.put(error)
        sleep(.1)
        assert self.received is None

    def test_construction_with_bad_persistence(self, caplog, bot):
        class my_per:
            def __init__(self):
                self.store_user_data = False
                self.store_chat_data = False
                self.store_bot_data = False

        with pytest.raises(
                TypeError,
                match=
                'persistence should be based on telegram.ext.BasePersistence'):
            Dispatcher(bot, None, persistence=my_per())

    def test_error_handler_that_raises_errors(self, dp):
        """
        Make sure that errors raised in error handlers don't break the main loop of the dispatcher
        """
        handler_raise_error = MessageHandler(Filters.all,
                                             self.callback_raise_error)
        handler_increase_count = MessageHandler(Filters.all,
                                                self.callback_increase_count)
        error = TelegramError('Unauthorized.')

        dp.add_error_handler(self.error_handler_raise_error)

        # From errors caused by handlers
        dp.add_handler(handler_raise_error)
        dp.update_queue.put(self.message_update)
        sleep(.1)

        # From errors in the update_queue
        dp.remove_handler(handler_raise_error)
        dp.add_handler(handler_increase_count)
        dp.update_queue.put(error)
        dp.update_queue.put(self.message_update)
        sleep(.1)

        assert self.count == 1

    def test_run_async_multiple(self, bot, dp, dp2):
        def get_dispatcher_name(q):
            q.put(current_thread().name)

        q1 = Queue()
        q2 = Queue()

        dp.run_async(get_dispatcher_name, q1)
        dp2.run_async(get_dispatcher_name, q2)

        sleep(.1)

        name1 = q1.get()
        name2 = q2.get()

        assert name1 != name2

    def test_multiple_run_async_decorator(self, dp, dp2):
        # Make sure we got two dispatchers and that they are not the same
        assert isinstance(dp, Dispatcher)
        assert isinstance(dp2, Dispatcher)
        assert dp is not dp2

        @run_async
        def must_raise_runtime_error():
            pass

        with pytest.raises(RuntimeError):
            must_raise_runtime_error()

    def test_run_async_with_args(self, dp):
        dp.add_handler(
            MessageHandler(Filters.all,
                           run_async(self.callback_if_not_update_queue),
                           pass_update_queue=True))

        dp.update_queue.put(self.message_update)
        sleep(.1)
        assert self.received == self.message_update.message

    def test_error_in_handler(self, dp):
        dp.add_handler(MessageHandler(Filters.all, self.callback_raise_error))
        dp.add_error_handler(self.error_handler)

        dp.update_queue.put(self.message_update)
        sleep(.1)
        assert self.received == self.message_update.message.text

    def test_add_remove_handler(self, dp):
        handler = MessageHandler(Filters.all, self.callback_increase_count)
        dp.add_handler(handler)
        dp.update_queue.put(self.message_update)
        sleep(.1)
        assert self.count == 1
        dp.remove_handler(handler)
        dp.update_queue.put(self.message_update)
        assert self.count == 1

    def test_add_remove_handler_non_default_group(self, dp):
        handler = MessageHandler(Filters.all, self.callback_increase_count)
        dp.add_handler(handler, group=2)
        with pytest.raises(KeyError):
            dp.remove_handler(handler)
        dp.remove_handler(handler, group=2)

    def test_error_start_twice(self, dp):
        assert dp.running
        dp.start()

    def test_handler_order_in_group(self, dp):
        dp.add_handler(
            MessageHandler(Filters.photo, self.callback_set_count(1)))
        dp.add_handler(MessageHandler(Filters.all, self.callback_set_count(2)))
        dp.add_handler(MessageHandler(Filters.text,
                                      self.callback_set_count(3)))
        dp.update_queue.put(self.message_update)
        sleep(.1)
        assert self.count == 2

    def test_groups(self, dp):
        dp.add_handler(
            MessageHandler(Filters.all, self.callback_increase_count))
        dp.add_handler(MessageHandler(Filters.all,
                                      self.callback_increase_count),
                       group=2)
        dp.add_handler(MessageHandler(Filters.all,
                                      self.callback_increase_count),
                       group=-1)

        dp.update_queue.put(self.message_update)
        sleep(.1)
        assert self.count == 3

    def test_add_handler_errors(self, dp):
        handler = 'not a handler'
        with pytest.raises(TypeError, match='handler is not an instance of'):
            dp.add_handler(handler)

        handler = MessageHandler(Filters.photo, self.callback_set_count(1))
        with pytest.raises(TypeError, match='group is not int'):
            dp.add_handler(handler, 'one')

    def test_flow_stop(self, dp, bot):
        passed = []

        def start1(b, u):
            passed.append('start1')
            raise DispatcherHandlerStop

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)

        update = Update(1,
                        message=Message(1,
                                        None,
                                        None,
                                        None,
                                        text='/start',
                                        entities=[
                                            MessageEntity(
                                                type=MessageEntity.BOT_COMMAND,
                                                offset=0,
                                                length=len('/start'))
                                        ],
                                        bot=bot))

        # If Stop raised handlers in other groups should not be called.
        passed = []
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start3), 1)
        dp.add_handler(CommandHandler('start', start2), 2)
        dp.process_update(update)
        assert passed == ['start1']

    def test_exception_in_handler(self, dp, bot):
        passed = []
        err = Exception('General exception')

        def start1(b, u):
            passed.append('start1')
            raise err

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)

        update = Update(1,
                        message=Message(1,
                                        None,
                                        None,
                                        None,
                                        text='/start',
                                        entities=[
                                            MessageEntity(
                                                type=MessageEntity.BOT_COMMAND,
                                                offset=0,
                                                length=len('/start'))
                                        ],
                                        bot=bot))

        # If an unhandled exception was caught, no further handlers from the same group should be
        # called. Also, the error handler should be called and receive the exception
        passed = []
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start2), 1)
        dp.add_handler(CommandHandler('start', start3), 2)
        dp.add_error_handler(error)
        dp.process_update(update)
        assert passed == ['start1', 'error', err, 'start3']

    def test_telegram_error_in_handler(self, dp, bot):
        passed = []
        err = TelegramError('Telegram error')

        def start1(b, u):
            passed.append('start1')
            raise err

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)

        update = Update(1,
                        message=Message(1,
                                        None,
                                        None,
                                        None,
                                        text='/start',
                                        entities=[
                                            MessageEntity(
                                                type=MessageEntity.BOT_COMMAND,
                                                offset=0,
                                                length=len('/start'))
                                        ],
                                        bot=bot))

        # If a TelegramException was caught, an error handler should be called and no further
        # handlers from the same group should be called.
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start2), 1)
        dp.add_handler(CommandHandler('start', start3), 2)
        dp.add_error_handler(error)
        dp.process_update(update)
        assert passed == ['start1', 'error', err, 'start3']
        assert passed[2] is err

    def test_error_while_saving_chat_data(self, dp, bot):
        increment = []

        class OwnPersistence(BasePersistence):
            def __init__(self):
                super(BasePersistence, self).__init__()
                self.store_user_data = True
                self.store_chat_data = True
                self.store_bot_data = True

            def get_bot_data(self):
                return dict()

            def update_bot_data(self, data):
                raise Exception

            def get_chat_data(self):
                return defaultdict(dict)

            def update_chat_data(self, chat_id, data):
                raise Exception

            def get_user_data(self):
                return defaultdict(dict)

            def update_user_data(self, user_id, data):
                raise Exception

        def start1(b, u):
            pass

        def error(b, u, e):
            increment.append("error")

        # If updating a user_data or chat_data from a persistence object throws an error,
        # the error handler should catch it

        update = Update(1,
                        message=Message(1,
                                        User(1, "Test", False),
                                        None,
                                        Chat(1, "lala"),
                                        text='/start',
                                        entities=[
                                            MessageEntity(
                                                type=MessageEntity.BOT_COMMAND,
                                                offset=0,
                                                length=len('/start'))
                                        ],
                                        bot=bot))
        my_persistence = OwnPersistence()
        dp = Dispatcher(bot, None, persistence=my_persistence)
        dp.add_handler(CommandHandler('start', start1))
        dp.add_error_handler(error)
        dp.process_update(update)
        assert increment == ["error", "error", "error"]

    def test_flow_stop_in_error_handler(self, dp, bot):
        passed = []
        err = TelegramError('Telegram error')

        def start1(b, u):
            passed.append('start1')
            raise err

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)
            raise DispatcherHandlerStop

        update = Update(1,
                        message=Message(1,
                                        None,
                                        None,
                                        None,
                                        text='/start',
                                        entities=[
                                            MessageEntity(
                                                type=MessageEntity.BOT_COMMAND,
                                                offset=0,
                                                length=len('/start'))
                                        ],
                                        bot=bot))

        # If a TelegramException was caught, an error handler should be called and no further
        # handlers from the same group should be called.
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start2), 1)
        dp.add_handler(CommandHandler('start', start3), 2)
        dp.add_error_handler(error)
        dp.process_update(update)
        assert passed == ['start1', 'error', err]
        assert passed[2] is err

    def test_error_handler_context(self, cdp):
        cdp.add_error_handler(self.callback_context)

        error = TelegramError('Unauthorized.')
        cdp.update_queue.put(error)
        sleep(.1)
        assert self.received == 'Unauthorized.'

    def test_sensible_worker_thread_names(self, dp2):
        thread_names = [
            thread.name
            for thread in getattr(dp2, '_Dispatcher__async_threads')
        ]
        print(thread_names)
        for thread_name in thread_names:
            assert thread_name.startswith("Bot:{}:worker:".format(dp2.bot.id))

    @pytest.mark.skipif(sys.version_info < (3, 0),
                        reason='pytest fails this for no reason')
    def test_non_context_deprecation(self, dp):
        with pytest.warns(TelegramDeprecationWarning):
            Dispatcher(dp.bot,
                       dp.update_queue,
                       job_queue=dp.job_queue,
                       workers=0,
                       use_context=False)
def update():
    return Update(
        0,
        Message(0, User(0, 'Testuser', False), datetime.datetime.utcnow(),
                Chat(0, 'private')))
Exemplo n.º 6
0
def check_rise_fall_day(context: CallbackContext) -> NoReturn:
    chat_data = context.job.context.dispatcher.chat_data
    datetime_now = datetime.now()
    date_now = datetime_now.date()
    datetime_zero = datetime.fromtimestamp(0)

    for c_id, cd in chat_data.items():
        stonks = cd.get(conf.INTERNALS['stock'], {})
        chat_custom = Chat(c_id, 'group')
        message_custom = Message(0, datetime_now, chat=chat_custom)
        update_custom = Update(0, message=message_custom)
        msg_daily = get_daily_dict(cd)
        daily_rise = msg_daily[conf.JOBS['check_rise_fall_day']['dict']
                               ['rise']]
        daily_fall = msg_daily[conf.JOBS['check_rise_fall_day']['dict']
                               ['fall']]

        for symbol, stonk in stonks.items():
            msg_last_rise_at = daily_rise.get(symbol, datetime_zero).date()
            msg_last_fall_at = daily_fall.get(symbol, datetime_zero).date()
            context.args = [symbol]

            if msg_last_rise_at == date_now and msg_last_fall_at == date_now:
                continue

            res_calc = stonk.calculate_perf_rise_fall_daily()
            to_send_message = []

            if res_calc:
                if stonk.daily_rise.calculated_at.date(
                ) == date_now and msg_last_rise_at < date_now:
                    if stonk.daily_rise.percent >= conf.JOBS[
                            'check_rise_fall_day']['threshold_perc_rise']:
                        text = f"🚀🚀🚀 {stonk.name} ({stonk.symbol}) is rocketing to " \
                               f"{round_currency_scalar(stonk.daily_rise.price)} " \
                               f"{conf.LOCAL['currency']} (+{stonk.daily_rise.percent.round(2)}%)"
                        to_send_message.append(text)
                        daily_rise[symbol] = datetime_now

                if stonk.daily_fall.calculated_at.date(
                ) == date_now and msg_last_fall_at < date_now:
                    if stonk.daily_fall.percent <= conf.JOBS[
                            'check_rise_fall_day']['threshold_perc_fall']:
                        text = f"📉📉📉 {stonk.name} ({stonk.symbol}) is drow" \
                               f"ning to {round_currency_scalar(stonk.daily_fall.price)} " \
                               f"{conf.LOCAL['currency']} ({stonk.daily_fall.percent.round(2)}%)"
                        to_send_message.append(text)
                        daily_fall[symbol] = datetime_now

                for message in to_send_message:
                    try:
                        send_message(context, c_id, message)
                        chart(update_custom,
                              context,
                              reply=False,
                              symbols=[stonk.symbol])
                    except error.Unauthorized:
                        error_message = f'Rise/Fall check: User ID {c_id} blocked our bot. Thus, this user was will ' \
                                        f'be removed from chat_data.'
                        error_handler(update_custom, context, error_message)

                        del context.job.context.dispatcher.chat_data[c_id]

                        break
Exemplo n.º 7
0
def update():
    _update = Update(0)
    _update.message = Message(0, 0, datetime.utcnow(), Chat(0, 0))
    return _update
class TestDispatcher(object):
    message_update = Update(1,
                            message=Message(1, User(1, '', False), None, Chat(1, ''), text='Text'))
    received = None
    count = 0

    @pytest.fixture(autouse=True)
    def reset(self):
        self.received = None
        self.count = 0

    def error_handler(self, bot, update, error):
        self.received = error.message

    def error_handler_raise_error(self, bot, update, error):
        raise Exception('Failing bigly')

    def callback_increase_count(self, bot, update):
        self.count += 1

    def callback_set_count(self, count):
        def callback(bot, update):
            self.count = count

        return callback

    def callback_raise_error(self, bot, update):
        raise TelegramError(update.message.text)

    def callback_if_not_update_queue(self, bot, update, update_queue=None):
        if update_queue is not None:
            self.received = update.message

    def callback_context(self, update, context):
        if (isinstance(context, CallbackContext) and
                isinstance(context.bot, Bot) and
                isinstance(context.update_queue, Queue) and
                isinstance(context.job_queue, JobQueue) and
                isinstance(context.error, TelegramError)):
            self.received = context.error.message

    def test_error_handler(self, dp):
        dp.add_error_handler(self.error_handler)
        error = TelegramError('Unauthorized.')
        dp.update_queue.put(error)
        sleep(.1)
        assert self.received == 'Unauthorized.'

        # Remove handler
        dp.remove_error_handler(self.error_handler)
        self.reset()

        dp.update_queue.put(error)
        sleep(.1)
        assert self.received is None

    def test_error_handler_that_raises_errors(self, dp):
        """
        Make sure that errors raised in error handlers don't break the main loop of the dispatcher
        """
        handler_raise_error = MessageHandler(Filters.all, self.callback_raise_error)
        handler_increase_count = MessageHandler(Filters.all, self.callback_increase_count)
        error = TelegramError('Unauthorized.')

        dp.add_error_handler(self.error_handler_raise_error)

        # From errors caused by handlers
        dp.add_handler(handler_raise_error)
        dp.update_queue.put(self.message_update)
        sleep(.1)

        # From errors in the update_queue
        dp.remove_handler(handler_raise_error)
        dp.add_handler(handler_increase_count)
        dp.update_queue.put(error)
        dp.update_queue.put(self.message_update)
        sleep(.1)

        assert self.count == 1

    def test_run_async_multiple(self, bot, dp, dp2):
        def get_dispatcher_name(q):
            q.put(current_thread().name)

        q1 = Queue()
        q2 = Queue()

        dp.run_async(get_dispatcher_name, q1)
        dp2.run_async(get_dispatcher_name, q2)

        sleep(.1)

        name1 = q1.get()
        name2 = q2.get()

        assert name1 != name2

    def test_multiple_run_async_decorator(self, dp, dp2):
        # Make sure we got two dispatchers and that they are not the same
        assert isinstance(dp, Dispatcher)
        assert isinstance(dp2, Dispatcher)
        assert dp is not dp2

        @run_async
        def must_raise_runtime_error():
            pass

        with pytest.raises(RuntimeError):
            must_raise_runtime_error()

    def test_run_async_with_args(self, dp):
        dp.add_handler(MessageHandler(Filters.all,
                                      run_async(self.callback_if_not_update_queue),
                                      pass_update_queue=True))

        dp.update_queue.put(self.message_update)
        sleep(.1)
        assert self.received == self.message_update.message

    def test_error_in_handler(self, dp):
        dp.add_handler(MessageHandler(Filters.all, self.callback_raise_error))
        dp.add_error_handler(self.error_handler)

        dp.update_queue.put(self.message_update)
        sleep(.1)
        assert self.received == self.message_update.message.text

    def test_add_remove_handler(self, dp):
        handler = MessageHandler(Filters.all, self.callback_increase_count)
        dp.add_handler(handler)
        dp.update_queue.put(self.message_update)
        sleep(.1)
        assert self.count == 1
        dp.remove_handler(handler)
        dp.update_queue.put(self.message_update)
        assert self.count == 1

    def test_add_remove_handler_non_default_group(self, dp):
        handler = MessageHandler(Filters.all, self.callback_increase_count)
        dp.add_handler(handler, group=2)
        with pytest.raises(KeyError):
            dp.remove_handler(handler)
        dp.remove_handler(handler, group=2)

    def test_error_start_twice(self, dp):
        assert dp.running
        dp.start()

    def test_handler_order_in_group(self, dp):
        dp.add_handler(MessageHandler(Filters.photo, self.callback_set_count(1)))
        dp.add_handler(MessageHandler(Filters.all, self.callback_set_count(2)))
        dp.add_handler(MessageHandler(Filters.text, self.callback_set_count(3)))
        dp.update_queue.put(self.message_update)
        sleep(.1)
        assert self.count == 2

    def test_groups(self, dp):
        dp.add_handler(MessageHandler(Filters.all, self.callback_increase_count))
        dp.add_handler(MessageHandler(Filters.all, self.callback_increase_count), group=2)
        dp.add_handler(MessageHandler(Filters.all, self.callback_increase_count), group=-1)

        dp.update_queue.put(self.message_update)
        sleep(.1)
        assert self.count == 3

    def test_add_handler_errors(self, dp):
        handler = 'not a handler'
        with pytest.raises(TypeError, match='handler is not an instance of'):
            dp.add_handler(handler)

        handler = MessageHandler(Filters.photo, self.callback_set_count(1))
        with pytest.raises(TypeError, match='group is not int'):
            dp.add_handler(handler, 'one')

    def test_flow_stop(self, dp, bot):
        passed = []

        def start1(b, u):
            passed.append('start1')
            raise DispatcherHandlerStop

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)

        update = Update(1, message=Message(1, None, None, None, text='/start', bot=bot))

        # If Stop raised handlers in other groups should not be called.
        passed = []
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start3), 1)
        dp.add_handler(CommandHandler('start', start2), 2)
        dp.process_update(update)
        assert passed == ['start1']

    def test_exception_in_handler(self, dp, bot):
        passed = []

        def start1(b, u):
            passed.append('start1')
            raise Exception('General exception')

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)

        update = Update(1, message=Message(1, None, None, None, text='/start', bot=bot))

        # If an unhandled exception was caught, no further handlers from the same group should be
        # called.
        passed = []
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start2), 1)
        dp.add_handler(CommandHandler('start', start3), 2)
        dp.add_error_handler(error)
        dp.process_update(update)
        assert passed == ['start1', 'start3']

    def test_telegram_error_in_handler(self, dp, bot):
        passed = []
        err = TelegramError('Telegram error')

        def start1(b, u):
            passed.append('start1')
            raise err

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)

        update = Update(1, message=Message(1, None, None, None, text='/start', bot=bot))

        # If a TelegramException was caught, an error handler should be called and no further
        # handlers from the same group should be called.
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start2), 1)
        dp.add_handler(CommandHandler('start', start3), 2)
        dp.add_error_handler(error)
        dp.process_update(update)
        assert passed == ['start1', 'error', err, 'start3']
        assert passed[2] is err

    def test_flow_stop_in_error_handler(self, dp, bot):
        passed = []
        err = TelegramError('Telegram error')

        def start1(b, u):
            passed.append('start1')
            raise err

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)
            raise DispatcherHandlerStop

        update = Update(1, message=Message(1, None, None, None, text='/start', bot=bot))

        # If a TelegramException was caught, an error handler should be called and no further
        # handlers from the same group should be called.
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start2), 1)
        dp.add_handler(CommandHandler('start', start3), 2)
        dp.add_error_handler(error)
        dp.process_update(update)
        assert passed == ['start1', 'error', err]
        assert passed[2] is err

    def test_error_handler_context(self, cdp):
        cdp.add_error_handler(self.callback_context)

        error = TelegramError('Unauthorized.')
        cdp.update_queue.put(error)
        sleep(.1)
        assert self.received == 'Unauthorized.'

    @pytest.mark.skipif(sys.version_info < (3, 0), reason='pytest fails this for no reason')
    def test_non_context_deprecation(self, dp):
        with pytest.warns(TelegramDeprecationWarning):
            Dispatcher(dp.bot, dp.update_queue, job_queue=dp.job_queue, workers=0,
                       use_context=False)
Exemplo n.º 9
0
def callback_query(bot):
    return Update(0,
                  callback_query=CallbackQuery(2, None, None,
                                               data='test data'))
def shiping_query():
    return Update(1, shipping_query=ShippingQuery(42, User(1, 'test user', False), 'invoice_payload',
                                                  ShippingAddress('EN', 'my_state', 'my_city',
                                                                  'steer_1', '', 'post_code')))
Exemplo n.º 11
0
    def test_context(self, cdp, prefixmessage):
        handler = PrefixHandler(['!', '#', 'mytrig-'], ['help', 'test'], self.callback_context)
        cdp.add_handler(handler)

        cdp.process_update(Update(0, prefixmessage))
        assert self.test_flag
Exemplo n.º 12
0
def update(bot):
    user = User(id=321, first_name='test_user', is_bot=False)
    chat = Chat(id=123, type='group')
    message = Message(1, user, None, chat, text="Hi there", bot=bot)
    return Update(0, message=message)
Exemplo n.º 13
0
    def test_dispatcher_integration_handlers(self, caplog, bot,
                                             base_persistence, chat_data,
                                             user_data):
        def get_user_data():
            return user_data

        def get_chat_data():
            return chat_data

        base_persistence.get_user_data = get_user_data
        base_persistence.get_chat_data = get_chat_data
        # base_persistence.update_chat_data = lambda x: x
        # base_persistence.update_user_data = lambda x: x
        updater = Updater(bot=bot,
                          persistence=base_persistence,
                          use_context=True)
        dp = updater.dispatcher

        def callback_known_user(update, context):
            if not context.user_data['test1'] == 'test2':
                pytest.fail('user_data corrupt')

        def callback_known_chat(update, context):
            if not context.chat_data['test3'] == 'test4':
                pytest.fail('chat_data corrupt')

        def callback_unknown_user_or_chat(update, context):
            if not context.user_data == {}:
                pytest.fail('user_data corrupt')
            if not context.chat_data == {}:
                pytest.fail('chat_data corrupt')
            context.user_data[1] = 'test7'
            context.chat_data[2] = 'test8'

        known_user = MessageHandler(Filters.user(user_id=12345),
                                    callback_known_user,
                                    pass_chat_data=True,
                                    pass_user_data=True)
        known_chat = MessageHandler(Filters.chat(chat_id=-67890),
                                    callback_known_chat,
                                    pass_chat_data=True,
                                    pass_user_data=True)
        unknown = MessageHandler(Filters.all,
                                 callback_unknown_user_or_chat,
                                 pass_chat_data=True,
                                 pass_user_data=True)
        dp.add_handler(known_user)
        dp.add_handler(known_chat)
        dp.add_handler(unknown)
        user1 = User(id=12345, first_name='test user', is_bot=False)
        user2 = User(id=54321, first_name='test user', is_bot=False)
        chat1 = Chat(id=-67890, type='group')
        chat2 = Chat(id=-987654, type='group')
        m = Message(1, user1, None, chat2)
        u = Update(0, m)
        with caplog.at_level(logging.ERROR):
            dp.process_update(u)
        rec = caplog.records[-1]
        assert rec.msg == 'No error handlers are registered, logging exception.'
        assert rec.levelname == 'ERROR'
        rec = caplog.records[-2]
        assert rec.msg == 'No error handlers are registered, logging exception.'
        assert rec.levelname == 'ERROR'
        m.from_user = user2
        m.chat = chat1
        u = Update(1, m)
        dp.process_update(u)
        m.chat = chat2
        u = Update(2, m)

        def save_chat_data(data):
            if -987654 not in data:
                pytest.fail()

        def save_user_data(data):
            if 54321 not in data:
                pytest.fail()

        base_persistence.update_chat_data = save_chat_data
        base_persistence.update_user_data = save_user_data
        dp.process_update(u)

        assert dp.user_data[54321][1] == 'test7'
        assert dp.chat_data[-987654][2] == 'test8'
Exemplo n.º 14
0
def chat_join_request_update(bot, chat_join_request):
    return Update(0, chat_join_request=chat_join_request)
Exemplo n.º 15
0
def chat_update(chat_message):
    return Update(update_id=2, message=chat_message)
Exemplo n.º 16
0
 def setUp(self):
     self.update = Update(0)
     self.update.message = Message(0, 0, datetime.utcnow(), Chat(0, 0))
Exemplo n.º 17
0
def pre_checkout_query():
    return Update(
        1,
        pre_checkout_query=PreCheckoutQuery('id', User(1, 'test user', False),
                                            'EUR', 223, 'invoice_payload'),
    )
Exemplo n.º 18
0
class TestDispatcher:
    message_update = Update(1,
                            message=Message(1,
                                            None,
                                            Chat(1, ''),
                                            from_user=User(1, '', False),
                                            text='Text'))
    received = None
    count = 0

    @pytest.fixture(autouse=True, name='reset')
    def reset_fixture(self):
        self.reset()

    def reset(self):
        self.received = None
        self.count = 0

    def error_handler(self, bot, update, error):
        self.received = error.message

    def error_handler_context(self, update, context):
        self.received = context.error.message

    def error_handler_raise_error(self, bot, update, error):
        raise Exception('Failing bigly')

    def callback_increase_count(self, bot, update):
        self.count += 1

    def callback_set_count(self, count):
        def callback(bot, update):
            self.count = count

        return callback

    def callback_raise_error(self, bot, update):
        if isinstance(bot, Bot):
            raise TelegramError(update.message.text)
        raise TelegramError(bot.message.text)

    def callback_if_not_update_queue(self, bot, update, update_queue=None):
        if update_queue is not None:
            self.received = update.message

    def callback_context(self, update, context):
        if (isinstance(context, CallbackContext)
                and isinstance(context.bot, Bot)
                and isinstance(context.update_queue, Queue)
                and isinstance(context.job_queue, JobQueue)
                and isinstance(context.error, TelegramError)):
            self.received = context.error.message

    def test_one_context_per_update(self, cdp):
        def one(update, context):
            if update.message.text == 'test':
                context.my_flag = True

        def two(update, context):
            if update.message.text == 'test':
                if not hasattr(context, 'my_flag'):
                    pytest.fail()
            else:
                if hasattr(context, 'my_flag'):
                    pytest.fail()

        cdp.add_handler(MessageHandler(Filters.regex('test'), one), group=1)
        cdp.add_handler(MessageHandler(None, two), group=2)
        u = Update(1, Message(1, None, None, None, text='test'))
        cdp.process_update(u)
        u.message.text = 'something'
        cdp.process_update(u)

    def test_error_handler(self, dp):
        dp.add_error_handler(self.error_handler)
        error = TelegramError('Unauthorized.')
        dp.update_queue.put(error)
        sleep(0.1)
        assert self.received == 'Unauthorized.'

        # Remove handler
        dp.remove_error_handler(self.error_handler)
        self.reset()

        dp.update_queue.put(error)
        sleep(0.1)
        assert self.received is None

    def test_double_add_error_handler(self, dp, caplog):
        dp.add_error_handler(self.error_handler)
        with caplog.at_level(logging.DEBUG):
            dp.add_error_handler(self.error_handler)
            assert len(caplog.records) == 1
            assert caplog.records[-1].getMessage().startswith(
                'The callback is already registered')

    def test_construction_with_bad_persistence(self, caplog, bot):
        class my_per:
            def __init__(self):
                self.store_user_data = False
                self.store_chat_data = False
                self.store_bot_data = False

        with pytest.raises(
                TypeError,
                match=
                'persistence must be based on telegram.ext.BasePersistence'):
            Dispatcher(bot, None, persistence=my_per())

    def test_error_handler_that_raises_errors(self, dp):
        """
        Make sure that errors raised in error handlers don't break the main loop of the dispatcher
        """
        handler_raise_error = MessageHandler(Filters.all,
                                             self.callback_raise_error)
        handler_increase_count = MessageHandler(Filters.all,
                                                self.callback_increase_count)
        error = TelegramError('Unauthorized.')

        dp.add_error_handler(self.error_handler_raise_error)

        # From errors caused by handlers
        dp.add_handler(handler_raise_error)
        dp.update_queue.put(self.message_update)
        sleep(0.1)

        # From errors in the update_queue
        dp.remove_handler(handler_raise_error)
        dp.add_handler(handler_increase_count)
        dp.update_queue.put(error)
        dp.update_queue.put(self.message_update)
        sleep(0.1)

        assert self.count == 1

    @pytest.mark.parametrize(['run_async', 'expected_output'], [(True, 5),
                                                                (False, 0)])
    def test_default_run_async_error_handler(self, dp, monkeypatch, run_async,
                                             expected_output):
        def mock_async_err_handler(*args, **kwargs):
            self.count = 5

        # set defaults value to dp.bot
        dp.bot.defaults = Defaults(run_async=run_async)
        try:
            dp.add_handler(
                MessageHandler(Filters.all, self.callback_raise_error))
            dp.add_error_handler(self.error_handler)

            monkeypatch.setattr(dp, 'run_async', mock_async_err_handler)
            dp.process_update(self.message_update)

            assert self.count == expected_output

        finally:
            # reset dp.bot.defaults values
            dp.bot.defaults = None

    @pytest.mark.parametrize(['run_async', 'expected_output'],
                             [(True, 'running async'), (False, None)])
    def test_default_run_async(self, monkeypatch, dp, run_async,
                               expected_output):
        def mock_run_async(*args, **kwargs):
            self.received = 'running async'

        # set defaults value to dp.bot
        dp.bot.defaults = Defaults(run_async=run_async)
        try:
            dp.add_handler(MessageHandler(Filters.all, lambda u, c: None))
            monkeypatch.setattr(dp, 'run_async', mock_run_async)
            dp.process_update(self.message_update)
            assert self.received == expected_output

        finally:
            # reset defaults value
            dp.bot.defaults = None

    def test_run_async_multiple(self, bot, dp, dp2):
        def get_dispatcher_name(q):
            q.put(current_thread().name)

        q1 = Queue()
        q2 = Queue()

        dp.run_async(get_dispatcher_name, q1)
        dp2.run_async(get_dispatcher_name, q2)

        sleep(0.1)

        name1 = q1.get()
        name2 = q2.get()

        assert name1 != name2

    def test_multiple_run_async_decorator(self, dp, dp2):
        # Make sure we got two dispatchers and that they are not the same
        assert isinstance(dp, Dispatcher)
        assert isinstance(dp2, Dispatcher)
        assert dp is not dp2

        @run_async
        def must_raise_runtime_error():
            pass

        with pytest.raises(RuntimeError):
            must_raise_runtime_error()

    def test_run_async_with_args(self, dp):
        dp.add_handler(
            MessageHandler(Filters.all,
                           run_async(self.callback_if_not_update_queue),
                           pass_update_queue=True))

        dp.update_queue.put(self.message_update)
        sleep(0.1)
        assert self.received == self.message_update.message

    def test_multiple_run_async_deprecation(self, dp):
        assert isinstance(dp, Dispatcher)

        @run_async
        def callback(update, context):
            pass

        dp.add_handler(MessageHandler(Filters.all, callback))

        with pytest.warns(TelegramDeprecationWarning,
                          match='@run_async decorator'):
            dp.process_update(self.message_update)

    def test_async_raises_dispatcher_handler_stop(self, dp, caplog):
        @run_async
        def callback(update, context):
            raise DispatcherHandlerStop()

        dp.add_handler(MessageHandler(Filters.all, callback))

        with caplog.at_level(logging.WARNING):
            dp.update_queue.put(self.message_update)
            sleep(0.1)
            assert len(caplog.records) == 1
            assert (caplog.records[-1].getMessage().startswith(
                'DispatcherHandlerStop is not supported '
                'with async functions'))

    def test_async_raises_exception(self, dp, caplog):
        @run_async
        def callback(update, context):
            raise RuntimeError('async raising exception')

        dp.add_handler(MessageHandler(Filters.all, callback))

        with caplog.at_level(logging.WARNING):
            dp.update_queue.put(self.message_update)
            sleep(0.1)
            assert len(caplog.records) == 1
            assert (caplog.records[-1].getMessage().startswith(
                'A promise with deactivated error handling'))

    def test_add_async_handler(self, dp):
        dp.add_handler(
            MessageHandler(
                Filters.all,
                self.callback_if_not_update_queue,
                pass_update_queue=True,
                run_async=True,
            ))

        dp.update_queue.put(self.message_update)
        sleep(0.1)
        assert self.received == self.message_update.message

    def test_run_async_no_error_handler(self, dp, caplog):
        def func():
            raise RuntimeError('Async Error')

        with caplog.at_level(logging.ERROR):
            dp.run_async(func)
            sleep(0.1)
            assert len(caplog.records) == 1
            assert caplog.records[-1].getMessage().startswith(
                'No error handlers are registered')

    def test_async_handler_error_handler(self, dp):
        dp.add_handler(
            MessageHandler(Filters.all,
                           self.callback_raise_error,
                           run_async=True))
        dp.add_error_handler(self.error_handler)

        dp.update_queue.put(self.message_update)
        sleep(0.1)
        assert self.received == self.message_update.message.text

    def test_async_handler_async_error_handler_context(self, cdp):
        cdp.add_handler(
            MessageHandler(Filters.all,
                           self.callback_raise_error,
                           run_async=True))
        cdp.add_error_handler(self.error_handler_context, run_async=True)

        cdp.update_queue.put(self.message_update)
        sleep(2)
        assert self.received == self.message_update.message.text

    def test_async_handler_error_handler_that_raises_error(self, dp, caplog):
        handler = MessageHandler(Filters.all,
                                 self.callback_raise_error,
                                 run_async=True)
        dp.add_handler(handler)
        dp.add_error_handler(self.error_handler_raise_error, run_async=False)

        with caplog.at_level(logging.ERROR):
            dp.update_queue.put(self.message_update)
            sleep(0.1)
            assert len(caplog.records) == 1
            assert caplog.records[-1].getMessage().startswith(
                'An uncaught error was raised')

        # Make sure that the main loop still runs
        dp.remove_handler(handler)
        dp.add_handler(
            MessageHandler(Filters.all,
                           self.callback_increase_count,
                           run_async=True))
        dp.update_queue.put(self.message_update)
        sleep(0.1)
        assert self.count == 1

    def test_async_handler_async_error_handler_that_raises_error(
            self, dp, caplog):
        handler = MessageHandler(Filters.all,
                                 self.callback_raise_error,
                                 run_async=True)
        dp.add_handler(handler)
        dp.add_error_handler(self.error_handler_raise_error, run_async=True)

        with caplog.at_level(logging.ERROR):
            dp.update_queue.put(self.message_update)
            sleep(0.1)
            assert len(caplog.records) == 1
            assert caplog.records[-1].getMessage().startswith(
                'An uncaught error was raised')

        # Make sure that the main loop still runs
        dp.remove_handler(handler)
        dp.add_handler(
            MessageHandler(Filters.all,
                           self.callback_increase_count,
                           run_async=True))
        dp.update_queue.put(self.message_update)
        sleep(0.1)
        assert self.count == 1

    def test_error_in_handler(self, dp):
        dp.add_handler(MessageHandler(Filters.all, self.callback_raise_error))
        dp.add_error_handler(self.error_handler)

        dp.update_queue.put(self.message_update)
        sleep(0.1)
        assert self.received == self.message_update.message.text

    def test_add_remove_handler(self, dp):
        handler = MessageHandler(Filters.all, self.callback_increase_count)
        dp.add_handler(handler)
        dp.update_queue.put(self.message_update)
        sleep(0.1)
        assert self.count == 1
        dp.remove_handler(handler)
        dp.update_queue.put(self.message_update)
        assert self.count == 1

    def test_add_remove_handler_non_default_group(self, dp):
        handler = MessageHandler(Filters.all, self.callback_increase_count)
        dp.add_handler(handler, group=2)
        with pytest.raises(KeyError):
            dp.remove_handler(handler)
        dp.remove_handler(handler, group=2)

    def test_error_start_twice(self, dp):
        assert dp.running
        dp.start()

    def test_handler_order_in_group(self, dp):
        dp.add_handler(
            MessageHandler(Filters.photo, self.callback_set_count(1)))
        dp.add_handler(MessageHandler(Filters.all, self.callback_set_count(2)))
        dp.add_handler(MessageHandler(Filters.text,
                                      self.callback_set_count(3)))
        dp.update_queue.put(self.message_update)
        sleep(0.1)
        assert self.count == 2

    def test_groups(self, dp):
        dp.add_handler(
            MessageHandler(Filters.all, self.callback_increase_count))
        dp.add_handler(MessageHandler(Filters.all,
                                      self.callback_increase_count),
                       group=2)
        dp.add_handler(MessageHandler(Filters.all,
                                      self.callback_increase_count),
                       group=-1)

        dp.update_queue.put(self.message_update)
        sleep(0.1)
        assert self.count == 3

    def test_add_handler_errors(self, dp):
        handler = 'not a handler'
        with pytest.raises(TypeError, match='handler is not an instance of'):
            dp.add_handler(handler)

        handler = MessageHandler(Filters.photo, self.callback_set_count(1))
        with pytest.raises(TypeError, match='group is not int'):
            dp.add_handler(handler, 'one')

    def test_flow_stop(self, dp, bot):
        passed = []

        def start1(b, u):
            passed.append('start1')
            raise DispatcherHandlerStop

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)

        update = Update(
            1,
            message=Message(
                1,
                None,
                None,
                None,
                text='/start',
                entities=[
                    MessageEntity(type=MessageEntity.BOT_COMMAND,
                                  offset=0,
                                  length=len('/start'))
                ],
                bot=bot,
            ),
        )

        # If Stop raised handlers in other groups should not be called.
        passed = []
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start3), 1)
        dp.add_handler(CommandHandler('start', start2), 2)
        dp.process_update(update)
        assert passed == ['start1']

    def test_exception_in_handler(self, dp, bot):
        passed = []
        err = Exception('General exception')

        def start1(b, u):
            passed.append('start1')
            raise err

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)

        update = Update(
            1,
            message=Message(
                1,
                None,
                None,
                None,
                text='/start',
                entities=[
                    MessageEntity(type=MessageEntity.BOT_COMMAND,
                                  offset=0,
                                  length=len('/start'))
                ],
                bot=bot,
            ),
        )

        # If an unhandled exception was caught, no further handlers from the same group should be
        # called. Also, the error handler should be called and receive the exception
        passed = []
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start2), 1)
        dp.add_handler(CommandHandler('start', start3), 2)
        dp.add_error_handler(error)
        dp.process_update(update)
        assert passed == ['start1', 'error', err, 'start3']

    def test_telegram_error_in_handler(self, dp, bot):
        passed = []
        err = TelegramError('Telegram error')

        def start1(b, u):
            passed.append('start1')
            raise err

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)

        update = Update(
            1,
            message=Message(
                1,
                None,
                None,
                None,
                text='/start',
                entities=[
                    MessageEntity(type=MessageEntity.BOT_COMMAND,
                                  offset=0,
                                  length=len('/start'))
                ],
                bot=bot,
            ),
        )

        # If a TelegramException was caught, an error handler should be called and no further
        # handlers from the same group should be called.
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start2), 1)
        dp.add_handler(CommandHandler('start', start3), 2)
        dp.add_error_handler(error)
        dp.process_update(update)
        assert passed == ['start1', 'error', err, 'start3']
        assert passed[2] is err

    def test_error_while_saving_chat_data(self, bot):
        increment = []

        class OwnPersistence(BasePersistence):
            def __init__(self):
                super().__init__()
                self.store_user_data = True
                self.store_chat_data = True
                self.store_bot_data = True

            def get_bot_data(self):
                return {}

            def update_bot_data(self, data):
                raise Exception

            def get_chat_data(self):
                return defaultdict(dict)

            def update_chat_data(self, chat_id, data):
                raise Exception

            def get_user_data(self):
                return defaultdict(dict)

            def update_user_data(self, user_id, data):
                raise Exception

            def get_conversations(self, name):
                pass

            def update_conversation(self, name, key, new_state):
                pass

        def start1(b, u):
            pass

        def error(b, u, e):
            increment.append("error")

        # If updating a user_data or chat_data from a persistence object throws an error,
        # the error handler should catch it

        update = Update(
            1,
            message=Message(
                1,
                None,
                Chat(1, "lala"),
                from_user=User(1, "Test", False),
                text='/start',
                entities=[
                    MessageEntity(type=MessageEntity.BOT_COMMAND,
                                  offset=0,
                                  length=len('/start'))
                ],
                bot=bot,
            ),
        )
        my_persistence = OwnPersistence()
        dp = Dispatcher(bot,
                        None,
                        persistence=my_persistence,
                        use_context=False)
        dp.add_handler(CommandHandler('start', start1))
        dp.add_error_handler(error)
        dp.process_update(update)
        assert increment == ["error", "error", "error"]

    def test_flow_stop_in_error_handler(self, dp, bot):
        passed = []
        err = TelegramError('Telegram error')

        def start1(b, u):
            passed.append('start1')
            raise err

        def start2(b, u):
            passed.append('start2')

        def start3(b, u):
            passed.append('start3')

        def error(b, u, e):
            passed.append('error')
            passed.append(e)
            raise DispatcherHandlerStop

        update = Update(
            1,
            message=Message(
                1,
                None,
                None,
                None,
                text='/start',
                entities=[
                    MessageEntity(type=MessageEntity.BOT_COMMAND,
                                  offset=0,
                                  length=len('/start'))
                ],
                bot=bot,
            ),
        )

        # If a TelegramException was caught, an error handler should be called and no further
        # handlers from the same group should be called.
        dp.add_handler(CommandHandler('start', start1), 1)
        dp.add_handler(CommandHandler('start', start2), 1)
        dp.add_handler(CommandHandler('start', start3), 2)
        dp.add_error_handler(error)
        dp.process_update(update)
        assert passed == ['start1', 'error', err]
        assert passed[2] is err

    def test_error_handler_context(self, cdp):
        cdp.add_error_handler(self.callback_context)

        error = TelegramError('Unauthorized.')
        cdp.update_queue.put(error)
        sleep(0.1)
        assert self.received == 'Unauthorized.'

    def test_sensible_worker_thread_names(self, dp2):
        thread_names = [
            thread.name
            for thread in getattr(dp2, '_Dispatcher__async_threads')
        ]
        print(thread_names)
        for thread_name in thread_names:
            assert thread_name.startswith(f"Bot:{dp2.bot.id}:worker:")

    def test_non_context_deprecation(self, dp):
        with pytest.warns(TelegramDeprecationWarning):
            Dispatcher(dp.bot,
                       dp.update_queue,
                       job_queue=dp.job_queue,
                       workers=0,
                       use_context=False)

    def test_error_while_persisting(self, cdp, monkeypatch):
        class OwnPersistence(BasePersistence):
            def __init__(self):
                super().__init__()
                self.store_user_data = True
                self.store_chat_data = True
                self.store_bot_data = True

            def update(self, data):
                raise Exception('PersistenceError')

            def update_bot_data(self, data):
                self.update(data)

            def update_chat_data(self, chat_id, data):
                self.update(data)

            def update_user_data(self, user_id, data):
                self.update(data)

            def get_chat_data(self):
                pass

            def get_bot_data(self):
                pass

            def get_user_data(self):
                pass

            def get_conversations(self, name):
                pass

            def update_conversation(self, name, key, new_state):
                pass

        def callback(update, context):
            pass

        test_flag = False

        def error(update, context):
            nonlocal test_flag
            test_flag = str(context.error) == 'PersistenceError'
            raise Exception('ErrorHandlingError')

        def logger(message):
            assert 'uncaught error was raised while handling' in message

        update = Update(1,
                        message=Message(1,
                                        None,
                                        Chat(1, ''),
                                        from_user=User(1, '', False),
                                        text='Text'))
        handler = MessageHandler(Filters.all, callback)
        cdp.add_handler(handler)
        cdp.add_error_handler(error)
        monkeypatch.setattr(cdp.logger, 'exception', logger)

        cdp.persistence = OwnPersistence()
        cdp.process_update(update)
        assert test_flag

    def test_persisting_no_user_no_chat(self, cdp):
        class OwnPersistence(BasePersistence):
            def __init__(self):
                super().__init__()
                self.store_user_data = True
                self.store_chat_data = True
                self.store_bot_data = True
                self.test_flag_bot_data = False
                self.test_flag_chat_data = False
                self.test_flag_user_data = False

            def update_bot_data(self, data):
                self.test_flag_bot_data = True

            def update_chat_data(self, chat_id, data):
                self.test_flag_chat_data = True

            def update_user_data(self, user_id, data):
                self.test_flag_user_data = True

            def update_conversation(self, name, key, new_state):
                pass

            def get_conversations(self, name):
                pass

            def get_user_data(self):
                pass

            def get_bot_data(self):
                pass

            def get_chat_data(self):
                pass

        def callback(update, context):
            pass

        handler = MessageHandler(Filters.all, callback)
        cdp.add_handler(handler)
        cdp.persistence = OwnPersistence()

        update = Update(1,
                        message=Message(1,
                                        None,
                                        None,
                                        from_user=User(1, '', False),
                                        text='Text'))
        cdp.process_update(update)
        assert cdp.persistence.test_flag_bot_data
        assert cdp.persistence.test_flag_user_data
        assert not cdp.persistence.test_flag_chat_data

        cdp.persistence.test_flag_bot_data = False
        cdp.persistence.test_flag_user_data = False
        cdp.persistence.test_flag_chat_data = False
        update = Update(1,
                        message=Message(1,
                                        None,
                                        Chat(1, ''),
                                        from_user=None,
                                        text='Text'))
        cdp.process_update(update)
        assert cdp.persistence.test_flag_bot_data
        assert not cdp.persistence.test_flag_user_data
        assert cdp.persistence.test_flag_chat_data

    def test_update_persistence_once_per_update(self, monkeypatch, dp):
        def update_persistence(*args, **kwargs):
            self.count += 1

        def dummy_callback(*args):
            pass

        monkeypatch.setattr(dp, 'update_persistence', update_persistence)

        for group in range(5):
            dp.add_handler(MessageHandler(Filters.text, dummy_callback),
                           group=group)

        update = Update(1,
                        message=Message(1,
                                        None,
                                        Chat(1, ''),
                                        from_user=None,
                                        text=None))
        dp.process_update(update)
        assert self.count == 0

        update = Update(1,
                        message=Message(1,
                                        None,
                                        Chat(1, ''),
                                        from_user=None,
                                        text='text'))
        dp.process_update(update)
        assert self.count == 1

    def test_update_persistence_all_async(self, monkeypatch, dp):
        def update_persistence(*args, **kwargs):
            self.count += 1

        def dummy_callback(*args, **kwargs):
            pass

        monkeypatch.setattr(dp, 'update_persistence', update_persistence)
        monkeypatch.setattr(dp, 'run_async', dummy_callback)

        for group in range(5):
            dp.add_handler(MessageHandler(Filters.text,
                                          dummy_callback,
                                          run_async=True),
                           group=group)

        update = Update(1,
                        message=Message(1,
                                        None,
                                        Chat(1, ''),
                                        from_user=None,
                                        text='Text'))
        dp.process_update(update)
        assert self.count == 0

        dp.bot.defaults = Defaults(run_async=True)
        try:
            for group in range(5):
                dp.add_handler(MessageHandler(Filters.text, dummy_callback),
                               group=group)

            update = Update(1,
                            message=Message(1,
                                            None,
                                            Chat(1, ''),
                                            from_user=None,
                                            text='Text'))
            dp.process_update(update)
            assert self.count == 0
        finally:
            dp.bot.defaults = None

    @pytest.mark.parametrize('run_async', [DEFAULT_FALSE, False])
    def test_update_persistence_one_sync(self, monkeypatch, dp, run_async):
        def update_persistence(*args, **kwargs):
            self.count += 1

        def dummy_callback(*args, **kwargs):
            pass

        monkeypatch.setattr(dp, 'update_persistence', update_persistence)
        monkeypatch.setattr(dp, 'run_async', dummy_callback)

        for group in range(5):
            dp.add_handler(MessageHandler(Filters.text,
                                          dummy_callback,
                                          run_async=True),
                           group=group)
        dp.add_handler(MessageHandler(Filters.text,
                                      dummy_callback,
                                      run_async=run_async),
                       group=5)

        update = Update(1,
                        message=Message(1,
                                        None,
                                        Chat(1, ''),
                                        from_user=None,
                                        text='Text'))
        dp.process_update(update)
        assert self.count == 1

    @pytest.mark.parametrize('run_async,expected', [(DEFAULT_FALSE, 1),
                                                    (False, 1), (True, 0)])
    def test_update_persistence_defaults_async(self, monkeypatch, dp,
                                               run_async, expected):
        def update_persistence(*args, **kwargs):
            self.count += 1

        def dummy_callback(*args, **kwargs):
            pass

        monkeypatch.setattr(dp, 'update_persistence', update_persistence)
        monkeypatch.setattr(dp, 'run_async', dummy_callback)
        dp.bot.defaults = Defaults(run_async=run_async)

        try:
            for group in range(5):
                dp.add_handler(MessageHandler(Filters.text, dummy_callback),
                               group=group)

            update = Update(1,
                            message=Message(1,
                                            None,
                                            Chat(1, ''),
                                            from_user=None,
                                            text='Text'))
            dp.process_update(update)
            assert self.count == expected
        finally:
            dp.bot.defaults = None
Exemplo n.º 19
0
 def mockUpdate(text):
     message = Message(0, None, None, None)
     message.text = text
     update = Update(0)
     update.message = message
     return update
Exemplo n.º 20
0
    def test_error_while_saving_chat_data(self, bot):
        increment = []

        class OwnPersistence(BasePersistence):
            def __init__(self):
                super().__init__()
                self.store_user_data = True
                self.store_chat_data = True
                self.store_bot_data = True

            def get_bot_data(self):
                return {}

            def update_bot_data(self, data):
                raise Exception

            def get_chat_data(self):
                return defaultdict(dict)

            def update_chat_data(self, chat_id, data):
                raise Exception

            def get_user_data(self):
                return defaultdict(dict)

            def update_user_data(self, user_id, data):
                raise Exception

            def get_conversations(self, name):
                pass

            def update_conversation(self, name, key, new_state):
                pass

        def start1(b, u):
            pass

        def error(b, u, e):
            increment.append("error")

        # If updating a user_data or chat_data from a persistence object throws an error,
        # the error handler should catch it

        update = Update(
            1,
            message=Message(
                1,
                None,
                Chat(1, "lala"),
                from_user=User(1, "Test", False),
                text='/start',
                entities=[
                    MessageEntity(type=MessageEntity.BOT_COMMAND,
                                  offset=0,
                                  length=len('/start'))
                ],
                bot=bot,
            ),
        )
        my_persistence = OwnPersistence()
        dp = Dispatcher(bot,
                        None,
                        persistence=my_persistence,
                        use_context=False)
        dp.add_handler(CommandHandler('start', start1))
        dp.add_error_handler(error)
        dp.process_update(update)
        assert increment == ["error", "error", "error"]
Exemplo n.º 21
0
    def test_context(self, cdp, message):
        handler = RegexHandler(r'(t)est(.*)', self.callback_context)
        cdp.add_handler(handler)

        cdp.process_update(Update(0, message=message))
        assert self.test_flag
Exemplo n.º 22
0
    def test_error_while_persisting(self, cdp, monkeypatch):
        class OwnPersistence(BasePersistence):
            def __init__(self):
                super().__init__()
                self.store_user_data = True
                self.store_chat_data = True
                self.store_bot_data = True

            def update(self, data):
                raise Exception('PersistenceError')

            def update_bot_data(self, data):
                self.update(data)

            def update_chat_data(self, chat_id, data):
                self.update(data)

            def update_user_data(self, user_id, data):
                self.update(data)

            def get_chat_data(self):
                pass

            def get_bot_data(self):
                pass

            def get_user_data(self):
                pass

            def get_conversations(self, name):
                pass

            def update_conversation(self, name, key, new_state):
                pass

        def callback(update, context):
            pass

        test_flag = False

        def error(update, context):
            nonlocal test_flag
            test_flag = str(context.error) == 'PersistenceError'
            raise Exception('ErrorHandlingError')

        def logger(message):
            assert 'uncaught error was raised while handling' in message

        update = Update(1,
                        message=Message(1,
                                        None,
                                        Chat(1, ''),
                                        from_user=User(1, '', False),
                                        text='Text'))
        handler = MessageHandler(Filters.all, callback)
        cdp.add_handler(handler)
        cdp.add_error_handler(error)
        monkeypatch.setattr(cdp.logger, 'exception', logger)

        cdp.persistence = OwnPersistence()
        cdp.process_update(update)
        assert test_flag
Exemplo n.º 23
0
def chat_member(bot, chat_member_updated):
    return Update(0, my_chat_member=chat_member_updated)
Exemplo n.º 24
0
    def test_persisting_no_user_no_chat(self, cdp):
        class OwnPersistence(BasePersistence):
            def __init__(self):
                super().__init__()
                self.store_user_data = True
                self.store_chat_data = True
                self.store_bot_data = True
                self.test_flag_bot_data = False
                self.test_flag_chat_data = False
                self.test_flag_user_data = False

            def update_bot_data(self, data):
                self.test_flag_bot_data = True

            def update_chat_data(self, chat_id, data):
                self.test_flag_chat_data = True

            def update_user_data(self, user_id, data):
                self.test_flag_user_data = True

            def update_conversation(self, name, key, new_state):
                pass

            def get_conversations(self, name):
                pass

            def get_user_data(self):
                pass

            def get_bot_data(self):
                pass

            def get_chat_data(self):
                pass

        def callback(update, context):
            pass

        handler = MessageHandler(Filters.all, callback)
        cdp.add_handler(handler)
        cdp.persistence = OwnPersistence()

        update = Update(1,
                        message=Message(1,
                                        None,
                                        None,
                                        from_user=User(1, '', False),
                                        text='Text'))
        cdp.process_update(update)
        assert cdp.persistence.test_flag_bot_data
        assert cdp.persistence.test_flag_user_data
        assert not cdp.persistence.test_flag_chat_data

        cdp.persistence.test_flag_bot_data = False
        cdp.persistence.test_flag_user_data = False
        cdp.persistence.test_flag_chat_data = False
        update = Update(1,
                        message=Message(1,
                                        None,
                                        Chat(1, ''),
                                        from_user=None,
                                        text='Text'))
        cdp.process_update(update)
        assert cdp.persistence.test_flag_bot_data
        assert not cdp.persistence.test_flag_user_data
        assert cdp.persistence.test_flag_chat_data
def chosen_inline_result():
    return Update(1,
                  chosen_inline_result=ChosenInlineResult(
                      'result_id', User(1, 'test_user'), 'query'))
Exemplo n.º 26
0
def call_handler(updater, handler, message):
    update = Update(update_id=1, message=message)
    context = CallbackContext.from_update(update, updater.dispatcher)
    return handler(update, context)
Exemplo n.º 27
0
def update(request):
    return Update(update_id=TestUpdate.update_id, **request.param)
Exemplo n.º 28
0
def update(message):
    return Update(update_id=1, message=message)
Exemplo n.º 29
0
def poll_answer(bot):
    return Update(0,
                  poll_answer=PollAnswer(1, User(2, 'test user', False),
                                         [0, 1]))
    def test_nested_conversation_handler(self, dp, bot, user1, user2):
        self.nested_states[self.DRINKING] = [
            ConversationHandler(entry_points=self.drinking_entry_points,
                                states=self.drinking_states,
                                fallbacks=self.drinking_fallbacks,
                                map_to_parent=self.drinking_map_to_parent)
        ]
        handler = ConversationHandler(entry_points=self.entry_points,
                                      states=self.nested_states,
                                      fallbacks=self.fallbacks)
        dp.add_handler(handler)

        # User one, starts the state machine.
        message = Message(0,
                          user1,
                          None,
                          self.group,
                          text='/start',
                          bot=bot,
                          entities=[
                              MessageEntity(type=MessageEntity.BOT_COMMAND,
                                            offset=0,
                                            length=len('/start'))
                          ])
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.THIRSTY

        # The user is thirsty and wants to brew coffee.
        message.text = '/brew'
        message.entities[0].length = len('/brew')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.BREWING

        # Lets pour some coffee.
        message.text = '/pourCoffee'
        message.entities[0].length = len('/pourCoffee')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.DRINKING

        # The user is holding the cup
        message.text = '/hold'
        message.entities[0].length = len('/hold')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.HOLDING

        # The user is sipping coffee
        message.text = '/sip'
        message.entities[0].length = len('/sip')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.SIPPING

        # The user is swallowing
        message.text = '/swallow'
        message.entities[0].length = len('/swallow')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.SWALLOWING

        # The user is holding the cup again
        message.text = '/hold'
        message.entities[0].length = len('/hold')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.HOLDING

        # The user wants to replenish the coffee supply
        message.text = '/replenish'
        message.entities[0].length = len('/replenish')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.REPLENISHING
        assert handler.conversations[(0, user1.id)] == self.BREWING

        # The user wants to drink their coffee again
        message.text = '/pourCoffee'
        message.entities[0].length = len('/pourCoffee')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.DRINKING

        # The user is now ready to start coding
        message.text = '/startCoding'
        message.entities[0].length = len('/startCoding')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.CODING

        # The user decides it's time to drink again
        message.text = '/drinkMore'
        message.entities[0].length = len('/drinkMore')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.DRINKING

        # The user is holding their cup
        message.text = '/hold'
        message.entities[0].length = len('/hold')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.HOLDING

        # The user wants to end with the drinking and go back to coding
        message.text = '/end'
        message.entities[0].length = len('/end')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.END
        assert handler.conversations[(0, user1.id)] == self.CODING

        # The user wants to drink once more
        message.text = '/drinkMore'
        message.entities[0].length = len('/drinkMore')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.DRINKING

        # The user wants to stop altogether
        message.text = '/stop'
        message.entities[0].length = len('/stop')
        dp.process_update(Update(update_id=0, message=message))
        assert self.current_state[user1.id] == self.STOPPING
        assert handler.conversations.get((0, user1.id)) is None