Upgrade Telegram lib, refactor component for breaking changes (#44147)

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Olivér Falvai 2020-12-17 21:09:58 +01:00 committed by GitHub
parent d18c9f1c74
commit 6ffa3c18b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 147 additions and 47 deletions

View file

@ -553,7 +553,7 @@ class TelegramNotificationService:
)
return params
def _send_msg(self, func_send, msg_error, *args_msg, **kwargs_msg):
def _send_msg(self, func_send, msg_error, message_tag, *args_msg, **kwargs_msg):
"""Send one message."""
try:
@ -572,7 +572,6 @@ class TelegramNotificationService:
ATTR_CHAT_ID: chat_id,
ATTR_MESSAGEID: message_id,
}
message_tag = kwargs_msg.get(ATTR_MESSAGE_TAG)
if message_tag is not None:
event_data[ATTR_MESSAGE_TAG] = message_tag
self.hass.bus.async_fire(EVENT_TELEGRAM_SENT, event_data)
@ -594,7 +593,17 @@ class TelegramNotificationService:
for chat_id in self._get_target_chat_ids(target):
_LOGGER.debug("Send message in chat ID %s with params: %s", chat_id, params)
self._send_msg(
self.bot.sendMessage, "Error sending message", chat_id, text, **params
self.bot.send_message,
"Error sending message",
params[ATTR_MESSAGE_TAG],
chat_id,
text,
parse_mode=params[ATTR_PARSER],
disable_web_page_preview=params[ATTR_DISABLE_WEB_PREV],
disable_notification=params[ATTR_DISABLE_NOTIF],
reply_to_message_id=params[ATTR_REPLY_TO_MSGID],
reply_markup=params[ATTR_REPLYMARKUP],
timeout=params[ATTR_TIMEOUT],
)
def delete_message(self, chat_id=None, **kwargs):
@ -603,7 +612,7 @@ class TelegramNotificationService:
message_id, _ = self._get_msg_ids(kwargs, chat_id)
_LOGGER.debug("Delete message %s in chat ID %s", message_id, chat_id)
deleted = self._send_msg(
self.bot.deleteMessage, "Error deleting message", chat_id, message_id
self.bot.delete_message, "Error deleting message", None, chat_id, message_id
)
# reduce message_id anyway:
if self._last_message_id[chat_id] is not None:
@ -628,26 +637,41 @@ class TelegramNotificationService:
text = f"{title}\n{message}" if title else message
_LOGGER.debug("Editing message with ID %s", message_id or inline_message_id)
return self._send_msg(
self.bot.editMessageText,
self.bot.edit_message_text,
"Error editing text message",
params[ATTR_MESSAGE_TAG],
text,
chat_id=chat_id,
message_id=message_id,
inline_message_id=inline_message_id,
**params,
parse_mode=params[ATTR_PARSER],
disable_web_page_preview=params[ATTR_DISABLE_WEB_PREV],
reply_markup=params[ATTR_REPLYMARKUP],
timeout=params[ATTR_TIMEOUT],
)
if type_edit == SERVICE_EDIT_CAPTION:
func_send = self.bot.editMessageCaption
params[ATTR_CAPTION] = kwargs.get(ATTR_CAPTION)
else:
func_send = self.bot.editMessageReplyMarkup
return self._send_msg(
self.bot.edit_message_caption,
"Error editing message attributes",
params[ATTR_MESSAGE_TAG],
chat_id=chat_id,
message_id=message_id,
inline_message_id=inline_message_id,
caption=kwargs.get(ATTR_CAPTION),
reply_markup=params[ATTR_REPLYMARKUP],
timeout=params[ATTR_TIMEOUT],
parse_mode=params[ATTR_PARSER],
)
return self._send_msg(
func_send,
self.bot.edit_message_reply_markup,
"Error editing message attributes",
params[ATTR_MESSAGE_TAG],
chat_id=chat_id,
message_id=message_id,
inline_message_id=inline_message_id,
**params,
reply_markup=params[ATTR_REPLYMARKUP],
timeout=params[ATTR_TIMEOUT],
)
def answer_callback_query(
@ -662,26 +686,18 @@ class TelegramNotificationService:
show_alert,
)
self._send_msg(
self.bot.answerCallbackQuery,
self.bot.answer_callback_query,
"Error sending answer callback query",
params[ATTR_MESSAGE_TAG],
callback_query_id,
text=message,
show_alert=show_alert,
**params,
timeout=params[ATTR_TIMEOUT],
)
def send_file(self, file_type=SERVICE_SEND_PHOTO, target=None, **kwargs):
"""Send a photo, sticker, video, or document."""
params = self._get_msg_kwargs(kwargs)
caption = kwargs.get(ATTR_CAPTION)
func_send = {
SERVICE_SEND_PHOTO: self.bot.sendPhoto,
SERVICE_SEND_STICKER: self.bot.sendSticker,
SERVICE_SEND_ANIMATION: self.bot.sendAnimation,
SERVICE_SEND_VIDEO: self.bot.sendVideo,
SERVICE_SEND_VOICE: self.bot.sendVoice,
SERVICE_SEND_DOCUMENT: self.bot.sendDocument,
}.get(file_type)
file_content = load_data(
self.hass,
url=kwargs.get(ATTR_URL),
@ -691,17 +707,89 @@ class TelegramNotificationService:
authentication=kwargs.get(ATTR_AUTHENTICATION),
verify_ssl=kwargs.get(ATTR_VERIFY_SSL),
)
if file_content:
for chat_id in self._get_target_chat_ids(target):
_LOGGER.debug("Send file to chat ID %s. Caption: %s", chat_id, caption)
self._send_msg(
func_send,
"Error sending file",
chat_id,
file_content,
caption=caption,
**params,
)
_LOGGER.debug("Sending file to chat ID %s", chat_id)
if file_type == SERVICE_SEND_PHOTO:
self._send_msg(
self.bot.send_photo,
"Error sending photo",
params[ATTR_MESSAGE_TAG],
chat_id=chat_id,
photo=file_content,
caption=kwargs.get(ATTR_CAPTION),
disable_notification=params[ATTR_DISABLE_NOTIF],
reply_markup=params[ATTR_REPLYMARKUP],
timeout=params[ATTR_TIMEOUT],
parse_mode=params[ATTR_PARSER],
)
elif file_type == SERVICE_SEND_STICKER:
self._send_msg(
self.bot.send_sticker,
"Error sending sticker",
params[ATTR_MESSAGE_TAG],
chat_id=chat_id,
sticker=file_content,
disable_notification=params[ATTR_DISABLE_NOTIF],
reply_markup=params[ATTR_REPLYMARKUP],
timeout=params[ATTR_TIMEOUT],
)
elif file_type == SERVICE_SEND_VIDEO:
self._send_msg(
self.bot.send_video,
"Error sending video",
params[ATTR_MESSAGE_TAG],
chat_id=chat_id,
video=file_content,
caption=kwargs.get(ATTR_CAPTION),
disable_notification=params[ATTR_DISABLE_NOTIF],
reply_markup=params[ATTR_REPLYMARKUP],
timeout=params[ATTR_TIMEOUT],
parse_mode=params[ATTR_PARSER],
)
elif file_type == SERVICE_SEND_DOCUMENT:
self._send_msg(
self.bot.send_document,
"Error sending document",
params[ATTR_MESSAGE_TAG],
chat_id=chat_id,
document=file_content,
caption=kwargs.get(ATTR_CAPTION),
disable_notification=params[ATTR_DISABLE_NOTIF],
reply_markup=params[ATTR_REPLYMARKUP],
timeout=params[ATTR_TIMEOUT],
parse_mode=params[ATTR_PARSER],
)
elif file_type == SERVICE_SEND_VOICE:
self._send_msg(
self.bot.send_voice,
"Error sending voice",
params[ATTR_MESSAGE_TAG],
chat_id=chat_id,
voice=file_content,
caption=kwargs.get(ATTR_CAPTION),
disable_notification=params[ATTR_DISABLE_NOTIF],
reply_markup=params[ATTR_REPLYMARKUP],
timeout=params[ATTR_TIMEOUT],
)
elif file_type == SERVICE_SEND_ANIMATION:
self._send_msg(
self.bot.send_animation,
"Error sending animation",
params[ATTR_MESSAGE_TAG],
chat_id=chat_id,
animation=file_content,
caption=kwargs.get(ATTR_CAPTION),
disable_notification=params[ATTR_DISABLE_NOTIF],
reply_markup=params[ATTR_REPLYMARKUP],
timeout=params[ATTR_TIMEOUT],
parse_mode=params[ATTR_PARSER],
)
file_content.seek(0)
else:
_LOGGER.error("Can't send file with kwargs: %s", kwargs)
@ -716,19 +804,23 @@ class TelegramNotificationService:
"Send location %s/%s to chat ID %s", latitude, longitude, chat_id
)
self._send_msg(
self.bot.sendLocation,
self.bot.send_location,
"Error sending location",
params[ATTR_MESSAGE_TAG],
chat_id=chat_id,
latitude=latitude,
longitude=longitude,
**params,
disable_notification=params[ATTR_DISABLE_NOTIF],
timeout=params[ATTR_TIMEOUT],
)
def leave_chat(self, chat_id=None):
"""Remove bot from chat."""
chat_id = self._get_target_chat_ids(chat_id)[0]
_LOGGER.debug("Leave from chat ID %s", chat_id)
leaved = self._send_msg(self.bot.leaveChat, "Error leaving chat", chat_id)
leaved = self._send_msg(
self.bot.leave_chat, "Error leaving chat", None, chat_id
)
return leaved

