Hosting an Alexa Skill on AWS Lambda, and app.js or index.js


#1

Hello Everybody!

I went through coding and testing my Alexa skill using the local webhook route, and everything except certification was going well. And now, I am trying to host my Alexa Skill on an AWS Lambda server. I go through the guide on Jovo for bundling my files into a zip file, which I then upload to my AWS function.

Everything connects, and my Alexa skill will run, but the problem is it appears to only run the code in my index.js file? I have my app.js which has all of my logic on it, but how do I get that over into my index.js file? I am not the most knowledgeable but it appears that in my index.js file, that is where my export.handler is being assigned to a custom SkillBuilder which has a .lambda() method called upon it. (Which I believe is making the lamdba object/it work) I am using the code from the development console’s index.js file, since I believe I need the error checking which was in that to be able to pass certification. As I now do.

I could try and move all my app logic from my app.js to my index.js file, as I see some projects do on github, and it would work, (I have transferred over a small amount of my code to see) but it would take a lot of time. Is there any other solution people are aware of please?

I see there was a similar question on May 20th, I tried his solution and it did not help.

If I try to just use the prebuilt code block in my index.js, like I was for the webhook, and not the code.
from the dev console, to try and see if it would work a different way, and I would solve certification another way, like so:

//AWS Lambda
exports.handler = async (event, context, callback) => {
await app.handle(new Lambda(event, context, callback));
};

It gives me an error ‘Lambda is not defined’ when I try the Alexa launch test in the AWS console.

Thank you for any help please!


#2

Hi! Could you share your complete index.js file?


#3

‘use strict’;

const { WebhookVerified: Webhook, ExpressJS } = require(‘jovo-framework’);
const { app } = require(’./app.js’);

//ExpressJS (Jovo Webhook)
if (process.argv.indexOf(’–webhook’) > -1) {
const port = process.env.JOVO_PORT || 3000;
Webhook.jovoApp = app;

Webhook.listen(port, () => {
console.info(Local server listening on port ${port}.);
});

Webhook.post([’/webhook’,’/webhook_alexa’], async (req, res) => {
await app.handle(new ExpressJS(req, res));
});
}

//default security from Alexa
const Alexa = require(‘ask-sdk-core’);

const LaunchRequestHandler = {

canHandle(handlerInput) {
    return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
},
handle(handlerInput) {

    const speakOutput = 'Hello there! My name is Elizabeth'; //this works, can change stuff here
	
    return handlerInput.responseBuilder
          .speak(speakOutput)
          .reprompt(speakOutput)
          .getResponse(); 
	//app.followUpState('IntroState').ask(speech, reprompt);		
		
}

};

//testing intent handlers, this works after, we would need to add states and everything over to here
/*
const GoodIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === ‘IntentRequest’ && Alexa.getIntentName(handlerInput.requestEnvelope) === ‘GoodIntent’;
},
handle(handlerInput) {

    const speakOutput = 'I\'m happy to hear that. Before we get started, could I get your first name?';

    return handlerInput.responseBuilder
        .speak(speakOutput)
        .reprompt('I\'m so pleased to hear that. Could I get your first name please?')
        .getResponse();
}

};
*/

// Dont think we need this intent handler regardless
/*
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === ‘IntentRequest’
&& Alexa.getIntentName(handlerInput.requestEnvelope) === ‘HelloWorldIntent’;
},
handle(handlerInput) {
const speakOutput = ‘Hello World!’;
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt(‘add a reprompt if you want to keep the session open for the user to respond’)
.getResponse();
}
};
*/
const HelpIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === ‘IntentRequest’
&& Alexa.getIntentName(handlerInput.requestEnvelope) === ‘AMAZON.HelpIntent’;
},
handle(handlerInput) {
const speakOutput = ‘You can say hello to me! How can I help?’;

    return handlerInput.responseBuilder
        .speak(speakOutput)
        .reprompt(speakOutput)
        .getResponse();
}

};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === ‘IntentRequest’
&& (Alexa.getIntentName(handlerInput.requestEnvelope) === ‘AMAZON.CancelIntent’
|| Alexa.getIntentName(handlerInput.requestEnvelope) === ‘AMAZON.StopIntent’);
},
handle(handlerInput) {
const speakOutput = ‘Goodbye!’;
return handlerInput.responseBuilder
.speak(speakOutput)
.getResponse();
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === ‘SessionEndedRequest’;
},
handle(handlerInput) {
// Any cleanup logic goes here.
return handlerInput.responseBuilder.getResponse();
}
};

// The intent reflector is used for interaction model testing and debugging.
// It will simply repeat the intent the user said. You can create custom handlers
// for your intents by defining them above, then also adding them to the request
// handler chain below.
const IntentReflectorHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === ‘IntentRequest’;
},
handle(handlerInput) {
const intentName = Alexa.getIntentName(handlerInput.requestEnvelope);
const speakOutput = You just triggered ${intentName};

    return handlerInput.responseBuilder
        .speak(speakOutput)
        //.reprompt('add a reprompt if you want to keep the session open for the user to respond')
        .getResponse();
}

};

// Generic error handling to capture any syntax or routing errors. If you receive an error
// stating the request handler chain is not found, you have not implemented a handler for
// the intent being invoked or included it in the skill builder below.
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(~~~~ Error handled: ${error.stack});
const speakOutput = Sorry, I had trouble doing what you asked. Please try again.;

    return handlerInput.responseBuilder
        .speak(speakOutput)
        .reprompt(speakOutput)
        .getResponse();
}

};

// The SkillBuilder acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you’ve
// defined are included below. The order matters - they’re processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
//HelloWorldIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
//GoodIntentHandler,
IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn’t override your custom intent handlers
)
.addErrorHandlers(
ErrorHandler,
)
.lambda();
//end security by Alexa

/*
//AWS Lambda
exports.handler = async (event, context, callback) => {
// context.callbackWaitsForEmptyEventLoop = false;
await app.handle(new Lambda(event, context, callback));
};
*/
Thank you!


#4

Ah, this is code from the ASK SDK, not from Jovo.

Learn about the difference here: https://www.jovo.tech/courses/project-4-quiz-game-ask-sdk-jovo


#5

Yes, I needed to use the ASK SDK to pass the Alexa certification I believe.

However, if my index.js is just :

‘use strict’;

const { WebhookVerified: Webhook, ExpressJS } = require(‘jovo-framework’);
const { app } = require(’./app.js’);

//ExpressJS (Jovo Webhook)
if (process.argv.indexOf(’–webhook’) > -1) {
const port = process.env.JOVO_PORT || 3000;
Webhook.jovoApp = app;

Webhook.listen(port, () => {
console.info(Local server listening on port ${port}.);
});

Webhook.post([’/webhook’,’/webhook_alexa’], async (req, res) => {
await app.handle(new ExpressJS(req, res));
});
}

//AWS Lambda
exports.handler = async (event, context, callback) => {

// context.callbackWaitsForEmptyEventLoop = false;
await app.handle(new Lambda(event, context, callback));
};

I get the lambda is not defined error I mentioned.
Thanks!


#6

I think I may have solved it!

I noticed in your example in github,
you have
const { Webhook, ExpressJS, Lamdba } = require(‘jovo-framework’); //I was missing the lamdba!

I think it works now!

thank you so much!