Escrito por Rafael Nogales en Planeta Chatbot. 

Antes de responder a esta pregunta conviene explicar que Telegram nos ofrece dos mecanismos para que nuestro bot reciba las nuevas notificaciones.
Cuando un usuario escribe a nuestro bot no le escribe a él directamente sino que el mensaje va primero a los servidores de Telegram que actúan como intermediarios.

El mecanismo por defecto que nos ofrece Telegram para enviar las notificaciones consiste en que ellos no van a enviarlas sino que las dejan en un buzón que nuestro bot debe consultar regularmente para ver si hay algo nuevo. A este buzón se le llama pool.

Como podréis imaginar este mecanismo no es muy eficiente en el lado del bot, por eso Telegram ofrece una alternativa, establecer un webhook.

En informática un hook es un mecanismo de comunicación entre aplicaciones basado en eventos.Imaginemos que tenemos dos aplicaciones, una de ellas será la aplicación S (de Servidora) y otra la aplicación C (de cliente).

La aplicación C puede suscribirse a algún evento que S produzca de forma que S enviará una notificación a C cada vez que ocurra el evento sin que C tenga que estar pendiente y consultando a S todo el rato.

Esto es especialmente útil para aquellos casos en los que el evento ocurra en cualquier momento y sea esporádico (como es el caso de un mensaje de Telegram). Un webhook básicamente es un hook que usa la web como mecanismo de comunicación.

Recapitulando, para establecer un webhook lo que debemos hacer es decirle a los servidores de Telegram que nuestro bot no va a ir a mirar la pool sino que espera que sea el propio Telegram quien le avise de las notificaciones nuevas.

Supongamos que ya has creado tu bot de Telegram usando el BotFather:

Create Bot I

Create Bot II

En ese caso ya tendrás tu token, si te fijas es un token para acceder a la API HTTP (esto ya nos da una pista de que todas las comunicaciones que hagamos entre nuestro bot y Telegram van a ser peticiones HTTP). Para establecer el webhook basta enviar una petición HTTP a api.telegram.org a la siguiente URL:

https://api.telegram.org/bot<BOT_TOKEN>/setWebHook?url=<TU_URL_DE_HEROKU>

Ojo! entre bot y <BOT_TOKEN> no hay “/”

Si, lo has hecho bien deberías ver algo así:

Create webhook

Con esto ya tendríamos nuestro webhook creado.

Extra:

Si en algún momento quisiéramos borrar el webhook y volver a usar el mecanismo de pooling (el por defecto) bastaría con dejar el campo url vacío, es decir, entrar a este otro link:

https://api.telegram.org/bot<BOT_TOKEN>/setWebHook?url=

Delete webhook

Ahora vamos a programar el bot. Para ello, podríamos usar librerías que vienen ya preparadas para crear bots de Telegram, pero para ilustrar cómo funciona el webhook voy a poner un ejemplo de un bot simple con el mínimo código necesario y sin usar frameworks complejos ya que por debajo los frameworks hacen esto mismo.

El archivo principal de nuestro bot es un típico archivo estilo Flask (Python) / Express (si lo hiciesemos con NodeJS)

# bot.py  import requests   import os  from flask import Flask, request# Add your telegram token as environment variable  BOT_URL = f'https://api.telegram.org/bot{os.environ["BOT_KEY"]}/'      app = Flask(__name__)      @app.route('/', methods=['POST'])  def main():    data = request.json     print(data) # Comment to hide what Telegram is sending you   chat_id = data['message']['chat']['id']   message = data['message']['text']     json_data = {   "chat_id": chat_id,   "text": message,   }     message_url = BOT_URL + 'sendMessage'   requests.post(message_url, json=json_data)     return ''      if __name__ == '__main__':    port = int(os.environ.get('PORT', 5000))   app.run(host='0.0.0.0', port=port, debug=True)

Si nos fijamos la aplicación recibe una petición POST con unos datos codificados en JSON (Flask lo almacena en el objeto request.json)
Este JSON contiene un objeto ‘message’ que a su vez tiene un chat_id (remitente) y el texto del mensaje (text)
Hay mucha más información en ese JSON, pero lo ignoramos porque para este ejemplo sencillo no lo necesitamos.

El bot lo que hace es responder con otro JSON en el que se especifica a quién responderle (chat_id) y qué escribir (text). Y se envía de vuelta a Telegram mediante una petición POST. Ese es el mecanismo que usa Telegram para la comunicación.

La mayor parte del código es válido para desplegarlo en cualquier plataforma el único detalle para que Heroku no de problemas es el uso de la variable de entorno PORT:

Para desplegar con éxito el bot en Heroku necesitamos que Flask responda por el puerto que le asigne Heroku a esa aplicación. Por eso necesitamos os.environ.get (‘PORT’, 5000). El 5000 es el puerto por defecto de Flask, para que también funcione dónde exista la variable de entorno PORT, como es el caso de vuestra máquina local. Además Heroku necesita saber dos cosas más:

  1. Las dependencias de nuestra aplicación (requirements.txt)
  2. El punto de entrada de la aplicación (Procfile)

En el Procfile escribiremos esto:

web: python bot.py

Es el comando para arrancar el servidor y lo de web hace referencia al servicio de Heroku al que se va a asociar ese comando en este caso es el web porque queremos poner una API.

El archivo requirements.txt quedaría así

requests  flask

Con esto ya tendríamos la aplicación lista para funcionar, pero necesitamos crear una aplicación en Heroku, configurarla y asociar ese código a dicha aplicación.

Supongo que ya has creado una aplicación vacía, en ese caso podrías añadir el buildpack de Python. Sin embargo, no es necesario porque Heroku va a saber que esto es Python y lo va a añadir automáticamente. Lo que no va a saber es que necesita una variable de entorno BOT_KEY.

Para añadir variables de entorno vamos al Heroku Dashboard a la pestaña Settings y añadimos la variable de entorno así:

Además voy a suponer que estamos usando GitHub como nuestro repositorio de código, si no es así debemos usar Heroku CLI para hacer el deploy.
Con GitHub es mucho más simple así que lo recomiendo encarecidamente.

Si usamos GitHub basta ir a la pestaña de Deploy y enlazar nuestra aplicación con un repositorio nuestro (si nunca has hecho esto antes te pedirá las credenciales de GitHub para poder conectarse a tus repositorios, porque de lo contrario Heroku no podría hacerlo).

En esta imagen vemos como queda la aplicación después de conectarla y activar el despliegue automático (esto último no es obligatorio, pero es bastante cómodo)

Una vez hemos llegado a este punto y la app se haya desplegado conviene revisar el log de Heroku para ver que todo está bien (el log está en el boton More, arriba a la derecha):

Log trás el despliegue

Ahora podemos abrir Telegram y probar el bot:

Con esto habríamos acabado. Es interesante ver lo que ocurre en el log cuando mandamos mensajes, para aprender a entender mejor cómo funcionan he dejado un print del json que recibe el bot, es interesante echarle un ojo.

Si eres un desarrollador puedes hacer un fork del repositorio https://github.com/RNogales94/telegram-bot-webhook y utilizar el código como base, aunque para proyectos grandes recomiendo el uso de algún framework para Telegram como python-telegram-bot:

Si te ha gustado este artículo, recomiéndalo a otros y compártelo. Si trabajas en una empresa dirigiendo un proyecto relacionado con NLP o chatbots, ponte en contacto conmigo para recibir asesoría y ayudaros a diseñar un prototipo inicial sobre el que trabajar.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *