Add support for forum topics

This commit is contained in:
wulan17 2023-10-12 22:48:12 +03:00 committed by KurimuzonAkuma
parent 85c2d7a885
commit 58f2254f4f
51 changed files with 1434 additions and 52 deletions

View File

@ -123,5 +123,14 @@ class ChatEventAction(AutoName):
MESSAGE_UNPINNED = auto() MESSAGE_UNPINNED = auto()
"a message has been unpinned (see ``unpinned_message``)" "a message has been unpinned (see ``unpinned_message``)"
CREATED_FORUM_TOPIC = auto()
"a new forum topic has been created (see `created_forum_topic`)"
EDITED_FORUM_TOPIC = auto()
"a forum topic has been edited (see `old_forum_topic` and `new_forum_topic`)"
DELETED_FORUM_TOPIC = auto()
"a forum topic has been deleted (see `deleted_forum_topic`)"
UNKNOWN = auto() UNKNOWN = auto()
"Unknown chat event action" "Unknown chat event action"

View File

@ -39,6 +39,24 @@ class MessageServiceType(AutoName):
DELETE_CHAT_PHOTO = auto() DELETE_CHAT_PHOTO = auto()
"Deleted chat photo" "Deleted chat photo"
FORUM_TOPIC_CREATED = auto()
"a new forum topic created in the chat"
FORUM_TOPIC_CLOSED = auto()
"a new forum topic closed in the chat"
FORUM_TOPIC_REOPENED = auto()
"a new forum topic reopened in the chat"
FORUM_TOPIC_EDITED = auto()
"a new forum topic renamed in the chat"
GENERAL_TOPIC_HIDDEN = auto()
"a forum general topic hidden in the chat"
GENERAL_TOPIC_UNHIDDEN = auto()
"a forum general topic unhidden in the chat"
GROUP_CHAT_CREATED = auto() GROUP_CHAT_CREATED = auto()
"Group chat created" "Group chat created"

View File

@ -21,6 +21,7 @@ from typing import Union
import pyrogram import pyrogram
from pyrogram import raw from pyrogram import raw
from pyrogram import types from pyrogram import types
from pyrogram import utils
class SendGame: class SendGame:
@ -29,6 +30,7 @@ class SendGame:
chat_id: Union[int, str], chat_id: Union[int, str],
game_short_name: str, game_short_name: str,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
protect_content: bool = None, protect_content: bool = None,
reply_markup: Union[ reply_markup: Union[
@ -55,6 +57,10 @@ class SendGame:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs.
for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -84,7 +90,7 @@ class SendGame:
), ),
message="", message="",
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
noforwards=protect_content, noforwards=protect_content,
reply_markup=await reply_markup.write(self) if reply_markup else None reply_markup=await reply_markup.write(self) if reply_markup else None

View File

@ -20,6 +20,7 @@ from typing import Union
import pyrogram import pyrogram
from pyrogram import raw from pyrogram import raw
from pyrogram import utils
class SendInlineBotResult: class SendInlineBotResult:
@ -29,6 +30,7 @@ class SendInlineBotResult:
query_id: int, query_id: int,
result_id: str, result_id: str,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None reply_to_message_id: int = None
) -> "raw.base.Updates": ) -> "raw.base.Updates":
"""Send an inline bot result. """Send an inline bot result.
@ -52,6 +54,10 @@ class SendInlineBotResult:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs.
for supergroups only
reply_to_message_id (``bool``, *optional*): reply_to_message_id (``bool``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -70,6 +76,6 @@ class SendInlineBotResult:
id=result_id, id=result_id,
random_id=self.rnd_id(), random_id=self.rnd_id(),
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id)
) )
) )

View File

@ -20,12 +20,16 @@ from .add_chat_members import AddChatMembers
from .archive_chats import ArchiveChats from .archive_chats import ArchiveChats
from .ban_chat_member import BanChatMember from .ban_chat_member import BanChatMember
from .create_channel import CreateChannel from .create_channel import CreateChannel
from .create_forum_topic import CreateForumTopic
from .create_group import CreateGroup from .create_group import CreateGroup
from .create_supergroup import CreateSupergroup from .create_supergroup import CreateSupergroup
from .close_forum_topic import CloseForumTopic
from .delete_channel import DeleteChannel from .delete_channel import DeleteChannel
from .delete_chat_photo import DeleteChatPhoto from .delete_chat_photo import DeleteChatPhoto
from .delete_forum_topic import DeleteForumTopic
from .delete_supergroup import DeleteSupergroup from .delete_supergroup import DeleteSupergroup
from .delete_user_history import DeleteUserHistory from .delete_user_history import DeleteUserHistory
from .edit_forum_topic import EditForumTopic
from .get_chat import GetChat from .get_chat import GetChat
from .get_chat_event_log import GetChatEventLog from .get_chat_event_log import GetChatEventLog
from .get_chat_member import GetChatMember from .get_chat_member import GetChatMember
@ -34,6 +38,8 @@ from .get_chat_members_count import GetChatMembersCount
from .get_chat_online_count import GetChatOnlineCount from .get_chat_online_count import GetChatOnlineCount
from .get_dialogs import GetDialogs from .get_dialogs import GetDialogs
from .get_dialogs_count import GetDialogsCount from .get_dialogs_count import GetDialogsCount
from .get_forum_topics import GetForumTopics
from .get_forum_topics_by_id import GetForumTopicsByID
from .get_nearby_chats import GetNearbyChats from .get_nearby_chats import GetNearbyChats
from .get_send_as_chats import GetSendAsChats from .get_send_as_chats import GetSendAsChats
from .join_chat import JoinChat from .join_chat import JoinChat
@ -78,14 +84,20 @@ class Chats(
SetChatUsername, SetChatUsername,
SetChatPermissions, SetChatPermissions,
GetDialogsCount, GetDialogsCount,
GetForumTopics,
GetForumTopicsByID,
ArchiveChats, ArchiveChats,
UnarchiveChats, UnarchiveChats,
CreateGroup, CreateGroup,
CreateSupergroup, CreateSupergroup,
CreateChannel, CreateChannel,
CreateForumTopic,
CloseForumTopic,
AddChatMembers, AddChatMembers,
DeleteChannel, DeleteChannel,
DeleteForumTopic,
DeleteSupergroup, DeleteSupergroup,
EditForumTopic,
GetNearbyChats, GetNearbyChats,
SetAdministratorTitle, SetAdministratorTitle,
SetSlowMode, SetSlowMode,

View File

@ -0,0 +1,58 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import pyrogram
from pyrogram import raw
from pyrogram import types
from typing import Union
class CloseForumTopic:
async def close_forum_topic(
self: "pyrogram.Client",
chat_id: Union[int, str],
topic_id: int
) -> bool:
"""Close a forum topic.
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
topic_id (``int``):
Unique identifier (int) of the target forum topic.
Returns:
`bool`: On success, a Boolean is returned.
Example:
.. code-block:: python
await app.close_forum_topic(chat_id, topic_id)
"""
await self.invoke(
raw.functions.channels.EditForumTopic(
channel=await self.resolve_peer(chat_id),
topic_id=topic_id,
closed=True
)
)
return True

View File

@ -0,0 +1,68 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import pyrogram
from pyrogram import raw
from pyrogram import types
from typing import Union
class CreateForumTopic:
async def create_forum_topic(
self: "pyrogram.Client",
chat_id: Union[int, str],
title: str,
icon_color: int = None,
icon_emoji_id: int = None
) -> "types.ForumTopicCreated":
"""Create a new forum topic.
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
title (``str``):
The forum topic title.
icon_color (``int``, *optional*):
The color of forum topic icon.
icon_emoji_id (``int``, *optional*):
Unique identifier of the custom emoji shown as the topic icon
Returns:
:obj:`~pyrogram.types.ForumTopicCreated`: On success, a forum_topic_created object is returned.
Example:
.. code-block:: python
await app.create_forum_topic("Topic Title")
"""
r = await self.invoke(
raw.functions.channels.CreateForumTopic(
channel=await self.resolve_peer(chat_id),
title=title,
random_id=self.rnd_id(),
icon_color=icon_color,
icon_emoji_id=icon_emoji_id
)
)
return types.ForumTopicCreated._parse(r.updates[1].message)

View File

@ -0,0 +1,57 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import pyrogram
from pyrogram import raw
from pyrogram import types
from typing import Union
class DeleteForumTopic:
async def delete_forum_topic(
self: "pyrogram.Client",
chat_id: Union[int, str],
topic_id: int
) -> bool:
"""Delete a forum topic.
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
topic_id (``int``):
Unique identifier (int) of the target forum topic.
Returns:
`bool`: On success, a Boolean is returned.
Example:
.. code-block:: python
await app.delete_forum_topic(chat_id, topic_id)
"""
await self.invoke(
raw.functions.channels.DeleteTopicHistory(
channel=await self.resolve_peer(chat_id),
top_msg_id=topic_id
)
)
return True

View File

@ -0,0 +1,77 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import pyrogram
from pyrogram import raw
from pyrogram import types
from typing import Union
class EditForumTopic:
async def edit_forum_topic(
self: "pyrogram.Client",
chat_id: Union[int, str],
topic_id: int,
title: str = None,
icon_emoji_id: int = None,
closed: bool = None,
hidden: bool = None
) -> bool:
"""Edit a forum topic.
.. include:: /_includes/usable-by/users-bots.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
topic_id (``int``):
Unique identifier (int) of the target forum topic.
title (``str``, *optional*):
The forum topic title.
icon_emoji_id (``int``, *optional*):
Unique identifier of the custom emoji shown as the topic icon.
closed (``bool``, *optional*):
Close forum topic.
hidden (``bool``, *optional*):
Hide forum topic.
Returns:
`bool`: On success, a Boolean is returned.
Example:
.. code-block:: python
await app.edit_forum_topic(chat_id,topic_id,"New Topic Title")
"""
await self.invoke(
raw.functions.channels.EditForumTopic(
channel=await self.resolve_peer(chat_id),
topic_id=topic_id,
title=title,
icon_emoji_id=icon_emoji_id,
closed=closed,
hidden=hidden
)
)
return True

View File

@ -0,0 +1,64 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Union, Optional, AsyncGenerator
import pyrogram
from pyrogram import raw
from pyrogram import types
class GetForumTopics:
async def get_forum_topics(
self: "pyrogram.Client",
chat_id: Union[int, str],
limit: int = 0
) -> Optional[AsyncGenerator["types.ForumTopic", None]]:
"""Get one or more topic from a chat.
.. include:: /_includes/usable-by/users.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
limit (``int``, *optional*):
Limits the number of topics to be retrieved.
Returns:
``Generator``: On success, a generator yielding :obj:`~pyrogram.types.ForumTopic` objects is returned.
Example:
.. code-block:: python
# get all forum topics
async for topic in app.get_forum_topics(chat_id):
print(topic)
"""
r = await self.invoke(
raw.functions.channels.GetForumTopics(
channel=await self.resolve_peer(chat_id),
offset_date=0,
offset_id=0,
offset_topic=0,
limit=limit
)
)
for topic in r.topics:
yield types.ForumTopic._parse(topic)

View File

@ -0,0 +1,79 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging
from typing import Union, List, Iterable
import pyrogram
from pyrogram import raw
from pyrogram import types
from pyrogram import utils
log = logging.getLogger(__name__)
class GetForumTopicsByID:
async def get_forum_topics_by_id(
self: "pyrogram.Client",
chat_id: Union[int, str],
topic_ids: Union[int, Iterable[int]]
) -> Union["types.ForumTopic", List["types.ForumTopic"]]:
"""Get one or more topic from a chat by using topic identifiers.
.. include:: /_includes/usable-by/users.rst
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
topic_ids (``int`` | Iterable of ``int``, *optional*):
Pass a single topic identifier or an iterable of topic ids (as integers) to get the information of the
topic themselves.
Returns:
:obj:`~pyrogram.types.ForumTopic` | List of :obj:`~pyrogram.types.ForumTopic`: In case *topic_ids* was not
a list, a single topic is returned, otherwise a list of topics is returned.
Example:
.. code-block:: python
# Get one topic
await app.get_forum_topics_by_id(chat_id, 12345)
# Get more than one topic (list of topics)
await app.get_forum_topics_by_id(chat_id, [12345, 12346])
Raises:
ValueError: In case of invalid arguments.
"""
is_iterable = not isinstance(topic_ids, int)
ids = list(topic_ids) if is_iterable else [topic_ids]
r = await self.invoke(
raw.functions.channels.GetForumTopicsByID(
channel=await self.resolve_peer(chat_id),
topics=ids
)
)
topics = types.List()
for i in r:
topics.append(types.ForumTopic._parse(i))
return topics if is_iterable else topics[0]

View File

@ -92,6 +92,7 @@ class PromoteChatMember:
pin_messages=privileges.can_pin_messages, pin_messages=privileges.can_pin_messages,
add_admins=privileges.can_promote_members, add_admins=privileges.can_promote_members,
manage_call=privileges.can_manage_video_chats, manage_call=privileges.can_manage_video_chats,
manage_topics=privileges.can_manage_topics,
other=privileges.can_manage_chat other=privileges.can_manage_chat
), ),
rank=rank or "" rank=rank or ""

View File

@ -92,6 +92,7 @@ class RestrictChatMember:
change_info=not permissions.can_change_info, change_info=not permissions.can_change_info,
invite_users=not permissions.can_invite_users, invite_users=not permissions.can_invite_users,
pin_messages=not permissions.can_pin_messages, pin_messages=not permissions.can_pin_messages,
manage_topics=not permissions.can_manage_topics,
) )
) )
) )

View File

@ -80,6 +80,7 @@ class SetChatPermissions:
change_info=not permissions.can_change_info, change_info=not permissions.can_change_info,
invite_users=not permissions.can_invite_users, invite_users=not permissions.can_invite_users,
pin_messages=not permissions.can_pin_messages, pin_messages=not permissions.can_pin_messages,
manage_topics=not permissions.can_manage_topics,
) )
) )
) )

View File

@ -31,6 +31,7 @@ class CopyMediaGroup:
message_id: int, message_id: int,
captions: Union[List[str], str] = None, captions: Union[List[str], str] = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
) -> List["types.Message"]: ) -> List["types.Message"]:
@ -65,6 +66,10 @@ class CopyMediaGroup:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -119,7 +124,7 @@ class CopyMediaGroup:
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
multi_media=multi_media, multi_media=multi_media,
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
schedule_date=utils.datetime_to_timestamp(schedule_date) schedule_date=utils.datetime_to_timestamp(schedule_date)
), ),
sleep_threshold=60 sleep_threshold=60

View File

@ -21,7 +21,7 @@ from datetime import datetime
from typing import Union, List, Optional from typing import Union, List, Optional
import pyrogram import pyrogram
from pyrogram import types, enums from pyrogram import types, enums, utils
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -36,6 +36,7 @@ class CopyMessage:
parse_mode: Optional["enums.ParseMode"] = None, parse_mode: Optional["enums.ParseMode"] = None,
caption_entities: List["types.MessageEntity"] = None, caption_entities: List["types.MessageEntity"] = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -83,6 +84,10 @@ class CopyMessage:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -114,6 +119,7 @@ class CopyMessage:
parse_mode=parse_mode, parse_mode=parse_mode,
caption_entities=caption_entities, caption_entities=caption_entities,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
schedule_date=schedule_date, schedule_date=schedule_date,
protect_content=protect_content, protect_content=protect_content,

View File

@ -46,6 +46,7 @@ class SendAnimation:
thumb: Union[str, BinaryIO] = None, thumb: Union[str, BinaryIO] = None,
file_name: str = None, file_name: str = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -115,6 +116,10 @@ class SendAnimation:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -230,7 +235,7 @@ class SendAnimation:
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -44,6 +44,7 @@ class SendAudio:
thumb: Union[str, BinaryIO] = None, thumb: Union[str, BinaryIO] = None,
file_name: str = None, file_name: str = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -108,6 +109,10 @@ class SendAudio:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -217,7 +222,7 @@ class SendAudio:
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -34,6 +34,7 @@ class SendCachedMedia:
parse_mode: Optional["enums.ParseMode"] = None, parse_mode: Optional["enums.ParseMode"] = None,
caption_entities: List["types.MessageEntity"] = None, caption_entities: List["types.MessageEntity"] = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -76,6 +77,10 @@ class SendCachedMedia:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -97,13 +102,12 @@ class SendCachedMedia:
await app.send_cached_media("me", file_id) await app.send_cached_media("me", file_id)
""" """
r = await self.invoke( r = await self.invoke(
raw.functions.messages.SendMedia( raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=utils.get_input_media_from_file_id(file_id), media=utils.get_input_media_from_file_id(file_id),
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -33,6 +33,7 @@ class SendContact:
last_name: str = None, last_name: str = None,
vcard: str = None, vcard: str = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -69,6 +70,10 @@ class SendContact:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -101,7 +106,7 @@ class SendContact:
), ),
message="", message="",
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -30,6 +30,7 @@ class SendDice:
chat_id: Union[int, str], chat_id: Union[int, str],
emoji: str = "🎲", emoji: str = "🎲",
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -61,6 +62,10 @@ class SendDice:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -89,13 +94,12 @@ class SendDice:
# Send a basketball # Send a basketball
await app.send_dice(chat_id, "🏀") await app.send_dice(chat_id, "🏀")
""" """
r = await self.invoke( r = await self.invoke(
raw.functions.messages.SendMedia( raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=raw.types.InputMediaDice(emoticon=emoji), media=raw.types.InputMediaDice(emoticon=emoji),
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -42,6 +42,7 @@ class SendDocument:
file_name: str = None, file_name: str = None,
force_document: bool = None, force_document: bool = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -100,6 +101,10 @@ class SendDocument:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -195,7 +200,7 @@ class SendDocument:
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -31,6 +31,7 @@ class SendLocation:
latitude: float, latitude: float,
longitude: float, longitude: float,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -61,6 +62,10 @@ class SendLocation:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message If the message is a reply, ID of the original message
@ -93,7 +98,7 @@ class SendLocation:
), ),
message="", message="",
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -43,6 +43,7 @@ class SendMediaGroup:
"types.InputMediaDocument" "types.InputMediaDocument"
]], ]],
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -64,6 +65,10 @@ class SendMediaGroup:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -395,7 +400,7 @@ class SendMediaGroup:
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
multi_media=multi_media, multi_media=multi_media,
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content noforwards=protect_content
), ),

View File

@ -33,6 +33,7 @@ class SendMessage:
entities: List["types.MessageEntity"] = None, entities: List["types.MessageEntity"] = None,
disable_web_page_preview: bool = None, disable_web_page_preview: bool = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -70,6 +71,10 @@ class SendMessage:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -128,7 +133,7 @@ class SendMessage:
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
no_webpage=disable_web_page_preview or None, no_webpage=disable_web_page_preview or None,
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
reply_markup=await reply_markup.write(self) if reply_markup else None, reply_markup=await reply_markup.write(self) if reply_markup else None,

View File

