Fix multiple webhook secrets for Telegram bot (#149103)

This commit is contained in:
hanwg 2025-07-22 13:42:40 +08:00 committed by GitHub
parent ef2531d28d
commit 42cf4e8db7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 12 deletions

View File

@ -82,7 +82,7 @@ class PushBot(BaseTelegramBot):
self.base_url = config.data.get(CONF_URL) or get_url( self.base_url = config.data.get(CONF_URL) or get_url(
hass, require_ssl=True, allow_internal=False hass, require_ssl=True, allow_internal=False
) )
self.webhook_url = f"{self.base_url}{TELEGRAM_WEBHOOK_URL}" self.webhook_url = self.base_url + _get_webhook_url(bot)
async def shutdown(self) -> None: async def shutdown(self) -> None:
"""Shutdown the app.""" """Shutdown the app."""
@ -98,9 +98,11 @@ class PushBot(BaseTelegramBot):
api_kwargs={"secret_token": self.secret_token}, api_kwargs={"secret_token": self.secret_token},
connect_timeout=5, connect_timeout=5,
) )
except TelegramError: except TelegramError as err:
retry_num += 1 retry_num += 1
_LOGGER.warning("Error trying to set webhook (retry #%d)", retry_num) _LOGGER.warning(
"Error trying to set webhook (retry #%d)", retry_num, exc_info=err
)
return False return False
@ -143,7 +145,6 @@ class PushBotView(HomeAssistantView):
"""View for handling webhook calls from Telegram.""" """View for handling webhook calls from Telegram."""
requires_auth = False requires_auth = False
url = TELEGRAM_WEBHOOK_URL
name = "telegram_webhooks" name = "telegram_webhooks"
def __init__( def __init__(
@ -160,6 +161,7 @@ class PushBotView(HomeAssistantView):
self.application = application self.application = application
self.trusted_networks = trusted_networks self.trusted_networks = trusted_networks
self.secret_token = secret_token self.secret_token = secret_token
self.url = _get_webhook_url(bot)
async def post(self, request: HomeAssistantRequest) -> Response | None: async def post(self, request: HomeAssistantRequest) -> Response | None:
"""Accept the POST from telegram.""" """Accept the POST from telegram."""
@ -183,3 +185,7 @@ class PushBotView(HomeAssistantView):
await self.application.process_update(update) await self.application.process_update(update)
return None return None
def _get_webhook_url(bot: Bot) -> str:
return f"{TELEGRAM_WEBHOOK_URL}_{bot.id}"

View File

@ -364,7 +364,7 @@ async def test_webhook_endpoint_generates_telegram_text_event(
events = async_capture_events(hass, "telegram_text") events = async_capture_events(hass, "telegram_text")
response = await client.post( response = await client.post(
TELEGRAM_WEBHOOK_URL, f"{TELEGRAM_WEBHOOK_URL}_123456",
json=update_message_text, json=update_message_text,
headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token}, headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token},
) )
@ -391,7 +391,7 @@ async def test_webhook_endpoint_generates_telegram_command_event(
events = async_capture_events(hass, "telegram_command") events = async_capture_events(hass, "telegram_command")
response = await client.post( response = await client.post(
TELEGRAM_WEBHOOK_URL, f"{TELEGRAM_WEBHOOK_URL}_123456",
json=update_message_command, json=update_message_command,
headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token}, headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token},
) )
@ -418,7 +418,7 @@ async def test_webhook_endpoint_generates_telegram_callback_event(
events = async_capture_events(hass, "telegram_callback") events = async_capture_events(hass, "telegram_callback")
response = await client.post( response = await client.post(
TELEGRAM_WEBHOOK_URL, f"{TELEGRAM_WEBHOOK_URL}_123456",
json=update_callback_query, json=update_callback_query,
headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token}, headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token},
) )
@ -594,7 +594,7 @@ async def test_webhook_endpoint_unauthorized_update_doesnt_generate_telegram_tex
events = async_capture_events(hass, "telegram_text") events = async_capture_events(hass, "telegram_text")
response = await client.post( response = await client.post(
TELEGRAM_WEBHOOK_URL, f"{TELEGRAM_WEBHOOK_URL}_123456",
json=unauthorized_update_message_text, json=unauthorized_update_message_text,
headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token}, headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token},
) )
@ -618,7 +618,7 @@ async def test_webhook_endpoint_without_secret_token_is_denied(
async_capture_events(hass, "telegram_text") async_capture_events(hass, "telegram_text")
response = await client.post( response = await client.post(
TELEGRAM_WEBHOOK_URL, f"{TELEGRAM_WEBHOOK_URL}_123456",
json=update_message_text, json=update_message_text,
) )
assert response.status == 401 assert response.status == 401
@ -636,7 +636,7 @@ async def test_webhook_endpoint_invalid_secret_token_is_denied(
async_capture_events(hass, "telegram_text") async_capture_events(hass, "telegram_text")
response = await client.post( response = await client.post(
TELEGRAM_WEBHOOK_URL, f"{TELEGRAM_WEBHOOK_URL}_123456",
json=update_message_text, json=update_message_text,
headers={"X-Telegram-Bot-Api-Secret-Token": incorrect_secret_token}, headers={"X-Telegram-Bot-Api-Secret-Token": incorrect_secret_token},
) )

View File

@ -7,6 +7,7 @@ from unittest.mock import AsyncMock, patch
from telegram import WebhookInfo from telegram import WebhookInfo
from telegram.error import TimedOut from telegram.error import TimedOut
from homeassistant.components.telegram_bot.webhooks import TELEGRAM_WEBHOOK_URL
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
@ -115,7 +116,7 @@ async def test_webhooks_update_invalid_json(
client = await hass_client() client = await hass_client()
response = await client.post( response = await client.post(
"/api/telegram_webhooks", f"{TELEGRAM_WEBHOOK_URL}_123456",
headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token}, headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token},
) )
assert response.status == 400 assert response.status == 400
@ -139,7 +140,7 @@ async def test_webhooks_unauthorized_network(
return_value=IPv4Network("1.2.3.4"), return_value=IPv4Network("1.2.3.4"),
) as mock_remote: ) as mock_remote:
response = await client.post( response = await client.post(
"/api/telegram_webhooks", f"{TELEGRAM_WEBHOOK_URL}_123456",
json="mock json", json="mock json",
headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token}, headers={"X-Telegram-Bot-Api-Secret-Token": mock_generate_secret_token},
) )