diff --git a/homeassistant/components/telegram_bot/bot.py b/homeassistant/components/telegram_bot/bot.py index c9046f7183b..754dc84305c 100644 --- a/homeassistant/components/telegram_bot/bot.py +++ b/homeassistant/components/telegram_bot/bot.py @@ -97,6 +97,7 @@ from .const import ( CONF_API_ENDPOINT, CONF_CHAT_ID, CONF_PROXY_URL, + DEFAULT_TIMEOUT_SECONDS, DOMAIN, EVENT_TELEGRAM_ATTACHMENT, EVENT_TELEGRAM_CALLBACK, @@ -1107,12 +1108,26 @@ def initialize_bot(hass: HomeAssistant, p_config: MappingProxyType[str, Any]) -> api_key: str = p_config[CONF_API_KEY] + # set up timeouts to handle large file downloads and uploads + # server-side file size limit is 2GB + read_timeout = DEFAULT_TIMEOUT_SECONDS + media_write_timeout = DEFAULT_TIMEOUT_SECONDS + proxy_url: str | None = p_config.get(CONF_PROXY_URL) if proxy_url is not None: proxy = httpx.Proxy(proxy_url) - request = HTTPXRequest(connection_pool_size=8, proxy=proxy) + request = HTTPXRequest( + connection_pool_size=8, + proxy=proxy, + read_timeout=read_timeout, + media_write_timeout=media_write_timeout, + ) else: - request = HTTPXRequest(connection_pool_size=8) + request = HTTPXRequest( + connection_pool_size=8, + read_timeout=read_timeout, + media_write_timeout=media_write_timeout, + ) base_url: str = p_config[CONF_API_ENDPOINT] @@ -1151,7 +1166,9 @@ async def load_data( params["verify"] = verify_ssl retry_num = 0 - async with httpx.AsyncClient(timeout=15, headers=headers, **params) as client: + async with httpx.AsyncClient( + timeout=DEFAULT_TIMEOUT_SECONDS, headers=headers, **params + ) as client: while retry_num < num_retries: try: req = await client.get(url) @@ -1175,6 +1192,7 @@ async def load_data( if data.read(): data.seek(0) data.name = url + _LOGGER.debug("file downloaded: %s", url) return data _LOGGER.warning("Empty data (retry #%s) in %s)", retry_num + 1, url) retry_num += 1 diff --git a/homeassistant/components/telegram_bot/const.py b/homeassistant/components/telegram_bot/const.py index adda79cf87f..a950c825840 100644 --- a/homeassistant/components/telegram_bot/const.py +++ b/homeassistant/components/telegram_bot/const.py @@ -24,6 +24,8 @@ BOT_NAME = "telegram_bot" ERROR_FIELD = "error_field" ERROR_MESSAGE = "error_message" + +DEFAULT_TIMEOUT_SECONDS = 1800 # 30 minutes DEFAULT_API_ENDPOINT = "https://api.telegram.org" DEFAULT_TRUSTED_NETWORKS = [ip_network("149.154.160.0/20"), ip_network("91.108.4.0/22")] diff --git a/tests/components/telegram_bot/test_broadcast.py b/tests/components/telegram_bot/test_broadcast.py index 0b3ee0066ee..11892f95cc1 100644 --- a/tests/components/telegram_bot/test_broadcast.py +++ b/tests/components/telegram_bot/test_broadcast.py @@ -1,12 +1,18 @@ """Test Telegram broadcast.""" +from httpx import Request as HTTPXRequest + +from homeassistant.components.telegram_bot.bot import TelegramBotConfigEntry +from homeassistant.components.telegram_bot.const import DEFAULT_TIMEOUT_SECONDS from homeassistant.core import HomeAssistant from tests.common import MockConfigEntry async def test_setup( - hass: HomeAssistant, mock_broadcast_config_entry: MockConfigEntry + hass: HomeAssistant, + mock_broadcast_config_entry: MockConfigEntry, + mock_external_calls: None, ) -> None: """Test setting up Telegram broadcast.""" mock_broadcast_config_entry.add_to_hass(hass) @@ -14,3 +20,10 @@ async def test_setup( await hass.async_block_till_done() assert hass.services.has_service("telegram_bot", "send_message") is True + + config_entry: TelegramBotConfigEntry = hass.config_entries.async_get_known_entry( + mock_broadcast_config_entry.entry_id + ) + request: HTTPXRequest = config_entry.runtime_data.bot.request + assert request.read_timeout == DEFAULT_TIMEOUT_SECONDS + assert request._media_write_timeout == DEFAULT_TIMEOUT_SECONDS