Cómo hacer un bot de SITP

en Python

¿Qué es un bot?

Un bot es un programa que se comunica con humanos vía una aplicación de chat.

¿Qué es un SITP bot?

SITP bot es un bot que ayuda a conocer más información acerca de los buses SITP.

¿Qué es un bus SITP?

Bus SITP es un bus del Sistema Integrado de Transporte Público, que circula por las calles de Bogotá.

¿De dónde el bot obtiene la información?

Haciendo "scraping" de la página de SITP.
El web scraping es una técnica para extraer información de sitios web.

Para realizar scraping en Python se usa una librería llamada Scrapy.

¿Cómo funciona un bot de Telegram?

Polling: un script de Python cada cierto tiempo se conecta a servidores de Telegram y pregunta si hay mensajes nuevos.


Webhook: una URL específica en nuestro servidor a la cual Telegram envía nuevos mensajes.

¿Cómo crear un webhook?

1. Obtener token de Telegram:

¿Cómo crear un webhook?

2. Decir a Telegram el URL dónde estará el webhook:

curl -F "url=https://sitp.vero4ka.info/bot/<token>/" 
    https://api.telegram.org/bot<token>/setWebhook

¿Cómo crear un webhook?

3. Escribir un endpoint para el webhook:

class TelegramCommandReceiveView(View):

    def post(self, request, bot_token):
        if bot_token != settings.TELEGRAM_TOKEN:
            return HttpResponseForbidden('Invalid token')

        try:
            raw = request.body.decode('utf-8')
            payload = json.loads(raw)
        except ValueError:
            return HttpResponseBadRequest('Invalid request body')

        # Haz algo con payload

        return JsonResponse({}, status=200)

¿Cómo me llegan los mensajes?

{  
   "update_id": 302347250,
   "message": {  
      "message_id": 60,
      "from": {  
         "id": 237007449,
         "first_name": "Pepito",
         "username": "pepito123"
      },
      "chat": {  
         "id": 237007449,
         "first_name": "Pepito",
         "username": "pepito123",
         "type": "private"
      },
      "date": 1483840800,
      "text": "Hola",
      "entities":[  
         {  
            "type":"bot_command",
            "offset":0,
            "length":4
         }
      ]
   }
}

¿Cómo puedo responder?

$ pip install telepot
TelegramBot = 
    telepot.Bot(settings.TELEGRAM_TOKEN)

chat_id = payload['message']['chat']['id']

# Enviar un mensaje simple
bot.sendMessage(chat_id, 'Hola')

# Enviar un texto enriquecido
bot.sendMessage(
    chat_id, 
    '*Hola*, ¿cómo vas?', 
    parse_mode='Markdown'
)

¿Cómo puedo responder?

$ pip install emoji 
import emoji

# Enviar un mensaje con emoji
bot.sendMessage(
    chat_id, 
    emoji.emojize(
        'Hola :wink:', 
        use_aliases=True,
    ), 
    parse_mode='Markdown'
)

# Enviar foto
bot.sendPhoto(chat_id, photo)

# Enviar audio
bot.sendAudio(chat_id, audio)

¿Cómo puedo responder?

# Enviar ubicación
bot.sendLocation(chat_id, latitude, longitude)

# Pedir al usuario a enviar su ubicación
keyboard = ReplyKeyboardMarkup(keyboard=[
    [KeyboardButton(
        text='Enviar mi ubicación',
        request_location=True,
    )],
])
bot.sendMessage(
    chat_id,
    'Enviar mi ubicación',
    reply_markup=ReplyKeyboardMarkup(
        keyboard=[
            [KeyboardButton(text="Enviar mi ubicación", request_location=True)]
        ],
    ),
)

¿Cómo puedo responder?

¿Cómo crear un bot de Facebook?

1. Crear una aplicación en Facebook y agregar "Messenger":

¿Cómo crear un bot de Facebook?

2. Configurar un webhook:

¿Cómo crear un bot de Facebook?

3. Para poder verificar que nuestro bot esté bien configurado, Facebook nos mandará una petición GET a nuestro servidor:

GET https://mipagina.com/bot/fb-webhook/
       ?hub.mode=subscribe
       &hub.challenge=1122334455
       &hub.verify_token=una-frase-secreta

y esperará que le respondemos con el código 200 y el contenido del paramentro hub.challenge cuando verify_token coincide con la frase secreta que especificamos, o con el código HTTP 403 en el caso opuesto.