@ -40,6 +40,7 @@ class SendPhoto:
has_spoiler: bool = None, has_spoiler: bool = None,
ttl_seconds: int = None, ttl_seconds: int = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -91,6 +92,10 @@ class SendPhoto:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -179,7 +184,7 @@ class SendPhoto:
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -42,6 +42,7 @@ class SendPoll:
is_closed: bool = None, is_closed: bool = None,
disable_notification: bool = None, disable_notification: bool = None,
protect_content: bool = None, protect_content: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
reply_markup: Union[ reply_markup: Union[
@ -114,6 +115,10 @@ class SendPoll:
protect_content (``bool``, *optional*): protect_content (``bool``, *optional*):
Protects the contents of the sent message from forwarding and saving. Protects the contents of the sent message from forwarding and saving.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -132,7 +137,6 @@ class SendPoll:
await app.send_poll(chat_id, "Is this a poll question?", ["Yes", "No", "Maybe"]) await app.send_poll(chat_id, "Is this a poll question?", ["Yes", "No", "Maybe"])
""" """
solution, solution_entities = (await utils.parse_text_entities( solution, solution_entities = (await utils.parse_text_entities(
self, explanation, explanation_parse_mode, explanation_entities self, explanation, explanation_parse_mode, explanation_entities
)).values() )).values()
@ -161,7 +165,7 @@ class SendPoll:
), ),
message="", message="",
silent=disable_notification, silent=disable_notification,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -36,6 +36,7 @@ class SendSticker:
chat_id: Union[int, str], chat_id: Union[int, str],
sticker: Union[str, BinaryIO], sticker: Union[str, BinaryIO],
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -69,6 +70,10 @@ class SendSticker:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -154,7 +159,7 @@ class SendSticker:
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -35,6 +35,7 @@ class SendVenue:
foursquare_id: str = "", foursquare_id: str = "",
foursquare_type: str = "", foursquare_type: str = "",
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -78,6 +79,10 @@ class SendVenue:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message If the message is a reply, ID of the original message
@ -117,7 +122,7 @@ class SendVenue:
), ),
message="", message="",
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -47,6 +47,7 @@ class SendVideo:
file_name: str = None, file_name: str = None,
supports_streaming: bool = True, supports_streaming: bool = True,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -121,6 +122,10 @@ class SendVideo:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -236,7 +241,7 @@ class SendVideo:
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -38,6 +38,7 @@ class SendVideoNote:
length: int = 1, length: int = 1,
thumb: Union[str, BinaryIO] = None, thumb: Union[str, BinaryIO] = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -83,6 +84,10 @@ class SendVideoNote:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message If the message is a reply, ID of the original message
@ -178,7 +183,7 @@ class SendVideoNote:
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -40,6 +40,7 @@ class SendVoice:
caption_entities: List["types.MessageEntity"] = None, caption_entities: List["types.MessageEntity"] = None,
duration: int = 0, duration: int = 0,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -86,6 +87,10 @@ class SendVoice:
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message If the message is a reply, ID of the original message
@ -179,7 +184,7 @@ class SendVoice:
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
silent=disable_notification or None, silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id, reply_to=utils.get_reply_to(reply_to_message_id, message_thread_id),
random_id=self.rnd_id(), random_id=self.rnd_id(),
schedule_date=utils.datetime_to_timestamp(schedule_date), schedule_date=utils.datetime_to_timestamp(schedule_date),
noforwards=protect_content, noforwards=protect_content,

View File

@ -17,8 +17,9 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from .input_message_content import InputMessageContent from .input_message_content import InputMessageContent
from .input_reply_to_message import InputReplyToMessage
from .input_text_message_content import InputTextMessageContent from .input_text_message_content import InputTextMessageContent
__all__ = [ __all__ = [
"InputMessageContent", "InputTextMessageContent" "InputMessageContent", "InputReplyToMessage", "InputTextMessageContent"
] ]

View File

@ -0,0 +1,52 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw
from ..object import Object
class InputReplyToMessage(Object):
"""Contains information about a target replied message.
Parameters:
reply_to_message_id (``int``, *optional*):
ID of the original message you want to reply.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
"""
def __init__(
self, *,
reply_to_message_id: int = None,
message_thread_id: int = None
):
super().__init__()
self.reply_to_message_id = reply_to_message_id
self.message_thread_id = message_thread_id
def write(self):
if not any((self.reply_to_message_id, self.message_thread_id)):
return None
return raw.types.InputReplyToMessage(
reply_to_msg_id=self.reply_to_message_id or message_thread_id, # type: ignore[arg-type]
top_msg_id=self.message_thread_id if self.reply_to_message_id else None,
).write()

View File

@ -21,6 +21,13 @@ from .audio import Audio
from .contact import Contact from .contact import Contact
from .dice import Dice from .dice import Dice
from .document import Document from .document import Document
from .forum_topic import ForumTopic
from .forum_topic_created import ForumTopicCreated
from .forum_topic_closed import ForumTopicClosed
from .forum_topic_reopened import ForumTopicReopened
from .forum_topic_edited import ForumTopicEdited
from .general_forum_topic_hidden import GeneralTopicHidden
from .general_forum_topic_unhidden import GeneralTopicUnhidden
from .game import Game from .game import Game
from .location import Location from .location import Location
from .message import Message from .message import Message
@ -41,7 +48,9 @@ from .web_page import WebPage
from .message_reactions import MessageReactions from .message_reactions import MessageReactions
__all__ = [ __all__ = [
"Animation", "Audio", "Contact", "Document", "Game", "Location", "Message", "MessageEntity", "Photo", "Thumbnail", "Animation", "Audio", "Contact", "Document", "ForumTopic", "ForumTopicCreated",
"StrippedThumbnail", "Poll", "PollOption", "Sticker", "Venue", "Video", "VideoNote", "Voice", "WebPage", "Dice", "ForumTopicClosed", "ForumTopicReopened", "ForumTopicEdited", "GeneralTopicHidden",
"Reaction", "WebAppData", "MessageReactions" "GeneralTopicUnhidden", "Game", "Location", "Message", "MessageEntity", "Photo", "Thumbnail",
"StrippedThumbnail", "Poll", "PollOption", "Sticker", "Venue", "Video", "VideoNote", "Voice",
"WebPage", "Dice", "Reaction", "WebAppData", "MessageReactions"
] ]

View File

@ -0,0 +1,150 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw, types
from typing import Union
from ..object import Object
class ForumTopic(Object):
# todo
# notify_settings: `~pyrogram.types.PeerNotifySettings`
# draft: `~pyrogram.types.DraftMessage`
"""A forum topic.
Parameters:
id (``Integer``):
Id of the topic
date (``Integer``):
Date topic created
title (``String``):
Name of the topic
icon_color (``Integer``):
Color of the topic icon in RGB format
top_message (``Integer``):
N/A
read_inbox_max_id (``Integer``):
N/A
read_outbox_max_id (``Integer``):
N/A
unread_count (``Integer``):
N/A
unread_mentions_count (``Integer``):
N/A
unread_reactions_count (``Integer``):
N/A
from_id (:obj:`~pyrogram.types.PeerChannel` | :obj:`~pyrogram.types.PeerUser`):
Topic creator.
my (``Boolean``, *optional*):
N/A
closed (``Boolean``, *optional*):
N/A
pinned (``Boolean``, *optional*):
N/A
short (``Boolean``, *optional*):
N/A
icon_emoji_id (``Integer``, *optional*):
Unique identifier of the custom emoji shown as the topic icon
"""
def __init__(
self,
*,
id: int,
date: int,
title: str,
icon_color: int,
top_message: int,
read_inbox_max_id: int,
read_outbox_max_id: int,
unread_count: int,
unread_mentions_count: int,
unread_reactions_count: int,
from_id: Union["types.PeerChannel", "types.PeerUser"],
# notify_settings: "types.PeerNotifySettings", //todo
my: bool = None,
closed: bool = None,
pinned: bool = None,
short: bool = None,
icon_emoji_id: int = None,
# draft: "types.DraftMessage" = None //todo
):
super().__init__()
self.id = id
self.date = date
self.title = title
self.icon_color = icon_color
self.top_message = top_message
self.read_inbox_max_id = read_inbox_max_id
self.read_outbox_max_id = read_outbox_max_id
self.unread_count = unread_count
self.unread_mentions_count = unread_mentions_count
self.unread_reactions_count = unread_reactions_count
self.from_id = from_id
# self.notify_settings = notify_settings //todo
self.my = my
self.closed = closed
self.pinned = pinned
self.short = short
self.icon_emoji_id = icon_emoji_id
# self.draft = draft //todo
@staticmethod
def _parse(forum_topic: "raw.types.forum_topic") -> "ForumTopic":
from_id = forum_topic.from_id
if isinstance(from_id, raw.types.PeerChannel):
peer = types.PeerChannel._parse(from_id)
if isinstance(from_id, raw.types.PeerUser):
peer = types.PeerUser._parse(from_id)
return ForumTopic(
id=getattr(forum_topic, "id", None),
date=getattr(forum_topic, "date", None),
title=getattr(forum_topic, "title", None),
icon_color=getattr(forum_topic, "icon_color", None),
top_message=getattr(forum_topic, "top_message", None),
read_inbox_max_id=getattr(forum_topic, "read_inbox_max_id", None),
read_outbox_max_id=getattr(forum_topic, "read_outbox_max_id", None),
unread_count=getattr(forum_topic, "unread_count", None),
unread_mentions_count=getattr(forum_topic, "unread_mentions_count", None),
unread_reactions_count=getattr(forum_topic, "unread_reactions_count", None),
from_id=peer,
# notify_settings=None, //todo
my=getattr(forum_topic, "my", None),
closed=getattr(forum_topic, "closed", None),
pinned=getattr(forum_topic, "pinned", None),
short=getattr(forum_topic, "short", None),
icon_emoji_id=getattr(forum_topic, "icon_emoji_id", None),
# draft=None //todo
)

