Sábado, Diciembre 16, 2017

Exprimiendo Telegram. Un bot interactivo para preguntas y respuestas

telegram-bot-interactivo

Hasta el momento nuestro bot solo nos enviaba mensajes, imágenes o archivos cuando le habíamos programado. Cierto es que esto es una gran ventaja, puesto que podemos hacer que nos avise cuando se produzcan determinados eventos. En el artículo de hoy, vamos a dar un paso adicional hacia el bot interactivo.

¿A que me refiero con un bot interactivo?. Pues tan sencillo como que podamos interactuar con él. Es decir, le podamos preguntar, u ordenar  que haga algo, y nuestro bot nos responda.

Y, ¿para que necesitas un bot interactivo?. Un bot interactivo tiene cientos de utilidades, pero posiblemente, la mayor de sus utilidades es la confianza. Me explico. Aunque nuestro primigenio bot lo podemos programar para que nos avise ante un determinado suceso, ¿quien nos asegura que el bot funciona? o mejor, que pasa cuando tu máquina ha caído sin previo aviso. Por ejemplo, cuando hay un corte de tensión, no se produce una parada programada, con lo que nuestro bot no nos avisará.

Y entonces ¿donde reside la confianza?, en el simple hecho de que podemos comunicar con nuestro bot interactivo. Así, por ejemplo, si no sabemos si nuestra máquina remota está funcionado, simplemente, le podemos preguntar a bot interactivo.

Por mucho que confíes en la programación que hayas realizado para que ante un evento determinado tu bot te avise, siempre te quedarán dudas.  Somos humanos, nos equivocamos, y tenemos dudas. Pero si podemos  preguntarle a nuestro a nuestro bot interactivo, seguro que estaremos  más tranquilos.

Vamos allá adelante con nuestro bot interactivo

Desarrollo de un bot interactivo

Como he comentado en la introducción de este artículo de Exprimiendo Telegram, la idea es implementar un bot interactivo, es decir, que responda ante nuestras acciones.

Para conseguir nuestro objetivo utilizaremos otro objeto de la librería Python Telegram Bot que estamos utilizando en este tutorial. Se trata del objeto Updater.

El propósito de este objeto es el de recibir todas las actualizaciones de Telegram, y entregarlas a otro objeto, en particular a Dispatcher para que sean procesadas. Esto lo hace en un hilo separado, es decir, en un segundo plano, de tal forma que el usario puede interactuar con el bot.

Así, con unas pocas líneas de código, veremos como se implementa esto,

1.- Declaramos el objeto Updater

updater = Updater(token=token)

2.- Definimos un método

def start(bot, update):
    bot.send_message(chat_id=update.message.chat_id,
                     text="¿Si?, mi amo!")

3.- Definimos el negociador, es decir, el objeto que se encargará de gestionar el evento, y se lo asignamos al despachador,

start_handler = CommandHandler('start', start)
updater.dispacher.add_handler(start_handler)

Por último iniciamos nuestro objeto,

updater.start_polling()
updater.idle()

Como ves es tremendamente sencilla, lo que nos abre todo un mundo de posibilidades con unas pocas líneas de código.

Si te fijas, aquí, toda la responsabilidad recae en los negociadores o Handler, y es precisamente aquí donde nos vamos a centrar.

Los negociadores de nuestro bot interactivo

Existen diferentes tipos de negociadores (Handler) que nos permiten interactuar de diferentes formas. Vamos a verlos todos con detalle, puesto que esto es el meollo de la cuestión, y donde podemos sacarle todo el provecho a nuestro bot interactivo.

CommandHandler

CommandHandler es el negociador (Handler) fundamental. Este se encarga de gestionar las órdenes de Telegram.

Una orden o comando es un mensaje de Telegram que comienza con /. La orden más habitual y que se suele definir generalmente es start. Para ejemplo, tienes la que hemos definido anteriormente.

La definición mínima básica es la que hemos dado en el ejemplo anterior, donde definimos la orden que activará a nuestro negociador y la acción que deberá emprender el despachador,

Así cuando escribamos en Telegram /start, nuestro bot, tal y como lo hemos programado, nos responderá con "¿Si?, mi amo!".

Exprimiendo Telegram. Un bot interactivo para preguntas y respuestas. Inicio.

El resto de parámetros que le podemos pasar a este negociador son opcionales. Sin embargo, quiero destacar pass_args, que es un booleano, que determina si el negociador pasará argumentos.

En particular este parámetro lo utilizamos en senderbot en una de las funciones que le pasamos al negociador. A continuación puedes ver la definición de la función,

def caps(bot, update, args):
    text_caps = ' '.join(args).upper()
    bot.send_message(chat_id=update.message.chat_id, text=text_caps)

