Por: Josue Soriano Publicado el: 2017-10-11 21:33:27, 2630
En los últimos días he estado indagando en la creación de un chatbot que reemplace el sistema de comunicacion del Alimentador de Mascotas el cual funciona por medio de Emails he indagando un poco me tope con los Chatbots de Telegram este sistema de chats permite programar un chat en telgram que responda segun lo que una persona le escriba al chat. Este sistema tiene una API Publica que permite utilizar cualquier lenguaje de programacion para poder crear un sistema de respuestas en base a las peticiones de los usuarios del chatbot.
Para este articulo, voy a desarrollar un chatbot que funcione de la siguiente manera:
Antes de comenzar a programar debemos decirle a telegram que vamos a crear un nuevo bot; obiamente para esto necesitamos tener instalado telegram en nuestro Celular, en el APP de telegram utilizamos el buscador para localizar a BotFather (si estan viendo este articulo desde un celular, este link los llevara al chat directamente) Una vez aqui procedemos a la creación del Bot con el comando /newbot:
este comando nos pide dos cosas: El Nombre con el que se presentara el bot y el nombre de usuario del Bot, este ultimo debe ser sin espacios y debe terminar en "bot"; hecho esto nos dara el mensaje de finalizado y nos mostrara el accesso por medio de una clave (en este caso nos genero 419578624:AAGahgdR-3zKRmCBw-HKgLrQlC5UyKMQSlQ), esta clave es importante ya que es la que le daremos a nuestro codigo para que pueda responder a los usuarios y la podemos cambiar posteriormente utilizando otros comandos del BotFather, pero por los momentos vamos a dejar esta.
Con esto ya tenemos todo listo para poder hacer nuestro Bot, y para hacer el servicio que va a estar pendiente de lo que escriban nuestros usuarios; para ello vamos a utilizar como lenguaje de programacion Python y una libreria de clases llamada telepot.
Telepot es una libreria de objetos que nos permite comunicarnos por medio de funciones sencillas y con nombres similares a los que tiene la API de Telegram, para tener esta libreria podemos utilizar el instalador de paquetes de Python pip, para los usuarios de Windows les dejo este largo y aburrido tutorial (y de paso en Ingles) para instalar el lenguaje de programacion junto con su instalador de Paquetes; les garantizo que funciona muy bien en windows (ya lo probe, en algunos lugares me toca trabajar con windows). En sistemas operativos Linux basados en Debian basta con el comando:
$ sudo apt-get install build-essential python-dev python-smbus python-pip
Listo ahora que ya tenemos python y pip (ya sea en windows o en linux) podemos correr el siguiente comando para instalar las librerias de python que vamos a necesitar:
pip install telepot httplib2 html2text
Con lo anterior ya tenemos listo todo para poder hacer un archivo de python que se conecte a telegram, sin embargo antes de conectarnos a telegram vamos a definir las funciones que permiten conectarse a las apis de Chuck Norris y de Trivia Number. Para que no se pierdad (como lo hice yo cuando estaba tratando de entender el lenguaje) en python no existen corchetes ni, puntos y comas al final de cada linea, el lenguaje consiste en escribir una linea de codigo, y si las lineas siguientes pertenecen a una estructura de control de flujo (condiciones, ciclos o casos), se utiliza un sistema de sangrias, que pueden ser espacios o tabulaciones, en lo personal prefiero las tabulaciones, les dejo el ejemplo de las funciones:
import httplib2
import json
import html2text
# Función que consigue bromas de Chuck Norris de Internet. Utiliza un HTTP GET y luego un analizador JSON
def getChuckNorrisQuote():
# La base de datos donde se almacenan las bromas
ICNDB="http://api.icndb.com/jokes/random"
# Realizar una solicitud HTTP para obtener la respuesta (resp) y el contenido (content)
resp, content = httplib2.Http().request(ICNDB)
# El contenido está en el siguiente formato JSON y necesita ser analizado:
# {u'type': u'success', u'value' : {u'joke': 'Texto del chiste', u'id': 238, u'categories': []}}
parsed_content = json.loads(content)
joke = "\n\n** Chiste Random de Chuck Norris **:\n" + html2text.html2text(parsed_content['value']['joke'])
return joke
# Función que obtiene un número trivial de Internet. Utiliza un HTTP GET y luego un analizador JSON
def getNumberTrivia():
# La base de datos donde se almacenan las trivia
NUMDB="http://numbersapi.com/random/trivia?json"
# Realizar una solicitud HTTP para obtener la respuesta (resp) y el contenido (content)
resp, content = httplib2.Http().request(NUMDB)
# El contenido está en el siguiente formato JSON y necesita ser analizado:
# {u'text': u'Texto de la trivia', u'type' : u'trivia, u'number': , u'found': True}
parsed_content = json.loads(content)
trivia = "\n\n** Curiosidad del Numero " + str(parsed_content['number']) + " **\n"
trivia = trivia + parsed_content['text']
return trivia
Explicando un poco el codigo anterior: las primeras tres lineas importan a nuestro programa las clases necesarias para poder ejecutar nuestras funciones, en las lineas "def" estamos declarando la funcion al final se colocan dos puntos ":" para decirle al codigo que lo que sigue acontinuacion se ejecutara cuando se llame la funcion correspondiente, por ello las siguientes lineas van tabuladas a la derecha.
Ahora ya que tenemos las funciones necesarias vamos a hacer una funcion que se encargara de contestar los chats de nuestro BOT utilizando las funciones anteriores, el resultado final seria:
# coding=utf8
import time
import telepot
import httplib2
import json
import html2text
from telepot.loop import MessageLoop
#Variables Globales
BOTKEY = "419578624:AAGahgdR-3zKRmCBw-HKgLrQlC5UyKMQSlQ" #aqui debe ir la llave generada por el botfather
bot = telepot.Bot(BOTKEY)
# Función que consigue bromas de Chuck Norris de Internet. Utiliza un HTTP GET y luego un analizador JSON
def getChuckNorrisQuote():
# La base de datos donde se almacenan las bromas
ICNDB="http://api.icndb.com/jokes/random"
# Realizar una solicitud HTTP para obtener la respuesta (resp) y el contenido (content)
resp, content = httplib2.Http().request(ICNDB)
# El contenido está en el siguiente formato JSON y necesita ser analizado:
# {u'type': u'success', u'value' : {u'joke': 'Texto del chiste', u'id': 238, u'categories': []}}
parsed_content = json.loads(content)
joke = "\n\n** Chiste Random de Chuck Norris **:\n" + html2text.html2text(parsed_content['value']['joke'])
return joke
# Función que obtiene un número trivial de Internet. Utiliza un HTTP GET y luego un analizador JSON
def getNumberTrivia():
# La base de datos donde se almacenan las trivia
NUMDB="http://numbersapi.com/random/trivia?json"
# Realizar una solicitud HTTP para obtener la respuesta (resp) y el contenido (content)
resp, content = httplib2.Http().request(NUMDB)
# El contenido está en el siguiente formato JSON y necesita ser analizado:
# {u'text': u'Texto de la trivia', u'type' : u'trivia, u'number': , u'found': True}
parsed_content = json.loads(content)
trivia = "\n\n** Curiosidad del Numero " + str(parsed_content['number']) + " **\n"
trivia = trivia + parsed_content['text']
return trivia
def botSupervisor(msg):
content_type, chat_type, chat_id = telepot.glance(msg)
#Este es un comentario
if content_type == 'text':
MENSAJE = msg['text']
if MENSAJE == "/start":
bot.sendMessage(chat_id, "Bienvenido a Joker 504 Bot utiliza los siguientes comandos: \n/chucknorris\n/numbertrivia")
elif MENSAJE == "/chucknorris":
#llamamos la funcion getChuckNorrisQuote() y almacenamos el chiste en la variable joke:
joke = getChuckNorrisQuote();
#Enviamos el valor de la variable joke por medio de mensaje
bot.sendMessage(chat_id, joke)
elif MENSAJE == "/numbertrivia":
#llamamos la funcion getNumberTrivia() y almacenamos el chiste en la variable joke:
trivia = getNumberTrivia();
#Enviamos el valor de la variable trivia por medio de mensaje
bot.sendMessage(chat_id, trivia)
else:
bot.sendMessage(chat_id, "No entiendo lo que pides")
#Programa principal
try:
MessageLoop(bot, botSupervisor).run_as_thread()
while True:
time.sleep(10)
except KeyboardInterrupt:
print "Proceso cancelado por el Usuario"
except SystemExit:
print "Error al iniciar el proceso"
Expliquemos un poco lo anterior, comencemos con las primeras lineas:
# coding=utf8
import time
import telepot
import httplib2
import json
import html2text
from telepot.loop import MessageLoop
Estas las primeras lineas nos sirven, como mencione anteriormente, para llamar los objetos necesarios para que nuestro programa funcione, en el caso del from telepot.loop import MessageLoop estoy refiriendo un objeto especifico que se encuentra desntro de la libreria telepot.loop, este objeto MessageLoop nos ayudara a crear un ciclo infinito que va estar revisando constantemente lo que las personas escriban al chat; ahora las lineas de las variables:
#Variables Globales
BOTKEY = "419578624:AAGahgdR-3zKRmCBw-HKgLrQlC5UyKMQSlQ" #aqui debe ir la llave generada por el botfather
bot = telepot.Bot(BOTKEY)
La variable BOTKEY tendra llave con la que nos conectamos a nuestro BOT y la variable bot sera la variable encargada de crear el ciclo infinito que mencione anteriormente; las siguientes lineas corresponden a las funciones getChuckNorrisQuote() y getNumberTrivia() que se encargaran de hacer las solicitudes de los chistes y trivias; posterior a esto llegamos a la funcion botSupervisor(msg) esta funcion sera la que se ejecutara de forma infinita hasta que nosotros cancelemos el programa con la combinacion Ctrl+C:
def botSupervisor(msg):
content_type, chat_type, chat_id = telepot.glance(msg)
#Este es un comentario
if content_type == 'text':
MENSAJE = msg['text']
if MENSAJE == "/start":
bot.sendMessage(chat_id, "Bienvenido a Joker 504 Bot utiliza los siguientes comandos: \n/chucknorris\n/numbertrivia")
elif MENSAJE == "/chucknorris":
#llamamos la funcion getChuckNorrisQuote() y almacenamos el chiste en la variable joke:
joke = getChuckNorrisQuote();
#Enviamos el valor de la variable joke por medio de mensaje
bot.sendMessage(chat_id, joke)
elif MENSAJE == "/numbertrivia":
#llamamos la funcion getNumberTrivia() y almacenamos el chiste en la variable joke:
trivia = getNumberTrivia();
#Enviamos el valor de la variable trivia por medio de mensaje
bot.sendMessage(chat_id, trivia)
else:
bot.sendMessage(chat_id, "No entiendo lo que pides")
La funcion trabaja con las siguientes variables:
Las siguientes instrucciones definen que para proseguir se requiere que el mensaje sea unicamente texto: if content_type == 'text':
lo siguiente sera Evaluar el texto enviado, para ello tenemos la condicion que evalua si es /start, /chucknorris, /numbertrivia o cualquer otro texto lo descartamos en el else:
else:
bot.sendMessage(chat_id, "No entiendo lo que pides")
la funcion bot.sendMessage se encarga de enviar el texto al usuario que tenga un chat_id especifico.
Por ultimo necesitmos ejecutar la funcion anterior por medio del loop infinito, para ello creamos un try (intento) que ejecutara la funcion botSupervisor(msg) de manera infinita hasta que se cancele el programa o el programa genere un error:
#Programa principal
try:
MessageLoop(bot, botSupervisor).run_as_thread()
while True:
time.sleep(10)
except KeyboardInterrupt:
print "Proceso cancelado por el Usuario"
except SystemExit:
print "Error al iniciar el proceso"
Para ejecutarlo se guarda el archivo, yo lo nombre joker504bot.py y lo ejecutamos en la termina, con esto, estamos listos para probarlo desde nuestro telefono:
$ python joker504bot.py
Como les mencione anteriormente, la idea de aprender esto es combinar este conocimiento con el Script del alimentador de Mascotas para que ahora este funcione por medio de comandos de un ChatBot, espero mi proximo articulo trate sobre este cambio.