Skip to content

Instantly share code, notes, and snippets.

@softwarechido
Last active April 23, 2019 22:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save softwarechido/523067f4489beea7cdca0b25a38f2468 to your computer and use it in GitHub Desktop.
Save softwarechido/523067f4489beea7cdca0b25a38f2468 to your computer and use it in GitHub Desktop.
Agregamos templates de APL y payload para parametrizar las imagenes
// lambda
// Este ejemplo es una demostración de como manejar intents en una skill de Alexa utilziando el Alexa Skills Kit SDK (v2)
const Alexa = require('ask-sdk-core');
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
},
handle(handlerInput) {
const speechText = 'Hola! bienvenido a Nutrición Inteligente. ¿Cómo te puedo ayudar?';
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('Nutrición Inteligente')
.reprompt('¿Cómo te puedo ayudar?')
.addDirective({
type: 'Alexa.Presentation.APL.RenderDocument',
version: '1.0',
document: require('./welcome.json'),
datasources: {}
})
.getResponse();
}
};
const HolaMundoIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HolaMundoIntent';
},
handle(handlerInput) {
const speechText = 'Hola Mundo!';
return handlerInput.responseBuilder
.speak(speechText)
//.reprompt('agrega un texto de reprompt si deseas dejar la sesión abierta para que el usuario responda. No olvide cerrar con una pregunta. ¿Cómo te puedo ayudar?')
.getResponse();
}
};
const ConsejoIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'ConsejoIntent';
},
handle(handlerInput) {
const listaConsejos = [
'Alimentate de forma balanceada entre carbohidratos, grasas y proteínas',
'Divide tus calorías en tres comidas, por ejemplo si tu plan es comer 1800 calorías, distribuye 600 en cada comida',
'Procura alimentos de bajo índice glucémico, es decir, alimentos que no suban tus niveles de azucar en la sangre'
];
const indiceAleatorio = Math.floor(Math.random() * listaConsejos.length);
const consejoAleatorio = listaConsejos[indiceAleatorio];
const speechOutput = consejoAleatorio;
return handlerInput.responseBuilder
.speak(`${speechOutput} ¿qué mas necesitas?`)
.reprompt('¿qué mas necesitas?')
.addDirective({
type: 'Alexa.Presentation.APL.RenderDocument',
version: '1.0',
document: require('./main.json'),
datasources: {
"bodyTemplate7Data": {
"type": "object",
"objectId": "bt7Sample",
"title": "Consejo",
"image": {
"sources": [
{
"url": "https://s3.amazonaws.com/nutricioninteligente/screen4.png",
"size": "small",
"widthPixels": 0,
"heightPixels": 0
},
{
"url": "https://s3.amazonaws.com/nutricioninteligente/screen4.png",
"size": "large",
"widthPixels": 0,
"heightPixels": 0
}
]
},
"logoUrl": "",
"hintText": "Try, \"Alexa, dime mi peso ideal\""
}
}
})
.getResponse();
}
};
const PesoIdealIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'PesoIdealIntent';
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
var estatura = request.intent.slots.estatura.value;
var pesoidealHombre = (estatura-100)-((estatura-150)/4);
var pesoidealMujer = (estatura-100)-((estatura-150)/2);
const speechOutput = ` Tu peso ideal si eres hombre es ${pesoidealHombre} y es ${pesoidealMujer} si eres mujer`;
return handlerInput.responseBuilder
.speak(`${speechOutput} ¿qué mas necesitas?`)
.reprompt('¿qué mas necesitas?')
.addDirective({
type: 'Alexa.Presentation.APL.RenderDocument',
version: '1.0',
document: require('./main.json'),
datasources: {
"bodyTemplate7Data": {
"type": "object",
"objectId": "bt7Sample",
"title": "Peso ideal",
"image": {
"sources": [
{
"url": "https://s3.amazonaws.com/nutricioninteligente/screen1.png",
"size": "small",
"widthPixels": 0,
"heightPixels": 0
},
{
"url": "https://s3.amazonaws.com/nutricioninteligente/screen1.png",
"size": "large",
"widthPixels": 0,
"heightPixels": 0
}
]
},
"logoUrl": "",
"hintText": "Try, \"Alexa, dime mi peso ideal\""
}
}
})
.getResponse();
}
};
const HelpIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
const speechText = 'Me puedes decir dame un consejo o calcula mi peso ideal. ¿Cómo te puedo ayudar?';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
|| handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const speechText = 'Adios!';
return handlerInput.responseBuilder
.speak(speechText)
.getResponse();
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
},
handle(handlerInput) {
// Any cleanup logic goes here.
return handlerInput.responseBuilder.getResponse();
}
};
// Este handler para que hagas tus pruebas y debugging.
// Simplemente repite el intent que dijo el usuario.
const IntentReflectorHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest';
},
handle(handlerInput) {
const intentName = handlerInput.requestEnvelope.request.intent.name;
const speechText = `Lanzaste el intent que se llama ${intentName}`;
return handlerInput.responseBuilder
.speak(speechText)
//.reprompt('agrega un texto de reprompt si deseas dejar la sesión abierta para que el usuario responda. No olvide cerrar con una pregunta. ¿Cómo te puedo ayudar?')
.getResponse();
}
};
// Erro genério para capturar erroes de sintaxis o de enrutamiento.
// Si recibes un error, eso significa que no hay un handler que regrese "true" para el método canHandle()
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`~~~~ Error handled: ${error.message}`);
const speechText = `Lo siento, No puedo entender lo que has dicho. Por favor inténtalo de nuevo`;
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
// Este handler funciona como el punto de entrada de tu skill, se encarga de enrutar
// todas las peticiones.
// Asegúrate de tener todos los handlers e interceptores dado de alta aquí.
// El órden importa, son procesador de arriba hacia abajo.
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
HolaMundoIntentHandler,
ConsejoIntentHandler,
PesoIdealIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
IntentReflectorHandler) // Asegúrate de que el IntentReflector sea el último para evitar que maneje peticiones incorrectas
.addErrorHandlers(
ErrorHandler)
.lambda();
{
"type": "APL",
"version": "1.0",
"theme": "dark",
"import": [
{
"name": "alexa-layouts",
"version": "1.0.0"
}
],
"resources": [
{
"description": "Stock color for the light theme",
"colors": {
"colorTextPrimary": "#151920"
}
},
{
"description": "Stock color for the dark theme",
"when": "${viewport.theme == 'dark'}",
"colors": {
"colorTextPrimary": "#f0f1ef"
}
},
{
"description": "Standard font sizes",
"dimensions": {
"textSizeBody": 48,
"textSizePrimary": 27,
"textSizeSecondary": 23,
"textSizeSecondaryHint": 25
}
},
{
"description": "Common spacing values",
"dimensions": {
"spacingThin": 6,
"spacingSmall": 12,
"spacingMedium": 24,
"spacingLarge": 48,
"spacingExtraLarge": 72
}
},
{
"description": "Common margins and padding",
"dimensions": {
"marginTop": 40,
"marginLeft": 60,
"marginRight": 60,
"marginBottom": 40
}
}
],
"styles": {
"textStyleBase": {
"description": "Base font description; set color",
"values": [
{
"color": "@colorTextPrimary"
}
]
},
"textStyleBase0": {
"description": "Thin version of basic font",
"extend": "textStyleBase",
"values": {
"fontWeight": "100"
}
},
"textStyleBase1": {
"description": "Light version of basic font",
"extend": "textStyleBase",
"values": {
"fontWeight": "300"
}
},
"mixinBody": {
"values": {
"fontSize": "@textSizeBody"
}
},
"mixinPrimary": {
"values": {
"fontSize": "@textSizePrimary"
}
},
"mixinSecondary": {
"values": {
"fontSize": "@textSizeSecondary"
}
},
"textStylePrimary": {
"extend": [
"textStyleBase1",
"mixinPrimary"
]
},
"textStyleSecondary": {
"extend": [
"textStyleBase0",
"mixinSecondary"
]
},
"textStyleBody": {
"extend": [
"textStyleBase1",
"mixinBody"
]
},
"textStyleSecondaryHint": {
"values": {
"fontFamily": "Bookerly",
"fontStyle": "italic",
"fontSize": "@textSizeSecondaryHint",
"color": "@colorTextPrimary"
}
}
},
"layouts": {},
"mainTemplate": {
"parameters": [
"payload"
],
"items": [
{
"when": "${viewport.shape == 'round'}",
"type": "Container",
"direction": "column",
"items": [
{
"type": "Image",
"source": "${payload.bodyTemplate7Data.backgroundImage.sources[0].url}",
"scale": "best-fill",
"position": "absolute",
"width": "100vw",
"height": "100vh"
},
{
"type": "AlexaHeader",
"headerTitle": "${payload.bodyTemplate7Data.title}",
"headerAttributionImage": "${payload.bodyTemplate7Data.logoUrl}"
},
{
"type": "Container",
"grow": 1,
"alignItems": "center",
"justifyContent": "center",
"items": [
{
"type": "Image",
"source": "${payload.bodyTemplate7Data.image.sources[0].url}",
"scale": "best-fill",
"width": "100vh",
"height": "70vw",
"align": "center"
}
]
}
]
},
{
"type": "Container",
"items": [
{
"type": "Image",
"source": "${payload.bodyTemplate7Data.backgroundImage.sources[0].url}",
"scale": "best-fill",
"position": "absolute",
"width": "100vw",
"height": "100vh"
},
{
"type": "AlexaHeader",
"headerTitle": "${payload.bodyTemplate7Data.title}",
"headerAttributionImage": "${payload.bodyTemplate7Data.logoUrl}"
},
{
"type": "Container",
"direction": "row",
"paddingLeft": "5vw",
"paddingRight": "5vw",
"paddingBottom": "5vh",
"alignItems": "center",
"justifyContent": "center",
"items": [
{
"type": "Image",
"height": "75vh",
"width": "90vw",
"source": "${payload.bodyTemplate7Data.image.sources[0].url}",
"scale": "best-fill",
"align": "center"
}
]
}
]
}
]
}
}
{
"interactionModel": {
"languageModel": {
"invocationName": "nutrición inteligente",
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "HolaMundoIntent",
"slots": [],
"samples": [
"hola",
"cómo estás",
"di hola mundo",
"di hola",
"comenta hola mundo",
"comenta hola"
]
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "ConsejoIntent",
"slots": [],
"samples": [
"que me de un consejo",
"consejo",
"quiero un consejo",
"dame un consejo",
"un consejo"
]
},
{
"name": "PesoIdealIntent",
"slots": [
{
"name": "estatura",
"type": "AMAZON.NUMBER",
"samples": [
"mido {estatura}",
"{estatura}"
]
}
],
"samples": [
"dame mi peso ideal",
"calcúla mi peso ideal",
"mi peso ideal",
"peso ideal",
"quiero saber mi peso ideal",
"cuanto debo de pesar",
"dime mi peso ideal",
"cual es mi peso ideal"
]
}
],
"types": []
},
"dialog": {
"intents": [
{
"name": "PesoIdealIntent",
"confirmationRequired": false,
"prompts": {},
"slots": [
{
"name": "estatura",
"type": "AMAZON.NUMBER",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.666209592402.794048786262"
}
}
]
}
],
"delegationStrategy": "ALWAYS"
},
"prompts": [
{
"id": "Elicit.Slot.666209592402.794048786262",
"variations": [
{
"type": "PlainText",
"value": "¿cuánto mides en centimetros?"
}
]
}
]
}
}
{
"type": "APL",
"version": "1.0",
"theme": "dark",
"import": [],
"resources": [],
"styles": {},
"layouts": {},
"mainTemplate": {
"items": [
{
"type": "Container",
"height": "100vh",
"width": "100vw",
"direction": "column",
"alignItems": "center",
"justifyContent": "center",
"items": [
{
"type": "Text",
"text": "Nutrición Inteligente"
},
{
"type": "Text",
"text": "¡Bienvenidos!"
}
]
}
]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment