Telegram - отличная платформа с множеством замечательных пользователей (я сам пользуюсь Telegram). И как лучше всего пользователям Telegram получать уведомления? Мы не можем знать наверняка. Может, им нравится электронная почта или что-то еще. Но можно догадаться, что отправлять уведомления в Telegram было бы довольно удобно.

Если вы хотите отправлять уведомления Telegram из своего приложения, вы попали в нужное место. Я добавил эту функцию в свое приложение, и она мне очень нравится.

Одно небольшое примечание. В этой статье я привожу примеры кода на Python. Но эти идеи не относятся к Python и могут быть без проблем переведены на другой язык.

Итак, без лишних слов, давайте рассмотрим, как это сделать.

Создайте бота Telegram

Прежде всего, вам необходимо создать бота Telegram. Для этого вам понадобится еще один Telegram-бот - BotFather. Просто поговорите с ним (нажмите старт).

Теперь вы видите, на что он способен. Но нас интересует создание нового бота, поэтому мы и выберем именно его (/newbot).

Вы быстро обнаружите, что имя бота должно оканчиваться на «бот». А поскольку вы похожи на меня и приходите в игру слишком поздно, большинство имен ботов уже заняты.

Но в конце концов вы найдете имя для своего бота и получите токен доступа, который нам понадобится.

Теперь, когда у вас есть бот, пользователи Telegram могут его найти и использовать. Но есть одна проблема - вы не можете связать пользователей, пришедших из Telegram, с пользователями в вашем приложении. Позвольте мне показать вам, почему.

Как только пользователь нажмет кнопку «Пуск» на вашем боте, вы получите «обновление». Вы можете проверить все обновления бота даже в браузере, посетив следующий URL https://api.telegram.org/bot{bot_token}/getUpdates (не забудьте использовать свой токен доступа в URL). Вот что у меня получилось:

Ничего не умеете читать? Не волнуйся. Вы можете исправить это, установив в браузере какое-нибудь расширение JSON prettifier. Я использую JSON Formatter для Chrome. Выглядит намного лучше.

Как видите, мы не получаем столько информации о человеке. Из этой информации мы можем получить их полное имя. Но было бы хорошо, если бы пользователь указал свое полное имя в вашем приложении и не гарантирует его уникальность. Поэтому мы не можем использовать это для поиска пользователя в ваших приложениях.

Еще одна информация, которую мы получаем, - это имя пользователя. Это более полезно, поскольку оно уникально для всех пользователей Telegram. Но, скорее всего, в ваших приложениях этого нет. Поэтому нам нужно попросить пользователя ввести свое имя пользователя где-нибудь в приложении. Это слишком много работы, и я не уверен, что кто-то ее сделает.

Другой вариант связать пользователя - попросить его предоставить боту адрес электронной почты, который они использовали в вашем приложении. Но в этом слишком много недостатков: пользователь может сделать опечатку при вводе электронной почты, пользователь может ввести адрес электронной почты другого пользователя и использовать систему. Это очень плохо.

Можем ли мы сделать лучше?

Связывание пользователя

Конечно можем. Чтобы связать пользователя, мы воспользуемся методом, который называется глубинная ссылка.

Во-первых, вам нужно создать случайный уникальный токен для каждого пользователя. Я использовал следующий код для создания токена с помощью Python:

from secrets import token_urlsafe
token = token_urlsafe(8)
token
# => 'uEDbtJFHxKc'

Затем вам нужно сохранить этот токен, чтобы впоследствии можно было найти пользователя с ним. Вы можете сохранить его в своей базе данных или использовать другое место, например, кеш. У меня Notification модель, поэтому я добавил поле в таблицу модели.

