2
0
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:
Dan 2018-01-23 15:35:37 +01:00
commit 6584e99cae
8 changed files with 228 additions and 34 deletions

View File

@ -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

View File

@ -18,3 +18,4 @@
from .chat_action import ChatAction
from .client import Client
from .parse_mode import ParseMode

View File

@ -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)
)
)

View 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"""

View File

@ -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

View 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
)

View File

@ -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
)

View 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")