Despliegue de mi primer chatbot sobre oracle application container cloud service. Diseño de apis con oracle apiary. Parte II

Por Rolando Carrasco O ACE director
Publicado en Diciembre 2017


Esta es la segunda parte de esta serie, en la primera vimos como diseñar la API que vamos a utilizar con nuestro bot. Ahora vamos a escribir un poco de código de Python para que consuma las APIs.


PASO 2 (Desarrollo de mi programa Python)

Lo primero que debes de hacer es tener instalado Python y Django en tu máquina.

Descarga Python 3.1.6 y sobre de él descarga Django. Haz uso de la utilería PIP, para que puedas realizar la instalación de los módulos necesarios.

Para descargar Python, entra aquí:
https://www.python.org/downloads/

El código que vas a utilizar ha sido probado con Python 3.6.1. Esta versión de Python debe ya venir con PIP, para que puedas instalar paquetes.


Primero validemos tu ambiente:


Y para PIP:


Posteriormente, vamos a instalar Django. Para eso ejecuta:


Con esto estás listo para crear a tu bot usando Python y Django.
Los primero que vas a hacer es crear una estructura de directorios sobre las cuales vamos a trabajar el código. Solo realiza las equivalencias según tu sistema operativo. Yo lo haré sobre Microsoft Windows; pero tanto los pasos, como el código funcionan perfectamente sobre Linux. Así que solo realiza las equivalencias en cuanto a los paths y demás.

La estructura de directorios debe quedar así:


Estando sobre la carpeta de mibot vamos a generar nuestro proyecto. Para ello, ejecuta lo siguiente:


Entra a la carpeta otnbot y verás lo siguiente:


Aquí ejecuta lo siguiente:


De manera que se generará la siguiente carpeta: finbot y adentro de ella:


Entra a la carpeta de otnbot y abre el archivo de settings.py y agrega la línea marcada en amarillo:


Posteriormente vamos a ir a la carpeta: C:\OTN\oaccs\mibot\otnbot\otnbot  y abrir el archivos urls.py. Aquí debemos agregar la URL a la cual le enviará los mensajes el FB Messenger. De manera que quede algo así:


Dado que le estamos diciendo que los requests que lleguen a fin_otnbot/ lo mande al archivo  urls.py de nuestro proyecto finbot, debemos de crear dicho archivo.

Genéralo con el siguiente contenido:

      # otnbot/finbot/urls.py
      from django.conf.urls import include, url
      from .views import otnbotView
      urlpatterns = [
        url(r'^754a7121cb13cf3bb01975d8373a8d80a176a3d34ff0052433/?$', otnbotView.as_view()) 
      ] 


Esa cadena de números, letras y caracteres debe ser única.

Yo te sugiero que escribas un programa que genere la cadena, no copies la mía. Usa una propia. Por lo menos cámbiale algo.


Bien. Estamos a punto de entrar al detalle de cómo escribir el código que represente a nuestro bot. Tengamos en cuenta lo siguiente:

  1. Es un código de ejemplo. Lo podemos mejorar, complementar, criticar en conjunto. Mi afán no es mostrar que este sea el mejor código, es simplemente un ejemplo.
  2. Vamos a ver cómo funcionan algunos recursos de la API de Facebook Messenger, esta es una gran API creada por ellos. Fácil de usar, de entender, etc
  3. El código lo vas a poder consultar en mi github. Ahí podemos colaborar para mejorarlo
  4. El código corre sobre cualquier tipo de contenedor que sea capaz de ejecutar Python. Estamos usando 3.6.1.  En esta serie de artículos vamos a usar Oracle Application Container Cloud Service.
  5. La parte de Inteligencia Artificial no es algo que vayamos a cubrir en este artículo. Eso da para muchos otros, no es mi objetivo enfocarme en ello. Vamos a hacer un bot para entender cómo funcionan, entender sus bases.

Habiendo dicho esto, démosle un vistazo al código. Primero que nada, ve a tu carpeta:

