Conectando el lambda de una skill a una API externa
Joaquín Engelmo (a.k.a. Kini)
Posted on September 4, 2019
Uno de los temas pendientes que tenía en mi skill "Estrenos de Cine" era conectarla a una API externa que me diera la info de las películas. Hasta ahora tenía un fichero en formato JSON en el propio lambda pero tenía que estar actualizando a mano y, obviamente, esto no escala :)
Conectar una skill a una API externa no debería afectar en nada al modelo ya que lo que cambia es la "fuente" de datos con los que se trabaja en el lambda. No será necesario volver a pasar por certificación porque lo que estamos cambiando es el server y con actualizar el código desplegado en la la versión que usa la skill de live bastaría.
The Movie DB API
Lo primero es encontrar la API adecuada para nuestra skill. La información que necesita mi skill es el listado películas que están por estrenar para un país en concreto con, al menos, los siguientes datos por película: título y fecha de estreno.
Aunque parezca muy simple, el tema del título tiene su parte interesante. Al menos en España traducimos (o cambiamos completamente) los títulos de las películas. A veces esa traducción al español no es completa sino que, en el mismo título, combinamos varios idiomas como "Vengadores: Engdame". Otras veces no traducimos nada como "Toy Story 4".
Esto es un reto a la hora de crear la respuesta para nuestro skill ya que al estar creado para español es el idioma que usará. Pero en ejemplos como los anteriores tendremos que ver cómo manejar estos escenarios si queremos intentar ofrecer la mejor experiencia al usuario. Os contaré en otro post cómo he afrontado yo esta casuística, usando SSML, para indicar a Alexa el idioma que tiene que usar al decir el título de cada película.
Dejando a un lado este tema, encontré una API que cubría lo que necesitaba:
- Poder pedir por las películas que están por estrenar
- Poder indicar el país y el idioma esperado
- Tener un modelo de respuesta con, al menos, el título de la película y su fecha de estreno
Teniendo en cuenta lo anterior pude encontrar TheMovieDB API, una API de uso gratuito, accesible por HTTP con respuesta JSON y con unos límites que no suponían un problema para el uso que tiene mi skill. Además tiene un buen foro de soporte y estadísticas de uso por día.
Entre los muchos endpoint que tiene, existe uno que justamente me da lo que buscaba y, además, podría paginar resultados si preparara mi skill para eso. El tema de la paginación y la experiencia en asistentes de voz da también para otro post :)
Como se puede ver en la imagen anterior, podemos generar una query con lo que nos interesa. Nos basta con usar el formato indicado y obtener una API Key. El proceso es muy sencillo y no merece la pena describirlo por aquí. Os pongo el enlace con la info necesaria para empezar.
Si hacemos una petición de prueba podremos ver el modelo resultante de la llamada. Si nos fijamos en la imagen anterior vemos que, además del título y de la fecha de estreno, tenemos también un idioma original y un título original. Esto lo usaremos a la hora de decidir con qué idioma Alexa tendrá que decirlo al usuario.
Usando Retrofit2 para conectar la lambda con la API
Viniendo del mundo JVM me era bastante natural y sencillo optar por Retrofit2 para conectar con la API. Ya lo he usado más veces y, sin poder comparar con muchas otras opciones, me parece de lo más sencillo que hay para lo que yo necesitaba. No hay un único approach para hacer esto y mi diseño no es el mejor para sistemas más grandes y temas como el testing. Todo feedback es bienvenido pero por dejar claras las expectativas :D
Lo primero es añadir las dependencias necesarias al proyecto del lambda. En este caso voy a añadir también la del GSON converter que usaré a la hora de inicializar Retrofit.
Lo siguiente que vamos a crear es el modelo que va representar la respuesta de la API. El modelo básico de cada película ya lo tenía en el código actual pero le añadí campos para manejar también el idioma y el título original que usaremos en otro post.
Además nos hace falta una clase para representar la salida de la respuesta a la API con el listado de películas.
Una vez tenemos el modelo vamos a crear la clase que representa la API a la cuál vamos a atacar. No tiene mucho misterio, lo único es añadir bien los query params que vamos a necesitar para nuestras peticiones e indicar correctamente el tipo resultado.
Para hacer uso de la API y alojar toda la lógica de Retrofit creo una clase nueva. Tener esta clase me permite encapsular toda la lógica de acceso a la API externa y será el sitio para inicializar Retrofit y acceder a la API Key que tendremos como variable de entorno.
Esa variable de entorno se declara en la consola de AWS Lambda.
Como paso final queda hacer uso del servicio anterior desde la clase que antes usaba el fichero JSON con las películas. Al tener eso separado desde el principio de la lógica del handler me permite poder "cambiar la fuente" de datos modificando lo mínimo el handler.
En este caso la modificación necesaria del handler ha sido para la recuperación del idioma de la request. Esa información la usaremos para pasar a la API la región y el lenguaje.
Ha quedado un post más largo de lo que esperaba pero creo que es bastante completo. Si estás haciendo una skill con lambda en algún lenguaje de la JVM creo que te podría ser útil.
He dejado sin explicar el tema de marcar el idioma de los títulos películas con SSML para que Alexa los diga correctamente. Esto os lo cuento en el siguiente post :)
Posted on September 4, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.