Y el negociador, quedará como sigue,

caps_handler = CommandHandler('caps', caps, pass_args=True)
dispatcher.add_handler(caps_handler)

En este ejemplo, lo que hacemos es que todos los argumentos que pasamos a la función, los unimos, separados por espacio y los convierte a mayúsculas. Una vez convertido, el bot, nos manda un mensaje con el resultado.

Exprimiendo Telegram. Un bot interactivo para preguntas y respuestas. Mayúsculas.

MessageHandler

MessageHandler es un negociador que se encarga de gestionar mensajes de Telegram, en particular los mensajes de texto, multimedia o las actualizaciones de estado.

En este negociador hay dos parámetros fundamentales,

  • filters. Establece con que tipo de mensajes interactuará el negociador. Hay diferentes tipos de filtros. De todos los tipos de filtro quiero destacar los siguientes,
  • Filters.text. Para mensajes tipo texto.
  • Filters.audio. Mensajes de audio.
  • Filters.photo. Imágenes.
  • Filters.document. Cualquier tipo de archivo
  • Filters.command. Órdenes o comandos (palabras que comienzan por /).
  • callback. Es la función que asociamos al negociador y que pasaremos al despachador.

Los filtros se pueden combinar. Es decir se puede definir que el mensaje sea o de texto o de audio, para lo que se indicaría Filters.text | Filters.autio.

En el bot que estamos desarrollando he incluido tres negociadores de este tipo. Uno para texto, uno para imagen y un tercero para documento.

MessageHandler con Filters.text

El primero de los negociadores, el de tipo texto, lo único que hace es repetir lo que escribimos. Así cuando escribimos cualquier texto (que no sea una orden), el bot, lo que hará será repetirlo.

La función que realiza el eco es la siguiente,

def echo(bot, update):
    bot.send_message(chat_id=update.message.chat_id,
                     text=update.message.text)

Y la definición del negociador, así como la asignación al despachador tal y como indico a continuación,

echo_handler = MessageHandler(Filters.text, echo)
dispatcher.add_handler(echo_handler)

Si te fijas, hemos definido el filtro del tipo Filters.text, para que solo responda ante mensajes de texto.

MessageHandler con Filters.photo

El siguiente de los negociadores trata con un mensaje tipo photo. Este mensaje tiene la característica de que está compuesto por varios tamaños de imagen. En el ejemplo, lo que hacemos es seleccionar la mas grande, update.message.photo[-1], convertirla a escala de grises, y mandarla de vuelta, tal y como puedes ver en el siguiente código,

def grises(bot, update):
    photo_file = bot.get_file(update.message.photo[-1].file_id)
    response = requests.get(photo_file['file_path'])
    img = Image.open(BytesIO(response.content))
    img = img.convert('LA')
    bio = BytesIO()
    bio.name = 'image.png'
    img.save(bio, 'PNG')
    bio.seek(0)
    bot.send_photo(chat_id=update.message.chat_id,
                   photo=bio)

A continuación definimos el negociador y se lo asignamos al despachador,

grises_handler = MessageHandler(Filters.photo, grises)
dispatcher.add_handler(grises_handler)

En este caso el filtro para seleccionar imágenes es Filters.photo.

Exprimiendo Telegram. Un bot interactivo para preguntas y respuestas. Foto.

En la siguiente imagen puedes ver el resultado de la conversión a escala de grises,

Exprimiendo Telegram. Un bot interactivo para preguntas y respuestas. Grises.

MessageHandler con Filters.document

El último de los filtros que veremos en este artículo asociado al negociador MessageHandler es Filters.document. He querido añadir este filtro para que se vea la diferencia de pasar una imagen a un documento. Aunque inicialmente puede estar claro, lo cierto es que puede dar lugar a confusión. Es posible pasar a Telegram una imagen tanto como photo como document. Fíjate que en la imagen anterior al marcar la opción Comprimir imagen dice Enviar 1 FOTO, mientras que en la siguiente captura de pantalla, dice Enviar 1 archivo.

Exprimiendo Telegram. Un bot interactivo para preguntas y respuestas. Documento.

A continuación encontrarás el código correspondiente a este negociador. Lo que hace es leer el documento y cifrarlo en base64. Esto lo estoy utilizando para incorporar algunas imágenes en el código css de mi pagina. De esta manera la página de estilos de la página es algo mas pesada, pero se reduce el numero de peticiones al servidor.

Una vez cifrada la imagen en base 64 devuelve un mensaje con el texto resultante.