C:\OTN\oaccs\mibot\otnbot\finbot   aquí verás estos archivos:


Estoy resaltando el views.py, pues todo lo que vamos a trabajar es sobre de él. Si lo abres en este momento, deberás ver algo así:


Es decir, está vacío. Justamente aquí es donde vamos a escribir nuestro código.

Es el siguiente:

      # -*- coding: utf-8 -*-
      # otnbot/finbot/views.py
      import json, requests, random, re
      from pprint import pprint
      
      from django.views import generic
      from django.http.response import HttpResponse
      from django.views.decorators.csrf import csrf_exempt
      from django.utils.decorators import method_decorator

# A continuacion se puede ver el arreglo de frases, palabras que puede procesar el bot.

comando =    {'sucursales': ["""La lista de sucursales,    es:.""",
        	"""Las    sucursales que tenemos, son:     """],
        'que sucursales tienen':      ["""La lista de    sucursales, es:.""",
        	"""Las    sucursales que tenemos, son:     """],
        'q sucursales tienen':      ["""La lista de    sucursales, es:.""",
        	"""Las    sucursales que tenemos, son:     """],
        'que sucursales hay':      ["""La lista de    sucursales, es:.""",
	        """Las    sucursales que tenemos, son:     """],
        'q sucursales hay':      ["""La lista de    sucursales, es:.""",
    	    """Las    sucursales que tenemos, son:     """],
        'ke sucursales ay':      ["""La lista de    sucursales, es:.""",
        	"""Las    sucursales que tenemos, son:     """],
        'mi numero de folio es 70501':    ["""El estado de su solicitud esta en estado de 
REVISION. """, """La revisión de la solicitud tarda 2 días. Le agradeceremos vistarnos luego de
transcurrido la fase de revisión. """], 'folio 70501':    ["""El estado de su solicitud esta en estado de REVISION. """, """La revisión de la solicitud tarda 2 días. Le agradeceremos vistarnos luego de
transcurrido la fase de revisión. """], 'claro, es el 70501': ["""El estado de su solicitud esta en estado de
REVISION. """, """La revisión de la solicitud tarda 2 días. Le agradeceremos vistarnos luego de
transcurrido la fase de revisión. """], 'folio 7050': [""" Folio inexistente. El folio debe ser de 5 dígitos y está al reverso
de tu ticket. """], 'folio 70501.': [""" Su credito ha sido aprobado. """], 'hay alguna sucursal cercana a este codigo postal': [""" Tu sucursal mas cercana, es:
"""], 'me gustaria saber el status de mi solicitud de credito.': [""" Por supuesto, me indica
su número de folio """], 'me gustaria saber el status de mi solicitud de credito': [""" Por supuesto, me indica
su número de folio """], 'me gustaria saber el estatus de mi solicitud de credito': [""" Por supuesto, me indica
su número de folio """], 'me gustaria saber el estatus de mi solicitud': [""" Por supuesto, me indica su número
de folio """], 'me gustaria saber el status de mi solicitud': [""" Por supuesto, me indica su número
de folio """], 'estatus de mi solicitud': [""" Por supuesto, me indica su número de folio """], 'estatus solicitud': [""" Por supuesto, me indica su número de folio """], 'status': [""" Por supuesto, me indica su número de folio """], 'solicitud': [""" Por supuesto, me indica su número de folio """], 'alguna sucursal cercana a este codigo postal': [""" Tu sucursal mas cercana, es:
"""], 'cual es la sucursal mas cercana a mi codigo postal': [""" Tu sucursal mas cercana, es:
"""], 'horarios': [""" Abrimos de 8AM a 10PM en todas las sucursales. Aqui te esperamos.  """], 'quiero saber el horario de sus sucursales': [""" Abrimos de 8AM a 4PM en todas las
sucursales.
Aqui te esperamos.  """], 'a que hora abren': [""" Abrimos de 8AM a 4PM en todas las sucursales. """], 'a q hora abren': [""" Abrimos de 8AM a 4PM en todas las sucursales. """], 'pedido': [""" Tu pedido ha sido recibido. Gracias. """], 'quiero': [""" Tu pedido ha sido recibido. Puedes recogerlo en la sucursal. Gracias.
"""], 'oye': [""" Sí. Dime. """], 'ver': [""" Por el momento no contamos con mas Sucursales en tu ciudad. """], 'no, gracias': [""" Estamos para servirte. """], 'hola': [""" Hola. ¿En qué te podemos ayudar, """], 'mucho': [""" Esperamos poderle servir mejor en el futuro. Si gusta puede contactar a uno
de nuestros ejecutivos. """], 'ola': [""" Hola. ¿En qué te podemos ayudar, """], 'rechazo': [""" ¿Que fue lo que lo hizo rechazar? """], 'gracias': [""" Perfecto. Gracias por visitar el asistente en linea. """], 'conforme, gracias': [""" Perfecto. Gracias por visitar el asistente de seguimiento de
crédito. """], 'hasta luego': [""" Hasta Luego. """], 'bye': [""" Bye. """] } def fbpostmsg(fb_id, rcvdmsg):    # Limpia el mensaje enviado desde el chat de FB print ("=================== RECBIENDO EL MENSAJE DESDE FB =====================") print (str(rcvdmsg)) # URL de la API de sucursales. Aquí deberás colocar la tuya post_msg_spsbank = 'https://private-ec955f-spsbank.apiary-mock.com/spsbank'   resp = requests.get(post_msg_spsbank) pprint(resp.json())    j = json.loads(resp.text) print (j['Branches'][0]['branchID'])   sucursal = j['Branches'][2]['branchID'] sucursal1 = j['Branches'][0]['name'] sucursal2 = j['Branches'][1]['name'] sucursal3 = j['Branches'][2]['name'] sucursal1url = j['Branches'][0]['image_url'] sucursal2url = j['Branches'][1]['image_url'] sucursal3url = j['Branches'][2]['image_url'] nombre = j['Branches'][2]['name'] print (sucursal) print (nombre)   resultado = '\n' invresultado = '\n'   print ("#### MIDE #####") print (len(j['Branches'])) tamano =  len(j['Branches']) limite = tamano - 1 for i in range(0,tamano): sucursal = j['Branches'][i]['branchID'] nombre = j['Branches'][i]['name'] if i<limite: resultado += str(sucursal) + " " + nombre + ",\n" else: resultado += str(sucursal) + " " + nombre print (resultado)    tokens = re.split(':',rcvdmsg.lower()) print (tokens) msg_text = '' suc = '' bandera = '0' for token in tokens: if token == 'folio 70501.': bandera = '1' if token == 'rechazo': bandera = '2' if token == 'que sucursales tienen': suc = resultado bandera = '3' if token == 'q sucursales tienen': suc = resultado bandera = '3' if token == 'que sucursales hay': suc = resultado bandera = '3' if token == 'q sucursales hay': suc = resultado bandera = '3' if token == 'ke sucursales ay': suc = resultado bandera = '3' if token == 'sucursales': suc = resultado bandera = '3' if token == 'mucho': bandera = '4' if token == 'hola': print ("&&&&& FBID %%%%%") print (fb_id) usrdetailsurl = "https://graph.facebook.com/v2.6/%s"%fb_id usrdetailsparams = {'fields':'first_name,last_name,profile_pic',
'access_token':'EAABydslxyIQBANCsrDFvo0WehhOD9QNrIVvG30dovKnKmDNEQUy2YAJx4XPaGwyTJI5F4pUmmSCdyZB
qWLfo0LPFYQbwSd38mWagy9ZAp9r6PyyYaU0PFF9lzVtda2GeVOZBnMujE3ZAZCpZBmKNVVAUxl2iBueXJyuqhnzrJzIwZDZD'} usrdetails = requests.get(usrdetailsurl, params=usrdetailsparams).json() nombre = usrdetails['first_name'] apellido = usrdetails['last_name'] print (usrdetails) print ("$$$$$ USUARIO  $$$$$") print (nombre) suc = ' ' + str(nombre) + '?' if token == 'ola': print ("&&&&& FBID %%%%%") print (fb_id) usrdetailsurl = "https://graph.facebook.com/v2.6/%s"%fb_id usrdetailsparams = {'fields':'first_name,last_name,profile_pic',
'access_token':'EAABydslxyIQBANCsrDFvo0WehhOD9QNrIVvG30dovKnKmDNEQUy2YAJx4XPaGwyTJI5F4pUmmSCdyZBqWLfo
0LPFYQbwSd38mWagy9ZAp9r6PyyYaU0PFF9lzVtda2GeVOZBnMujE3ZAZCpZBmKNVVAUxl2iBueXJyuqhnzrJzIwZDZD'} usrdetails = requests.get(usrdetailsurl, params=usrdetailsparams).json() nombre = usrdetails['first_name'] apellido = usrdetails['last_name'] print (usrdetails) print ("$$$$$ USUARIO  $$$$$") print (nombre) suc = ' ' + str(nombre) + '?' if token == 'pedido': print ("####### PEDIDO ########") print (tokens[1]) post_complain = 'https://private-ec955f-spsbank.apiary-mock.com/spsbank/complain' request_ped_msg   = json.dumps({"pedido":{"idSucursal":"1","producto":"aspirina","cantidad":"3"}}) response_ped_msg  = requests.post(post_complain, headers={"Content-Type":
"application/json"},data=request_ped_msg) pprint(response_ped_msg.json()) if token == 'hay alguna sucursal cercana a este codigo postal': print ("#######") print (tokens[1]) post_suc_spsbank = 'https://private-ec955f-spsbank.apiary-mock.com/spsbank/zipcode/'
+ tokens[1] resp_suc = requests.get(post_suc_spsbank) pprint(resp_suc.json()) jsuc = json.loads(resp_suc.text) nombre = jsuc['name'] idsuc = jsuc['branchID']    suc = str(idsuc)+ "-" + nombre if token == 'alguna sucursal cercana a este codigo postal': print ("#######") print (tokens[1]) post_suc_spsbank = 'https://private-ec955f-spsbank.apiary-mock.com/spsbank/zipcode/'
+ tokens[1] resp_suc = requests.get(post_suc_spsbank) pprint(resp_suc.json()) jsuc = json.loads(resp_suc.text) nombre = jsuc['name'] idsuc = jsuc['branchID'] suc = str(idsuc)+ "-" + nombre if token == 'cual es la sucursal mas cercana a mi codigo postal': print ("#######") print (tokens[1]) post_suc_spsbank = 'https://private-ec955f-spsbank.apiary-mock.com/spsbank/zipcode/' +
tokens[1] resp_suc = requests.get(post_suc_spsbank) pprint(resp_suc.json()) jsuc = json.loads(resp_suc.text) nombre = jsuc['name'] idsuc = jsuc['branchID'] suc = str(idsuc)+ "-" + nombre if token in comando: print (token)                         msg_text = random.choice(comando[token]) + suc break if not msg_text: msg_text = "Disculpa, no entendi lo que me escribiste." postmsgurl =
'https://graph.facebook.com/v2.6/me/messages?access_token=EAABydslxyIQBANCsrDFvo0WehhOD9QNrIV
vG30dovKnKmDNEQUy2YAJx4XPaGwyTJI5F4pUmmSCdyZBqWLfo0LPFYQbwSd38mWagy9ZAp9r6PyyYaU0PFF9lzVtda2GeVOZBn
MujE3ZAZCpZBmKNVVAUxl2iBueXJyuqhnzrJzIwZDZD'    if bandera == '1': response_msg = json.dumps({"recipient":{"id":fb_id}, "message":{ "attachment":{
"type":"template", "payload":{
"template_type":"button", "text":msg_text, "buttons":[{"type":"web_url",
"url":"http://www.google.com",
"title":"Acepto Credito"},{"type":"postback","title":"Rechazo
Credito","payload":"rechazo"}]}}}}) if bandera == '0': response_msg = json.dumps({"recipient":{"id":fb_id}, "message":{"text":msg_text}}) if bandera == '2': response_msg = json.dumps({"recipient":{"id":fb_id}, "message":{ "attachment":{
"type":"template", "payload":{ "template_type":"button", "text":msg_text,
"buttons":[{"type":"web_url",
"url":"http://www.google.com", "title":"Mal Trato"},{"type":"postback","title":"Mucho
Tiempo","payload":"mucho"}]}}}}) if bandera == '3': response_msg = json.dumps({"recipient":{"id":fb_id}, "message":{"attachment":
{"type":
"template","payload":
{"template_type": "list","elements": [{"title": "Lista de todas nuestras
sucursales","image_url":
"http://www.elfinanciero.com.mx/files/article_main/uploads/2016/07/15/5788fbbc3d31c.jpg",
"subtitle":
"Ingresa para ver mas informacion","default_action":
{"type": "web_url","url": "https://www.banco.com","messenger_extensions":
"true","webview_height_ratio": "tall","fallback_url": "https://www.banco.com"},"buttons":
[{"title":
"IR","type": "web_url","url":
"https://www.google.com","messenger_extensions": "true","webview_height_ratio":
"tall","fallback_url":
"https://www.banco.com"}]},{"title": "Sucursal
1","image_url":sucursal1url,"subtitle":sucursal1,"default_action": {"type": "web_url","url":
"https://www.google.com","messenger_extensions": "true","webview_height_ratio":
"tall","fallback_url": "https://www.bank.com.mx"},"buttons":
[{"title": "Revisar su ubicacion","type": "web_url","url":
"https://www.tudecide.com/Sucursales/Detalle/41/9/Iztacalco","messenger_extensions":
"true","webview_height_ratio": "tall","fallback_url": "https://www.google.com"}]}
,{"title": "Sucursal
2","image_url":sucursal2url,"subtitle":sucursal2,"default_action": {"type": "web_url","url":
"https://www.google.com","messenger_extensions":
"true","webview_height_ratio": "tall","fallback_url": "https://www.bank.com.mx"},"buttons":
[{"title": "Revisar su ubicacion","type":
"web_url","url": "https://www.banco.com","messenger_extensions": "true","webview_height_ratio":
"tall","fallback_url":
"https://www.google.com"}]},{"title": "Sucursal 3","image_url":sucursal3url,"subtitle":sucursal3,
"default_action": {"type": "web_url","url":
"https://www.google.com","messenger_extensions": "true","webview_height_ratio":
"tall","fallback_url": "https://www.bank.com.mx"},"buttons":
[{"title": "Revisar su ubicación","type": "web_url","url":
"https://www.tudecide.com/Sucursales/Detalle/41/9/Tlalpan","messenger_extensions":
"true","webview_height_ratio": "tall","fallback_url": "https://www.google.com"}]}],"buttons":
[{"title": "Ver más...","type": "postback","payload": "ver" }]  }}} }) if bandera == '4': response_msg = json.dumps({"recipient":{"id":fb_id},"message":{"attachment":
{"type":"template","payload":{"template_type":"button","text":msg_text,"buttons":
[{"type":"phone_number","title":"Llamar a un ejecutivo","payload":"+5215513846357"}]}}} }) status = requests.post(postmsgurl, headers={"Content-Type":
"application/json"},data=response_msg) pprint(status.json()) # Aqui se generan las vistas       class otnbotView(generic.View): def get(self, request, *args, **kwargs): if self.request.GET['hub.verify_token'] == '4318232572': return HttpResponse(self.request.GET['hub.challenge']) else: return HttpResponse('Token invalido') @method_decorator(csrf_exempt) def dispatch(self, request, *args, **kwargs): return generic.View.dispatch(self, request, *args, **kwargs) # Aquí se maneja el mensaje recibido por FB def post(self, request, *args, **kwargs): # Convierte el texto en un vocabulario entendible por Python incoming_message = json.loads(self.request.body.decode('utf-8')) print ("==========================  UUUUUU ========================") pprint(incoming_message) # Se hace un loop por cada mensaje recibido por FB # Esto debido a que se pueden recibir multiples mensajes for entry in incoming_message['entry']: for message in entry['messaging']: # Revisa el formato del mensaje # Ya que se pueden recibir varios formatos: message, postback, etc if 'message' in message: # Lo mandamos a la terminal print ("((((((((((((((((((((( EMPEZANDO )))))))))))))))))))))))))))") pprint(message) # Asumimos que solo viene texto # y que lo demás viene como adjunto fbpostmsg(message['sender']['id'], message['message']['text']) if 'postback' in message: # Lo manda a la terminal print ("((((((((((((((((((((( EMPEZANDO )))))))))))))))))))))))))))") pprint(message) # Asumimos que solo viene texto # y que lo demás viene como adjunto. fbpostmsg(message['sender']['id'], message['postback']['payload']) return HttpResponse()

Hagamos una revisión rápida del código:

El código funciona de una manera muy simple, el request llega a esta parte:

      # Aqui se generan    las vistas       
      class otnbotView(generic.View):
      	def    get(self, request, *args, **kwargs):
      		if    self.request.GET['hub.verify_token'] == '4318232572':
      			return HttpResponse(self.request.GET['hub.challenge'])
      		else:
      			return HttpResponse('Token invalido')
      
      @method_decorator(csrf_exempt)
      def dispatch(self,    request, *args, **kwargs):
      return    generic.View.dispatch(self, request, *args, **kwargs)
       # Aquí se maneja el mensaje    recibido por FB
      def post(self,    request, *args, **kwargs):
        # Convierte el texto en un    vocabulario entendible por Python
        incoming_message    = json.loads(self.request.body.decode('utf-8'))
        print    ("==========================     UUUUUU ========================")
        pprint(incoming_message)
        # Se hace un loop por cada mensaje    recibido por FB
        # Esto debido a que se pueden recibir    multiples mensajes
     for entry in    incoming_message['entry']:
       for message in entry['messaging']:
        # Revisa el    formato del mensaje
        # Ya que se pueden recibir varios formatos:    message, postback, etc
        if    'message' in message:
        	# Lo mandamos a la terminal
	        print    ("((((((((((((((((((((( EMPEZANDO )))))))))))))))))))))))))))")
    	    pprint(message)
        	# Asumimos que solo viene    texto
	        # y que lo demás viene    como adjunto
    	    fbpostmsg(message['sender']['id'],    message['message']['text'])
        
      if 'postback' in message:
        # Lo manda a la terminal
        print    ("((((((((((((((((((((( EMPEZANDO )))))))))))))))))))))))))))")
        pprint(message)
        # Asumimos que solo viene    texto
        # y que lo demás viene como adjunto.
        fbpostmsg(message['sender']['id'],    message['postback']['payload'])
      return HttpResponse()

Este bloque es el que recibe el mensaje directamente desde el chat de Facebook.

Esta línea:

if self.request.GET['hub.verify_token'] ==  '4318232572':

Valida el token que en el siguiente capítulo se configurará en el webhook de FB. Digamos que con esto validamos que el mensaje de Facebook es el que esperábamos, y que sí corresponde a nuestra conversación.


Posteriormente el código limpia el mensaje que viene desde FB y valida si vienen uno o varios mensajes. Si todo esto sale bien lo manda a nuestra función:

      fbpostmsg(message['sender']['id'],    message['message']['text'])
      

Esta función ya desarma el JSON que proviene de FB, y realiza la lógica para poder contestarle al usuario.
Aquí adentro es donde hacemos las llamadas a las APIs que hicimos en el artículo anterior, por ejemplo:

	# URL de la API de sucursales
      post_msg_spsbank    = 'https://private-ec955f-spsbank.apiary-mock.com/spsbank'   
     
      resp =    requests.get(post_msg_spsbank)
      pprint(resp.json())
      
        j =    json.loads(resp.text)
        print    (j['Branches'][0]['branchID'])
        
        sucursal =    j['Branches'][2]['branchID']
        sucursal1    = j['Branches'][0]['name']
        sucursal2    = j['Branches'][1]['name']
        sucursal3    = j['Branches'][2]['name']
        sucursal1url = j['Branches'][0]['image_url']
        sucursal2url = j['Branches'][1]['image_url']
        sucursal3url = j['Branches'][2]['image_url']
        nombre = j['Branches'][2]['name']
        print (sucursal)
        print (nombre)
        
        resultado = '\n'
        invresultado = '\n'   
        
        print ("####    MIDE #####")
        print    (len(j['Branches']))
        tamano =  len(j['Branches'])
        limite = tamano - 1
        for i in    range(0,tamano):
        	sucursal = j['Branches'][i]['branchID']
	        nombre    = j['Branches'][i]['name']
    	    if    i<limite:
        		resultado += str(sucursal) +    " " + nombre + ",\n"
        	else:
		        resultado += str(sucursal) + "    " + nombre
        
        print (resultado)

Aquí mandamos a la API de Sucursales (puedes cambiar la URL por la tuya). Y no solo eso, sino que recuperamos la respuesta y la dejamos lista para usarse a lo largo del código. Si alguna pregunta o comentario que nos haga el usuario, tiene que ver con Sucursales, ya estamos listos para responderle.

Pensemos que el usuario quiere saber las sucursales que tiene esta institución financiera, con el uso del API lo puede hacer y después el bot construye un mensaje para responder algo así:


if bandera == '3':
      response_msg = json.dumps({"recipient":{"id":fb_id},    "message":{"attachment": {"type":   
"template","payload": {"template_type":
"list","elements": [{"title": "Lista de todas nuestras sucursales","image_url":
"http://www.elfinanciero.com.mx/files/article_main/uploads/2016/07/15/5788fbbc3d31c.jpg",
"subtitle":
"Ingresa para ver mas informacion","default_action": {"type": "web_url","url":
"https://www.banco.com","messenger_extensions":
"true","webview_height_ratio": "tall","fallback_url": "https://www.banco.com"},"buttons":
[{"title":
"IR","type": "web_url","url":
"https://www.google.com","messenger_extensions": "true","webview_height_ratio":
"tall","fallback_url": "https://www.banco.com"}]},{"title"
"Sucursal 1","image_url":sucursal1url,"subtitle":sucursal1,"default_action":
{"type": "web_url","url":
"https://www.google.com","messenger_extensions": "true","webview_height_ratio":
"tall","fallback_url":
"https://www.bank.com.mx"},"buttons": [{"title": "Revisar su ubicacion","type":
"web_url","url": "https://www.tudecide.com/Sucursales/Detalle/41/9/Iztacalco",
"messenger_extensions":
"true","webview_height_ratio":
"tall","fallback_url": "https://www.google.com"}]},{"title":
"Sucursal 2","image_url":sucursal2url,"subtitle":sucursal2,"default_action":
{"type": "web_url","url": "https://www.google.com","messenger_extensions":
"true","webview_height_ratio":
"tall","fallback_url":
"https://www.bank.com.mx"},"buttons": [{"title": "Revisar su ubicacion","type":
"web_url","url":
"https://www.banco.com","messenger_extensions":"true","webview_height_ratio":
"tall","fallback_url":
"https://www.google.com"}]},{"title": "Sucursal
3","image_url":sucursal3url,"subtitle":sucursal3,"default_action": {"type": "web_url","url":
"https://www.google.com","messenger_extensions":
"true","webview_height_ratio": "tall","fallback_url": "https://www.bank.com.mx"},"buttons":
[{"title": "Revisar su ubicación","type":
"web_url","url": "https://www.tudecide.com/Sucursales/Detalle/41/9/Tlalpan",
"messenger_extensions":
"true","webview_height_ratio":
"tall","fallback_url": "https://www.google.com"}]}],"buttons":
[{"title": "Ver más...","type": "postback","payload": "ver" }]  }}} })


