diff --git a/README.md b/README.md
index 9d49ff2e7..289e38d7a 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
A simple, but extensible Python implementation for the Telegram Bot API.
Both synchronous and asynchronous.
-## Supported Bot API version: 6.9!
+##
Supported Bot API version: 7.0!
diff --git a/telebot/__init__.py b/telebot/__init__.py
index 4a4324507..3cbc6d7b1 100644
--- a/telebot/__init__.py
+++ b/telebot/__init__.py
@@ -217,6 +217,8 @@ def __init__(
self.edited_message_handlers = []
self.channel_post_handlers = []
self.edited_channel_post_handlers = []
+ self.message_reaction_handlers = []
+ self.message_reaction_count_handlers = []
self.inline_handlers = []
self.chosen_inline_handlers = []
self.callback_query_handlers = []
@@ -227,6 +229,8 @@ def __init__(
self.my_chat_member_handlers = []
self.chat_member_handlers = []
self.chat_join_request_handlers = []
+ self.chat_boost_handlers = []
+ self.removed_chat_boost_handlers = []
self.custom_filters = {}
self.state_handlers = []
@@ -670,6 +674,8 @@ def process_new_updates(self, updates: List[types.Update]):
new_edited_messages = None
new_channel_posts = None
new_edited_channel_posts = None
+ new_message_reactions = None
+ new_message_reaction_counts = None
new_inline_queries = None
new_chosen_inline_results = None
new_callback_queries = None
@@ -680,6 +686,8 @@ def process_new_updates(self, updates: List[types.Update]):
new_my_chat_members = None
new_chat_members = None
new_chat_join_request = None
+ new_chat_boosts = None
+ new_removed_chat_boosts = None
for update in updates:
if apihelper.ENABLE_MIDDLEWARE and not self.use_class_middlewares:
@@ -737,6 +745,18 @@ def process_new_updates(self, updates: List[types.Update]):
if update.chat_join_request:
if new_chat_join_request is None: new_chat_join_request = []
new_chat_join_request.append(update.chat_join_request)
+ if update.message_reaction:
+ if new_message_reactions is None: new_message_reactions = []
+ new_message_reactions.append(update.message_reaction)
+ if update.message_reaction_count:
+ if new_message_reaction_counts is None: new_message_reaction_counts = []
+ new_message_reaction_counts.append(update.message_reaction_count)
+ if update.chat_boost:
+ if new_chat_boosts is None: new_chat_boosts = []
+ new_chat_boosts.append(update.chat_boost)
+ if update.removed_chat_boost:
+ if new_removed_chat_boosts is None: new_removed_chat_boosts = []
+ new_removed_chat_boosts.append(update.removed_chat_boost)
if new_messages:
self.process_new_messages(new_messages)
@@ -766,6 +786,14 @@ def process_new_updates(self, updates: List[types.Update]):
self.process_new_chat_member(new_chat_members)
if new_chat_join_request:
self.process_new_chat_join_request(new_chat_join_request)
+ if new_message_reactions:
+ self.process_new_message_reaction(new_message_reactions)
+ if new_message_reaction_counts:
+ self.process_new_message_reaction_count(new_message_reaction_counts)
+ if new_chat_boosts:
+ self.process_new_chat_boost(new_chat_boosts)
+ if new_removed_chat_boosts:
+ self.process_new_removed_chat_boost(new_removed_chat_boosts)
def process_new_messages(self, new_messages):
"""
@@ -776,23 +804,35 @@ def process_new_messages(self, new_messages):
self.__notify_update(new_messages)
self._notify_command_handlers(self.message_handlers, new_messages, 'message')
- def process_new_edited_messages(self, edited_message):
+ def process_new_edited_messages(self, new_edited_message):
"""
:meta private:
"""
- self._notify_command_handlers(self.edited_message_handlers, edited_message, 'edited_message')
+ self._notify_command_handlers(self.edited_message_handlers, new_edited_message, 'edited_message')
- def process_new_channel_posts(self, channel_post):
+ def process_new_channel_posts(self, new_channel_post):
"""
:meta private:
"""
- self._notify_command_handlers(self.channel_post_handlers, channel_post, 'channel_post')
+ self._notify_command_handlers(self.channel_post_handlers, new_channel_post, 'channel_post')
- def process_new_edited_channel_posts(self, edited_channel_post):
+ def process_new_edited_channel_posts(self, new_edited_channel_post):
"""
:meta private:
"""
- self._notify_command_handlers(self.edited_channel_post_handlers, edited_channel_post, 'edited_channel_post')
+ self._notify_command_handlers(self.edited_channel_post_handlers, new_edited_channel_post, 'edited_channel_post')
+
+ def process_new_message_reaction(self, new_message_reactions):
+ """
+ :meta private:
+ """
+ self._notify_command_handlers(self.message_reaction_handlers, new_message_reactions, 'message_reaction')
+
+ def process_new_message_reaction_count(self, new_message_reaction_counts):
+ """
+ :meta private:
+ """
+ self._notify_command_handlers(self.message_reaction_count_handlers, new_message_reaction_counts, 'message_reaction_count')
def process_new_inline_query(self, new_inline_queries):
"""
@@ -818,41 +858,54 @@ def process_new_shipping_query(self, new_shipping_queries):
"""
self._notify_command_handlers(self.shipping_query_handlers, new_shipping_queries, 'shipping_query')
- def process_new_pre_checkout_query(self, pre_checkout_queries):
+ def process_new_pre_checkout_query(self, new_pre_checkout_queries):
"""
:meta private:
"""
- self._notify_command_handlers(self.pre_checkout_query_handlers, pre_checkout_queries, 'pre_checkout_query')
+ self._notify_command_handlers(self.pre_checkout_query_handlers, new_pre_checkout_queries, 'pre_checkout_query')
- def process_new_poll(self, polls):
+ def process_new_poll(self, new_polls):
"""
:meta private:
"""
- self._notify_command_handlers(self.poll_handlers, polls, 'poll')
+ self._notify_command_handlers(self.poll_handlers, new_polls, 'poll')
- def process_new_poll_answer(self, poll_answers):
+ def process_new_poll_answer(self, new_poll_answers):
"""
:meta private:
"""
- self._notify_command_handlers(self.poll_answer_handlers, poll_answers, 'poll_answer')
+ self._notify_command_handlers(self.poll_answer_handlers, new_poll_answers, 'poll_answer')
- def process_new_my_chat_member(self, my_chat_members):
+ def process_new_my_chat_member(self, new_my_chat_members):
"""
:meta private:
"""
- self._notify_command_handlers(self.my_chat_member_handlers, my_chat_members, 'my_chat_member')
+ self._notify_command_handlers(self.my_chat_member_handlers, new_my_chat_members, 'my_chat_member')
- def process_new_chat_member(self, chat_members):
+ def process_new_chat_member(self, new_chat_members):
"""
:meta private:
"""
- self._notify_command_handlers(self.chat_member_handlers, chat_members, 'chat_member')
+ self._notify_command_handlers(self.chat_member_handlers, new_chat_members, 'chat_member')
- def process_new_chat_join_request(self, chat_join_request):
+ def process_new_chat_join_request(self, new_chat_join_request):
"""
:meta private:
"""
- self._notify_command_handlers(self.chat_join_request_handlers, chat_join_request, 'chat_join_request')
+ self._notify_command_handlers(self.chat_join_request_handlers, new_chat_join_request, 'chat_join_request')
+
+ def process_new_chat_boost(self, new_chat_boosts):
+ """
+ :meta private:
+ """
+ self._notify_command_handlers(self.chat_boost_handlers, new_chat_boosts, 'chat_boost')
+
+ def process_new_removed_chat_boost(self, new_removed_chat_boosts):
+ """
+ :meta private:
+ """
+ self._notify_command_handlers(self.removed_chat_boost_handlers, new_removed_chat_boosts, 'removed_chat_boost')
+
def process_middlewares(self, update):
"""
@@ -1303,6 +1356,29 @@ def close(self) -> bool:
:return: :obj:`bool`
"""
return apihelper.close(self.token)
+
+ def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reaction: Optional[List[types.ReactionType]]=None, is_big: Optional[bool]=None) -> bool:
+ """
+ Use this method to set a reaction to a message in a chat. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
+
+ Telegram documentation: https://core.telegram.org/bots/api#setmessagereaction
+
+ :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)
+ :type chat_id: :obj:`int` or :obj:`str`
+
+ :param message_id: Identifier of the message to set reaction to
+ :type message_id: :obj:`int`
+
+ :param reaction: New list of reaction types to set on the message. Currently, as non-premium users, bots can set up to one reaction per message.
+ A custom emoji reaction can be used if it is either already present on the message or explicitly allowed by chat administrators.
+ :type reaction: :obj:`list` of :class:`telebot.types.ReactionType`
+
+ :param is_big: Pass True to set the reaction with a big animation
+ :type is_big: :obj:`bool`
+
+ :return: :obj:`bool`
+ """
+ return apihelper.set_message_reaction(self.token, chat_id, message_id, reaction, is_big)
def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None,
@@ -1474,14 +1550,16 @@ def send_message(
self, chat_id: Union[int, str], text: str,
parse_mode: Optional[str]=None,
entities: Optional[List[types.MessageEntity]]=None,
- disable_web_page_preview: Optional[bool]=None,
+ disable_web_page_preview: Optional[bool]=None, # deprecated, for backward compatibility
disable_notification: Optional[bool]=None,
protect_content: Optional[bool]=None,
- reply_to_message_id: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
timeout: Optional[int]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None,
+ link_preview_options : Optional[types.LinkPreviewOptions]=None) -> types.Message:
"""
Use this method to send text messages.
@@ -1503,7 +1581,7 @@ def send_message(
:param entities: List of special entities that appear in message text, which can be specified instead of parse_mode
:type entities: Array of :class:`telebot.types.MessageEntity`
- :param disable_web_page_preview: Disables link previews for links in this message
+ :param disable_web_page_preview: deprecated. Disables link previews for links in this message
:type disable_web_page_preview: :obj:`bool`
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
@@ -1512,10 +1590,10 @@ def send_message(
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
:type reply_to_message_id: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
:type allow_sending_without_reply: :obj:`bool`
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
@@ -1528,20 +1606,61 @@ def send_message(
:param message_thread_id: Identifier of a message thread, in which the message will be sent
:type message_thread_id: :obj:`int`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
+ :param link_preview_options: Link preview options.
+ :type link_preview_options: :class:`telebot.types.LinkPreviewOptions`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
parse_mode = self.parse_mode if (parse_mode is None) else parse_mode
- disable_web_page_preview = self.disable_web_page_preview if (disable_web_page_preview is None) else disable_web_page_preview
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
+
+ if disable_web_page_preview is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.")
+
+ if link_preview_options:
+ # show a conflict warning
+ logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated")
+ else:
+ # create a LinkPreviewOptions object
+ link_preview_options = types.LinkPreviewOptions(
+ disable_web_page_preview=disable_web_page_preview
+ )
+
+ if link_preview_options and (link_preview_options.disable_web_page_preview is None):
+ link_preview_options.disable_web_page_preview = self.disable_web_page_preview
return types.Message.de_json(
apihelper.send_message(
- self.token, chat_id, text, disable_web_page_preview, reply_to_message_id,
+ self.token, chat_id, text,
reply_markup, parse_mode, disable_notification, timeout,
- entities, allow_sending_without_reply, protect_content=protect_content, message_thread_id=message_thread_id))
+ entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, link_preview_options=link_preview_options))
def forward_message(
self, chat_id: Union[int, str], from_chat_id: Union[int, str],
@@ -1595,11 +1714,11 @@ def copy_message(
caption_entities: Optional[List[types.MessageEntity]]=None,
disable_notification: Optional[bool]=None,
protect_content: Optional[bool]=None,
- reply_to_message_id: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
- reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
timeout: Optional[int]=None,
- message_thread_id: Optional[int]=None) -> types.MessageID:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.MessageID:
"""
Use this method to copy messages of any kind.
@@ -1628,10 +1747,10 @@ def copy_message(
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
:type reply_to_message_id: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
:type allow_sending_without_reply: :obj:`bool`
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard
@@ -1644,6 +1763,9 @@ def copy_message(
:param message_thread_id: Identifier of a message thread, in which the message will be sent
:type message_thread_id: :obj:`int`
+
+ :param reply_parameters: Additional parameters for replies to messages
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the MessageId of the sent message is returned.
:rtype: :class:`telebot.types.MessageID`
@@ -1651,12 +1773,32 @@ def copy_message(
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
parse_mode = self.parse_mode if (parse_mode is None) else parse_mode
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
return types.MessageID.de_json(
apihelper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities,
- disable_notification, reply_to_message_id, allow_sending_without_reply, reply_markup,
- timeout, protect_content, message_thread_id))
+ disable_notification, reply_markup,
+ timeout, protect_content, message_thread_id, reply_parameters))
def delete_message(self, chat_id: Union[int, str], message_id: int,
timeout: Optional[int]=None) -> bool:
@@ -1686,16 +1828,108 @@ def delete_message(self, chat_id: Union[int, str], message_id: int,
:rtype: :obj:`bool`
"""
return apihelper.delete_message(self.token, chat_id, message_id, timeout)
+
+ def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]):
+ """
+ Use this method to delete multiple messages in a chat.
+ The number of messages to be deleted must not exceed 100.
+ If the chat is a private chat, the user must be an administrator of the chat for this to work and must have the appropriate admin rights.
+ Returns True on success.
+
+ Telegram documentation: https://core.telegram.org/bots/api#deletemessages
+
+ :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername)
+ :type chat_id: :obj:`int` or :obj:`str`
+
+ :param message_ids: Identifiers of the messages to be deleted
+ :type message_ids: :obj:`list` of :obj:`int`
+
+ :return: Returns True on success.
+
+ """
+ return apihelper.delete_messages(self.token, chat_id, message_ids)
+
+ def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None,
+ message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]:
+ """
+ Use this method to forward messages of any kind.
+
+ :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername)
+ :type chat_id: :obj:`int` or :obj:`str`
+
+ :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername)
+ :type from_chat_id: :obj:`int` or :obj:`str`
+
+ :param message_ids: Message identifiers in the chat specified in from_chat_id
+ :type message_ids: :obj:`list`
+
+ :param disable_notification: Sends the message silently. Users will receive a notification with no sound
+ :type disable_notification: :obj:`bool`
+
+ :param message_thread_id: Identifier of a message thread, in which the messages will be sent
+ :type message_thread_id: :obj:`int`
+
+ :param protect_content: Protects the contents of the forwarded message from forwarding and saving
+ :type protect_content: :obj:`bool`
+
+ :return: On success, the sent Message is returned.
+ :rtype: :class:`telebot.types.MessageID`
+ """
+
+ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
+ protect_content = self.protect_content if (protect_content is None) else protect_content
+
+ return [types.MessageID.de_json(message_id) for message_id in
+ apihelper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id)]
+
+ def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int],
+ disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None,
+ protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]:
+ """
+ Use this method to copy messages of any kind.
+
+ :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername)
+ :type chat_id: :obj:`int` or :obj:`str`
+
+ :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername)
+ :type from_chat_id: :obj:`int` or :obj:`str`
+
+ :param message_ids: Message identifiers in the chat specified in from_chat_id
+ :type message_ids: :obj:`list` of :obj:`int`
+
+ :param disable_notification: Sends the message silently. Users will receive a notification with no sound
+ :type disable_notification: :obj:`bool`
+
+ :param message_thread_id: Identifier of a message thread, in which the messages will be sent
+ :type message_thread_id: :obj:`int`
+
+ :param protect_content: Protects the contents of the forwarded message from forwarding and saving
+ :type protect_content: :obj:`bool`
+
+ :param remove_caption: Pass True to copy the messages without their captions
+ :type remove_caption: :obj:`bool`
+
+ :return: On success, an array of MessageId of the sent messages is returned.
+ :rtype: :obj:`list` of :class:`telebot.types.MessageID`
+ """
+ disable_notification = self.disable_notification if disable_notification is None else disable_notification
+ protect_content = self.protect_content if protect_content is None else protect_content
+
+ return [types.MessageID.de_json(message_id) for message_id in
+ apihelper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification,
+ protect_content, message_thread_id, remove_caption)]
+
def send_dice(
self, chat_id: Union[int, str],
emoji: Optional[str]=None, disable_notification: Optional[bool]=None,
- reply_to_message_id: Optional[int]=None,
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
timeout: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned.
@@ -1711,37 +1945,60 @@ def send_dice(
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
:type disable_notification: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
- :type reply_to_message_id: :obj:`int`
-
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions
to remove reply keyboard or to force a reply from the user.
:type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove`
or :class:`telebot.types.ForceReply`
- :param timeout: Timeout in seconds for the request.
- :type timeout: :obj:`int`
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
+ :type reply_to_message_id: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
:type allow_sending_without_reply: :obj:`bool`
+ :param timeout: Timeout in seconds for the request.
+ :type timeout: :obj:`int`
+
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
:param message_thread_id: Identifier of a message thread, in which the message will be sent
:type message_thread_id: :obj:`int`
+ :param reply_parameters: Additional parameters for replies to messages
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
return types.Message.de_json(
apihelper.send_dice(
- self.token, chat_id, emoji, disable_notification, reply_to_message_id,
- reply_markup, timeout, allow_sending_without_reply, protect_content, message_thread_id)
+ self.token, chat_id, emoji, disable_notification,
+ reply_markup, timeout, protect_content, message_thread_id, reply_parameters)
)
@@ -1751,12 +2008,13 @@ def send_photo(
caption_entities: Optional[List[types.MessageEntity]]=None,
disable_notification: Optional[bool]=None,
protect_content: Optional[bool]=None,
- reply_to_message_id: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
timeout: Optional[int]=None,
message_thread_id: Optional[int]=None,
- has_spoiler: Optional[bool]=None) -> types.Message:
+ has_spoiler: Optional[bool]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send photos. On success, the sent Message is returned.
@@ -1785,10 +2043,10 @@ def send_photo(
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
:type reply_to_message_id: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
:type allow_sending_without_reply: :obj:`bool`
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions
@@ -1804,6 +2062,9 @@ def send_photo(
:param has_spoiler: Pass True, if the photo should be sent as a spoiler
:type has_spoiler: :obj:`bool`
+
+ :param reply_parameters: Additional parameters for replies to messages
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
@@ -1811,30 +2072,51 @@ def send_photo(
parse_mode = self.parse_mode if (parse_mode is None) else parse_mode
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
return types.Message.de_json(
apihelper.send_photo(
- self.token, chat_id, photo, caption, reply_to_message_id, reply_markup,
+ self.token, chat_id, photo, caption, reply_markup,
parse_mode, disable_notification, timeout, caption_entities,
- allow_sending_without_reply, protect_content, message_thread_id, has_spoiler))
+ protect_content, message_thread_id, has_spoiler, reply_parameters))
# TODO: Rewrite this method like in API.
def send_audio(
self, chat_id: Union[int, str], audio: Union[Any, str],
caption: Optional[str]=None, duration: Optional[int]=None,
performer: Optional[str]=None, title: Optional[str]=None,
- reply_to_message_id: Optional[int]=None,
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
parse_mode: Optional[str]=None,
disable_notification: Optional[bool]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
timeout: Optional[int]=None,
thumbnail: Optional[Union[Any, str]]=None,
caption_entities: Optional[List[types.MessageEntity]]=None,
- allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
message_thread_id: Optional[int]=None,
- thumb: Optional[Union[Any, str]]=None,) -> types.Message:
+ thumb: Optional[Union[Any, str]]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send audio files, if you want Telegram clients to display them in the music player.
Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size,
@@ -1864,9 +2146,6 @@ def send_audio(
:param title: Track name
:type title: :obj:`str`
- :param reply_to_message_id: If the message is a reply, ID of the original message
- :type reply_to_message_id: :obj:`int`
-
:param reply_markup:
:type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove`
or :class:`telebot.types.ForceReply`
@@ -1877,6 +2156,12 @@ def send_audio(
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
:type disable_notification: :obj:`bool`
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
+ :type reply_to_message_id: :obj:`int`
+
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
+ :type allow_sending_without_reply: :obj:`bool`
+
:param timeout: Timeout in seconds for the request.
:type timeout: :obj:`int`
@@ -1889,9 +2174,6 @@ def send_audio(
:param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode
:type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
- :type allow_sending_without_reply: :obj:`bool`
-
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
@@ -1901,13 +2183,36 @@ def send_audio(
:param thumb: Deprecated. Use thumbnail instead
:type thumb: :obj:`str` or :class:`telebot.types.InputFile`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
parse_mode = self.parse_mode if (parse_mode is None) else parse_mode
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
if thumb is not None and thumbnail is None:
thumbnail = thumb
@@ -1915,23 +2220,24 @@ def send_audio(
return types.Message.de_json(
apihelper.send_audio(
- self.token, chat_id, audio, caption, duration, performer, title, reply_to_message_id,
+ self.token, chat_id, audio, caption, duration, performer, title,
reply_markup, parse_mode, disable_notification, timeout, thumbnail,
- caption_entities, allow_sending_without_reply, protect_content, message_thread_id))
+ caption_entities, protect_content, message_thread_id, reply_parameters))
# TODO: Rewrite this method like in API.
def send_voice(
self, chat_id: Union[int, str], voice: Union[Any, str],
caption: Optional[str]=None, duration: Optional[int]=None,
- reply_to_message_id: Optional[int]=None,
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
parse_mode: Optional[str]=None,
disable_notification: Optional[bool]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
timeout: Optional[int]=None,
caption_entities: Optional[List[types.MessageEntity]]=None,
- allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message.
For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as Audio or Document).
@@ -1952,9 +2258,6 @@ def send_voice(
:param duration: Duration of the voice message in seconds
:type duration: :obj:`int`
- :param reply_to_message_id: If the message is a reply, ID of the original message
- :type reply_to_message_id: :obj:`int`
-
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions
to remove reply keyboard or to force a reply from the user.
:type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove`
@@ -1966,51 +2269,78 @@ def send_voice(
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
:type disable_notification: :obj:`bool`
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
+ :type reply_to_message_id: :obj:`int`
+
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
+ :type allow_sending_without_reply: :obj:`bool`
+
:param timeout: Timeout in seconds for the request.
:type timeout: :obj:`int`
:param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode
:type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
- :type allow_sending_without_reply: :obj:`bool`
-
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
:param message_thread_id: Identifier of a message thread, in which the message will be sent
:type message_thread_id: :obj:`int`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
"""
parse_mode = self.parse_mode if (parse_mode is None) else parse_mode
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
return types.Message.de_json(
apihelper.send_voice(
- self.token, chat_id, voice, caption, duration, reply_to_message_id, reply_markup,
+ self.token, chat_id, voice, caption, duration, reply_markup,
parse_mode, disable_notification, timeout, caption_entities,
- allow_sending_without_reply, protect_content, message_thread_id))
+ protect_content, message_thread_id, reply_parameters))
# TODO: Rewrite this method like in API.
def send_document(
self, chat_id: Union[int, str], document: Union[Any, str],
- reply_to_message_id: Optional[int]=None,
caption: Optional[str]=None,
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
parse_mode: Optional[str]=None,
disable_notification: Optional[bool]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
timeout: Optional[int]=None,
thumbnail: Optional[Union[Any, str]]=None,
caption_entities: Optional[List[types.MessageEntity]]=None,
- allow_sending_without_reply: Optional[bool]=None,
visible_file_name: Optional[str]=None,
disable_content_type_detection: Optional[bool]=None,
data: Optional[Union[Any, str]]=None,
protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None,
- thumb: Optional[Union[Any, str]]=None,) -> types.Message:
+ thumb: Optional[Union[Any, str]]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send general files.
@@ -2023,9 +2353,6 @@ def send_document(
String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data
:type document: :obj:`str` or :class:`telebot.types.InputFile`
- :param reply_to_message_id: If the message is a reply, ID of the original message
- :type reply_to_message_id: :obj:`int`
-
:param caption: Document caption (may also be used when resending documents by file_id), 0-1024 characters after entities parsing
:type caption: :obj:`str`
@@ -2040,6 +2367,12 @@ def send_document(
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
:type disable_notification: :obj:`bool`
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
+ :type reply_to_message_id: :obj:`int`
+
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
+ :type allow_sending_without_reply: :obj:`bool`
+
:param timeout: Timeout in seconds for the request.
:type timeout: :obj:`int`
@@ -2049,9 +2382,6 @@ def send_document(
:param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode
:type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
- :type allow_sending_without_reply: :obj:`bool`
-
:param visible_file_name: allows to define file name that will be visible in the Telegram instead of original file name
:type visible_file_name: :obj:`str`
@@ -2070,13 +2400,36 @@ def send_document(
:param thumb: Deprecated. Use thumbnail instead
:type thumb: :obj:`str` or :class:`telebot.types.InputFile`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
parse_mode = self.parse_mode if (parse_mode is None) else parse_mode
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
if data and (not document):
# function typo miss compatibility
@@ -2090,26 +2443,26 @@ def send_document(
return types.Message.de_json(
apihelper.send_data(
self.token, chat_id, document, 'document',
- reply_to_message_id = reply_to_message_id, reply_markup = reply_markup, parse_mode = parse_mode,
+ reply_parameters=reply_parameters, reply_markup = reply_markup, parse_mode = parse_mode,
disable_notification = disable_notification, timeout = timeout, caption = caption, thumbnail= thumbnail,
- caption_entities = caption_entities, allow_sending_without_reply = allow_sending_without_reply,
- disable_content_type_detection = disable_content_type_detection, visible_file_name = visible_file_name,
- protect_content = protect_content, message_thread_id = message_thread_id))
+ caption_entities = caption_entities, disable_content_type_detection = disable_content_type_detection,
+ visible_file_name = visible_file_name, protect_content = protect_content, message_thread_id = message_thread_id))
# TODO: Rewrite this method like in API.
def send_sticker(
self, chat_id: Union[int, str],
sticker: Union[Any, str],
- reply_to_message_id: Optional[int]=None,
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
disable_notification: Optional[bool]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
timeout: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
protect_content:Optional[bool]=None,
data: Union[Any, str]=None,
message_thread_id: Optional[int]=None,
- emoji: Optional[str]=None) -> types.Message:
+ emoji: Optional[str]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers.
On success, the sent Message is returned.
@@ -2123,9 +2476,6 @@ def send_sticker(
as a String for Telegram to get a .webp file from the Internet, or upload a new one using multipart/form-data.
:type sticker: :obj:`str` or :class:`telebot.types.InputFile`
- :param reply_to_message_id: If the message is a reply, ID of the original message
- :type reply_to_message_id: :obj:`int`
-
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard
or to force a reply from the user.
:type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove`
@@ -2134,12 +2484,15 @@ def send_sticker(
:param disable_notification: to disable the notification
:type disable_notification: :obj:`bool`
- :param timeout: Timeout in seconds for the request.
- :type timeout: :obj:`int`
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
+ :type reply_to_message_id: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
:type allow_sending_without_reply: :obj:`bool`
+ :param timeout: Timeout in seconds for the request.
+ :type timeout: :obj:`int`
+
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
@@ -2152,25 +2505,47 @@ def send_sticker(
:param emoji: Emoji associated with the sticker; only for just uploaded stickers
:type emoji: :obj:`str`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
if data and (not sticker):
# function typo miss compatibility
logger.warning('The parameter "data" is deprecated. Use "sticker" instead.')
sticker = data
-
+
return types.Message.de_json(
apihelper.send_data(
- self.token, chat_id, sticker, 'sticker',
- reply_to_message_id=reply_to_message_id, reply_markup=reply_markup,
+ self.token, chat_id, sticker, 'sticker', reply_markup=reply_markup,
disable_notification=disable_notification, timeout=timeout,
- allow_sending_without_reply=allow_sending_without_reply,
- protect_content=protect_content, message_thread_id=message_thread_id, emoji=emoji))
+ protect_content=protect_content, message_thread_id=message_thread_id, emoji=emoji,
+ reply_parameters=reply_parameters))
def send_video(
self, chat_id: Union[int, str], video: Union[Any, str],
@@ -2184,14 +2559,15 @@ def send_video(
supports_streaming: Optional[bool]=None,
disable_notification: Optional[bool]=None,
protect_content: Optional[bool]=None,
- reply_to_message_id: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
timeout: Optional[int]=None,
data: Optional[Union[Any, str]]=None,
message_thread_id: Optional[int]=None,
has_spoiler: Optional[bool]=None,
- thumb: Optional[Union[Any, str]]=None,) -> types.Message:
+ thumb: Optional[Union[Any, str]]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document).
@@ -2233,10 +2609,10 @@ def send_video(
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
:type reply_to_message_id: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
:type allow_sending_without_reply: :obj:`bool`
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard
@@ -2259,13 +2635,36 @@ def send_video(
:param thumb: Deprecated. Use thumbnail instead
:type thumb: :obj:`str` or :class:`telebot.types.InputFile`
+ :param reply_parameters: Reply parameters
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
parse_mode = self.parse_mode if (parse_mode is None) else parse_mode
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
if data and (not video):
# function typo miss compatibility
@@ -2278,9 +2677,9 @@ def send_video(
return types.Message.de_json(
apihelper.send_video(
- self.token, chat_id, video, duration, caption, reply_to_message_id, reply_markup,
+ self.token, chat_id, video, duration, caption, reply_markup,
parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height,
- caption_entities, allow_sending_without_reply, protect_content, message_thread_id, has_spoiler))
+ caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters))
def send_animation(
self, chat_id: Union[int, str], animation: Union[Any, str],
@@ -2293,13 +2692,14 @@ def send_animation(
caption_entities: Optional[List[types.MessageEntity]]=None,
disable_notification: Optional[bool]=None,
protect_content: Optional[bool]=None,
- reply_to_message_id: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
timeout: Optional[int]=None,
message_thread_id: Optional[int]=None,
has_spoiler: Optional[bool]=None,
- thumb: Optional[Union[Any, str]]=None,) -> types.Message:
+ thumb: Optional[Union[Any, str]]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound).
On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future.
@@ -2337,9 +2737,12 @@ def send_animation(
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
:type reply_to_message_id: :obj:`int`
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
+ :type allow_sending_without_reply: :obj:`bool`
+
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard
or to force a reply from the user.
:type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove`
@@ -2354,9 +2757,6 @@ def send_animation(
:param caption_entities: List of special entities that appear in the caption, which can be specified instead of parse_mode
:type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
- :type allow_sending_without_reply: :obj:`bool`
-
:param message_thread_id: Identifier of a message thread, in which the video will be sent
:type message_thread_id: :obj:`int`
@@ -2366,37 +2766,61 @@ def send_animation(
:param thumb: Deprecated. Use thumbnail instead
:type thumb: :obj:`str` or :class:`telebot.types.InputFile`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
parse_mode = self.parse_mode if (parse_mode is None) else parse_mode
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
if thumbnail is None and thumb is not None:
thumbnail = thumb
logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.')
return types.Message.de_json(
apihelper.send_animation(
- self.token, chat_id, animation, duration, caption, reply_to_message_id,
+ self.token, chat_id, animation, duration, caption,
reply_markup, parse_mode, disable_notification, timeout, thumbnail,
- caption_entities, allow_sending_without_reply, protect_content, width, height, message_thread_id, has_spoiler))
+ caption_entities, protect_content, width, height, message_thread_id, has_spoiler, reply_parameters))
# TODO: Rewrite this method like in API.
def send_video_note(
self, chat_id: Union[int, str], data: Union[Any, str],
duration: Optional[int]=None,
length: Optional[int]=None,
- reply_to_message_id: Optional[int]=None,
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
disable_notification: Optional[bool]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
timeout: Optional[int]=None,
thumbnail: Optional[Union[Any, str]]=None,
- allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
message_thread_id: Optional[int]=None,
- thumb: Optional[Union[Any, str]]=None) -> types.Message:
+ thumb: Optional[Union[Any, str]]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long.
Use this method to send video messages. On success, the sent Message is returned.
@@ -2416,9 +2840,6 @@ def send_video_note(
:param length: Video width and height, i.e. diameter of the video message
:type length: :obj:`int`
- :param reply_to_message_id: If the message is a reply, ID of the original message
- :type reply_to_message_id: :obj:`int`
-
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard
or to force a reply from the user.
:type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove`
@@ -2427,6 +2848,12 @@ def send_video_note(
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
:type disable_notification: :obj:`bool`
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
+ :type reply_to_message_id: :obj:`int`
+
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
+ :type allow_sending_without_reply: :obj:`bool`
+
:param timeout: Timeout in seconds for the request.
:type timeout: :obj:`int`
@@ -2436,9 +2863,6 @@ def send_video_note(
so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under .
:type thumbnail: :obj:`str` or :class:`telebot.types.InputFile`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
- :type allow_sending_without_reply: :obj:`bool`
-
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
@@ -2446,13 +2870,37 @@ def send_video_note(
:type message_thread_id: :obj:`int`
:param thumb: Deprecated. Use thumbnail instead
- :type thumb: :obj:`str` or :class:`telebot.types.InputFile`
+ :type thumb: :obj:`str` or :class:`telebot.types.InputFile`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
if thumbnail is None and thumb is not None:
thumbnail = thumb
@@ -2460,8 +2908,8 @@ def send_video_note(
return types.Message.de_json(
apihelper.send_video_note(
- self.token, chat_id, data, duration, length, reply_to_message_id, reply_markup,
- disable_notification, timeout, thumbnail, allow_sending_without_reply, protect_content, message_thread_id))
+ self.token, chat_id, data, duration, length, reply_markup,
+ disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters))
def send_media_group(
@@ -2471,10 +2919,11 @@ def send_media_group(
types.InputMediaPhoto, types.InputMediaVideo]],
disable_notification: Optional[bool]=None,
protect_content: Optional[bool]=None,
- reply_to_message_id: Optional[int]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
timeout: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> List[types.Message]:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> List[types.Message]:
"""
Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files
can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned.
@@ -2493,28 +2942,51 @@ def send_media_group(
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
:type reply_to_message_id: :obj:`int`
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
+ :type allow_sending_without_reply: :obj:`bool`
+
:param timeout: Timeout in seconds for the request.
:type timeout: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
- :type allow_sending_without_reply: :obj:`bool`
-
:param message_thread_id: Identifier of a message thread, in which the media group will be sent
:type message_thread_id: :obj:`int`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, an array of Messages that were sent is returned.
:rtype: List[types.Message]
"""
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
result = apihelper.send_media_group(
- self.token, chat_id, media, disable_notification, reply_to_message_id, timeout,
- allow_sending_without_reply, protect_content, message_thread_id)
+ self.token, chat_id, media, disable_notification, timeout,
+ protect_content, message_thread_id, reply_parameters)
return [types.Message.de_json(msg) for msg in result]
# TODO: Rewrite this method like in API.
@@ -2522,16 +2994,17 @@ def send_location(
self, chat_id: Union[int, str],
latitude: float, longitude: float,
live_period: Optional[int]=None,
- reply_to_message_id: Optional[int]=None,
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
disable_notification: Optional[bool]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
timeout: Optional[int]=None,
horizontal_accuracy: Optional[float]=None,
heading: Optional[int]=None,
proximity_alert_radius: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send point on the map. On success, the sent Message is returned.
@@ -2549,9 +3022,6 @@ def send_location(
:param live_period: Period in seconds for which the location will be updated (see Live Locations, should be between 60 and 86400.
:type live_period: :obj:`int`
- :param reply_to_message_id: If the message is a reply, ID of the original message
- :type reply_to_message_id: :obj:`int`
-
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard
or to force a reply from the user.
:type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove`
@@ -2560,6 +3030,12 @@ def send_location(
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
:type disable_notification: :obj:`bool`
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
+ :type reply_to_message_id: :obj:`int`
+
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
+ :type allow_sending_without_reply: :obj:`bool`
+
:param timeout: Timeout in seconds for the request.
:type timeout: :obj:`int`
@@ -2572,28 +3048,48 @@ def send_location(
:param proximity_alert_radius: For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified.
:type proximity_alert_radius: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
- :type allow_sending_without_reply: :obj:`bool`
-
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
:param message_thread_id: Identifier of a message thread, in which the message will be sent
:type message_thread_id: :obj:`int`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
return types.Message.de_json(
apihelper.send_location(
self.token, chat_id, latitude, longitude, live_period,
- reply_to_message_id, reply_markup, disable_notification, timeout,
+ reply_markup, disable_notification, timeout,
horizontal_accuracy, heading, proximity_alert_radius,
- allow_sending_without_reply, protect_content, message_thread_id))
+ protect_content, message_thread_id, reply_parameters))
def edit_message_live_location(
self, latitude: float, longitude: float,
@@ -2695,14 +3191,15 @@ def send_venue(
foursquare_id: Optional[str]=None,
foursquare_type: Optional[str]=None,
disable_notification: Optional[bool]=None,
- reply_to_message_id: Optional[int]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
timeout: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
google_place_id: Optional[str]=None,
google_place_type: Optional[str]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send information about a venue. On success, the sent Message is returned.
@@ -2733,9 +3230,12 @@ def send_venue(
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
:type disable_notification: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
:type reply_to_message_id: :obj:`int`
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
+ :type allow_sending_without_reply: :obj:`bool`
+
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard,
custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
:type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove`
@@ -2744,10 +3244,6 @@ def send_venue(
:param timeout: Timeout in seconds for the request.
:type timeout: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if one of the specified
- replied-to messages is not found.
- :type allow_sending_without_reply: :obj:`bool`
-
:param google_place_id: Google Places identifier of the venue
:type google_place_id: :obj:`str`
@@ -2760,18 +3256,41 @@ def send_venue(
:param message_thread_id: The thread identifier of a message from which the reply will be sent
:type message_thread_id: :obj:`int`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
return types.Message.de_json(
apihelper.send_venue(
self.token, chat_id, latitude, longitude, title, address, foursquare_id, foursquare_type,
- disable_notification, reply_to_message_id, reply_markup, timeout,
- allow_sending_without_reply, google_place_id, google_place_type, protect_content, message_thread_id))
+ disable_notification, reply_markup, timeout,
+ google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters))
# TODO: Rewrite this method like in API.
@@ -2780,11 +3299,12 @@ def send_contact(
first_name: str, last_name: Optional[str]=None,
vcard: Optional[str]=None,
disable_notification: Optional[bool]=None,
- reply_to_message_id: Optional[int]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
timeout: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
- protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None) -> types.Message:
+ protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send phone contacts. On success, the sent Message is returned.
@@ -2808,9 +3328,12 @@ def send_contact(
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
:type disable_notification: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
:type reply_to_message_id: :obj:`int`
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
+ :type allow_sending_without_reply: :obj:`bool`
+
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard,
custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
:type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove`
@@ -2819,28 +3342,47 @@ def send_contact(
:param timeout: Timeout in seconds for the request.
:type timeout: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if one of the specified
- replied-to messages is not found.
- :type allow_sending_without_reply: :obj:`bool`
-
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
:param message_thread_id: The thread identifier of a message from which the reply will be sent
:type message_thread_id: :obj:`int`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
return types.Message.de_json(
apihelper.send_contact(
self.token, chat_id, phone_number, first_name, last_name, vcard,
- disable_notification, reply_to_message_id, reply_markup, timeout,
- allow_sending_without_reply, protect_content, message_thread_id))
+ disable_notification, reply_markup, timeout,
+ protect_content, message_thread_id, reply_parameters))
def send_chat_action(
self, chat_id: Union[int, str], action: str, timeout: Optional[int]=None, message_thread_id: Optional[int]=None) -> bool:
@@ -3791,8 +4333,9 @@ def edit_message_text(
inline_message_id: Optional[str]=None,
parse_mode: Optional[str]=None,
entities: Optional[List[types.MessageEntity]]=None,
- disable_web_page_preview: Optional[bool]=None,
- reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> Union[types.Message, bool]:
+ disable_web_page_preview: Optional[bool]=None, # deprecated, for backward compatibility
+ reply_markup: Optional[types.InlineKeyboardMarkup]=None,
+ link_preview_options : Optional[types.LinkPreviewOptions]=None) -> Union[types.Message, bool]:
"""
Use this method to edit text and game messages.
@@ -3816,20 +4359,38 @@ def edit_message_text(
:param entities: List of special entities that appear in the message text, which can be specified instead of parse_mode
:type entities: List of :obj:`telebot.types.MessageEntity`
- :param disable_web_page_preview: Disables link previews for links in this message
+ :param disable_web_page_preview: deprecated. Disables link previews for links in this message
:type disable_web_page_preview: :obj:`bool`
:param reply_markup: A JSON-serialized object for an inline keyboard.
:type reply_markup: :obj:`InlineKeyboardMarkup`
+ :param link_preview_options: A JSON-serialized object for options used to automatically generate previews for links.
+ :type link_preview_options: :obj:`LinkPreviewOptions`
+
:return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned.
:rtype: :obj:`types.Message` or :obj:`bool`
"""
parse_mode = self.parse_mode if (parse_mode is None) else parse_mode
- disable_web_page_preview = self.disable_web_page_preview if (disable_web_page_preview is None) else disable_web_page_preview
+
+ if disable_web_page_preview is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.")
+
+ if link_preview_options:
+ # show a conflict warning
+ logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated")
+ else:
+ # create a LinkPreviewOptions object
+ link_preview_options = types.LinkPreviewOptions(
+ disable_web_page_preview=disable_web_page_preview
+ )
+
+ if link_preview_options and (link_preview_options.disable_web_page_preview is None):
+ link_preview_options.disable_web_page_preview = self.disable_web_page_preview
result = apihelper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode,
- entities, disable_web_page_preview, reply_markup)
+ entities, reply_markup, link_preview_options)
if type(result) == bool: # if edit inline message return is bool not Message.
return result
return types.Message.de_json(result)
@@ -3902,12 +4463,13 @@ def edit_message_reply_markup(
def send_game(
self, chat_id: Union[int, str], game_short_name: str,
disable_notification: Optional[bool]=None,
- reply_to_message_id: Optional[int]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
timeout: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Used to send the game.
@@ -3922,35 +4484,58 @@ def send_game(
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
:type disable_notification: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
:type reply_to_message_id: :obj:`int`
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
+ :type allow_sending_without_reply: :obj:`bool`
+
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
:type reply_markup: :obj:`InlineKeyboardMarkup` or :obj:`ReplyKeyboardMarkup` or :obj:`ReplyKeyboardRemove` or :obj:`ForceReply`
:param timeout: Timeout in seconds for waiting for a response from the bot.
:type timeout: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if one of the specified replied-to messages is not found.
- :type allow_sending_without_reply: :obj:`bool`
-
:param protect_content: Protects the contents of the sent message from forwarding and saving
:type protect_content: :obj:`bool`
:param message_thread_id: The identifier of a message thread, in which the game message will be sent.
:type message_thread_id: :obj:`int`
+ :param reply_parameters: Reply parameters
+ :type reply_parameters: :obj:`ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :obj:`types.Message`
"""
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
result = apihelper.send_game(
self.token, chat_id, game_short_name, disable_notification,
- reply_to_message_id, reply_markup, timeout,
- allow_sending_without_reply, protect_content, message_thread_id)
+ reply_markup, timeout,
+ protect_content, message_thread_id, reply_parameters)
return types.Message.de_json(result)
def set_game_score(
@@ -4040,15 +4625,16 @@ def send_invoice(
send_email_to_provider: Optional[bool]=None,
is_flexible: Optional[bool]=None,
disable_notification: Optional[bool]=None,
- reply_to_message_id: Optional[int]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
provider_data: Optional[str]=None,
timeout: Optional[int]=None,
- allow_sending_without_reply: Optional[bool]=None,
max_tip_amount: Optional[int] = None,
suggested_tip_amounts: Optional[List[int]]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Sends invoice.
@@ -4119,9 +4705,12 @@ def send_invoice(
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
:type disable_notification: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
:type reply_to_message_id: :obj:`int`
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
+ :type allow_sending_without_reply: :obj:`bool`
+
:param reply_markup: A JSON-serialized object for an inline keyboard. If empty,
one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button
:type reply_markup: :obj:`str`
@@ -4133,9 +4722,6 @@ def send_invoice(
:param timeout: Timeout of a request, defaults to None
:type timeout: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found
- :type allow_sending_without_reply: :obj:`bool`
-
:param max_tip_amount: The maximum accepted amount for tips in the smallest units of the currency
:type max_tip_amount: :obj:`int`
@@ -4150,20 +4736,43 @@ def send_invoice(
:param message_thread_id: The identifier of a message thread, in which the invoice message will be sent
:type message_thread_id: :obj:`int`
+ :param reply_parameters: Required if the message is a reply. Additional interface options.
+ :type reply_parameters: :obj:`types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :obj:`types.Message`
"""
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
result = apihelper.send_invoice(
self.token, chat_id, title, description, invoice_payload, provider_token,
currency, prices, start_parameter, photo_url, photo_size, photo_width,
photo_height, need_name, need_phone_number, need_email, need_shipping_address,
send_phone_number_to_provider, send_email_to_provider, is_flexible, disable_notification,
- reply_to_message_id, reply_markup, provider_data, timeout, allow_sending_without_reply,
- max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id)
+ reply_markup, provider_data, timeout,
+ max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id, reply_parameters)
return types.Message.de_json(result)
def create_invoice_link(self,
@@ -4282,13 +4891,14 @@ def send_poll(
close_date: Optional[Union[int, datetime]]=None,
is_closed: Optional[bool]=None,
disable_notification: Optional[bool]=False,
- reply_to_message_id: Optional[int]=None,
+ reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility
+ allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
- allow_sending_without_reply: Optional[bool]=None,
timeout: Optional[int]=None,
explanation_entities: Optional[List[types.MessageEntity]]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send a native poll.
On success, the sent Message is returned.
@@ -4336,10 +4946,10 @@ def send_poll(
:param disable_notification: Sends the message silently. Users will receive a notification with no sound.
:type disable_notification: :obj:`bool`
- :param reply_to_message_id: If the message is a reply, ID of the original message
+ :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message
:type reply_to_message_id: :obj:`int`
- :param allow_sending_without_reply: Pass True, if the poll allows multiple options to be voted simultaneously.
+ :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found
:type allow_sending_without_reply: :obj:`bool`
:param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard,
@@ -4359,12 +4969,35 @@ def send_poll(
:param message_thread_id: The identifier of a message thread, in which the poll will be sent
:type message_thread_id: :obj:`int`
+ :param reply_parameters: reply parameters.
+ :type reply_parameters: :obj:`ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :obj:`types.Message`
"""
disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
protect_content = self.protect_content if (protect_content is None) else protect_content
- allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+
+ if allow_sending_without_reply is not None:
+ # show a deprecation warning
+ logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.")
+
+ if reply_parameters:
+ # show a conflict warning
+ logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated")
+ else:
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ reply_to_message_id,
+ allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ )
+
+ if reply_parameters and (reply_parameters.allow_sending_without_reply is None):
+ reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply
if isinstance(question, types.Poll):
raise RuntimeError("The send_poll signature was changed, please see send_poll function details.")
@@ -4377,8 +5010,8 @@ def send_poll(
question, options,
is_anonymous, type, allows_multiple_answers, correct_option_id,
explanation, explanation_parse_mode, open_period, close_date, is_closed,
- disable_notification, reply_to_message_id, allow_sending_without_reply,
- reply_markup, timeout, explanation_entities, protect_content, message_thread_id))
+ disable_notification,reply_markup, timeout, explanation_entities, protect_content, message_thread_id,
+ reply_parameters))
def stop_poll(
self, chat_id: Union[int, str], message_id: int,
@@ -4624,6 +5257,25 @@ def answer_callback_query(
:rtype: :obj:`bool`
"""
return apihelper.answer_callback_query(self.token, callback_query_id, text, show_alert, url, cache_time)
+
+ def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types.UserChatBoosts:
+ """
+ Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a UserChatBoosts object.
+
+ Telegram documentation: https://core.telegram.org/bots/api#getuserchatboosts
+
+ :param chat_id: Unique identifier for the target chat or username of the target channel
+ :type chat_id: :obj:`int` | :obj:`str`
+
+ :param user_id: Unique identifier of the target user
+ :type user_id: :obj:`int`
+
+ :return: On success, a UserChatBoosts object is returned.
+ :rtype: :class:`telebot.types.UserChatBoosts`
+ """
+
+ result = apihelper.get_user_chat_boosts(self.token, chat_id, user_id)
+ return types.UserChatBoosts.de_json(result)
def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None):
"""
@@ -6174,6 +6826,109 @@ def register_edited_channel_post_handler(self, callback: Callable, content_types
**kwargs)
self.add_edited_channel_post_handler(handler_dict)
+
+ def message_reaction_handler(self, func=None, **kwargs):
+ """
+ Handles new incoming message reaction.
+ As a parameter to the decorator function, it passes :class:`telebot.types.MessageReactionUpdated` object.
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return:
+ """
+ def decorator(handler):
+ handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
+ self.add_message_reaction_handler(handler_dict)
+ return handler
+
+ return decorator
+
+ def add_message_reaction_handler(self, handler_dict):
+ """
+ Adds message reaction handler
+ Note that you should use register_message_reaction_handler to add message_reaction_handler to the bot.
+
+ :meta private:
+
+ :param handler_dict:
+ :return:
+ """
+ self.message_reaction_handlers.append(handler_dict)
+
+ def register_message_reaction_handler(self, callback: Callable, func: Callable=None, pass_bot: Optional[bool]=False, **kwargs):
+ """
+ Registers message reaction handler.
+
+ :param callback: function to be called
+ :type callback: :obj:`function`
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
+ :type pass_bot: :obj:`bool`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return: None
+ """
+ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
+ self.add_message_reaction_handler(handler_dict)
+
+ def message_reaction_count_handler(self, func=None, **kwargs):
+ """
+ Handles new incoming message reaction count.
+ As a parameter to the decorator function, it passes :class:`telebot.types.MessageReactionCountUpdated` object.
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return:
+ """
+ def decorator(handler):
+ handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
+ self.add_message_reaction_count_handler(handler_dict)
+ return handler
+
+ return decorator
+
+ def add_message_reaction_count_handler(self, handler_dict):
+ """
+ Adds message reaction count handler
+ Note that you should use register_message_reaction_count_handler to add message_reaction_count_handler to the bot.
+
+ :meta private:
+
+ :param handler_dict:
+ :return:
+ """
+ self.message_reaction_count_handlers.append(handler_dict)
+
+ def register_message_reaction_count_handler(self, callback: Callable, func: Callable=None, pass_bot: Optional[bool]=False, **kwargs):
+ """
+ Registers message reaction count handler.
+
+ :param callback: function to be called
+ :type callback: :obj:`function`
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
+ :type pass_bot: :obj:`bool`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return: None
+ """
+ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
+ self.add_message_reaction_count_handler(handler_dict)
+
def inline_handler(self, func, **kwargs):
"""
Handles new incoming inline query.
@@ -6688,6 +7443,105 @@ def register_chat_join_request_handler(self, callback: Callable, func: Optional[
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
self.add_chat_join_request_handler(handler_dict)
+ def chat_boost_handler(self, func=None, **kwargs):
+ """
+ Handles new incoming chat boost state.
+ it passes :class:`telebot.types.ChatBoostUpdated` object.
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+ :return: None
+ """
+ def decorator(handler):
+ handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
+ self.add_chat_boost_handler(handler_dict)
+ return handler
+
+ return decorator
+
+ def add_chat_boost_handler(self, handler_dict):
+ """
+ Adds a chat_boost handler.
+ Note that you should use register_chat_boost_handler to add chat_boost_handler to the bot.
+
+ :meta private:
+
+ :param handler_dict:
+ :return:
+ """
+ self.chat_boost_handlers.append(handler_dict)
+
+ def register_chat_boost_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs):
+ """
+ Registers chat boost handler.
+
+ :param callback: function to be called
+ :type callback: :obj:`function`
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return: None
+ """
+ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
+ self.add_chat_boost_handler(handler_dict)
+
+ def removed_chat_boost_handler(self, func=None, **kwargs):
+ """
+ Handles new incoming chat boost state.
+ it passes :class:`telebot.types.ChatBoostRemoved` object.
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+ :return: None
+ """
+ def decorator(handler):
+ handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
+ self.add_removed_chat_boost_handler(handler_dict)
+ return handler
+
+ return decorator
+
+ def add_removed_chat_boost_handler(self, handler_dict):
+ """
+ Adds a removed_chat_boost handler.
+ Note that you should use register_removed_chat_boost_handler to add removed_chat_boost_handler to the bot.
+
+ :meta private:
+
+ :param handler_dict:
+ :return:
+ """
+ self.removed_chat_boost_handlers.append(handler_dict)
+
+ def register_removed_chat_boost_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs):
+ """
+ Registers removed chat boost handler.
+
+ :param callback: function to be called
+ :type callback: :obj:`function`
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return: None
+ """
+ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
+ self.add_removed_chat_boost_handler(handler_dict)
+
+
def _test_message_handler(self, message_handler, message):
"""
Test message handler
diff --git a/telebot/apihelper.py b/telebot/apihelper.py
index bfee49967..d307e9bae 100644
--- a/telebot/apihelper.py
+++ b/telebot/apihelper.py
@@ -237,16 +237,14 @@ def download_file(token, file_path):
def send_message(
token, chat_id, text,
- disable_web_page_preview=None, reply_to_message_id=None, reply_markup=None,
+ reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None,
- entities=None, allow_sending_without_reply=None, protect_content=None,
- message_thread_id=None):
+ entities=None, protect_content=None,
+ message_thread_id=None, reply_parameters=None, link_preview_options=None):
method_url = r'sendMessage'
payload = {'chat_id': str(chat_id), 'text': text}
- if disable_web_page_preview is not None:
- payload['disable_web_page_preview'] = disable_web_page_preview
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if link_preview_options is not None:
+ payload['link_preview'] = link_preview_options.to_json()
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if parse_mode:
@@ -257,12 +255,12 @@ def send_message(
payload['timeout'] = timeout
if entities:
payload['entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload, method='post')
@@ -332,6 +330,16 @@ def get_user_profile_photos(token, user_id, offset=None, limit=None):
payload['limit'] = limit
return _make_request(token, method_url, params=payload)
+def set_message_reaction(token, chat_id, message_id, reaction=None, is_big=None):
+ method_url = r'setMessageReaction'
+ payload = {'chat_id': chat_id, 'message_id': message_id}
+ if reaction:
+ payload['reaction'] = json.dumps([r.to_dict() for r in reaction])
+ if is_big is not None:
+ payload['is_big'] = is_big
+ return _make_request(token, method_url, params=payload)
+
+
def get_chat(token, chat_id):
method_url = r'getChat'
@@ -404,8 +412,8 @@ def forward_message(
def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None,
- disable_notification=None, reply_to_message_id=None, allow_sending_without_reply=None,
- reply_markup=None, timeout=None, protect_content=None, message_thread_id=None):
+ disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None,
+ reply_parameters=None):
method_url = r'copyMessage'
payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id}
if caption is not None:
@@ -416,12 +424,8 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m
payload['caption_entities'] = _convert_entites(caption_entities)
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
- if reply_markup is not None:
- payload['reply_markup'] = _convert_markup(reply_markup)
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
if timeout:
payload['timeout'] = timeout
if protect_content is not None:
@@ -433,35 +437,33 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m
def send_dice(
token, chat_id,
- emoji=None, disable_notification=None, reply_to_message_id=None,
- reply_markup=None, timeout=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ emoji=None, disable_notification=None,
+ reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None):
method_url = r'sendDice'
payload = {'chat_id': chat_id}
if emoji:
payload['emoji'] = emoji
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload)
def send_photo(
token, chat_id, photo,
- caption=None, reply_to_message_id=None, reply_markup=None,
+ caption=None, reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None,
- caption_entities=None, allow_sending_without_reply=None, protect_content=None,
- message_thread_id=None, has_spoiler=None):
+ caption_entities=None, protect_content=None,
+ message_thread_id=None, has_spoiler=None, reply_parameters=None):
method_url = r'sendPhoto'
payload = {'chat_id': chat_id}
files = None
@@ -473,8 +475,6 @@ def send_photo(
files = {'photo': photo}
if caption:
payload['caption'] = caption
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if parse_mode:
@@ -485,36 +485,34 @@ def send_photo(
payload['timeout'] = timeout
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
if has_spoiler is not None:
payload['has_spoiler'] = has_spoiler
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload, files=files, method='post')
def send_media_group(
token, chat_id, media,
- disable_notification=None, reply_to_message_id=None,
- timeout=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ disable_notification=None,
+ timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None):
method_url = r'sendMediaGroup'
media_json, files = convert_input_media_array(media)
payload = {'chat_id': chat_id, 'media': media_json}
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(
token, method_url, params=payload,
method='post' if files else 'get',
@@ -523,11 +521,11 @@ def send_media_group(
def send_location(
token, chat_id, latitude, longitude,
- live_period=None, reply_to_message_id=None,
+ live_period=None,
reply_markup=None, disable_notification=None,
timeout=None, horizontal_accuracy=None, heading=None,
- proximity_alert_radius=None, allow_sending_without_reply=None, protect_content=None,
- message_thread_id=None):
+ proximity_alert_radius=None, protect_content=None,
+ message_thread_id=None, reply_parameters=None):
method_url = r'sendLocation'
payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude}
if live_period:
@@ -538,10 +536,6 @@ def send_location(
payload['heading'] = heading
if proximity_alert_radius:
payload['proximity_alert_radius'] = proximity_alert_radius
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if disable_notification is not None:
@@ -552,6 +546,8 @@ def send_location(
payload['protect_content'] = protect_content
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload)
@@ -601,9 +597,8 @@ def stop_message_live_location(
def send_venue(
token, chat_id, latitude, longitude, title, address,
foursquare_id=None, foursquare_type=None, disable_notification=None,
- reply_to_message_id=None, reply_markup=None, timeout=None,
- allow_sending_without_reply=None, google_place_id=None,
- google_place_type=None, protect_content=None, message_thread_id=None):
+ reply_markup=None, timeout=None, google_place_id=None,
+ google_place_type=None, protect_content=None, message_thread_id=None, reply_parameters=None):
method_url = r'sendVenue'
payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address}
if foursquare_id:
@@ -612,14 +607,10 @@ def send_venue(
payload['foursquare_type'] = foursquare_type
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if google_place_id:
payload['google_place_id'] = google_place_id
if google_place_type:
@@ -628,13 +619,15 @@ def send_venue(
payload['protect_content'] = protect_content
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload)
def send_contact(
token, chat_id, phone_number, first_name, last_name=None, vcard=None,
- disable_notification=None, reply_to_message_id=None, reply_markup=None, timeout=None,
- allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ disable_notification=None, reply_markup=None, timeout=None,
+ protect_content=None, message_thread_id=None, reply_parameters=None):
method_url = r'sendContact'
payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name}
if last_name:
@@ -643,18 +636,16 @@ def send_contact(
payload['vcard'] = vcard
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload)
@@ -669,10 +660,10 @@ def send_chat_action(token, chat_id, action, timeout=None, message_thread_id=Non
return _make_request(token, method_url, params=payload)
-def send_video(token, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None,
+def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=None,
parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None,
- thumbnail=None, width=None, height=None, caption_entities=None, allow_sending_without_reply=None, protect_content=None,
- message_thread_id=None, has_spoiler=None):
+ thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None,
+ message_thread_id=None, has_spoiler=None, reply_parameters=None):
method_url = r'sendVideo'
payload = {'chat_id': chat_id}
files = None
@@ -684,8 +675,6 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_to_messa
payload['duration'] = duration
if caption:
payload['caption'] = caption
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if parse_mode:
@@ -710,21 +699,21 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_to_messa
payload['height'] = height
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
if has_spoiler is not None:
payload['has_spoiler'] = has_spoiler
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload, files=files, method='post')
def send_animation(
- token, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None,
+ token, chat_id, data, duration=None, caption=None, reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None,
- allow_sending_without_reply=None, protect_content=None, width=None, height=None, message_thread_id=None,
+ protect_content=None, width=None, height=None, message_thread_id=None, reply_parameters=None,
has_spoiler=None):
method_url = r'sendAnimation'
payload = {'chat_id': chat_id}
@@ -737,8 +726,6 @@ def send_animation(
payload['duration'] = duration
if caption:
payload['caption'] = caption
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if parse_mode:
@@ -757,8 +744,6 @@ def send_animation(
payload['thumbnail'] = thumbnail
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if width:
@@ -769,12 +754,14 @@ def send_animation(
payload['message_thread_id'] = message_thread_id
if has_spoiler is not None:
payload['has_spoiler'] = has_spoiler
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload, files=files, method='post')
-def send_voice(token, chat_id, voice, caption=None, duration=None, reply_to_message_id=None, reply_markup=None,
+def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None, caption_entities=None,
- allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ protect_content=None, message_thread_id=None, reply_parameters=None):
method_url = r'sendVoice'
payload = {'chat_id': chat_id}
files = None
@@ -786,8 +773,6 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_to_mess
payload['caption'] = caption
if duration:
payload['duration'] = duration
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if parse_mode:
@@ -798,18 +783,18 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_to_mess
payload['timeout'] = timeout
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload, files=files, method='post')
-def send_video_note(token, chat_id, data, duration=None, length=None, reply_to_message_id=None, reply_markup=None,
- disable_notification=None, timeout=None, thumbnail=None, allow_sending_without_reply=None, protect_content=None,
- message_thread_id=None):
+def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None,
+ disable_notification=None, timeout=None, thumbnail=None, protect_content=None,
+ message_thread_id=None, reply_parameters=None):
method_url = r'sendVideoNote'
payload = {'chat_id': chat_id}
files = None
@@ -823,8 +808,6 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_to_m
payload['length'] = length
else:
payload['length'] = 639 # seems like it is MAX length size
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if disable_notification is not None:
@@ -839,18 +822,18 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_to_m
files = {'thumbnail': thumbnail}
else:
payload['thumbnail'] = thumbnail
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload, files=files, method='post')
-def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_to_message_id=None,
+def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None,
reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None,
- caption_entities=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None):
method_url = r'sendAudio'
payload = {'chat_id': chat_id}
files = None
@@ -866,8 +849,6 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non
payload['performer'] = performer
if title:
payload['title'] = title
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if parse_mode:
@@ -886,19 +867,19 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non
payload['thumbnail'] = thumbnail
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload, files=files, method='post')
-def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_markup=None, parse_mode=None,
+def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=None,
disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None,
- allow_sending_without_reply=None, disable_content_type_detection=None, visible_file_name=None,
- protect_content = None, message_thread_id=None, emoji=None):
+ disable_content_type_detection=None, visible_file_name=None,
+ protect_content = None, message_thread_id=None, emoji=None, reply_parameters=None):
method_url = get_method_by_type(data_type)
payload = {'chat_id': chat_id}
files = None
@@ -909,8 +890,6 @@ def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_m
files = {data_type: file_data}
else:
payload[data_type] = data
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if parse_mode and data_type == 'document':
@@ -931,8 +910,6 @@ def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_m
payload['thumbnail'] = thumbnail
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if method_url == 'sendDocument' and disable_content_type_detection is not None:
@@ -941,6 +918,8 @@ def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_m
payload['message_thread_id'] = message_thread_id
if emoji:
payload['emoji'] = emoji
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload, files=files, method='post')
@@ -1309,7 +1288,7 @@ def unpin_all_chat_messages(token, chat_id):
# Updating messages
def edit_message_text(token, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None,
- entities = None, disable_web_page_preview=None, reply_markup=None):
+ entities = None, reply_markup=None, link_preview_options=None):
method_url = r'editMessageText'
payload = {'text': text}
if chat_id:
@@ -1322,10 +1301,10 @@ def edit_message_text(token, text, chat_id=None, message_id=None, inline_message
payload['parse_mode'] = parse_mode
if entities:
payload['entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(entities))
- if disable_web_page_preview is not None:
- payload['disable_web_page_preview'] = disable_web_page_preview
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
+ if link_preview_options is not None:
+ payload['link_preview'] = link_preview_options.to_json()
return _make_request(token, method_url, params=payload, method='post')
@@ -1389,24 +1368,22 @@ def delete_message(token, chat_id, message_id, timeout=None):
def send_game(
token, chat_id, game_short_name,
- disable_notification=None, reply_to_message_id=None, reply_markup=None, timeout=None,
- allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ disable_notification=None, reply_markup=None, timeout=None,
+ protect_content=None, message_thread_id=None, reply_parameters=None):
method_url = r'sendGame'
payload = {'chat_id': chat_id, 'game_short_name': game_short_name}
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload)
@@ -1470,9 +1447,9 @@ def send_invoice(
start_parameter = None, photo_url=None, photo_size=None, photo_width=None, photo_height=None,
need_name=None, need_phone_number=None, need_email=None, need_shipping_address=None,
send_phone_number_to_provider = None, send_email_to_provider = None, is_flexible=None,
- disable_notification=None, reply_to_message_id=None, reply_markup=None, provider_data=None,
- timeout=None, allow_sending_without_reply=None, max_tip_amount=None, suggested_tip_amounts=None,
- protect_content=None, message_thread_id=None):
+ disable_notification=None, reply_markup=None, provider_data=None,
+ timeout=None, max_tip_amount=None, suggested_tip_amounts=None,
+ protect_content=None, message_thread_id=None, reply_parameters=None):
"""
Use this method to send invoices. On success, the sent Message is returned.
:param token: Bot's token (you don't need to fill this)
@@ -1538,16 +1515,12 @@ def send_invoice(
payload['is_flexible'] = is_flexible
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = _convert_markup(reply_markup)
if provider_data:
payload['provider_data'] = provider_data
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if max_tip_amount is not None:
payload['max_tip_amount'] = max_tip_amount
if suggested_tip_amounts is not None:
@@ -1556,6 +1529,8 @@ def send_invoice(
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload)
@@ -1627,6 +1602,11 @@ def answer_callback_query(token, callback_query_id, text=None, show_alert=None,
return _make_request(token, method_url, params=payload, method='post')
+def get_user_chat_boosts(token, chat_id, user_id):
+ method_url = 'getUserChatBoosts'
+ payload = {'chat_id': chat_id, 'user_id': user_id}
+ return _make_request(token, method_url, params=payload)
+
def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None,
button=None):
method_url = 'answerInlineQuery'
@@ -1792,10 +1772,9 @@ def create_invoice_link(token, title, description, payload, provider_token,
def send_poll(
token, chat_id,
question, options,
- is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None,
- explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None,
- disable_notification=False, reply_to_message_id=None, allow_sending_without_reply=None,
- reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None):
+ is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None,
+ explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False,
+ reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None):
method_url = r'sendPoll'
payload = {
'chat_id': str(chat_id),
@@ -1823,13 +1802,8 @@ def send_poll(
payload['close_date'] = close_date
if is_closed is not None:
payload['is_closed'] = is_closed
-
if disable_notification:
payload['disable_notification'] = disable_notification
- if reply_to_message_id is not None:
- payload['reply_to_message_id'] = reply_to_message_id
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if reply_markup is not None:
payload['reply_markup'] = _convert_markup(reply_markup)
if timeout:
@@ -1841,6 +1815,8 @@ def send_poll(
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = reply_parameters.to_json()
return _make_request(token, method_url, params=payload)
def create_forum_topic(token, chat_id, name, icon_color=None, icon_custom_emoji_id=None):
@@ -1917,6 +1893,48 @@ def unhide_general_forum_topic(token, chat_id):
payload = {'chat_id': chat_id}
return _make_request(token, method_url, params=payload)
+def delete_messages(token, chat_id, message_ids):
+ method_url = 'deleteMessages'
+ payload = {
+ 'chat_id': chat_id,
+ 'message_ids': message_ids
+ }
+ return _make_request(token, method_url, params=payload)
+
+def forward_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None,
+ message_thread_id=None, protect_content=None):
+ method_url = 'forwardMessages'
+ payload = {
+ 'chat_id': chat_id,
+ 'from_chat_id': from_chat_id,
+ 'message_ids': message_ids,
+ }
+ if disable_notification is not None:
+ payload['disable_notification'] = disable_notification
+ if message_thread_id is not None:
+ payload['message_thread_id'] = message_thread_id
+ if protect_content is not None:
+ payload['protect_content'] = protect_content
+ return _make_request(token, method_url, params=payload)
+
+def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None,
+ message_thread_id=None, protect_content=None, remove_caption=None):
+ method_url = 'copyMessages'
+ payload = {
+ 'chat_id': chat_id,
+ 'from_chat_id': from_chat_id,
+ 'message_ids': message_ids,
+ }
+ if disable_notification is not None:
+ payload['disable_notification'] = disable_notification
+ if message_thread_id is not None:
+ payload['message_thread_id'] = message_thread_id
+ if protect_content is not None:
+ payload['protect_content'] = protect_content
+ if remove_caption is not None:
+ payload['remove_caption'] = remove_caption
+ return _make_request(token, method_url, params=payload)
+
def _convert_list_json_serializable(results):
ret = ''
diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py
index 92748a9fc..3e8b305a3 100644
--- a/telebot/async_telebot.py
+++ b/telebot/async_telebot.py
@@ -159,6 +159,8 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[
self.edited_message_handlers = []
self.channel_post_handlers = []
self.edited_channel_post_handlers = []
+ self.message_reaction_handlers = []
+ self.message_reaction_count_handlers = []
self.inline_handlers = []
self.chosen_inline_handlers = []
self.callback_query_handlers = []
@@ -169,6 +171,8 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[
self.my_chat_member_handlers = []
self.chat_member_handlers = []
self.chat_join_request_handlers = []
+ self.removed_chat_boost_handlers = []
+ self.chat_boost_handlers = []
self.custom_filters = {}
self.state_handlers = []
self.middlewares = []
@@ -576,6 +580,8 @@ async def process_new_updates(self, updates: List[types.Update]):
new_edited_messages = None
new_channel_posts = None
new_edited_channel_posts = None
+ new_message_reactions = None
+ new_message_reaction_count_handlers = None
new_inline_queries = None
new_chosen_inline_results = None
new_callback_queries = None
@@ -586,6 +592,8 @@ async def process_new_updates(self, updates: List[types.Update]):
new_my_chat_members = None
new_chat_members = None
chat_join_request = None
+ removed_chat_boost_handlers = None
+ chat_boost_handlers = None
for update in updates:
logger.debug('Processing updates: {0}'.format(update))
if update.message:
@@ -630,6 +638,19 @@ async def process_new_updates(self, updates: List[types.Update]):
if update.chat_join_request:
if chat_join_request is None: chat_join_request = []
chat_join_request.append(update.chat_join_request)
+ if update.message_reaction:
+ if new_message_reactions is None: new_message_reactions = []
+ new_message_reactions.append(update.message_reaction)
+ if update.message_reaction_count:
+ if new_message_reaction_count_handlers is None: new_message_reaction_count_handlers = []
+ new_message_reaction_count_handlers.append(update.message_reaction_count)
+ if update.chat_boost:
+ if chat_boost_handlers is None: chat_boost_handlers = []
+ chat_boost_handlers.append(update.chat_boost)
+ if update.removed_chat_boost:
+ if removed_chat_boost_handlers is None: removed_chat_boost_handlers = []
+ removed_chat_boost_handlers.append(update.removed_chat_boost)
+
if new_messages:
await self.process_new_messages(new_messages)
@@ -659,6 +680,12 @@ async def process_new_updates(self, updates: List[types.Update]):
await self.process_new_chat_member(new_chat_members)
if chat_join_request:
await self.process_chat_join_request(chat_join_request)
+ if new_message_reactions:
+ await self.process_new_message_reaction(new_message_reactions)
+ if new_message_reaction_count_handlers:
+ await self.process_new_message_reaction_count(new_message_reaction_count_handlers)
+ if chat_boost_handlers:
+ await self.process_new_chat_boost(chat_boost_handlers)
async def process_new_messages(self, new_messages):
"""
@@ -685,6 +712,18 @@ async def process_new_edited_channel_posts(self, edited_channel_post):
"""
await self._process_updates(self.edited_channel_post_handlers, edited_channel_post, 'edited_channel_post')
+ async def process_new_message_reaction(self, message_reaction):
+ """
+ :meta private:
+ """
+ await self._process_updates(self.message_reaction_handlers, message_reaction, 'message_reaction')
+
+ async def process_new_message_reaction_count(self, message_reaction_count):
+ """
+ :meta private:
+ """
+ await self._process_updates(self.message_reaction_count_handlers, message_reaction_count, 'message_reaction_count')
+
async def process_new_inline_query(self, new_inline_queries):
"""
:meta private:
@@ -745,6 +784,18 @@ async def process_chat_join_request(self, chat_join_request):
"""
await self._process_updates(self.chat_join_request_handlers, chat_join_request, 'chat_join_request')
+ async def process_new_chat_boost(self, chat_boost):
+ """
+ :meta private:
+ """
+ await self._process_updates(self.chat_boost_handlers, chat_boost, 'chat_boost')
+
+ async def process_new_removed_chat_boost(self, removed_chat_boost):
+ """
+ :meta private:
+ """
+ await self._process_updates(self.removed_chat_boost_handlers, removed_chat_boost, 'removed_chat_boost')
+
async def _get_middlewares(self, update_type):
"""
:meta private:
@@ -1346,6 +1397,111 @@ def register_edited_channel_post_handler(self, callback: Callable[[Any], Awaitab
**kwargs)
self.add_edited_channel_post_handler(handler_dict)
+ def message_reaction_handler(self, func=None, **kwargs):
+ """
+ Handles new incoming message reaction.
+ As a parameter to the decorator function, it passes :class:`telebot.types.MessageReactionUpdated` object.
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return:
+ """
+
+ def decorator(handler):
+ handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
+ self.add_message_reaction_handler(handler_dict)
+ return handler
+
+ return decorator
+
+ def add_message_reaction_handler(self, handler_dict):
+ """
+ Adds message reaction handler.
+ Note that you should use register_message_reaction_handler to add message_reaction_handler.
+
+ :meta private:
+
+ :param handler_dict:
+ :return:
+ """
+ self.message_reaction_handlers.append(handler_dict)
+
+ def register_message_reaction_handler(self, callback: Callable[[Any], Awaitable], func: Callable=None, pass_bot: Optional[bool]=False, **kwargs):
+ """
+ Registers message reaction handler.
+
+ :param callback: function to be called
+ :type callback: :obj:`Awaitable`
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
+ :type pass_bot: :obj:`bool`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return: None
+ """
+ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
+ self.add_message_reaction_handler(handler_dict)
+
+ def message_reaction_count_handler(self, func=None, **kwargs):
+ """
+ Handles new incoming message reaction count.
+ As a parameter to the decorator function, it passes :class:`telebot.types.MessageReactionCountUpdated` object.
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return:
+ """
+
+ def decorator(handler):
+ handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
+ self.add_message_reaction_count_handler(handler_dict)
+ return handler
+
+ return decorator
+
+ def add_message_reaction_count_handler(self, handler_dict):
+ """
+ Adds message reaction count handler
+ Note that you should use register_message_reaction_count_handler to add message_reaction_count_handler to the bot.
+
+ :meta private:
+
+ :param handler_dict:
+ :return:
+ """
+ self.message_reaction_count_handlers.append(handler_dict)
+
+ def register_message_reaction_count_handler(self, callback: Callable[[Any], Awaitable], func: Callable=None, pass_bot: Optional[bool]=False, **kwargs):
+ """
+ Registers message reaction count handler.
+
+ :param callback: function to be called
+ :type callback: :obj:`Awaitable`
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
+ :type pass_bot: :obj:`bool`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return: None
+ """
+ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
+ self.add_message_reaction_count_handler(handler_dict)
+
+
def inline_handler(self, func, **kwargs):
"""
Handles new incoming inline query.
@@ -1870,6 +2026,105 @@ def register_chat_join_request_handler(self, callback: Callable[[Any], Awaitable
handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
self.add_chat_join_request_handler(handler_dict)
+
+ def chat_boost_handler(self, func=None, **kwargs):
+ """
+ Handles new incoming chat boost state.
+ it passes :class:`telebot.types.ChatBoostUpdated` object.
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+ :return: None
+ """
+ def decorator(handler):
+ handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
+ self.add_chat_boost_handler(handler_dict)
+ return handler
+
+ return decorator
+
+ def add_chat_boost_handler(self, handler_dict):
+ """
+ Adds a chat_boost handler.
+ Note that you should use register_chat_boost_handler to add chat_boost_handler to the bot.
+
+ :meta private:
+
+ :param handler_dict:
+ :return:
+ """
+ self.chat_boost_handlers.append(handler_dict)
+
+ def register_chat_boost_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs):
+ """
+ Registers chat boost handler.
+
+ :param callback: function to be called
+ :type callback: :obj:`function`
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return: None
+ """
+ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
+ self.add_chat_boost_handler(handler_dict)
+
+ def removed_chat_boost_handler(self, func=None, **kwargs):
+ """
+ Handles new incoming chat boost state.
+ it passes :class:`telebot.types.ChatBoostRemoved` object.
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param kwargs: Optional keyword arguments(custom filters)
+ :return: None
+ """
+ def decorator(handler):
+ handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
+ self.add_removed_chat_boost_handler(handler_dict)
+ return handler
+
+ return decorator
+
+ def add_removed_chat_boost_handler(self, handler_dict):
+ """
+ Adds a removed_chat_boost handler.
+ Note that you should use register_removed_chat_boost_handler to add removed_chat_boost_handler to the bot.
+
+ :meta private:
+
+ :param handler_dict:
+ :return:
+ """
+ self.removed_chat_boost_handlers.append(handler_dict)
+
+ def register_removed_chat_boost_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs):
+ """
+ Registers removed chat boost handler.
+
+ :param callback: function to be called
+ :type callback: :obj:`function`
+
+ :param func: Function executed as a filter
+ :type func: :obj:`function`
+
+ :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files)
+
+ :param kwargs: Optional keyword arguments(custom filters)
+
+ :return: None
+ """
+ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs)
+ self.add_removed_chat_boost_handler(handler_dict)
+
@staticmethod
def _build_handler_dict(handler, pass_bot=False, **filters):
"""
@@ -2165,6 +2420,30 @@ async def get_webhook_info(self, timeout: Optional[int]=None) -> types.WebhookIn
result = await asyncio_helper.get_webhook_info(self.token, timeout)
return types.WebhookInfo.de_json(result)
+ async def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reaction: Optional[List[types.ReactionType]]=None, is_big: Optional[bool]=None) -> bool:
+ """
+ Use this method to set a reaction to a message in a chat. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
+
+ Telegram documentation: https://core.telegram.org/bots/api#setmessagereaction
+
+ :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)
+ :type chat_id: :obj:`int` or :obj:`str`
+
+ :param message_id: Identifier of the message to set reaction to
+ :type message_id: :obj:`int`
+
+ :param reaction: New list of reaction types to set on the message. Currently, as non-premium users, bots can set up to one reaction per message.
+ A custom emoji reaction can be used if it is either already present on the message or explicitly allowed by chat administrators.
+ :type reaction: :obj:`list` of :class:`telebot.types.ReactionType`
+
+ :param is_big: Pass True to set the reaction with a big animation
+ :type is_big: :obj:`bool`
+
+ :return: :obj:`bool`
+ """
+ result = await asyncio_helper.set_message_reaction(self.token, chat_id, message_id, reaction, is_big)
+ return result
+
async def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None,
limit: Optional[int]=None) -> types.UserProfilePhotos:
"""
@@ -2358,7 +2637,9 @@ async def send_message(
allow_sending_without_reply: Optional[bool]=None,
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
timeout: Optional[int]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None,
+ link_preview_options: Optional[types.LinkPreviewOptions]=None) -> types.Message:
"""
Use this method to send text messages.
@@ -2405,6 +2686,12 @@ async def send_message(
:param message_thread_id: Unique identifier for the target message thread (topic) of the forum; for forum supergroups only
:type message_thread_id: :obj:`int`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
+ :param link_preview_options: Options for previewing links.
+ :type link_preview_options: :class:`telebot.types.LinkPreviewOptions`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
@@ -2414,11 +2701,29 @@ async def send_message(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+ if disable_web_page_preview:
+ # show a deprecation warning
+ logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.")
+
+ # create a LinkPreviewOptions object
+ link_preview_options = types.LinkPreviewOptions(
+ disable_web_page_preview=disable_web_page_preview
+ )
+
return types.Message.de_json(
await asyncio_helper.send_message(
- self.token, chat_id, text, disable_web_page_preview, reply_to_message_id,
+ self.token, chat_id, text,
reply_markup, parse_mode, disable_notification, timeout,
- entities, allow_sending_without_reply, protect_content, message_thread_id))
+ entities, protect_content, message_thread_id, reply_parameters, link_preview_options))
async def forward_message(
self, chat_id: Union[int, str], from_chat_id: Union[int, str],
@@ -2475,7 +2780,8 @@ async def copy_message(
allow_sending_without_reply: Optional[bool]=None,
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
timeout: Optional[int]=None,
- message_thread_id: Optional[int]=None) -> types.MessageID:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.MessageID:
"""
Use this method to copy messages of any kind.
@@ -2521,6 +2827,9 @@ async def copy_message(
:param message_thread_id: Identifier of a message thread, in which the message will be sent
:type message_thread_id: :obj:`int`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the MessageId of the sent message is returned.
:rtype: :class:`telebot.types.MessageID`
"""
@@ -2529,10 +2838,20 @@ async def copy_message(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
return types.MessageID.de_json(
await asyncio_helper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities,
- disable_notification, reply_to_message_id, allow_sending_without_reply, reply_markup,
- timeout, protect_content, message_thread_id))
+ disable_notification, reply_markup,
+ timeout, protect_content, message_thread_id, reply_parameters))
async def delete_message(self, chat_id: Union[int, str], message_id: int,
timeout: Optional[int]=None) -> bool:
@@ -2562,6 +2881,94 @@ async def delete_message(self, chat_id: Union[int, str], message_id: int,
:rtype: :obj:`bool`
"""
return await asyncio_helper.delete_message(self.token, chat_id, message_id, timeout)
+
+ async def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]):
+ """
+ Use this method to delete multiple messages in a chat.
+ The number of messages to be deleted must not exceed 100.
+ If the chat is a private chat, the user must be an administrator of the chat for this to work and must have the appropriate admin rights.
+ Returns True on success.
+
+ Telegram documentation: https://core.telegram.org/bots/api#deletemessages
+
+ :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername)
+ :type chat_id: :obj:`int` or :obj:`str`
+
+ :param message_ids: Identifiers of the messages to be deleted
+ :type message_ids: :obj:`list` of :obj:`int`
+
+ :return: Returns True on success.
+
+ """
+ return await asyncio_helper.delete_messages(self.token, chat_id, message_ids)
+
+ async def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None,
+ message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]:
+ """
+ Use this method to forward messages of any kind.
+
+ :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername)
+ :type chat_id: :obj:`int` or :obj:`str`
+
+ :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername)
+ :type from_chat_id: :obj:`int` or :obj:`str`
+
+ :param message_ids: Message identifiers in the chat specified in from_chat_id
+ :type message_ids: :obj:`list`
+
+ :param disable_notification: Sends the message silently. Users will receive a notification with no sound
+ :type disable_notification: :obj:`bool`
+
+ :param message_thread_id: Identifier of a message thread, in which the messages will be sent
+ :type message_thread_id: :obj:`int`
+
+ :param protect_content: Protects the contents of the forwarded message from forwarding and saving
+ :type protect_content: :obj:`bool`
+
+ :return: On success, the sent Message is returned.
+ :rtype: :class:`telebot.types.MessageID`
+ """
+
+ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification
+ protect_content = self.protect_content if (protect_content is None) else protect_content
+ result = await asyncio_helper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id)
+ return [types.MessageID.de_json(message_id) for message_id in result]
+
+ async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int],
+ disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None,
+ protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]:
+ """
+ Use this method to copy messages of any kind.
+
+ :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername)
+ :type chat_id: :obj:`int` or :obj:`str`
+
+ :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername)
+ :type from_chat_id: :obj:`int` or :obj:`str`
+
+ :param message_ids: Message identifiers in the chat specified in from_chat_id
+ :type message_ids: :obj:`list` of :obj:`int`
+
+ :param disable_notification: Sends the message silently. Users will receive a notification with no sound
+ :type disable_notification: :obj:`bool`
+
+ :param message_thread_id: Identifier of a message thread, in which the messages will be sent
+ :type message_thread_id: :obj:`int`
+
+ :param protect_content: Protects the contents of the forwarded message from forwarding and saving
+ :type protect_content: :obj:`bool`
+
+ :param remove_caption: Pass True to copy the messages without their captions
+ :type remove_caption: :obj:`bool`
+
+ :return: On success, an array of MessageId of the sent messages is returned.
+ :rtype: :obj:`list` of :class:`telebot.types.MessageID`
+ """
+ disable_notification = self.disable_notification if disable_notification is None else disable_notification
+ protect_content = self.protect_content if protect_content is None else protect_content
+ result = await asyncio_helper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification,
+ protect_content, message_thread_id, remove_caption)
+ return [types.MessageID.de_json(message_id) for message_id in result]
async def send_dice(
self, chat_id: Union[int, str],
@@ -2571,7 +2978,8 @@ async def send_dice(
timeout: Optional[int]=None,
allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned.
@@ -2606,6 +3014,9 @@ async def send_dice(
:param message_thread_id: The identifier of a message thread, unique within the chat to which the message with the thread identifier belongs
:type message_thread_id: :obj:`int`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
@@ -2614,10 +3025,20 @@ async def send_dice(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
return types.Message.de_json(
await asyncio_helper.send_dice(
- self.token, chat_id, emoji, disable_notification, reply_to_message_id,
- reply_markup, timeout, allow_sending_without_reply, protect_content, message_thread_id)
+ self.token, chat_id, emoji, disable_notification,
+ reply_markup, timeout, protect_content, message_thread_id, reply_parameters)
)
async def send_photo(
@@ -2631,7 +3052,8 @@ async def send_photo(
reply_markup: Optional[REPLY_MARKUP_TYPES]=None,
timeout: Optional[int]=None,
message_thread_id: Optional[int]=None,
- has_spoiler: Optional[bool]=None) -> types.Message:
+ has_spoiler: Optional[bool]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send photos. On success, the sent Message is returned.
@@ -2680,6 +3102,9 @@ async def send_photo(
:param has_spoiler: Pass True, if the photo should be sent as a spoiler
:type has_spoiler: :obj:`bool`
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
+
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
"""
@@ -2688,11 +3113,21 @@ async def send_photo(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
return types.Message.de_json(
await asyncio_helper.send_photo(
- self.token, chat_id, photo, caption, reply_to_message_id, reply_markup,
+ self.token, chat_id, photo, caption, reply_markup,
parse_mode, disable_notification, timeout, caption_entities,
- allow_sending_without_reply, protect_content, message_thread_id, has_spoiler))
+ protect_content, message_thread_id, has_spoiler, reply_parameters))
async def send_audio(
self, chat_id: Union[int, str], audio: Union[Any, str],
@@ -2708,7 +3143,8 @@ async def send_audio(
allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
message_thread_id: Optional[int]=None,
- thumb: Optional[Union[Any, str]]=None) -> types.Message:
+ thumb: Optional[Union[Any, str]]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send audio files, if you want Telegram clients to display them in the music player.
Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size,
@@ -2774,6 +3210,9 @@ async def send_audio(
:param thumb: Deprecated. Use thumbnail instead
:type thumb: :obj:`str` or :class:`telebot.types.InputFile`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
@@ -2787,11 +3226,21 @@ async def send_audio(
thumbnail = thumb
logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead')
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
return types.Message.de_json(
await asyncio_helper.send_audio(
- self.token, chat_id, audio, caption, duration, performer, title, reply_to_message_id,
+ self.token, chat_id, audio, caption, duration, performer, title,
reply_markup, parse_mode, disable_notification, timeout, thumbnail,
- caption_entities, allow_sending_without_reply, protect_content, message_thread_id))
+ caption_entities, protect_content, message_thread_id, reply_parameters))
async def send_voice(
self, chat_id: Union[int, str], voice: Union[Any, str],
@@ -2804,7 +3253,8 @@ async def send_voice(
caption_entities: Optional[List[types.MessageEntity]]=None,
allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message.
For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as Audio or Document).
@@ -2853,6 +3303,9 @@ async def send_voice(
:param message_thread_id: Identifier of a message thread, in which the message will be sent
:type message_thread_id: :obj:`int`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
"""
@@ -2861,11 +3314,21 @@ async def send_voice(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
return types.Message.de_json(
await asyncio_helper.send_voice(
- self.token, chat_id, voice, caption, duration, reply_to_message_id, reply_markup,
+ self.token, chat_id, voice, caption, duration, reply_markup,
parse_mode, disable_notification, timeout, caption_entities,
- allow_sending_without_reply, protect_content, message_thread_id))
+ protect_content, message_thread_id, reply_parameters))
async def send_document(
self, chat_id: Union[int, str], document: Union[Any, str],
@@ -2883,7 +3346,8 @@ async def send_document(
data: Optional[Union[Any, str]]=None,
protect_content: Optional[bool]=None,
message_thread_id: Optional[int]=None,
- thumb: Optional[Union[Any, str]]=None) -> types.Message:
+ thumb: Optional[Union[Any, str]]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send general files.
@@ -2942,6 +3406,9 @@ async def send_document(
:param thumb: Deprecated. Use thumbnail instead
:type thumb: :obj:`str` or :class:`telebot.types.InputFile`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
@@ -2960,14 +3427,24 @@ async def send_document(
thumbnail = thumb
logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.')
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
return types.Message.de_json(
await asyncio_helper.send_data(
self.token, chat_id, document, 'document',
- reply_to_message_id = reply_to_message_id, reply_markup = reply_markup, parse_mode = parse_mode,
+ reply_markup = reply_markup, parse_mode = parse_mode,
disable_notification = disable_notification, timeout = timeout, caption = caption, thumbnail= thumbnail,
- caption_entities = caption_entities, allow_sending_without_reply = allow_sending_without_reply,
+ caption_entities = caption_entities,
disable_content_type_detection = disable_content_type_detection, visible_file_name = visible_file_name, protect_content = protect_content,
- message_thread_id = message_thread_id))
+ message_thread_id = message_thread_id, reply_parameters=reply_parameters))
async def send_sticker(
self, chat_id: Union[int, str], sticker: Union[Any, str],
@@ -2979,7 +3456,8 @@ async def send_sticker(
protect_content: Optional[bool]=None,
data: Union[Any, str]=None,
message_thread_id: Optional[int]=None,
- emoji: Optional[str]=None) -> types.Message:
+ emoji: Optional[str]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers.
On success, the sent Message is returned.
@@ -3021,6 +3499,9 @@ async def send_sticker(
:param emoji: Emoji associated with the sticker; only for just uploaded stickers
:type emoji: :obj:`str`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
@@ -3034,13 +3515,23 @@ async def send_sticker(
logger.warning('The parameter "data" is deprecated. Use "sticker" instead.')
sticker = data
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
return types.Message.de_json(
await asyncio_helper.send_data(
self.token, chat_id, sticker, 'sticker',
- reply_to_message_id=reply_to_message_id, reply_markup=reply_markup,
+ reply_markup=reply_markup,
disable_notification=disable_notification, timeout=timeout,
- allow_sending_without_reply=allow_sending_without_reply, protect_content=protect_content,
- message_thread_id=message_thread_id, emoji=emoji))
+ protect_content=protect_content,
+ message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters))
async def send_video(
self, chat_id: Union[int, str], video: Union[Any, str],
@@ -3061,7 +3552,8 @@ async def send_video(
data: Optional[Union[Any, str]]=None,
message_thread_id: Optional[int]=None,
has_spoiler: Optional[bool]=None,
- thumb: Optional[Union[Any, str]]=None) -> types.Message:
+ thumb: Optional[Union[Any, str]]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document).
@@ -3128,6 +3620,9 @@ async def send_video(
:param thumb: Deprecated. Use thumbnail instead
:type thumb: :obj:`str` or :class:`telebot.types.InputFile`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
@@ -3137,6 +3632,16 @@ async def send_video(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
if data and not(video):
# function typo miss compatibility
logger.warning('The parameter "data" is deprecated. Use "video" instead.')
@@ -3148,9 +3653,9 @@ async def send_video(
return types.Message.de_json(
await asyncio_helper.send_video(
- self.token, chat_id, video, duration, caption, reply_to_message_id, reply_markup,
+ self.token, chat_id, video, duration, caption, reply_markup,
parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height,
- caption_entities, allow_sending_without_reply, protect_content, message_thread_id, has_spoiler))
+ caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters))
async def send_animation(
self, chat_id: Union[int, str], animation: Union[Any, str],
@@ -3169,7 +3674,8 @@ async def send_animation(
timeout: Optional[int]=None,
message_thread_id: Optional[int]=None,
has_spoiler: Optional[bool]=None,
- thumb: Optional[Union[Any, str]]=None) -> types.Message:
+ thumb: Optional[Union[Any, str]]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound).
On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future.
@@ -3235,6 +3741,9 @@ async def send_animation(
:param thumb: Deprecated. Use thumbnail instead
:type thumb: :obj:`str` or :class:`telebot.types.InputFile`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
@@ -3244,15 +3753,25 @@ async def send_animation(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
if thumb is not None and thumbnail is None:
thumbnail = thumb
logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.')
return types.Message.de_json(
await asyncio_helper.send_animation(
- self.token, chat_id, animation, duration, caption, reply_to_message_id,
+ self.token, chat_id, animation, duration, caption,
reply_markup, parse_mode, disable_notification, timeout, thumbnail,
- caption_entities, allow_sending_without_reply, width, height, protect_content, message_thread_id, has_spoiler))
+ caption_entities, width, height, protect_content, message_thread_id, has_spoiler, reply_parameters))
async def send_video_note(
self, chat_id: Union[int, str], data: Union[Any, str],
@@ -3266,7 +3785,8 @@ async def send_video_note(
allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
message_thread_id: Optional[int]=None,
- thumb: Optional[Union[Any, str]]=None) -> types.Message:
+ thumb: Optional[Union[Any, str]]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long.
Use this method to send video messages. On success, the sent Message is returned.
@@ -3317,6 +3837,9 @@ async def send_video_note(
:param thumb: Deprecated. Use thumbnail instead
:type thumb: :obj:`str` or :class:`telebot.types.InputFile`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
@@ -3325,14 +3848,24 @@ async def send_video_note(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
if thumb is not None and thumbnail is None:
thumbnail = thumb
logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.')
return types.Message.de_json(
await asyncio_helper.send_video_note(
- self.token, chat_id, data, duration, length, reply_to_message_id, reply_markup,
- disable_notification, timeout, thumbnail, allow_sending_without_reply, protect_content, message_thread_id))
+ self.token, chat_id, data, duration, length, reply_markup,
+ disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters))
async def send_media_group(
self, chat_id: Union[int, str],
@@ -3344,7 +3877,8 @@ async def send_media_group(
reply_to_message_id: Optional[int]=None,
timeout: Optional[int]=None,
allow_sending_without_reply: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> List[types.Message]:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> List[types.Message]:
"""
Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files
can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned.
@@ -3374,6 +3908,9 @@ async def send_media_group(
:param message_thread_id: Identifier of a message thread, in which the messages will be sent
:type message_thread_id: :obj:`int`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, an array of Messages that were sent is returned.
:rtype: List[types.Message]
@@ -3382,9 +3919,18 @@ async def send_media_group(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
result = await asyncio_helper.send_media_group(
- self.token, chat_id, media, disable_notification, reply_to_message_id, timeout,
- allow_sending_without_reply, protect_content, message_thread_id)
+ self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters)
return [types.Message.de_json(msg) for msg in result]
async def send_location(
@@ -3400,7 +3946,8 @@ async def send_location(
proximity_alert_radius: Optional[int]=None,
allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send point on the map. On success, the sent Message is returned.
@@ -3449,6 +3996,9 @@ async def send_location(
:param message_thread_id: Identifier of a message thread, in which the message will be sent
:type message_thread_id: :obj:`int`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
@@ -3457,12 +4007,22 @@ async def send_location(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
return types.Message.de_json(
await asyncio_helper.send_location(
self.token, chat_id, latitude, longitude, live_period,
- reply_to_message_id, reply_markup, disable_notification, timeout,
+ reply_markup, disable_notification, timeout,
horizontal_accuracy, heading, proximity_alert_radius,
- allow_sending_without_reply, protect_content, message_thread_id))
+ protect_content, message_thread_id, reply_parameters))
async def edit_message_live_location(
self, latitude: float, longitude: float,
@@ -3570,7 +4130,8 @@ async def send_venue(
google_place_id: Optional[str]=None,
google_place_type: Optional[str]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send information about a venue. On success, the sent Message is returned.
@@ -3627,6 +4188,9 @@ async def send_venue(
:param message_thread_id: The thread to which the message will be sent
:type message_thread_id: :obj:`int`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
@@ -3635,11 +4199,21 @@ async def send_venue(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
return types.Message.de_json(
await asyncio_helper.send_venue(
self.token, chat_id, latitude, longitude, title, address, foursquare_id, foursquare_type,
- disable_notification, reply_to_message_id, reply_markup, timeout,
- allow_sending_without_reply, google_place_id, google_place_type, protect_content, message_thread_id)
+ disable_notification, reply_markup, timeout,
+ google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters)
)
async def send_contact(
@@ -3652,7 +4226,8 @@ async def send_contact(
timeout: Optional[int]=None,
allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send phone contacts. On success, the sent Message is returned.
@@ -3696,6 +4271,9 @@ async def send_contact(
:param message_thread_id: The thread to which the message will be sent
:type message_thread_id: :obj:`int`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :class:`telebot.types.Message`
@@ -3704,11 +4282,21 @@ async def send_contact(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
return types.Message.de_json(
await asyncio_helper.send_contact(
self.token, chat_id, phone_number, first_name, last_name, vcard,
- disable_notification, reply_to_message_id, reply_markup, timeout,
- allow_sending_without_reply, protect_content, message_thread_id)
+ disable_notification, reply_markup, timeout,
+ protect_content, message_thread_id, reply_parameters)
)
async def send_chat_action(
@@ -4660,7 +5248,8 @@ async def edit_message_text(
parse_mode: Optional[str]=None,
entities: Optional[List[types.MessageEntity]]=None,
disable_web_page_preview: Optional[bool]=None,
- reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> Union[types.Message, bool]:
+ reply_markup: Optional[types.InlineKeyboardMarkup]=None,
+ link_preview_options: Optional[types.LinkPreviewOptions]=None) -> Union[types.Message, bool]:
"""
Use this method to edit text and game messages.
@@ -4690,14 +5279,26 @@ async def edit_message_text(
:param reply_markup: A JSON-serialized object for an inline keyboard.
:type reply_markup: :obj:`InlineKeyboardMarkup`
+ :param link_preview_options: A JSON-serialized object for options used to automatically generate Telegram link previews for messages.
+ :type link_preview_options: :obj:`LinkPreviewOptions`
+
:return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned.
:rtype: :obj:`types.Message` or :obj:`bool`
"""
parse_mode = self.parse_mode if (parse_mode is None) else parse_mode
disable_web_page_preview = self.disable_web_page_preview if (disable_web_page_preview is None) else disable_web_page_preview
+ if disable_web_page_preview:
+ # show a deprecation warning
+ logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.")
+
+ # create a LinkPreviewOptions object
+ link_preview_options = types.LinkPreviewOptions(
+ disable_web_page_preview=disable_web_page_preview
+ )
+
result = await asyncio_helper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode,
- entities, disable_web_page_preview, reply_markup)
+ entities, reply_markup, link_preview_options)
if type(result) == bool: # if edit inline message return is bool not Message.
return result
return types.Message.de_json(result)
@@ -4775,7 +5376,8 @@ async def send_game(
timeout: Optional[int]=None,
allow_sending_without_reply: Optional[bool]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Used to send the game.
@@ -4807,6 +5409,9 @@ async def send_game(
:param message_thread_id: Identifier of the thread to which the message will be sent.
:type message_thread_id: :obj:`int`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :obj:`types.Message`
@@ -4815,10 +5420,20 @@ async def send_game(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
result = await asyncio_helper.send_game(
self.token, chat_id, game_short_name, disable_notification,
- reply_to_message_id, reply_markup, timeout,
- allow_sending_without_reply, protect_content, message_thread_id)
+ reply_markup, timeout,
+ protect_content, message_thread_id, reply_parameters)
return types.Message.de_json(result)
async def set_game_score(
@@ -4915,7 +5530,8 @@ async def send_invoice(
max_tip_amount: Optional[int] = None,
suggested_tip_amounts: Optional[List[int]]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Sends invoice.
@@ -5016,6 +5632,9 @@ async def send_invoice(
:param message_thread_id: The identifier of a message thread, in which the invoice message will be sent
:type message_thread_id: :obj:`int`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :obj:`types.Message`
@@ -5024,13 +5643,23 @@ async def send_invoice(
protect_content = self.protect_content if (protect_content is None) else protect_content
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
result = await asyncio_helper.send_invoice(
self.token, chat_id, title, description, invoice_payload, provider_token,
currency, prices, start_parameter, photo_url, photo_size, photo_width,
photo_height, need_name, need_phone_number, need_email, need_shipping_address,
send_phone_number_to_provider, send_email_to_provider, is_flexible, disable_notification,
- reply_to_message_id, reply_markup, provider_data, timeout, allow_sending_without_reply,
- max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id)
+ reply_markup, provider_data, timeout,
+ max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id, reply_parameters)
return types.Message.de_json(result)
@@ -5155,7 +5784,8 @@ async def send_poll(
timeout: Optional[int]=None,
explanation_entities: Optional[List[types.MessageEntity]]=None,
protect_content: Optional[bool]=None,
- message_thread_id: Optional[int]=None) -> types.Message:
+ message_thread_id: Optional[int]=None,
+ reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message:
"""
Use this method to send a native poll.
On success, the sent Message is returned.
@@ -5225,6 +5855,9 @@ async def send_poll(
:param message_thread_id: The identifier of a message thread, in which the poll will be sent
:type message_thread_id: :obj:`int`
+
+ :param reply_parameters: Reply parameters.
+ :type reply_parameters: :class:`telebot.types.ReplyParameters`
:return: On success, the sent Message is returned.
:rtype: :obj:`types.Message`
@@ -5234,6 +5867,16 @@ async def send_poll(
allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply
explanation_parse_mode = self.parse_mode if (explanation_parse_mode is None) else explanation_parse_mode
+ if allow_sending_without_reply or reply_to_message_id:
+ # show a deprecation warning
+ logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.")
+
+ # create a ReplyParameters object
+ reply_parameters = types.ReplyParameters(
+ allow_sending_without_reply=allow_sending_without_reply,
+ message_id=reply_to_message_id
+ )
+
if isinstance(question, types.Poll):
raise RuntimeError("The send_poll signature was changed, please see send_poll function details.")
@@ -5243,8 +5886,8 @@ async def send_poll(
question, options,
is_anonymous, type, allows_multiple_answers, correct_option_id,
explanation, explanation_parse_mode, open_period, close_date, is_closed,
- disable_notification, reply_to_message_id, allow_sending_without_reply,
- reply_markup, timeout, explanation_entities, protect_content, message_thread_id))
+ disable_notification,
+ reply_markup, timeout, explanation_entities, protect_content, message_thread_id, reply_parameters))
async def stop_poll(
self, chat_id: Union[int, str], message_id: int,
@@ -5490,6 +6133,33 @@ async def answer_callback_query(
:rtype: :obj:`bool`
"""
return await asyncio_helper.answer_callback_query(self.token, callback_query_id, text, show_alert, url, cache_time)
+
+# getUserChatBoosts
+# Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a UserChatBoosts object.
+
+# Parameter Type Required Description
+# chat_id Integer or String Yes Unique identifier for the chat or username of the channel (in the format @channelusername)
+# user_id Integer Yes Unique identifier of the target user
+
+ async def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types.UserChatBoosts:
+ """
+ Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a UserChatBoosts object.
+
+ Telegram documentation: https://core.telegram.org/bots/api#getuserchatboosts
+
+ :param chat_id: Unique identifier for the target chat or username of the target channel
+ :type chat_id: :obj:`int` | :obj:`str`
+
+ :param user_id: Unique identifier of the target user
+ :type user_id: :obj:`int`
+
+ :return: On success, a UserChatBoosts object is returned.
+ :rtype: :class:`telebot.types.UserChatBoosts`
+ """
+
+ result = await asyncio_helper.get_user_chat_boosts(self.token, chat_id, user_id)
+ return types.UserChatBoosts.de_json(result)
+
async def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None):
"""
diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py
index 526166eec..872fb591d 100644
--- a/telebot/asyncio_helper.py
+++ b/telebot/asyncio_helper.py
@@ -278,16 +278,14 @@ async def _check_result(method_name, result: aiohttp.ClientResponse):
async def send_message(
token, chat_id, text,
- disable_web_page_preview=None, reply_to_message_id=None, reply_markup=None,
+ reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None,
- entities=None, allow_sending_without_reply=None, protect_content=None,
- message_thread_id=None):
+ entities=None, protect_content=None,
+ message_thread_id=None, reply_parameters=None, link_preview_options=None):
method_name = 'sendMessage'
params = {'chat_id': str(chat_id), 'text': text}
- if disable_web_page_preview is not None:
- params['disable_web_page_preview'] = disable_web_page_preview
- if reply_to_message_id:
- params['reply_to_message_id'] = reply_to_message_id
+ if link_preview_options is not None:
+ params['link_preview_options'] = json.dumps(link_preview_options.to_dict())
if reply_markup:
params['reply_markup'] = await _convert_markup(reply_markup)
if parse_mode:
@@ -298,8 +296,8 @@ async def send_message(
params['timeout'] = timeout
if entities:
params['entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(entities))
- if allow_sending_without_reply is not None:
- params['allow_sending_without_reply'] = allow_sending_without_reply
+ if reply_parameters is not None:
+ params['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if protect_content is not None:
params['protect_content'] = protect_content
if message_thread_id:
@@ -318,6 +316,15 @@ async def get_user_profile_photos(token, user_id, offset=None, limit=None):
payload['limit'] = limit
return await _process_request(token, method_url, params=payload)
+async def set_message_reaction(token, chat_id, message_id, reaction=None, is_big=None):
+ method_url = r'setMessageReaction'
+ payload = {'chat_id': chat_id, 'message_id': message_id}
+ if reaction:
+ payload['reaction'] = json.dumps([r.to_dict() for r in reaction])
+ if is_big is not None:
+ payload['is_big'] = is_big
+ return await _process_request(token, method_url, params=payload)
+
async def get_chat(token, chat_id):
method_url = r'getChat'
@@ -397,8 +404,8 @@ async def forward_message(
async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None,
- disable_notification=None, reply_to_message_id=None, allow_sending_without_reply=None,
- reply_markup=None, timeout=None, protect_content=None, message_thread_id=None):
+ disable_notification=None,
+ reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None):
method_url = r'copyMessage'
payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id}
if caption is not None:
@@ -409,12 +416,10 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p
payload['caption_entities'] = await _convert_entites(caption_entities)
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup is not None:
payload['reply_markup'] = await _convert_markup(reply_markup)
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if timeout:
payload['timeout'] = timeout
if protect_content is not None:
@@ -426,36 +431,34 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p
async def send_dice(
token, chat_id,
- emoji=None, disable_notification=None, reply_to_message_id=None,
- reply_markup=None, timeout=None, allow_sending_without_reply=None, protect_content=None,
- message_thread_id=None):
+ emoji=None, disable_notification=None,
+ reply_markup=None, timeout=None, protect_content=None,
+ message_thread_id=None,reply_parameters=None):
method_url = r'sendDice'
payload = {'chat_id': chat_id}
if emoji:
payload['emoji'] = emoji
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
return await _process_request(token, method_url, params=payload)
async def send_photo(
token, chat_id, photo,
- caption=None, reply_to_message_id=None, reply_markup=None,
+ caption=None, reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None,
- caption_entities=None, allow_sending_without_reply=None, protect_content=None,
- message_thread_id=None, has_spoiler=None):
+ caption_entities=None, protect_content=None,
+ message_thread_id=None, has_spoiler=None,reply_parameters=None):
method_url = r'sendPhoto'
payload = {'chat_id': chat_id}
files = None
@@ -467,8 +470,6 @@ async def send_photo(
files = {'photo': photo}
if caption:
payload['caption'] = caption
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if parse_mode:
@@ -479,8 +480,8 @@ async def send_photo(
payload['timeout'] = timeout
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
@@ -492,23 +493,21 @@ async def send_photo(
async def send_media_group(
token, chat_id, media,
- disable_notification=None, reply_to_message_id=None,
- timeout=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ disable_notification=None,
+ timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None):
method_url = r'sendMediaGroup'
media_json, files = await convert_input_media_array(media)
payload = {'chat_id': chat_id, 'media': media_json}
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
return await _process_request(
token, method_url, params=payload,
method='post' if files else 'get',
@@ -517,10 +516,10 @@ async def send_media_group(
async def send_location(
token, chat_id, latitude, longitude,
- live_period=None, reply_to_message_id=None,
+ live_period=None,
reply_markup=None, disable_notification=None,
timeout=None, horizontal_accuracy=None, heading=None,
- proximity_alert_radius=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ proximity_alert_radius=None, protect_content=None, message_thread_id=None,reply_parameters=None):
method_url = r'sendLocation'
payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude}
if live_period:
@@ -531,10 +530,8 @@ async def send_location(
payload['heading'] = heading
if proximity_alert_radius:
payload['proximity_alert_radius'] = proximity_alert_radius
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if disable_notification is not None:
@@ -594,9 +591,9 @@ async def stop_message_live_location(
async def send_venue(
token, chat_id, latitude, longitude, title, address,
foursquare_id=None, foursquare_type=None, disable_notification=None,
- reply_to_message_id=None, reply_markup=None, timeout=None,
- allow_sending_without_reply=None, google_place_id=None,
- google_place_type=None, protect_content=None, message_thread_id=None):
+ reply_markup=None, timeout=None,
+ google_place_id=None,
+ google_place_type=None, protect_content=None, message_thread_id=None,reply_parameters=None):
method_url = r'sendVenue'
payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address}
if foursquare_id:
@@ -605,14 +602,12 @@ async def send_venue(
payload['foursquare_type'] = foursquare_type
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if google_place_id:
payload['google_place_id'] = google_place_id
if google_place_type:
@@ -626,8 +621,8 @@ async def send_venue(
async def send_contact(
token, chat_id, phone_number, first_name, last_name=None, vcard=None,
- disable_notification=None, reply_to_message_id=None, reply_markup=None, timeout=None,
- allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ disable_notification=None, reply_markup=None, timeout=None,
+ protect_content=None, message_thread_id=None,reply_parameters=None):
method_url = r'sendContact'
payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name}
if last_name:
@@ -636,14 +631,12 @@ async def send_contact(
payload['vcard'] = vcard
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
@@ -661,10 +654,10 @@ async def send_chat_action(token, chat_id, action, timeout=None, message_thread_
return await _process_request(token, method_url, params=payload)
-async def send_video(token, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None,
+async def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=None,
parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None,
- thumbnail=None, width=None, height=None, caption_entities=None, allow_sending_without_reply=None,
- protect_content=None, message_thread_id=None, has_spoiler=None):
+ thumbnail=None, width=None, height=None, caption_entities=None,
+ protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None):
method_url = r'sendVideo'
payload = {'chat_id': chat_id}
files = None
@@ -676,8 +669,8 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_to
payload['duration'] = duration
if caption:
payload['caption'] = caption
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if parse_mode:
@@ -702,8 +695,6 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_to
payload['height'] = height
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
@@ -714,10 +705,10 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_to
async def send_animation(
- token, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None,
+ token, chat_id, data, duration=None, caption=None, reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None,
- allow_sending_without_reply=None, width=None, height=None, protect_content=None, message_thread_id=None,
- has_spoiler=None):
+ width=None, height=None, protect_content=None, message_thread_id=None,
+ has_spoiler=None,reply_parameters=None):
method_url = r'sendAnimation'
payload = {'chat_id': chat_id}
files = None
@@ -729,8 +720,8 @@ async def send_animation(
payload['duration'] = duration
if caption:
payload['caption'] = caption
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if parse_mode:
@@ -749,8 +740,6 @@ async def send_animation(
payload['thumbnail'] = thumbnail
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if width:
payload['width'] = width
if height:
@@ -764,9 +753,9 @@ async def send_animation(
return await _process_request(token, method_url, params=payload, files=files, method='post')
-async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_to_message_id=None, reply_markup=None,
+async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None, caption_entities=None,
- allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ protect_content=None, message_thread_id=None,reply_parameters=None):
method_url = r'sendVoice'
payload = {'chat_id': chat_id}
files = None
@@ -778,8 +767,8 @@ async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_t
payload['caption'] = caption
if duration:
payload['duration'] = duration
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if parse_mode:
@@ -790,8 +779,6 @@ async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_t
payload['timeout'] = timeout
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
@@ -799,9 +786,9 @@ async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_t
return await _process_request(token, method_url, params=payload, files=files, method='post')
-async def send_video_note(token, chat_id, data, duration=None, length=None, reply_to_message_id=None, reply_markup=None,
- disable_notification=None, timeout=None, thumbnail=None, allow_sending_without_reply=None, protect_content=None,
- message_thread_id=None):
+async def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None,
+ disable_notification=None, timeout=None, thumbnail=None, protect_content=None,
+ message_thread_id=None,reply_parameters=None):
method_url = r'sendVideoNote'
payload = {'chat_id': chat_id}
files = None
@@ -815,8 +802,8 @@ async def send_video_note(token, chat_id, data, duration=None, length=None, repl
payload['length'] = length
else:
payload['length'] = 639 # seems like it is MAX length size
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if disable_notification is not None:
@@ -831,8 +818,6 @@ async def send_video_note(token, chat_id, data, duration=None, length=None, repl
files = {'thumbnail': thumbnail}
else:
payload['thumbnail'] = thumbnail
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
@@ -840,9 +825,9 @@ async def send_video_note(token, chat_id, data, duration=None, length=None, repl
return await _process_request(token, method_url, params=payload, files=files, method='post')
-async def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_to_message_id=None,
+async def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None,
reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None,
- caption_entities=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ caption_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None):
method_url = r'sendAudio'
payload = {'chat_id': chat_id}
files = None
@@ -858,8 +843,8 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform
payload['performer'] = performer
if title:
payload['title'] = title
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if parse_mode:
@@ -878,8 +863,6 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform
payload['thumbnail'] = thumbnail
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
@@ -887,10 +870,10 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform
return await _process_request(token, method_url, params=payload, files=files, method='post')
-async def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_markup=None, parse_mode=None,
+async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=None,
disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None,
- allow_sending_without_reply=None, disable_content_type_detection=None, visible_file_name=None, protect_content=None,
- message_thread_id=None, emoji=None):
+ disable_content_type_detection=None, visible_file_name=None, protect_content=None,
+ message_thread_id=None, emoji=None,reply_parameters=None):
method_url = await get_method_by_type(data_type)
payload = {'chat_id': chat_id}
files = None
@@ -901,8 +884,8 @@ async def send_data(token, chat_id, data, data_type, reply_to_message_id=None, r
files = {data_type: file_data}
else:
payload[data_type] = data
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if parse_mode and data_type == 'document':
@@ -923,8 +906,6 @@ async def send_data(token, chat_id, data, data_type, reply_to_message_id=None, r
payload['thumbnail'] = thumbnail
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if method_url == 'sendDocument' and disable_content_type_detection is not None:
@@ -1297,7 +1278,7 @@ async def unpin_all_chat_messages(token, chat_id):
# Updating messages
async def edit_message_text(token, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None,
- entities = None, disable_web_page_preview=None, reply_markup=None):
+ entities = None, reply_markup=None, link_preview_options=None):
method_url = r'editMessageText'
payload = {'text': text}
if chat_id:
@@ -1310,10 +1291,10 @@ async def edit_message_text(token, text, chat_id=None, message_id=None, inline_m
payload['parse_mode'] = parse_mode
if entities:
payload['entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(entities))
- if disable_web_page_preview is not None:
- payload['disable_web_page_preview'] = disable_web_page_preview
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
+ if link_preview_options is not None:
+ payload['link_preview_options'] = link_preview_options.to_json()
return await _process_request(token, method_url, params=payload, method='post')
@@ -1377,20 +1358,18 @@ async def delete_message(token, chat_id, message_id, timeout=None):
async def send_game(
token, chat_id, game_short_name,
- disable_notification=None, reply_to_message_id=None, reply_markup=None, timeout=None,
- allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
+ disable_notification=None, reply_markup=None, timeout=None,
+ protect_content=None, message_thread_id=None,reply_parameters=None):
method_url = r'sendGame'
payload = {'chat_id': chat_id, 'game_short_name': game_short_name}
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
@@ -1458,9 +1437,9 @@ async def send_invoice(
start_parameter = None, photo_url=None, photo_size=None, photo_width=None, photo_height=None,
need_name=None, need_phone_number=None, need_email=None, need_shipping_address=None,
send_phone_number_to_provider = None, send_email_to_provider = None, is_flexible=None,
- disable_notification=None, reply_to_message_id=None, reply_markup=None, provider_data=None,
- timeout=None, allow_sending_without_reply=None, max_tip_amount=None, suggested_tip_amounts=None,
- protect_content=None, message_thread_id=None):
+ disable_notification=None, reply_markup=None, provider_data=None,
+ timeout=None, max_tip_amount=None, suggested_tip_amounts=None,
+ protect_content=None, message_thread_id=None,reply_parameters=None):
"""
Use this method to send invoices. On success, the sent Message is returned.
:param token: Bot's token (you don't need to fill this)
@@ -1526,16 +1505,14 @@ async def send_invoice(
payload['is_flexible'] = is_flexible
if disable_notification is not None:
payload['disable_notification'] = disable_notification
- if reply_to_message_id:
- payload['reply_to_message_id'] = reply_to_message_id
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup:
payload['reply_markup'] = await _convert_markup(reply_markup)
if provider_data:
payload['provider_data'] = provider_data
if timeout:
payload['timeout'] = timeout
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
if max_tip_amount is not None:
payload['max_tip_amount'] = max_tip_amount
if suggested_tip_amounts is not None:
@@ -1614,6 +1591,10 @@ async def answer_callback_query(token, callback_query_id, text=None, show_alert=
payload['cache_time'] = cache_time
return await _process_request(token, method_url, params=payload, method='post')
+async def get_user_chat_boosts(token, chat_id, user_id):
+ method_url = 'getUserChatBoosts'
+ payload = {'chat_id': chat_id, 'user_id': user_id}
+ return await _process_request(token, method_url, params=payload)
async def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None,
button=None):
@@ -1779,8 +1760,8 @@ async def send_poll(
question, options,
is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None,
explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None,
- disable_notification=False, reply_to_message_id=None, allow_sending_without_reply=None,
- reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None):
+ disable_notification=False,
+ reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None):
method_url = r'sendPoll'
payload = {
'chat_id': str(chat_id),
@@ -1811,10 +1792,8 @@ async def send_poll(
if disable_notification:
payload['disable_notification'] = disable_notification
- if reply_to_message_id is not None:
- payload['reply_to_message_id'] = reply_to_message_id
- if allow_sending_without_reply is not None:
- payload['allow_sending_without_reply'] = allow_sending_without_reply
+ if reply_parameters is not None:
+ payload['reply_parameters'] = json.dumps(reply_parameters.to_dict())
if reply_markup is not None:
payload['reply_markup'] = await _convert_markup(reply_markup)
if timeout:
@@ -1896,6 +1875,53 @@ async def unhide_general_forum_topic(token, chat_id):
payload = {'chat_id': chat_id}
return await _process_request(token, method_url, params=payload)
+async def delete_messages(token, chat_id, message_ids):
+ method_url = 'deleteMessages'
+ payload = {
+ 'chat_id': chat_id,
+ 'message_ids': message_ids
+ }
+ return await _process_request(token, method_url, params=payload)
+
+async def forward_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None,
+ message_thread_id=None, protect_content=None):
+ method_url = 'forwardMessages'
+ payload = {
+ 'chat_id': chat_id,
+ 'from_chat_id': from_chat_id,
+ 'message_ids': message_ids,
+ }
+ if disable_notification is not None:
+ payload['disable_notification'] = disable_notification
+ if message_thread_id is not None:
+ payload['message_thread_id'] = message_thread_id
+ if protect_content is not None:
+ payload['protect_content'] = protect_content
+
+ result = await _process_request(token, method_url, params=payload)
+ return result
+
+async def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None,
+ message_thread_id=None, protect_content=None, remove_caption=None):
+ method_url = 'copyMessages'
+ payload = {
+ 'chat_id': chat_id,
+ 'from_chat_id': from_chat_id,
+ 'message_ids': message_ids,
+ }
+ if disable_notification is not None:
+ payload['disable_notification'] = disable_notification
+ if message_thread_id is not None:
+ payload['message_thread_id'] = message_thread_id
+ if protect_content is not None:
+ payload['protect_content'] = protect_content
+ if remove_caption is not None:
+ payload['remove_caption'] = remove_caption
+
+ result = await _process_request(token, method_url, params=payload)
+ return result
+
+
async def _convert_list_json_serializable(results):
ret = ''
for r in results:
@@ -2024,3 +2050,5 @@ class RequestTimeout(Exception):
This class represents a request timeout.
"""
pass
+
+
diff --git a/telebot/types.py b/telebot/types.py
index 73efd5592..5b8c42536 100644
--- a/telebot/types.py
+++ b/telebot/types.py
@@ -127,6 +127,14 @@ class Update(JsonDeserializable):
:param edited_channel_post: Optional. New version of a channel post that is known to the bot and was edited
:type edited_channel_post: :class:`telebot.types.Message`
+ :param message_reaction: Optional. A reaction to a message was changed by a user. The bot must be an administrator in the chat
+ and must explicitly specify "message_reaction" in the list of allowed_updates to receive these updates. The update isn't received for reactions set by bots.
+ :type message_reaction: :class:`telebot.types.MessageReactionUpdated`
+
+ :param message_reaction_count: Optional. Reactions to a message with anonymous reactions were changed. The bot must be an administrator in the chat and must explicitly specify
+ "message_reaction_count" in the list of allowed_updates to receive these updates.
+ :type message_reaction_count: :class:`telebot.types.MessageReactionCountUpdated`
+
:param inline_query: Optional. New incoming inline query
:type inline_query: :class:`telebot.types.InlineQuery`
@@ -165,6 +173,12 @@ class Update(JsonDeserializable):
can_invite_users administrator right in the chat to receive these updates.
:type chat_join_request: :class:`telebot.types.ChatJoinRequest`
+ :param chat_boost: Optional. A chat boost was added or changed. The bot must be an administrator in the chat to receive these updates.
+ :type chat_boost: :class:`telebot.types.ChatBoost`
+
+ :param removed_chat_boost: Optional. A chat boost was removed. The bot must be an administrator in the chat to receive these updates.
+ :type removed_chat_boost: :class:`telebot.types.RemovedChatBoost`
+
:return: Instance of the class
:rtype: :class:`telebot.types.Update`
@@ -188,13 +202,17 @@ def de_json(cls, json_string):
my_chat_member = ChatMemberUpdated.de_json(obj.get('my_chat_member'))
chat_member = ChatMemberUpdated.de_json(obj.get('chat_member'))
chat_join_request = ChatJoinRequest.de_json(obj.get('chat_join_request'))
+ message_reaction = MessageReactionUpdated.de_json(obj.get('message_reaction'))
+ message_reaction_count = MessageReactionCountUpdated.de_json(obj.get('message_reaction_count'))
+ removed_chat_boost = ChatBoostRemoved.de_json(obj.get('removed_chat_boost'))
+ chat_boost = ChatBoost.de_json(obj.get('chat_boost'))
return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query,
chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer,
- my_chat_member, chat_member, chat_join_request)
+ my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost)
def __init__(self, update_id, message, edited_message, channel_post, edited_channel_post, inline_query,
chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer,
- my_chat_member, chat_member, chat_join_request):
+ my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost):
self.update_id = update_id
self.message = message
self.edited_message = edited_message
@@ -210,6 +228,10 @@ def __init__(self, update_id, message, edited_message, channel_post, edited_chan
self.my_chat_member = my_chat_member
self.chat_member = chat_member
self.chat_join_request = chat_join_request
+ self.message_reaction = message_reaction
+ self.message_reaction_count = message_reaction_count
+ self.removed_chat_boost = removed_chat_boost
+ self.chat_boost = chat_boost
class ChatMemberUpdated(JsonDeserializable):
@@ -539,6 +561,26 @@ class Chat(JsonDeserializable):
Returned only in getChat.
:type active_usernames: :obj:`list` of :obj:`str`
+ :param available_reactions: Optional. List of available chat reactions; for private chats, supergroups and channels.
+ Returned only in getChat.
+ :type available_reactions: :obj:`list` of :class:`telebot.types.ReactionType`
+
+ :param accent_color_id: Optional. Optional. Identifier of the accent color for the chat name and backgrounds of the chat photo,
+ reply header, and link preview. See accent colors for more details. Returned only in getChat. Always returned in getChat.
+ :type accent_color_id: :obj:`int`
+
+ :param background_custom_emoji_id: Optional. Custom emoji identifier of emoji chosen by the chat for the reply header
+ and link preview background. Returned only in getChat.
+ :type background_custom_emoji_id: :obj:`str`
+
+ :param profile_accent_color_id: Optional. Identifier of the accent color for the chat's profile background.
+ See profile accent colors for more details. Returned only in getChat.
+ :type profile_accent_color_id: :obj:`int`
+
+ :param profile_background_custom_emoji_id: Optional. Custom emoji identifier of the emoji chosen by the chat for its profile background.
+ Returned only in getChat.
+ :type profile_background_custom_emoji_id: :obj:`str`
+
:param emoji_status_custom_emoji_id: Optional. Custom emoji identifier of emoji status of the other party in a private chat.
Returned only in getChat.
:type emoji_status_custom_emoji_id: :obj:`str`
@@ -600,6 +642,10 @@ class Chat(JsonDeserializable):
chats. Returned only in getChat.
:type has_protected_content: :obj:`bool`
+ :param has_visible_history: Optional. True, if new chat members will have access to old messages;
+ available only to chat administrators. Returned only in getChat.
+ :type has_visible_history: :obj:`bool`
+
:param sticker_set_name: Optional. For supergroups, name of group sticker set. Returned only in getChat.
:type sticker_set_name: :obj:`str`
@@ -632,6 +678,8 @@ def de_json(cls, json_string):
obj['permissions'] = ChatPermissions.de_json(obj['permissions'])
if 'location' in obj:
obj['location'] = ChatLocation.de_json(obj['location'])
+ if 'available_reactions' in obj:
+ obj['available_reactions'] = [ReactionType(reaction) for reaction in obj['available_reactions']]
return cls(**obj)
def __init__(self, id, type, title=None, username=None, first_name=None,
@@ -642,7 +690,9 @@ def __init__(self, id, type, title=None, username=None, first_name=None,
can_set_sticker_set=None, linked_chat_id=None, location=None,
join_to_send_messages=None, join_by_request=None, has_restricted_voice_and_video_messages=None,
is_forum=None, active_usernames=None, emoji_status_custom_emoji_id=None,
- has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, **kwargs):
+ has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None,
+ available_reactions=None, accent_color_id=None, background_custom_emoji_id=None, profile_accent_color_id=None,
+ profile_background_custom_emoji_id=None, has_visible_history=None,**kwargs):
self.id: int = id
self.type: str = type
self.title: str = title
@@ -672,6 +722,13 @@ def __init__(self, id, type, title=None, username=None, first_name=None,
self.has_hidden_members: bool = has_hidden_members
self.has_aggressive_anti_spam_enabled: bool = has_aggressive_anti_spam_enabled
self.emoji_status_expiration_date: int = emoji_status_expiration_date
+ self.available_reactions: List[ReactionType] = available_reactions
+ self.accent_color_id: int = accent_color_id
+ self.background_custom_emoji_id: str = background_custom_emoji_id
+ self.profile_accent_color_id: int = profile_accent_color_id
+ self.profile_background_custom_emoji_id: str = profile_background_custom_emoji_id
+ self.has_visible_history: bool = has_visible_history
+
class MessageID(JsonDeserializable):
@@ -776,6 +833,9 @@ class Message(JsonDeserializable):
:param forward_date: Optional. For forwarded messages, date the original message was sent in Unix time
:type forward_date: :obj:`int`
+ :forward_origin: Optional. For forwarded messages, information about the original message;
+ :type forward_origin: :class:`telebot.types.MessageOrigin`
+
:param is_topic_message: Optional. True, if the message is sent to a forum topic
:type is_topic_message: :obj:`bool`
@@ -787,6 +847,12 @@ class Message(JsonDeserializable):
will not contain further reply_to_message fields even if it itself is a reply.
:type reply_to_message: :class:`telebot.types.Message`
+ :param external_reply: Optional. Information about the message that is being replied to, which may come from another chat or forum topic
+ :type external_reply: :class:`telebot.types.ExternalReplyInfo`
+
+ :param quote: Optional. For replies that quote part of the original message, the quoted part of the message
+ :type quote: :class:`telebot.types.TextQuote`
+
:param via_bot: Optional. Bot through which the message was sent
:type via_bot: :class:`telebot.types.User`
@@ -810,6 +876,10 @@ class Message(JsonDeserializable):
appear in the text
:type entities: :obj:`list` of :class:`telebot.types.MessageEntity`
+ :param link_preview_options: Optional. Options used for link preview generation for the message,
+ if it is a text message and link preview options were changed
+ :type link_preview_options: :class:`telebot.types.LinkPreviewOptions`
+
:param animation: Optional. Message is an animation, information about the animation. For backward
compatibility, when this field is set, the document field will also be set
:type animation: :class:`telebot.types.Animation`
@@ -924,8 +994,8 @@ class Message(JsonDeserializable):
the payment. More about payments »
:type successful_payment: :class:`telebot.types.SuccessfulPayment`
- :param user_shared: Optional. Service message: a user was shared with the bot
- :type user_shared: :class:`telebot.types.UserShared`
+ :param users_shared: Optional. Service message: a user was shared with the bot
+ :type users_shared: :class:`telebot.types.UserShared`
:param chat_shared: Optional. Service message: a chat was shared with the bot
:type chat_shared: :class:`telebot.types.ChatShared`
@@ -963,6 +1033,18 @@ class Message(JsonDeserializable):
:param general_forum_topic_unhidden: Optional. Service message: the 'General' forum topic unhidden
:type general_forum_topic_unhidden: :class:`telebot.types.GeneralForumTopicUnhidden`
+ :param giveaway_created: Optional. Service message: a giveaway has been created
+ :type giveaway_created: :class:`telebot.types.GiveawayCreated`
+
+ :param giveaway: Optional. The message is a scheduled giveaway message
+ :type giveaway: :class:`telebot.types.Giveaway`
+
+ :param giveaway_winners: Optional. Service message: giveaway winners(public winners)
+ :type giveaway_winners: :class:`telebot.types.GiveawayWinners`
+
+ :param giveaway_completed: Optional. Service message: giveaway completed, without public winners
+ :type giveaway_completed: :class:`telebot.types.GiveawayCompleted`
+
:param video_chat_scheduled: Optional. Service message: video chat scheduled
:type video_chat_scheduled: :class:`telebot.types.VideoChatScheduled`
@@ -1066,7 +1148,7 @@ def de_json(cls, json_string):
if 'caption' in obj:
opts['caption'] = obj['caption']
if 'contact' in obj:
- opts['contact'] = Contact.de_json(json.dumps(obj['contact']))
+ opts['contact'] = Contact.de_json(obj['contact'])
content_type = 'contact'
if 'location' in obj:
opts['location'] = Location.de_json(obj['location'])
@@ -1179,15 +1261,36 @@ def de_json(cls, json_string):
if 'write_access_allowed' in obj:
opts['write_access_allowed'] = WriteAccessAllowed.de_json(obj['write_access_allowed'])
content_type = 'write_access_allowed'
- if 'user_shared' in obj:
- opts['user_shared'] = UserShared.de_json(obj['user_shared'])
- content_type = 'user_shared'
+ if 'users_shared' in obj:
+ opts['users_shared'] = UserShared.de_json(obj['users_shared'])
+ content_type = 'users_shared' # COMPATIBILITY BROKEN!
if 'chat_shared' in obj:
opts['chat_shared'] = ChatShared.de_json(obj['chat_shared'])
content_type = 'chat_shared'
if 'story' in obj:
opts['story'] = Story.de_json(obj['story'])
content_type = 'story'
+ if 'external_reply' in obj:
+ opts['external_reply'] = ExternalReplyInfo.de_json(obj['external_reply'])
+ if 'quote' in obj:
+ opts['quote'] = TextQuote.de_json(obj['quote'])
+ if 'link_preview_options' in obj:
+ opts['link_preview_options'] = LinkPreviewOptions.de_json(obj['link_preview_options'])
+ if 'giveaway_created' in obj:
+ opts['giveaway_created'] = GiveawayCreated.de_json(obj['giveaway_created'])
+ content_type = 'giveaway_created'
+ if 'giveaway' in obj:
+ opts['giveaway'] = Giveaway.de_json(obj['giveaway'])
+ content_type = 'giveaway'
+ if 'giveaway_winners' in obj:
+ opts['giveaway_winners'] = GiveawayWinners.de_json(obj['giveaway_winners'])
+ content_type = 'giveaway_winners'
+ if 'giveaway_completed' in obj:
+ opts['giveaway_completed'] = GiveawayCompleted.de_json(obj['giveaway_completed'])
+ content_type = 'giveaway_completed'
+ if 'message_origin' in obj:
+ opts['message_origin'] = MessageOrigin.de_json(obj['message_origin'])
+
return cls(message_id, from_user, date, chat, content_type, opts, json_string)
@classmethod
@@ -1283,9 +1386,20 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso
self.general_forum_topic_hidden: Optional[GeneralForumTopicHidden] = None
self.general_forum_topic_unhidden: Optional[GeneralForumTopicUnhidden] = None
self.write_access_allowed: Optional[WriteAccessAllowed] = None
- self.user_shared: Optional[UserShared] = None
+ self.users_shared: Optional[UserShared] = None
+ self.user_shared: Optional[UserShared] = self.users_shared
self.chat_shared: Optional[ChatShared] = None
self.story: Optional[Story] = None
+ self.external_reply: Optional[ExternalReplyInfo] = None
+ self.quote: Optional[TextQuote] = None
+ self.link_preview_options: Optional[LinkPreviewOptions] = None
+ self.giveaway_created: Optional[GiveawayCreated] = None
+ self.giveaway: Optional[Giveaway] = None
+ self.giveaway_winners: Optional[GiveawayWinners] = None
+ self.giveaway_completed: Optional[GiveawayCompleted] = None
+ self.forward_origin: Optional[MessageOrigin] = None
+
+
for key in options:
setattr(self, key, options[key])
self.json = json_string
@@ -2292,13 +2406,12 @@ def to_dict(self):
return {'type': self.type}
-
-class KeyboardButtonRequestUser(Dictionaryable):
+class KeyboardButtonRequestUsers(Dictionaryable):
"""
This object defines the criteria used to request a suitable user.
The identifier of the selected user will be shared with the bot when the corresponding button is pressed.
- Telegram documentation: https://core.telegram.org/bots/api#keyboardbuttonrequestuser
+ Telegram documentation: https://core.telegram.org/bots/api#keyboardbuttonrequestusers
:param request_id: Signed 32-bit identifier of the request, which will be received back in the UserShared object.
Must be unique within the message
@@ -2312,15 +2425,19 @@ class KeyboardButtonRequestUser(Dictionaryable):
If not specified, no additional restrictions are applied.
:type user_is_premium: :obj:`bool`
+ :param max_quantity: Optional. The maximum number of users to be selected; 1-10. Defaults to 1.
+ :type max_quantity: :obj:`int`
+
:return: Instance of the class
- :rtype: :class:`telebot.types.KeyboardButtonRequestUser`
+ :rtype: :class:`telebot.types.KeyboardButtonRequestUsers`
"""
- def __init__(self, request_id: int, user_is_bot: Optional[bool]=None, user_is_premium: Optional[bool]=None) -> None:
+ def __init__(self, request_id: int, user_is_bot: Optional[bool]=None, user_is_premium: Optional[bool]=None, max_quantity: Optional[int]=None) -> None:
self.request_id: int = request_id
self.user_is_bot: Optional[bool] = user_is_bot
self.user_is_premium: Optional[bool] = user_is_premium
+ self.max_quantity: Optional[int] = max_quantity
def to_dict(self) -> dict:
data = {'request_id': self.request_id}
@@ -2328,8 +2445,11 @@ def to_dict(self) -> dict:
data['user_is_bot'] = self.user_is_bot
if self.user_is_premium is not None:
data['user_is_premium'] = self.user_is_premium
+ if self.max_quantity is not None:
+ data['max_quantity'] = self.max_quantity
return data
+KeyboardButtonRequestUser = KeyboardButtonRequestUsers
class KeyboardButtonRequestChat(Dictionaryable):
"""
@@ -2431,7 +2551,7 @@ class KeyboardButton(Dictionaryable, JsonSerializable):
:param request_user: Optional. If specified, pressing the button will open a list of suitable users. Tapping on any user
will send their identifier to the bot in a “user_shared” service message. Available in private chats only.
- :type request_user: :class:`telebot.types.KeyboardButtonRequestUser`
+ :type request_user: :class:`telebot.types.KeyboardButtonRequestUsers`
:param request_chat: Optional. If specified, pressing the button will open a list of suitable chats. Tapping on a chat will
send its identifier to the bot in a “chat_shared” service message. Available in private chats only.
@@ -2442,15 +2562,18 @@ class KeyboardButton(Dictionaryable, JsonSerializable):
"""
def __init__(self, text: str, request_contact: Optional[bool]=None,
request_location: Optional[bool]=None, request_poll: Optional[KeyboardButtonPollType]=None,
- web_app: Optional[WebAppInfo]=None, request_user: Optional[KeyboardButtonRequestUser]=None,
- request_chat: Optional[KeyboardButtonRequestChat]=None):
+ web_app: Optional[WebAppInfo]=None, request_user: Optional[KeyboardButtonRequestUsers]=None,
+ request_chat: Optional[KeyboardButtonRequestChat]=None, request_users: Optional[KeyboardButtonRequestUsers]=None):
self.text: str = text
self.request_contact: bool = request_contact
self.request_location: bool = request_location
self.request_poll: KeyboardButtonPollType = request_poll
self.web_app: WebAppInfo = web_app
- self.request_user: KeyboardButtonRequestUser = request_user
+ self.request_user: KeyboardButtonRequestUsers = request_user
self.request_chat: KeyboardButtonRequestChat = request_chat
+ self.request_users: KeyboardButtonRequestUsers = request_users
+ if request_user is not None:
+ self.request_users = request_user
def to_json(self):
@@ -3586,17 +3709,24 @@ class InputTextMessageContent(Dictionaryable):
parse_mode
:type entities: :obj:`list` of :class:`telebot.types.MessageEntity`
- :param disable_web_page_preview: Optional. Disables link previews for links in the sent message
+ :param disable_web_page_preview: Optional, deprecated. Disables link previews for links in the sent message
:type disable_web_page_preview: :obj:`bool`
:return: Instance of the class
:rtype: :class:`telebot.types.InputTextMessageContent`
"""
- def __init__(self, message_text, parse_mode=None, entities=None, disable_web_page_preview=None):
+ def __init__(self, message_text, parse_mode=None, entities=None, disable_web_page_preview=None, link_preview_options=None):
self.message_text: str = message_text
self.parse_mode: str = parse_mode
self.entities: List[MessageEntity] = entities
- self.disable_web_page_preview: bool = disable_web_page_preview
+ link_preview_options: LinkPreviewOptions = link_preview_options
+ if disable_web_page_preview is not None:
+ logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.")
+
+ if link_preview_options:
+ logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated")
+ else:
+ self.link_preview_options: LinkPreviewOptions = LinkPreviewOptions(disable_web_page_preview)
def to_dict(self):
json_dict = {'message_text': self.message_text}
@@ -3604,8 +3734,8 @@ def to_dict(self):
json_dict['parse_mode'] = self.parse_mode
if self.entities:
json_dict['entities'] = MessageEntity.to_list_of_dicts(self.entities)
- if self.disable_web_page_preview is not None:
- json_dict['disable_web_page_preview'] = self.disable_web_page_preview
+ if self.link_preview_options:
+ json_dict['link_preview_options'] = self.link_preview_options.to_dict()
return json_dict
@@ -7515,7 +7645,7 @@ def __init__(self, from_request: Optional[bool]=None, web_app_name: Optional[str
class UserShared(JsonDeserializable):
"""
This object contains information about the user whose identifier was shared with the bot using a
- `telebot.types.KeyboardButtonRequestUser` button.
+ `telebot.types.KeyboardButtonRequestUsers` button.
Telegram documentation: https://core.telegram.org/bots/api#usershared
@@ -7802,7 +7932,6 @@ def __init__(self, text: str, web_app: Optional[WebAppInfo]=None, start_paramete
self.web_app: Optional[WebAppInfo] = web_app
self.start_parameter: Optional[str] = start_parameter
-
def to_dict(self) -> dict:
json_dict = {
'text': self.text
@@ -7835,3 +7964,1201 @@ def de_json(cls, json_string):
def __init__(self) -> None:
pass
+
+# base class
+class ReactionType(JsonDeserializable, Dictionaryable, JsonSerializable):
+ """
+ This object represents a reaction type.
+
+ Telegram documentation: https://core.telegram.org/bots/api#reactiontype
+
+ :param type: Type of the reaction
+ :type type: :obj:`str`
+
+ :return: Instance of the class
+ :rtype: :class:`ReactionType`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ # remove type
+ if obj['type'] == 'emoji':
+ del obj['type']
+ return ReactionTypeEmoji(**obj)
+ elif obj['type'] == 'custom_emoji':
+ del obj['type']
+ return ReactionTypeCustomEmoji(**obj)
+
+ def __init__(self, type: str) -> None:
+ self.type: str = type
+
+ def to_dict(self) -> dict:
+ json_dict = {
+ 'type': self.type
+ }
+ return json_dict
+
+ def to_json(self) -> str:
+ return json.dumps(self.to_dict())
+
+
+class ReactionTypeEmoji(ReactionType):
+ """
+ This object represents an emoji reaction type.
+
+ Telegram documentation: https://core.telegram.org/bots/api#reactiontypeemoji
+
+ :param type: Type of the reaction, must be emoji
+ :type type: :obj:`str`
+
+ :param emoji: Reaction emoji. List is available on the API doc.
+ :type emoji: :obj:`str`
+
+ :return: Instance of the class
+ :rtype: :class:`ReactionTypeEmoji`
+ """
+
+ def __init__(self, emoji: str) -> None:
+ super().__init__('emoji')
+ self.emoji: str = emoji
+
+ def to_dict(self) -> dict:
+ json_dict = super().to_dict()
+ json_dict['emoji'] = self.emoji
+ return json_dict
+
+
+class ReactionTypeCustomEmoji(ReactionType):
+ """
+ This object represents a custom emoji reaction type.
+
+ Telegram documentation: https://core.telegram.org/bots/api#reactiontypecustomemoji
+
+ :param type: Type of the reaction, must be custom_emoji
+ :type type: :obj:`str`
+
+ :param custom_emoji: Identifier of the custom emoji
+ :type custom_emoji: :obj:`str`
+
+ :return: Instance of the class
+ :rtype: :class:`ReactionTypeCustomEmoji`
+ """
+
+ def __init__(self, custom_emoji: str) -> None:
+ super().__init__('custom_emoji')
+ self.custom_emoji: str = custom_emoji
+
+ def to_dict(self) -> dict:
+ json_dict = super().to_dict()
+ json_dict['custom_emoji'] = self.custom_emoji
+ return json_dict
+
+
+class MessageReactionUpdated(JsonDeserializable):
+ """
+ This object represents a service message about a change in the list of the current user's reactions to a message.
+
+ Telegram documentation: https://core.telegram.org/bots/api#messagereactionupdated
+
+ :param chat: The chat containing the message the user reacted to
+ :type chat: :class:`telebot.types.Chat`
+
+ :param message_id: Unique identifier of the message inside the chat
+ :type message_id: :obj:`int`
+
+ :param user: Optional. The user that changed the reaction, if the user isn't anonymous
+ :type user: :class:`telebot.types.User`
+
+ :param actor_chat: Optional. The chat on behalf of which the reaction was changed, if the user is anonymous
+ :type actor_chat: :class:`telebot.types.Chat`
+
+ :param date: Date of the change in Unix time
+ :type date: :obj:`int`
+
+ :param old_reaction: Previous list of reaction types that were set by the user
+ :type old_reaction: :obj:`list` of :class:`ReactionType`
+
+ :param new_reaction: New list of reaction types that have been set by the user
+ :type new_reaction: :obj:`list` of :class:`ReactionType`
+
+ :return: Instance of the class
+ :rtype: :class:`MessageReactionUpdated`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+
+ obj['chat'] = Chat.de_json(obj['chat'])
+ if 'user' in obj:
+ obj['user'] = User.de_json(obj['user'])
+ if 'actor_chat' in obj:
+ obj['actor_chat'] = Chat.de_json(obj['actor_chat'])
+ obj['old_reaction'] = [ReactionType.de_json(reaction) for reaction in obj['old_reaction']]
+ obj['new_reaction'] = [ReactionType.de_json(reaction) for reaction in obj['new_reaction']]
+ return cls(**obj)
+
+ def __init__(self, chat: Chat, message_id: int, date: int, old_reaction: List[ReactionType], new_reaction: List[ReactionType],
+ user: Optional[User]=None, actor_chat: Optional[Chat]=None) -> None:
+ self.chat: Chat = chat
+ self.message_id: int = message_id
+ self.user: Optional[User] = user
+ self.actor_chat: Optional[Chat] = actor_chat
+ self.date: int = date
+ self.old_reaction: List[ReactionType] = old_reaction
+ self.new_reaction: List[ReactionType] = new_reaction
+
+
+
+class MessageReactionCountUpdated(JsonDeserializable):
+ """
+ This object represents a service message about a change in the list of the current user's reactions to a message.
+
+ Telegram documentation: https://core.telegram.org/bots/api#messagereactioncountupdated
+
+ :param chat: The chat containing the message
+ :type chat: :class:`telebot.types.Chat`
+
+ :param message_id: Unique message identifier inside the chat
+ :type message_id: :obj:`int`
+
+ :param date: Date of the change in Unix time
+ :type date: :obj:`int`
+
+ :param reactions: List of reactions that are present on the message
+ :type reactions: :obj:`list` of :class:`ReactionCount`
+
+ :return: Instance of the class
+ :rtype: :class:`MessageReactionCountUpdated`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ obj['chat'] = Chat.de_json(obj['chat'])
+ obj['reactions'] = [ReactionCount.de_json(reaction) for reaction in obj['reactions']]
+ return cls(**obj)
+
+ def __init__(self, chat: Chat, message_id: int, date: int, reactions: List[ReactionCount]) -> None:
+ self.chat: Chat = chat
+ self.message_id: int = message_id
+ self.date: int = date
+ self.reactions: List[ReactionCount] = reactions
+
+
+class ReactionCount(JsonDeserializable):
+ """
+ This object represents a reaction added to a message along with the number of times it was added.
+
+ Telegram documentation: https://core.telegram.org/bots/api#reactioncount
+
+ :param type: Type of the reaction
+ :type type: :class:`ReactionType`
+
+ :param total_count: Number of times the reaction was added
+ :type total_count: :obj:`int`
+
+ :return: Instance of the class
+ :rtype: :class:`ReactionCount`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ obj['type'] = ReactionType.de_json(obj['type'])
+ return cls(**obj)
+
+ def __init__(self, type: ReactionType, total_count: int) -> None:
+ self.type: ReactionType = type
+ self.total_count: int = total_count
+
+
+class ExternalReplyInfo(JsonDeserializable):
+ """
+ This object contains information about a message that is being replied to,
+ which may come from another chat or forum topic.
+
+ Telegram documentation: https://core.telegram.org/bots/api#externalreplyinfo
+
+ :param origin: Origin of the message replied to by the given message
+ :type origin: :class:`MessageOrigin`
+
+ :param chat: Optional. Chat the original message belongs to. Available only if the chat is a supergroup or a channel.
+ :type chat: :class:`Chat`
+
+ :param message_id: Optional. Unique message identifier inside the original chat. Available only if the original chat is a supergroup or a channel.
+ :type message_id: :obj:`int`
+
+ :param link_preview_options: Optional. Options used for link preview generation for the original message, if it is a text message
+ :type link_preview_options: :class:`LinkPreviewOptions`
+
+ :param animation: Optional. Message is an animation, information about the animation
+ :type animation: :class:`Animation`
+
+ :param audio: Optional. Message is an audio file, information about the file
+ :type audio: :class:`Audio`
+
+ :param document: Optional. Message is a general file, information about the file
+ :type document: :class:`Document`
+
+ :param photo: Optional. Message is a photo, available sizes of the photo
+ :type photo: :obj:`list` of :class:`PhotoSize`
+
+ :param sticker: Optional. Message is a sticker, information about the sticker
+ :type sticker: :class:`Sticker`
+
+ :param story: Optional. Message is a forwarded story
+ :type story: :class:`Story`
+
+ :param video: Optional. Message is a video, information about the video
+ :type video: :class:`Video`
+
+ :param video_note: Optional. Message is a video note, information about the video message
+ :type video_note: :class:`VideoNote`
+
+ :param voice: Optional. Message is a voice message, information about the file
+ :type voice: :class:`Voice`
+
+ :param has_media_spoiler: Optional. True, if the message media is covered by a spoiler animation
+ :type has_media_spoiler: :obj:`bool`
+
+ :param contact: Optional. Message is a shared contact, information about the contact
+ :type contact: :class:`Contact`
+
+ :param dice: Optional. Message is a dice with random value
+ :type dice: :class:`Dice`
+
+ :param game: Optional. Message is a game, information about the game. More about games »
+ :type game: :class:`Game`
+
+ :param giveaway: Optional. Message is a scheduled giveaway, information about the giveaway
+ :type giveaway: :class:`Giveaway`
+
+ :param giveaway_winners: Optional. A giveaway with public winners was completed
+ :type giveaway_winners: :class:`GiveawayWinners`
+
+ :param invoice: Optional. Message is an invoice for a payment, information about the invoice. More about payments »
+ :type invoice: :class:`Invoice`
+
+ :param location: Optional. Message is a shared location, information about the location
+ :type location: :class:`Location`
+
+ :param poll: Optional. Message is a native poll, information about the poll
+ :type poll: :class:`Poll`
+
+ :param venue: Optional. Message is a venue, information about the venue
+ :type venue: :class:`Venue`
+
+ :return: Instance of the class
+ :rtype: :class:`ExternalReplyInfo`
+ """
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ origin = MessageOrigin.de_json(obj['origin'])
+ if 'chat' in obj:
+ chat = Chat.de_json(obj['chat'])
+ if 'link_preview_options' in obj:
+ link_preview_options = LinkPreviewOptions.de_json(obj['link_preview_options'])
+
+ #todo: update data processing to common way
+
+ animation = obj.get('animation')
+ if animation is not None:
+ animation = Animation.de_json(animation)
+
+ audio = obj.get('audio')
+ if audio is not None:
+ audio = Audio.de_json(audio)
+
+ document = obj.get('document')
+ if document is not None:
+ document = Document.de_json(document)
+
+ photo = obj.get('photo')
+ if photo is not None:
+ photo = [PhotoSize.de_json(photo[i]) for i in range(len(photo))]
+
+ sticker = obj.get('sticker')
+ if sticker is not None:
+ sticker = Sticker.de_json(sticker)
+
+ story = obj.get('story')
+ if story is not None:
+ story = Story.de_json(story)
+
+ video = obj.get('video')
+ if video is not None:
+ video = Video.de_json(video)
+
+ video_note = obj.get('video_note')
+ if video_note is not None:
+ video_note = VideoNote.de_json(video_note)
+
+ voice = obj.get('voice')
+ if voice is not None:
+ voice = Voice.de_json(voice)
+
+ has_media_spoiler = obj.get('has_media_spoiler')
+ if has_media_spoiler is not None:
+ has_media_spoiler = bool(has_media_spoiler)
+
+ contact = obj.get('contact')
+ if contact is not None:
+ contact = Contact.de_json(contact)
+
+ dice = obj.get('dice')
+ if dice is not None:
+ dice = Dice.de_json(dice)
+
+ game = obj.get('game')
+ if game is not None:
+ game = Game.de_json(game)
+
+ giveaway = obj.get('giveaway')
+ if giveaway is not None:
+ giveaway = Giveaway.de_json(giveaway)
+
+ giveaway_winners = obj.get('giveaway_winners')
+ if giveaway_winners is not None:
+ giveaway_winners = GiveawayWinners.de_json(giveaway_winners)
+
+ invoice = obj.get('invoice')
+ if invoice is not None:
+ invoice = Invoice.de_json(invoice)
+
+ location = obj.get('location')
+ if location is not None:
+ location = Location.de_json(location)
+
+ poll = obj.get('poll')
+ if poll is not None:
+ poll = Poll.de_json(poll)
+
+ venue = obj.get('venue')
+ if venue is not None:
+ venue = Venue.de_json(venue)
+
+ return cls(origin=origin, chat=chat, message_id=message_id, link_preview_options=link_preview_options,
+ animation=animation, audio=audio, document=document, photo=photo, sticker=sticker, story=story,
+ video=video, video_note=video_note, voice=voice, has_media_spoiler=has_media_spoiler,
+ contact=contact, dice=dice, game=game, giveaway=giveaway, giveaway_winners=giveaway_winners,
+ invoice=invoice, location=location, poll=poll, venue=venue)
+
+ def __init__(self, origin: MessageOrigin, chat: Optional[Chat]=None, message_id: Optional[int]=None,
+ link_preview_options: Optional[LinkPreviewOptions]=None, animation: Optional[Animation]=None,
+ audio: Optional[Audio]=None, document: Optional[Document]=None, photo: Optional[List[PhotoSize]]=None,
+ sticker: Optional[Sticker]=None, story: Optional[Story]=None, video: Optional[Video]=None,
+ video_note: Optional[VideoNote]=None, voice: Optional[Voice]=None,
+ has_media_spoiler: Optional[bool]=None, contact: Optional[Contact]=None,
+ dice: Optional[Dice]=None, game: Optional[Game]=None, giveaway: Optional[Giveaway]=None,
+ giveaway_winners: Optional[GiveawayWinners]=None, invoice: Optional[Invoice]=None,
+ location: Optional[Location]=None, poll: Optional[Poll]=None,
+ venue: Optional[Venue]=None) -> None:
+ self.origin: MessageOrigin = origin
+
+ self.chat: Optional[Chat] = chat
+ self.message_id: Optional[int] = message_id
+ self.link_preview_options: Optional[LinkPreviewOptions] = link_preview_options
+ self.animation: Optional[Animation] = animation
+ self.audio: Optional[Audio] = audio
+ self.document: Optional[Document] = document
+ self.photo: Optional[List[PhotoSize]] = photo
+ self.sticker: Optional[Sticker] = sticker
+ self.story: Optional[Story] = story
+ self.video: Optional[Video] = video
+ self.video_note: Optional[VideoNote] = video_note
+ self.voice: Optional[Voice] = voice
+ self.has_media_spoiler: Optional[bool] = has_media_spoiler
+ self.contact: Optional[Contact] = contact
+ self.dice: Optional[Dice] = dice
+ self.game: Optional[Game] = game
+ self.giveaway: Optional[Giveaway] = giveaway
+ self.giveaway_winners: Optional[GiveawayWinners] = giveaway_winners
+ self.invoice: Optional[Invoice] = invoice
+ self.location: Optional[Location] = location
+ self.poll: Optional[Poll] = poll
+ self.venue: Optional[Venue] = venue
+
+
+class MessageOrigin(JsonDeserializable):
+ """
+ This object describes the origin of a message.
+
+ Telegram documentation: https://core.telegram.org/bots/api#messageorigin
+
+ :param type: Type of the message origin
+ :type type: :obj:`str`
+
+ :param date: Date the message was sent originally in Unix time
+ :type date: :obj:`int`
+
+ :param sender_user: User that sent the message originally (for MessageOriginUser)
+ :type sender_user: :class:`User`
+
+ :param sender_user_name: Name of the user that sent the message originally (for MessageOriginHiddenUser)
+ :type sender_user_name: :obj:`str`
+
+ :param sender_chat: Chat that sent the message originally (for MessageOriginChat)
+ :type sender_chat: :class:`Chat`
+
+ :param author_signature: Optional. Author signature for certain cases
+ :type author_signature: :obj:`str`
+
+ :return: Instance of the class
+ :rtype: :class:`MessageOrigin`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+
+ message_type = obj.get('type')
+ if message_type == 'user':
+ sender_user = User.de_json(obj['sender_user'])
+ return MessageOriginUser(date=obj['date'], sender_user=sender_user)
+ elif message_type == 'hidden_user':
+ return MessageOriginHiddenUser(date=obj['date'], sender_user_name=obj['sender_user_name'])
+ elif message_type == 'chat':
+ sender_chat = Chat.de_json(obj['sender_chat'])
+ return MessageOriginChat(date=obj['date'], sender_chat=sender_chat, author_signature=obj.get('author_signature'))
+ elif message_type == 'channel':
+ chat = Chat.de_json(obj['chat'])
+ return MessageOriginChannel(date=obj['date'], chat=chat, message_id=obj['message_id'], author_signature=obj.get('author_signature'))
+
+ def __init__(self, type: str, date: int) -> None:
+ self.type: str = type
+ self.date: int = date
+
+
+class MessageOriginUser(MessageOrigin):
+ """
+ The message was originally sent by a known user.
+
+ :param sender_user: User that sent the message originally
+ :type sender_user: :class:`User`
+ """
+
+ def __init__(self, date: int, sender_user: User) -> None:
+ super().__init__('user', date)
+ self.sender_user: User = sender_user
+
+
+class MessageOriginHiddenUser(MessageOrigin):
+ """
+ The message was originally sent by an unknown user.
+
+ :param sender_user_name: Name of the user that sent the message originally
+ :type sender_user_name: :obj:`str`
+ """
+
+ def __init__(self, date: int, sender_user_name: str) -> None:
+ super().__init__('hidden_user', date)
+ self.sender_user_name: str = sender_user_name
+
+
+class MessageOriginChat(MessageOrigin):
+ """
+ The message was originally sent on behalf of a chat to a group chat.
+
+ :param sender_chat: Chat that sent the message originally
+ :type sender_chat: :class:`Chat`
+
+ :param author_signature: Optional. For messages originally sent by an anonymous chat administrator, original message author signature
+ :type author_signature: :obj:`str`
+ """
+
+ def __init__(self, date: int, sender_chat: Chat, author_signature: Optional[str] = None) -> None:
+ super().__init__('chat', date)
+ self.sender_chat: Chat = sender_chat
+ self.author_signature: Optional[str] = author_signature
+
+
+class MessageOriginChannel(MessageOrigin):
+ """
+ The message was originally sent to a channel chat.
+
+ :param chat: Channel chat to which the message was originally sent
+ :type chat: :class:`Chat`
+
+ :param message_id: Unique message identifier inside the chat
+ :type message_id: :obj:`int`
+
+ :param author_signature: Optional. Signature of the original post author
+ :type author_signature: :obj:`str`
+ """
+
+ def __init__(self, date: int, chat: Chat, message_id: int, author_signature: Optional[str] = None) -> None:
+ super().__init__('channel', date)
+ self.chat: Chat = chat
+ self.message_id: int = message_id
+ self.author_signature: Optional[str] = author_signature
+
+
+class LinkPreviewOptions(JsonDeserializable, Dictionaryable, JsonSerializable):
+ """
+ Describes the options used for link preview generation.
+
+ Telegram documentation: https://core.telegram.org/bots/api#linkpreviewoptions
+
+ :param is_disabled: Optional. True, if the link preview is disabled
+ :type is_disabled: :obj:`bool`
+
+ :param url: Optional. URL to use for the link preview. If empty, then the first URL found in the message text will be used
+ :type url: :obj:`str`
+
+ :param prefer_small_media: Optional. True, if the media in the link preview is supposed to be shrunk; ignored if the URL isn't explicitly specified or media size change isn't supported for the preview
+ :type prefer_small_media: :obj:`bool`
+
+ :param prefer_large_media: Optional. True, if the media in the link preview is supposed to be enlarged; ignored if the URL isn't explicitly specified or media size change isn't supported for the preview
+ :type prefer_large_media: :obj:`bool`
+
+ :param show_above_text: Optional. True, if the link preview must be shown above the message text; otherwise, the link preview will be shown below the message text
+ :type show_above_text: :obj:`bool`
+
+ :return: Instance of the class
+ :rtype: :class:`LinkPreviewOptions`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ #todo: adopt to common way
+ return cls(is_disabled=obj.get('is_disabled'), url=obj.get('url'), prefer_small_media=obj.get('prefer_small_media'),
+ prefer_large_media=obj.get('prefer_large_media'), show_above_text=obj.get('show_above_text'))
+
+
+ def __init__(self, is_disabled: Optional[bool] = None, url: Optional[str] = None,
+ prefer_small_media: Optional[bool] = None, prefer_large_media: Optional[bool] = None,
+ show_above_text: Optional[bool] = None) -> None:
+ self.is_disabled: Optional[bool] = is_disabled
+ self.url: Optional[str] = url
+ self.prefer_small_media: Optional[bool] = prefer_small_media
+ self.prefer_large_media: Optional[bool] = prefer_large_media
+ self.show_above_text: Optional[bool] = show_above_text
+
+ def to_dict(self) -> dict:
+ json_dict = {}
+
+ if self.is_disabled is not None:
+ json_dict['is_disabled'] = self.is_disabled
+ if self.url is not None:
+ json_dict['url'] = self.url
+ if self.prefer_small_media is not None:
+ json_dict['prefer_small_media'] = self.prefer_small_media
+ if self.prefer_large_media is not None:
+ json_dict['prefer_large_media'] = self.prefer_large_media
+ if self.show_above_text is not None:
+ json_dict['show_above_text'] = self.show_above_text
+
+
+ def to_json(self) -> str:
+ return json.dumps(self.to_dict())
+
+
+class Giveaway(JsonDeserializable):
+ """
+ This object represents a message about a scheduled giveaway.
+
+ Telegram documentation: https://core.telegram.org/bots/api#giveaway
+
+ :param chats: The list of chats which the user must join to participate in the giveaway
+ :type chats: :obj:`list` of :class:`Chat`
+
+ :param winners_selection_date: Point in time (Unix timestamp) when winners of the giveaway will be selected
+ :type winners_selection_date: :obj:`int`
+
+ :param winner_count: The number of users which are supposed to be selected as winners of the giveaway
+ :type winner_count: :obj:`int`
+
+ :param only_new_members: Optional. True, if only users who join the chats after the giveaway started should be eligible to win
+ :type only_new_members: :obj:`bool`
+
+ :param has_public_winners: Optional. True, if the list of giveaway winners will be visible to everyone
+ :type has_public_winners: :obj:`bool`
+
+ :param prize_description: Optional. Description of additional giveaway prize
+ :type prize_description: :obj:`str`
+
+ :param country_codes: Optional. A list of two-letter ISO 3166-1 alpha-2 country codes indicating the countries from which eligible users for the giveaway must come. If empty, then all users can participate in the giveaway.
+ :type country_codes: :obj:`list` of :obj:`str`
+
+ :param premium_subscription_month_count: Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for
+ :type premium_subscription_month_count: :obj:`int`
+
+ :return: Instance of the class
+ :rtype: :class:`Giveaway`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ self.chats = [Chat.de_json(chat) for chat in obj['chats']]
+ return cls(**obj)
+
+ def __init__(self, chats: List[Chat], winners_selection_date: int, winner_count: int,
+ only_new_members: Optional[bool] = None, has_public_winners: Optional[bool] = None,
+ prize_description: Optional[str] = None, country_codes: Optional[List[str]] = None,
+ premium_subscription_month_count: Optional[int] = None) -> None:
+ self.chats: List[Chat] = chats
+ self.winners_selection_date: int = winners_selection_date
+ self.winner_count: int = winner_count
+ self.only_new_members: Optional[bool] = only_new_members
+ self.has_public_winners: Optional[bool] = has_public_winners
+ self.prize_description: Optional[str] = prize_description
+ self.country_codes: Optional[List[str]] = country_codes
+ self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count
+
+
+class GiveawayWinners(JsonDeserializable):
+ """
+ This object represents a message about the completion of a giveaway with public winners.
+
+ Telegram documentation: https://core.telegram.org/bots/api#giveawaywinners
+
+ :param chat: The chat that created the giveaway
+ :type chat: :class:`Chat`
+
+ :param giveaway_message_id: Identifier of the messsage with the giveaway in the chat
+ :type giveaway_message_id: :obj:`int`
+
+ :param winners_selection_date: Point in time (Unix timestamp) when winners of the giveaway were selected
+ :type winners_selection_date: :obj:`int`
+
+ :param winner_count: Total number of winners in the giveaway
+ :type winner_count: :obj:`int`
+
+ :param winners: List of up to 100 winners of the giveaway
+ :type winners: :obj:`list` of :class:`User`
+
+ :param additional_chat_count: Optional. The number of other chats the user had to join in order to be eligible for the giveaway
+ :type additional_chat_count: :obj:`int`
+
+ :param premium_subscription_month_count: Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for
+ :type premium_subscription_month_count: :obj:`int`
+
+ :param unclaimed_prize_count: Optional. Number of undistributed prizes
+ :type unclaimed_prize_count: :obj:`int`
+
+ :param only_new_members: Optional. True, if only users who had joined the chats after the giveaway started were eligible to win
+ :type only_new_members: :obj:`bool`
+
+ :param was_refunded: Optional. True, if the giveaway was canceled because the payment for it was refunded
+ :type was_refunded: :obj:`bool`
+
+ :param prize_description: Optional. Description of additional giveaway prize
+ :type prize_description: :obj:`str`
+
+ :return: Instance of the class
+ :rtype: :class:`GiveawayWinners`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ obj['chat'] = Chat.de_json(obj['chat'])
+ obj['winners'] = [User.de_json(user) for user in obj['winners']]
+ return cls(**obj)
+
+ def __init__(self, chat: Chat, giveaway_message_id: int, winners_selection_date: int, winner_count: int,
+ winners: List[User], additional_chat_count: Optional[int] = None,
+ premium_subscription_month_count: Optional[int] = None, unclaimed_prize_count: Optional[int] = None,
+ only_new_members: Optional[bool] = None, was_refunded: Optional[bool] = None,
+ prize_description: Optional[str] = None) -> None:
+ self.chat: Chat = chat
+ self.giveaway_message_id: int = giveaway_message_id
+ self.winners_selection_date: int = winners_selection_date
+ self.winner_count: int = winner_count
+ self.winners: List[User] = winners
+ self.additional_chat_count: Optional[int] = additional_chat_count
+ self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count
+ self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count
+ self.only_new_members: Optional[bool] = only_new_members
+ self.was_refunded: Optional[bool] = was_refunded
+ self.prize_description: Optional[str] = prize_description
+
+
+class GiveawayCompleted(JsonDeserializable):
+ """
+ This object represents a service message about the completion of a giveaway without public winners.
+
+ Telegram documentation: https://core.telegram.org/bots/api#giveawaycompleted
+
+ :param winner_count: Number of winners in the giveaway
+ :type winner_count: :obj:`int`
+
+ :param unclaimed_prize_count: Optional. Number of undistributed prizes
+ :type unclaimed_prize_count: :obj:`int`
+
+ :param giveaway_message: Optional. Message with the giveaway that was completed, if it wasn't deleted
+ :type giveaway_message: :class:`Message`
+
+ :return: Instance of the class
+ :rtype: :class:`GiveawayCompleted`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ if 'giveaway_message' in obj:
+ obj['giveaway_message'] = Message.de_json(obj['giveaway_message'])
+ return cls(**obj)
+
+ def __init__(self, winner_count: int, unclaimed_prize_count: Optional[int] = None,
+ giveaway_message: Optional[Message] = None) -> None:
+ self.winner_count: int = winner_count
+ self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count
+ self.giveaway_message: Optional[Message] = giveaway_message
+
+
+class GiveawayCreated(JsonDeserializable):
+ """
+ This object represents a service message about the creation of a scheduled giveaway. Currently holds no information.
+ """
+
+
+class TextQuote(JsonDeserializable):
+ """
+ This object contains information about the quoted part of a message that is replied to by the given message.
+
+ Telegram documentation: https://core.telegram.org/bots/api#textquote
+
+ :param text: Text of the quoted part of a message that is replied to by the given message
+ :type text: :obj:`str`
+
+ :param entities: Optional. Special entities that appear in the quote. Currently, only bold, italic, underline, strikethrough, spoiler, and custom_emoji entities are kept in quotes.
+ :type entities: :obj:`list` of :class:`MessageEntity`
+
+ :param position: Approximate quote position in the original message in UTF-16 code units as specified by the sender
+ :type position: :obj:`int`
+
+ :param is_manual: Optional. True, if the quote was chosen manually by the message sender. Otherwise, the quote was added automatically by the server.
+ :type is_manual: :obj:`bool`
+
+ :return: Instance of the class
+ :rtype: :class:`TextQuote`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ obj['entities'] = [MessageEntity.de_json(entity) for entity in obj.get('entities', [])]
+ return cls(**obj)
+
+ def __init__(self, text: str, entities: Optional[List[MessageEntity]] = None,
+ position: Optional[int] = None, is_manual: Optional[bool] = None) -> None:
+ self.text: str = text
+ self.entities: Optional[List[MessageEntity]] = entities
+ self.position: Optional[int] = position
+ self.is_manual: Optional[bool] = is_manual
+
+
+class ReplyParameters(JsonDeserializable, Dictionaryable, JsonSerializable):
+ """
+ Describes reply parameters for the message that is being sent.
+
+ Telegram documentation: https://core.telegram.org/bots/api#replyparameters
+
+ :param message_id: Identifier of the message that will be replied to in the current chat, or in the chat chat_id if it is specified
+ :type message_id: :obj:`int`
+
+ :param chat_id: Optional. If the message to be replied to is from a different chat, unique identifier for the chat or username of the channel (in the format @channelusername)
+ :type chat_id: :obj:`int` or :obj:`str`
+
+ :param allow_sending_without_reply: Optional. Pass True if the message should be sent even if the specified message to be replied to is not found; can be used only for replies in the same chat and forum topic.
+ :type allow_sending_without_reply: :obj:`bool`
+
+ :param quote: Optional. Quoted part of the message to be replied to; 0-1024 characters after entities parsing. The quote must be an exact substring of the message to be replied to, including bold, italic, underline, strikethrough, spoiler, and custom_emoji entities. The message will fail to send if the quote isn't found in the original message.
+ :type quote: :obj:`str`
+
+ :param quote_parse_mode: Optional. Mode for parsing entities in the quote. See formatting options for more details.
+ :type quote_parse_mode: :obj:`str`
+
+ :param quote_entities: Optional. A JSON-serialized list of special entities that appear in the quote. It can be specified instead of quote_parse_mode.
+ :type quote_entities: :obj:`list` of :class:`MessageEntity`
+
+ :param quote_position: Optional. Position of the quote in the original message in UTF-16 code units
+ :type quote_position: :obj:`int`
+
+ :return: Instance of the class
+ :rtype: :class:`ReplyParameters`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ obj['quote_entities'] = [MessageEntity.de_json(entity) for entity in obj.get('quote_entities', [])]
+ return cls(**obj)
+
+ def __init__(self, message_id: int, chat_id: Optional[Union[int, str]] = None,
+ allow_sending_without_reply: Optional[bool] = None, quote: Optional[str] = None,
+ quote_parse_mode: Optional[str] = None, quote_entities: Optional[List[MessageEntity]] = None,
+ quote_position: Optional[int] = None) -> None:
+ self.message_id: int = message_id
+ self.chat_id: Optional[Union[int, str]] = chat_id
+ self.allow_sending_without_reply: Optional[bool] = allow_sending_without_reply
+ self.quote: Optional[str] = quote
+ self.quote_parse_mode: Optional[str] = quote_parse_mode
+ self.quote_entities: Optional[List[MessageEntity]] = quote_entities
+ self.quote_position: Optional[int] = quote_position
+
+ def to_dict(self) -> dict:
+ json_dict = {
+ 'message_id': self.message_id
+ }
+ if self.chat_id is not None:
+ json_dict['chat_id'] = self.chat_id
+ if self.allow_sending_without_reply is not None:
+ json_dict['allow_sending_without_reply'] = self.allow_sending_without_reply
+ if self.quote is not None:
+ json_dict['quote'] = self.quote
+ if self.quote_parse_mode is not None:
+ json_dict['quote_parse_mode'] = self.quote_parse_mode
+ if self.quote_entities is not None:
+ json_dict['quote_entities'] = [entity.to_dict() for entity in self.quote_entities]
+ if self.quote_position is not None:
+ json_dict['quote_position'] = self.quote_position
+ return json_dict
+
+ def to_json(self) -> str:
+ return json.dumps(self.to_dict())
+
+
+class UsersShared(JsonDeserializable):
+ """
+ This object contains information about the users whose identifiers were shared with the bot
+ using a KeyboardButtonRequestUsers button.
+
+ Telegram documentation: https://core.telegram.org/bots/api#usersshared
+
+ :param request_id: Identifier of the request
+ :type request_id: :obj:`int`
+
+ :param user_ids: Identifiers of the shared users. These numbers may have more than 32 significant bits
+ and some programming languages may have difficulty/silent defects in interpreting them.
+ But they have at most 52 significant bits, so 64-bit integers or double-precision float
+ types are safe for storing these identifiers. The bot may not have access to the users and
+ could be unable to use these identifiers unless the users are already known to the bot by
+ some other means.
+ :type user_ids: :obj:`list` of :obj:`int`
+
+ :return: Instance of the class
+ :rtype: :class:`UsersShared`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ return cls(**obj)
+
+ def __init__(self, request_id, user_ids):
+ self.request_id = request_id
+ self.user_ids = user_ids
+
+
+class ChatBoostUpdated(JsonDeserializable):
+ """
+ This object represents a boost added to a chat or changed.
+
+ Telegram documentation: https://core.telegram.org/bots/api#chatboostupdated
+
+ :param chat: Chat which was boosted
+ :type chat: :class:`Chat`
+
+ :param boost: Infomation about the chat boost
+ :type boost: :class:`ChatBoost`
+
+ :return: Instance of the class
+ :rtype: :class:`ChatBoostUpdated`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ obj['chat'] = Chat.de_json(obj['chat'])
+ obj['boost'] = ChatBoost.de_json(obj['boost'])
+ return cls(**obj)
+
+ def __init__(self, chat, boost):
+ self.chat = chat
+ self.boost = boost
+
+
+class ChatBoostRemoved(JsonDeserializable):
+ """
+ This object represents a boost removed from a chat.
+
+ Telegram documentation: https://core.telegram.org/bots/api#chatboostremoved
+
+ :param chat: Chat which was boosted
+ :type chat: :class:`Chat`
+
+ :param boost_id: Unique identifier of the boost
+ :type boost_id: :obj:`str`
+
+ :param remove_date: Point in time (Unix timestamp) when the boost was removed
+ :type remove_date: :obj:`int`
+
+ :param source: Source of the removed boost
+ :type source: :class:`ChatBoostSource`
+
+ :return: Instance of the class
+ :rtype: :class:`ChatBoostRemoved`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ obj['chat'] = Chat.de_json(obj['chat'])
+ obj['source'] = ChatBoostSource.de_json(obj['source'])
+ return cls(**obj)
+
+ def __init__(self, chat, boost_id, remove_date, source):
+ self.chat = chat
+ self.boost_id = boost_id
+ self.remove_date = remove_date
+ self.source = source
+
+
+class ChatBoostSource(JsonDeserializable):
+ """
+ This object describes the source of a chat boost.
+
+ Telegram documentation: https://core.telegram.org/bots/api#chatboostsource
+
+ :param source: Source of the boost
+ :type source: :obj:`str`
+
+ :return: Instance of the class
+ :rtype: :class:`ChatBoostSource`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ return cls(**cls.check_json(json_string))
+
+ def __init__(self, source):
+ self.source = source
+
+
+class ChatBoostSourcePremium(ChatBoostSource):
+ """
+ The boost was obtained by subscribing to Telegram Premium or by gifting a Telegram Premium subscription to another user.
+
+ Telegram documentation: https://core.telegram.org/bots/api#chatboostsourcepremium
+
+ :param source: Source of the boost, always “premium”
+ :type source: :obj:`str`
+
+ :param user: User that boosted the chat
+ :type user: :class:`User`
+
+ :return: Instance of the class
+ :rtype: :class:`ChatBoostSourcePremium`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ user = User.de_json(obj['user'])
+ return cls(user)
+
+ def __init__(self, user):
+ super().__init__('premium')
+ self.user = user
+
+
+class ChatBoostSourceGiftCode(ChatBoostSource):
+ """
+ The boost was obtained by the creation of Telegram Premium gift codes to boost a chat.
+
+ Telegram documentation: https://core.telegram.org/bots/api#chatboostsourcegiftcode
+
+ :param source: Source of the boost, always “gift_code”
+ :type source: :obj:`str`
+
+ :param user: User for which the gift code was created
+ :type user: :class:`User`
+
+ :return: Instance of the class
+ :rtype: :class:`ChatBoostSourceGiftCode`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ user = User.de_json(obj['user'])
+ return cls(user)
+
+ def __init__(self, user):
+ super().__init__('gift_code')
+ self.user = user
+
+
+class ChatBoostSourceGiveaway(ChatBoostSource):
+ """
+ The boost was obtained by the creation of a Telegram Premium giveaway.
+
+ Telegram documentation: https://core.telegram.org/bots/api#chatboostsourcegiveaway
+
+ :param source: Source of the boost, always “giveaway”
+ :type source: :obj:`str`
+
+ :param giveaway_message_id: Identifier of a message in the chat with the giveaway; the message could have been deleted already. May be 0 if the message isn't sent yet.
+ :type giveaway_message_id: :obj:`int`
+
+ :param user: User that won the prize in the giveaway if any
+ :type user: :class:`User`
+
+ :param is_unclaimed: True, if the giveaway was completed, but there was no user to win the prize
+ :type is_unclaimed: :obj:`bool`
+
+ :return: Instance of the class
+ :rtype: :class:`ChatBoostSourceGiveaway`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ user = User.de_json(obj['user']) if 'user' in obj else None
+ return cls(obj['giveaway_message_id'], user, obj.get('is_unclaimed'))
+
+ def __init__(self, giveaway_message_id, user=None, is_unclaimed=None):
+ super().__init__('giveaway')
+ self.giveaway_message_id = giveaway_message_id
+ self.user = user
+ self.is_unclaimed = is_unclaimed
+
+
+class ChatBoost(JsonDeserializable):
+ """
+ This object contains information about a chat boost.
+
+ Telegram documentation: https://core.telegram.org/bots/api#chatboost
+
+ :param boost_id: Unique identifier of the boost
+ :type boost_id: :obj:`str`
+
+ :param add_date: Point in time (Unix timestamp) when the chat was boosted
+ :type add_date: :obj:`int`
+
+ :param expiration_date: Point in time (Unix timestamp) when the boost will automatically expire, unless the booster's Telegram Premium subscription is prolonged
+ :type expiration_date: :obj:`int`
+
+ :param source: Source of the added boost
+ :type source: :class:`ChatBoostSource`
+
+ :return: Instance of the class
+ :rtype: :class:`ChatBoost`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ obj['source'] = ChatBoostSource.de_json(obj['source'])
+ return cls(**obj)
+
+ def __init__(self, boost_id, add_date, expiration_date, source):
+ self.boost_id = boost_id
+ self.add_date = add_date
+ self.expiration_date = expiration_date
+ self.source: ChatBoostSource = source
+
+
+class UserChatBoosts(JsonDeserializable):
+ """
+ This object represents a list of boosts added to a chat by a user.
+
+ Telegram documentation: https://core.telegram.org/bots/api#userchatboosts
+
+ :param boosts: The list of boosts added to the chat by the user
+ :type boosts: :obj:`list` of :class:`ChatBoost`
+
+ :return: Instance of the class
+ :rtype: :class:`UserChatBoosts`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ obj['boosts'] = [ChatBoost.de_json(boost) for boost in obj['boosts']]
+ return cls(**obj)
+
+ def __init__(self, boosts):
+ self.boosts: ChatBoost = boosts
+
+
+class InaccessibleMessage(JsonDeserializable):
+ """
+ This object describes a message that was deleted or is otherwise inaccessible to the bot.
+
+ Telegram documentation: https://core.telegram.org/bots/api#inaccessiblemessage
+
+ :param chat: Chat the message belonged to
+ :type chat: :class:`Chat`
+
+ :param message_id: Unique message identifier inside the chat
+ :type message_id: :obj:`int`
+
+ :param date: Always 0. The field can be used to differentiate regular and inaccessible messages.
+ :type date: :obj:`int`
+
+ :return: Instance of the class
+ :rtype: :class:`InaccessibleMessage`
+ """
+
+ @classmethod
+ def de_json(cls, json_string):
+ if json_string is None:
+ return None
+ obj = cls.check_json(json_string)
+ obj['chat'] = Chat.de_json(obj['chat'])
+ return cls(**obj)
+
+ def __init__(self, chat, message_id, date):
+ self.chat = chat
+ self.message_id = message_id
+ self.date = date
diff --git a/telebot/util.py b/telebot/util.py
index 88fb4db96..9f0c7ab4c 100644
--- a/telebot/util.py
+++ b/telebot/util.py
@@ -45,7 +45,7 @@
update_types = [
"message", "edited_message", "channel_post", "edited_channel_post", "inline_query", "chosen_inline_result",
"callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer", "my_chat_member", "chat_member",
- "chat_join_request",
+ "chat_join_request", "message_reaction", "message_reaction_count", "chat_boost", "removed_chat_boost",
]
diff --git a/tests/test_handler_backends.py b/tests/test_handler_backends.py
index 21cf8f9b2..fa893c489 100644
--- a/tests/test_handler_backends.py
+++ b/tests/test_handler_backends.py
@@ -65,9 +65,13 @@ def update_type(message):
my_chat_member = None
chat_member = None
chat_join_request = None
+ message_reaction = None
+ message_reaction_count = None
+ chat_boost = None
+ chat_boost_removed = None
return types.Update(1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query,
chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer,
- my_chat_member, chat_member, chat_join_request)
+ my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed)
@pytest.fixture()
@@ -85,9 +89,13 @@ def reply_to_message_update_type(reply_to_message):
my_chat_member = None
chat_member = None
chat_join_request = None
+ message_reaction = None
+ message_reaction_count = None
+ chat_boost = None
+ chat_boost_removed = None
return types.Update(1001234038284, reply_to_message, edited_message, channel_post, edited_channel_post,
inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query,
- poll, poll_answer, my_chat_member, chat_member, chat_join_request)
+ poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed)
def next_handler(message):
diff --git a/tests/test_telebot.py b/tests/test_telebot.py
index 280a19f7c..52adbc2fe 100644
--- a/tests/test_telebot.py
+++ b/tests/test_telebot.py
@@ -542,9 +542,13 @@ def create_message_update(text):
my_chat_member = None
chat_member = None
chat_join_request = None
+ message_reaction = None
+ message_reaction_count = None
+ chat_boost = None
+ chat_boost_removed = None
return types.Update(-1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query,
chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer,
- my_chat_member, chat_member, chat_join_request)
+ my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed)
def test_is_string_unicode(self):
s1 = u'string'