class Notification(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
	# ...
    connect_token = models.CharField(max_length=64, null=True)

Итак, мы создали токен uEDbtJFHxKc и сохранили его. Теперь нам нужно использовать этот токен в URL-адресе бота Telegram, который пользователь должен щелкнуть, чтобы все заработало:

telegram_url = 'https://www.telegram.me'
bot_name = 'music_notification_bot'
token = 'uEDbtJFHxKc'
url = f'{telegram_url}/{bot_name}?start={token}'

Теперь, когда у нас есть URL-адрес 'https://telegram.me/music_notification_bot?start=uEDbtJFHxKc', пора показать его пользователю. Просто отобразите его в любом месте вашего приложения и дождитесь, пока пользователь щелкнет по нему.

Как только пользователь поймает наживку и нажмет «Старт», вы должны получить еще одно обновление:

{
    "ok": true,
    "result": [
        // ...
        // previous updates
       	// ...
		{
			"update_id": 599162365,
			"message": {
                "message_id": 174,
                "from": { ... },
                "chat": { ... },
                "date": 1549788357,
                "text": "/start uEDbtJFHxKc",
                "entities": [ ... ]
        	}
        }
    ]
}

Наконец-то мы можем идентифицировать нашего пользователя. Поле text теперь содержит наш токен пользователя. Давайте возьмем это из этого поля:

bot_token = 'your_bot_token'
updates_url = f'https://api.telegram.org/bot{bot_token}/getUpdates'

import requests
response = requests.get(updates_url).json()
text = response['result'][0]['message']['text']
text
# => '/start uEDbtJFHxKc'

splitted_text = text.split(' ')
# => ['/start', 'uEDbtJFHxKc']

token = splitted_text[-1]
# => 'uEDbtJFHxKc'

Этот токен можно использовать для поиска пользователя. Ваша реализация зависит от того, как вы изначально сохранили токен. Но вот как я это делаю:

notification = Notification.objects.get(channel='telegram', connect_token=token)
user = notification.user

Итак, пользователь нажал кнопку «Пуск». Но они видят, что ничего не произошло. Давай хотя бы поприветствуем их.

Чтобы поприветствовать пользователя, нам нужно обнаружить, что пользователь начал разговор с нашим ботом. Есть два варианта, как это сделать: опрос и веб-перехватчики.

Вы уже знаете, что такое опрос. Вы уже это сделали. Или, по крайней мере, видел, как я это делаю. Проверив https://api.telegram.org/bot{bot_token}/getUpdates страницу, мы провели один опрос. Опрос проверяет наличие обновлений постоянно, например, каждые 2 секунды. Таким образом, мы всегда можем узнать, когда кто-то взаимодействовал с ботом.

Веб-перехватчики идут немного в другом направлении. Вместо того, чтобы проверять обновления каждые 2 секунды, мы просто ждем обновления. И когда это произойдет, Telegram отправит запрос с данными обновления на указанный нами URL. Таким образом, мы можем дать немного отдохнуть как нашему серверу, так и серверу Telegram и просто дождаться обновления.

Опрос может быть лучше, если у вас большой трафик, но, к сожалению, это скорее исключение, поэтому я решил использовать веб-перехватчик.

Вебхуки

Установить веб-перехватчик в Telegram очень просто. Вам просто нужно отправить запрос на https://api.telegram.org/bot{bot_token}/setWebhook?url={your_server_url}. Открытие этой ссылки в вашем браузере тоже работает. your_server_url - это URL-адрес, на который Telegram будет отправлять обновления. Вот что вы должны получить в ответ:

{
    "ok": true,
    "result": true,
    "description": "Webhook was set"
}

Если вы не доверяете себе, посетите https://api.telegram.org/bot{bot_token}/getWebhookInfo, чтобы еще раз убедиться, что все в порядке. Вы должны увидеть что-то вроде этого:

{
    "ok": true,
    "result": {
        "url": "https://example.com/your_server_endpoint",
        "has_custom_certificate": false,
        "pending_update_count": 0,
        "max_connections": 40
    }
}

Теперь. Если что-то не так (например, вы указали неправильный URL), вы всегда можете удалить веб-перехватчик, посетив https://api.telegram.org/bot{bot_token}/deleteWebhook, а затем снова настроив веб-перехватчик.

Местное развитие

Прежде чем продолжить, я хотел бы сказать несколько слов о местном развитии. Вебхуки для этого не очень подходят. Веб-перехватчики отправляются на URL-адрес, и, скорее всего, вы не знаете URL-адрес своего компьютера. Кроме того, веб-перехватчик Telegram требует, чтобы URL-адрес был безопасным (HTTPS).

Но есть решение этой проблемы: ngrok. ngrok - это инструмент, который открывает миру вашу локальную среду. Загрузите ngrok, установите его и запустите с того порта, на котором работает ваш сервер. Мой сервер работает на 8000 порту, поэтому мне нужно запустить консоль

/path/to/ngrok http 8000

Затем ngrok должен предоставить вам URL-адрес, который вы можете использовать для установки веб-перехватчика.

Приветствуя пользователя

Теперь, когда вы готовы к разработке, давайте поприветствуем наших пользователей - они этого ждут.

После того, как пользователь нажмет «Пуск», ваш Telegram отправит обновление на URL-адрес вашего сервера. Интересные части обновления должны выглядеть так:

{
    "message": {
        "chat": {
            "id": 457
        },
		"text": "/start uEDbtJFHxKc",
    }
}

Это идеальное время, чтобы связать пользователя с помощью текста сообщения. Также есть интересная информация, идентификатор чата. Идентификатор чата - это то, что нам нужно, чтобы отправить сообщение этому пользователю. В Telegram есть конечная точка API для отправки сообщения следующего вида https://api.telegram.org/bot{bot_token}/sendMessage?chat_id={chat_id}&text={text}. Я не уверен, что мне нужно объяснять, как его использовать, но вот как выглядит мой код, обрабатывающий веб-перехватчик:

import json
import requests

def callback(request):
    body = json.loads(request.body)
    text = body['message']['text']
    token = text.split(' ')[-1]
    associate_user_by_token(token)

    bot_key = os.environ.get('TELEGRAM_API_KEY')
    chat_id = body['message']['chat']['id']
	text = "Welcome!"

	send_message_url = f'https://api.telegram.org/bot{bot_key}/sendMessage?chat_id={chat_id}&text={text}'
	requests.post(send_message_url)

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

Отправка уведомлений

Наконец, мы подошли к вопросу, зачем мы все это делаем - push-уведомлениям. Вы можете уведомить пользователя о некоторой информации, которая произошла в вашем приложении. Например, кому-то понравился пост пользователя или что-то еще. Я использую Telegram, чтобы сообщать о новых релизах музыки от любимых исполнителей пользователя.

Вы уже знаете, как отправлять уведомления. Вам просто нужно отправить сообщение, используя https://api.telegram.org/bot{bot_token}/sendMessage?chat_id={chat_id}&text={notification_text}.

Конечно, если вы планируете отправлять уведомления не только тогда, когда пользователь взаимодействует с ботом, вам необходимо сохранить chat_id в своей базе данных.

Вы также можете включить в свое сообщение ссылки или другое форматирование. В этом случае вам нужно будет добавить еще один параметр в URL-адрес отправляемого сообщения, parse_mode. Есть 2 варианта синтаксического анализа: Markdown или HTML. Я использую Markdown, так как считаю его более простым в использовании. Если вы не знакомы с Markdown, вы можете использовать HMTL, но я бы рекомендовал прочитать насколько просто Markdown.

Вот как выглядит URL-адрес отправляемого сообщения с parse_mode параметром https://api.telegram.org/bot{bot_token}/sendMessage?chat_id={chat_id}&text={notification_text}&parse_mode=markdown.

Я добавляю ссылки на новые выпуски в текст уведомлений вот так {release.date}: {release.artist.name} - [{release.title}]({release.url}). Подробнее о том, как форматировать сообщения, вы можете прочитать здесь.

Кроме того, есть дополнительные параметры для URL-адреса отправки сообщения, например disable_notification. Всегда есть что исследовать.

Заключение

Теперь ты должен знать, как

  • создать бота в Telegram с помощью BotFather
  • проверить наличие обновлений (и что лучше - веб-перехватчики или опрос)
  • связать пользователя с помощью глубинных ссылок
  • отправить приветственное сообщение и продолжить отправку уведомлений
  • форматировать сообщения, которые вы отправляете

Надеюсь, эта статья была вам полезна. Это пятая часть из серии статей о МуН. Следите за обновлениями части 6. Вы можете найти код этого проекта, как и других моих проектов, на моей странице GitHub. Оставляйте свои комментарии ниже и подписывайтесь на меня, если вам понравилась эта статья.

Первоначально опубликовано на https://kholinlabs.com/telegram-push-notifications 12 февраля 2019 г.