View File

@ -0,0 +1,29 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from ..object import Object
class ForumTopicClosed(Object):
"""A service message about a forum topic closed in the chat.
Currently holds no information.
"""
def __init__(self):
super().__init__()

View File

@ -0,0 +1,62 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw
from ..object import Object
class ForumTopicCreated(Object):
"""A service message about a new forum topic created in the chat.
Parameters:
id (``Integer``):
Id of the topic
title (``String``):
Name of the topic.
icon_color (``Integer``):
Color of the topic icon in RGB format
icon_emoji_id (``Integer``, *optional*):
Unique identifier of the custom emoji shown as the topic icon
"""
def __init__(
self, *,
id: int,
title: str,
icon_color: int,
icon_emoji_id: int = None
):
super().__init__()
self.id = id
self.title = title
self.icon_color = icon_color
self.icon_emoji_id = icon_emoji_id
@staticmethod
def _parse(message: "raw.base.Message") -> "ForumTopicCreated":
return ForumTopicCreated(
id=getattr(message, "id", None),
title=getattr(message.action, "title", None),
icon_color=getattr(message.action, "icon_color", None),
icon_emoji_id=getattr(message.action, "icon_emoji_id", None)
)

View File

@ -0,0 +1,56 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw
from ..object import Object
class ForumTopicEdited(Object):
"""A service message about a forum topic renamed in the chat.
Parameters:
title (``String``):
Name of the topic.
icon_color (``Integer``):
Color of the topic icon in RGB format
icon_custom_emoji_id (``String``, *optional*):
Unique identifier of the custom emoji shown as the topic icon
"""
def __init__(
self, *,
title: str = None,
icon_color: int = None,
icon_emoji_id: str = None
):
super().__init__()
self.title = title
self.icon_color = icon_color
self.icon_emoji_id = icon_emoji_id
@staticmethod
def _parse(action: "raw.types.MessageActionTopicEdit") -> "ForumTopicEdited":
return ForumTopicEdited(
title=getattr(action, "title", None),
icon_color=getattr(action, "icon_color", None),
icon_emoji_id=getattr(action, "icon_emoji_id", None)
)

View File

@ -0,0 +1,29 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from ..object import Object
class ForumTopicReopened(Object):
"""A service message about a forum topic reopened in the chat.
Currently holds no information.
"""
def __init__(self):
super().__init__()

View File

@ -0,0 +1,29 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from ..object import Object
class GeneralTopicHidden(Object):
"""A service message about a general topic hidden in the chat.
Currently holds no information.
"""
def __init__(self):
super().__init__()

View File

@ -0,0 +1,29 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from ..object import Object
class GeneralTopicUnhidden(Object):
"""A service message about a general topic unhidden in the chat.
Currently holds no information.
"""
def __init__(self):
super().__init__()

View File

