Skip to content

Api 7.4 collapsible block quotes #4286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions telegram/_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -4407,6 +4407,8 @@ def _parse_html(
insert = f'<a href="{escaped_text}">{escaped_text}</a>'
elif entity.type == MessageEntity.BLOCKQUOTE:
insert = f"<blockquote>{escaped_text}</blockquote>"
elif entity.type == MessageEntity.EXPANDABLE_BLOCKQUOTE:
insert = f"<blockquote expandable>{escaped_text}</blockquote>"
elif entity.type == MessageEntity.BOLD:
insert = f"<b>{escaped_text}</b>"
elif entity.type == MessageEntity.ITALIC:
Expand Down Expand Up @@ -4557,11 +4559,12 @@ def _parse_markdown(
) -> Optional[str]:
if version == 1:
for entity_type in (
MessageEntity.UNDERLINE,
MessageEntity.STRIKETHROUGH,
MessageEntity.SPOILER,
MessageEntity.EXPANDABLE_BLOCKQUOTE,
MessageEntity.BLOCKQUOTE,
MessageEntity.CUSTOM_EMOJI,
MessageEntity.SPOILER,
MessageEntity.STRIKETHROUGH,
MessageEntity.UNDERLINE,
):
if any(entity.type == entity_type for entity in entities):
name = entity_type.name.title().replace("_", " ") # type:ignore[attr-defined]
Expand Down Expand Up @@ -4641,8 +4644,10 @@ def _parse_markdown(
insert = f"~{escaped_text}~"
elif entity.type == MessageEntity.SPOILER:
insert = f"||{escaped_text}||"
elif entity.type == MessageEntity.BLOCKQUOTE:
elif entity.type in (MessageEntity.BLOCKQUOTE, MessageEntity.EXPANDABLE_BLOCKQUOTE):
insert = ">" + "\n>".join(escaped_text.splitlines())
if entity.type == MessageEntity.EXPANDABLE_BLOCKQUOTE:
insert = f"{insert}||"
elif entity.type == MessageEntity.CUSTOM_EMOJI:
# This should never be needed because ids are numeric but the documentation
# specifically mentions it so here we are
Expand Down
71 changes: 38 additions & 33 deletions telegram/_messageentity.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,50 +140,55 @@ def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["MessageEntit

return super().de_json(data=data, bot=bot)

MENTION: Final[str] = constants.MessageEntityType.MENTION
""":const:`telegram.constants.MessageEntityType.MENTION`"""
HASHTAG: Final[str] = constants.MessageEntityType.HASHTAG
""":const:`telegram.constants.MessageEntityType.HASHTAG`"""
CASHTAG: Final[str] = constants.MessageEntityType.CASHTAG
""":const:`telegram.constants.MessageEntityType.CASHTAG`"""
PHONE_NUMBER: Final[str] = constants.MessageEntityType.PHONE_NUMBER
""":const:`telegram.constants.MessageEntityType.PHONE_NUMBER`"""
ALL_TYPES: Final[List[str]] = list(constants.MessageEntityType)
"""List[:obj:`str`]: A list of all available message entity types."""
BLOCKQUOTE: Final[str] = constants.MessageEntityType.BLOCKQUOTE
""":const:`telegram.constants.MessageEntityType.BLOCKQUOTE`

.. versionadded:: 20.8
"""
BOLD: Final[str] = constants.MessageEntityType.BOLD
""":const:`telegram.constants.MessageEntityType.BOLD`"""
BOT_COMMAND: Final[str] = constants.MessageEntityType.BOT_COMMAND
""":const:`telegram.constants.MessageEntityType.BOT_COMMAND`"""
URL: Final[str] = constants.MessageEntityType.URL
""":const:`telegram.constants.MessageEntityType.URL`"""
CASHTAG: Final[str] = constants.MessageEntityType.CASHTAG
""":const:`telegram.constants.MessageEntityType.CASHTAG`"""
CODE: Final[str] = constants.MessageEntityType.CODE
""":const:`telegram.constants.MessageEntityType.CODE`"""
CUSTOM_EMOJI: Final[str] = constants.MessageEntityType.CUSTOM_EMOJI
""":const:`telegram.constants.MessageEntityType.CUSTOM_EMOJI`

.. versionadded:: 20.0
"""
EMAIL: Final[str] = constants.MessageEntityType.EMAIL
""":const:`telegram.constants.MessageEntityType.EMAIL`"""
BOLD: Final[str] = constants.MessageEntityType.BOLD
""":const:`telegram.constants.MessageEntityType.BOLD`"""
EXPANDABLE_BLOCKQUOTE: Final[str] = constants.MessageEntityType.EXPANDABLE_BLOCKQUOTE
""":const:`telegram.constants.MessageEntityType.EXPANDABLE_BLOCKQUOTE`

.. versionadded:: NEXT.VERSION
"""
HASHTAG: Final[str] = constants.MessageEntityType.HASHTAG
""":const:`telegram.constants.MessageEntityType.HASHTAG`"""
ITALIC: Final[str] = constants.MessageEntityType.ITALIC
""":const:`telegram.constants.MessageEntityType.ITALIC`"""
CODE: Final[str] = constants.MessageEntityType.CODE
""":const:`telegram.constants.MessageEntityType.CODE`"""
MENTION: Final[str] = constants.MessageEntityType.MENTION
""":const:`telegram.constants.MessageEntityType.MENTION`"""
PHONE_NUMBER: Final[str] = constants.MessageEntityType.PHONE_NUMBER
""":const:`telegram.constants.MessageEntityType.PHONE_NUMBER`"""
PRE: Final[str] = constants.MessageEntityType.PRE
""":const:`telegram.constants.MessageEntityType.PRE`"""
SPOILER: Final[str] = constants.MessageEntityType.SPOILER
""":const:`telegram.constants.MessageEntityType.SPOILER`

.. versionadded:: 13.10
"""
STRIKETHROUGH: Final[str] = constants.MessageEntityType.STRIKETHROUGH
""":const:`telegram.constants.MessageEntityType.STRIKETHROUGH`"""
TEXT_LINK: Final[str] = constants.MessageEntityType.TEXT_LINK
""":const:`telegram.constants.MessageEntityType.TEXT_LINK`"""
TEXT_MENTION: Final[str] = constants.MessageEntityType.TEXT_MENTION
""":const:`telegram.constants.MessageEntityType.TEXT_MENTION`"""
UNDERLINE: Final[str] = constants.MessageEntityType.UNDERLINE
""":const:`telegram.constants.MessageEntityType.UNDERLINE`"""
STRIKETHROUGH: Final[str] = constants.MessageEntityType.STRIKETHROUGH
""":const:`telegram.constants.MessageEntityType.STRIKETHROUGH`"""
SPOILER: Final[str] = constants.MessageEntityType.SPOILER
""":const:`telegram.constants.MessageEntityType.SPOILER`

.. versionadded:: 13.10
"""
CUSTOM_EMOJI: Final[str] = constants.MessageEntityType.CUSTOM_EMOJI
""":const:`telegram.constants.MessageEntityType.CUSTOM_EMOJI`

.. versionadded:: 20.0
"""
BLOCKQUOTE: Final[str] = constants.MessageEntityType.BLOCKQUOTE
""":const:`telegram.constants.MessageEntityType.BLOCKQUOTE`

.. versionadded:: 20.8
"""
ALL_TYPES: Final[List[str]] = list(constants.MessageEntityType)
"""List[:obj:`str`]: A list of all available message entity types."""
URL: Final[str] = constants.MessageEntityType.URL
""":const:`telegram.constants.MessageEntityType.URL`"""
61 changes: 33 additions & 28 deletions telegram/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -1630,48 +1630,53 @@ class MessageEntityType(StringEnum):

__slots__ = ()

MENTION = "mention"
""":obj:`str`: Message entities representing a mention."""
HASHTAG = "hashtag"
""":obj:`str`: Message entities representing a hashtag."""
CASHTAG = "cashtag"
""":obj:`str`: Message entities representing a cashtag."""
PHONE_NUMBER = "phone_number"
""":obj:`str`: Message entities representing a phone number."""
BLOCKQUOTE = "blockquote"
""":obj:`str`: Message entities representing a block quotation.

.. versionadded:: 20.8
"""
BOLD = "bold"
""":obj:`str`: Message entities representing bold text."""
BOT_COMMAND = "bot_command"
""":obj:`str`: Message entities representing a bot command."""
URL = "url"
""":obj:`str`: Message entities representing a url."""
CASHTAG = "cashtag"
""":obj:`str`: Message entities representing a cashtag."""
CODE = "code"
""":obj:`str`: Message entities representing monowidth string."""
CUSTOM_EMOJI = "custom_emoji"
""":obj:`str`: Message entities representing inline custom emoji stickers.

.. versionadded:: 20.0
"""
EMAIL = "email"
""":obj:`str`: Message entities representing a email."""
BOLD = "bold"
""":obj:`str`: Message entities representing bold text."""
EXPANDABLE_BLOCKQUOTE = "expandable_blockquote"
""":obj:`str`: Message entities representing collapsed-by-default block quotation.

.. versionadded:: NEXT.VERSION
"""
HASHTAG = "hashtag"
""":obj:`str`: Message entities representing a hashtag."""
ITALIC = "italic"
""":obj:`str`: Message entities representing italic text."""
CODE = "code"
""":obj:`str`: Message entities representing monowidth string."""
MENTION = "mention"
""":obj:`str`: Message entities representing a mention."""
PHONE_NUMBER = "phone_number"
""":obj:`str`: Message entities representing a phone number."""
PRE = "pre"
""":obj:`str`: Message entities representing monowidth block."""
SPOILER = "spoiler"
""":obj:`str`: Message entities representing spoiler text."""
STRIKETHROUGH = "strikethrough"
""":obj:`str`: Message entities representing strikethrough text."""
TEXT_LINK = "text_link"
""":obj:`str`: Message entities representing clickable text URLs."""
TEXT_MENTION = "text_mention"
""":obj:`str`: Message entities representing text mention for users without usernames."""
UNDERLINE = "underline"
""":obj:`str`: Message entities representing underline text."""
STRIKETHROUGH = "strikethrough"
""":obj:`str`: Message entities representing strikethrough text."""
SPOILER = "spoiler"
""":obj:`str`: Message entities representing spoiler text."""
CUSTOM_EMOJI = "custom_emoji"
""":obj:`str`: Message entities representing inline custom emoji stickers.

.. versionadded:: 20.0
"""
BLOCKQUOTE = "blockquote"
""":obj:`str`: Message entities representing a block quotation.

.. versionadded:: 20.8
"""
URL = "url"
""":obj:`str`: Message entities representing a url."""


class MessageLimit(IntEnum):
Expand Down
33 changes: 27 additions & 6 deletions tests/test_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,12 @@ class TestMessageBase:
{"length": 2, "offset": 150, "type": "custom_emoji", "custom_emoji_id": "1"},
{"length": 34, "offset": 154, "type": "blockquote"},
{"length": 6, "offset": 181, "type": "bold"},
{"length": 33, "offset": 190, "type": "expandable_blockquote"},
]
test_text_v2 = (
r"Test for <bold, ita_lic, \`code, links, text-mention and `\pre. "
"http://google.com and bold nested in strk>trgh nested in italic. Python pre. Spoiled. "
"👍.\nMultiline\nblock quote\nwith nested."
"👍.\nMultiline\nblock quote\nwith nested.\n\nMultiline\nexpandable\nblock quote."
)
test_message = Message(
message_id=1,
Expand Down Expand Up @@ -732,7 +733,8 @@ def test_text_html_simple(self):
'<pre><code class="python">Python pre</code></pre>. '
'<span class="tg-spoiler">Spoiled</span>. '
'<tg-emoji emoji-id="1">👍</tg-emoji>.\n'
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>"
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>\n\n"
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>"
)
text_html = self.test_message_v2.text_html
assert text_html == test_html_string
Expand All @@ -753,7 +755,8 @@ def test_text_html_urled(self):
'<pre><code class="python">Python pre</code></pre>. '
'<span class="tg-spoiler">Spoiled</span>. '
'<tg-emoji emoji-id="1">👍</tg-emoji>.\n'
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>"
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>\n\n"
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>"
)
text_html = self.test_message_v2.text_html_urled
assert text_html == test_html_string
Expand All @@ -778,6 +781,9 @@ def test_text_markdown_v2_simple(self):
">Multiline\n"
">block quote\n"
r">with *nested*\."
"\n\n>Multiline\n"
">expandable\n"
r">block quote\.||"
)
text_markdown = self.test_message_v2.text_markdown_v2
assert text_markdown == test_md_string
Expand Down Expand Up @@ -834,6 +840,9 @@ def test_text_markdown_v2_urled(self):
">Multiline\n"
">block quote\n"
r">with *nested*\."
"\n\n>Multiline\n"
">expandable\n"
r">block quote\.||"
)
text_markdown = self.test_message_v2.text_markdown_v2_urled
assert text_markdown == test_md_string
Expand Down Expand Up @@ -950,7 +959,8 @@ def test_caption_html_simple(self):
'<pre><code class="python">Python pre</code></pre>. '
'<span class="tg-spoiler">Spoiled</span>. '
'<tg-emoji emoji-id="1">👍</tg-emoji>.\n'
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>"
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>\n\n"
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>"
)
caption_html = self.test_message_v2.caption_html
assert caption_html == test_html_string
Expand All @@ -971,7 +981,8 @@ def test_caption_html_urled(self):
'<pre><code class="python">Python pre</code></pre>. '
'<span class="tg-spoiler">Spoiled</span>. '
'<tg-emoji emoji-id="1">👍</tg-emoji>.\n'
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>"
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>\n\n"
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>"
)
caption_html = self.test_message_v2.caption_html_urled
assert caption_html == test_html_string
Expand All @@ -996,6 +1007,9 @@ def test_caption_markdown_v2_simple(self):
">Multiline\n"
">block quote\n"
r">with *nested*\."
"\n\n>Multiline\n"
">expandable\n"
r">block quote\.||"
)
caption_markdown = self.test_message_v2.caption_markdown_v2
assert caption_markdown == test_md_string
Expand Down Expand Up @@ -1027,6 +1041,9 @@ def test_caption_markdown_v2_urled(self):
">Multiline\n"
">block quote\n"
r">with *nested*\."
"\n\n>Multiline\n"
">expandable\n"
r">block quote\.||"
)
caption_markdown = self.test_message_v2.caption_markdown_v2_urled
assert caption_markdown == test_md_string
Expand Down Expand Up @@ -1488,6 +1505,9 @@ async def test_reply_markdown_v2(self, monkeypatch, message):
">Multiline\n"
">block quote\n"
r">with *nested*\."
"\n\n>Multiline\n"
">expandable\n"
r">block quote\.||"
)

async def make_assertion(*_, **kwargs):
Expand Down Expand Up @@ -1538,7 +1558,8 @@ async def test_reply_html(self, monkeypatch, message):
'<pre><code class="python">Python pre</code></pre>. '
'<span class="tg-spoiler">Spoiled</span>. '
'<tg-emoji emoji-id="1">👍</tg-emoji>.\n'
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>"
"<blockquote>Multiline\nblock quote\nwith <b>nested</b>.</blockquote>\n\n"
"<blockquote expandable>Multiline\nexpandable\nblock quote.</blockquote>"
)

async def make_assertion(*_, **kwargs):
Expand Down