Сообщить об ошибке.

Форматирование и отправка сообщений в python-telegram-bot

Представленные здесь фрагменты кода форматирования/отправки сообщений в Telegram применяются как к автоматическому способу получения обновлений (при помощи telegram.ext), так и к ручному (пользовательскому).

Внимание! Пакеты python-telegram-bot версии 13.x будут придерживаться многопоточной парадигмы программирования (*на данный момент актуальна версия 13.15). Пакеты версий 20.x и новее предоставляют чистый асинхронный Python интерфейс для Telegram Bot API. Дополнительно смотрите основные изменения в пакете python-telegram-bot версии 20.x.

Если используется подмодуль telegram.ext, то можно получить chat_id в функции обратного вызова обработчика с помощью метода update.message.chat_id. Напоминаем, что в функцию обратного вызова обработчика автоматически передаются объекты update и context в качестве аргументов. Доступ к экземпляру bot можно получить из объекта context. Например, для отправки текстового сообщения: context.bot.send_message().

Примечание. Как правило, можно отправлять сообщения пользователям, передавая их идентификатор пользователя в качестве chat_id. Если у бота есть чат с пользователем, то он отправит сообщение в этот чат.

Содержание:


Варианты отправки сообщений в Telegram.

Отправка текстового сообщения в Telegram.

Доступ к экземпляру bot можно получить из объекта context. Например, для отправки текстового сообщения: context.bot.send_message().

# для версии 13.x 
bot.send_message(chat_id=chat_id, text="Текст сообщения...")
# для версии 20.x
await bot.send_message(chat_id=chat_id, text="Текст сообщения...")

Примечание: метод .send_message (как и любой из методов .send_* класса telegram.Bot()) возвращает экземпляр класса telegram.Message(), поэтому его можно использовать в коде позже.

Принимаемые аргументы методом bot.send_message():

  • chat_id: тип Int - идентификатор целевого чата или имя пользователя целевого канала (в формате @channelusername).
  • text: тип str - Текст отправляемого сообщения, 1-4096 символов после разбора сущностей.
  • message_thread_id: тип Int - идентификатор целевой ветки сообщений (темы) форума; только для супергрупп форума.
  • parse_mode: режим для синтаксического анализа объектов в тексте сообщения. может быть telegram.ParseMode.MARKDOWN_V2 или telegram.ParseMode.HTML Дополнительные сведения смотрите ниже.
  • disable_web_page_preview: тип bool - отключает предварительный просмотр ссылок в этом сообщении.
  • disable_notification: тип bool - отправляет сообщение беззвучно. Пользователи получат уведомление без звука.
  • protect_content: тип bool - защищает содержимое отправленного сообщения от пересылки и сохранения.
  • reply_to_message_id: тип int - если сообщение является ответом, то это идентификатор исходного сообщения (подставляется автоматически в методы update.message.reply_*()).
  • allow_sending_without_reply: тип bool - значение True, если сообщение должно быть отправлено, даже если указанное сообщение с ответом reply_to_message_id не найдено.

Дополнительно смотрите описание метода sendMessage в Telegram API.

Ответ на полученное сообщение о время обновления.

# для версии 13.x 
update.message.reply_text("Текст ответа на сообщение.")
# для версии 20.x 
await update.message.reply_text("Текст ответа на сообщение.")

Примечание: метод update.message.reply_text() представляет собой ссылку на метод context.bot.send_message() с теми же значениями по умолчанию и уже переданным chat_id.

Существуют эквиваленты этого метода для ответа на сообщение фотографиями, звуком и т. д., и подобные ссылки существуют во всей библиотеке python-telegram-bot.

Отправка действия в чат.

Чтобы сообщить пользователю, что что-то происходит на стороне бота (например, пишется сообщение) - используйте следующий код:

# для версии 13.x 
bot.send_chat_action(chat_id=chat_id, action=telegram.constants.ChatAction.TYPING)
# для версии 20.x 
await bot.send_chat_action(chat_id=chat_id, action=telegram.constants.ChatAction.TYPING)

В качестве альтернативы, если есть несколько команд и хочется повторять приведенный выше фрагмент кода во всех командах, то смотрите раздел "Использование декораторов в python-telegram-bot". Там же найдете описание класса constants.ChatAction.

Описание метода sendChatAction в Telegram API

Форматирование сообщения (жирный, курсив, и т.д.).