@ -78,6 +78,9 @@ class Message(Object, Update):
chat (:obj:`~pyrogram.types.Chat`, *optional*): chat (:obj:`~pyrogram.types.Chat`, *optional*):
Conversation the message belongs to. Conversation the message belongs to.
topics (:obj:`~pyrogram.types.ForumTopic`, *optional*):
Topic the message belongs to.
forward_from (:obj:`~pyrogram.types.User`, *optional*): forward_from (:obj:`~pyrogram.types.User`, *optional*):
For forwarded messages, sender of the original message. For forwarded messages, sender of the original message.
@ -96,6 +99,13 @@ class Message(Object, Update):
forward_date (:py:obj:`~datetime.datetime`, *optional*): forward_date (:py:obj:`~datetime.datetime`, *optional*):
For forwarded messages, date the original message was sent. For forwarded messages, date the original message was sent.
is_topic_message (``bool``, *optional*):
True, if the message is sent to a forum topic
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs.
for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
The id of the message which this message directly replied to. The id of the message which this message directly replied to.
@ -279,6 +289,24 @@ class Message(Object, Update):
E.g.: "/start 1 2 3" would produce ["start", "1", "2", "3"]. E.g.: "/start 1 2 3" would produce ["start", "1", "2", "3"].
Only applicable when using :obj:`~pyrogram.filters.command`. Only applicable when using :obj:`~pyrogram.filters.command`.
forum_topic_created (:obj:`~pyrogram.types.ForumTopicCreated`, *optional*):
Service message: forum topic created
forum_topic_closed (:obj:`~pyrogram.types.ForumTopicClosed`, *optional*):
Service message: forum topic closed
forum_topic_reopened (:obj:`~pyrogram.types.ForumTopicReopened`, *optional*):
Service message: forum topic reopened
forum_topic_edited (:obj:`~pyrogram.types.ForumTopicEdited`, *optional*):
Service message: forum topic edited
general_topic_hidden (:obj:`~pyrogram.types.GeneralTopicHidden`, *optional*):
Service message: forum general topic hidden
general_topic_unhidden (:obj:`~pyrogram.types.GeneralTopicUnhidden`, *optional*):
Service message: forum general topic unhidden
video_chat_scheduled (:obj:`~pyrogram.types.VideoChatScheduled`, *optional*): video_chat_scheduled (:obj:`~pyrogram.types.VideoChatScheduled`, *optional*):
Service message: voice chat scheduled. Service message: voice chat scheduled.
@ -316,12 +344,15 @@ class Message(Object, Update):
sender_chat: "types.Chat" = None, sender_chat: "types.Chat" = None,
date: datetime = None, date: datetime = None,
chat: "types.Chat" = None, chat: "types.Chat" = None,
topics: "types.ForumTopic" = None,
forward_from: "types.User" = None, forward_from: "types.User" = None,
forward_sender_name: str = None, forward_sender_name: str = None,
forward_from_chat: "types.Chat" = None, forward_from_chat: "types.Chat" = None,
forward_from_message_id: int = None, forward_from_message_id: int = None,
forward_signature: str = None, forward_signature: str = None,
forward_date: datetime = None, forward_date: datetime = None,
is_topic_message: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_to_top_message_id: int = None, reply_to_top_message_id: int = None,
reply_to_message: "Message" = None, reply_to_message: "Message" = None,
@ -373,6 +404,12 @@ class Message(Object, Update):
outgoing: bool = None, outgoing: bool = None,
matches: List[Match] = None, matches: List[Match] = None,
command: List[str] = None, command: List[str] = None,
forum_topic_created: "types.ForumTopicCreated" = None,
forum_topic_closed: "types.ForumTopicClosed" = None,
forum_topic_reopened: "types.ForumTopicReopened" = None,
forum_topic_edited: "types.ForumTopicEdited" = None,
general_topic_hidden: "types.GeneralTopicHidden" = None,
general_topic_unhidden: "types.GeneralTopicUnhidden" = None,
video_chat_scheduled: "types.VideoChatScheduled" = None, video_chat_scheduled: "types.VideoChatScheduled" = None,
video_chat_started: "types.VideoChatStarted" = None, video_chat_started: "types.VideoChatStarted" = None,
video_chat_ended: "types.VideoChatEnded" = None, video_chat_ended: "types.VideoChatEnded" = None,
@ -393,12 +430,15 @@ class Message(Object, Update):
self.sender_chat = sender_chat self.sender_chat = sender_chat
self.date = date self.date = date
self.chat = chat self.chat = chat
self.topics = topics
self.forward_from = forward_from self.forward_from = forward_from
self.forward_sender_name = forward_sender_name self.forward_sender_name = forward_sender_name
self.forward_from_chat = forward_from_chat self.forward_from_chat = forward_from_chat
self.forward_from_message_id = forward_from_message_id self.forward_from_message_id = forward_from_message_id
self.forward_signature = forward_signature self.forward_signature = forward_signature
self.forward_date = forward_date self.forward_date = forward_date
self.is_topic_message = is_topic_message
self.message_thread_id = message_thread_id
self.reply_to_message_id = reply_to_message_id self.reply_to_message_id = reply_to_message_id
self.reply_to_top_message_id = reply_to_top_message_id self.reply_to_top_message_id = reply_to_top_message_id
self.reply_to_message = reply_to_message self.reply_to_message = reply_to_message
@ -451,6 +491,12 @@ class Message(Object, Update):
self.matches = matches self.matches = matches
self.command = command self.command = command
self.reply_markup = reply_markup self.reply_markup = reply_markup
self.forum_topic_created = forum_topic_created
self.forum_topic_closed = forum_topic_closed
self.forum_topic_reopened = forum_topic_reopened
self.forum_topic_edited = forum_topic_edited
self.general_topic_hidden = general_topic_hidden
self.general_topic_unhidden = general_topic_unhidden
self.video_chat_scheduled = video_chat_scheduled self.video_chat_scheduled = video_chat_scheduled
self.video_chat_started = video_chat_started self.video_chat_started = video_chat_started
self.video_chat_ended = video_chat_ended self.video_chat_ended = video_chat_ended
@ -464,6 +510,7 @@ class Message(Object, Update):
message: raw.base.Message, message: raw.base.Message,
users: dict, users: dict,
chats: dict, chats: dict,
topics: dict = None,
is_scheduled: bool = False, is_scheduled: bool = False,
replies: int = 1 replies: int = 1
): ):
@ -491,6 +538,7 @@ class Message(Object, Update):
users.update({i.id: i for i in r}) users.update({i.id: i for i in r})
if isinstance(message, raw.types.MessageService): if isinstance(message, raw.types.MessageService):
message_thread_id = None
action = message.action action = message.action
new_chat_members = None new_chat_members = None
@ -502,6 +550,13 @@ class Message(Object, Update):
group_chat_created = None group_chat_created = None
channel_chat_created = None channel_chat_created = None
new_chat_photo = None new_chat_photo = None
is_topic_message = None
forum_topic_created = None
forum_topic_closed = None
forum_topic_reopened = None
forum_topic_edited = None
general_topic_hidden = None
general_topic_unhidden = None
video_chat_scheduled = None video_chat_scheduled = None
video_chat_started = None video_chat_started = None
video_chat_ended = None video_chat_ended = None
@ -540,6 +595,26 @@ class Message(Object, Update):
elif isinstance(action, raw.types.MessageActionChatEditPhoto): elif isinstance(action, raw.types.MessageActionChatEditPhoto):
new_chat_photo = types.Photo._parse(client, action.photo) new_chat_photo = types.Photo._parse(client, action.photo)
service_type = enums.MessageServiceType.NEW_CHAT_PHOTO service_type = enums.MessageServiceType.NEW_CHAT_PHOTO
elif isinstance(action, raw.types.MessageActionTopicCreate):
forum_topic_created = types.ForumTopicCreated._parse(message)
service_type = enums.MessageServiceType.FORUM_TOPIC_CREATED
elif isinstance(action, raw.types.MessageActionTopicEdit):
if action.title:
forum_topic_edited = types.ForumTopicEdited._parse(action)
service_type = enums.MessageServiceType.FORUM_TOPIC_EDITED
elif action.hidden:
general_topic_hidden = types.GeneralTopicHidden()
service_type = enums.MessageServiceType.GENERAL_TOPIC_HIDDEN
elif action.closed:
forum_topic_closed = types.ForumTopicClosed()
service_type = enums.MessageServiceType.FORUM_TOPIC_CLOSED
else:
if hasattr(action, "hidden"):
general_topic_unhidden = types.GeneralTopicUnhidden()
service_type = enums.MessageServiceType.GENERAL_TOPIC_UNHIDDEN
else:
forum_topic_reopened = types.ForumTopicReopened()
service_type = enums.MessageServiceType.FORUM_TOPIC_REOPENED
elif isinstance(action, raw.types.MessageActionGroupCallScheduled): elif isinstance(action, raw.types.MessageActionGroupCallScheduled):
video_chat_scheduled = types.VideoChatScheduled._parse(action) video_chat_scheduled = types.VideoChatScheduled._parse(action)
service_type = enums.MessageServiceType.VIDEO_CHAT_SCHEDULED service_type = enums.MessageServiceType.VIDEO_CHAT_SCHEDULED
@ -562,8 +637,10 @@ class Message(Object, Update):
parsed_message = Message( parsed_message = Message(
id=message.id, id=message.id,
message_thread_id=message_thread_id,
date=utils.timestamp_to_datetime(message.date), date=utils.timestamp_to_datetime(message.date),
chat=types.Chat._parse(client, message, users, chats, is_chat=True), chat=types.Chat._parse(client, message, users, chats, is_chat=True),
topics=None,
from_user=from_user, from_user=from_user,
sender_chat=sender_chat, sender_chat=sender_chat,
service=service_type, service=service_type,
@ -576,6 +653,13 @@ class Message(Object, Update):
migrate_from_chat_id=-migrate_from_chat_id if migrate_from_chat_id else None, migrate_from_chat_id=-migrate_from_chat_id if migrate_from_chat_id else None,
group_chat_created=group_chat_created, group_chat_created=group_chat_created,
channel_chat_created=channel_chat_created, channel_chat_created=channel_chat_created,
is_topic_message=is_topic_message,
forum_topic_created=forum_topic_created,
forum_topic_closed=forum_topic_closed,
forum_topic_reopened=forum_topic_reopened,
forum_topic_edited=forum_topic_edited,
general_topic_hidden=general_topic_hidden,
general_topic_unhidden=general_topic_unhidden,
video_chat_scheduled=video_chat_scheduled, video_chat_scheduled=video_chat_scheduled,
video_chat_started=video_chat_started, video_chat_started=video_chat_started,
video_chat_ended=video_chat_ended, video_chat_ended=video_chat_ended,
@ -614,9 +698,18 @@ class Message(Object, Update):
client.message_cache[(parsed_message.chat.id, parsed_message.id)] = parsed_message client.message_cache[(parsed_message.chat.id, parsed_message.id)] = parsed_message
if message.reply_to:
if message.reply_to.forum_topic:
if message.reply_to.reply_to_top_id:
parsed_message.message_thread_id = message.reply_to.reply_to_top_id
else:
parsed_message.message_thread_id = message.reply_to.reply_to_msg_id
parsed_message.is_topic_message = True
return parsed_message return parsed_message
if isinstance(message, raw.types.Message): if isinstance(message, raw.types.Message):
message_thread_id = None
entities = [types.MessageEntity._parse(client, entity, users) for entity in message.entities] entities = [types.MessageEntity._parse(client, entity, users) for entity in message.entities]
entities = types.List(filter(lambda x: x is not None, entities)) entities = types.List(filter(lambda x: x is not None, entities))
@ -626,6 +719,7 @@ class Message(Object, Update):
forward_from_message_id = None forward_from_message_id = None
forward_signature = None forward_signature = None
forward_date = None forward_date = None
is_topic_message = None
forward_header = message.fwd_from # type: raw.types.MessageFwdHeader forward_header = message.fwd_from # type: raw.types.MessageFwdHeader
@ -760,8 +854,10 @@ class Message(Object, Update):
parsed_message = Message( parsed_message = Message(
id=message.id, id=message.id,
message_thread_id=message_thread_id,
date=utils.timestamp_to_datetime(message.date), date=utils.timestamp_to_datetime(message.date),
chat=types.Chat._parse(client, message, users, chats, is_chat=True), chat=types.Chat._parse(client, message, users, chats, is_chat=True),
topics=None,
from_user=from_user, from_user=from_user,
sender_chat=sender_chat, sender_chat=sender_chat,
text=( text=(
@ -793,6 +889,7 @@ class Message(Object, Update):
forward_from_message_id=forward_from_message_id, forward_from_message_id=forward_from_message_id,
forward_signature=forward_signature, forward_signature=forward_signature,
forward_date=forward_date, forward_date=forward_date,
is_topic_message=is_topic_message,
mentioned=message.mentioned, mentioned=message.mentioned,
scheduled=is_scheduled, scheduled=is_scheduled,
from_scheduled=message.from_scheduled, from_scheduled=message.from_scheduled,
@ -824,6 +921,24 @@ class Message(Object, Update):
) )
if message.reply_to: if message.reply_to:
if message.reply_to.forum_topic:
if message.reply_to.reply_to_top_id:
thread_id = message.reply_to.reply_to_top_id
parsed_message.reply_to_message_id = message.reply_to.reply_to_msg_id
else:
thread_id = message.reply_to.reply_to_msg_id
parsed_message.message_thread_id = thread_id
parsed_message.is_topic_message = True
if topics:
parsed_message.topics = types.ForumTopic._parse(topics[thread_id])
else:
try:
msg = await client.get_messages(parsed_message.chat.id,message.id)
if getattr(msg, "topics"):
parsed_message.topics = msg.topics
except Exception:
pass
else:
parsed_message.reply_to_message_id = message.reply_to.reply_to_msg_id parsed_message.reply_to_message_id = message.reply_to.reply_to_msg_id
parsed_message.reply_to_top_message_id = message.reply_to.reply_to_top_id parsed_message.reply_to_top_message_id = message.reply_to.reply_to_top_id
@ -838,7 +953,7 @@ class Message(Object, Update):
reply_to_message_ids=message.id, reply_to_message_ids=message.id,
replies=replies - 1 replies=replies - 1
) )
if reply_to_message and not reply_to_message.forum_topic_created:
parsed_message.reply_to_message = reply_to_message parsed_message.reply_to_message = reply_to_message
except MessageIdsEmpty: except MessageIdsEmpty:
pass pass
@ -895,6 +1010,7 @@ class Message(Object, Update):
entities: List["types.MessageEntity"] = None, entities: List["types.MessageEntity"] = None,
disable_web_page_preview: bool = None, disable_web_page_preview: bool = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -942,6 +1058,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -974,6 +1093,7 @@ class Message(Object, Update):
entities=entities, entities=entities,
disable_web_page_preview=disable_web_page_preview, disable_web_page_preview=disable_web_page_preview,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
schedule_date=schedule_date, schedule_date=schedule_date,
protect_content=protect_content, protect_content=protect_content,
@ -1001,6 +1121,7 @@ class Message(Object, Update):
"types.ReplyKeyboardRemove", "types.ReplyKeyboardRemove",
"types.ForceReply" "types.ForceReply"
] = None, ] = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
progress: Callable = None, progress: Callable = None,
progress_args: tuple = () progress_args: tuple = ()
@ -1065,6 +1186,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -1120,6 +1244,7 @@ class Message(Object, Update):
height=height, height=height,
thumb=thumb, thumb=thumb,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup, reply_markup=reply_markup,
progress=progress, progress=progress,
@ -1138,6 +1263,7 @@ class Message(Object, Update):
title: str = None, title: str = None,
thumb: str = None, thumb: str = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_markup: Union[ reply_markup: Union[
"types.InlineKeyboardMarkup", "types.InlineKeyboardMarkup",
@ -1205,6 +1331,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -1259,6 +1388,7 @@ class Message(Object, Update):
title=title, title=title,
thumb=thumb, thumb=thumb,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup, reply_markup=reply_markup,
progress=progress, progress=progress,
@ -1273,6 +1403,7 @@ class Message(Object, Update):
parse_mode: Optional["enums.ParseMode"] = None, parse_mode: Optional["enums.ParseMode"] = None,
caption_entities: List["types.MessageEntity"] = None, caption_entities: List["types.MessageEntity"] = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_markup: Union[ reply_markup: Union[
"types.InlineKeyboardMarkup", "types.InlineKeyboardMarkup",
@ -1321,6 +1452,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -1347,6 +1481,7 @@ class Message(Object, Update):
parse_mode=parse_mode, parse_mode=parse_mode,
caption_entities=caption_entities, caption_entities=caption_entities,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup reply_markup=reply_markup
) )
@ -1396,6 +1531,7 @@ class Message(Object, Update):
last_name: str = "", last_name: str = "",
vcard: str = "", vcard: str = "",
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_markup: Union[ reply_markup: Union[
"types.InlineKeyboardMarkup", "types.InlineKeyboardMarkup",
@ -1443,6 +1579,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -1469,6 +1608,7 @@ class Message(Object, Update):
last_name=last_name, last_name=last_name,
vcard=vcard, vcard=vcard,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup reply_markup=reply_markup
) )
@ -1484,6 +1624,7 @@ class Message(Object, Update):
file_name: str = None, file_name: str = None,
force_document: bool = None, force_document: bool = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
reply_markup: Union[ reply_markup: Union[
@ -1552,6 +1693,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -1608,6 +1752,7 @@ class Message(Object, Update):
file_name=file_name, file_name=file_name,
force_document=force_document, force_document=force_document,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
schedule_date=schedule_date, schedule_date=schedule_date,
reply_markup=reply_markup, reply_markup=reply_markup,
@ -1620,6 +1765,7 @@ class Message(Object, Update):
game_short_name: str, game_short_name: str,
quote: bool = None, quote: bool = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_markup: Union[ reply_markup: Union[
"types.InlineKeyboardMarkup", "types.InlineKeyboardMarkup",
@ -1657,6 +1803,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -1680,6 +1829,7 @@ class Message(Object, Update):
chat_id=self.chat.id, chat_id=self.chat.id,
game_short_name=game_short_name, game_short_name=game_short_name,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup reply_markup=reply_markup
) )
@ -1690,6 +1840,7 @@ class Message(Object, Update):
result_id: str, result_id: str,
quote: bool = None, quote: bool = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: bool = None,
reply_to_message_id: int = None reply_to_message_id: int = None
) -> "Message": ) -> "Message":
"""Bound method *reply_inline_bot_result* of :obj:`~pyrogram.types.Message`. """Bound method *reply_inline_bot_result* of :obj:`~pyrogram.types.Message`.
@ -1725,6 +1876,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``bool``, *optional*): reply_to_message_id (``bool``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -1745,6 +1899,7 @@ class Message(Object, Update):
query_id=query_id, query_id=query_id,
result_id=result_id, result_id=result_id,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id reply_to_message_id=reply_to_message_id
) )
@ -1754,6 +1909,7 @@ class Message(Object, Update):
longitude: float, longitude: float,
quote: bool = None, quote: bool = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_markup: Union[ reply_markup: Union[
"types.InlineKeyboardMarkup", "types.InlineKeyboardMarkup",
@ -1795,6 +1951,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message If the message is a reply, ID of the original message
@ -1819,6 +1978,7 @@ class Message(Object, Update):
latitude=latitude, latitude=latitude,
longitude=longitude, longitude=longitude,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup reply_markup=reply_markup
) )
@ -1828,6 +1988,7 @@ class Message(Object, Update):
media: List[Union["types.InputMediaPhoto", "types.InputMediaVideo"]], media: List[Union["types.InputMediaPhoto", "types.InputMediaVideo"]],
quote: bool = None, quote: bool = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None reply_to_message_id: int = None
) -> List["types.Message"]: ) -> List["types.Message"]:
"""Bound method *reply_media_group* of :obj:`~pyrogram.types.Message`. """Bound method *reply_media_group* of :obj:`~pyrogram.types.Message`.
@ -1861,6 +2022,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -1881,6 +2045,7 @@ class Message(Object, Update):
chat_id=self.chat.id, chat_id=self.chat.id,
media=media, media=media,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id reply_to_message_id=reply_to_message_id
) )
@ -1894,6 +2059,7 @@ class Message(Object, Update):
has_spoiler: bool = None, has_spoiler: bool = None,
ttl_seconds: int = None, ttl_seconds: int = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_markup: Union[ reply_markup: Union[
"types.InlineKeyboardMarkup", "types.InlineKeyboardMarkup",
@ -1954,6 +2120,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -2006,6 +2175,7 @@ class Message(Object, Update):
has_spoiler=has_spoiler, has_spoiler=has_spoiler,
ttl_seconds=ttl_seconds, ttl_seconds=ttl_seconds,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup, reply_markup=reply_markup,
progress=progress, progress=progress,
@ -2029,6 +2199,7 @@ class Message(Object, Update):
quote: bool = None, quote: bool = None,
disable_notification: bool = None, disable_notification: bool = None,
protect_content: bool = None, protect_content: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
reply_markup: Union[ reply_markup: Union[
@ -2114,6 +2285,9 @@ class Message(Object, Update):
protect_content (``bool``, *optional*): protect_content (``bool``, *optional*):
Protects the contents of the sent message from forwarding and saving. Protects the contents of the sent message from forwarding and saving.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -2152,6 +2326,7 @@ class Message(Object, Update):
is_closed=is_closed, is_closed=is_closed,
disable_notification=disable_notification, disable_notification=disable_notification,
protect_content=protect_content, protect_content=protect_content,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
schedule_date=schedule_date, schedule_date=schedule_date,
reply_markup=reply_markup reply_markup=reply_markup
@ -2162,6 +2337,7 @@ class Message(Object, Update):
sticker: Union[str, BinaryIO], sticker: Union[str, BinaryIO],
quote: bool = None, quote: bool = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_markup: Union[ reply_markup: Union[
"types.InlineKeyboardMarkup", "types.InlineKeyboardMarkup",
@ -2204,6 +2380,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -2251,6 +2430,7 @@ class Message(Object, Update):
chat_id=self.chat.id, chat_id=self.chat.id,
sticker=sticker, sticker=sticker,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup, reply_markup=reply_markup,
progress=progress, progress=progress,
@ -2267,6 +2447,7 @@ class Message(Object, Update):
foursquare_id: str = "", foursquare_id: str = "",
foursquare_type: str = "", foursquare_type: str = "",
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_markup: Union[ reply_markup: Union[
"types.InlineKeyboardMarkup", "types.InlineKeyboardMarkup",
@ -2323,6 +2504,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message If the message is a reply, ID of the original message
@ -2351,6 +2535,7 @@ class Message(Object, Update):
foursquare_id=foursquare_id, foursquare_id=foursquare_id,
foursquare_type=foursquare_type, foursquare_type=foursquare_type,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup reply_markup=reply_markup
) )
@ -2370,6 +2555,7 @@ class Message(Object, Update):
thumb: str = None, thumb: str = None,
supports_streaming: bool = True, supports_streaming: bool = True,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_markup: Union[ reply_markup: Union[
"types.InlineKeyboardMarkup", "types.InlineKeyboardMarkup",
@ -2448,6 +2634,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -2505,6 +2694,7 @@ class Message(Object, Update):
thumb=thumb, thumb=thumb,
supports_streaming=supports_streaming, supports_streaming=supports_streaming,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup, reply_markup=reply_markup,
progress=progress, progress=progress,
@ -2519,6 +2709,7 @@ class Message(Object, Update):
length: int = 1, length: int = 1,
thumb: str = None, thumb: str = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_markup: Union[ reply_markup: Union[
"types.InlineKeyboardMarkup", "types.InlineKeyboardMarkup",
@ -2573,6 +2764,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message If the message is a reply, ID of the original message
@ -2623,6 +2817,7 @@ class Message(Object, Update):
length=length, length=length,
thumb=thumb, thumb=thumb,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup, reply_markup=reply_markup,
progress=progress, progress=progress,
@ -2638,6 +2833,7 @@ class Message(Object, Update):
caption_entities: List["types.MessageEntity"] = None, caption_entities: List["types.MessageEntity"] = None,
duration: int = 0, duration: int = 0,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
reply_markup: Union[ reply_markup: Union[
"types.InlineKeyboardMarkup", "types.InlineKeyboardMarkup",
@ -2693,6 +2889,9 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message If the message is a reply, ID of the original message
@ -2744,6 +2943,7 @@ class Message(Object, Update):
caption_entities=caption_entities, caption_entities=caption_entities,
duration=duration, duration=duration,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup, reply_markup=reply_markup,
progress=progress, progress=progress,
@ -2945,6 +3145,7 @@ class Message(Object, Update):
async def forward( async def forward(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
message_thread_id: int = None,
disable_notification: bool = None, disable_notification: bool = None,
schedule_date: datetime = None schedule_date: datetime = None
) -> Union["types.Message", List["types.Message"]]: ) -> Union["types.Message", List["types.Message"]]:
@ -2971,6 +3172,9 @@ class Message(Object, Update):
For your personal cloud (Saved Messages) you can simply use "me" or "self". For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str). For a contact that exists in your Telegram address book you can use his phone number (str).
message_thread_id (``int``, *optional*):
Unique identifier of a message thread to which the message belongs; for supergroups only
disable_notification (``bool``, *optional*): disable_notification (``bool``, *optional*):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
@ -2988,6 +3192,7 @@ class Message(Object, Update):
chat_id=chat_id, chat_id=chat_id,
from_chat_id=self.chat.id, from_chat_id=self.chat.id,
message_ids=self.id, message_ids=self.id,
message_thread_id=message_thread_id,
disable_notification=disable_notification, disable_notification=disable_notification,
schedule_date=schedule_date schedule_date=schedule_date
) )
@ -2999,6 +3204,7 @@ class Message(Object, Update):
parse_mode: Optional["enums.ParseMode"] = None, parse_mode: Optional["enums.ParseMode"] = None,
caption_entities: List["types.MessageEntity"] = None, caption_entities: List["types.MessageEntity"] = None,
disable_notification: bool = None, disable_notification: bool = None,
message_thread_id: int = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: datetime = None, schedule_date: datetime = None,
protect_content: bool = None, protect_content: bool = None,
@ -3048,6 +3254,10 @@ class Message(Object, Update):
Sends the message silently. Sends the message silently.
Users will receive a notification with no sound. Users will receive a notification with no sound.
message_thread_id (``int``, *optional*):
Unique identifier for the target message thread (topic) of the forum.
for forum supergroups only.
reply_to_message_id (``int``, *optional*): reply_to_message_id (``int``, *optional*):
If the message is a reply, ID of the original message. If the message is a reply, ID of the original message.
@ -3085,6 +3295,7 @@ class Message(Object, Update):
parse_mode=enums.ParseMode.DISABLED, parse_mode=enums.ParseMode.DISABLED,
disable_web_page_preview=not self.web_page, disable_web_page_preview=not self.web_page,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
schedule_date=schedule_date, schedule_date=schedule_date,
protect_content=protect_content, protect_content=protect_content,
@ -3095,6 +3306,7 @@ class Message(Object, Update):
self._client.send_cached_media, self._client.send_cached_media,
chat_id=chat_id, chat_id=chat_id,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
reply_to_message_id=reply_to_message_id, reply_to_message_id=reply_to_message_id,
schedule_date=schedule_date, schedule_date=schedule_date,
protect_content=protect_content, protect_content=protect_content,
@ -3125,6 +3337,7 @@ class Message(Object, Update):
last_name=self.contact.last_name, last_name=self.contact.last_name,
vcard=self.contact.vcard, vcard=self.contact.vcard,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
schedule_date=schedule_date schedule_date=schedule_date
) )
elif self.location: elif self.location:
@ -3133,6 +3346,7 @@ class Message(Object, Update):
latitude=self.location.latitude, latitude=self.location.latitude,
longitude=self.location.longitude, longitude=self.location.longitude,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
schedule_date=schedule_date schedule_date=schedule_date
) )
elif self.venue: elif self.venue:
@ -3145,6 +3359,7 @@ class Message(Object, Update):
foursquare_id=self.venue.foursquare_id, foursquare_id=self.venue.foursquare_id,
foursquare_type=self.venue.foursquare_type, foursquare_type=self.venue.foursquare_type,
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
schedule_date=schedule_date schedule_date=schedule_date
) )
elif self.poll: elif self.poll:
@ -3153,19 +3368,24 @@ class Message(Object, Update):
question=self.poll.question, question=self.poll.question,
options=[opt.text for opt in self.poll.options], options=[opt.text for opt in self.poll.options],
disable_notification=disable_notification, disable_notification=disable_notification,
message_thread_id=message_thread_id,
schedule_date=schedule_date schedule_date=schedule_date
) )
elif self.game: elif self.game:
return await self._client.send_game( return await self._client.send_game(
chat_id, chat_id,
game_short_name=self.game.short_name, game_short_name=self.game.short_name,
disable_notification=disable_notification disable_notification=disable_notification,
message_thread_id=message_thread_id
) )
else: else:
raise ValueError("Unknown media type") raise ValueError("Unknown media type")
if self.sticker or self.video_note: # Sticker and VideoNote should have no caption if self.sticker or self.video_note: # Sticker and VideoNote should have no caption
return await send_media(file_id=file_id) return await send_media(
file_id=file_id,
message_thread_id=message_thread_id
)
else: else:
if caption is None: if caption is None:
caption = self.caption or "" caption = self.caption or ""
@ -3175,7 +3395,8 @@ class Message(Object, Update):
file_id=file_id, file_id=file_id,
caption=caption, caption=caption,
parse_mode=parse_mode, parse_mode=parse_mode,
caption_entities=caption_entities caption_entities=caption_entities,
message_thread_id=message_thread_id
) )
else: else:
raise ValueError("Can't copy this message") raise ValueError("Can't copy this message")

