Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions 1 changes/unreleased/5078.FoNwUYLbXQFRebTFhR6UPn.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ features = "Full Support for Bot API 9.3"

pull_requests = [
{ uid = "5078", author_uid = "aelkheir", closes_threads = ["5077"] },
{ uid = "5079", author_uid = "aelkheir" },
]
2 changes: 2 additions & 0 deletions 2 docs/source/inclusions/bot_methods.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
- Used for sending media grouped together
* - :meth:`~telegram.Bot.send_message`
- Used for sending text messages
* - :meth:`~telegram.Bot.send_message_draft`
- Used for streaming partial text messages
* - :meth:`~telegram.Bot.send_paid_media`
- Used for sending paid media to channels
* - :meth:`~telegram.Bot.send_photo`
Expand Down
2 changes: 1 addition & 1 deletion 2 docs/substitutions/global.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

.. |message_thread_id| replace:: Unique identifier for the target message thread of the forum topic.

.. |message_thread_id_arg| replace:: Unique identifier for the target message thread (topic) of the forum; for forum supergroups only.
.. |message_thread_id_arg| replace:: Unique identifier for the target message thread (topic) of a forum; for forum supergroups and private chats of bots with forum topic mode enabled only.

.. |parse_mode| replace:: Mode for parsing entities. See :class:`telegram.constants.ParseMode` and `formatting options <https://core.telegram.org/bots/api#formatting-options>`__ for more details.

Expand Down
86 changes: 78 additions & 8 deletions 86 src/telegram/_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,69 @@ async def delete_message(
api_kwargs=api_kwargs,
)

async def send_message_draft(
self,
chat_id: int,
draft_id: int,
text: str,
message_thread_id: int | None = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
entities: Sequence["MessageEntity"] | None = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict | None = None,
) -> bool:
"""Use this method to stream a partial message to a user while the message is being
generated; supported only for bots with forum topic mode enabled.

.. versionadded:: NEXT.VERSION

Args:
chat_id (:obj:`int`): Unique identifier for the target private chat.
draft_id (:obj:`int`): Unique identifier of the message draft; must be non-zero.
Changes of drafts with the same identifier are animated.
text (:obj:`str`): Text of the message to be sent,
:tg-const:`telegram.constants.MessageLimit.MIN_TEXT_LENGTH`-
:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`): |parse_mode|
entities (Sequence[:class:`telegram.MessageEntity`], optional): Sequence of special
entities that appear in message text, which can be specified instead of
:paramref:`parse_mode`.

|sequenceargs|
message_thread_id (:obj:`int`, optional): Unique identifier for the target
message thread.


Returns:
:obj:`bool`: On success, :obj:`True` is returned.

Raises:
:class:`telegram.error.TelegramError`

"""
data: JSONDict = {
"chat_id": chat_id,
"draft_id": draft_id,
"text": text,
"entities": entities,
}
return await self._send_message(
"sendMessageDraft",
data,
message_thread_id=message_thread_id,
parse_mode=parse_mode,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)

