1

I am working on a project of Amazon Alexa of booking a table in a restaurant and I have four intents:

  • makeReservation
  • futureOrCurrentLocation
  • getRestaurantName
  • selectRestaurants

I am facing one issue that the linear flow of intent is not working. I have stored the previous intent in the session and checked the previous intent from the session and on that basic I am calling the next intent.

But when I say Alexa with the previous intent String in the response of the current intent, it jumps to the new intent we have called, but it throws an exception.

Actually it should work like if I say some intent String in the response of other intent then it should repeat the current intent once again.

And one more issue I am facing is that I need to append the String in the user utterance like e.g.:

Alexa: "Where would you like to go?"

User: "Go to {Restaurant Name}"

I didn't want to append this "Go to" in the restaurant name.

// Lambda Function code for Alexa.
const Alexa = require("ask-sdk");

// Book a table
const makeReservation_Handler =  {
    canHandle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
        return request.type === 'IntentRequest' && request.intent.name === 'makeReservation' ;
    },
    handle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
        const responseBuilder = handlerInput.responseBuilder;
        let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();

        sessionAttributes.tableTalkType = 1;
        handlerInput.attributesManager.setSessionAttributes(sessionAttributes);

        return responseBuilder
            .addDelegateDirective({
                name: 'futureOrCurrentLocation',
                confirmationStatus: 'NONE',
                slots: {}
            })
            .withShouldEndSession(false)
            .getResponse();
    },
};

const futureOrCurrentLocation_Handler = {
    canHandle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
        return request.type === 'IntentRequest' && request.intent.name === 'futureOrCurrentLocation' ;
    },
    async handle(handlerInput) {
        const { requestEnvelope, serviceClientFactory, responseBuilder } = handlerInput;
        let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
        let previousIntentName = getPreviousIntent(sessionAttributes);

        if (previousIntentName == 'makeReservation') {
            const request = handlerInput.requestEnvelope.request;
            // const responseBuilder = handlerInput.responseBuilder;
            const slotValues = getSlotValues(request.intent.slots);
            const location = slotValues.locationType.heardAs;
            const tableTalkType = sessionAttributes.tableTalkType;
            let say = '';

            // delegate to Alexa to collect all the required slots
            const currentIntent = request.intent;
            if (request.dialogState && request.dialogState !== 'COMPLETED') {
                return handlerInput.responseBuilder
                    .addDelegateDirective(currentIntent)
                    .getResponse();

            }

            if (location == 'future location') {
                say = `Future location not available at this moment. Please ask to current location.`;
                return responseBuilder
                .speak(say)
                .reprompt(say)
                .getResponse();
            } else if(location == 'current location' && tableTalkType == 1){
                return responseBuilder
                .addDelegateDirective({
                    name: 'getRestaurantName',
                    confirmationStatus: 'NONE',
                    slots: {}
                })
                .getResponse();
            } else if (location == 'current location' && tableTalkType == 2) {
                return userCreatedTableListing_Handler.handle(handlerInput);
            } else {
                say = `invalid input.Please try again`;
                return responseBuilder
                .speak(say)
                .reprompt(say)
                .getResponse();
            }
        } else {
            return errorIntent_Handler.handle(handlerInput);
        }
    },
};

const getRestaurantName_Handler = {
    canHandle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
        return request.type === 'IntentRequest' && request.intent.name === 'getRestaurantName' ;
    },
    handle(handlerInput) {
        let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
        let previousIntentName = getPreviousIntent(sessionAttributes);

        if (previousIntentName == 'futureOrCurrentLocation') {
            const request = handlerInput.requestEnvelope.request;
            let slotValues = getSlotValues(request.intent.slots);

            // delegate to Alexa to collect all the required slots
            const currentIntent = request.intent;
            if (request.dialogState && request.dialogState !== 'COMPLETED') {
                return handlerInput.responseBuilder
                    .addDelegateDirective(currentIntent)
                    .getResponse();

            }

            //   SLOT: restaurantname
            if (request.dialogState && request.dialogState == 'COMPLETED' && slotValues.restaurantname.heardAs) {
                return new Promise((resolve) => {
                    getRestaurants(slotValues, handlerInput).then(say => {
                        resolve(handlerInput.responseBuilder.speak(say).reprompt(say).withShouldEndSession(false).getResponse());
                    }).catch(error => {
                        console.log(error);
                    });
                });
            }
        } else {
            return errorIntent_Handler.handle(handlerInput);
        }
    }
};

