2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-08-28 21:07:59 +00:00

Implement editing of messages sent via inline bots

- edit_message_text
- edit_message_caption
- edit_message_media
- edit_message_reply_markup
This commit is contained in:
Dan 2019-06-14 02:12:06 +02:00
parent a2d1752e89
commit 22199b0fe5
6 changed files with 122 additions and 65 deletions

View File

@ -156,3 +156,6 @@ class BaseClient:
def get_profile_photos(self, *args, **kwargs):
pass
def edit_message_text(self, *args, **kwargs):
pass

View File

@ -16,6 +16,7 @@
# 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 base64
import struct
from base64 import b64decode, b64encode
from typing import Union, List
@ -191,3 +192,14 @@ def parse_deleted_messages(client, update) -> List["pyrogram.Message"]:
)
return pyrogram.List(parsed_messages)
def unpack_inline_message_id(inline_message_id: str) -> types.InputBotInlineMessageID:
r = inline_message_id + "=" * (-len(inline_message_id) % 4)
r = struct.unpack("<iqq", base64.b64decode(r, altchars="-_"))
return types.InputBotInlineMessageID(
dc_id=r[0],
id=r[1],
access_hash=r[2]
)

View File

@ -19,61 +19,58 @@
from typing import Union
import pyrogram
from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient
class EditMessageCaption(BaseClient):
def edit_message_caption(
self,
chat_id: Union[int, str],
message_id: int,
caption: str,
chat_id: Union[int, str] = None,
message_id: int = None,
inline_message_id: str = None,
parse_mode: str = "",
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
) -> "pyrogram.Message":
"""Edit captions of messages.
"""Edit caption of media messages.
Parameters:
chat_id (``int`` | ``str``):
caption (``str``):
New caption of the media message.
chat_id (``int`` | ``str``, *optional*):
Required if *inline_message_id* is not specified.
Unique identifier (int) or username (str) of the target chat.
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).
message_id (``int``):
message_id (``int``, *optional*):
Required if *inline_message_id* is not specified.
Message identifier in the chat specified in chat_id.
caption (``str``):
New caption of the message.
inline_message_id (``str``, *optional*):
Required if *chat_id* and *message_id* are not specified.
Identifier of the inline message.
parse_mode (``str``, *optional*):
Pass "markdown" or "html" if you want Telegram apps to show bold, italic, fixed-width text or inline
URLs in your caption. Defaults to "markdown".
URLs in your message. Defaults to "markdown".
reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
:obj:`Message`: On success, the edited message is returned.
:obj:`Message` | ``bool``: On success, if the edited message was sent by the bot, the edited message is
returned, otherwise True is returned (message sent via the bot, as inline query result).
Raises:
RPCError: In case of a Telegram RPC error.
"""
style = self.html if parse_mode.lower() == "html" else self.markdown
r = self.send(
functions.messages.EditMessage(
peer=self.resolve_peer(chat_id),
id=message_id,
reply_markup=reply_markup.write() if reply_markup else None,
**style.parse(caption)
)
)
for i in r.updates:
if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)):
return pyrogram.Message._parse(
self, i.message,
{i.id: i for i in r.users},
{i.id: i for i in r.chats}
return self.edit_message_text(
text=caption,
chat_id=chat_id,
message_id=message_id,
inline_message_id=inline_message_id,
parse_mode=parse_mode,
reply_markup=reply_markup
)

View File

@ -32,35 +32,42 @@ from pyrogram.client.types.input_media import InputMedia
class EditMessageMedia(BaseClient):
def edit_message_media(
self,
chat_id: Union[int, str],
message_id: int,
media: InputMedia,
chat_id: Union[int, str] = None,
message_id: int = None,
inline_message_id: str = None,
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
) -> "pyrogram.Message":
"""Edit audio, document, photo, or video messages.
"""Edit animation, audio, document, photo or video messages.
If a message is a part of a message album, then it can be edited only to a photo or a video. Otherwise,
message type can be changed arbitrarily. When inline message is edited, new file can't be uploaded.
Use previously uploaded file via its file_id or specify a URL. On success, if the edited message was sent
by the bot, the edited Message is returned, otherwise True is returned.
Use previously uploaded file via its file_id or specify a URL.
Parameters:
chat_id (``int`` | ``str``):
media (:obj:`InputMedia`)
One of the InputMedia objects describing an animation, audio, document, photo or video.
chat_id (``int`` | ``str``, *optional*):
Required if *inline_message_id* is not specified.
Unique identifier (int) or username (str) of the target chat.
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).
message_id (``int``):
message_id (``int``, *optional*):
Required if *inline_message_id* is not specified.
Message identifier in the chat specified in chat_id.
media (:obj:`InputMedia`)
One of the InputMedia objects describing an animation, audio, document, photo or video.
inline_message_id (``str``, *optional*):
Required if *chat_id* and *message_id* are not specified.
Identifier of the inline message.
reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
:obj:`Message`: On success, the edited message is returned.
:obj:`Message` | ``bool``: On success, if the edited message was sent by the bot, the edited message is
returned, otherwise True is returned (message sent via the bot, as inline query result).
Raises:
RPCError: In case of a Telegram RPC error.
@ -92,8 +99,7 @@ class EditMessageMedia(BaseClient):
)
else:
media = utils.get_input_media_from_file_id(media.media, 2)
if isinstance(media, InputMediaVideo):
elif isinstance(media, InputMediaVideo):
if os.path.exists(media.media):
media = self.send(
functions.messages.UploadMedia(
@ -130,8 +136,7 @@ class EditMessageMedia(BaseClient):
)
else:
media = utils.get_input_media_from_file_id(media.media, 4)
if isinstance(media, InputMediaAudio):
elif isinstance(media, InputMediaAudio):
if os.path.exists(media.media):
media = self.send(
functions.messages.UploadMedia(
@ -167,8 +172,7 @@ class EditMessageMedia(BaseClient):
)
else:
media = utils.get_input_media_from_file_id(media.media, 9)
if isinstance(media, InputMediaAnimation):
elif isinstance(media, InputMediaAnimation):
if os.path.exists(media.media):
media = self.send(
functions.messages.UploadMedia(
@ -206,8 +210,7 @@ class EditMessageMedia(BaseClient):
)
else:
media = utils.get_input_media_from_file_id(media.media, 10)
if isinstance(media, InputMediaDocument):
elif isinstance(media, InputMediaDocument):
if os.path.exists(media.media):
media = self.send(
functions.messages.UploadMedia(
@ -239,12 +242,22 @@ class EditMessageMedia(BaseClient):
else:
media = utils.get_input_media_from_file_id(media.media, 5)
if inline_message_id is not None:
return self.send(
functions.messages.EditInlineBotMessage(
id=utils.unpack_inline_message_id(inline_message_id),
media=media,
reply_markup=reply_markup.write() if reply_markup else None,
**style.parse(caption)
)
)
r = self.send(
functions.messages.EditMessage(
peer=self.resolve_peer(chat_id),
id=message_id,
reply_markup=reply_markup.write() if reply_markup else None,
media=media,
reply_markup=reply_markup.write() if reply_markup else None,
**style.parse(caption)
)
)

View File

@ -20,43 +20,57 @@ from typing import Union
import pyrogram
from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient
from pyrogram.client.ext import BaseClient, utils
class EditMessageReplyMarkup(BaseClient):
def edit_message_reply_markup(
self,
chat_id: Union[int, str],
message_id: int,
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
reply_markup: "pyrogram.InlineKeyboardMarkup" = None,
chat_id: Union[int, str] = None,
message_id: int = None,
inline_message_id: str = None
) -> "pyrogram.Message":
"""Edit only the reply markup of messages sent by the bot or via the bot (for inline bots).
Parameters:
chat_id (``int`` | ``str``):
reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
chat_id (``int`` | ``str``, *optional*):
Required if *inline_message_id* is not specified.
Unique identifier (int) or username (str) of the target chat.
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).
message_id (``int``):
message_id (``int``, *optional*):
Required if *inline_message_id* is not specified.
Message identifier in the chat specified in chat_id.
reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
inline_message_id (``str``, *optional*):
Required if *chat_id* and *message_id* are not specified.
Identifier of the inline message.
Returns:
:obj:`Message` | ``bool``: In case the edited message is sent by the bot, the edited message is returned,
otherwise, True is returned in case the edited message is send by the user.
:obj:`Message` | ``bool``: On success, if the edited message was sent by the bot, the edited message is
returned, otherwise True is returned (message sent via the bot, as inline query result).
Raises:
RPCError: In case of a Telegram RPC error.
"""
if inline_message_id is not None:
return self.send(
functions.messages.EditInlineBotMessage(
id=utils.unpack_inline_message_id(inline_message_id),
reply_markup=reply_markup.write() if reply_markup else None,
)
)
r = self.send(
functions.messages.EditMessage(
peer=self.resolve_peer(chat_id),
id=message_id,
reply_markup=reply_markup.write() if reply_markup else None
reply_markup=reply_markup.write() if reply_markup else None,
)
)

View File

@ -20,15 +20,16 @@ from typing import Union
import pyrogram
from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient
from pyrogram.client.ext import BaseClient, utils
class EditMessageText(BaseClient):
def edit_message_text(
self,
chat_id: Union[int, str],
message_id: int,
text: str,
chat_id: Union[int, str] = None,
message_id: int = None,
inline_message_id: str = None,
parse_mode: str = "",
disable_web_page_preview: bool = None,
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
@ -36,16 +37,22 @@ class EditMessageText(BaseClient):
"""Edit text messages.
Parameters:
chat_id (``int`` | ``str``):
text (``str``):
New text of the message.
chat_id (``int`` | ``str``, *optional*):
Required if *inline_message_id* is not specified.
Unique identifier (int) or username (str) of the target chat.
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).
message_id (``int``):
message_id (``int``, *optional*):
Required if *inline_message_id* is not specified.
Message identifier in the chat specified in chat_id.
text (``str``):
New text of the message.
inline_message_id (``str``, *optional*):
Required if *chat_id* and *message_id* are not specified.
Identifier of the inline message.
parse_mode (``str``, *optional*):
Pass "markdown" or "html" if you want Telegram apps to show bold, italic, fixed-width text or inline
@ -58,13 +65,24 @@ class EditMessageText(BaseClient):
An InlineKeyboardMarkup object.
Returns:
:obj:`Message`: On success, the edited message is returned.
:obj:`Message` | ``bool``: On success, if the edited message was sent by the bot, the edited message is
returned, otherwise True is returned (message sent via the bot, as inline query result).
Raises:
RPCError: In case of a Telegram RPC error.
"""
style = self.html if parse_mode.lower() == "html" else self.markdown
if inline_message_id is not None:
return self.send(
functions.messages.EditInlineBotMessage(
id=utils.unpack_inline_message_id(inline_message_id),
no_webpage=disable_web_page_preview or None,
reply_markup=reply_markup.write() if reply_markup else None,
**style.parse(text)
)
)
r = self.send(
functions.messages.EditMessage(
peer=self.resolve_peer(chat_id),