Vemos cómo ese JSON contiene la lista de sucursales y sacamos la respuesta de la llamada de la API. Hay ligas que debes de cambiar para acondicionar tu chatbot y revestirlo. Lo que viene aquí es de ejemplos de ubicaciones en México, pero al leer el mensaje sabrás qué debes de cambiar, por ejemplo:

  1. www.banco.com.mx
  2. www.bank.com.mx

La lista de comandos que le puedes enviar al bot, es la que viene en el arreglo de la parte de hasta arriba, eso lo puedes extender, quitar, modificar a tu conveniencia.

Analiza el código, verás que es muy simple y lo podrás extender a tu modo y gusto.



PREPARAR PAQUETE PARA SUBIR A OACCS (Oracle Application Container Cloud Service)

Al momento debes de tener esta estructura:


Debemos de preparar nuestro paquete para subirlo a OACCS. Lo primero que debemos de hacer crear una carpeta que contenga los módulos de los cuales depende nuestro código.

Así que primero vamos a crear un archivo que se llame requirement.txt con el siguiente contenido:

  Django==1.11.1
  requests==2.6.0
  django-sslserver==0.20

Este archivo colócalo al nivel de manage.py:


Esto le está indicando las versiones y nombres de los módulos de los cuales depende nuestro código.

Ya que lo tengas ejecuta la siguiente instrucción:


Esto generará la carpeta modules con este contenido:


Ahora vuelve a la carpeta de otnbot y vamos a agregar dos archivos mas:

  1. Manifest.json
  2. Start.sh

El primero contiene información de la aplicación a subir a la nube, y debe contener lo siguiente:

	  {
      "runtime": {
      "majorVersion": "3.6.1"
      },
      "command": "sh ./start.sh",
      "isClustered": false,
      "release": {
      "version": "1.0"
      },
      "notes": "Python App FBbot"
      }


Fíjate cómo hace referencia a start.sh, que es lo que el container debe ejecutar para levantar tu aplicación. En un momento verás lo que debe contener ese .sh. El resto es información de la versión de Python; así como opciones de clustering. Igualmente indica la versión de tu app y algunas notas que quieras colocar.

El start.sh, debe lucir así:

	  #!/bin/sh
      export PYTHONPATH=modules
      python manage.py runserver 0.0.0.0:8080


Tu carpeta de otnbot, luce así:

El último paso es simplemente hacer un zip del contenido de todos estos archivos y carpetas. El zip debe lucir así:


En el siguiente artículo, vamos a ver cómo subirlo al OACCS, para finalmente poderlo registrar en FB y usar el bot.

El código del bot lo puedes descargar de aquí:
https://github.com/RCPDevChamp/oracle/tree/master/OTN/oaccs/mibot/otnbot

Siéntete libre de mejorarlo y extenderlo, esa es la intención.



Rolando Carrasco es un Oracle ACE enfocado a las tecnologías de Middleware. Su experiencia es de casi 15 años en la integración de aplicaciones. Actualmente se desempeña como CTO de una firma mexicana de consultoría, llamada S&P Solutions. Rolando ha trabajado con tecnología Oracle desde el 2001, fue parte del equipo de Product Management de Oracle Fusion Middleware, por lo que tiene un background grande en el uso de estas tecnologías a lo largo de la región de latinoamérica. Rolando es co-líder del grupo de usuarios de Oracle en México.