const selectRestaurants_Handler = {
    canHandle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
        return request.type === 'IntentRequest' && request.intent.name === 'selectRestaurants' ;
    },
    handle(handlerInput) {
        let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
        let previousIntentName = getPreviousIntent(sessionAttributes);

        if (previousIntentName == 'getRestaurantName') {
            const request = handlerInput.requestEnvelope.request;
            const responseBuilder = handlerInput.responseBuilder;
            let slotValues = getSlotValues(request.intent.slots);
            let say = '';

            let restaurantListArray = sessionAttributes.sessionrestaurantList ? sessionAttributes.sessionrestaurantList : [];

            sessionAttributes.previousIntent = '';
            handlerInput.attributesManager.setSessionAttributes(sessionAttributes);

            let restaurantIndex = slotValues.selectRestaurant.heardAs;
            let restaurantData = {
                name: '',
                address: '',
                restaurantlatitude: '',
                restaurantlongitude: '',
                restaurantID:'',
                restaurantImageUrl: '',
                date: '',
                time:'',
                people: '',
            };

            if (restaurantListArray.length >= restaurantIndex) {

                let jsonData = JSON.parse(restaurantListArray[restaurantIndex - 1]);

                if ((restaurantIndex) && (jsonData[restaurantIndex].name !== '' && typeof jsonData[restaurantIndex].name !== undefined && jsonData[restaurantIndex].name !== null)) {
                    let restaurantAddress1 = jsonData[restaurantIndex].location.address1 ? jsonData[restaurantIndex].location.address1: '';
                    let restaurantAddress2 = jsonData[restaurantIndex].location.address2 ? jsonData[restaurantIndex].location.address2: '';
                    let restaurantAddress3 = jsonData[restaurantIndex].location.address3 ? jsonData[restaurantIndex].location.address3: '';

                    restaurantData['name'] = jsonData[restaurantIndex].name;
                    restaurantData['address'] = restaurantAddress1.concat(restaurantAddress2, restaurantAddress3);
                    restaurantData['restaurantID'] = jsonData[restaurantIndex].id;
                    restaurantData['restaurantImageUrl'] = jsonData[restaurantIndex].image_url;
                    restaurantData['restaurantlatitude'] = jsonData[restaurantIndex].coordinates.latitude;
                    restaurantData['restaurantlongitude'] = jsonData[restaurantIndex].coordinates.longitude;

                    sessionAttributes.restaurantData = restaurantData;
                    handlerInput.attributesManager.setSessionAttributes(sessionAttributes);

                    say = `selected Restaurant name is ${jsonData[restaurantIndex].name} in ${restaurantAddress1} ${restaurantAddress2} ${restaurantAddress3}.`;
                    return responseBuilder
                    .addDelegateDirective({
                        name: 'bookingDate',
                        confirmationStatus: 'NONE',
                        slots: {}
                    })
                    .speak(say)
                    // .reprompt('try again, Please provide date')
                    .withShouldEndSession(false)
                    .getResponse();
                } else {
                    say = 'Restaurant not available. please say again';
                    return responseBuilder
                    .speak(say)
                    .reprompt('Restaurant not available. please say again')
                    .withShouldEndSession(false)
                    .getResponse();
                }
            } else {
                say = 'Please select valid input.';
                return responseBuilder
                .speak(say)
                .reprompt('Please select valid input')
                .withShouldEndSession(false)
                .getResponse();
            }
        } else {
            return errorIntent_Handler.handle(handlerInput);
        }
    },
};

const errorIntent_Handler = {
    canHandle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
        return request.type === 'IntentRequest' && request.intent.name === 'errorIntent' ;
    },
    handle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
        const responseBuilder = handlerInput.responseBuilder;
        let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();

        let say = 'Sorry. There is some problem with the response. Please say again';

        return responseBuilder
            .speak(say)
            .reprompt(say)
            .getResponse();
    },
};
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sedhal
  • 522
  • 4
  • 13
  • I'd look through this documentation from Amazon Alexa specifically addressing this need: https://developer.amazon.com/docs/custom-skills/dialog-interface-reference.html – Chuck LaPress Sep 20 '19 at 17:31
  • @ChuckLaPress thanks for your replay. You have any sample code please share with here. – sedhal Sep 21 '19 at 18:59

0 Answers0