Skip to content

Commit 6b43edb

Browse files
authored
feat(messages): add send_message_draft method (for AI streaming effects private chats) (#231)
1 parent 90d1a5d commit 6b43edb

3 files changed

Lines changed: 117 additions & 0 deletions

File tree

compiler/docs/compiler.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ def get_title_list(s: str) -> list:
460460
send_web_app_custom_request
461461
get_owned_bots
462462
get_similar_bots
463+
send_message_draft
463464
""",
464465
phone="""
465466
Phone

pyrogram/methods/bots/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from .get_inline_bot_results import GetInlineBotResults
3131
from .request_callback_answer import RequestCallbackAnswer
3232
from .send_game import SendGame
33+
from .send_message_draft import SendMessageDraft
3334
from .send_inline_bot_result import SendInlineBotResult
3435
from .send_web_app_custom_request import SendWebAppCustomRequest
3536
from .set_bot_commands import SetBotCommands
@@ -69,5 +70,6 @@ class Bots(
6970
GetBotName,
7071
GetOwnedBots,
7172
GetSimilarBots,
73+
SendMessageDraft,
7274
):
7375
pass
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Pyrogram - Telegram MTProto API Client Library for Python
2+
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
3+
#
4+
# This file is part of Pyrogram.
5+
#
6+
# Pyrogram is free software: you can redistribute it and/or modify
7+
# it under the terms of the GNU Lesser General Public License as published
8+
# by the Free Software Foundation, either version 3 of the License, or
9+
# (at your option) any later version.
10+
#
11+
# Pyrogram is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
# GNU Lesser General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU Lesser General Public License
17+
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
18+
19+
from typing import Union, Optional
20+
21+
import pyrogram
22+
from pyrogram import raw, utils, enums, types
23+
24+
25+
class SendMessageDraft:
26+
async def send_message_draft(
27+
self: "pyrogram.Client",
28+
chat_id: Union[int, str],
29+
draft_id: int,
30+
text: str,
31+
parse_mode: Optional["enums.ParseMode"] = None,
32+
entities: list["types.MessageEntity"] = None,
33+
message_thread_id: int = None,
34+
) -> bool:
35+
"""Sends a draft for a being generated text message.
36+
37+
Use this method to stream a partial message to a user while the message is being generated. This method shows a live text preview as it is being composed. To achieve a smooth
38+
AI-streaming effect, call this method repeatedly with progressively longer text, passing a consistent *draft_id* for all frames of the same stream.
39+
40+
.. include:: /_includes/usable-by/bots.rst
41+
42+
Parameters:
43+
chat_id (``int`` | ``str``):
44+
Unique identifier of the target chat.
45+
46+
draft_id (``int``):
47+
Unique identifier of the message draft; must be non-zero. Changes of drafts with the same identifier are animated.
48+
49+
text (``str``):
50+
Text of the message to be sent, 1-4096 characters after entities parsing.
51+
52+
parse_mode (:obj:`~pyrogram.enums.ParseMode`, *optional*):
53+
Mode for parsing entities in the message text. By default, texts are parsed using Markdown and HTML styles.
54+
55+
entities (List of :obj:`~pyrogram.types.MessageEntity`, *optional*):
56+
List of special entities that appear in the text, which can be specified instead of **parse_mode**.
57+
58+
message_thread_id (``int``, *optional*):
59+
Unique identifier for the target message thread.
60+
61+
Returns:
62+
``bool``: On success, True is returned.
63+
64+
Raises:
65+
ValueError: If the text is empty or the chat type is not a private chat.
66+
:obj:`~pyrogram.errors.RPCError`: In case of a Telegram RPC error.
67+
68+
Example:
69+
.. code-block:: python
70+
71+
text = "Hello! I'm your Pyrogram bot! How can I help you?"
72+
words = text.split()
73+
draft_id = 1
74+
for i, word in enumerate(words):
75+
await app.send_message_draft(
76+
chat_id=chat_id,
77+
draft_id=draft_id,
78+
text=" ".join(words[:i+1]),
79+
)
80+
await app.send_message(chat_id, text)
81+
82+
"""
83+
84+
if not chat_id:
85+
raise ValueError("chat_id is required")
86+
87+
if not text:
88+
raise ValueError("text cannot be empty")
89+
90+
peer = await self.resolve_peer(chat_id)
91+
92+
if not isinstance(peer, (raw.types.InputPeerUser, raw.types.InputPeerSelf)):
93+
raise ValueError("Streaming text is only supported in private chats (user-to-bot)")
94+
95+
message, entities = (
96+
await utils.parse_text_entities(self, text, parse_mode, entities)
97+
).values()
98+
99+
if not message:
100+
raise ValueError("text cannot be empty after parsing")
101+
102+
return await self.invoke(
103+
raw.functions.messages.SetTyping(
104+
peer=peer,
105+
action=raw.types.SendMessageTextDraftAction(
106+
random_id=draft_id,
107+
text=raw.types.TextWithEntities(
108+
text=message,
109+
entities=entities or []
110+
)
111+
),
112+
top_msg_id=message_thread_id
113+
)
114+
)

0 commit comments

Comments
 (0)