View file

@ -2,7 +2,7 @@
"domain": "telegram_bot",
"name": "Telegram bot",
"documentation": "https://www.home-assistant.io/integrations/telegram_bot",
"requirements": ["python-telegram-bot==11.1.0", "PySocks==1.7.1"],
"requirements": ["python-telegram-bot==13.1", "PySocks==1.7.1"],
"dependencies": ["http"],
"codeowners": []
}

View file

@ -3,10 +3,10 @@ import logging
from telegram import Update
from telegram.error import NetworkError, RetryAfter, TelegramError, TimedOut
from telegram.ext import Handler, Updater
from telegram.ext import CallbackContext, Dispatcher, Handler, Updater
from telegram.utils.types import HandlerArg
from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import callback
from . import CONF_ALLOWED_CHAT_IDS, BaseTelegramBotEntity, initialize_bot
@ -18,12 +18,10 @@ async def async_setup_platform(hass, config):
bot = initialize_bot(config)
pol = TelegramPoll(bot, hass, config[CONF_ALLOWED_CHAT_IDS])
@callback
def _start_bot(_event):
"""Start the bot."""
pol.start_polling()
@callback
def _stop_bot(_event):
"""Stop the bot."""
pol.stop_polling()
@ -34,15 +32,15 @@ async def async_setup_platform(hass, config):
return True
def process_error(bot, update, error):
def process_error(update: Update, context: CallbackContext):
"""Telegram bot error handler."""
try:
raise error
raise context.error
except (TimedOut, NetworkError, RetryAfter):
# Long polling timeout or connection problem. Nothing serious.
pass
except TelegramError:
_LOGGER.error('Update "%s" caused error "%s"', update, error)
_LOGGER.error('Update "%s" caused error: "%s"', update, context.error)
def message_handler(handler):
@ -59,10 +57,17 @@ def message_handler(handler):
"""Check is update valid."""
return isinstance(update, Update)
def handle_update(self, update, dispatcher):
def handle_update(
self,
update: HandlerArg,
dispatcher: Dispatcher,
check_result: object,
context: CallbackContext = None,
):
"""Handle update."""
optional_args = self.collect_optional_args(dispatcher, update)
return self.callback(dispatcher.bot, update, **optional_args)
context.args = optional_args
return self.callback(update, context)
return MessageHandler()
@ -89,6 +94,6 @@ class TelegramPoll(BaseTelegramBotEntity):
"""Stop the polling task."""
self.updater.stop()
def process_update(self, bot, update):
def process_update(self, update: HandlerArg, context: CallbackContext):
"""Process incoming message."""
self.process_message(update.to_dict())

View file

@ -374,6 +374,9 @@ answer_callback_query:
show_alert:
description: Show a permanent notification.
example: true
timeout:
description: Timeout for sending the answer. Will help with timeout errors (poor internet connection, etc)
example: "1000"
delete_message:
description: Delete a previously sent message.

View file

@ -1816,7 +1816,7 @@ python-songpal==0.12
python-tado==0.8.1
# homeassistant.components.telegram_bot
python-telegram-bot==11.1.0
python-telegram-bot==13.1
# homeassistant.components.vlc_telnet
python-telnet-vlc==1.0.4