¿Cómo crear un bot de Facebook?

class FacebookCommandReceiveView(View):

    def get(self, request):
        if (
            request.GET.get('hub.mode') == 'subscribe' and 
            request.GET.get('hub.verify_token') 
                == settings.FACEBOOK_VERIFY_TOKEN
        ):
            return HttpResponse(request.GET.get('hub.challenge'))
        else:
            return HttpResponseForbidden()

4. Escribir una vista que se encargará de recibir la petición:

¿Cómo crear un bot de Facebook?

5. Oprimir el botón "Verify and Save". Después de eso Facebook nos dará un token de la aplicación y permitirá configurar el webhook:

¿Cómo crear un bot de Facebook?

6. Suscribirse a los eventos en Messenger:

¿Cómo crear un bot de Facebook?

7. Damos click en "Edit notes" y entramos a el formulario
de configuración:

¿Cómo crear un bot de Facebook?

8. Después de que Facebook verifique el comportamiento de nuestro bot, recibimos el mensaje de aprobación:

¿Cómo crear un bot de Facebook?

9. Cuando nuestro bot esté listo, lo podemos activar para todos los usuarios:

¿Cómo me llegan los mensajes?

{
    "object": "page", 
    "entry": [{
        "messaging": [
            {
                "timestamp": 148596022321686, 
                "message": {
                    "seq": 110377, 
                    "mid": "mid.1424360289686:0b78d5e099", 
                    "text": "Hola"
                }, "recipient": {
                    "id": "2445077123307282"
                }, "sender": {
                    "id": "1341234970435656"
                }
            }
        ], 
        "id": "51247423670015", 
        "time": 1485960807075
    }]
}

¿Cómo puedo responder?

class FacebookCommandReceiveView(View):

    def post(self, request, bot_keyword):
        if bot_keyword != settings.FACEBOOK_VERIFY_TOKEN:
            return HttpResponseForbidden('Invalid token')

        data = json.loads(request.body.decode('utf-8'))

        # Make sure this is a page subscription
        if data['object'] == 'page':
            # Iterate over each entry - there may be multiple if batched
            for entry in data['entry']:
                # Iterate over each messaging event
                for event in entry['messaging']:
                    if event.get('message'):
                        # Recibimos un mensaje
                    elif event.get('delivery'):
                        # Mensaje recibido
                    elif event.get('read'):
                        # Mensaje leído
                    elif event.get('postback'):
                        # Postback, por ejemplo, de un botón
                    # ...

        return HttpResponse()

¿Cómo puedo responder?

recipient_id = event['sender']['id']
message = event['message']
message_text = message.get('text', '')

if 'hola' in message_text:
    payload = {
        'message': {
            'text': 'Hola :)',
        },
        'recipient': {
            'id': recipient_id,
        }
    }

    base_url = 'https://graph.facebook.com/v2.6/me/messages'
    response = requests.post(
        '{}?access_token={}'.format(base_url, ACCESS_TOKEN),
        json=payload,
    )
    if response.status_code == 200:
        response_body = response.json()
    else:
        logger.error('Unable to send message')

¿Cómo puedo enviar un adjunto?

# Enviar un adjunto: 
# imagen, audio, video, archivo

payload = {
    'message': {
        'attachment': {
            'type': 'image',
            'payload': {
                'url': image_url,
            }
        }
    },
    'recipient': {
        'id': recipient_id,
    }
}

¿Cómo puedo pedir la ubicación?

payload = {
    'message': {
        'text': message,
        'quick_replies': [{
            'content_type': 'location',
        }]
    },
    'recipient': {
        'id': recipient_id,
    }
}

Se puede pedir a usuario a enviar información ​específica por medio de "Quick Replies":

¿Cómo puedo enviar la ubicación?

No se puede :(

 

Pero es posible generar una imagen del mapa, usando, por ejemplo, los mapas estáticos de Google o Mapbox:

 

 

https://api.mapbox.com/v4/mapbox.streets/
    pin-s+f44({long},{lat})/
    {long},{lat},15/300x200.png?
    access_token={access_token}

¡Gracias por su atención!

@vero4ka_ru

https://telegram.me/sitp_bot

https://www.facebook.com/SITPbot

Cómo hacer un bot de SITP en Python

By Vera Cansadadeserfeliz

Cómo hacer un bot de SITP en Python

  • 7,081