amazon-web-servicesalexa-skills-kitalexa-voice-service

Alexa Skill Lambda Node.js dynamic intents in handler


Is it possible to dynamically fill the intents in the lambda function of an alexa skill? For example:

const handlers = {
var intentName = this.event.request.intent.name;
'LaunchRequest': function () {
    this.emit(':ask', welcomeOutput, welcomeReprompt);
},
'AMAZON.HelpIntent': function () {
    speechOutput = 'Placeholder response for AMAZON.HelpIntent.';
    reprompt = '';
    this.emit(':ask', speechOutput, reprompt);
},
'AMAZON.CancelIntent': function () {
    speechOutput = 'Placeholder response for AMAZON.CancelIntent';
    this.emit(':tell', speechOutput);
},
'AMAZON.StopIntent': function () {
    speechOutput = 'Placeholder response for AMAZON.StopIntent.';
    this.emit(':tell', speechOutput);
},
'SessionEndedRequest': function () {
    speechOutput = '';
    //this.emit(':saveState',true);//uncomment to save attributes to db on session end
    this.emit(':tell', speechOutput);
},
'ci_clothing': function () {
    speechOutput = '';

    speechOutput = "Here is the output";
    this.emit(":ask", speechOutput, speechOutput);
},}


exports.handler = (event, context) => {
   const alexa = Alexa.handler(event, context);
   alexa.appId = APP_ID;
   // To enable string internationalization (i18n) features, set a resources object.
   //alexa.resources = languageStrings;
   alexa.registerHandlers(handlers);
   //alexa.dynamoDBTableName = 'DYNAMODB_TABLE_NAME'; //uncomment this line to save attributes to DB
   alexa.execute();};

For example if I wanted to have the 'ci_clothing' intent dynamically. How would I do that?


Solution

  • Yes it is possible. The only thing you need is a helper function which creates all handlers. Afterwards use this helper function to registerHandlers.

    Something like that:

    const getHandlers = (request) => {
        const intentName = request.intent.name;
        return {
            'LaunchRequest': function () {
                this.emit(':ask', welcomeOutput, welcomeReprompt);
            },
            'AMAZON.HelpIntent': function () {
                speechOutput = 'Placeholder response for AMAZON.HelpIntent.';
                reprompt = '';
                this.emit(':ask', speechOutput, reprompt);
            },
            'AMAZON.CancelIntent': function () {
                speechOutput = 'Placeholder response for AMAZON.CancelIntent';
                this.emit(':tell', speechOutput);
            },
            'AMAZON.StopIntent': function () {
                speechOutput = 'Placeholder response for AMAZON.StopIntent.';
                this.emit(':tell', speechOutput);
            },
            'SessionEndedRequest': function () {
                speechOutput = '';
                //this.emit(':saveState',true);//uncomment to save attributes to db on session end
                this.emit(':tell', speechOutput);
            },
            [intentName]: function () {
                speechOutput = '';
    
                speechOutput = "Here is the output";
                this.emit(":ask", speechOutput, speechOutput);
            },
        };
    };
    
    exports.handler = (event, context) => {
        const alexa = Alexa.handler(event, context);
        alexa.appId = APP_ID;
        alexa.registerHandlers(getHandlers(event.request));
        alexa.execute();
    };
    

    Disclaimer: It's not tested

    Edit:

    But I think it's not best practice to overwrite all your handlers. You should definitely use the Built-In intents and not your "rule them all" intent. Accordingly you should do a small change within getHandlers :

    const getHandlers = (request) => {
        const intentName = request.intent.name;
        const handlers = {
            'LaunchRequest': function () {
                this.emit(':ask', welcomeOutput, welcomeReprompt);
            },
            'AMAZON.HelpIntent': function () {
                speechOutput = 'Placeholder response for AMAZON.HelpIntent.';
                reprompt = '';
                this.emit(':ask', speechOutput, reprompt);
            },
            'AMAZON.CancelIntent': function () {
                speechOutput = 'Placeholder response for AMAZON.CancelIntent';
                this.emit(':tell', speechOutput);
            },
            'AMAZON.StopIntent': function () {
                speechOutput = 'Placeholder response for AMAZON.StopIntent.';
                this.emit(':tell', speechOutput);
            },
            'SessionEndedRequest': function () {
                speechOutput = '';
                //this.emit(':saveState',true);//uncomment to save attributes to db on session end
                this.emit(':tell', speechOutput);
            },
        };
    
        if (!handlers[intentName]) {
            handlers[intentName] = function () {
                speechOutput = '';
    
                speechOutput = "Here is the output";
                this.emit(":ask", speechOutput, speechOutput);
            };
        }
    
        return handlers;
    };