From d5197d75bbf3f9040bcc9e39709bdb6b3eac830e Mon Sep 17 00:00:00 2001 From: Meta42 Date: Wed, 6 May 2026 17:24:41 +0800 Subject: [PATCH 1/2] fix(telegram): avoid conflicting get_updates proxy config --- src/bub/channels/telegram.py | 4 +-- tests/test_channels.py | 65 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/bub/channels/telegram.py b/src/bub/channels/telegram.py index e412d142..c8f5d029 100644 --- a/src/bub/channels/telegram.py +++ b/src/bub/channels/telegram.py @@ -173,10 +173,10 @@ async def start(self, stop_event: asyncio.Event) -> None: len(self._allow_chats), bool(proxy), ) - get_updates_request = HTTPXRequest(read_timeout=30) + get_updates_request = HTTPXRequest(read_timeout=30, proxy=proxy) builder = Application.builder().token(self._settings.token).get_updates_request(get_updates_request) if proxy: - builder = builder.proxy(proxy).get_updates_proxy(proxy) + builder = builder.proxy(proxy) self._app = builder.build() self._app.add_handler(CommandHandler("start", self._on_start)) self._app.add_handler(CommandHandler("bub", self._on_message, has_args=True, block=False)) diff --git a/tests/test_channels.py b/tests/test_channels.py index 54f56158..46c78f3e 100644 --- a/tests/test_channels.py +++ b/tests/test_channels.py @@ -425,6 +425,71 @@ async def send_message(chat_id: str, text: str) -> None: assert sent == [("42", "hello")] +@pytest.mark.asyncio +async def test_telegram_channel_start_with_proxy_does_not_call_get_updates_proxy( + monkeypatch: pytest.MonkeyPatch, load_config +) -> None: + load_config( + """ +telegram: + token: "test-token" + proxy: "http://127.0.0.1:1087" +""".strip() + ) + + class FakeUpdater: + async def start_polling(self, **kwargs) -> None: + self.kwargs = kwargs + + class FakeApp: + def __init__(self) -> None: + self.updater = FakeUpdater() + self.handlers: list[object] = [] + + def add_handler(self, handler: object) -> None: + self.handlers.append(handler) + + async def initialize(self) -> None: + return + + async def start(self) -> None: + return + + class FakeBuilder: + def __init__(self) -> None: + self.app = FakeApp() + self.request = None + self.proxy_value = None + + def token(self, token: str) -> "FakeBuilder": + self.token_value = token + return self + + def get_updates_request(self, request: object) -> "FakeBuilder": + self.request = request + return self + + def proxy(self, proxy: str) -> "FakeBuilder": + self.proxy_value = proxy + return self + + def get_updates_proxy(self, _proxy: str) -> "FakeBuilder": + raise AssertionError("get_updates_proxy should not be called when get_updates_request is already set") + + def build(self) -> FakeApp: + return self.app + + fake_builder = FakeBuilder() + monkeypatch.setattr("bub.channels.telegram.Application.builder", lambda: fake_builder) + + channel = TelegramChannel(lambda message: None) + await channel.start(asyncio.Event()) + + assert fake_builder.proxy_value == "http://127.0.0.1:1087" + assert fake_builder.request is not None + assert fake_builder.app.updater.kwargs == {"drop_pending_updates": True, "allowed_updates": ["message"]} + + @pytest.mark.asyncio async def test_telegram_channel_build_message_returns_command_directly(load_config) -> None: _load_channel_config(load_config, telegram_value="test-token") From 6ebe1a14160b4a2c951862779280913d92c6342c Mon Sep 17 00:00:00 2001 From: Meta42 Date: Wed, 6 May 2026 17:49:22 +0800 Subject: [PATCH 2/2] test(telegram): simplify proxy startup regression fixture --- tests/test_channels.py | 110 ++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/tests/test_channels.py b/tests/test_channels.py index 46c78f3e..ac4440d5 100644 --- a/tests/test_channels.py +++ b/tests/test_channels.py @@ -101,6 +101,63 @@ def _message( ) +class _FakeTelegramUpdater: + def __init__(self) -> None: + self.kwargs: dict[str, object] | None = None + + async def start_polling(self, **kwargs) -> None: + self.kwargs = kwargs + + +class _FakeTelegramApp: + def __init__(self) -> None: + self.updater = _FakeTelegramUpdater() + self.handlers: list[object] = [] + + def add_handler(self, handler: object) -> None: + self.handlers.append(handler) + + async def initialize(self) -> None: + return + + async def start(self) -> None: + return + + +class _FakeTelegramBuilder: + def __init__(self) -> None: + self.app = _FakeTelegramApp() + self.request: object | None = None + self.proxy_value: str | None = None + self.token_value: str | None = None + + def token(self, token: str) -> _FakeTelegramBuilder: + self.token_value = token + return self + + def get_updates_request(self, request: object) -> _FakeTelegramBuilder: + self.request = request + return self + + def proxy(self, proxy: str) -> _FakeTelegramBuilder: + self.proxy_value = proxy + return self + + def get_updates_proxy(self, _proxy: str) -> _FakeTelegramBuilder: + raise AssertionError("get_updates_proxy should not be called when get_updates_request is already set") + + def build(self) -> _FakeTelegramApp: + return self.app + + +def _telegram_proxy_config() -> str: + return """ +telegram: + token: "test-token" + proxy: "http://127.0.0.1:1087" +""".strip() + + @pytest.mark.asyncio async def test_buffered_handler_passes_commands_through_immediately() -> None: handled: list[str] = [] @@ -429,57 +486,8 @@ async def send_message(chat_id: str, text: str) -> None: async def test_telegram_channel_start_with_proxy_does_not_call_get_updates_proxy( monkeypatch: pytest.MonkeyPatch, load_config ) -> None: - load_config( - """ -telegram: - token: "test-token" - proxy: "http://127.0.0.1:1087" -""".strip() - ) - - class FakeUpdater: - async def start_polling(self, **kwargs) -> None: - self.kwargs = kwargs - - class FakeApp: - def __init__(self) -> None: - self.updater = FakeUpdater() - self.handlers: list[object] = [] - - def add_handler(self, handler: object) -> None: - self.handlers.append(handler) - - async def initialize(self) -> None: - return - - async def start(self) -> None: - return - - class FakeBuilder: - def __init__(self) -> None: - self.app = FakeApp() - self.request = None - self.proxy_value = None - - def token(self, token: str) -> "FakeBuilder": - self.token_value = token - return self - - def get_updates_request(self, request: object) -> "FakeBuilder": - self.request = request - return self - - def proxy(self, proxy: str) -> "FakeBuilder": - self.proxy_value = proxy - return self - - def get_updates_proxy(self, _proxy: str) -> "FakeBuilder": - raise AssertionError("get_updates_proxy should not be called when get_updates_request is already set") - - def build(self) -> FakeApp: - return self.app - - fake_builder = FakeBuilder() + load_config(_telegram_proxy_config()) + fake_builder = _FakeTelegramBuilder() monkeypatch.setattr("bub.channels.telegram.Application.builder", lambda: fake_builder) channel = TelegramChannel(lambda message: None)