Artigo original: How to set up push notifications in your Telegram bot

Traduzido em português europeu

Escrito por: Nikita Kholin

O Telegram é uma ótima plataforma com muitos utilizadores – eu próprio sou um utilizador do Telegram. Qual seria a melhor forma para os utilizadores do Telegram receberem notificações? Não podemos ter a certeza. Talvez gostem de receber por e-mail ou de outro forma, mas podemos supor que enviar notificações para o Telegram seria bastante conveniente.

Se gostarias de enviar notificações para o Telegram a partir da tua aplicação, vieste ao sítio certo. Adicionei esta funcionalidade à minha aplicação e adorei.

Uma pequena nota: neste artigo, forneci exemplos de código em Python. As ideias, contudo, não são específicas para o Python e podem ser traduzidas para outra linguagem sem qualquer problema.

Então, sem mais demoras, vamos ver como podemos fazê-lo.

Criar um bot do Telegram

Em primeiro lugar, precisas criar um bot do Telegram. Para fazer isto, tens de utilizar outro bot do Telegram, o BotFather. Começa a falar com ele (clica em start).

K0IHhahp6VR-IJDs8ohcZRxBBlUMaRWuUt4g

Agora, podes ver o que ele pode fazer, mas o que nos interessa é criar um novo bot. Por isso, vamos escolher (/newbot).

4TCF43Y1rArQcRQb-5F6XblOvTEMXUwWazrd

Vamos descobrir rapidamente que o nome do bot deve terminar com "bot". E, visto que és como eu e chegaste à festa muito tarde, maior parte dos nomes de bot já estão ocupados.

yRoEugA8JJ1ccppRU8g3kcy40mGsJqCalzRG

Eventualmente, porém, vais encontrar um nome para o teu bot e receber um token de acesso de que vamos precisar.

Agora que tens um bot, os utilizadores do Telegram podem encontrá-lo e utilizá-lo, mas há um problema — não podes associar os utilizadores que vêm do Telegram aos utilizadores da tua aplicação. Permite-me mostrar-te a razão.

Assim que um utilizador clicar no botão "Start" no teu bot, vais receber uma "atualização". Podes verificar todas as atualizações do bot até mesmo no teu browser ao visitar o seguinte URL: https://api.telegram.org/bot{bot_token}/getUpdates (não te esqueças de utilizar o teu token de acesso no URL). Isto é o que obtive:

AydGLffhxTaXFcqwj3untIxDVGf-AyGE26pc

Não consegues ler nada? Não te preocupes. Podes corrigir isso ao instalar alguma extensão JSON prettifier no teu navegador. Eu utilizo o JSON Formatter para o Chrome. Tem um aspeto muito melhor.

iG2V6vR4rqS8Lmw-Cxg5FisuCHU9XAFEquzc

Então, como podes ver, não recebemos grande informação sobre a pessoa. A partir dessa informação, podes obter o nome completo da pessoa. Seria, no entanto, uma sorte se o utilizador fornecesse o seu nome completo na tua aplicação, e não temos garantia que seja único. Por isso, não podemos utilizar isso para encontra um utilizador nas tuas aplicações.

Outra informação que obtemos é o nome de utilizador. Isto é mais útil porque é único entre todos os utilizadores do Telegram. O mais provável, porém, é que não tenhas isso disponível nas tuas aplicações. Então, teríamos de pedir ao utilizador para inserir o seu nome de utilizador algures na aplicação. É muito trabalho que não tenho a certeza se alguém o faria.

Outra opção para associar um utilizador seria pedir-lhes para fornecer o e-mail que utilizaram para o bot na tua aplicação. Ocorre que isso tem muitas falhas: o utilizador pode enganar-se ao escrever o e-mail, o utilizador pode inserir um e-mail de outro utilizador para se aproveitarem do sistema. Isso é muito mau.

Podemos fazer melhor?

Associar um utilizador

Claro que podemos. Para associar o utilizador, vamos utilizar uma técnica chamada deep linking (texto em inglês).

Primeiro, tens de criar um token aleatório único para cada utilizador. Utilizei o seguinte código para gerar o token, utilizando Python:

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

De seguida, precisas guardar esse token para ser possível encontrar um utilizador com o token mais tarde. Podes guardar o token na tua base de dados ou utilizar outro local, como por exemplo uma cache. Tenho um modelo Notification, por isso adicionei um campo a uma tabela do modelo.

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

Então, geramos o token uEDbtJFHxKc e guardamo-lo. Agora, vamos ter de utilizar este token num URL para o bot do Telegram, que o utilizador tem de clicar para fazer com que tudo funcione:

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

Agora que temos o nosso URL, 'https://telegram.me/music_notification_bot?start=uEDbtJFHxKc', está na hora de o exibir ao utilizador. Exibe-o em qualquer sitio da tua aplicação e aguarda que o utilizador clique nele.

Assim que o utilizador morder o isco e clicar em “Start”, deves receber outra atualização:

{
    "ok": true,
    "result": [
        // ...
        // atualizações anteriores
       	// ...
		{
			"update_id": 599162365,
			"message": {
                "message_id": 174,
                "from": { ... },
                "chat": { ... },
                "date": 1549788357,
                "text": "/start uEDbtJFHxKc",
                "entities": [ ... ]
        	}
        }
    ]
}

Podemos, finalmente, identificar o nosso utilizador. O campo text contém agora o nosso token de utilizador. Vamos avançar e removê-lo deste campo:

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'

Este token pode ser utilizado para encontrar o utilizador. A tua implementação depende da forma como guardaste o token inicialmente. Mas aqui fica como eu faço:

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

Então, o utilizador clicou no botão "Start", mas reparou que nada aconteceu. Vamos dar as boas vindas, pelo menos.

t3LnDt2icX4drb1ZwOr4t0gd8rHaoNhuOxoR

Para dar as boas vindas ao utilizador, precisamos de descobrir se o utilizador iniciou uma conversa com o nosso bot. Existem duas opções para como podemos fazer isso: polling e webhooks.

Já sabes o que é polling. Já o fizeste. Ou pelo menos já me viste a fazê-lo. Assim que consultamos a página https://api.telegram.org/bot{bot_token}/getUpdates, fizemos uma poll. Polling é verificar constantemente se existem atualizações, a cada 2 segundos, por exemplo. Desta forma podemos saber sempre quando alguém interagiu com o bot.

Os Webhooks vão numa direção um pouco diferente. Em vez de verificar a cada 2 segundos se existem atualizações, simplesmente esperamos que aconteça uma atualização. Quando acontecer, o Telegram enviará um pedido com a informação da atualização para um URL que especificamos. Deste modo, podemos dar algum descanso tanto aos nossos servidores como aos do Telegram, e simplesmente esperar que chegue alguma atualização.

Polling pode ser melhor se tiveres um tráfego elevado mas, infelizmente, é uma exceção, por isso, decidimos utilizar o webhook.

Webhooks

nn4BJScN-LpTraRBdaaZ6--uBVl7Ikrlfj6E

Configurar um webhook no Telegram é muito fácil. Só tens de enviar um pedido para https://api.telegram.org/bot{bot_token}/setWebhook?url={your_server_url}. Abrir este link no teu browser também funciona. your_server_url é o URL para onde o Telegram enviará as atualizações. Aqui está o que deves obter como resposta:

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

Se não confiares nas tuas capacidades, podes visitar https://api.telegram.org/bot{bot_token}/getWebhookInfo apenas para verificar que está tudo OK. Deves ver algo como isto:

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

Agora, se algo não estiver OK (como teres colocado o URL errado), podes sempre remover o webhook ao visitar https://api.telegram.org/bot{bot_token}/deleteWebhook e de seguida, configurar novamente o webhook.

Desenvolvimento local

Antes de avançar, gostaria de partilhar algumas palavras sobre o desenvolvimento local. Os webhooks não são muito adequados para isto. Os webhooks são enviados para um URL e muito provavelmente não sabes qual é o URL do teu computador. Além disso, um webhook do Telegram requer que o URL seja seguro (HTTPS).

Existe, no entanto, uma solução para este problema: ngrok. ngrok é uma ferramenta que expõe o teu ambiente local ao mundo. Descarrega o ngrok, faz a instalação e inicia-o com a porta em que o teu servidor está a executar. O meu servidor está a executar na porta 8000, por isso, teria de executar o seguinte na consola

/path/to/ngrok http 8000

Depois, o ngrok deve fornecer-te um URL que podes utilizar para configurar um webhook.

Dar as boas vindas a um utilizador

g5chjEivn8kFMGCWNKvl1x5FmYxWRaXlfPgX

Agora que tens tudo pronto para o desenvolvimento, vamos dar as boas vindas ao nosso utilizador — está à espera disso.

Assim que o utilizador clicar em "Start", o teu Telegram enviará uma atualização para o URL do teu servidor. As partes interessantes da atualização devem ter este aspeto:

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

Esta é a altura ideal para associar o utilizador através de uma mensagem de texto. Também existe um pedaço de informação interessante, ID de Chat. O ID de Chat é o que precisamos para enviar uma mensagem a esse utilizador. O Telegram tem um endpoint de  API para enviar uma mensagem, que tem este aspeto: https://api.telegram.org/bot{bot_token}/sendMessage?chat_id={chat_id}&text={text}. Não tenho a certeza se preciso de explicar como utilizá-lo, mas aqui está como fica o meu código que processa o webhook:

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)

Se enviarmos uma mensagem de boas vindas depois do utilizador ter clicado no famoso botão de "Start", o utilizador não terá dúvidas sobre o funcionamento da aplicação.

Enviar notificações

xfdeU5lYWIBYfeZ9wjFxW6x1zxjVNLnMvB2P

Por fim, chegamos à razão pela qual estamos a fazer tudo isto — enviar notificações. Podes querer notificar o utilizador sobre algo que tenha acontecido na tua aplicação. Por exemplo, alguém colocou um gosto na publicação do utilizador, ou algo do género. Eu utilizo o Telegram para enviar notificações sobre novos lançamentos de músicas dos artistas favoritos do utilizador.

Já sabes como enviar notificações. Apenas precisas enviar uma mensagem utilizando https://api.telegram.org/bot{bot_token}/sendMessage?chat_id={chat_id}&text={notification_text}.

Claro, se não estiveres a planear enviar notificações só quando o utilizador interage com o bot, vais ter de guardar o chat_id na tua base de dados.

Também podes querer incluir links ou outro tipo de formatações na tua mensagem. Neste caso, é necessário adicionares outro parâmetro ao URL de envio da mensagem, o parse_mode. Existem duas opções de parsing: Markdown ou HTML. Eu utilizei Markdown porque acho mais simples de utilizar. Se não estiveres à vontade com Markdown, podes utilizar HMTL, mas recomendo que leias quão fácil é realmente o Markdown (texto em inglês).

Aqui está o aspeto do URL de envio da mensagem com o parâmetro parse_mode: https://api.telegram.org/bot{bot_token}/sendMessage?chat_id={chat_id}&text={notification_text}&parse_mode=markdown.

Eu adiciono links para novas atualizações ao texto das notificações desta forma: {release.date}: {release.artist.name} - [{release.title}]({release.url}). Podes ler mais sobre como formatar as tuas mensagens aqui (Link em Inglês).

Além disso, existem mais parâmetros disponíveis para o URL de envio da mensagem, como por exemplo o disable_notification. Existe sempre algo a ser explorado.

Conclusão

Agora, deves saber como:

  • Criar um bot no Telegram utilizando o BotFather
  • Verificar se existem atualizações (e qual é a melhor forma de o fazer — webhooks ou polling)
  • Associar utilizadores utilizando deep linking
  • Enviar uma mensagem de boas vindas e continuar a enviar notificações
  • Formatar as mensagens que envias

Espero que este artigo tenha sido útil para ti. Esta é a quinta parte de uma série de artigos sobre o MuN (link em inglês). Fica atento/a à parte 6. Podes encontrar o código deste projeto, assim como os meus outros projetos na minha página do GitHub. Segue o autor se tiveres gostado deste artigo.

Publicado originalmente em https://kholinlabs.com/telegram-push-notifications, a 12 de Fevereiro de 2019.