Móntate tu propio bot por cuatro duros

AWS Lambda como plataforma para un bot de Telegram

Por Alberto Fernández Valiente

Telegram

Servicio de mensajería nacido en 2013. A mediados de 2015 habilitan el uso de chatbots mediante una API Rest.

Telepot

Librería que permite construir aplicaciones con la API de chatbots de Telegram. Compatible con Python 2.7 y 3+.

Polling vs Webhook

Polling

  • Ejecutable desde la propia máquina de desarrollo
  • En ejecución aunque no haya mensajes que procesar
  • No escalable

Webhook

  • Requiere de un dominio con certificado SSL
  • Sólo se ejecuta cuando Telegram nos envía un mensaje
  • Varias posibilidades de escalado

Lambda

Plataforma para el despliegue de servicios serverless de AWS introducida a finales de 2014. A finales de 2015 añaden soporte para Python.

Lambda

Ventajas

  • Coste, capa gratuita suficiente para muchos servicios
  • Disponibilidad, nos olvidamos de monitorizar instancias
  • Escalabilidad, sin necesidad de configurar auto scaling

Lambda

Limitaciones

  • 100 ejecuciones concurrentes por defecto
  • 300 segundos de ejecución máxima
  • 50 MB por paquete de despliegue

Lambda

Desventajas

  • Python 2.7
  • Depuración de código
  • Herramientas de despliegue

Zappa

Framework para Python que permite crear servicios serverless. Lanzado en enero de 2016.


$ pip install zappa
$ zappa init
$ zappa deploy dev
          

Zappa

Cómo funciona

  • API Gateway
  • Lambda
  • Cloudwatch
  • S3

Zappa

Cómo se gestiona

  • Cloudformation ≥ 0.24.0
  • Roles, API Gateway, Lambda, etc... < 0.24.0

Zappa

Gestión de roles y usuarios

Permisos necesarios

  • API Gateway
  • Lambda
  • Cloudwatch
  • S3
  • Cloudformation

Zappa

Configuración


{
	"dev": {
		"aws_region": "eu-west-1",
		"memory_size": 128,
		"http_methods": ["GET", "POST"],
		"parameter_depth": "1",
		"integration_response_codes": [200],
		"method_response_codes": [200],
		"project_name": "<NOMBRE>",
		"log_level": "INFO",
		"s3_bucket": "<BUCKET>",
		"app_function": "bot.app",
		"remote_env_bucket": "<BUCKET>",
		"remote_env_file": "config.json"
	}
}
          

Ejemplo de mensaje de Telegram

Código del webhook


import os
import telepot
from flask import Flask, request

app = Flask(__name__)
bot = telepot.Bot(os.getenv('TELEGRAM_TOKEN'))

@app.route("/", methods=['GET', 'POST'])
def webhook():
  msg = request.json
  if msg:
      key = telepot._find_first_key(msg, TELEGRAM_MSG_TYPES)
      process_msg(msg[key])
  return 'OK'  # allways ack telegram msg
          

Código del procesado de mensajes


def process_msg(msg):
  flavor = telepot.flavor(msg)
  if flavor == 'callback_query':
      process_callback(msg)
  elif flavor == 'chat' and is_start_cmd(msg):
      chat_id = msg['chat']['id']
      kb = get_days_keyboard()
      bot.sendMessage(chat_id, START_MSG, reply_markup=kb)
          

Código del procesado de callback


def process_callback(msg):
  bot.answerCallbackQuery(msg['id'])  # ack callback
  chat_id = msg['from']['id']
  data = msg['data'].split()

  if data[0] == 'days':
      kb = get_days_keyboard()
      bot.sendMessage(chat_id, DAYS_MSG, reply_markup=kb)
  elif data[0] == 'schedules':
      process_schedules(chat_id, data[1])
  elif data[0] == 'slots':
      process_slots(chat_id, data[1], data[2])
          

Otras ideas

  • Ejecución asíncrona de tareas tipo Celery
  • Creación de miniaturas al subir imágenes a S3
  • API dinámica de una web alojada en S3
  • API paralelizable de baja latencia
  • Despliegue de aplicación Django o Flask

Gracias a todos

Código disponible en Github