Skip to content
Merged
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 changes/unreleased/5078.FoNwUYLbXQFRebTFhR6UPn.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
features = "Full Support for Bot API 9.3"

pull_requests = [
{ uid = "5086", author_uids = ["Bibo-Joshi"] },
{ uid = "5078", author_uid = "aelkheir", closes_threads = ["5077"] },
{ uid = "5079", author_uid = "aelkheir" },
{ uid = "5085", author_uids = ["Bibo-Joshi"] },
Expand Down
2 changes: 2 additions & 0 deletions docs/source/inclusions/bot_methods.rst
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,8 @@
- Used for setting the business accounts profile photo
* - :meth:`~telegram.Bot.post_story`
- Used for posting a story on behalf of business account.
* - :meth:`~telegram.Bot.repost_story`
- Used for reposting an existing story on behalf of business account.
* - :meth:`~telegram.Bot.edit_story`
- Used for editing business stories posted by the bot.
* - :meth:`~telegram.Bot.convert_gift_to_stars`
Expand Down
81 changes: 81 additions & 0 deletions src/telegram/_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,7 @@ async def forward_message(
video_start_timestamp: int | None = None,
direct_messages_topic_id: int | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
message_effect_id: str | None = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
Expand Down Expand Up @@ -1361,6 +1362,10 @@ async def forward_message(
forwarded to a direct messages chat.

.. versionadded:: 22.4
message_effect_id (:obj:`str`, optional): Unique identifier of the message effect to be
added to the message; only available when forwarding to private chats

.. versionadded:: NEXT.VERSION

Returns:
:class:`telegram.Message`: On success, the sent Message is returned.
Expand Down Expand Up @@ -1388,6 +1393,7 @@ async def forward_message(
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
direct_messages_topic_id=direct_messages_topic_id,
message_effect_id=message_effect_id,
)

async def forward_messages(
Expand Down Expand Up @@ -8414,6 +8420,7 @@ async def copy_message(
video_start_timestamp: int | None = None,
direct_messages_topic_id: int | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
message_effect_id: str | None = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: int | None = None,
Expand Down Expand Up @@ -8475,6 +8482,10 @@ async def copy_message(
direct_messages_topic_id (:obj:`int`, optional): |direct_messages_topic_id|

.. versionadded:: 22.4
message_effect_id (:obj:`str`, optional): Unique identifier of the message effect to be
added to the message; only available when copying to private chats

.. versionadded:: NEXT.VERSION

Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
Expand Down Expand Up @@ -8537,6 +8548,7 @@ async def copy_message(
"direct_messages_topic_id": direct_messages_topic_id,
"video_start_timestamp": video_start_timestamp,
"suggested_post_parameters": suggested_post_parameters,
"message_effect_id": message_effect_id,
}

result = await self._post(
Expand Down Expand Up @@ -11645,6 +11657,73 @@ async def decline_suggested_post(
api_kwargs=api_kwargs,
)

async def repost_story(
self,
business_connection_id: str,
from_chat_id: int,
from_story_id: int,
active_period: int,
post_to_chat_page: bool | None = None,
protect_content: ODVInput[bool] = 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,
) -> Story:
"""
Reposts a story on behalf of a business account from another business account.
Both business accounts must be managed by the same bot, and the story on the source account
must have been posted (or reposted) by the bot. Requires the
:attr:`~telegram.BusinessBotRight.can_manage_stories` business bot right for both
business accounts.

.. versionadded:: NEXT.VERSION

Args:
business_connection_id (:obj:`str`): Unique identifier of the business
from_chat_id (:obj:`int`): Unique identifier of the chat which posted the story that
should be reposted
from_story_id (:obj:`int`): Unique identifier of the story that should be reposted
active_period (:obj:`int`): Period after which the story is moved to the archive, in
seconds; must be one of
:tg-const:`telegram.constants.StoryLimit.SIX_HOURS`,
:tg-const:`telegram.constants.StoryLimit.TWELVE_HOURS`,
:tg-const:`telegram.constants.StoryLimit.ONE_DAY`, or
:tg-const:`telegram.constants.StoryLimit.TWO_DAYS`.
post_to_chat_page (:obj:`bool`, optional): Pass :obj:`True` to keep the story
accessible after it expires.
protect_content (:obj:`bool`, optional): Pass :obj:`True` if the content of the story
must be protected from forwarding and screenshotting

Returns:
:class:`telegram.Story`

Raises:
:class:`telegram.error.TelegramError`
"""
data: JSONDict = {
"business_connection_id": business_connection_id,
"from_chat_id": from_chat_id,
"from_story_id": from_story_id,
"active_period": active_period,
"post_to_chat_page": post_to_chat_page,
"protect_content": protect_content,
}
return Story.de_json(
data=await self._post(
"repostStory",
data,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
),
bot=self,
)

def to_dict(self, recursive: bool = True) -> JSONDict: # noqa: ARG002
"""See :meth:`telegram.TelegramObject.to_dict`."""
data: JSONDict = {"id": self.id, "username": self.username, "first_name": self.first_name}
Expand Down Expand Up @@ -11971,3 +12050,5 @@ def to_dict(self, recursive: bool = True) -> JSONDict: # noqa: ARG002
"""Alias for :meth:`approve_suggested_post`"""
declineSuggestedPost = decline_suggested_post
"""Alias for :meth:`decline_suggested_post`"""
repostStory = repost_story
"""Alias for :meth:`repost_story`"""
2 changes: 2 additions & 0 deletions src/telegram/_callbackquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,7 @@ async def copy_message(
allow_paid_broadcast: bool | None = None,
video_start_timestamp: int | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
message_effect_id: str | None = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: int | None = None,
Expand Down Expand Up @@ -925,6 +926,7 @@ async def copy_message(
show_caption_above_media=show_caption_above_media,
allow_paid_broadcast=allow_paid_broadcast,
suggested_post_parameters=suggested_post_parameters,
message_effect_id=message_effect_id,
)

MAX_ANSWER_TEXT_LENGTH: Final[int] = (
Expand Down
52 changes: 52 additions & 0 deletions src/telegram/_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
PhotoSize,
ReplyParameters,
Sticker,
Story,
SuggestedPostParameters,
UserChatBoosts,
Venue,
Expand Down Expand Up @@ -2361,6 +2362,7 @@ async def send_copy(
video_start_timestamp: int | None = None,
direct_messages_topic_id: int | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
message_effect_id: str | None = None,
*,
reply_to_message_id: int | None = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
Expand Down Expand Up @@ -2406,6 +2408,7 @@ async def send_copy(
allow_paid_broadcast=allow_paid_broadcast,
direct_messages_topic_id=direct_messages_topic_id,
suggested_post_parameters=suggested_post_parameters,
message_effect_id=message_effect_id,
)

async def copy_message(
Expand All @@ -2425,6 +2428,7 @@ async def copy_message(
video_start_timestamp: int | None = None,
direct_messages_topic_id: int | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
message_effect_id: str | None = None,
*,
reply_to_message_id: int | None = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
Expand Down Expand Up @@ -2470,6 +2474,7 @@ async def copy_message(
allow_paid_broadcast=allow_paid_broadcast,
direct_messages_topic_id=direct_messages_topic_id,
suggested_post_parameters=suggested_post_parameters,
message_effect_id=message_effect_id,
)

async def send_copies(
Expand Down Expand Up @@ -2576,6 +2581,7 @@ async def forward_from(
video_start_timestamp: int | None = None,
direct_messages_topic_id: int | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
message_effect_id: str | None = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
Expand Down Expand Up @@ -2612,6 +2618,7 @@ async def forward_from(
message_thread_id=message_thread_id,
direct_messages_topic_id=direct_messages_topic_id,
suggested_post_parameters=suggested_post_parameters,
message_effect_id=message_effect_id,
)

async def forward_to(
Expand All @@ -2624,6 +2631,7 @@ async def forward_to(
video_start_timestamp: int | None = None,
direct_messages_topic_id: int | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
message_effect_id: str | None = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
Expand Down Expand Up @@ -2661,6 +2669,7 @@ async def forward_to(
message_thread_id=message_thread_id,
direct_messages_topic_id=direct_messages_topic_id,
suggested_post_parameters=suggested_post_parameters,
message_effect_id=message_effect_id,
)

async def forward_messages_from(
Expand Down Expand Up @@ -3892,6 +3901,49 @@ async def decline_suggested_post(
api_kwargs=api_kwargs,
)

async def repost_story(
self,
business_connection_id: str,
from_story_id: int,
active_period: int,
post_to_chat_page: bool | None = None,
protect_content: ODVInput[bool] = 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,
) -> "Story":
"""Shortcut for::

await bot.repost_story(
from_chat_id=update.effective_chat.id,
*args, **kwargs
)

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

.. versionadded:: NEXT.VERSION

Returns:
:class:`Story`: On success, :class:`Story` is returned.

"""
return await self.get_bot().repost_story(
business_connection_id=business_connection_id,
from_chat_id=self.id,
from_story_id=from_story_id,
active_period=active_period,
post_to_chat_page=post_to_chat_page,
protect_content=protect_content,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)


class Chat(_ChatBase):
"""This object represents a chat.
Expand Down
13 changes: 13 additions & 0 deletions src/telegram/_checklists.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional

from telegram._chat import Chat
from telegram._messageentity import MessageEntity
from telegram._telegramobject import TelegramObject
from telegram._user import User
Expand Down Expand Up @@ -51,6 +52,10 @@ class ChecklistTask(TelegramObject):
entities that appear in the task text.
completed_by_user (:class:`telegram.User`, optional): User that completed the task; omitted
if the task wasn't completed
completed_by_chat (:class:`telegram.Chat`, optional): Chat that completed the task; omitted
if the task wasn't completed by a chat

.. versionadded:: NEXT.VERSION
completion_date (:class:`datetime.datetime`, optional): Point in time when
the task was completed; :attr:`~telegram.constants.ZERO_DATE` if the task wasn't
completed
Expand All @@ -64,6 +69,10 @@ class ChecklistTask(TelegramObject):
entities that appear in the task text.
completed_by_user (:class:`telegram.User`): Optional. User that completed the task; omitted
if the task wasn't completed
completed_by_chat (:class:`telegram.Chat`): Optional. Chat that completed the task; omitted
if the task wasn't completed by a chat

.. versionadded:: NEXT.VERSION
completion_date (:class:`datetime.datetime`): Optional. Point in time when
the task was completed; :attr:`~telegram.constants.ZERO_DATE` if the task wasn't
completed
Expand All @@ -72,6 +81,7 @@ class ChecklistTask(TelegramObject):
"""

__slots__ = (
"completed_by_chat",
"completed_by_user",
"completion_date",
"id",
Expand All @@ -86,6 +96,7 @@ def __init__(
text_entities: Sequence[MessageEntity] | None = None,
completed_by_user: User | None = None,
completion_date: dtm.datetime | None = None,
completed_by_chat: Chat | None = None,
*,
api_kwargs: JSONDict | None = None,
):
Expand All @@ -94,6 +105,7 @@ def __init__(
self.text: str = text
self.text_entities: tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self.completed_by_user: User | None = completed_by_user
self.completed_by_chat: Chat | None = completed_by_chat
self.completion_date: dtm.datetime | None = completion_date

self._id_attrs = (self.id,)
Expand All @@ -114,6 +126,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChecklistTask"
data["completion_date"] = from_timestamp(date, tzinfo=loc_tzinfo)

data["completed_by_user"] = de_json_optional(data.get("completed_by_user"), User, bot)
data["completed_by_chat"] = de_json_optional(data.get("completed_by_chat"), Chat, bot)
data["text_entities"] = de_list_optional(data.get("text_entities"), MessageEntity, bot)

return super().de_json(data=data, bot=bot)
Expand Down
6 changes: 6 additions & 0 deletions src/telegram/_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -3871,6 +3871,7 @@ async def forward(
message_thread_id: int | None = None,
video_start_timestamp: int | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
message_effect_id: str | None = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
Expand Down Expand Up @@ -3917,6 +3918,7 @@ async def forward(
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
direct_messages_topic_id=self._extract_direct_messages_topic_id(),
message_effect_id=message_effect_id,
)

async def copy(
Expand All @@ -3934,6 +3936,7 @@ async def copy(
allow_paid_broadcast: bool | None = None,
video_start_timestamp: int | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
message_effect_id: str | None = None,
*,
reply_to_message_id: int | None = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
Expand Down Expand Up @@ -3984,6 +3987,7 @@ async def copy(
allow_paid_broadcast=allow_paid_broadcast,
direct_messages_topic_id=self._extract_direct_messages_topic_id(),
suggested_post_parameters=suggested_post_parameters,
message_effect_id=message_effect_id,
)

async def reply_copy(
Expand All @@ -4002,6 +4006,7 @@ async def reply_copy(
allow_paid_broadcast: bool | None = None,
video_start_timestamp: int | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
message_effect_id: str | None = None,
*,
reply_to_message_id: int | None = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
Expand Down Expand Up @@ -4066,6 +4071,7 @@ async def reply_copy(
allow_paid_broadcast=allow_paid_broadcast,
direct_messages_topic_id=self._extract_direct_messages_topic_id(),
suggested_post_parameters=suggested_post_parameters,
message_effect_id=message_effect_id,
)

async def reply_paid_media(
Expand Down
Loading
Loading