async def test_basic(self, app, prefix, command):
        """Test the basic expected response from a prefix handler"""
        handler = self.make_default_handler()
        app.add_handler(handler)
        text = prefix + command

        assert await self.response(app, make_message_update(text))
        assert not is_match(handler, make_message_update(command))
        assert not is_match(handler,
                            make_message_update(prefix + "notacommand"))
        assert not is_match(handler,
                            make_command_update(f"not {text} at start"))
        assert not is_match(
            handler,
            make_message_update(bot=app.bot, message=None, caption="caption"))

        handler = PrefixHandler(prefix=["!", "#"],
                                command="cmd",
                                callback=self.callback)
        assert isinstance(handler.commands, frozenset)
        assert handler.commands == {"!cmd", "#cmd"}

        handler = PrefixHandler(prefix="#",
                                command={"cmd", "bmd"},
                                callback=self.callback)
        assert isinstance(handler.commands, frozenset)
        assert handler.commands == {"#cmd", "#bmd"}
    def test_pass_args(self, dp, prefix_message):
        handler = self.make_default_handler(self.ch_callback_args, pass_args=True)
        dp.add_handler(handler)
        assert self.response(dp, make_message_update(prefix_message))

        update_with_args = make_message_update(prefix_message.text + ' one two')
        assert self.response(dp, update_with_args)
 def test_with_filter(self, prefix_message_text):
     handler = self.make_default_handler(filters=Filters.group)
     text = prefix_message_text
     assert is_match(handler,
                     make_message_update(text, chat=Chat(-23, Chat.GROUP)))
     assert not is_match(
         handler, make_message_update(text, chat=Chat(23, Chat.PRIVATE)))
    def test_basic(self, dp, prefix, command):
        """Test the basic expected response from a prefix handler"""
        handler = self.make_default_handler()
        dp.add_handler(handler)
        text = prefix + command

        assert self.response(dp, make_message_update(text))
        assert not is_match(handler, make_message_update(command))
        assert not is_match(handler, make_message_update(prefix + 'notacommand'))
        assert not is_match(handler, make_command_update('not {} at start'.format(text)))
    def test_basic_after_editing(self, dp, prefix, command):
        """Test the basic expected response from a prefix handler"""
        handler = self.make_default_handler()
        dp.add_handler(handler)
        text = prefix + command

        assert self.response(dp, make_message_update(text))
        handler.command = 'foo'
        text = prefix + 'foo'
        assert self.response(dp, make_message_update(text))
    async def test_basic(self, app, command):
        """Test whether a command handler responds to its command
        and not to others, or badly formatted commands"""
        handler = self.make_default_handler()
        app.add_handler(handler)

        assert await self.response(app,
                                   make_command_update(command, bot=app.bot))
        assert not is_match(handler,
                            make_command_update(command[1:], bot=app.bot))
        assert not is_match(
            handler, make_command_update(f"/not{command[1:]}", bot=app.bot))
        assert not is_match(
            handler, make_command_update(f"not {command} at start",
                                         bot=app.bot))
        assert not is_match(
            handler,
            make_message_update(bot=app.bot, message=None, caption="caption"))

        handler = CommandHandler(["FOO", "bAR"], callback=self.callback)
        assert isinstance(handler.commands, frozenset)
        assert handler.commands == {"foo", "bar"}

        handler = CommandHandler(["FOO"], callback=self.callback)
        assert isinstance(handler.commands, frozenset)
        assert handler.commands == {"foo"}
    async def test_webhook_arbitrary_callback_data(self, monkeypatch, updater,
                                                   invalid_data, chat_id):
        """Here we only test one simple setup. telegram.ext.ExtBot.insert_callback_data is tested
        extensively in test_bot.py in conjunction with get_updates."""
        updater.bot.arbitrary_callback_data = True

        async def return_true(*args, **kwargs):
            return True

        try:
            monkeypatch.setattr(updater.bot, "set_webhook", return_true)
            monkeypatch.setattr(updater.bot, "delete_webhook", return_true)

            ip = "127.0.0.1"
            port = randrange(1024, 49152)  # Select random port

            async with updater:
                await updater.start_webhook(ip, port, url_path="TOKEN")
                # Now, we send an update to the server
                reply_markup = InlineKeyboardMarkup.from_button(
                    InlineKeyboardButton(text="text",
                                         callback_data="callback_data"))
                if not invalid_data:
                    reply_markup = updater.bot.callback_data_cache.process_keyboard(
                        reply_markup)

                update = make_message_update(
                    message="test_webhook_arbitrary_callback_data",
                    message_factory=make_message,
                    reply_markup=reply_markup,
                    user=updater.bot.bot,
                )

                await send_webhook_message(ip, port, update.to_json(), "TOKEN")
                received_update = await updater.update_queue.get()

                assert received_update.update_id == update.update_id
                message_dict = update.message.to_dict()
                received_dict = received_update.message.to_dict()
                message_dict.pop("reply_markup")
                received_dict.pop("reply_markup")
                assert message_dict == received_dict

                button = received_update.message.reply_markup.inline_keyboard[
                    0][0]
                if invalid_data:
                    assert isinstance(button.callback_data,
                                      InvalidCallbackData)
                else:
                    assert button.callback_data == "callback_data"

                await updater.stop()
        finally:
            updater.bot.arbitrary_callback_data = False
            updater.bot.callback_data_cache.clear_callback_data()
            updater.bot.callback_data_cache.clear_callback_queries()
    async def test_webhook_update_de_json_fails(self, monkeypatch, updater,
                                                caplog):
        async def delete_webhook(*args, **kwargs):
            return True

        async def set_webhook(*args, **kwargs):
            return True

        def de_json_fails(*args, **kwargs):
            raise TypeError("Invalid input")

        monkeypatch.setattr(updater.bot, "set_webhook", set_webhook)
        monkeypatch.setattr(updater.bot, "delete_webhook", delete_webhook)
        orig_de_json = Update.de_json
        monkeypatch.setattr(Update, "de_json", de_json_fails)

        ip = "127.0.0.1"
        port = randrange(1024, 49152)  # Select random port

        async with updater:
            return_value = await updater.start_webhook(
                ip_address=ip,
                port=port,
                url_path="TOKEN",
            )
            assert return_value is updater.update_queue
            assert updater.running

            # Now, we send an update to the server
            update = make_message_update("Webhook")
            with caplog.at_level(logging.CRITICAL):
                await send_webhook_message(ip, port, update.to_json(), "TOKEN")

            assert len(caplog.records) == 1
            assert caplog.records[-1].getMessage().startswith(
                "Something went wrong processing")

            # Make sure that everything works fine again when receiving proper updates
            caplog.clear()
            with caplog.at_level(logging.CRITICAL):
                monkeypatch.setattr(Update, "de_json", orig_de_json)
                await send_webhook_message(ip, port, update.to_json(), "TOKEN")
                assert (
                    await
                    updater.update_queue.get()).to_dict() == update.to_dict()
            assert len(caplog.records) == 0

            await updater.stop()
            assert not updater.running
    async def test_webhook_ssl_just_for_telegram(self, monkeypatch, updater):
        """Here we just test that the SSL info is pased to Telegram, but __not__ to the the
        webhook server"""
        async def set_webhook(**kwargs):
            self.test_flag.append(bool(kwargs.get("certificate")))
            return True

        async def return_true(*args, **kwargs):
            return True

        orig_wh_server_init = WebhookServer.__init__

        def webhook_server_init(*args, **kwargs):
            self.test_flag = [kwargs.get("ssl_ctx") is None]
            orig_wh_server_init(*args, **kwargs)

        monkeypatch.setattr(updater.bot, "set_webhook", set_webhook)
        monkeypatch.setattr(updater.bot, "delete_webhook", return_true)
        monkeypatch.setattr(
            "telegram.ext._utils.webhookhandler.WebhookServer.__init__",
            webhook_server_init)

        ip = "127.0.0.1"
        port = randrange(1024, 49152)  # Select random port
        async with updater:
            await updater.start_webhook(ip,
                                        port,
                                        webhook_url=None,
                                        cert=Path(__file__).as_posix())

            # Now, we send an update to the server
            update = make_message_update(message="test_message")
            await send_webhook_message(ip, port, update.to_json())
            assert (await
                    updater.update_queue.get()).to_dict() == update.to_dict()
            assert self.test_flag == [True, True]
            await updater.stop()
 def test_filters_for_wrong_command(self, mock_filter):
     """Filters should not be executed if the command does not match the handler"""
     handler = self.make_default_handler(filters=mock_filter)
     assert not is_match(handler, make_message_update('/test'))
     assert not mock_filter.tested
 def prefix_message_update(self, prefix_message):
     return make_message_update(prefix_message)
    async def test_webhook_basic(self, monkeypatch, updater,
                                 drop_pending_updates, ext_bot, secret_token):
        # Testing with both ExtBot and Bot to make sure any logic in WebhookHandler
        # that depends on this distinction works
        if ext_bot and not isinstance(updater.bot, ExtBot):
            updater.bot = ExtBot(updater.bot.token)
        if not ext_bot and not type(updater.bot) is Bot:
            updater.bot = DictBot(updater.bot.token)

        async def delete_webhook(*args, **kwargs):
            # Dropping pending updates is done by passing the parameter to delete_webhook
            if kwargs.get("drop_pending_updates"):
                self.message_count += 1
            return True

        async def set_webhook(*args, **kwargs):
            return True

        monkeypatch.setattr(updater.bot, "set_webhook", set_webhook)
        monkeypatch.setattr(updater.bot, "delete_webhook", delete_webhook)

        ip = "127.0.0.1"
        port = randrange(1024, 49152)  # Select random port

        async with updater:
            return_value = await updater.start_webhook(
                drop_pending_updates=drop_pending_updates,
                ip_address=ip,
                port=port,
                url_path="TOKEN",
                secret_token=secret_token,
            )
            assert return_value is updater.update_queue
            assert updater.running

            # Now, we send an update to the server
            update = make_message_update("Webhook")
            await send_webhook_message(ip,
                                       port,
                                       update.to_json(),
                                       "TOKEN",
                                       secret_token=secret_token)
            assert (await
                    updater.update_queue.get()).to_dict() == update.to_dict()

            # Returns Not Found if path is incorrect
            response = await send_webhook_message(ip, port, "123456",
                                                  "webhook_handler.py")
            assert response.status_code == HTTPStatus.NOT_FOUND

            # Returns METHOD_NOT_ALLOWED if method is not allowed
            response = await send_webhook_message(ip,
                                                  port,
                                                  None,
                                                  "TOKEN",
                                                  get_method="HEAD")
            assert response.status_code == HTTPStatus.METHOD_NOT_ALLOWED

            if secret_token:
                # Returns Forbidden if no secret token is set
                response_text = "<html><title>403: {0}</title><body>403: {0}</body></html>"
                response = await send_webhook_message(ip, port,
                                                      update.to_json(),
                                                      "TOKEN")
                assert response.status_code == HTTPStatus.FORBIDDEN
                assert response.text == response_text.format(
                    "Request did not include the secret token")

                # Returns Forbidden if the secret token is wrong
                response = await send_webhook_message(
                    ip,
                    port,
                    update.to_json(),
                    "TOKEN",
                    secret_token="NotTheSecretToken")
                assert response.status_code == HTTPStatus.FORBIDDEN
                assert response.text == response_text.format(
                    "Request had the wrong secret token")

            await updater.stop()
            assert not updater.running

            if drop_pending_updates:
                assert self.message_count == 1
            else:
                assert self.message_count == 0

            # We call the same logic twice to make sure that restarting the updater works as well
            await updater.start_webhook(
                drop_pending_updates=drop_pending_updates,
                ip_address=ip,
                port=port,
                url_path="TOKEN",
            )
            assert updater.running
            update = make_message_update("Webhook")
            await send_webhook_message(ip, port, update.to_json(), "TOKEN")
            assert (await
                    updater.update_queue.get()).to_dict() == update.to_dict()
            await updater.stop()
            assert not updater.running