No response from CanfulFillIntentRequest in alexa - node.js

const HelloWorldIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'CanFulfillIntentRequest'
},
handle(handlerInput) {
if(handlerInput.requestEnvelope.request.intent.name === 'Myname'){
return MynameHandler.handle(handlerInput);
}
const MynameHandler = {
handle(handlerInput) {
const speechText = 'ALex';
const repromtText = 'Please respond';
return handlerInput.responseBuilder
.speak(speechText)
.withCanFulfillIntent(
{
"canFulfill":"YES",
})
.getResponse();
}
};
{
"session":{
"new": true,
"sessionId":"SessionId.<My Session id>",
"application":{
"applicationId":"amzn1.ask.skill.<Application id>"
},
"attributes":{
"key": "string value"
},
"user":{
"userId":"amzn1.ask.account.<user id>
}
},
"request":{
"type":"CanFulfillIntentRequest",
"requestId":"EdwRequestId.<request id>",
"intent":{
"name":"Myname"
},
"locale":"en-US",
"timestamp":"2018-10-12T09:36:31Z"
},
"context":{
"AudioPlayer":{
"playerActivity":"IDLE"
},
"System":{
"application":{
"applicationId":"amzn1.ask.skill.<application id>"
},
"user":{
"userId":"amzn1.ask.account.<user id>"
},
"device":{
"supportedInterfaces":{
}
}
}
},
"version":"1.0"
}
I have been implementing CanfulFillIntentRequest for many days, but no luck so far. I am using alexa-sdk-nodejs v2. I am not able to build the response for CanfulFillIntent. I tried implementing it in an exact way as stated in these documents.
https://developer.amazon.com/docs/custom-skills/understand-name-free-interaction-for-custom-skills.html
https://developer.amazon.com/docs/custom-skills/implement-canfulfillintentrequest-for-name-free-interaction.html.
This is my response handler .
return handlerInput.responseBuilder
.withCanFulfillIntent(
{
'canFulfill': 'MAYBE',
'slots':{
}
})
.getResponse();
}
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
//return handlerInput.requestEnvelope.request.type === 'IntentRequest' || 'CanFulfillIntentRequest'
return handlerInput.requestEnvelope.request.type === 'CanFulfillIntentRequest'
// && handlerInput.requestEnvelope.request.intent.name === 'Myname' || 'HotelIntent';
},
handle(handlerInput) {
if(handlerInput.requestEnvelope.request.intent.name === 'Myname'){
return MynameHandler.handle(handlerInput);
}
};
When i run JSON code in manual JSON, It does not respond to the CanfulFillIntent request and it gets redirected to error handler code.

The withCanFulfillIntent() response builder helper method is only available in ASK SDK for Node.js (Public Beta)
Install public beta by
npm install --save ask-sdk-model#beta
npm install --save ask-sdk-core#beta
or use this in package.json
"dependencies": {
"ask-sdk-core": "^2.1.0-beta.1",
"ask-sdk-model": "^1.4.0-beta.1"
}
I tried your code with beta and got expected results:
{
"version": "1.0",
"response": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>ALex</speak>"
},
"reprompt": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>Please respond</speak>"
}
},
"shouldEndSession": false,
"canFulfillIntent": {
"canFulfill": "YES"
}
},
"userAgent": "ask-node/2.1.0-beta.4 Node/v8.10.0",
"sessionAttributes": {
"key": "string value"
}
}

Related

null response when calling lambda

