Cleanup error handling for Telegram bot (#163689)
This commit is contained in:
@@ -468,7 +468,7 @@ async def _async_send_telegram_message(service: ServiceCall) -> ServiceResponse:
|
||||
targets = _build_targets(service)
|
||||
|
||||
service_responses: JsonValueType = []
|
||||
errors: list[tuple[HomeAssistantError, str]] = []
|
||||
errors: list[tuple[Exception, str]] = []
|
||||
|
||||
# invoke the service for each target
|
||||
for target_config_entry, target_chat_id, target_notify_entity_id in targets:
|
||||
@@ -495,7 +495,7 @@ async def _async_send_telegram_message(service: ServiceCall) -> ServiceResponse:
|
||||
|
||||
assert isinstance(service_responses, list)
|
||||
service_responses.extend(formatted_responses)
|
||||
except HomeAssistantError as ex:
|
||||
except (HomeAssistantError, TelegramError) as ex:
|
||||
target = target_notify_entity_id or str(target_chat_id)
|
||||
errors.append((ex, target))
|
||||
|
||||
|
||||
@@ -433,7 +433,6 @@ class TelegramNotificationService:
|
||||
async def _send_msgs(
|
||||
self,
|
||||
func_send: Callable,
|
||||
msg_error: str,
|
||||
message_tag: str | None,
|
||||
*args_msg: Any,
|
||||
context: Context | None = None,
|
||||
@@ -459,12 +458,10 @@ class TelegramNotificationService:
|
||||
|
||||
response: Message = await self._send_msg(
|
||||
func_send,
|
||||
msg_error,
|
||||
message_tag,
|
||||
chat_id,
|
||||
*args_msg,
|
||||
context=context,
|
||||
suppress_error=len(chat_ids) > 1,
|
||||
**kwargs_msg,
|
||||
)
|
||||
if response:
|
||||
@@ -475,58 +472,39 @@ class TelegramNotificationService:
|
||||
async def _send_msg(
|
||||
self,
|
||||
func_send: Callable,
|
||||
msg_error: str,
|
||||
message_tag: str | None,
|
||||
*args_msg: Any,
|
||||
context: Context | None = None,
|
||||
suppress_error: bool = False,
|
||||
**kwargs_msg: Any,
|
||||
) -> Any:
|
||||
"""Send one message."""
|
||||
try:
|
||||
out = await func_send(*args_msg, **kwargs_msg)
|
||||
if isinstance(out, Message):
|
||||
chat_id = out.chat_id
|
||||
message_id = out.message_id
|
||||
self._last_message_id[chat_id] = message_id
|
||||
_LOGGER.debug(
|
||||
"Last message ID: %s (from chat_id %s)",
|
||||
self._last_message_id,
|
||||
chat_id,
|
||||
)
|
||||
|
||||
event_data: dict[str, Any] = {
|
||||
ATTR_CHAT_ID: chat_id,
|
||||
ATTR_MESSAGEID: message_id,
|
||||
}
|
||||
if message_tag is not None:
|
||||
event_data[ATTR_MESSAGE_TAG] = message_tag
|
||||
if kwargs_msg.get(ATTR_MESSAGE_THREAD_ID) is not None:
|
||||
event_data[ATTR_MESSAGE_THREAD_ID] = kwargs_msg[
|
||||
ATTR_MESSAGE_THREAD_ID
|
||||
]
|
||||
|
||||
event_data["bot"] = _get_bot_info(self.bot, self.config)
|
||||
|
||||
self.hass.bus.async_fire(
|
||||
EVENT_TELEGRAM_SENT, event_data, context=context
|
||||
)
|
||||
async_dispatcher_send(
|
||||
self.hass, signal(self.bot), EVENT_TELEGRAM_SENT, event_data
|
||||
)
|
||||
except TelegramError as exc:
|
||||
if not suppress_error:
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="action_failed",
|
||||
translation_placeholders={"error": str(exc)},
|
||||
) from exc
|
||||
|
||||
_LOGGER.error(
|
||||
"%s: %s. Args: %s, kwargs: %s", msg_error, exc, args_msg, kwargs_msg
|
||||
out = await func_send(*args_msg, **kwargs_msg)
|
||||
if isinstance(out, Message):
|
||||
chat_id = out.chat_id
|
||||
message_id = out.message_id
|
||||
self._last_message_id[chat_id] = message_id
|
||||
_LOGGER.debug(
|
||||
"Last message ID: %s (from chat_id %s)",
|
||||
self._last_message_id,
|
||||
chat_id,
|
||||
)
|
||||
|
||||
event_data: dict[str, Any] = {
|
||||
ATTR_CHAT_ID: chat_id,
|
||||
ATTR_MESSAGEID: message_id,
|
||||
}
|
||||
if message_tag is not None:
|
||||
event_data[ATTR_MESSAGE_TAG] = message_tag
|
||||
if kwargs_msg.get(ATTR_MESSAGE_THREAD_ID) is not None:
|
||||
event_data[ATTR_MESSAGE_THREAD_ID] = kwargs_msg[ATTR_MESSAGE_THREAD_ID]
|
||||
|
||||
event_data["bot"] = _get_bot_info(self.bot, self.config)
|
||||
|
||||
self.hass.bus.async_fire(EVENT_TELEGRAM_SENT, event_data, context=context)
|
||||
async_dispatcher_send(
|
||||
self.hass, signal(self.bot), EVENT_TELEGRAM_SENT, event_data
|
||||
)
|
||||
|
||||
return None
|
||||
return out
|
||||
|
||||
async def send_message(
|
||||
@@ -542,7 +520,6 @@ class TelegramNotificationService:
|
||||
params = self._get_msg_kwargs(kwargs)
|
||||
return await self._send_msgs(
|
||||
self.bot.send_message,
|
||||
"Error sending message",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
text,
|
||||
chat_id=chat_id,
|
||||
@@ -567,7 +544,6 @@ class TelegramNotificationService:
|
||||
_LOGGER.debug("Delete message %s in chat ID %s", message_id, chat_id)
|
||||
deleted: bool = await self._send_msg(
|
||||
self.bot.delete_message,
|
||||
"Error deleting message",
|
||||
None,
|
||||
chat_id,
|
||||
message_id,
|
||||
@@ -644,7 +620,6 @@ class TelegramNotificationService:
|
||||
|
||||
return await self._send_msg(
|
||||
self.bot.edit_message_media,
|
||||
"Error editing message media",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
media=media,
|
||||
chat_id=chat_id,
|
||||
@@ -678,7 +653,6 @@ class TelegramNotificationService:
|
||||
_LOGGER.debug("Editing message with ID %s", message_id or inline_message_id)
|
||||
return await self._send_msg(
|
||||
self.bot.edit_message_text,
|
||||
"Error editing text message",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
text,
|
||||
chat_id=chat_id,
|
||||
@@ -693,7 +667,6 @@ class TelegramNotificationService:
|
||||
if type_edit == SERVICE_EDIT_CAPTION:
|
||||
return await self._send_msg(
|
||||
self.bot.edit_message_caption,
|
||||
"Error editing message attributes",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=chat_id,
|
||||
message_id=message_id,
|
||||
@@ -707,7 +680,6 @@ class TelegramNotificationService:
|
||||
|
||||
return await self._send_msg(
|
||||
self.bot.edit_message_reply_markup,
|
||||
"Error editing message attributes",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=chat_id,
|
||||
message_id=message_id,
|
||||
@@ -735,7 +707,6 @@ class TelegramNotificationService:
|
||||
)
|
||||
await self._send_msg(
|
||||
self.bot.answer_callback_query,
|
||||
"Error sending answer callback query",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
callback_query_id,
|
||||
text=message,
|
||||
@@ -756,7 +727,6 @@ class TelegramNotificationService:
|
||||
_LOGGER.debug("Send action %s in chat ID %s", chat_action, chat_id)
|
||||
is_successful = await self._send_msg(
|
||||
self.bot.send_chat_action,
|
||||
"Error sending action",
|
||||
None,
|
||||
chat_id=chat_id,
|
||||
action=chat_action,
|
||||
@@ -791,7 +761,6 @@ class TelegramNotificationService:
|
||||
if file_type == SERVICE_SEND_PHOTO:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_photo,
|
||||
"Error sending photo",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
photo=file_content,
|
||||
@@ -808,7 +777,6 @@ class TelegramNotificationService:
|
||||
if file_type == SERVICE_SEND_STICKER:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_sticker,
|
||||
"Error sending sticker",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
sticker=file_content,
|
||||
@@ -823,7 +791,6 @@ class TelegramNotificationService:
|
||||
if file_type == SERVICE_SEND_VIDEO:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_video,
|
||||
"Error sending video",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
video=file_content,
|
||||
@@ -840,7 +807,6 @@ class TelegramNotificationService:
|
||||
if file_type == SERVICE_SEND_DOCUMENT:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_document,
|
||||
"Error sending document",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
document=file_content,
|
||||
@@ -857,7 +823,6 @@ class TelegramNotificationService:
|
||||
if file_type == SERVICE_SEND_VOICE:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_voice,
|
||||
"Error sending voice",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
voice=file_content,
|
||||
@@ -873,7 +838,6 @@ class TelegramNotificationService:
|
||||
# SERVICE_SEND_ANIMATION
|
||||
return await self._send_msgs(
|
||||
self.bot.send_animation,
|
||||
"Error sending animation",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
animation=file_content,
|
||||
@@ -899,7 +863,6 @@ class TelegramNotificationService:
|
||||
if stickerid:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_sticker,
|
||||
"Error sending sticker",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
sticker=stickerid,
|
||||
@@ -925,7 +888,6 @@ class TelegramNotificationService:
|
||||
params = self._get_msg_kwargs(kwargs)
|
||||
return await self._send_msgs(
|
||||
self.bot.send_location,
|
||||
"Error sending location",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
latitude=latitude,
|
||||
@@ -951,7 +913,6 @@ class TelegramNotificationService:
|
||||
openperiod = kwargs.get(ATTR_OPEN_PERIOD)
|
||||
return await self._send_msgs(
|
||||
self.bot.send_poll,
|
||||
"Error sending poll",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
question=question,
|
||||
@@ -974,9 +935,7 @@ class TelegramNotificationService:
|
||||
) -> Any:
|
||||
"""Remove bot from chat."""
|
||||
_LOGGER.debug("Leave from chat ID %s", chat_id)
|
||||
return await self._send_msg(
|
||||
self.bot.leave_chat, "Error leaving chat", None, chat_id, context=context
|
||||
)
|
||||
return await self._send_msg(self.bot.leave_chat, None, chat_id, context=context)
|
||||
|
||||
async def set_message_reaction(
|
||||
self,
|
||||
@@ -1000,7 +959,6 @@ class TelegramNotificationService:
|
||||
|
||||
await self._send_msg(
|
||||
self.bot.set_message_reaction,
|
||||
"Error setting message reaction",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id,
|
||||
message_id,
|
||||
@@ -1023,7 +981,6 @@ class TelegramNotificationService:
|
||||
directory_path = self.hass.config.path(DOMAIN)
|
||||
file: File = await self._send_msg(
|
||||
self.bot.get_file,
|
||||
"Error getting file",
|
||||
None,
|
||||
file_id=file_id,
|
||||
context=context,
|
||||
|
||||
@@ -353,7 +353,7 @@ async def test_send_sticker_partial_error(
|
||||
assert mock_send_sticker.call_count == 2
|
||||
assert err.value.translation_key == "multiple_errors"
|
||||
assert err.value.translation_placeholders == {
|
||||
"errors": "`entity_id` notify.mock_title_mock_chat_1: Action failed. mock network error\n`entity_id` notify.mock_title_mock_chat_2: Action failed. mock network error"
|
||||
"errors": "`entity_id` notify.mock_title_mock_chat_1: mock network error\n`entity_id` notify.mock_title_mock_chat_2: mock network error"
|
||||
}
|
||||
|
||||
|
||||
@@ -364,7 +364,7 @@ async def test_send_sticker_error(hass: HomeAssistant, webhook_bot) -> None:
|
||||
) as mock_bot:
|
||||
mock_bot.side_effect = NetworkError("mock network error")
|
||||
|
||||
with pytest.raises(HomeAssistantError) as err:
|
||||
with pytest.raises(TelegramError) as err:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SEND_STICKER,
|
||||
@@ -377,8 +377,8 @@ async def test_send_sticker_error(hass: HomeAssistant, webhook_bot) -> None:
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_bot.assert_called_once()
|
||||
assert err.value.translation_domain == DOMAIN
|
||||
assert err.value.translation_key == "action_failed"
|
||||
assert err.typename == "NetworkError"
|
||||
assert err.value.message == "mock network error"
|
||||
|
||||
|
||||
async def test_send_message_with_invalid_inline_keyboard(
|
||||
@@ -2264,7 +2264,7 @@ async def test_download_file_when_bot_failed_to_get_file(
|
||||
"homeassistant.components.telegram_bot.bot.Bot.get_file",
|
||||
AsyncMock(side_effect=TelegramError("failed to get file")),
|
||||
),
|
||||
pytest.raises(HomeAssistantError) as err,
|
||||
pytest.raises(TelegramError) as err,
|
||||
):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
@@ -2273,7 +2273,9 @@ async def test_download_file_when_bot_failed_to_get_file(
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert err.value.translation_key == "action_failed"
|
||||
|
||||
assert err.typename == "TelegramError"
|
||||
assert err.value.message == "failed to get file"
|
||||
|
||||
|
||||
async def test_download_file_when_empty_file_path(
|
||||
|
||||
Reference in New Issue
Block a user