Fixed markup-entities parsing.

This commit is contained in:
Alex Root Junior 2018-07-15 21:00:35 +03:00
parent 3abb48537c
commit f52c59376d
2 changed files with 98 additions and 56 deletions

View file

@ -1,5 +1,6 @@
import datetime import datetime
import functools import functools
import sys
import typing import typing
from . import base from . import base
@ -21,6 +22,7 @@ from .video import Video
from .video_note import VideoNote from .video_note import VideoNote
from .voice import Voice from .voice import Voice
from ..utils import helper from ..utils import helper
from ..utils import markdown as md
class Message(base.TelegramObject): class Message(base.TelegramObject):
@ -157,6 +159,49 @@ class Message(base.TelegramObject):
if command: if command:
return command[1].strip() return command[1].strip()
def parse_entities(self, as_html=True):
"""
Text or caption formatted as HTML.
:return: str
"""
text = self.text or self.caption
if text is None:
raise TypeError("This message doesn't have any text.")
quote_fn = md.quote_html if as_html else md.escape_md
if not self.entities:
return quote_fn(text)
if not sys.maxunicode == 0xffff:
text = text.encode('utf-16-le')
result = ''
offset = 0
for entity in sorted(self.entities, key=lambda item: item.offset):
entity_text = entity.parse(text, as_html=as_html)
if sys.maxunicode == 0xffff:
part = text[offset:entity.offset]
result += quote_fn(part) + entity_text
else:
part = text[offset * 2:entity.offset * 2]
result += quote_fn(part.decode('utf-16-le')) + entity_text
offset = entity.offset + entity.length
if sys.maxunicode == 0xffff:
part = text[offset:]
result += quote_fn(part)
else:
part = text[offset * 2:]
result += quote_fn(part.decode('utf-16-le'))
return result
@property @property
def md_text(self) -> str: def md_text(self) -> str:
""" """
@ -164,28 +209,16 @@ class Message(base.TelegramObject):
:return: str :return: str
""" """
text = self.caption if self.caption else self.text return self.parse_entities(False)
if self.text and self.entities:
for entity in reversed(self.entities):
text = entity.apply_md(text)
return text
@property @property
def html_text(self) -> str: def html_text(self) -> str:
""" """
Text or caption formatted as HTML. Text or caption formatted as HTML
:return: str :return: str
""" """
text = self.caption if self.caption else self.text return self.parse_entities(True)
if self.text and self.entities:
for entity in reversed(self.entities):
text = entity.apply_html(text)
return text
async def reply(self, text, parse_mode=None, disable_web_page_preview=None, async def reply(self, text, parse_mode=None, disable_web_page_preview=None,
disable_notification=None, reply_markup=None, reply=True) -> 'Message': disable_notification=None, reply_markup=None, reply=True) -> 'Message':

View file

@ -1,3 +1,5 @@
import sys
from . import base from . import base
from . import fields from . import fields
from .user import User from .user import User
@ -16,56 +18,63 @@ class MessageEntity(base.TelegramObject):
url: base.String = fields.Field() url: base.String = fields.Field()
user: User = fields.Field(base=User) user: User = fields.Field(base=User)
def _apply(self, text, func): def get_text(self, text):
return text[:self.offset] + \
func(text[self.offset:self.offset + self.length]) + \
text[self.offset + self.length:]
def apply_md(self, text):
""" """
Apply entity for text as Markdown Get value of entity
:param text: :param text: full text
:return: :return: part of text
""" """
if self.type == MessageEntityType.BOLD: if sys.maxunicode == 0xffff:
return self._apply(text, markdown.bold) return text[self.offset:self.offset + self.length]
elif self.type == MessageEntityType.ITALIC:
return self._apply(text, markdown.italic) if not isinstance(text, bytes):
elif self.type == MessageEntityType.PRE: entity_text = text.encode('utf-16-le')
return self._apply(text, markdown.pre) else:
elif self.type == MessageEntityType.CODE: entity_text = text
return self._apply(text, markdown.code)
elif self.type == MessageEntityType.URL: entity_text = entity_text[self.offset * 2:(self.offset + self.length) * 2]
return self._apply(text, lambda url: markdown.link(url, url)) return entity_text.decode('utf-16-le')
elif self.type == MessageEntityType.TEXT_LINK:
return self._apply(text, lambda url: markdown.link(url, self.url)) def parse(self, text, as_html=True):
if self.type == MessageEntityType.TEXT_MENTION and self.user: """
return self._apply(text, lambda name: self.user.get_mention(name, as_html=False)) Get entity value with markup
:param text: original text
:param as_html: as html?
:return: entity text with markup
"""
if not text:
return text return text
entity_text = self.get_text(text)
def apply_html(self, text):
"""
Apply entity for text as HTML
:param text:
:return:
"""
if self.type == MessageEntityType.BOLD: if self.type == MessageEntityType.BOLD:
return self._apply(text, markdown.hbold) if as_html:
return markdown.hbold(entity_text)
return markdown.bold(entity_text)
elif self.type == MessageEntityType.ITALIC: elif self.type == MessageEntityType.ITALIC:
return self._apply(text, markdown.hitalic) if as_html:
return markdown.hitalic(entity_text)
return markdown.italic(entity_text)
elif self.type == MessageEntityType.PRE: elif self.type == MessageEntityType.PRE:
return self._apply(text, markdown.hpre) if as_html:
return markdown.hpre(entity_text)
return markdown.pre(entity_text)
elif self.type == MessageEntityType.CODE: elif self.type == MessageEntityType.CODE:
return self._apply(text, markdown.hcode) if as_html:
return markdown.hcode(entity_text)
return markdown.code(entity_text)
elif self.type == MessageEntityType.URL: elif self.type == MessageEntityType.URL:
return self._apply(text, lambda url: markdown.hlink(url, url)) if as_html:
return markdown.hlink(entity_text, entity_text)
return markdown.link(entity_text, entity_text)
elif self.type == MessageEntityType.TEXT_LINK: elif self.type == MessageEntityType.TEXT_LINK:
return self._apply(text, lambda url: markdown.hlink(url, self.url)) if as_html:
if self.type == MessageEntityType.TEXT_MENTION and self.user: return markdown.hlink(entity_text, self.url)
return self._apply(text, lambda name: self.user.get_mention(name, as_html=True)) return markdown.link(entity_text, self.url)
return text elif self.type == MessageEntityType.TEXT_MENTION and self.user:
return self.user.get_mention(entity_text)
return entity_text
class MessageEntityType(helper.Helper): class MessageEntityType(helper.Helper):