def tobase64(bot, update):
    photo_file = bot.get_file(update.message.document.file_id)
    response = requests.get(photo_file['file_path'])
    encoded_string = base64.b64encode(response.content).decode()
    bot.send_message(chat_id=update.message.chat_id,
                     text=encoded_string)

Como he hecho en los otros casos, a continuación, tienes la definición del negociador y su asignación al despachador,

base64_handler = MessageHandler(Filters.document, tobase64)
dispatcher.add_handler(base64_handler)

Definiendo las órdenes con @BotFather

Una vez definido todas las órdenes que le podemos dar a nuestro bot interactivo, es interesante definir una ayuda, de forma que el usuario sepa que opciones tenemos. Para esto, es necesario que utilicemos a @BotFather, tal y como hemos hecho en otras ocasiones.

Para ello, una vez estemos en la conversación con @BotFather, y utiliza el comando /setcommands selecciona tu Bot

Exprimiendo Telegram. Un bot interactivo para preguntas y respuestas. BotFather.

Pega el listado de todos las órdenes asociadas a tu bot. Por ejemplo, en el caso que nos ocupa, las órdenes serían las siguientes,

start - Inicia el bot
info - Algo de información
donde - Nos da las coordenadas de donde estamos
temp - Nos dice la temperatura de la máquina
samba - Nos dice si el servicio samba está funcionando
mariadb - Nos dice si el servicio mariadb está funcionando
apache - Nos dice si el servicio apache está funcionando
vpn - Nos dice el estado del OpenVPN
caps - Convierte un texto que le pasemos a mayúsculas
stop - detiene el bot

Exprimiendo Telegram. Un bot interactivo para preguntas y respuestas. BotFather. Órdenes.

senderbot se convierte en un bot interactivo

Con lo que hemos visto hasta el momento, ya tienes una clara idea de como trabajar con estos dos tipos de negociadores. Esto lo he incorporado a senderbot para convertirlo en un bot interactivo, con algunas funcionalidades interesantes, y por supuesto las que hemos visto hasta el momento.

Así, si no quieres crear tu propio bot, puedes hacer uso de este, teniendo en cuenta las opciones o posibilidades que tiene.

Para instalar le bot, solo tienes que ejecutar las siguientes órdenes,

sudo add-apt-repository ppa:atareao/telegram
sudo apt update
sudo apt install senderbot

Para iniciar el bot en modo interactivo, tienes que ejecutar la siguiente orden,

senderbot -o

¿Para que utilizo ahora el bot?

Actualmente el bot, lo tengo instalado en la Raspberry Pi, y lo tengo en funcionamiento según la orden que he puesto en el apartado interior. Con las nuevas funcionalidades añadidas al bot interactivo, puedo hacer las siguientes acciones,

  • Preguntar la temperatura a la que se encuentra la Raspberry Pi. Esto funciona no solo para la Raspberry Pi, sino para cualquier dispositivo en el que lo tengas instalado. Otra opción habría sido configurar el bot para que me diga la temperatura cada cierto tiempo, pero mas o menos es estable con lo que no tiene sentido. Mas sentido tiene que nos avise en el caso de que se supere una temperatura determinada. Sin embargo, siempre nos queda la duda de si tenemos algún problema con el bot. De esta manera siempre le podemos preguntar a ver si la Raspberry Pi está calentita.
  • Igualmente en la Raspberry Pi, tengo instalado, entre otros, MariaDB, Apache, Samba y un VPN. Le puedo preguntar al bot interactivo sobre el estado de cada uno de estos servicios. El bot me responderá informándome si está en funcionamiento o si tiene algún problema.
  • He añadido una orden, llamada consejo de forma que cuando la utilizas te responde con una cita del programa fortune
  • Si envías una foto (en modo foto no documento), la convierte a escala de grises, mientras que si envías una imagen en modo archivo, la cifra en base 64, utilizando en ambos casos los procedimientos descritos anteriormente.

El código fuente

Por si quieres crear tu propio bot interactivo, y no quieres partir de cero, o si quieres estudiar el código para mejorarlo, o darle nuevas funcionalidades, indicarte que está disponible en GiHub

En el próximo capítulo…

En el próximo capítulo de esta serie, veremos otros negociadores, y mejoraremos la entrada de datos a nuestro bot. Es decir, crearemos nuestro propio teclado, para poder interactuar de una forma más cómoda…

 

Fuente: atareao

¿Quién está en línea?

Hay 86 invitados y ningún miembro en línea

Contador de Visitas

9075113
Hoy Hoy 856
Ayer Ayer 560
Esta semana Esta semana 4952
Este mes Este mes 13880
Total de Visitas Total de Visitas 9075113

Día con más
visitantes

11-11-2017 : 2493

Gracias por su visita