mirror of
https://github.com/pyrogram/pyrogram
synced 2025-08-28 12:57:52 +00:00
Merge branch 'html_style' into docs
This commit is contained in:
commit
6584e99cae
@ -23,3 +23,4 @@ __version__ = "0.4.2"
|
||||
from .api.errors import Error
|
||||
from .client import ChatAction
|
||||
from .client import Client
|
||||
from .client import ParseMode
|
||||
|
@ -18,3 +18,4 @@
|
||||
|
||||
from .chat_action import ChatAction
|
||||
from .client import Client
|
||||
from .parse_mode import ParseMode
|
||||
|
@ -47,8 +47,8 @@ from pyrogram.api.types import (
|
||||
InputPeerUser, InputPeerChat, InputPeerChannel
|
||||
)
|
||||
from pyrogram.crypto import CTR
|
||||
from pyrogram.extensions import Markdown
|
||||
from pyrogram.session import Auth, Session
|
||||
from .style import Markdown, HTML
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -89,6 +89,7 @@ class Client:
|
||||
self.peers_by_username = {}
|
||||
|
||||
self.markdown = Markdown(self.peers_by_id)
|
||||
self.html = HTML(self.peers_by_id)
|
||||
|
||||
self.config = None
|
||||
self.proxy = None
|
||||
@ -471,6 +472,7 @@ class Client:
|
||||
def send_message(self,
|
||||
chat_id: int or str,
|
||||
text: str,
|
||||
parse_mode: str = "",
|
||||
disable_web_page_preview: bool = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_msg_id: int = None):
|
||||
@ -485,6 +487,11 @@ class Client:
|
||||
text (:obj:`str`):
|
||||
Text of the message to be sent.
|
||||
|
||||
parse_mode (:obj:`str`):
|
||||
Use :obj:`pyrogram.ParseMode.MARKDOWN` or :obj:`pyrogram.ParseMode.HTML` if you want Telegram apps
|
||||
to show bold, italic, fixed-width text or inline URLs in your message.
|
||||
Defaults to MARKDOWN.
|
||||
|
||||
disable_web_page_preview (:obj:`bool`, optional):
|
||||
Disables link previews for links in this message.
|
||||
|
||||
@ -501,6 +508,8 @@ class Client:
|
||||
Raises:
|
||||
:class:`pyrogram.Error`
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
|
||||
return self.send(
|
||||
functions.messages.SendMessage(
|
||||
peer=self.resolve_peer(chat_id),
|
||||
@ -508,7 +517,7 @@ class Client:
|
||||
silent=disable_notification or None,
|
||||
reply_to_msg_id=reply_to_msg_id,
|
||||
random_id=self.rnd_id(),
|
||||
**self.markdown.parse(text)
|
||||
**style.parse(text)
|
||||
)
|
||||
)
|
||||
|
||||
@ -557,6 +566,7 @@ class Client:
|
||||
chat_id: int or str,
|
||||
photo: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
ttl_seconds: int = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None):
|
||||
@ -575,6 +585,11 @@ class Client:
|
||||
caption (:obj:`bool`, optional):
|
||||
Photo caption, 0-200 characters.
|
||||
|
||||
parse_mode (:obj:`str`):
|
||||
Use :obj:`pyrogram.ParseMode.MARKDOWN` or :obj:`pyrogram.ParseMode.HTML` if you want Telegram apps
|
||||
to show bold, italic, fixed-width text or inline URLs in your caption.
|
||||
Defaults to MARKDOWN.
|
||||
|
||||
ttl_seconds (:obj:`int`, optional):
|
||||
Self-Destruct Timer.
|
||||
If you set a timer, the photo will self-destruct in :obj:`ttl_seconds`
|
||||
@ -593,6 +608,7 @@ class Client:
|
||||
Raises:
|
||||
:class:`pyrogram.Error`
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
file = self.save_file(photo)
|
||||
|
||||
while True:
|
||||
@ -607,7 +623,7 @@ class Client:
|
||||
silent=disable_notification or None,
|
||||
reply_to_msg_id=reply_to_message_id,
|
||||
random_id=self.rnd_id(),
|
||||
**self.markdown.parse(caption)
|
||||
**style.parse(caption)
|
||||
)
|
||||
)
|
||||
except FilePartMissing as e:
|
||||
@ -619,6 +635,7 @@ class Client:
|
||||
chat_id: int or str,
|
||||
audio: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
duration: int = 0,
|
||||
performer: str = None,
|
||||
title: str = None,
|
||||
@ -641,6 +658,11 @@ class Client:
|
||||
caption (:obj:`str`, optional):
|
||||
Audio caption, 0-200 characters.
|
||||
|
||||
parse_mode (:obj:`str`):
|
||||
Use :obj:`pyrogram.ParseMode.MARKDOWN` or :obj:`pyrogram.ParseMode.HTML` if you want Telegram apps
|
||||
to show bold, italic, fixed-width text or inline URLs in your caption.
|
||||
Defaults to MARKDOWN.
|
||||
|
||||
duration (:obj:`int`, optional):
|
||||
Duration of the audio in seconds.
|
||||
|
||||
@ -663,6 +685,7 @@ class Client:
|
||||
Raises:
|
||||
:class:`pyrogram.Error`
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
file = self.save_file(audio)
|
||||
|
||||
while True:
|
||||
@ -685,7 +708,7 @@ class Client:
|
||||
silent=disable_notification or None,
|
||||
reply_to_msg_id=reply_to_message_id,
|
||||
random_id=self.rnd_id(),
|
||||
**self.markdown.parse(caption)
|
||||
**style.parse(caption)
|
||||
)
|
||||
)
|
||||
except FilePartMissing as e:
|
||||
@ -697,6 +720,7 @@ class Client:
|
||||
chat_id: int or str,
|
||||
document: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None):
|
||||
"""Use this method to send general files.
|
||||
@ -714,6 +738,11 @@ class Client:
|
||||
caption (:obj:`str`, optional):
|
||||
Document caption, 0-200 characters.
|
||||
|
||||
parse_mode (:obj:`str`):
|
||||
Use :obj:`pyrogram.ParseMode.MARKDOWN` or :obj:`pyrogram.ParseMode.HTML` if you want Telegram apps
|
||||
to show bold, italic, fixed-width text or inline URLs in your caption.
|
||||
Defaults to MARKDOWN.
|
||||
|
||||
disable_notification (:obj:`bool`, optional):
|
||||
Sends the message silently.
|
||||
Users will receive a notification with no sound.
|
||||
@ -727,6 +756,7 @@ class Client:
|
||||
Raises:
|
||||
:class:`pyrogram.Error`
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
file = self.save_file(document)
|
||||
|
||||
while True:
|
||||
@ -744,7 +774,7 @@ class Client:
|
||||
silent=disable_notification or None,
|
||||
reply_to_msg_id=reply_to_message_id,
|
||||
random_id=self.rnd_id(),
|
||||
**self.markdown.parse(caption)
|
||||
**style.parse(caption)
|
||||
)
|
||||
)
|
||||
except FilePartMissing as e:
|
||||
@ -755,10 +785,11 @@ class Client:
|
||||
def send_video(self,
|
||||
chat_id: int or str,
|
||||
video: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
duration: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
caption: str = "",
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None):
|
||||
"""Use this method to send video files.
|
||||
@ -773,6 +804,14 @@ class Client:
|
||||
Video to send.
|
||||
Pass a file path as string to send a video that exists on your local machine.
|
||||
|
||||
caption (:obj:`str`, optional):
|
||||
Video caption, 0-200 characters.
|
||||
|
||||
parse_mode (:obj:`str`):
|
||||
Use :obj:`pyrogram.ParseMode.MARKDOWN` or :obj:`pyrogram.ParseMode.HTML` if you want Telegram apps
|
||||
to show bold, italic, fixed-width text or inline URLs in your caption.
|
||||
Defaults to MARKDOWN.
|
||||
|
||||
duration (:obj:`int`, optional):
|
||||
Duration of sent video in seconds.
|
||||
|
||||
@ -782,9 +821,6 @@ class Client:
|
||||
height (:obj:`int`, optional):
|
||||
Video height.
|
||||
|
||||
caption (:obj:`str`, optional):
|
||||
Video caption, 0-200 characters.
|
||||
|
||||
disable_notification (:obj:`bool`, optional):
|
||||
Sends the message silently.
|
||||
Users will receive a notification with no sound.
|
||||
@ -798,6 +834,7 @@ class Client:
|
||||
Raises:
|
||||
:class:`pyrogram.Error`
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
file = self.save_file(video)
|
||||
|
||||
while True:
|
||||
@ -819,7 +856,7 @@ class Client:
|
||||
silent=disable_notification or None,
|
||||
reply_to_msg_id=reply_to_message_id,
|
||||
random_id=self.rnd_id(),
|
||||
**self.markdown.parse(caption)
|
||||
**style.parse(caption)
|
||||
)
|
||||
)
|
||||
except FilePartMissing as e:
|
||||
@ -831,6 +868,7 @@ class Client:
|
||||
chat_id: int or str,
|
||||
voice: str,
|
||||
caption: str = "",
|
||||
parse_mode: str = "",
|
||||
duration: int = 0,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None):
|
||||
@ -849,6 +887,11 @@ class Client:
|
||||
caption (:obj:`str`, optional):
|
||||
Voice message caption, 0-200 characters.
|
||||
|
||||
parse_mode (:obj:`str`):
|
||||
Use :obj:`pyrogram.ParseMode.MARKDOWN` or :obj:`pyrogram.ParseMode.HTML` if you want Telegram apps
|
||||
to show bold, italic, fixed-width text or inline URLs in your caption.
|
||||
Defaults to MARKDOWN.
|
||||
|
||||
duration (:obj:`int`, optional):
|
||||
Duration of the voice message in seconds.
|
||||
|
||||
@ -865,6 +908,7 @@ class Client:
|
||||
Raises:
|
||||
:class:`pyrogram.Error`
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
file = self.save_file(voice)
|
||||
|
||||
while True:
|
||||
@ -885,7 +929,7 @@ class Client:
|
||||
silent=disable_notification or None,
|
||||
reply_to_msg_id=reply_to_message_id,
|
||||
random_id=self.rnd_id(),
|
||||
**self.markdown.parse(caption)
|
||||
**style.parse(caption)
|
||||
)
|
||||
)
|
||||
except FilePartMissing as e:
|
||||
@ -1192,6 +1236,7 @@ class Client:
|
||||
chat_id: int or str,
|
||||
message_id: int,
|
||||
text: str,
|
||||
parse_mode: str = "",
|
||||
disable_web_page_preview: bool = None):
|
||||
"""Use this method to edit text messages.
|
||||
|
||||
@ -1207,25 +1252,33 @@ class Client:
|
||||
text (:obj:`str`):
|
||||
New text of the message.
|
||||
|
||||
parse_mode (:obj:`str`):
|
||||
Use :obj:`pyrogram.ParseMode.MARKDOWN` or :obj:`pyrogram.ParseMode.HTML` if you want Telegram apps
|
||||
to show bold, italic, fixed-width text or inline URLs in your message.
|
||||
Defaults to MARKDOWN.
|
||||
|
||||
disable_web_page_preview (:obj:`bool`, optional):
|
||||
Disables link previews for links in this message.
|
||||
|
||||
Raises:
|
||||
:class:`pyrogram.Error`
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
|
||||
return self.send(
|
||||
functions.messages.EditMessage(
|
||||
peer=self.resolve_peer(chat_id),
|
||||
id=message_id,
|
||||
no_webpage=disable_web_page_preview or None,
|
||||
**self.markdown.parse(text)
|
||||
**style.parse(text)
|
||||
)
|
||||
)
|
||||
|
||||
def edit_message_caption(self,
|
||||
chat_id: int or str,
|
||||
message_id: int,
|
||||
caption: str):
|
||||
caption: str,
|
||||
parse_mode: str = ""):
|
||||
"""Use this method to edit captions of messages.
|
||||
|
||||
Args:
|
||||
@ -1240,14 +1293,21 @@ class Client:
|
||||
caption (:obj:`str`):
|
||||
New caption of the message.
|
||||
|
||||
parse_mode (:obj:`str`):
|
||||
Use :obj:`pyrogram.ParseMode.MARKDOWN` or :obj:`pyrogram.ParseMode.HTML` if you want Telegram apps
|
||||
to show bold, italic, fixed-width text or inline URLs in your caption.
|
||||
Defaults to MARKDOWN.
|
||||
|
||||
Raises:
|
||||
:class:`pyrogram.Error`
|
||||
"""
|
||||
style = self.html if parse_mode.lower() == "html" else self.markdown
|
||||
|
||||
return self.send(
|
||||
functions.messages.EditMessage(
|
||||
peer=self.resolve_peer(chat_id),
|
||||
id=message_id,
|
||||
**self.markdown.parse(caption)
|
||||
**style.parse(caption)
|
||||
)
|
||||
)
|
||||
|
||||
|
29
pyrogram/client/parse_mode.py
Normal file
29
pyrogram/client/parse_mode.py
Normal file
@ -0,0 +1,29 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 Dan Tès <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/>.
|
||||
|
||||
|
||||
class ParseMode:
|
||||
"""This class provides a convenient access to parse modes.
|
||||
It is intended to be used with any method that accepts the optional argument **parse_mode**
|
||||
"""
|
||||
|
||||
HTML = "html"
|
||||
"""Set the parse mode to HTML style"""
|
||||
|
||||
MARKDOWN = "markdown"
|
||||
"""Set the parse mode to Markdown style"""
|
@ -16,4 +16,5 @@
|
||||
# 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 .html import HTML
|
||||
from .markdown import Markdown
|
82
pyrogram/client/style/html.py
Normal file
82
pyrogram/client/style/html.py
Normal file
@ -0,0 +1,82 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 Dan Tès <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 re
|
||||
|
||||
from pyrogram.api.types import (
|
||||
MessageEntityBold as Bold,
|
||||
MessageEntityItalic as Italic,
|
||||
MessageEntityCode as Code,
|
||||
MessageEntityTextUrl as Url,
|
||||
MessageEntityPre as Pre,
|
||||
MessageEntityMentionName as MentionInvalid,
|
||||
InputMessageEntityMentionName as Mention,
|
||||
)
|
||||
from . import utils
|
||||
|
||||
|
||||
class HTML:
|
||||
SMP_RE = re.compile(r"[\U00010000-\U0010FFFF]")
|
||||
HTML_RE = re.compile(r"<(\w+)(?: href=\"(.*)\")?>(.*)</\1>")
|
||||
MENTION_RE = re.compile(r"tg://user\?id=(\d+)")
|
||||
|
||||
def __init__(self, peers_by_id):
|
||||
self.peers_by_id = peers_by_id
|
||||
|
||||
def parse(self, text):
|
||||
entities = []
|
||||
text = utils.add_surrogates(text)
|
||||
offset = 0
|
||||
|
||||
for match in self.HTML_RE.finditer(text):
|
||||
start = match.start() - offset
|
||||
style, url, body = match.groups()
|
||||
|
||||
if url:
|
||||
mention = self.MENTION_RE.match(url)
|
||||
|
||||
if mention:
|
||||
user_id = int(mention.group(1))
|
||||
input_user = self.peers_by_id.get(user_id, None)
|
||||
|
||||
entity = (
|
||||
Mention(start, len(body), input_user)
|
||||
if input_user else MentionInvalid(start, len(body), user_id)
|
||||
)
|
||||
else:
|
||||
entity = Url(start, len(body), url)
|
||||
else:
|
||||
if style == "b" or style == "strong":
|
||||
entity = Bold(start, len(body))
|
||||
elif style == "i" or style == "em":
|
||||
entity = Italic(start, len(body))
|
||||
elif style == "code":
|
||||
entity = Code(start, len(body))
|
||||
elif style == "pre":
|
||||
entity = Pre(start, len(body), "")
|
||||
else:
|
||||
continue
|
||||
|
||||
entities.append(entity)
|
||||
text = text.replace(match.group(), body)
|
||||
offset += len(style) * 2 + 5 + (len(url) + 8 if url else 0)
|
||||
|
||||
return dict(
|
||||
message=utils.remove_surrogates(text),
|
||||
entities=entities
|
||||
)
|
@ -17,7 +17,6 @@
|
||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import re
|
||||
from struct import unpack
|
||||
|
||||
from pyrogram.api.types import (
|
||||
MessageEntityBold as Bold,
|
||||
@ -27,6 +26,7 @@ from pyrogram.api.types import (
|
||||
MessageEntityPre as Pre,
|
||||
InputMessageEntityMentionName as Mention
|
||||
)
|
||||
from . import utils
|
||||
|
||||
|
||||
class Markdown:
|
||||
@ -36,9 +36,6 @@ class Markdown:
|
||||
"`": Code
|
||||
}
|
||||
|
||||
# SMP = Supplementary Multilingual Plane: https://en.wikipedia.org/wiki/Plane_(Unicode)#Overview
|
||||
SMP_RE = re.compile(r"[\U00010000-\U0010FFFF]")
|
||||
|
||||
# ``` python
|
||||
# for i in range(10):
|
||||
# print(i)
|
||||
@ -69,26 +66,12 @@ class Markdown:
|
||||
|
||||
MARKDOWN_RE = re.compile("|".join([PRE_RE, MENTION_RE, URL_RE, INLINE_RE]))
|
||||
|
||||
@classmethod
|
||||
def add_surrogates(cls, text):
|
||||
# Replace each SMP code point with a surrogate pair
|
||||
return cls.SMP_RE.sub(
|
||||
lambda match: # Split SMP in two surrogates
|
||||
"".join(chr(i) for i in unpack("<HH", match.group().encode("utf-16le"))),
|
||||
text
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def remove_surrogates(text):
|
||||
# Replace each surrogate pair with a SMP code point
|
||||
return text.encode("utf-16", "surrogatepass").decode("utf-16")
|
||||
|
||||
def __init__(self, peers_by_id):
|
||||
self.peers_by_id = peers_by_id
|
||||
|
||||
def parse(self, text):
|
||||
entities = []
|
||||
text = self.add_surrogates(text)
|
||||
text = utils.add_surrogates(text)
|
||||
offset = 0
|
||||
|
||||
for match in self.MARKDOWN_RE.finditer(text):
|
||||
@ -130,6 +113,6 @@ class Markdown:
|
||||
text = text.replace(pattern, replace)
|
||||
|
||||
return dict(
|
||||
message=self.remove_surrogates(text),
|
||||
message=utils.remove_surrogates(text),
|
||||
entities=entities
|
||||
)
|
37
pyrogram/client/style/utils.py
Normal file
37
pyrogram/client/style/utils.py
Normal file
@ -0,0 +1,37 @@
|
||||
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||
# Copyright (C) 2017-2018 Dan Tès <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 re
|
||||
from struct import unpack
|
||||
|
||||
# SMP = Supplementary Multilingual Plane: https://en.wikipedia.org/wiki/Plane_(Unicode)#Overview
|
||||
SMP_RE = re.compile(r"[\U00010000-\U0010FFFF]")
|
||||
|
||||
|
||||
def add_surrogates(text):
|
||||
# Replace each SMP code point with a surrogate pair
|
||||
return SMP_RE.sub(
|
||||
lambda match: # Split SMP in two surrogates
|
||||
"".join(chr(i) for i in unpack("<HH", match.group().encode("utf-16le"))),
|
||||
text
|
||||
)
|
||||
|
||||
|
||||
def remove_surrogates(text):
|
||||
# Replace each surrogate pair with a SMP code point
|
||||
return text.encode("utf-16", "surrogatepass").decode("utf-16")
|
Loading…
x
Reference in New Issue
Block a user