From 384f4eba71519e0da12c23226b0aac10a706bd8d Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Sun, 29 Nov 2020 15:48:29 +0100
Subject: [PATCH] Add support for manual text entities.
---
.../methods/messages/edit_message_caption.py | 7 +-
.../methods/messages/edit_message_text.py | 9 +-
pyrogram/methods/messages/send_animation.py | 8 +-
pyrogram/methods/messages/send_audio.py | 11 +-
pyrogram/methods/messages/send_document.py | 8 +-
pyrogram/methods/messages/send_message.py | 10 +-
pyrogram/methods/messages/send_photo.py | 8 +-
pyrogram/methods/messages/send_video.py | 8 +-
pyrogram/methods/messages/send_voice.py | 8 +-
pyrogram/types/input_media/input_media.py | 12 +-
.../input_media/input_media_animation.py | 9 +-
.../types/input_media/input_media_audio.py | 9 +-
.../types/input_media/input_media_document.py | 11 +-
.../types/input_media/input_media_photo.py | 11 +-
.../types/input_media/input_media_video.py | 9 +-
pyrogram/types/messages_and_media/message.py | 50 ++++++++
.../messages_and_media/message_entity.py | 116 ++++++++++++++----
pyrogram/utils.py | 25 +++-
18 files changed, 270 insertions(+), 59 deletions(-)
diff --git a/pyrogram/methods/messages/edit_message_caption.py b/pyrogram/methods/messages/edit_message_caption.py
index 76b6cc48..a1cceffa 100644
--- a/pyrogram/methods/messages/edit_message_caption.py
+++ b/pyrogram/methods/messages/edit_message_caption.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Union
+from typing import Union, List
from pyrogram import types
from pyrogram.scaffold import Scaffold
@@ -29,6 +29,7 @@ class EditMessageCaption(Scaffold):
message_id: int,
caption: str,
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
reply_markup: "types.InlineKeyboardMarkup" = None
) -> "types.Message":
"""Edit the caption of media messages.
@@ -52,6 +53,9 @@ class EditMessageCaption(Scaffold):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
@@ -68,5 +72,6 @@ class EditMessageCaption(Scaffold):
message_id=message_id,
text=caption,
parse_mode=parse_mode,
+ entities=caption_entities,
reply_markup=reply_markup
)
diff --git a/pyrogram/methods/messages/edit_message_text.py b/pyrogram/methods/messages/edit_message_text.py
index b7d84830..ece20d04 100644
--- a/pyrogram/methods/messages/edit_message_text.py
+++ b/pyrogram/methods/messages/edit_message_text.py
@@ -16,10 +16,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Union
+from typing import Union, List
from pyrogram import raw
from pyrogram import types
+from pyrogram import utils
from pyrogram.scaffold import Scaffold
@@ -30,6 +31,7 @@ class EditMessageText(Scaffold):
message_id: int,
text: str,
parse_mode: Union[str, None] = object,
+ entities: List["types.MessageEntity"] = None,
disable_web_page_preview: bool = None,
reply_markup: "types.InlineKeyboardMarkup" = None
) -> "types.Message":
@@ -54,6 +56,9 @@ class EditMessageText(Scaffold):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in message text, which can be specified instead of __parse_mode__.
+
disable_web_page_preview (``bool``, *optional*):
Disables link previews for links in this message.
@@ -81,7 +86,7 @@ class EditMessageText(Scaffold):
id=message_id,
no_webpage=disable_web_page_preview or None,
reply_markup=reply_markup.write() if reply_markup else None,
- **await self.parser.parse(text, parse_mode)
+ **await utils.parse_text_entities(self, text, parse_mode, entities)
)
)
diff --git a/pyrogram/methods/messages/send_animation.py b/pyrogram/methods/messages/send_animation.py
index 2abc8a92..e705b5c8 100644
--- a/pyrogram/methods/messages/send_animation.py
+++ b/pyrogram/methods/messages/send_animation.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union, BinaryIO
+from typing import Union, BinaryIO, List
from pyrogram import StopTransmission
from pyrogram import raw
@@ -37,6 +37,7 @@ class SendAnimation(Scaffold):
caption: str = "",
unsave: bool = False,
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
duration: int = 0,
width: int = 0,
height: int = 0,
@@ -83,6 +84,9 @@ class SendAnimation(Scaffold):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
duration (``int``, *optional*):
Duration of sent animation in seconds.
@@ -219,7 +223,7 @@ class SendAnimation(Scaffold):
random_id=self.rnd_id(),
schedule_date=schedule_date,
reply_markup=reply_markup.write() if reply_markup else None,
- **await self.parser.parse(caption, parse_mode)
+ **await utils.parse_text_entities(self, caption, parse_mode, caption_entities)
)
)
except FilePartMissing as e:
diff --git a/pyrogram/methods/messages/send_audio.py b/pyrogram/methods/messages/send_audio.py
index ceff4a54..18fd2bf1 100644
--- a/pyrogram/methods/messages/send_audio.py
+++ b/pyrogram/methods/messages/send_audio.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union, BinaryIO
+from typing import Union, BinaryIO, List
from pyrogram import StopTransmission
from pyrogram import raw
@@ -36,10 +36,12 @@ class SendAudio(Scaffold):
audio: Union[str, BinaryIO],
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
duration: int = 0,
performer: str = None,
title: str = None,
- thumb: Union[str, BinaryIO] = None, file_name: str = None,
+ thumb: Union[str, BinaryIO] = None,
+ file_name: str = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
schedule_date: int = None,
@@ -79,6 +81,9 @@ class SendAudio(Scaffold):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
duration (``int``, *optional*):
Duration of the audio in seconds.
@@ -213,7 +218,7 @@ class SendAudio(Scaffold):
random_id=self.rnd_id(),
schedule_date=schedule_date,
reply_markup=reply_markup.write() if reply_markup else None,
- **await self.parser.parse(caption, parse_mode)
+ **await utils.parse_text_entities(self, caption, parse_mode, caption_entities)
)
)
except FilePartMissing as e:
diff --git a/pyrogram/methods/messages/send_document.py b/pyrogram/methods/messages/send_document.py
index d64117d5..20fea5d5 100644
--- a/pyrogram/methods/messages/send_document.py
+++ b/pyrogram/methods/messages/send_document.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union, BinaryIO
+from typing import Union, BinaryIO, List
from pyrogram import StopTransmission
from pyrogram import raw
@@ -37,6 +37,7 @@ class SendDocument(Scaffold):
thumb: Union[str, BinaryIO] = None,
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
file_name: str = None,
force_document: bool = None,
disable_notification: bool = None,
@@ -82,6 +83,9 @@ class SendDocument(Scaffold):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
file_name (``str``, *optional*):
File name of the document sent.
Defaults to file's path basename.
@@ -191,7 +195,7 @@ class SendDocument(Scaffold):
random_id=self.rnd_id(),
schedule_date=schedule_date,
reply_markup=reply_markup.write() if reply_markup else None,
- **await self.parser.parse(caption, parse_mode)
+ **await utils.parse_text_entities(self, caption, parse_mode, caption_entities)
)
)
except FilePartMissing as e:
diff --git a/pyrogram/methods/messages/send_message.py b/pyrogram/methods/messages/send_message.py
index 93264731..e873b58d 100644
--- a/pyrogram/methods/messages/send_message.py
+++ b/pyrogram/methods/messages/send_message.py
@@ -16,9 +16,9 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Union
+from typing import Union, List
-from pyrogram import raw
+from pyrogram import raw, utils
from pyrogram import types
from pyrogram.scaffold import Scaffold
@@ -29,6 +29,7 @@ class SendMessage(Scaffold):
chat_id: Union[int, str],
text: str,
parse_mode: Union[str, None] = object,
+ entities: List["types.MessageEntity"] = None,
disable_web_page_preview: bool = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
@@ -58,6 +59,9 @@ class SendMessage(Scaffold):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in message text, which can be specified instead of __parse_mode__.
+
disable_web_page_preview (``bool``, *optional*):
Disables link previews for links in this message.
@@ -116,7 +120,7 @@ class SendMessage(Scaffold):
]))
"""
- message, entities = (await self.parser.parse(text, parse_mode)).values()
+ message, entities = (await utils.parse_text_entities(self, text, parse_mode, entities)).values()
r = await self.send(
raw.functions.messages.SendMessage(
diff --git a/pyrogram/methods/messages/send_photo.py b/pyrogram/methods/messages/send_photo.py
index 6caca1bf..0b84a8c0 100644
--- a/pyrogram/methods/messages/send_photo.py
+++ b/pyrogram/methods/messages/send_photo.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union, BinaryIO
+from typing import Union, BinaryIO, List
import pyrogram
from pyrogram import raw
@@ -36,6 +36,7 @@ class SendPhoto(Scaffold):
photo: Union[str, BinaryIO],
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
ttl_seconds: int = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
@@ -74,6 +75,9 @@ class SendPhoto(Scaffold):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
ttl_seconds (``int``, *optional*):
Self-Destruct Timer.
If you set a timer, the photo will self-destruct in *ttl_seconds*
@@ -169,7 +173,7 @@ class SendPhoto(Scaffold):
random_id=self.rnd_id(),
schedule_date=schedule_date,
reply_markup=reply_markup.write() if reply_markup else None,
- **await self.parser.parse(caption, parse_mode)
+ **await utils.parse_text_entities(self, caption, parse_mode, caption_entities)
)
)
except FilePartMissing as e:
diff --git a/pyrogram/methods/messages/send_video.py b/pyrogram/methods/messages/send_video.py
index cc4e082d..18eb5b67 100644
--- a/pyrogram/methods/messages/send_video.py
+++ b/pyrogram/methods/messages/send_video.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union, BinaryIO
+from typing import Union, BinaryIO, List
from pyrogram import StopTransmission
from pyrogram import raw
@@ -36,6 +36,7 @@ class SendVideo(Scaffold):
video: Union[str, BinaryIO],
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
duration: int = 0,
width: int = 0,
height: int = 0,
@@ -79,6 +80,9 @@ class SendVideo(Scaffold):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
duration (``int``, *optional*):
Duration of sent video in seconds.
@@ -213,7 +217,7 @@ class SendVideo(Scaffold):
random_id=self.rnd_id(),
schedule_date=schedule_date,
reply_markup=reply_markup.write() if reply_markup else None,
- **await self.parser.parse(caption, parse_mode)
+ **await utils.parse_text_entities(self, caption, parse_mode, caption_entities)
)
)
except FilePartMissing as e:
diff --git a/pyrogram/methods/messages/send_voice.py b/pyrogram/methods/messages/send_voice.py
index d6dd9bdb..36bea41c 100644
--- a/pyrogram/methods/messages/send_voice.py
+++ b/pyrogram/methods/messages/send_voice.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union, BinaryIO
+from typing import Union, BinaryIO, List
from pyrogram import StopTransmission
from pyrogram import raw
@@ -36,6 +36,7 @@ class SendVoice(Scaffold):
voice: Union[str, BinaryIO],
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
duration: int = 0,
disable_notification: bool = None,
reply_to_message_id: int = None,
@@ -74,6 +75,9 @@ class SendVoice(Scaffold):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
duration (``int``, *optional*):
Duration of the voice message in seconds.
@@ -175,7 +179,7 @@ class SendVoice(Scaffold):
random_id=self.rnd_id(),
schedule_date=schedule_date,
reply_markup=reply_markup.write() if reply_markup else None,
- **await self.parser.parse(caption, parse_mode)
+ **await utils.parse_text_entities(self, caption, parse_mode, caption_entities)
)
)
except FilePartMissing as e:
diff --git a/pyrogram/types/input_media/input_media.py b/pyrogram/types/input_media/input_media.py
index 6c739d87..bcbe2e52 100644
--- a/pyrogram/types/input_media/input_media.py
+++ b/pyrogram/types/input_media/input_media.py
@@ -16,6 +16,9 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from typing import List
+
+from ..messages_and_media import MessageEntity
from ..object import Object
@@ -31,9 +34,16 @@ class InputMedia(Object):
- :obj:`~pyrogram.types.InputMediaVideo`
"""
- def __init__(self, media: str, caption: str, parse_mode: str):
+ def __init__(
+ self,
+ media: str,
+ caption: str = None,
+ parse_mode: str = None,
+ caption_entities: List[MessageEntity] = None
+ ):
super().__init__()
self.media = media
self.caption = caption
self.parse_mode = parse_mode
+ self.caption_entities = caption_entities
diff --git a/pyrogram/types/input_media/input_media_animation.py b/pyrogram/types/input_media/input_media_animation.py
index a59f229f..bd9ac1b5 100644
--- a/pyrogram/types/input_media/input_media_animation.py
+++ b/pyrogram/types/input_media/input_media_animation.py
@@ -16,9 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Union
+from typing import Union, List
from .input_media import InputMedia
+from ..messages_and_media import MessageEntity
class InputMediaAnimation(InputMedia):
@@ -46,6 +47,9 @@ class InputMediaAnimation(InputMedia):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
width (``int``, *optional*):
Animation width.
@@ -62,11 +66,12 @@ class InputMediaAnimation(InputMedia):
thumb: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List[MessageEntity] = None,
width: int = 0,
height: int = 0,
duration: int = 0
):
- super().__init__(media, caption, parse_mode)
+ super().__init__(media, caption, parse_mode, caption_entities)
self.thumb = thumb
self.width = width
diff --git a/pyrogram/types/input_media/input_media_audio.py b/pyrogram/types/input_media/input_media_audio.py
index 99fa973c..be966d52 100644
--- a/pyrogram/types/input_media/input_media_audio.py
+++ b/pyrogram/types/input_media/input_media_audio.py
@@ -16,9 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Union
+from typing import Union, List
from .input_media import InputMedia
+from ..messages_and_media import MessageEntity
class InputMediaAudio(InputMedia):
@@ -48,6 +49,9 @@ class InputMediaAudio(InputMedia):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
duration (``int``, *optional*):
Duration of the audio in seconds
@@ -64,11 +68,12 @@ class InputMediaAudio(InputMedia):
thumb: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List[MessageEntity] = None,
duration: int = 0,
performer: str = "",
title: str = ""
):
- super().__init__(media, caption, parse_mode)
+ super().__init__(media, caption, parse_mode, caption_entities)
self.thumb = thumb
self.duration = duration
diff --git a/pyrogram/types/input_media/input_media_document.py b/pyrogram/types/input_media/input_media_document.py
index 23deec32..7d6500d4 100644
--- a/pyrogram/types/input_media/input_media_document.py
+++ b/pyrogram/types/input_media/input_media_document.py
@@ -16,9 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Union
+from typing import Union, List
from .input_media import InputMedia
+from ..messages_and_media import MessageEntity
class InputMediaDocument(InputMedia):
@@ -45,6 +46,9 @@ class InputMediaDocument(InputMedia):
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
"""
def __init__(
@@ -52,8 +56,9 @@ class InputMediaDocument(InputMedia):
media: str,
thumb: str = None,
caption: str = "",
- parse_mode: Union[str, None] = object
+ parse_mode: Union[str, None] = object,
+ caption_entities: List[MessageEntity] = None
):
- super().__init__(media, caption, parse_mode)
+ super().__init__(media, caption, parse_mode, caption_entities)
self.thumb = thumb
diff --git a/pyrogram/types/input_media/input_media_photo.py b/pyrogram/types/input_media/input_media_photo.py
index f8797982..7b0c97aa 100644
--- a/pyrogram/types/input_media/input_media_photo.py
+++ b/pyrogram/types/input_media/input_media_photo.py
@@ -16,9 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Union
+from typing import Union, List
from .input_media import InputMedia
+from ..messages_and_media import MessageEntity
class InputMediaPhoto(InputMedia):
@@ -41,12 +42,16 @@ class InputMediaPhoto(InputMedia):
Pass "markdown" or "md" to enable Markdown-style parsing only.
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
"""
def __init__(
self,
media: str,
caption: str = "",
- parse_mode: Union[str, None] = object
+ parse_mode: Union[str, None] = object,
+ caption_entities: List[MessageEntity] = None
):
- super().__init__(media, caption, parse_mode)
+ super().__init__(media, caption, parse_mode, caption_entities)
diff --git a/pyrogram/types/input_media/input_media_video.py b/pyrogram/types/input_media/input_media_video.py
index 3de713e1..8a3013bd 100644
--- a/pyrogram/types/input_media/input_media_video.py
+++ b/pyrogram/types/input_media/input_media_video.py
@@ -16,9 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
-from typing import Union
+from typing import Union, List
from .input_media import InputMedia
+from ..messages_and_media import MessageEntity
class InputMediaVideo(InputMedia):
@@ -48,6 +49,9 @@ class InputMediaVideo(InputMedia):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
width (``int``, *optional*):
Video width.
@@ -67,12 +71,13 @@ class InputMediaVideo(InputMedia):
thumb: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List[MessageEntity] = None,
width: int = 0,
height: int = 0,
duration: int = 0,
supports_streaming: bool = True
):
- super().__init__(media, caption, parse_mode)
+ super().__init__(media, caption, parse_mode, caption_entities)
self.thumb = thumb
self.width = width
diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py
index 1f85ba8b..4992c37d 100644
--- a/pyrogram/types/messages_and_media/message.py
+++ b/pyrogram/types/messages_and_media/message.py
@@ -711,6 +711,7 @@ class Message(Object, Update):
text: str,
quote: bool = None,
parse_mode: Union[str, None] = object,
+ entities: List["types.MessageEntity"] = None,
disable_web_page_preview: bool = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
@@ -749,6 +750,9 @@ class Message(Object, Update):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in message text, which can be specified instead of __parse_mode__.
+
disable_web_page_preview (``bool``, *optional*):
Disables link previews for links in this message.
@@ -779,6 +783,7 @@ class Message(Object, Update):
chat_id=self.chat.id,
text=text,
parse_mode=parse_mode,
+ entities=entities,
disable_web_page_preview=disable_web_page_preview,
disable_notification=disable_notification,
reply_to_message_id=reply_to_message_id,
@@ -793,6 +798,7 @@ class Message(Object, Update):
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
duration: int = 0,
width: int = 0,
height: int = 0,
@@ -846,6 +852,9 @@ class Message(Object, Update):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
duration (``int``, *optional*):
Duration of sent animation in seconds.
@@ -913,6 +922,7 @@ class Message(Object, Update):
animation=animation,
caption=caption,
parse_mode=parse_mode,
+ caption_entities=caption_entities,
duration=duration,
width=width,
height=height,
@@ -930,6 +940,7 @@ class Message(Object, Update):
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
duration: int = 0,
performer: str = None,
title: str = None,
@@ -983,6 +994,9 @@ class Message(Object, Update):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
duration (``int``, *optional*):
Duration of the audio in seconds.
@@ -1050,6 +1064,7 @@ class Message(Object, Update):
audio=audio,
caption=caption,
parse_mode=parse_mode,
+ caption_entities=caption_entities,
duration=duration,
performer=performer,
title=title,
@@ -1067,6 +1082,7 @@ class Message(Object, Update):
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
@@ -1112,6 +1128,9 @@ class Message(Object, Update):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
disable_notification (``bool``, *optional*):
Sends the message silently.
Users will receive a notification with no sound.
@@ -1140,6 +1159,7 @@ class Message(Object, Update):
file_id=file_id,
caption=caption,
parse_mode=parse_mode,
+ caption_entities=caption_entities,
disable_notification=disable_notification,
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup
@@ -1275,6 +1295,7 @@ class Message(Object, Update):
thumb: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
reply_markup: Union[
@@ -1330,6 +1351,9 @@ class Message(Object, Update):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
disable_notification (``bool``, *optional*):
Sends the message silently.
Users will receive a notification with no sound.
@@ -1383,6 +1407,7 @@ class Message(Object, Update):
thumb=thumb,
caption=caption,
parse_mode=parse_mode,
+ caption_entities=caption_entities,
disable_notification=disable_notification,
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
@@ -1670,6 +1695,7 @@ class Message(Object, Update):
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
ttl_seconds: int = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
@@ -1720,6 +1746,9 @@ class Message(Object, Update):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
ttl_seconds (``int``, *optional*):
Self-Destruct Timer.
If you set a timer, the photo will self-destruct in *ttl_seconds*
@@ -1777,6 +1806,7 @@ class Message(Object, Update):
photo=photo,
caption=caption,
parse_mode=parse_mode,
+ caption_entities=caption_entities,
ttl_seconds=ttl_seconds,
disable_notification=disable_notification,
reply_to_message_id=reply_to_message_id,
@@ -2093,6 +2123,7 @@ class Message(Object, Update):
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
duration: int = 0,
width: int = 0,
height: int = 0,
@@ -2147,6 +2178,9 @@ class Message(Object, Update):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
duration (``int``, *optional*):
Duration of sent video in seconds.
@@ -2217,6 +2251,7 @@ class Message(Object, Update):
video=video,
caption=caption,
parse_mode=parse_mode,
+ caption_entities=caption_entities,
duration=duration,
width=width,
height=height,
@@ -2353,6 +2388,7 @@ class Message(Object, Update):
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
duration: int = 0,
disable_notification: bool = None,
reply_to_message_id: int = None,
@@ -2403,6 +2439,9 @@ class Message(Object, Update):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
duration (``int``, *optional*):
Duration of the voice message in seconds.
@@ -2458,6 +2497,7 @@ class Message(Object, Update):
voice=voice,
caption=caption,
parse_mode=parse_mode,
+ caption_entities=caption_entities,
duration=duration,
disable_notification=disable_notification,
reply_to_message_id=reply_to_message_id,
@@ -2470,6 +2510,7 @@ class Message(Object, Update):
self,
text: str,
parse_mode: Union[str, None] = object,
+ entities: List["types.MessageEntity"] = None,
disable_web_page_preview: bool = None,
reply_markup: "types.InlineKeyboardMarkup" = None
) -> "Message":
@@ -2501,6 +2542,9 @@ class Message(Object, Update):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in message text, which can be specified instead of __parse_mode__.
+
disable_web_page_preview (``bool``, *optional*):
Disables link previews for links in this message.
@@ -2518,6 +2562,7 @@ class Message(Object, Update):
message_id=self.message_id,
text=text,
parse_mode=parse_mode,
+ entities=entities,
disable_web_page_preview=disable_web_page_preview,
reply_markup=reply_markup
)
@@ -2528,6 +2573,7 @@ class Message(Object, Update):
self,
caption: str,
parse_mode: Union[str, None] = object,
+ caption_entities: List["types.MessageEntity"] = None,
reply_markup: "types.InlineKeyboardMarkup" = None
) -> "Message":
"""Bound method *edit_caption* of :obj:`~pyrogram.types.Message`.
@@ -2558,6 +2604,9 @@ class Message(Object, Update):
Pass "html" to enable HTML-style parsing only.
Pass None to completely disable style parsing.
+ caption_entities (List of :obj:`~pyrogram.types.MessageEntity`):
+ List of special entities that appear in the caption, which can be specified instead of __parse_mode__.
+
reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
@@ -2572,6 +2621,7 @@ class Message(Object, Update):
message_id=self.message_id,
caption=caption,
parse_mode=parse_mode,
+ caption_entities=caption_entities,
reply_markup=reply_markup
)
diff --git a/pyrogram/types/messages_and_media/message_entity.py b/pyrogram/types/messages_and_media/message_entity.py
index a88a91c8..0dd13d70 100644
--- a/pyrogram/types/messages_and_media/message_entity.py
+++ b/pyrogram/types/messages_and_media/message_entity.py
@@ -16,12 +16,60 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from enum import Enum, auto
+
import pyrogram
from pyrogram import raw
from pyrogram import types
from ..object import Object
+class AutoName(Enum):
+ def _generate_next_value_(self, *args):
+ return self.lower()
+
+
+class MessageEntityType(AutoName):
+ MENTION = auto()
+ HASHTAG = auto()
+ CASHTAG = auto()
+ BOT_COMMAND = auto()
+ URL = auto()
+ EMAIL = auto()
+ PHONE_NUMBER = auto()
+ BOLD = auto()
+ ITALIC = auto()
+ UNDERLINE = auto()
+ STRIKETHROUGH = auto()
+ CODE = auto()
+ PRE = auto()
+ TEXT_LINK = auto()
+ TEXT_MENTION = auto()
+ BLOCKQUOTE = auto()
+
+
+RAW_ENTITIES_TO_TYPE = {
+ raw.types.MessageEntityMention: MessageEntityType.MENTION,
+ raw.types.MessageEntityHashtag: MessageEntityType.HASHTAG,
+ raw.types.MessageEntityCashtag: MessageEntityType.CASHTAG,
+ raw.types.MessageEntityBotCommand: MessageEntityType.BOT_COMMAND,
+ raw.types.MessageEntityUrl: MessageEntityType.URL,
+ raw.types.MessageEntityEmail: MessageEntityType.EMAIL,
+ raw.types.MessageEntityBold: MessageEntityType.BOLD,
+ raw.types.MessageEntityItalic: MessageEntityType.ITALIC,
+ raw.types.MessageEntityCode: MessageEntityType.CODE,
+ raw.types.MessageEntityPre: MessageEntityType.PRE,
+ raw.types.MessageEntityUnderline: MessageEntityType.UNDERLINE,
+ raw.types.MessageEntityStrike: MessageEntityType.STRIKETHROUGH,
+ raw.types.MessageEntityBlockquote: MessageEntityType.BLOCKQUOTE,
+ raw.types.MessageEntityTextUrl: MessageEntityType.TEXT_LINK,
+ raw.types.MessageEntityMentionName: MessageEntityType.TEXT_MENTION,
+ raw.types.MessageEntityPhone: MessageEntityType.PHONE_NUMBER
+}
+
+TYPE_TO_RAW_ENTITIES = {v.value: k for k, v in RAW_ENTITIES_TO_TYPE.items()}
+
+
class MessageEntity(Object):
"""One special entity in a text message.
For example, hashtags, usernames, URLs, etc.
@@ -29,9 +77,12 @@ class MessageEntity(Object):
Parameters:
type (``str``):
Type of the entity.
- Can be "mention" (@username), "hashtag", "cashtag", "bot_command", "url", "email", "phone_number", "bold"
- (bold text), "italic" (italic text), "code" (monowidth string), "pre" (monowidth block), "text_link"
- (for clickable text URLs), "text_mention" (for custom text mentions based on users' identifiers).
+ Can be "mention" (``@username``), "hashtag" (``#hashtag``), "cashtag" (``$PYRO``),
+ "bot_command" (``/start@pyrogrambot``), "url" (``https://pyrogram.org``),
+ "email" (``do-not-reply@pyrogram.org``), "phone_number" (``+1-420-069-1337``), "bold" (**bold text**),
+ "italic" (*italic text*), "underline" (underlined text), "strikethrough" (strikethrough text),
+ "code" (monowidth string), "pre" (monowidth block), "text_link" (for clickable text URLs),
+ "text_mention" (for users without usernames).
offset (``int``):
Offset in UTF-16 code units to the start of the entity.
@@ -44,26 +95,10 @@ class MessageEntity(Object):
user (:obj:`~pyrogram.types.User`, *optional*):
For "text_mention" only, the mentioned user.
- """
- ENTITIES = {
- raw.types.MessageEntityMention.ID: "mention",
- raw.types.MessageEntityHashtag.ID: "hashtag",
- raw.types.MessageEntityCashtag.ID: "cashtag",
- raw.types.MessageEntityBotCommand.ID: "bot_command",
- raw.types.MessageEntityUrl.ID: "url",
- raw.types.MessageEntityEmail.ID: "email",
- raw.types.MessageEntityBold.ID: "bold",
- raw.types.MessageEntityItalic.ID: "italic",
- raw.types.MessageEntityCode.ID: "code",
- raw.types.MessageEntityPre.ID: "pre",
- raw.types.MessageEntityUnderline.ID: "underline",
- raw.types.MessageEntityStrike.ID: "strike",
- raw.types.MessageEntityBlockquote.ID: "blockquote",
- raw.types.MessageEntityTextUrl.ID: "text_link",
- raw.types.MessageEntityMentionName.ID: "text_mention",
- raw.types.MessageEntityPhone.ID: "phone_number"
- }
+ language (``str``. *optional*):
+ For "pre" only, the programming language of the entity text.
+ """
def __init__(
self,
@@ -73,7 +108,8 @@ class MessageEntity(Object):
offset: int,
length: int,
url: str = None,
- user: "types.User" = None
+ user: "types.User" = None,
+ language: str = None
):
super().__init__(client)
@@ -82,19 +118,49 @@ class MessageEntity(Object):
self.length = length
self.url = url
self.user = user
+ self.language = language
@staticmethod
def _parse(client, entity, users: dict) -> "MessageEntity" or None:
- type = MessageEntity.ENTITIES.get(entity.ID, None)
+ type = RAW_ENTITIES_TO_TYPE.get(entity.__class__, None)
if type is None:
return None
return MessageEntity(
- type=type,
+ type=type.value,
offset=entity.offset,
length=entity.length,
url=getattr(entity, "url", None),
user=types.User._parse(client, users.get(getattr(entity, "user_id", None), None)),
+ language=getattr(entity, "language", None),
client=client
)
+
+ async def write(self):
+ args = self.__dict__.copy()
+
+ for arg in ("_client", "type", "user"):
+ args.pop(arg)
+
+ if self.user:
+ args["user_id"] = await self._client.resolve_peer(self.user.id)
+
+ if not self.url:
+ args.pop("url")
+
+ if self.language is None:
+ args.pop("language")
+
+ try:
+ entity = TYPE_TO_RAW_ENTITIES[self.type]
+
+ if entity is raw.types.MessageEntityMentionName:
+ entity = raw.types.InputMessageEntityMentionName
+ except KeyError as e:
+ raise ValueError(f"Invalid message entity type {e}")
+ else:
+ try:
+ return entity(**args)
+ except TypeError as e:
+ raise TypeError(f"{entity.QUALNAME}'s {e}")
diff --git a/pyrogram/utils.py b/pyrogram/utils.py
index e0b79786..4c444533 100644
--- a/pyrogram/utils.py
+++ b/pyrogram/utils.py
@@ -24,9 +24,9 @@ import os
import struct
from concurrent.futures.thread import ThreadPoolExecutor
from getpass import getpass
-from typing import List
-from typing import Union
+from typing import Union, List, Dict
+import pyrogram
from pyrogram import raw
from pyrogram import types
from pyrogram.file_id import FileId, FileType, PHOTO_TYPES, DOCUMENT_TYPES
@@ -294,3 +294,24 @@ def compute_password_check(r: raw.types.account.Password, password: str) -> raw.
)
return raw.types.InputCheckPasswordSRP(srp_id=srp_id, A=A_bytes, M1=M1_bytes)
+
+
+async def parse_text_entities(
+ client: "pyrogram.Client",
+ text: str,
+ parse_mode: str,
+ entities: List["types.MessageEntity"]
+) -> Dict[str, raw.base.MessageEntity]:
+ if entities:
+ # Inject the client instance because parsing user mentions requires it
+ for entity in entities:
+ entity._client = client
+
+ text, entities = text, [await entity.write() for entity in entities]
+ else:
+ text, entities = (await client.parser.parse(text, parse_mode)).values()
+
+ return {
+ "message": text,
+ "entities": entities
+ }