Skip to content

Instantly share code, notes, and snippets.

@germanviscuso
Last active December 31, 2018 02:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save germanviscuso/b9d9efd5d15a7907e1d2e4ada1fa65d6 to your computer and use it in GitHub Desktop.
Save germanviscuso/b9d9efd5d15a7907e1d2e4ada1fa65d6 to your computer and use it in GitHub Desktop.
Alexa Skill Basics: Advanced Fact Skill
{
"interactionModel": {
"languageModel": {
"invocationName": "curiosidades espaciales",
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "GetNewFactIntent",
"slots": [],
"samples": [
"necesito otro dato",
"quiero escuchar algo",
"dime algo ",
"nos das un dato por favor",
"me gustaría un dato",
"dinos algo nuevo",
"cuéntame algo",
"queremos saber mas",
"pidele un dato",
"dame un dato"
]
},
{
"name": "GetFactByPlanetIntent",
"slots": [
{
"name": "planeta",
"type": "ListaDeCuerposCelestes",
"samples": [
"quiero aprender de el planeta {planeta}",
"me interesa {planeta}",
"{planeta}"
]
}
],
"samples": [
"dame un dato del planeta {planeta}",
"Deseo aprender más del planeta {planeta}",
"el planeta {planeta} es el que me interesa",
"el planeta {planeta} ",
"{planeta} me interesa",
"{planeta} es el que me interesa",
"Deseo aprender más de {planeta}",
"Me interesa {planeta}",
"Nos datos un dato de {planeta}",
"Quiero saber más sobre {planeta}",
"{planeta} por favor",
"{planeta}",
"Dime sobre {planeta}"
]
},
{
"name": "AMAZON.RepeatIntent",
"samples": [
"repite el dato",
"dame el dato anterior",
"dame el dato anterior de nuevo",
"repite el dato anterior",
"repite el último dato"
]
}
],
"types": [
{
"name": "ListaDeCuerposCelestes",
"values": [
{
"name": {
"value": "Neptuno"
}
},
{
"name": {
"value": "Urano"
}
},
{
"name": {
"value": "Saturno",
"synonyms": [
"el que tiene anillos"
]
}
},
{
"name": {
"value": "Jupiter",
"synonyms": [
"Júpiter",
"el más grande"
]
}
},
{
"name": {
"value": "Marte"
}
},
{
"name": {
"value": "Tierra",
"synonyms": [
"La Tierra"
]
}
},
{
"name": {
"value": "Venus",
"synonyms": [
"el más caliente"
]
}
},
{
"name": {
"value": "Mercurio",
"synonyms": [
"el más pequeño",
"más pequeño"
]
}
},
{
"name": {
"value": "Luna",
"synonyms": [
"La Luna"
]
}
},
{
"name": {
"value": "Sol",
"synonyms": [
"El Sol"
]
}
}
]
}
]
},
"dialog": {
"intents": [
{
"name": "GetFactByPlanetIntent",
"confirmationRequired": false,
"prompts": {},
"slots": [
{
"name": "planeta",
"type": "ListaDeCuerposCelestes",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.519157955428.244945612195"
}
}
]
}
]
},
"prompts": [
{
"id": "Elicit.Slot.519157955428.244945612195",
"variations": [
{
"type": "PlainText",
"value": "¿De que planeta quieres saber más?"
},
{
"type": "PlainText",
"value": "¿Que planeta o cuerpo celeste te interesa?"
}
]
}
]
}
}
/* eslint-disable func-names */
/* eslint-disable no-console */
const Alexa = require('ask-sdk');
const https = require('https');
const GetNewFactHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'LaunchRequest'
|| (request.type === 'IntentRequest'
&& request.intent.name === 'GetNewFactIntent');
},
async handle(handlerInput) {
const randomFact = await getRandomFact();
const prompt = ' Si quieres otro dato, di el nombre de un planeta o di dame un dato para escuchar otro aleatorio. ';
const speechOutput = GET_FACT_MESSAGE + randomFact + prompt;
const repromptOutput = ' Di el nombre de un planeta para escuchar un dato o di salir para terminar. ';
storePastFactInDB(handlerInput, randomFact);
return handlerInput.responseBuilder
.speak(speechOutput)
.withSimpleCard(SKILL_NAME, randomFact)
.reprompt(repromptOutput)
.getResponse();
},
};
const PlanetSlotDialogHandler={
canHandle(handlerInput){
const request = handlerInput.requestEnvelope.request;
return (request.type === 'IntentRequest'
&& request.intent.name === 'GetFactByPlanetIntent'
&& request.dialogState !== 'COMPLETED');
},
handle(handlerInput){
const currentIntent = handlerInput.requestEnvelope.request.intent;
return handlerInput.responseBuilder
.addDelegateDirective(currentIntent)
.getResponse();
}
};
const GetFactByPlanetHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return (request.type === 'IntentRequest'
&& request.intent.name === 'GetFactByPlanetIntent');
},
async handle(handlerInput) {
const planet = getSlotValue(handlerInput);
let speechOutput;
let planetFact;
const prompt = ' Si quieres otro dato, di el nombre de un planeta o di dame un dato para escuchar otro aleatorio. ';
const repromptOutput = ' Di el nombre de un planeta para escuchar un dato o di salir para terminar. ';
if(planet&&(planet!==undefined)){
planetFact = await getFactByPlanet(planet);
speechOutput = GET_FACT_MESSAGE + planetFact + prompt;
await storePastFactInDB(handlerInput, planetFact);
} else{
planetFact = '';
speechOutput = 'Por favor di el nombre del algun cuerpo celeste. O quiero un dato para escuchar uno aleatorio. ';
}
return handlerInput.responseBuilder
.speak(speechOutput)
.withSimpleCard(SKILL_NAME, planetFact)
.reprompt(repromptOutput)
.getResponse();
},
};
const RepeatIntentHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return (request.type === 'IntentRequest'
&& request.intent.name === 'AMAZON.RepeatIntent');
},
handle(handlerInput){
let lastFact;
const prompt = ' Si quieres otro dato, di el nombre de un planeta o di dame un dato para escuchar otro aleatorio. ';
const repromptOutput = ' Di el nombre de un planeta para escuchar un dato o di salir para terminar. ';
let {pastFact} = handlerInput.attributesManager.getSessionAttributes();
if(pastFact){
lastFact = pastFact;
}else{
lastFact = 'Lo siento, no lo recuerdo. ';
}
const speechOutput = lastFact + prompt;
return handlerInput.responseBuilder
.speak(speechOutput)
.withSimpleCard(SKILL_NAME, speechOutput)
.reprompt(repromptOutput)
.getResponse();
}
};
const LaunchRequestHandler ={
canHandle(handlerInput){
const request = handlerInput.requestEnvelope.request;
return request.type === 'LaunchRequest';
},
handle(handlerInput){
const speechOutput = ' Bienvenido a curiosidades espaciales, la skill con datos del espacio. Puedes decir el nombre de un planeta o. dame un dato. para escuchar uno aleatorio.';
const repromptOutput = ' Dime que cuerpo celeste te interesa. ';
return handlerInput.responseBuilder
.speak(speechOutput)
.reprompt(repromptOutput)
.getResponse();
}
};
const HelpHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak(HELP_MESSAGE)
.reprompt(HELP_REPROMPT)
.getResponse();
},
};
const ExitHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& (request.intent.name === 'AMAZON.CancelIntent'
|| request.intent.name === 'AMAZON.StopIntent');
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak(STOP_MESSAGE)
.getResponse();
},
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'SessionEndedRequest';
},
handle(handlerInput) {
console.log(`Session ended with reason: ${handlerInput.requestEnvelope.request.reason}`);
return handlerInput.responseBuilder.getResponse();
},
};
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`Error: ${error.message}`);
return handlerInput.responseBuilder
.speak('Una disculpa, hubo un error.')
.reprompt('Ocurrió un error.')
.getResponse();
},
};
const LoadSessionFromDBRequestInterceptor ={
async process(handlerInput){
if(!handlerInput.attributesManager.getSessionAttributes().lastFact){
await loadSessionFromDB(handlerInput);
}
}
};
const SKILL_NAME = ' Curiosidades Espaciales ';
const GET_FACT_MESSAGE = ' Aqui esta tu dato: ';
const HELP_MESSAGE = ' Puedes pedir un dato, o decir cerrar... ¿Como te puedo ayudar? ';
const HELP_REPROMPT = ' Creo que pediste ayuda. Si quieres un dato, pidemelo o di salir para cerrar la skill. ';
const STOP_MESSAGE = ' ¡Adios! ';
//===== Helper Functions
function getRandomFact(){
const planetArr = ['sol', 'mercurio', 'venus', 'tierra', 'luna', 'marte', 'jupiter', 'saturno', 'urano', 'neptuno'];
const planetIndex = Math.floor(Math.random() * planetArr.length);
const randomPlanet = planetArr[planetIndex];
return getFactByPlanet(randomPlanet);
}
function getFactByPlanet(planet){
const jsonBody = JSON.stringify({
'Planet' : planet
});
let options = {
host: '3s23e83n4j.execute-api.eu-west-1.amazonaws.com',
port: 443,
path: '/prod/getByPlanet',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length' : Buffer.byteLength(jsonBody, 'utf8')
}
};
async function buildAlexaResponse(options, body){
let responseFromExtension = await httpRequestPromise(options, body);
return JSON.parse(responseFromExtension).Fact;
}
return buildAlexaResponse(options, jsonBody).then(function(result) {
return result;
});
}
function getSlotValue(handlerInput) {
let slotValue;
try {
let entityResolutionCode = handlerInput.requestEnvelope.request.intent.slots.planeta.resolutions.resolutionsPerAuthority[0].status.code;
if(entityResolutionCode === 'ER_SUCCESS_MATCH'){
slotValue = handlerInput.requestEnvelope.request.intent.slots.planeta.resolutions.resolutionsPerAuthority[0].values[0].value.name.toLowerCase();
}else{
slotValue = null;
}
} catch (error) {
slotValue = null;
}
return slotValue;
}
async function loadSessionFromDB(handlerInput){
let persistentAttributes = await handlerInput.attributesManager.getPersistentAttributes();
handlerInput.attributesManager.setSessionAttributes(persistentAttributes);
}
async function storePastFactInDB(handlerInput, pastFact){
await loadSessionFromDB(handlerInput);
let persistentAttributes = handlerInput.attributesManager.getSessionAttributes();
persistentAttributes.pastFact = pastFact;
handlerInput.attributesManager.setPersistentAttributes(persistentAttributes);
handlerInput.attributesManager.savePersistentAttributes();
}
// An http(s) request wrapped in promise & async
async function httpRequestPromise(options, body) {
// return new pending promise
return new Promise((resolve, reject) => {
const request = https.request(options, (response) => {
// reject promise if we get http errors
if (response.statusCode < 200 || response.statusCode > 299) {
reject(new Error(`Failed to make http request, status code: ` + response.statusCode));
}
// temporary data holder
const body = [];
// on every content chunk, push it to the data array
response.on(`data`, (chunk) => body.push(chunk));
// resolve promise with those joined chunks
response.on(`end`, () => resolve(body.join(``)));
});
// reject promise on connection errors of the request
request.on(`error`, (err) => reject(err));
request.write(body);
// finish request
request.end();
});
}
const skillBuilder = Alexa.SkillBuilders.standard();
exports.handler = skillBuilder
.addRequestHandlers(
LaunchRequestHandler,
GetNewFactHandler,
PlanetSlotDialogHandler,
GetFactByPlanetHandler,
RepeatIntentHandler,
HelpHandler,
ExitHandler,
SessionEndedRequestHandler
)
.addErrorHandlers(ErrorHandler)
.withAutoCreateTable(true)
.withTableName('CuriosidadesEspaciales')
.addRequestInterceptors(LoadSessionFromDBRequestInterceptor)
.lambda();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment