Split text in several messages if it hits Telegram limits
This commit is contained in:
parent
af64241d81
commit
e05b0ebe46
@ -15,7 +15,7 @@ from aiohttp import web
|
|||||||
|
|
||||||
# Project modules
|
# Project modules
|
||||||
from api import TelegramBot, TelegramError
|
from api import TelegramBot, TelegramError
|
||||||
from utilities import get_secure_key, make_lines_of_buttons
|
from utilities import escape_html_chars, get_secure_key, make_lines_of_buttons
|
||||||
|
|
||||||
# Do not log aiohttp `INFO` and `DEBUG` levels
|
# Do not log aiohttp `INFO` and `DEBUG` levels
|
||||||
logging.getLogger('aiohttp').setLevel(logging.WARNING)
|
logging.getLogger('aiohttp').setLevel(logging.WARNING)
|
||||||
@ -36,6 +36,7 @@ class Bot(TelegramBot):
|
|||||||
"Please retry later...")
|
"Please retry later...")
|
||||||
_authorization_denied_message = None
|
_authorization_denied_message = None
|
||||||
_unknown_command_message = None
|
_unknown_command_message = None
|
||||||
|
TELEGRAM_MESSAGES_MAX_LEN = 4096
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, token, hostname='', certificate=None, max_connections=40,
|
self, token, hostname='', certificate=None, max_connections=40,
|
||||||
@ -604,8 +605,58 @@ class Bot(TelegramBot):
|
|||||||
"but this handler does nothing yet."
|
"but this handler does nothing yet."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def split_message_text(text, limit=None, parse_mode='HTML'):
|
||||||
|
r"""Split text if it hits telegram limits for text messages.
|
||||||
|
|
||||||
|
Split at `\n` if possible.
|
||||||
|
Add a `[...]` at the end and beginning of split messages,
|
||||||
|
with proper code markdown.
|
||||||
|
"""
|
||||||
|
if parse_mode == 'HTML':
|
||||||
|
text = escape_html_chars(text)
|
||||||
|
tags = (
|
||||||
|
('`', '`')
|
||||||
|
if parse_mode == 'Markdown'
|
||||||
|
else ('<code>', '</code>')
|
||||||
|
if parse_mode.lower() == 'html'
|
||||||
|
else ('', '')
|
||||||
|
)
|
||||||
|
if limit is None:
|
||||||
|
limit = Bot.TELEGRAM_MESSAGES_MAX_LEN - 100
|
||||||
|
# Example text: "lines\nin\nreversed\order"
|
||||||
|
text = text.split("\n")[::-1] # ['order', 'reversed', 'in', 'lines']
|
||||||
|
text_part_number = 0
|
||||||
|
while len(text) > 0:
|
||||||
|
temp = []
|
||||||
|
text_part_number += 1
|
||||||
|
while (
|
||||||
|
len(text) > 0
|
||||||
|
and len(
|
||||||
|
"\n".join(temp + [text[-1]])
|
||||||
|
) < limit
|
||||||
|
):
|
||||||
|
# Append lines of `text` in order (`.pop` returns the last
|
||||||
|
# line in text) until the addition of the next line would hit
|
||||||
|
# the `limit`.
|
||||||
|
temp.append(text.pop())
|
||||||
|
# If graceful split failed (last line was longer than limit)
|
||||||
|
if len(temp) == 0:
|
||||||
|
# Force split last line
|
||||||
|
temp.append(text[-1][:limit])
|
||||||
|
text[-1] = text[-1][limit:]
|
||||||
|
text_chunk = "\n".join(temp) # Re-join this group of lines
|
||||||
|
prefix, suffix = '', ''
|
||||||
|
is_last = len(text) > 0
|
||||||
|
if text_part_number > 1:
|
||||||
|
prefix = f"{tags[0]}[...]{tags[1]}\n"
|
||||||
|
if is_last:
|
||||||
|
suffix = f"\n{tags[0]}[...]{tags[1]}"
|
||||||
|
yield (prefix + text_chunk + suffix), is_last
|
||||||
|
return
|
||||||
|
|
||||||
async def send_message(self, chat_id=None, text=None,
|
async def send_message(self, chat_id=None, text=None,
|
||||||
parse_mode=None,
|
parse_mode='HTML',
|
||||||
disable_web_page_preview=None,
|
disable_web_page_preview=None,
|
||||||
disable_notification=None,
|
disable_notification=None,
|
||||||
reply_to_message_id=None,
|
reply_to_message_id=None,
|
||||||
@ -636,15 +687,26 @@ class Bot(TelegramBot):
|
|||||||
and text != self.authorization_denied_message
|
and text != self.authorization_denied_message
|
||||||
):
|
):
|
||||||
reply_markup = self.default_keyboard
|
reply_markup = self.default_keyboard
|
||||||
return await self.sendMessage(
|
if not text:
|
||||||
chat_id=chat_id,
|
return
|
||||||
|
parse_mode = str(parse_mode)
|
||||||
|
text_chunks = self.split_message_text(
|
||||||
text=text,
|
text=text,
|
||||||
|
limit=self.__class__.TELEGRAM_MESSAGES_MAX_LEN - 100,
|
||||||
|
parse_mode=parse_mode
|
||||||
|
)
|
||||||
|
for text_chunk, is_last in text_chunks:
|
||||||
|
_reply_markup = (reply_markup if is_last else None)
|
||||||
|
sent_message_update = await self.sendMessage(
|
||||||
|
chat_id=chat_id,
|
||||||
|
text=text_chunk,
|
||||||
parse_mode=parse_mode,
|
parse_mode=parse_mode,
|
||||||
disable_web_page_preview=disable_web_page_preview,
|
disable_web_page_preview=disable_web_page_preview,
|
||||||
disable_notification=disable_notification,
|
disable_notification=disable_notification,
|
||||||
reply_to_message_id=reply_to_message_id,
|
reply_to_message_id=reply_to_message_id,
|
||||||
reply_markup=reply_markup
|
reply_markup=_reply_markup
|
||||||
)
|
)
|
||||||
|
return sent_message_update
|
||||||
|
|
||||||
async def answer_inline_query(self,
|
async def answer_inline_query(self,
|
||||||
inline_query_id=None,
|
inline_query_id=None,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user