My lambda function is returning a null response and I'm not sure why. When I change 'res.body' to 'res.statusCode' I get the status code 200 as expected. I've checked the logs of my api call and see that there are no issues with the details I am passing (also confirmed using a curl command. Any ideas?
const https = require('https');
function getRequest() {
const options = {
host: 'vehimgd36c3.execute-api.ap-southeast-2.amazonaws.com',
path: '/callinglink',
method: 'GET',
headers: {
'link': 'https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.Function.html'
}
}
return new Promise(function(resolve, reject) {
https.get(options, (res) => {
resolve(res.body)
}).on('error', (e) => {
reject(Error(e))
})
})
}
exports.GetReturnMessage = async (event) => {
try {
const result = await getRequest();
console.log(result)
return {
"sessionState": {
"dialogAction": {
"type": "Close"
},
"intent": {
"confirmationState": "Confirmed",
"name": "FinalResponse",
"state": "InProgress",
},
},
"messages": [
{
"contentType": "CustomPayload",
"content": result
},
]
};
} catch (error) {
console.log('Error is: ️', error);
return {
statusCode: 400,
body: error.message,
};
}
};
If you check how to use lambda and apigateway. apigateway expects the lamba function to return a response with the structure Read here
var response = {
"statusCode": 200,
"body": "{\n \"TotalCodeSize\": 104330022,\n \"FunctionCount\": 26\n}"
}
in that case you could try returning your object as follows:
exports.GetReturnMessage = async (event) => {
try {
const result = await getRequest();
console.log(result)
const response = {
"sessionState": {
"dialogAction": {
"type": "Close"
},
"intent": {
"confirmationState": "Confirmed",
"name": "FinalResponse",
"state": "InProgress",
},
},
"messages": [
{
"contentType": "CustomPayload",
"content": result
},
]
};
return {
"statusCode": 200,
"body": JSON.stringify(response)
}
} catch (error) {
console.log('Error is: ️', error);
return {
statusCode: 400,
body: error.message,
};
}
}

Unable to execute intents in Alexa Skills

For some reason I am unable to execute a few of my intents in my Alexa skill. Here is the flow of discussion as it is.
'open my passwords'
Alexa: what is your passphrase?
'my passphrase is test'
Alexa: You're in.
'what is my wifi password?'
Alexa: There was a problem with the requested skill's response.
Here is a screenshot of the conversation.
And here are my acceptable utterances, where type is of slot type AMAZON.SearchQuery.
At this point I am just trying to reach GetPasswordHandler and have her say 'hello world'. But I am unable to log or reach this intent. I was reaching it at one point and was able to execute this intent but for some reason it's not working now and I just get the generic There was a problem with the requested skill's response error.
I tried moving around the intents because I thought maybe the order in which they were listed was the problem but I have yet to find an order that works. I also tried using CloudWatch to log whatever the issue might be but I am pretty new to it and I might be using it incorrectly because I feel like the information isn't very helpful aside from the fact that alarms. All I have been able to find out from the JSON Input in the test panel is that the response was invalid. Here is what the error looks like in the input JSON for the SessionEndRequest.
"error": {
"type": "INVALID_RESPONSE",
"message": "An exception occurred while dispatching the request to the skill."
}
This is the input JSON for the initial GetPassword request.
"request": {
"type": "IntentRequest",
"requestId": "amzn1.echo-api.request.bdae78eb-3c92-49a8-b3af-c590e284b842",
"timestamp": "2020-02-05T17:23:03Z",
"locale": "en-US",
"intent": {
"name": "GetPassword",
"confirmationStatus": "NONE",
"slots": {
"type": {
"name": "type",
"value": "WiFi",
"confirmationStatus": "NONE",
"source": "USER"
}
}
}
}
Here is my Lambda code.
// This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK (v2).
// Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management,
// session persistence, api calls, and more.
const Alexa = require('ask-sdk-core');
const passphrase = 'test';
const instructions = `You can access existing passwords or create a new password.
Just specify password type, such as wifi, laptop or cellphone.`;
// the intent being invoked or included it in the skill builder below.
const LoginHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === "Login";
},
handle(handlerInput) {
console.log('test');
const request = handlerInput.requestEnvelope.request;
const responseBuilder = handlerInput.responseBuilder;
let slotValues = handlerInput.requestEnvelope.request.intent.slots
if (slotValues && slotValues.passphrase.value === passphrase){
var attributes = handlerInput.attributesManager.getSessionAttributes()
attributes.isLoggedIn = true
const speakOutput = "You're in.";
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
} else {
const speakOutput = `Passphrase not recognized. What is your passphrase?`;
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
}
};
const LaunchRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
},
handle(handlerInput) {
var attributes = handlerInput.attributesManager.getSessionAttributes();
if (attributes.isLoggedIn){
const speakOutput = `Welcome to your passwords. ${instructions}`;
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
} else {
const speakOutput = `What is your pass phrase?`;
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
}
};
// THIS IS THE INTENT THAT DOES NOT WORK
const GetPasswordHandler = {
canHandle(handlerInput) {
return (Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && handlerInput.requestEnvelope.request.intent.name === "GetPassword");
},
handle(handlerInput) {
console.log('yes');
const speakOutput = 'hello world';
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.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!';
handlerInput.sessionAttributes.isLoggedIn = false
return handlerInput.responseBuilder
.speak(speakOutput)
.getResponse();
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'SessionEndedRequest';
},
handle(handlerInput) {
// Any cleanup logic goes here.
handlerInput.sessionAttributes.isLoggedIn = false
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) {
handlerInput.sessionAttributes.isLoggedIn = false
console.log(`~~~~ Error handled: ${error.stack}`);
const speakOutput = `Sorry, I had trouble doing what you asked. Please try again. ${error.stack}`;
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,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
LoginHandler,
GetPasswordHandler,
HelpIntentHandler,
IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
)
.addErrorHandlers(
ErrorHandler,
)
.lambda();
And here is my JSON.
{
"interactionModel": {
"languageModel": {
"invocationName": "my passwords",
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "GetPassword",
"slots": [
{
"name": "type",
"type": "AMAZON.SearchQuery"
}
],
"samples": [
"password for my {type}",
"{type} password",
"what is my {type} password"
]
},
{
"name": "AMAZON.MoreIntent",
"samples": []
},
{
"name": "AMAZON.NavigateSettingsIntent",
"samples": []
},
{
"name": "AMAZON.NextIntent",
"samples": []
},
{
"name": "AMAZON.PauseIntent",
"samples": []
},
{
"name": "AMAZON.ResumeIntent",
"samples": []
},
{
"name": "Login",
"slots": [
{
"name": "passphrase",
"type": "AMAZON.SearchQuery"
}
],
"samples": [
"my passphrase is {passphrase}"
]
},
{
"name": "AMAZON.PageUpIntent",
"samples": []
},
{
"name": "AMAZON.PageDownIntent",
"samples": []
},
{
"name": "AMAZON.PreviousIntent",
"samples": []
},
{
"name": "AMAZON.ScrollRightIntent",
"samples": []
},
{
"name": "AMAZON.ScrollDownIntent",
"samples": []
},
{
"name": "AMAZON.ScrollLeftIntent",
"samples": []
},
{
"name": "AMAZON.ScrollUpIntent",
"samples": []
}
],
"types": []
}
}
}
I ended up just rewriting the intents and they work now. I'm not sure exactly what was wrong but I noticed that when I added the new intents they were added to the bottom of my skill manifest as opposed to the previous order. I am not 100% sure that this was the issue but it is the only thing I noticed changing when I remade the intentions.

Alexa Node JS: Using Dialog.Delegate and dialog state won't change to COMPLETE

Closest question I could find on here:
Alexa Dialog Model Step and dialogState is never in COMPLETED
But the solution there was to send Dialog.Delegate to Alexa Skill, which I am already doing.
I've read that there are potential bugs with the Skill Test, so I have tried this on Echosim and the Alexa App to no avail.
My code is below, followed by JSON response generated by testing in Lambda console.
I can't seem to make it to --console.log("You've made it in the else statement containing the switches")--
Moreover, I would expect the --console.log("Current dialog state before switches" + request.dialogState);-- to print twice since I have two slots to fill, but it only shows up once in the console.
Thanks in advance.
const HobbyIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HobbyIntent';
},
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
const responseBuilder = handlerInput.responseBuilder;
const currentIntent = request.intent;
if (request.dialogState !== 'COMPLETED'){
//const speechText = 'Would you like your hobby to be general,
competetive, observational, or do you want to collect something?';
console.log("Current dialog state before switches" + request.dialogState);
return handlerInput.responseBuilder
.addDelegateDirective(currentIntent)
.getResponse();
} else{
console.log("You've made it in the else statement containing the
switches")
const speechText = '';
var randomHobby = '';
console.log("Here are the current slots' contents: " + currentIntent.slots)
if (currentIntent.slots.hobbyType && currentIntent.slots.hobbyLocation){
var typeOfHobby = currentIntent.slots.hobbyType.resolutions.resolutionsPerAuthority[0].values[0].value.name;
var locationOfHobby = currentIntent.slots.hobbyLocation.resolutions.resolutionsPerAuthority[0].values[0].value.name;
switch(typeOfHobby){
case "competetive":
typeOfHobby = "CompetetiveHobbies";
break;
case "collection":
typeOfHobby = "CollectionHobbies";
break;
case "observational":
typeOfHobby = "ObservationalHobbies";
break;
default:
typeOfHobby = "GeneralHobbies"
break;
}
switch(locationOfHobby){
case "indoor":
locationOfHobby = "Indoors";
break;
case "outdoor":
locationOfHobby = "Outdoors";
break;
default:
return handlerInput.responseBuilder
.speak("I don't know any hobbies like that. Please try again.")
.addDelegateDirective(currentIntent)
.getResponse();
}
//randomHobby =
Hobbies.typeOfHobby.locationOfHobby[Math.floor(Math.random() *
Hobbies.typeOfHobby.locationOfHobby.length)];
//speechText = `You should definitely do ${randomHobby}`;
speechText = "you have reached the point after the switch statements"
} // end if for slot-matching
else{
speechText = "Something went wrong with the slots"
}
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.withSimpleCard('Hello World', speechText)
.getResponse();
}
},
};
Here is my JSON response:
Response:
{
"version": "1.0",
"response": {
"directives": [
{
"type": "Dialog.Delegate",
"updatedIntent": {
"name": "HobbyIntent",
"confirmationStatus": "NONE",
"slots": {
"hobbyType": {
"name": "hobbyType",
"value": "general",
"resolutions": {
"resolutionsPerAuthority": [
{
"authority": "amzn1.er-authority.echo-sdk.amzn1.ask.skill.a0b76b45-13ff-4be6-aff3-5b9bf60068d1.hobbieType",
"status": {
"code": "ER_SUCCESS_MATCH"
},
"values": [
{
"value": {
"name": "general",
"id": "958153f1b8b96ec4c4eb2147429105d9"
}
}
]
}
]
},
"confirmationStatus": "NONE",
"source": "USER"
},
"hobbyLocation": {
"name": "hobbyLocation",
"value": "indoors",
"resolutions": {
"resolutionsPerAuthority": [
{
"authority": "amzn1.er-authority.echo-sdk.amzn1.ask.skill.a0b76b45-13ff-4be6-aff3-5b9bf60068d1.hobbyLocation",
"status": {
"code": "ER_SUCCESS_MATCH"
},
"values": [
{
"value": {
"name": "indoor",
"id": "b276393840653779e270ecb76ba4db12"
}
}
]
}
]
},
"confirmationStatus": "NONE",
"source": "USER"
}
}
}
}
]
},
"userAgent": "ask-node/2.3.0 Node/v8.10.0",
"sessionAttributes": {}
}
Request ID:
"eafe99b7-f994-11e8-8fcf-dfe94cfc1e14"
Function Logs:
START RequestId: eafe99b7-f994-11e8-8fcf-dfe94cfc1e14 Version: $LATEST
2018-12-06T20:24:23.009Z eafe99b7-f994-11e8-8fcf-dfe94cfc1e14 Current dialog state before switchesIN_PROGRESS
END RequestId: eafe99b7-f994-11e8-8fcf-dfe94cfc1e14
REPORT RequestId: eafe99b7-f994-11e8-8fcf-dfe94cfc1e14 Duration: 95.26 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 21 MB
Once I commented out if (request.dialogState !== COMPLETED and manually check for each slot while delegating if it's not filled, it works.
handle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
const responseBuilder = handlerInput.responseBuilder;
const currentIntent = request.intent;
let slots = currentIntent.slots;
//if (request.dialogState !== 'COMPLETED'){ ------------ this will not work for some reason
if(!(slots.hobbyType.value)){
return handlerInput.responseBuilder
.addDelegateDirective(currentIntent)
.getResponse()
}else if(!(slots.hobbyLocation.value)){
return handlerInput.responseBuilder
.addDelegateDirective(currentIntent)
.getResponse()
}else{

Alexa Skill Learning: TypeError: Cannot read property 'value' of undefined

I keep getting an error when I try to test my basic skill (I'm trying to learn how to create them).
Here is the error from the log:
2018-11-21T16:10:55.759Z 06a36441-eda8-11e8-a421-f996bf66c592
Unexpected exception 'TypeError: Cannot read property 'value' of
undefined':
TypeError: Cannot read property 'value' of undefined at
Object.getSuggestion (/var/task/index.js:31:54) at emitNone
(events.js:86:13) at AlexaRequestEmitter.emit (events.js:185:7) at
AlexaRequestEmitter.EmitEvent
(/var/task/node_modules/alexa-sdk/lib/alexa.js:216:10) at
AlexaRequestEmitter.ValidateRequest
(/var/task/node_modules/alexa-sdk/lib/alexa.js:181:23) at
AlexaRequestEmitter.HandleLambdaEvent
(/var/task/node_modules/alexa-sdk/lib/alexa.js:126:25) at
AlexaRequestEmitter.value
(/var/task/node_modules/alexa-sdk/lib/alexa.js:100:31)
at exports.handler (/var/task/index.js:52:9)
How can I figure this out?
Here is my code:
var Alexa = require('alexa-sdk');
const APP_ID = 'amzn1.ask.skill.ab07421a-0a92-4c2b-b3bd-998e14286xxx';
const skillData = [
{
city: "Austin",
suggestion: "Austin has some of the most outstanding people."
},
{
city: "San Antonio",
suggestion: "San Antonio has some of the most outstanding people."
},
{
city: "Dallas",
suggestion: "The Dallas metroplex is one of the hottest places."
}
];
var number = 0;
while(number<3){
var handlers = {
'LaunchRequest': function () {
this.emit(':ask', 'Tell me the name of the major city you are closest to'
},
'Unhandled': function () {
this.emit(':ask', 'Try saying a city name like Austin, San Antonio, or Dallas');
},
'getSuggestion': function() {
var city = this.event.request.intent.slots.City.value;
this.emit(':ask', getSuggestion(skillData,'city', city.toUpperCase()).suggestion + '. Give me another city and I\'ll hook you up with the best peeps.');
},
'AMAZON.HelpIntent': function () {
this.emit(':ask', "What can I help you with?", "How can I help?");
},
'AMAZON.CancelIntent': function () {
this.emit(':tell', "Okay!");
},
'AMAZON.StopIntent': function () {
this.emit(':tell', "Goodbye!");
},
};
number = number+1;
}
exports.handler = function(event, context, callback){
var alexa = Alexa.handler(event, context);
alexa.appId = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};
function getSuggestion(arr, propName, cityName) {
for (var i=0; i < arr.length; i++) {
if (arr[i][propName] == cityName) {
return arr[i];
}
}
}
Update
I've made some changes that were suggested below, however, I am still getting an error after the initial response.
"errorMessage": "Cannot read property 'city' of undefined"
Please look at my new code and help me figure this out:
var Alexa = require('alexa-sdk');
const APP_ID = 'amzn1.ask.skill.ab07421a-0a92-4c2b-b3bd-998e14286xxx';
const skillData = [
{
city: 'Austin',
suggestion: "Austin is blahblahblahblahlshflashdfasldfha blah."
},
{
city: 'San Antonio',
suggestion: "San Antonio has blahblahblahblahlshflashdfasldfha blah."
},
{
city: 'Dallas',
suggestion: "The Dallas metroplex is one of the hottest blahblahblahbla blahblahblahblahblahblah."
}
];
var number = 0;
while(number<3){
var handlers = {
'LaunchRequest': function () {
this.emit(':ask', 'Tell me the name of the major city you are closest to!', 'Which major city are you closest to?');
},
'Unhandled': function () {
this.emit(':ask', "Try saying a city name like Austin, San Antonio, or Dallas");
},
'getSuggestion': function() {
var city = this.event.request.intent.slots.city.value;
this.emit(':ask', getSuggestion(skillData,'city', city.toUpperCase()).suggestion + '. Give me another city and I\'ll hook you up with the best peeps.');
},
'AMAZON.HelpIntent': function () {
this.emit(':ask', "What can I help you with?", "How can I help?");
},
'AMAZON.CancelIntent': function () {
this.emit(':tell', "Okay!");
},
'AMAZON.StopIntent': function () {
this.emit(':tell', "Goodbye!");
},
};
number = number+1;
}
exports.handler = function(event, context, callback){
var alexa = Alexa.handler(event, context);
alexa.appId = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};
function getSuggestion(arr, propName, cityName) {
for (var i=0; i < arr.length; i++) {
var prop = arr[i][propName];
prop = prop.toUpperCase();
if (prop == cityName) {
return arr[i];
}
}
}
UPDATE #2
After a lot of trying different things, I've gotten the skill to run with the help of bal simpson!
However, the skill still errors out when the user utters a city name. There must be an error in my Interaction Model, which is below:
{
"interactionModel": {
"languageModel": {
"invocationName": "city picker",
"intents": [
{
"name": "AMAZON.FallbackIntent",
"samples": []
},
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": [
"stop"
]
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "getSuggestion",
"slots": [],
"samples": [
"san antonio",
"dallas",
"austin"
]
}
],
"types": []
}
}
}
Getting close!!
As a last-ditch effort:
Here is my index.js housed in Lambda. Would anyone mind looking at this?
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "LaunchRequest";
},
handle(handlerInput) {
console.log("LaunchRequestHandler");
let speechText = 'Lets get you into your new home. Tell me the name of the major city you are closest to!';
let prompt = 'Which major city are you closest to?';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(prompt)
.getResponse();
}
};
const GetSuggestionIntentHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.requestEnvelope.request.intent.name === "getSuggestion"
);
},
handle(handlerInput) {
let intent = handlerInput.requestEnvelope.request.intent;
let city = intent.slot.city.value;
let suggestion = getSuggestion(skillData,'city', city.toUpperCase()).suggestion;
return handlerInput.responseBuilder
.speak(suggestion)
.reprompt('prompt')
.getResponse();
}
};
const HelpIntentHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.requestEnvelope.request.intent.name === "AMAZON.HelpIntent"
);
},
handle(handlerInput) {
const speechText = "Try saying a city name like Austin, San Antonio, or Dallas";
const promptText = "How can I help?";
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(promptText)
// .withSimpleCard("City Details", speechText)
.getResponse();
}
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
(handlerInput.requestEnvelope.request.intent.name ===
"AMAZON.CancelIntent" ||
handlerInput.requestEnvelope.request.intent.name ===
"AMAZON.StopIntent" ||
handlerInput.requestEnvelope.request.intent.name ===
"AMAZON.PauseIntent")
);
},
handle(handlerInput) {
const speechText = `Seeya later!`;
return (
handlerInput.responseBuilder
.speak(speechText)
.withShouldEndSession(true)
.getResponse()
);
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.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 handled: ${error.message}`);
return handlerInput.responseBuilder
.speak('Sorry, I can\'t understand the command. Try saying a city name like Austin, San Antonio, or Dallas')
.reprompt('Try saying a city name like Austin, San Antonio, or Dallas')
.getResponse();
},
};
const SystemExceptionHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type ===
"System.ExceptionEncountered"
);
},
handle(handlerInput) {
console.log(
`System exception encountered: ${
handlerInput.requestEnvelope.request.reason
}`
);
}
};
const skillBuilder = Alexa.SkillBuilders.custom();
exports.handler = skillBuilder
.addRequestHandlers(
LaunchRequestHandler,
GetSuggestionIntentHandler,
CancelAndStopIntentHandler,
HelpIntentHandler,
SystemExceptionHandler,
SessionEndedRequestHandler
)
.addErrorHandlers(ErrorHandler)
.lambda();
function getSuggestion(arr, propName, cityName) {
for (var i=0; i < arr.length; i++) {
var prop = arr[i][propName];
prop = prop.toUpperCase();
if (prop == cityName) {
return arr[i];
}
}
}
And here is my Interaction Model from the Developer Portal:
{
"interactionModel": {
"languageModel": {
"invocationName": "city picker",
"intents": [
{
"name": "AMAZON.FallbackIntent",
"samples": []
},
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": [
"stop"
]
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "getSuggestion",
"slots": [
{
"name": "city",
"type": "CITY_NAMES"
}
],
"samples": [
"{city}"
]
}
],
"types": [
{
"name": "CITY_NAMES",
"values": [
{
"name": {
"value": "dallas"
}
},
{
"name": {
"value": "san antonio"
}
},
{
"name": {
"value": "austin"
}
}
]
}
]
}
}
}
ok. alexa-sdk has been deprecated link. To get the new SDK, do this.
1 - Create a new function in Lambda.
2 - Choose AWS Serverless Application Repository.
3 - Choose alexa-skills-kit-nodejs-factskill.
4 - Click on deploy. Once deployed, click on functions and you should see the new function you just created with a name like aws-serverless-repository-alexaskillskitnodejsfact-NR8HPILH8WNI.
5 - Delete the code and replace the code with this.
const Alexa = require('ask-sdk');
const skillData = [
{
city: 'Austin',
suggestion: "Austin is blahblahblahblahlshflashdfasldfha blah."
},
{
city: 'San Antonio',
suggestion: "San Antonio has blahblahblahblahlshflashdfasldfha blah."
},
{
city: 'Dallas',
suggestion: "The Dallas metroplex is one of the hottest blahblahblahbla blahblahblahblahblahblah."
}
];
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "LaunchRequest";
},
handle(handlerInput) {
console.log("LaunchRequestHandler");
let speechText = 'Tell me the name of the major city you are closest to!';
let prompt = 'Which major city are you closest to?';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(prompt)
.getResponse();
}
};
const GetSuggestionIntentHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.requestEnvelope.request.intent.name === "getSuggestion"
);
},
handle(handlerInput) {
let intent = handlerInput.requestEnvelope.request.intent;
let city = intent.slots.city.value;
let suggestion = getSuggestion(skillData,'city', city.toUpperCase()).suggestion;
return handlerInput.responseBuilder
.speak(suggestion)
.reprompt('prompt')
.getResponse();
}
};
const HelpIntentHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.requestEnvelope.request.intent.name === "AMAZON.HelpIntent"
);
},
handle(handlerInput) {
const speechText = "Try saying a city name like Austin, San Antonio, or Dallas";
const promptText = "How can I help?";
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(promptText)
// .withSimpleCard("City Details", speechText)
.getResponse();
}
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
(handlerInput.requestEnvelope.request.intent.name ===
"AMAZON.CancelIntent" ||
handlerInput.requestEnvelope.request.intent.name ===
"AMAZON.StopIntent" ||
handlerInput.requestEnvelope.request.intent.name ===
"AMAZON.PauseIntent")
);
},
handle(handlerInput) {
const speechText = `Goodbye`;
return (
handlerInput.responseBuilder
.speak(speechText)
.withShouldEndSession(true)
.getResponse()
);
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.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 handled: ${error.message}`);
return handlerInput.responseBuilder
.speak('Sorry, I can\'t understand the command. Try saying a city name like Austin, San Antonio, or Dallas')
.reprompt('Try saying a city name like Austin, San Antonio, or Dallas')
.getResponse();
},
};
const SystemExceptionHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type ===
"System.ExceptionEncountered"
);
},
handle(handlerInput) {
console.log(
`System exception encountered: ${
handlerInput.requestEnvelope.request.reason
}`
);
}
};
const skillBuilder = Alexa.SkillBuilders.custom();
exports.handler = skillBuilder
.addRequestHandlers(
LaunchRequestHandler,
GetSuggestionIntentHandler,
CancelAndStopIntentHandler,
HelpIntentHandler,
SystemExceptionHandler,
SessionEndedRequestHandler
)
.addErrorHandlers(ErrorHandler)
.lambda();
function getSuggestion(arr, propName, cityName) {
for (var i=0; i < arr.length; i++) {
var prop = arr[i][propName];
prop = prop.toUpperCase();
if (prop == cityName) {
return arr[i];
}
}
}
6 - Go to developer.amazon.com and change your Alexa Skill endpoint to the new lambda ARN.
To add a slot type:
Specify slot in your sample phrases like this:
Change your slot name to city:
So instead of musicStations it will be city. Make sure you have entered the three values in your slot values like this:
Add your custom slot values to CITY_NAMES:
If you have done it right, your interaction model should be something like this:
"name": "getSuggestion",
"slots": [
{
"name": "city",
"type": "CITY_NAMES"
}
],
"samples": [
"city name is {city}",
"{city}"
]
Testing Lambda code
In the drop down menu, choose 'configure test events'.
Create new test event with JSON from your developer test portal which should look like this.
{
"version": "1.0",
"session": {
"new": true,
"sessionId": "amzn1.echo-api.session.XXXXXX",
"application": {
"applicationId": "amzn1.ask.skill.XXXXXX"
},
"user": {
"userId": "amzn1.ask.account.XXXXXX"
}
},
"context": {
"AudioPlayer": {
"playerActivity": "IDLE"
},
"System": {
"application": {
"applicationId": "amzn1.ask.skill.XXXXXX"
},
"user": {
"userId": "amzn1.ask.account.XXXXXX"
},
"device": {
"deviceId": "amzn1.ask.device.XXXXXX",
"supportedInterfaces": {
"AudioPlayer": {}
}
},
"apiEndpoint": "https://api.eu.amazonalexa.com",
"apiAccessToken": "ACCESS_TOKEN"
},
},
"request": {
"type": "IntentRequest",
"requestId": "amzn1.echo-api.request.XXXX",
"timestamp": "2018-12-03T20:28:29Z",
"locale": "en-IN",
"intent": {
"name": "PlayRadioIntent",
"confirmationStatus": "NONE",
"slots": {
"musicStation": {
"name": "musicStation",
"value": "classic rock",
"resolutions": {
"resolutionsPerAuthority": [
{
"authority": "amzn1.er-authority.XXXX.RadioStations",
"status": {
"code": "ER_SUCCESS_MATCH"
},
"values": [
{
"value": {
"name": "Classic Rock",
"id": "b8a5bd97a8a02691f9f81dcfb12184dd"
}
}
]
}
]
},
"confirmationStatus": "NONE",
"source": "USER"
}
}
}
}
Click on test button
Check Logs
Does the test result look like this? To see the logs, click on logs. It might have additional error details.

How to call Web3js function from Nodejs file

I have the following working web3js code, Calling App.createContract() on button click works well on a webpage, however I want to call App.createContract() or similar from another Nodejs controller. Infact what I am thinking of is making an API in Node which could call the web3js function and returns a JSON result back to the caller. Can you please help me how to import my web3js file and call the function from Node Controller? Thanks
import "../stylesheets/app.css";
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract';
import { default as CryptoJS} from 'crypto-js';
var accounts;
var account;
var shLogABI;
var shLogContract;
var shLogCode;
var shLogSource;
window.App = {
start: function() {
var self = this;
web3.eth.getAccounts(function(err, accs) {
if (err != null) {
alert("There was an error fetching your accounts.");
return;
}
if (accs.length == 0) {
alert("Couldn't get any accounts! Make sure your Ethereum client is configured correctly.");
return;
}
accounts = accs;
console.log(accounts);
account = accounts[0];
web3.eth.defaultAccount= account;
shLogSource= "pragma solidity ^0.4.6; contract SHLog { struct LogData{ string FileName; uint UploadTimeStamp; string AttestationDate; } mapping(uint => LogData) Trail; uint8 TrailCount=0; function AddNewLog(string FileName, uint UploadTimeStamp, string AttestationDate) { LogData memory newLog; newLog.FileName = FileName; newLog.UploadTimeStamp= UploadTimeStamp; newLog.AttestationDate= AttestationDate; Trail[TrailCount] = newLog; TrailCount++; } function GetTrailCount() returns(uint8){ return TrailCount; } function GetLog(uint8 TrailNo) returns (string,uint,string) { return (Trail[TrailNo].FileName, Trail[TrailNo].UploadTimeStamp, Trail[TrailNo].AttestationDate); } }";
web3.eth.compile.solidity(shLogSource, function(error, shLogCompiled){
shLogABI = JSON.parse(' [ { "constant": false, "inputs": [ { "name": "TrailNo", "type": "uint8" } ], "name": "GetLog", "outputs": [ { "name": "", "type": "string" }, { "name": "", "type": "uint256" }, { "name": "", "type": "string" } ], "payable": false, "type": "function" }, { "constant": false, "inputs": [ { "name": "FileName", "type": "string" }, { "name": "UploadTimeStamp", "type": "uint256" }, { "name": "AttestationDate", "type": "string" } ], "name": "AddNewLog", "outputs": [], "payable": false, "type": "function" }, { "constant": false, "inputs": [], "name": "GetTrailCount", "outputs": [ { "name": "", "type": "uint8" } ], "payable": false, "type": "function" } ]');
shLogContract = web3.eth.contract(shLogABI);
});
});
},
createContract: function()
{
shLogContract.new("", {from:account, gas: 3000000}, function (error, deployedContract){
if(deployedContract.address)
{
document.getElementById("contractAddress").value=deployedContract.address;
document.getElementById("fileName").value = '';
document.getElementById("uploadTimeStamp").value = '';
document.getElementById("attestationDate").value = '';
}
})
},
addNewLog: function()
{
var contractAddress = document.getElementById("contractAddress").value;
var deployedshLog = shLogContract.at(contractAddress);
var fileName = document.getElementById("fileName").value;
var uploadTimeStamp = document.getElementById("uploadTimeStamp").value;
var attestationDate = document.getElementById("attestationDate").value;
deployedshLog.AddNewLog(fileName, uploadTimeStamp, attestationDate, function(error){
console.log(error);
})
},
getLog: function()
{
try{
var contractAddress = document.getElementById("contractAddress").value;
var deployedshLog = shLogContract.at(contractAddress);
deployedshLog.GetTrailCount.call(function (error, trailCount){
deployedshLog.GetLog.call(trailCount-1, function(error, returnValues){
document.getElementById("fileName").value= returnValues[0];
document.getElementById("uploadTimeStamp").value = returnValues[1];
document.getElementById("attestationDate").value=returnValues[2];
})
})
}
catch (error) {
document.getElementById("fileName").value= error.message;
document.getElementById("uploadTimeStamp").value = error.message;
document.getElementById("attestationDate").value= error.message;
}
}
};
window.addEventListener('load', function() {
if (typeof web3 !== 'undefined') {
console.warn("Using web3 detected from external source. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
window.web3 = new Web3(web3.currentProvider);
} else {
console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}
App.start();
});
Simple example for web3js 1.0.0.beta*
1) Add web3js to your package.json on a server side:
"web3": "^1.0.0-beta.27"
2) Require and init web3 with some provider:
const Web3 = require('web3');
const web3SocketProvider = new Web3.providers.WebsocketProvider('ws://0.0.0.0:8546');
const web3Obj = new Web3(web3Provider);
Now you can use your web3 object as usual:
async function getAccounts() {
let accounts = await web3Obj.eth.getAccounts();
}

Resources