Telegram поддерживает некоторые параметры форматирования текста. Все подробности о том, что поддерживается, можно найти в официальной документации. Имейте в виду, что придется экранировать специальные символы, как описано в документации. Библиотека python-telegram-bot также предлагает вспомогательную функцию для экранирования текста Markdown. Для экранирования текста HTML можно использовать html.escape из стандартной библиотеки.

Можно форматировать текст с помощью любого метода/типа API, имеющего аргумент parse_mode. В дополнение к редактированию текста, необходимо передавать один из режимов разбора, доступных в классе telegram.ParseMode, в аргумент parse_mode. Начиная с версии 5.0 Bot API (версия пакета 13.1), также можно передать список telegram.MessageEntities в параметр entity.

Примечание. В обновлении API 4.5 Telegram представил Markdown v2, который поддерживает вложенные объекты и требует другого экранирования, чем Markdown v1. В официальной документации API Markdown v1 упоминается как устаревший режим, следовательно следует предпочесть Markdown v2. Для удобства, не забывайте также использовать метод message.reply_markdown_v2() вместо message.reply_markdown() и т. д.

Отправка текстового сообщения с форматированием MarkdownV2.

В настоящее время поддерживается следующая MarkdownV2 разметка:

*bold \*text*
_italic \*text_
__underline__
~strikethrough~
||spoiler||

# использование вложенности разметки MarkdownV2  
*bold _italic bold 
~italic bold strikethrough ||italic bold strikethrough spoiler||~ 
__underline italic bold___ bold*

[inline URL](http://www.example.com/)
[inline mention of a user](tg://user?id=123456789)
![👍](tg://emoji?id=5368324170671202286)
`inline fixed-width code`

'''
pre-formatted fixed-width code block
'''

'''python
pre-formatted fixed-width code block written in the Python programming language
'''

Обратите внимание:

  • Любой символ с кодом от 1 до 126 включительно может быть экранирован в любом месте с предшествующим символом '\', и в этом случае он обрабатывается как обычный символ, а не как часть разметки. Это подразумевает, что символ '\' обычно должен экранироваться предшествующим символом '\'.
  • Внутри объектов pre и code все символы "' и "\" должны экранироваться предшествующим символом "\".
  • Внутри (...) части встроенной ссылки и пользовательского определения эмодзи, все ')' и '\' должны быть экранированы предшествующим символом '\'.
  • Во всех остальных местах символы: '_', '*', '[', ']', '(', ')', '~', "', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!' должно быть экранировано предыдущим символом '\'.
  • В случае неоднозначности между курсивом и подчеркиванием объектов, сочетание __ всегда жадно обрабатывается слева направо как начало или конец объекта подчеркивания, поэтому вместо ___italic underline___ используйте ___italic underline_\r__, где \r - символ с кодом 13, который будет проигнорировано.
  • В качестве альтернативного значения для пользовательского смайлика должен быть указан допустимый смайлик. Эмодзи будут отображаться вместо пользовательских эмодзи в местах, где пользовательские эмодзи не могут быть отображены (например, в системных уведомлениях) или если сообщение пересылается пользователем, не являющимся премиум-пользователем. Рекомендуется использовать эмодзи из поля эмодзи пользовательского стикера с эмодзи.

Пример сообщения с форматированием Markdown:

# для версии 13.x 
bot.send_message(chat_id=chat_id, 
                 text="*bold* _italic_ `fixed width font` [link](http://google.com)\.", 
                 parse_mode=telegram.ParseMode.MARKDOWN_V2)

# для версии 20.x 
await bot.send_message(chat_id=chat_id, 
                 text="*bold* _italic_ `fixed width font` [link](http://google.com)\.", 
                 parse_mode=telegram.ParseMode.MARKDOWN_V2)

Пример ответа на сообщение с форматированием Markdown:

# для версии 13.x 
update.message.reply_markdown_v2(text="*bold* _italic_ `fixed "
                                 "width font` [link](http://google.com)\.")

# для версии 20.x 
await update.message.reply_markdown_v2(text="*bold* _italic_ `fixed "
                                 "width font` [link](http://google.com)\.")

Отправка текстового сообщения с форматированием HTML.

В настоящее время поддерживаются следующие HTML теги:

<b>жирный</b>, <strong>жирный</strong>
<i>курсив</i>, <em>курсив</em>
<u>подчеркивание</u>, <ins>подчеркивание</ins>
<s>зачеркнуто</s>, <strike>зачеркнуто</strike>, <del>зачеркнуто</del>
<span class="tg-spoiler">скрытый текст</span>, <tg-spoiler>скрытый текст</tg-spoiler>

<!-- использование вложенности HTML тегов -->
<b> 
bold <i>italic bold <s>italic bold strikethrough 
<span class="tg-spoiler">italic bold strikethrough spoiler</span></s> 
<u>underline italic bold</u></i> bold
</b>

<a href="http://www.example.com/">встроенный URL-адрес</a>
<a href="tg://user?id=123456789">встроенное упоминание пользователя</a>
<tg-emoji emoji-id="5368324170671202286">👍</tg-emoji>
<code>встроенный код фиксированной ширины</code>
<pre>предварительно отформатированный блок кода фиксированной ширины</pre>

<pre>
    <code class="language-python">
        предварительно отформатированный блок кода фиксированной ширины, 
        написанный на языке программирования Python
    </code>
</pre>

Обратите внимание:

  • Все символы <, > и &, которые не являются частью тега или HTML-объекта, должны быть заменены соответствующими HTML-объектами (&lt;, &gt; и &amp; соответственно).
  • Поддерживаются все числовые HTML-объекты.
  • В настоящее время API поддерживает только следующие именованные HTML-объекты: &lt;, &gt;, &amp; и &quot;.
  • Используйте вложенные теги <pre> и <code>, чтобы определить язык программирования для объекта <pre>.
  • Язык программирования не может быть указан для автономных тегов кода.
  • В качестве содержимого тега <tg-emoji> должен использоваться допустимый смайлик. Эмодзи будут отображаться вместо пользовательских эмодзи в местах, где пользовательские эмодзи не могут быть отображены (например, в системных уведомлениях) или если сообщение пересылается пользователем, не являющимся премиум-пользователем. Рекомендуется использовать эмодзи из поля эмодзи пользовательского стикера с эмодзи.

Пример сообщения с форматированием HTML:

# для версии 13.x 
bot.send_message(chat_id=chat_id, 
                 text='<b>bold</b> <i>italic</i> <a href="http://google.com">link</a>.', 
                 parse_mode=telegram.ParseMode.HTML)

# для версии 20.x 
await bot.send_message(chat_id=chat_id, 
                 text='<b>bold</b> <i>italic</i> <a href="http://google.com">link</a>.', 
                 parse_mode=telegram.ParseMode.HTML)

Пример ответа на сообщение с форматированием HTML:

# для версии 13.x 
update.message.reply_html(text='<b>bold</b> <i>italic</i> ' 
                          '<a href="http://google.com">link</a>.'")

# для версии 20.x 
await update.message.reply_html(text='<b>bold</b> <i>italic</i> ' 
                          '<a href="http://google.com">link</a>.'")

Обработка сущностей в сообщении (хэштеги, URL-адреса и т.д.).

Чтобы обрабатывать сущности в сообщениях, необходимо использовать класс telegram.MessageEntity. Для этого нужно извлечь сущности и соответствующий им текст из объекта telegram.Message с помощью telegram.Messag.parse_entities.

Объект telegram.MessageEntity представляет собой специальную сущность в текстовом сообщении. Например, хэштеги, имена пользователей, URL-адреса и т.д.

Messag.parse_entities(types=None):

Метод Messag.parse_entities() возвращает dict, который сопоставляет telegram.MessageEntity со строкой. Он содержит сущности из этого сообщения, отфильтрованные по их атрибуту telegram.MessageEntity.type в качестве ключа, и текст, которому принадлежит каждая сущность, в качестве значения dict.

Обратите внимание, что этот метод всегда следует использовать вместо атрибута entities, поскольку он вычисляет правильную подстроку из текста сообщения на основе кодовых точек UTF-16.

Аргумент types (List[str], необязательный) - список типов telegram.MessageEntity в виде строк. Если атрибут type объекта содержится в этом списке, то он будет возвращен. По умолчанию - это список всех типов.

Рассмотрим пример, который проверяет наличие URL-адресов в сообщении и печатает их на экране.

# Словарь, который отображает сущность в текст
entities = message.parse_entities()
for ent in entities:
    txt = entities[ent]
    if ent.type == ent.TEXT_LINK:
        # Текст со встроенным URL
        print(f"{txt} - {ent.url}")
    elif ent.type == ent.URL:
        # Обычный URL
        print(txt)

Для таких вещей, как извлечение только ссылок из сообщений Telegram, лучше использовать стороннее расширение ptbcontrib.extract_urls.

Предоставляет два метода, позволяющих легко извлекать гиперссылки из сообщений.

Поддерживает:

  • как простые ссылки, так и объекты сообщений,
  • как обычные сообщения, так и подписи,
  • извлечение исключительно прямых ссылок на сообщения Telegram.