Есть частый кейс, когда мы хотим получать некоторые сообщения/уведомления в свой телеграмм. Например, наша программа отловила ошибку и остановилась, наступило некоторое важное событие, парсер нашел что-то интересное на сайте и хочется все оперативно увидеть в этом мессенджере. Есть несколько хороших питоновских библиотек для работы с telegram, но я не сторонник их использования по ряду причин. Основное - они являются оболочками для чистого апи. А зачем пользоваться надстройками, если можно убрать лишнее звено? Плюс для продуктовых задач гораздо лучше использовать не истории с бот-пуллингом, а создание приложений, работу в рамках вебхуков.
- Принцип взаимодействия с Telegram
- Отправка POST-запроса с сообщением пользователю
- Отправка через GET-запрос
- Отправка кнопок
1. Принцип взаимодействия с Telegram
Всем айти-миром правят jsonы и http-запросы, в которых эти jsonы отправляются. С телеграммом - все то же самое. Он принимает на свои адреса запросы определенной структуры и отправляет свои запросы на ваши обработчики. Документации у него немало, в частности стоит изучить тут https://core.telegram.org/bots/api . Для работы с внешними обработчиками используются созданные в тг боты. И вот от имени бота пользователю, который на него подписан мы можем отправлять сообщения. А иногда и жестко спамить. Но не забываем, что у любых систем есть ограничения на число запросов. В явном виде в доке я таких ограничений не нашел, но на просторах интернета можно встретить такую формулировку:
Отправление ботом сообщений нескольким разным пользователям / в чаты, которые подключены к боту: до 30 сообщений с интервалом от 1 секунды.
В реальности просто между отправками сообщений использую интервалы от 5-10 секунд и пока не нарвался на блок. Для отправки http-запроса в питоне используется библиотека requests, работы с json - библиотека с похожим названием json. И иного нам не нужно. Только узнать из документации, какой метод отправляет сообщение и какие параметры он принимает. Это метод sendMessage. Для старта достаточно всего 2 параметра:
- chat_id - айди чата, в случае с отправкой лично пользователю совпадает с айди пользователя, отправке в групповой чат/канал - уже их айди;
- text - текст, который хотим отправить, можно даже вставлять эмодзи и форматирование.
Итого нам нужно:
1. Созданный телеграмм-бот через BotFather, токен от этого бота. Токен является своего рода ключом к взаимодействию. Поэтому храните их всегда в приватности и вне репозиториев.
2. Пользователь, который подписан на этого бота.
3. Узнать свой id в телеграмме. Когда уже будем принимать сообщения на свой обработчик, его легко увидеть по свойству user.id, а пока можно обратиться к какому-то уже готовому стороннему боту, возвращающему айди пользователя, но я предпочитаю покопаться в настройках самого ТГ в десктопной версии:
И все бы с этим способом хорошо, но вот только в своем аккаунте не увидел, где айди отразится. Пришлось зайти с другого аккаунта, перейти на свой профиль и увидеть заветный айди. Который сразу стоит сохранить
2. Отправка POST-запроса с сообщением пользователю
Запрос должен быть отправлен на следующий адрес, показываю в виде f-строки, куда подставите токен:
url = f"https://api.telegram.org/bot{token}/sendMessage"
Адрес, токен бота, метод.
В теле запроса отправляется словарь. В нашем случае из 2х ключей:
txt = 'Текст из питоновского кода'
params = {"chat_id": 11111111111,
"text": txt,}
В chat_id подставим полученный ранее айди пользователя, а в text - то, что хотим отправить:
Весь код отправки сообщения текста от бота в телеграмм может выглядеть очень компактно:
import json
import requests
token = "token"
url = f"https://api.telegram.org/bot{token}/sendMessage"
txt = 'Текст из питоновского кода'
params = {"chat_id": 11111111111,
"text": txt,}
response = requests.post(url, verify=True, data=params)
print(response)
print(response.json())
Если в словарик добавить параметр 'parse_mode': "HTML", то можно отсылать и форматированный текст:
Примеры такого форматирования в доке.
3. Отправка через GET-запрос
POSTом всегда отправлять правильнее и лучше. Но иногда можно и передать в адресной строке нужные параметры, и они тоже придут пользователю от телеграмм-бота. Запрос может выглядеть так:
https://api.telegram.org/bot{token}/sendMessage?chat_id={chat_id}&text={text}
И это можно прямо в браузере в адресной строке вызвать и получить сообщение в свой телеграмм:
Для наглядности тут сделал запрос через браузер, но делать его из кода аналогично, только указав requests.get. Со своей стороны рекомендую использовать все же post, с ним будет понадежнее)
4. Отправка кнопок
Что за бот, который не показывает кнопки? Это не бот) Для in-line кнопок используем в параметрах "reply_markup": buttons, а вот массив buttons опишем в таком виде для примера:
buttons = {"inline_keyboard":
[
[
{
"text": "1",
"callback_data": "1",
'resize_keyboard': True,
},
{
"text": "2",
"callback_data": "2",
'resize_keyboard': True,
},
{
"text": "3",
"callback_data": "3",
'resize_keyboard': True,
}
],
[{
"text": "4",
"callback_data": "3",
'resize_keyboard': True,
}],
[{
"text": "5",
"callback_data": "3"
},
{
"text": "6",
"callback_data": "3"
}
],
],
# 'is_persistent': True,
# 'resize_keyboard': True
}
И вот тут не забудем его перевести в текст:
buttons = json.dumps(buttons)
С кнопками на текущем этапе будет большая проблема, никак мы не увидим, что нажал пользователь, т.к. никаких обработчиков ОТ телеграмма у нас пока нет. Но посмамить себя и друзей от имени бота мы уже можем.