View File

@ -34,6 +34,8 @@ from .dialog import Dialog
from .emoji_status import EmojiStatus from .emoji_status import EmojiStatus
from .invite_link_importer import InviteLinkImporter from .invite_link_importer import InviteLinkImporter
from .restriction import Restriction from .restriction import Restriction
from .peer_channel import PeerChannel
from .peer_user import PeerUser
from .user import User from .user import User
from .username import Username from .username import Username
from .video_chat_ended import VideoChatEnded from .video_chat_ended import VideoChatEnded
@ -48,6 +50,8 @@ __all__ = [
"ChatPhoto", "ChatPhoto",
"ChatPreview", "ChatPreview",
"Dialog", "Dialog",
"PeerChannel",
"PeerUser",
"User", "User",
"Username", "Username",
"Restriction", "Restriction",

View File

@ -36,6 +36,9 @@ class Chat(Object):
type (:obj:`~pyrogram.enums.ChatType`): type (:obj:`~pyrogram.enums.ChatType`):
Type of chat. Type of chat.
is_forum (``bool``, *optional*):
True, if the supergroup chat is a forum
is_verified (``bool``, *optional*): is_verified (``bool``, *optional*):
True, if this chat has been verified by Telegram. Supergroups, channels and bots only. True, if this chat has been verified by Telegram. Supergroups, channels and bots only.
@ -146,6 +149,7 @@ class Chat(Object):
client: "pyrogram.Client" = None, client: "pyrogram.Client" = None,
id: int, id: int,
type: "enums.ChatType", type: "enums.ChatType",
is_forum: bool = None,
is_verified: bool = None, is_verified: bool = None,
is_participants_hidden: bool = None, is_participants_hidden: bool = None,
is_restricted: bool = None, is_restricted: bool = None,
@ -179,6 +183,7 @@ class Chat(Object):
self.id = id self.id = id
self.type = type self.type = type
self.is_forum = is_forum
self.is_verified = is_verified self.is_verified = is_verified
self.is_participants_hidden = is_participants_hidden self.is_participants_hidden = is_participants_hidden
self.is_restricted = is_restricted self.is_restricted = is_restricted
@ -258,6 +263,7 @@ class Chat(Object):
return Chat( return Chat(
id=peer_id, id=peer_id,
type=enums.ChatType.SUPERGROUP if getattr(channel, "megagroup", None) else enums.ChatType.CHANNEL, type=enums.ChatType.SUPERGROUP if getattr(channel, "megagroup", None) else enums.ChatType.CHANNEL,
is_forum=getattr(channel, "forum", None),
is_verified=getattr(channel, "verified", None), is_verified=getattr(channel, "verified", None),
is_restricted=getattr(channel, "restricted", None), is_restricted=getattr(channel, "restricted", None),
is_creator=getattr(channel, "creator", None), is_creator=getattr(channel, "creator", None),

View File

@ -130,6 +130,18 @@ class ChatEvent(Object):
deleted_invite_link (:obj:`~pyrogram.types.ChatInviteLink`, *optional*): deleted_invite_link (:obj:`~pyrogram.types.ChatInviteLink`, *optional*):
Deleted invite link. Deleted invite link.
For :obj:`~pyrogram.enums.ChatEventAction.INVITE_LINK_DELETED` action only. For :obj:`~pyrogram.enums.ChatEventAction.INVITE_LINK_DELETED` action only.
created_forum_topic (:obj:`~pyrogram.types.ForumTopic`, *optional*):
New forum topic.
For :obj:`~pyrogram.enums.ChatEvenAction.CREATED_FORUM_TOPIC` action only.
old_forum_topic, new_forum_topic (:obj:`~pyrogram.types.ForumTopic`, *optional*):
Edited forum topic.
For :obj:`~pyrogram.enums.ChatEvenAction.EDITED_FORUM_TOPIC` action only.
deleted_forum_topic (:obj:`~pyrogram.types.ForumTopic`, *optional*):
Deleted forum topic.
For :obj:`~pyrogram.enums.ChatEvenAction.DELETED_FORUM_TOPIC` action only.
""" """
def __init__( def __init__(
@ -190,7 +202,12 @@ class ChatEvent(Object):
old_invite_link: "types.ChatInviteLink" = None, old_invite_link: "types.ChatInviteLink" = None,
new_invite_link: "types.ChatInviteLink" = None, new_invite_link: "types.ChatInviteLink" = None,
revoked_invite_link: "types.ChatInviteLink" = None, revoked_invite_link: "types.ChatInviteLink" = None,
deleted_invite_link: "types.ChatInviteLink" = None deleted_invite_link: "types.ChatInviteLink" = None,
created_forum_topic: "types.ForumTopic" = None,
old_forum_topic: "types.ForumTopic" = None,
new_forum_topic: "types.ForumTopic" = None,
deleted_forum_topic: "types.ForumTopic" = None
): ):
super().__init__() super().__init__()
@ -252,6 +269,11 @@ class ChatEvent(Object):
self.revoked_invite_link = revoked_invite_link self.revoked_invite_link = revoked_invite_link
self.deleted_invite_link = deleted_invite_link self.deleted_invite_link = deleted_invite_link
self.created_forum_topic = created_forum_topic
self.old_forum_topic = old_forum_topic
self.new_forum_topic = new_forum_topic
self.deleted_forum_topic = deleted_forum_topic
@staticmethod @staticmethod
async def _parse( async def _parse(
client: "pyrogram.Client", client: "pyrogram.Client",
@ -318,6 +340,11 @@ class ChatEvent(Object):
revoked_invite_link: Optional[types.ChatInviteLink] = None revoked_invite_link: Optional[types.ChatInviteLink] = None
deleted_invite_link: Optional[types.ChatInviteLink] = None deleted_invite_link: Optional[types.ChatInviteLink] = None
created_forum_topic: Optional[types.ForumTopic] = None
old_forum_topic: Optional[types.ForumTopic] = None
new_forum_topic: Optional[types.ForumTopic] = None
deleted_forum_topic: Optional[types.ForumTopic] = None
if isinstance(action, raw.types.ChannelAdminLogEventActionChangeAbout): if isinstance(action, raw.types.ChannelAdminLogEventActionChangeAbout):
old_description = action.prev_value old_description = action.prev_value
new_description = action.new_value new_description = action.new_value
@ -426,6 +453,19 @@ class ChatEvent(Object):
deleted_invite_link = types.ChatInviteLink._parse(client, action.invite, users) deleted_invite_link = types.ChatInviteLink._parse(client, action.invite, users)
action = enums.ChatEventAction.INVITE_LINK_DELETED action = enums.ChatEventAction.INVITE_LINK_DELETED
elif isinstance(action, raw.types.ChannelAdminLogEventActionCreateTopic):
created_forum_topic = types.ForumTopic._parse(action.topic)
action = enums.ChatEventAction.CREATED_FORUM_TOPIC
elif isinstance(action, raw.types.ChannelAdminLogEventActionEditTopic):
old_forum_topic = types.ForumTopic._parse(action.prev_topic)
new_forum_topic = types.ForumTopic._parse(action.new_topic)
action = enums.ChatEventAction.EDITED_FORUM_TOPIC
elif isinstance(action, raw.types.ChannelAdminLogEventActionDeleteTopic):
created_forum_topic = types.ForumTopic._parse(action.topic)
action = enums.ChatEventAction.DELETED_FORUM_TOPIC
else: else:
action = f"{enums.ChatEventAction.UNKNOWN}-{action.QUALNAME}" action = f"{enums.ChatEventAction.UNKNOWN}-{action.QUALNAME}"
@ -485,5 +525,10 @@ class ChatEvent(Object):
old_invite_link=old_invite_link, old_invite_link=old_invite_link,
new_invite_link=new_invite_link, new_invite_link=new_invite_link,
revoked_invite_link=revoked_invite_link, revoked_invite_link=revoked_invite_link,
deleted_invite_link=deleted_invite_link deleted_invite_link=deleted_invite_link,
created_forum_topic=created_forum_topic,
old_forum_topic=old_forum_topic,
new_forum_topic=new_forum_topic,
deleted_forum_topic=deleted_forum_topic
) )

View File

@ -53,6 +53,10 @@ class ChatPermissions(Object):
can_pin_messages (``bool``, *optional*): can_pin_messages (``bool``, *optional*):
True, if the user is allowed to pin messages. True, if the user is allowed to pin messages.
Ignored in public supergroups. Ignored in public supergroups.
can_manage_topics (``bool``, *optional*):
True, if the user is allowed to create, rename, close, and reopen forum topics.
supergroups only.
""" """
def __init__( def __init__(
@ -65,7 +69,8 @@ class ChatPermissions(Object):
can_add_web_page_previews: bool = None, can_add_web_page_previews: bool = None,
can_change_info: bool = None, can_change_info: bool = None,
can_invite_users: bool = None, can_invite_users: bool = None,
can_pin_messages: bool = None can_pin_messages: bool = None,
can_manage_topics: bool = None
): ):
super().__init__(None) super().__init__(None)
@ -77,6 +82,7 @@ class ChatPermissions(Object):
self.can_change_info = can_change_info self.can_change_info = can_change_info
self.can_invite_users = can_invite_users self.can_invite_users = can_invite_users
self.can_pin_messages = can_pin_messages self.can_pin_messages = can_pin_messages
self.can_manage_topics = can_manage_topics
@staticmethod @staticmethod
def _parse(denied_permissions: "raw.base.ChatBannedRights") -> "ChatPermissions": def _parse(denied_permissions: "raw.base.ChatBannedRights") -> "ChatPermissions":
@ -94,5 +100,6 @@ class ChatPermissions(Object):
can_send_polls=not denied_permissions.send_polls, can_send_polls=not denied_permissions.send_polls,
can_change_info=not denied_permissions.change_info, can_change_info=not denied_permissions.change_info,
can_invite_users=not denied_permissions.invite_users, can_invite_users=not denied_permissions.invite_users,
can_pin_messages=not denied_permissions.pin_messages can_pin_messages=not denied_permissions.pin_messages,
can_manage_topics=not denied_permissions.manage_topics
) )

View File

@ -62,6 +62,10 @@ class ChatPrivileges(Object):
Groups and supergroups only. Groups and supergroups only.
True, if the user is allowed to pin messages. True, if the user is allowed to pin messages.
can_manage_topics (``bool``, *optional*):
supergroups only.
True, if the user is allowed to create, rename, close, and reopen forum topics.
is_anonymous (``bool``, *optional*): is_anonymous (``bool``, *optional*):
True, if the user's presence in the chat is hidden. True, if the user's presence in the chat is hidden.
""" """
@ -79,6 +83,7 @@ class ChatPrivileges(Object):
can_edit_messages: bool = False, # Channels only can_edit_messages: bool = False, # Channels only
can_invite_users: bool = False, can_invite_users: bool = False,
can_pin_messages: bool = False, # Groups and supergroups only can_pin_messages: bool = False, # Groups and supergroups only
can_manage_topics: bool = False, # Supergroups only
is_anonymous: bool = False is_anonymous: bool = False
): ):
super().__init__(None) super().__init__(None)
@ -93,6 +98,7 @@ class ChatPrivileges(Object):
self.can_edit_messages: bool = can_edit_messages self.can_edit_messages: bool = can_edit_messages
self.can_invite_users: bool = can_invite_users self.can_invite_users: bool = can_invite_users
self.can_pin_messages: bool = can_pin_messages self.can_pin_messages: bool = can_pin_messages
self.can_manage_topics: bool = can_manage_topics
self.is_anonymous: bool = is_anonymous self.is_anonymous: bool = is_anonymous
@staticmethod @staticmethod
@ -108,5 +114,6 @@ class ChatPrivileges(Object):
can_edit_messages=admin_rights.edit_messages, can_edit_messages=admin_rights.edit_messages,
can_invite_users=admin_rights.invite_users, can_invite_users=admin_rights.invite_users,
can_pin_messages=admin_rights.pin_messages, can_pin_messages=admin_rights.pin_messages,
can_manage_topics=admin_rights.manage_topics,
is_anonymous=admin_rights.anonymous is_anonymous=admin_rights.anonymous
) )

