Skip to content

Instantly share code, notes, and snippets.

@hundredwatt
Created May 25, 2017 20:35
Show Gist options
  • Save hundredwatt/afe27ff43d20553711ad66001075894e to your computer and use it in GitHub Desktop.
Save hundredwatt/afe27ff43d20553711ad66001075894e to your computer and use it in GitHub Desktop.
'use strict';
/**
* This code sample demonstrates an implementation of the Lex Code Hook Interface
* in order to serve a bot which manages dentist appointments.
* Bot, Intent, and Slot models which are compatible with this sample can be found in the Lex Console
* as part of the 'MakeAppointment' template.
*
* For instructions on how to set up and test this bot, as well as additional samples,
* visit the Lex Getting Started documentation.
*/
// --------------- Helpers to build responses which match the structure of the necessary dialog actions -----------------------
function elicitSlot(sessionAttributes, intentName, slots, slotToElicit, message, responseCard) {
return {
sessionAttributes,
dialogAction: {
type: 'ElicitSlot',
intentName,
slots,
slotToElicit,
message,
responseCard,
},
};
}
function confirmIntent(sessionAttributes, intentName, slots, message, responseCard) {
return {
sessionAttributes,
dialogAction: {
type: 'ConfirmIntent',
intentName,
slots,
message,
responseCard,
},
};
}
function close(sessionAttributes, fulfillmentState, message, responseCard) {
return {
sessionAttributes,
dialogAction: {
type: 'Close',
fulfillmentState,
message,
responseCard,
},
};
}
function delegate(sessionAttributes, slots) {
return {
sessionAttributes,
dialogAction: {
type: 'Delegate',
slots,
},
};
}
// Build a responseCard with a title, subtitle, and an optional set of options which should be displayed as buttons.
function buildResponseCard(title, subTitle, options) {
let buttons = null;
if (options != null) {
buttons = [];
for (let i = 0; i < Math.min(5, options.length); i++) {
buttons.push(options[i]);
}
}
return {
contentType: 'application/vnd.amazonaws.card.generic',
version: 1,
genericAttachments: [{
title,
subTitle,
buttons,
}],
};
}
// --------------- Functions that control the skill's behavior -----------------------
/**
* Performs dialog management and fulfillment for booking a dentists appointment.
*
* Beyond fulfillment, the implementation for this intent demonstrates the following:
* 1) Use of elicitSlot in slot validation and re-prompting
* 2) Use of confirmIntent to support the confirmation of inferred slot values, when confirmation is required
* on the bot model and the inferred slot values fully specify the intent.
*/
function repeatMe(intentRequest, callback) {
const phrase = intentRequest.currentIntent.slots.Phrase;
const source = intentRequest.invocationSource;
const outputSessionAttributes = intentRequest.sessionAttributes || {};
const bookingMap = JSON.parse(outputSessionAttributes.bookingMap || '{}');
const slots = intentRequest.currentIntent.slots;
callback(elicitSlot(outputSessionAttributes, intentRequest.currentIntent.name,
slots, phrase, "what do you want me to say?"))
return;
}
// --------------- Intents -----------------------
/**
* Called when the user specifies an intent for this skill.
*/
function dispatch(intentRequest, callback) {
// console.log(JSON.stringify(intentRequest, null, 2));
console.log(`dispatch userId=${intentRequest.userId}, intent=${intentRequest.currentIntent.name}`);
const name = intentRequest.currentIntent.name;
// Dispatch to your skill's intent handlers
if (name === 'RepeatMe') {
return repeatMe(intentRequest, callback);
}
throw new Error(`Intent with name ${name} not supported`);
}
// --------------- Main handler -----------------------
function loggingCallback(response, originalCallback) {
// console.log(JSON.stringify(response, null, 2));
originalCallback(null, response);
}
// Route the incoming request based on intent.
// The JSON body of the request is provided in the event slot.
exports.handler = (event, context, callback) => {
try {
// By default, treat the user request as coming from the America/New_York time zone.
process.env.TZ = 'America/New_York';
console.log(`event.bot.name=${event.bot.name}`);
/**
* Uncomment this if statement and populate with your Lex bot name and / or version as
* a sanity check to prevent invoking this Lambda function from an undesired Lex bot or
* bot version.
*/
/*
if (event.bot.name !== 'MakeAppointment') {
callback('Invalid Bot Name');
}
*/
dispatch(event, (response) => loggingCallback(response, callback));
} catch (err) {
callback(err);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment