Bug fix for Telegram bot integration: handle last message id (#146378)

This commit is contained in:
hanwg 2025-06-10 02:01:16 +08:00 committed by GitHub
parent f401ffb08c
commit d58157ca9e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 55 additions and 16 deletions

View File

@ -241,6 +241,7 @@ class TelegramNotificationService:
self._parse_mode = self._parsers.get(parser) self._parse_mode = self._parsers.get(parser)
self.bot = bot self.bot = bot
self.hass = hass self.hass = hass
self._last_message_id: dict[int, int] = {}
def _get_allowed_chat_ids(self) -> list[int]: def _get_allowed_chat_ids(self) -> list[int]:
allowed_chat_ids: list[int] = [ allowed_chat_ids: list[int] = [
@ -260,9 +261,6 @@ class TelegramNotificationService:
return allowed_chat_ids return allowed_chat_ids
def _get_last_message_id(self):
return dict.fromkeys(self._get_allowed_chat_ids())
def _get_msg_ids(self, msg_data, chat_id): def _get_msg_ids(self, msg_data, chat_id):
"""Get the message id to edit. """Get the message id to edit.
@ -277,9 +275,9 @@ class TelegramNotificationService:
if ( if (
isinstance(message_id, str) isinstance(message_id, str)
and (message_id == "last") and (message_id == "last")
and (self._get_last_message_id()[chat_id] is not None) and (chat_id in self._last_message_id)
): ):
message_id = self._get_last_message_id()[chat_id] message_id = self._last_message_id[chat_id]
else: else:
inline_message_id = msg_data["inline_message_id"] inline_message_id = msg_data["inline_message_id"]
return message_id, inline_message_id return message_id, inline_message_id
@ -408,10 +406,10 @@ class TelegramNotificationService:
if not isinstance(out, bool) and hasattr(out, ATTR_MESSAGEID): if not isinstance(out, bool) and hasattr(out, ATTR_MESSAGEID):
chat_id = out.chat_id chat_id = out.chat_id
message_id = out[ATTR_MESSAGEID] message_id = out[ATTR_MESSAGEID]
self._get_last_message_id()[chat_id] = message_id self._last_message_id[chat_id] = message_id
_LOGGER.debug( _LOGGER.debug(
"Last message ID: %s (from chat_id %s)", "Last message ID: %s (from chat_id %s)",
self._get_last_message_id(), self._last_message_id,
chat_id, chat_id,
) )
@ -480,9 +478,9 @@ class TelegramNotificationService:
context=context, context=context,
) )
# reduce message_id anyway: # reduce message_id anyway:
if self._get_last_message_id()[chat_id] is not None: if chat_id in self._last_message_id:
# change last msg_id for deque(n_msgs)? # change last msg_id for deque(n_msgs)?
self._get_last_message_id()[chat_id] -= 1 self._last_message_id[chat_id] -= 1
return deleted return deleted
async def edit_message(self, type_edit, chat_id=None, context=None, **kwargs): async def edit_message(self, type_edit, chat_id=None, context=None, **kwargs):

View File

@ -255,8 +255,8 @@ def mock_broadcast_config_entry() -> MockConfigEntry:
options={ATTR_PARSER: PARSER_MD}, options={ATTR_PARSER: PARSER_MD},
subentries_data=[ subentries_data=[
ConfigSubentryData( ConfigSubentryData(
unique_id="1234567890", unique_id="123456",
data={CONF_CHAT_ID: 1234567890}, data={CONF_CHAT_ID: 123456},
subentry_id="mock_id", subentry_id="mock_id",
subentry_type=CONF_ALLOWED_CHAT_IDS, subentry_type=CONF_ALLOWED_CHAT_IDS,
title="mock chat", title="mock chat",

View File

@ -413,7 +413,7 @@ async def test_subentry_flow_chat_error(
with patch( with patch(
"homeassistant.components.telegram_bot.config_flow.Bot.get_chat", "homeassistant.components.telegram_bot.config_flow.Bot.get_chat",
return_value=ChatFullInfo( return_value=ChatFullInfo(
id=1234567890, id=123456,
title="mock title", title="mock title",
first_name="mock first_name", first_name="mock first_name",
type="PRIVATE", type="PRIVATE",
@ -423,7 +423,7 @@ async def test_subentry_flow_chat_error(
): ):
result = await hass.config_entries.subentries.async_configure( result = await hass.config_entries.subentries.async_configure(
result["flow_id"], result["flow_id"],
user_input={CONF_CHAT_ID: 1234567890}, user_input={CONF_CHAT_ID: 123456},
) )
await hass.async_block_till_done() await hass.async_block_till_done()

View File

@ -17,8 +17,10 @@ from telegram.error import (
from homeassistant.components.telegram_bot import ( from homeassistant.components.telegram_bot import (
ATTR_CALLBACK_QUERY_ID, ATTR_CALLBACK_QUERY_ID,
ATTR_CAPTION,
ATTR_CHAT_ID, ATTR_CHAT_ID,
ATTR_FILE, ATTR_FILE,
ATTR_KEYBOARD_INLINE,
ATTR_LATITUDE, ATTR_LATITUDE,
ATTR_LONGITUDE, ATTR_LONGITUDE,
ATTR_MESSAGE, ATTR_MESSAGE,
@ -34,7 +36,9 @@ from homeassistant.components.telegram_bot import (
PLATFORM_BROADCAST, PLATFORM_BROADCAST,
SERVICE_ANSWER_CALLBACK_QUERY, SERVICE_ANSWER_CALLBACK_QUERY,
SERVICE_DELETE_MESSAGE, SERVICE_DELETE_MESSAGE,
SERVICE_EDIT_CAPTION,
SERVICE_EDIT_MESSAGE, SERVICE_EDIT_MESSAGE,
SERVICE_EDIT_REPLYMARKUP,
SERVICE_SEND_ANIMATION, SERVICE_SEND_ANIMATION,
SERVICE_SEND_DOCUMENT, SERVICE_SEND_DOCUMENT,
SERVICE_SEND_LOCATION, SERVICE_SEND_LOCATION,
@ -629,14 +633,23 @@ async def test_delete_message(
await hass.config_entries.async_setup(mock_broadcast_config_entry.entry_id) await hass.config_entries.async_setup(mock_broadcast_config_entry.entry_id)
await hass.async_block_till_done() await hass.async_block_till_done()
response = await hass.services.async_call(
DOMAIN,
SERVICE_SEND_MESSAGE,
{ATTR_MESSAGE: "mock message"},
blocking=True,
return_response=True,
)
assert response["chats"][0]["message_id"] == 12345
with patch( with patch(
"homeassistant.components.telegram_bot.bot.TelegramNotificationService.delete_message", "homeassistant.components.telegram_bot.bot.Bot.delete_message",
AsyncMock(return_value=True), AsyncMock(return_value=True),
) as mock: ) as mock:
await hass.services.async_call( await hass.services.async_call(
DOMAIN, DOMAIN,
SERVICE_DELETE_MESSAGE, SERVICE_DELETE_MESSAGE,
{ATTR_CHAT_ID: 12345, ATTR_MESSAGEID: 12345}, {ATTR_CHAT_ID: 123456, ATTR_MESSAGEID: "last"},
blocking=True, blocking=True,
) )
@ -655,7 +668,7 @@ async def test_edit_message(
await hass.async_block_till_done() await hass.async_block_till_done()
with patch( with patch(
"homeassistant.components.telegram_bot.bot.TelegramNotificationService.edit_message", "homeassistant.components.telegram_bot.bot.Bot.edit_message_text",
AsyncMock(return_value=True), AsyncMock(return_value=True),
) as mock: ) as mock:
await hass.services.async_call( await hass.services.async_call(
@ -668,6 +681,34 @@ async def test_edit_message(
await hass.async_block_till_done() await hass.async_block_till_done()
mock.assert_called_once() mock.assert_called_once()
with patch(
"homeassistant.components.telegram_bot.bot.Bot.edit_message_caption",
AsyncMock(return_value=True),
) as mock:
await hass.services.async_call(
DOMAIN,
SERVICE_EDIT_CAPTION,
{ATTR_CAPTION: "mock caption", ATTR_CHAT_ID: 12345, ATTR_MESSAGEID: 12345},
blocking=True,
)
await hass.async_block_till_done()
mock.assert_called_once()
with patch(
"homeassistant.components.telegram_bot.bot.Bot.edit_message_reply_markup",
AsyncMock(return_value=True),
) as mock:
await hass.services.async_call(
DOMAIN,
SERVICE_EDIT_REPLYMARKUP,
{ATTR_KEYBOARD_INLINE: [], ATTR_CHAT_ID: 12345, ATTR_MESSAGEID: 12345},
blocking=True,
)
await hass.async_block_till_done()
mock.assert_called_once()
async def test_async_setup_entry_failed( async def test_async_setup_entry_failed(
hass: HomeAssistant, mock_broadcast_config_entry: MockConfigEntry hass: HomeAssistant, mock_broadcast_config_entry: MockConfigEntry