View File

@ -0,0 +1,44 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw
from ..object import Object
class PeerChannel(Object):
"""A PeerChannel.
Parameters:
channel_id (``int``):
Id of the channel.
"""
def __init__(
self, *,
channel_id: int
):
super().__init__()
self.channel_id = channel_id
@staticmethod
def _parse(action: "raw.types.PeerChannel") -> "PeerChannel":
return PeerChannel(
channel_id=getattr(action, "channel_id", None)
)

View File

@ -0,0 +1,44 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw
from ..object import Object
class PeerUser(Object):
"""A PeerUser.
Parameters:
user_id (``int``):
Id of the user.
"""
def __init__(
self, *,
user_id: int
):
super().__init__()
self.user_id = user_id
@staticmethod
def _parse(action: "raw.types.PeerUser") -> "PeerUser":
return PeerUser(
user_id=getattr(action, "user_id", None)
)

View File

@ -91,6 +91,7 @@ async def parse_messages(
) -> List["types.Message"]: ) -> List["types.Message"]:
users = {i.id: i for i in messages.users} users = {i.id: i for i in messages.users}
chats = {i.id: i for i in messages.chats} chats = {i.id: i for i in messages.chats}
topics = {i.id: i for i in messages.topics} if hasattr(messages, "topics") else None
if not messages.messages: if not messages.messages:
return types.List() return types.List()
@ -98,7 +99,7 @@ async def parse_messages(
parsed_messages = [] parsed_messages = []
for message in messages.messages: for message in messages.messages:
parsed_messages.append(await types.Message._parse(client, message, users, chats, replies=0)) parsed_messages.append(await types.Message._parse(client, message, users, chats, topics, replies=0))
if replies: if replies:
messages_with_replies = { messages_with_replies = {
@ -128,6 +129,7 @@ async def parse_messages(
for reply in reply_messages: for reply in reply_messages:
if reply.id == reply_id: if reply.id == reply_id:
if not reply.forum_topic_created:
message.reply_to_message = reply message.reply_to_message = reply
return types.List(parsed_messages) return types.List(parsed_messages)
@ -245,6 +247,17 @@ def get_peer_type(peer_id: int) -> str:
raise ValueError(f"Peer id invalid: {peer_id}") raise ValueError(f"Peer id invalid: {peer_id}")
def get_reply_to(
reply_to_message_id: Optional[int],
message_thread_id: Optional[int],
) -> Optional[raw.types.InputReplyToMessage]:
if not any((reply_to_message_id, message_thread_id)):
return None
return raw.types.InputReplyToMessage(
reply_to_msg_id=reply_to_message_id or message_thread_id, # type: ignore[arg-type]
top_msg_id=message_thread_id if reply_to_message_id else None,
)
def get_channel_id(peer_id: int) -> int: def get_channel_id(peer_id: int) -> int:
return MAX_CHANNEL_ID - peer_id return MAX_CHANNEL_ID - peer_id