Este es uno de los capítulos del tutorial Exprimiendo Telegram. Crea tu propio bot para Telegram.. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.
En el capítulo anterior de esta serie Exprimiendo Telegram, un bot interactivo, vimos como interactuar con nuestro bot a base de enviarle ordenes o mediante el uso de filtros. En este nuevo capítulo, vamos a dar un paso mas allá, y vamos a interactuar con nuestro bot mediante un teclado para Telegram.
¿En que consiste un teclado para Telegram? Se trata de facilitar al usuario de nuestro bot, la introducción de comandos, o la elección de opciones. En general, estaremos de acuerdo que escribir en el móvil o incluso en una tableta no es lo más cómodo del mundo. A menos evidentemente que tengas un teclado bluetooth, y ni con esas, creo.
Para ayudar al usuario, Telegram, pone a nuestra disposición una serie de herramientas que nos van a simplificar considerablemente el trabajo a la hora de crear estos teclados.
Un teclado para Telegram
Antecedentes
Como comentaba en la introducción, en el artículo vimos como interactuar con nuestro bot utilizando dos tipos de negociadores. Estos tipos de negociadores eran,
CommandHandler
, que nos permitía definir órdenes para darle a nuestro botMessageHandler
, que conseguía que nuestro bot actuara en base a una serie de filtros.
A continuación vamos a ver un nuevo tipo de negociador que nos permitirá mejorar nuestra interacción con el usuario en base a utilizar un teclado para Telegram.
Un teclado para Telegram integrado en el chat
El primero de los negociadores a tener en cuenta es CallbackQueryHandler
. Se trata de un negociador que actúa en base a una respuesta. Esta respuesta nos la dará el usuario a través de un teclado que estará integrado en el propio chat, tal y como puedes ver en la siguiente captura de pantalla.
Si recuerdas en el capítulo anterior, para ver el estado de un servicio, teníamos que utilizar el comando /mariadb
o apache
. Con esta nueva técnica, introducimos una sola orden /info2
y el bot, nos muestra un mensaje, Elige el servicio
y las opciones. Pulsando una de las opciones nos indicará el estado de ese servicio.
¿Esto como se integra en nuestro bot?. Al igual que hicimos en el capítulo anterior, definimos una nueva función, como la que ves a continuación,
def info2(bot, update): keyboard = [[InlineKeyboardButton("MariaDB", callback_data='1'), InlineKeyboardButton("Apache", callback_data='2')], [InlineKeyboardButton("OpenVPN", callback_data='3')]] reply_markup = InlineKeyboardMarkup(keyboard) update.message.reply_text('Elige el servicio:', reply_markup=reply_markup)
Aquí hemos utilizado dos nuevos objetos,
InlineKeyboardButton
que nos permite crear un botón, con un texto, por ejemploMariaDB
y un valor de salidacallback_data
.InlineKeyboardMarkup
que es el que construye el teclado, pasándole una lista de listas deInlineKeyboardButton
. Cada una de las listas se corresponde con una fila de botones. Así, por ejemplo, en el ejemplo anterior, aparece un teclado, con dos botones en la primera fila y un botón en la segunda.
Además de definir la función, debemos asignarla al negociador y este al despachador, tal y como hicimos en el capítulo anterior. Esto se corresponde con el siguiente código,
info2_handler = CommandHandler('info2', info2) dispatcher.add_handler(info2_handler)
Ahora nos falta trabajar con la salida del teclado. Para ello, debemos crear una nueva función button
que indico a continuación,
def button(bot, update): query = update.callback_query logger.info('TELEGRAM query data: "%s" type: "%s"' % ( str(query.data), str(type(query.data)))) if query.data == '1': salida = run_command('systemctl status mariadb') if salida is not None: if salida.find('running') > -1: msg = 'MariaDB está funcionando!' elif salida.find('dead') > -1: msg = 'MariaDB está parado!' else: msg = 'Algo no va bien! MariaDB está parado!' else: msg = 'Algo no va bien! MariaDB está parado!' bot.edit_message_text(text=msg, chat_id=query.message.chat_id, message_id=query.message.message_id) elif query.data == '2': salida = run_command('systemctl status apache2') if salida is not None: if salida.find('running') > -1: msg = 'Apache está funcionando!' elif salida.find('dead') > -1: msg = 'Apache está parado!' else: msg = 'Algo no va bien! Apache está parado!' else: msg = 'Algo no va bien! Apache está parado!' bot.edit_message_text(text=msg, chat_id=query.message.chat_id, message_id=query.message.message_id) elif query.data == '3': salida = run_command('systemctl status openvpn') if salida is not None: if salida.find('Active: active') > -1: msg = 'OpenVPN está funcionando!' elif salida.find('dead') > -1: msg = 'OpenVPN está parado!' else: msg = 'Algo no va bien! OpenVPN está parado!' else: msg = 'Algo no va bien! OpenVPN está parado!' bot.edit_message_text(text=msg, chat_id=query.message.chat_id, message_id=query.message.message_id)
Lo importante de esta función se recoge en la primera línea query = update.callback_query
y por supuesto en la comparación query.data == X
. Esto se corresponde con los valores asignados en la función anterior.
Ahora, igual que en el caso anterior, debemos definir el negociador y asignarlo al despachador, aunque en este caso, lo hacemos en una única línea,
dispatcher.add_handler(CallbackQueryHandler(button))
Ya lo tenemos. Si te fijas es tremendamente sencillo, y sin lugar a dudas, muy cómodo para el usuario final.
Tengo que indicar que a mi me ha dado muchos quebraderos de cabeza, porque no conseguía hacerlo funcionar. Finalmente, entré en un grupo de Telegram >>> telegram.Bot(), donde me dieron la solución al problema. Este es el grupo oficial de python-telegram-bot.
La cuestión, es el punto de inicio del bot, que ya utilizamos en el capítulo anterior. Me refiero a la línea,
updater.start_polling()
Esta, hay que reemplazarla por,
updater.start_polling(allowed_updates=[])
Un teclado para Telegram también llega a senderbot
Como no podía ser de otra forma, he añadido también un teclado para Telegram a senderbot. Ahora, puedes ver el estado de los servicios Apache
, MariaDB
y OpenVPN
, con tan solo ejecutar la orden /info2
y seleccionando el servicio que quieras consultar.
Para instalar el bot, tienes que ejecutar las siguientes órdenes,
sudo add-apt-repository ppa:atareao/telegram sudo apt update sudo apt install senderbot
Si ya lo instalaste en versiones capítulos anteriores, solo tienes que actualizar el sistema, ejecutando la orden sudo apt update
.
Una vez instalado o actualizado, solo te queda ponerlo en marcha. Para ello, ejecuta la orden,
senderbot -o
Por otro lado, indicar que si utilizas python-telegram-bot
en la Raspberry, las dependencias python3-future
y python3-certifi
, no se encuentran disponibles en Jessie aunque si en Stretch.
Para instalarlas en Jessie, tienes que añadir la línea deb https://ftp.debian.org/debian jessie-backports main
al final de /etc/apt/sources.list
. Actualizar ejecutando la orden sudo apt update
y a continuación instalar, ejecutando las siguientes órdenes,
sudo apt -t jessie-backports install python3-future sudo apt -t jessie-backports install python3-certifi
Por supuesto, puedes consultar el código de este bot en senderbot en GitHub. Igualmente indicarte que si no quieres o no sabes o no te interesa modificar el código del bot, pero quieres que añada una funcionalidad adicional que te interese, o que modifique una parte o lo que sea, para poder utilizar tu bot en tu equipo, no tienes mas que contactar conmigo, y hacemos las modificaciones que necesites.
Conclusiones
Con este nuevo negociador, y la posibilidad de tener un teclado integrado en el propio chat, va a simplificar a los usuarios el uso del bot, sin tener que buscar la orden entre las definidas por el desarrollador.
Sin embargo, todavía podemos dar un paso mas y entrar en toda una conversación con el bot. Para ello, es necesario utilizar un nuevo negociador, ConversationHandler
que veremos en el próximo capítulo de esta serie.
Como has podido ver, crear un teclado para que el usuario interactúe con el bot es realmente sencillo. Las opciones y posibilidades que esto nos ofrece son espectaculares, sobre todo de cara al usuario.