async def delete_messages(
self,
chat_id: int | str,
Expand Down Expand Up @@ -3721,7 +3784,9 @@ async def send_chat_action(
action(:obj:`str`): Type of action to broadcast. Choose one, depending on what the user
is about to receive. For convenience look at the constants in
:class:`telegram.constants.ChatAction`.
message_thread_id (:obj:`int`, optional): |message_thread_id_arg|
message_thread_id (:obj:`int`, optional): Unique identifier for the target message
thread or topic of a forum; for supergroups and private chats of bots with forum
topic mode enabled only

.. versionadded:: 20.0
business_connection_id (:obj:`str`, optional): |business_id_str|
Expand Down Expand Up @@ -8903,8 +8968,9 @@ async def edit_forum_topic(
api_kwargs: JSONDict | None = None,
) -> bool:
"""
Use this method to edit name and icon of a topic in a forum supergroup chat. The bot must
be an administrator in the chat for this to work and must have the
Use this method to edit name and icon of a topic in a forum supergroup chat or a private
chat with a user. In the case of a supergroup chat the bot must be an administrator in the
chat for this to work and must have the
:paramref:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights,
unless it is the creator of the topic.

Expand Down Expand Up @@ -9046,7 +9112,8 @@ async def delete_forum_topic(
) -> bool:
"""
Use this method to delete a forum topic along with all its messages in a forum supergroup
chat. The bot must be an administrator in the chat for this to work and must have
chat or a private chat with a user. In the case of a supergroup chat the bot must be an
administrator in the chat for this to work and must have the
:paramref:`~telegram.ChatAdministratorRights.can_delete_messages` administrator rights.

.. versionadded:: 20.0
Expand Down Expand Up @@ -9088,10 +9155,11 @@ async def unpin_all_forum_topic_messages(
api_kwargs: JSONDict | None = None,
) -> bool:
"""
Use this method to clear the list of pinned messages in a forum topic. The bot must
be an administrator in the chat for this to work and must have
:paramref:`~telegram.ChatAdministratorRights.can_pin_messages` administrator rights
in the supergroup.
Use this method to clear the list of pinned messages in a forum topic in a forum supergroup
chat or a private chat with a user. In the case of a supergroup chat the bot must be an
administrator in the chat for this to work and must have the
:paramref:`~telegram.ChatAdministratorRights.can_pin_messages` administrator right in
the supergroup.

.. versionadded:: 20.0

Expand Down Expand Up @@ -11589,6 +11657,8 @@ def to_dict(self, recursive: bool = True) -> JSONDict: # noqa: ARG002
"""Alias for :meth:`get_me`"""
sendMessage = send_message
"""Alias for :meth:`send_message`"""
sendMessageDraft = send_message_draft
"""Alias for :meth:`send_message_draft`"""
deleteMessage = delete_message
"""Alias for :meth:`delete_message`"""
deleteMessages = delete_messages
Expand Down
38 changes: 38 additions & 0 deletions 38 src/telegram/_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,44 @@ async def send_message(
suggested_post_parameters=suggested_post_parameters,
)

async def send_message_draft(
self,
draft_id: int,
text: str,
message_thread_id: int | None = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
entities: Sequence["MessageEntity"] | None = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict | None = None,
) -> bool:
"""Shortcut for::

await bot.send_message_draft(update.effective_chat.id, *args, **kwargs)

For the documentation of the arguments, please see :meth:`telegram.Bot.send_message_draft`.

Returns:
:obj:`bool`: On success, :obj:`True` is returned.

"""
return await self.get_bot().send_message_draft(
chat_id=self.id,
draft_id=draft_id,
text=text,
message_thread_id=message_thread_id,
parse_mode=parse_mode,
entities=entities,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)

async def delete_message(
self,
message_id: int,
Expand Down
30 changes: 28 additions & 2 deletions 30 src/telegram/_forumtopic.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,38 @@ class ForumTopic(TelegramObject):
icon_color (:obj:`int`): Color of the topic icon in RGB format
icon_custom_emoji_id (:obj:`str`, optional): Unique identifier of the custom emoji shown
as the topic icon.
is_name_implicit (:obj:`bool`, optional): :obj:`True`, if the name of the topic wasn't
specified explicitly by its creator and likely needs to be changed by the bot.

.. versionadded:: NEXT.VERSION

Attributes:
message_thread_id (:obj:`int`): Unique identifier of the forum topic
name (:obj:`str`): Name of the topic
icon_color (:obj:`int`): Color of the topic icon in RGB format
icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the custom emoji shown
as the topic icon.
is_name_implicit (:obj:`bool`): Optional. :obj:`True`, if the name of the topic wasn't
specified explicitly by its creator and likely needs to be changed by the bot.

.. versionadded:: NEXT.VERSION
"""

__slots__ = ("icon_color", "icon_custom_emoji_id", "message_thread_id", "name")
__slots__ = (
"icon_color",
"icon_custom_emoji_id",
"is_name_implicit",
"message_thread_id",
"name",
)

def __init__(
self,
message_thread_id: int,
name: str,
icon_color: int,
icon_custom_emoji_id: str | None = None,
is_name_implicit: bool | None = None,
*,
api_kwargs: JSONDict | None = None,
):
Expand All @@ -63,6 +78,7 @@ def __init__(
self.name: str = name
self.icon_color: int = icon_color
self.icon_custom_emoji_id: str | None = icon_custom_emoji_id
self.is_name_implicit: bool | None = is_name_implicit

self._id_attrs = (self.message_thread_id, self.name, self.icon_color)

Expand All @@ -84,28 +100,38 @@ class ForumTopicCreated(TelegramObject):
icon_color (:obj:`int`): Color of the topic icon in RGB format
icon_custom_emoji_id (:obj:`str`, optional): Unique identifier of the custom emoji shown
as the topic icon.
is_name_implicit (:obj:`bool`, optional): :obj:`True`, if the name of the topic wasn't
specified explicitly by its creator and likely needs to be changed by the bot.

.. versionadded:: NEXT.VERSION

Attributes:
name (:obj:`str`): Name of the topic
icon_color (:obj:`int`): Color of the topic icon in RGB format
icon_custom_emoji_id (:obj:`str`): Optional. Unique identifier of the custom emoji shown
as the topic icon.
is_name_implicit (:obj:`bool`): Optional. :obj:`True`, if the name of the topic wasn't
specified explicitly by its creator and likely needs to be changed by the bot.

.. versionadded:: NEXT.VERSION
"""

__slots__ = ("icon_color", "icon_custom_emoji_id", "name")
__slots__ = ("icon_color", "icon_custom_emoji_id", "is_name_implicit", "name")

def __init__(
self,
name: str,
icon_color: int,
icon_custom_emoji_id: str | None = None,
is_name_implicit: bool | None = None,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(api_kwargs=api_kwargs)
self.name: str = name
self.icon_color: int = icon_color
self.icon_custom_emoji_id: str | None = icon_custom_emoji_id
self.is_name_implicit: bool | None = is_name_implicit

self._id_attrs = (self.name, self.icon_color)

Expand Down
69 changes: 58 additions & 11 deletions 69 src/telegram/_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,12 +496,12 @@ class Message(MaybeInaccessibleMessage):
reply_markup (:class:`telegram.InlineKeyboardMarkup`, optional): Inline keyboard attached
to the message. :paramref:`~telegram.InlineKeyboardButton.login_url` buttons are
represented as ordinary url buttons.
is_topic_message (:obj:`bool`, optional): :obj:`True`, if the message is sent to a forum
topic.
is_topic_message (:obj:`bool`, optional): :obj:`True`, if the message is sent to a topic
in a forum supergroup or a private chat with the bot.

.. versionadded:: 20.0
message_thread_id (:obj:`int`, optional): Unique identifier of a message thread to which
the message belongs; for supergroups only.
message_thread_id (:obj:`int`, optional): Unique identifier of a message thread or forum
topic to which the message belongs; for supergroups and private chats only.

.. versionadded:: 20.0
forum_topic_created (:class:`telegram.ForumTopicCreated`, optional): Service message:
Expand Down Expand Up @@ -898,12 +898,12 @@ class Message(MaybeInaccessibleMessage):
reply_markup (:class:`telegram.InlineKeyboardMarkup`): Optional. Inline keyboard attached
to the message. :paramref:`~telegram.InlineKeyboardButton.login_url` buttons are
represented as ordinary url buttons.
is_topic_message (:obj:`bool`): Optional. :obj:`True`, if the message is sent to a forum
topic.
is_topic_message (:obj:`bool`): Optional. :obj:`True`, if the message is sent to a topic
in a forum supergroup or a private chat with the bot.

.. versionadded:: 20.0
message_thread_id (:obj:`int`): Optional. Unique identifier of a message thread to which
the message belongs; for supergroups only.
message_thread_id (:obj:`int`): Optional. Unique identifier of a message thread or forum
topic to which the message belongs; for supergroups and private chats only.

.. versionadded:: 20.0
forum_topic_created (:class:`telegram.ForumTopicCreated`): Optional. Service message:
Expand Down Expand Up @@ -1982,9 +1982,9 @@ def _parse_message_thread_id(
return message_thread_id

# self.message_thread_id can be used for send_*.param.message_thread_id only if the
# thread is a forum topic. It does not work if the thread is a chain of replies to a
# message in a normal group. In that case, self.message_thread_id is just the message_id
# of the first message in the chain.
# thread is a forum topic (in supergroups or private chats). It does not work if the
# thread is a chain of replies to a message in a normal group. In that case,
# self.message_thread_id is just the message_id of the first message in the chain.
if not self.is_topic_message:
return None

Expand Down Expand Up @@ -2077,6 +2077,53 @@ async def reply_text(
suggested_post_parameters=suggested_post_parameters,
)

async def reply_text_draft(
self,
draft_id: int,
text: str,
parse_mode: ODVInput[str] = DEFAULT_NONE,
entities: Sequence["MessageEntity"] | None = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict | None = None,
) -> bool:
"""Shortcut for::

await bot.send_message_draft(
update.effective_message.chat_id,
message_thread_id=update.effective_message.message_thread_id,
*args,
**kwargs,
)

For the documentation of the arguments, please see :meth:`telegram.Bot.send_message_draft`.

Note:
|reply_same_thread|

Returns:
:obj:`bool`: On success, :obj:`True` is returned.

"""
message_thread_id = self._parse_message_thread_id(self.chat_id, message_thread_id)
return await self.get_bot().send_message_draft(
chat_id=self.chat_id,
draft_id=draft_id,
text=text,
parse_mode=parse_mode,
entities=entities,
message_thread_id=message_thread_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)

async def reply_markdown(
self,
text: str,
Expand Down
Loading
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.