I am working with on a Lambda function that an Alexa skill can use. All i want is something simple that can read the event and send the info back to the user. For this purpose I'm using the npm library ical.js https://www.npmjs.com/package/ical with the function ical.fromURL(url, options, function(err, data) {} ) but the problem is that the function never executes. I have the following code:
var Alexa = require("alexa-sdk");
var ical = require("ical");
var test = "This is a simple test 1";
exports.handler = function(event, context) {
var alexa = Alexa.handler(event, context);
alexa.registerHandlers(handlers);
alexa.execute();
};
var handlers = {
'LaunchRequest':function() {
console.log(test);
ical.fromURL('http://lanyrd.com/topics/nodejs/nodejs.ics', {}, function(err, data) {
test = "Nothing changes";
});
console.log(test);
test.emit(':tell', 'I am done');
}
};
This is the output I get from the could watch when I do "ask simulate -l en-US -t 'start calendar read'" in ASK CLI output on cloudwatch as you can see the test text doesn't change, and would work if it was outside of the function(err, data){}. I don't believe there are any problems with reading in the calendar as the link http://lanyrd.com/topics/nodejs/nodejs.ics downloads a working ics file. The function activates if I try it in the https://npm.runkit.com/ical tool. So I am not sure what I am doing wrong. Also the skill works gives the response when tested in the alexa skill kit development.
You mistype the test.emit(':tell', 'I am done'); instead of this.emit(':tell', 'I am done');.
Also your code will not return the data from the url, because the this.emit will be return first rather than your callback function. In order to return the data, you need to put the this.emit inside the callback function of ical.fromURL.
var handlers = {
'LaunchRequest':function() {
console.log(test);
ical.fromURL('http://lanyrd.com/topics/nodejs/nodejs.ics', {}, (err, data) => {
test = "Nothing changes";
console.log(test);
// you can edit the response here base on the data you receive.
this.emit(':tell', `I am done: ${test}`);
});
}
};
Related
I am currently developing an Amazon Alexa Skill, which asks the user for a color. The user enters the color by voice and Alexa checks, if the color is in a defined array of values. If that is the case, it returns the color name with an ID. Now this works as intended, but now I would like to put this value in AWS DynamoDB. I read some tutorials on how to connect and to write into DynamoDB using AWS Lambda (Runtime Node.js 8.10)
So, in the following code, you can see my AnswerIntentHandler of my Alexa Skill. I included the exports. handle function to write the value of the ID of the color and the name of the color in the table called "alexa_farbe". But when I simulate the Skill with the Alexa Skill developer, the code only gives out the "speechText" and doesn't seem to run the code to write into the DynamoDB. Perhaps it is not possible to run a exports.handle in the AnswerIntentHanlder or is it? I am very new to this topic so I am not really sure where the mistake in this code is. I provide the code of my AnswerIntentHandler, but I can also provide the whole code of the Alexa Skill.
I hope somebody can give me a hint what to to.
const AnswerIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'AnswerIntent';
},
handle(handlerInput) {
const slots = handlerInput.requestEnvelope.request.intent.slots;
const number = slots['FarbAuswahl'].value;
var numberid = slots['FarbAuswahl'].resolutions.resolutionsPerAuthority[0].values[0].value.id; /* ID der Farbe auslesen */
var speechText = 0;
speechText = `Prima, ich stelle die Farbe ${number} mit der ID ${numberid} ein!`;
/* Ab hier Versuch in die Datenbank DynamoDB zu schreiben */
exports.handle = function(e, etx, callback) {
var params = {
Item: {
ID: '${numberid}',
Farbname: '${number}'
},
TableName: 'alexa_farbe'
};
docClient.put(params, function(err, data) {
if(err) {
callback(err, null);
} else {
callback(null, data);
}
});
};
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('Ausgewählte Farbe:', speechText)
.getResponse();
},
};
You should not put the code in the exports.handler. Please take a look at this example (the DynamoDB support code is in the helpers.js file). As a coincidence it's also working with colors.
If the data you're storing is associated to each skill user (eg. a user attribute) a much easier way to do DynamoDB persistence is to use ASK persistent attributes (already supported in the ASK SDK).
I tried to edit the code and put the whole DynamoDB posting to another file called dynamodb.js. This is the content:
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});
exports.handle = function(e, ctx, callback) {
var params = {
Item: {
date: Date.now(),
message: "This hopefully works"
},
TableName: 'alexa_farbe'
};
docClient.put(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});
};
I just want to write the date and an example phrase into my DynamoDB.
To trigger this function, I tried to implement some kind of "runScript" into my AnswerIntentHandler of my Alexa Skill.
But it doesn't seem to trigger the file. Can you give me some advice whats wrong with this code and how to call another node.js file from the AnswerIntent.
Here is my edited AnswerIntent:
const AnswerIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'AnswerIntent';
},
handle(handlerInput) {
const slots = handlerInput.requestEnvelope.request.intent.slots;
let number = slots['FarbAuswahl'].value;
let numberid = slots['FarbAuswahl'].resolutions.resolutionsPerAuthority[0].values[0].value.id; /* ID der Farbe auslesen */
var speechText = 0;
speechText = `Prima, ich stelle die Farbe ${number} mit der ID ${numberid} ein!`;
module.runScript('./some-script.js', function (err) {
if (err) throw err;
console.log('finished running some-script.js');
});
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('Ausgewählte Farbe:', speechText)
.getResponse();
},
};
It may be a wrong way to use bull queue but here is what I want to do:
var Promise = require('bluebird');
var redis = require('redis');
var Queue = require('bull');
var redisClient = redis.createClient(6379);
var pdfQueue = new Queue('msg');
function check(resolve, reject,i) {
console.log('check called');
//Or if it is in Router then I want to send request, response in queue so that I can call them in on complete function
pdfQueue.add('msg',{'msg':'Hello', 'resolve':resolve,'reject':reject}).then(job=>{
console.log('added to the pdf')
});
}
pdfQueue.on('completed', function (job, result) {
//Here I want to call request.send('some msg');
//and resolve('complete');
resolve('final callback');
})
pdfQueue.process('msg',100,function (job,done) {
console.log('process');
done(null,'job done ')
})
function check2 () {
return new Promise(function(resolve, reject){
check(resolve,reject);
})
}
check2().then(data => {
console.log('got the value ', data)
});
In my real project I want to implement queue where I will be sending pdf to the user. Like res.download(pdf path); but this function should be in pdf.on('completed',()=>{ res.download(pdf path); }); or in resolve(pdfPath) but I am not able to find anyway to send pdf to the user using queue because I don't know how to call response or resolve in other functions by using queue jobs.
Please help me. Thanks you
I am trying to ask a question to the user and using AMAZON.yesIntent and noIntent to capture the response. In case I get response, I am calling other function which should emit something back to user. But the emit is not being called. Code below:
'use strict';
var Alexa = require("alexa-sdk");
var https = require('https');
var alexa;
exports.handler = function(event, context, callback) {
alexa = Alexa.handler(event, context);
alexa.registerHandlers(handlers);
alexa.execute();
};
var handlers = {
'LaunchRequest': function() {
alexa.emit(':ask', 'my text');
},
'oneShotIntent': function() {
var self = this;
// removed the code for simplicity
self.attributes['yes_no'] = true;
alexa.emit(':ask', 'sample yes no question');
})
},
'AMAZON.YesIntent': function () {
if (this.attributes['yes_no']) {
delete this.attributes['yes_no'];
alexa.emit('oneShotSecond');
}
},
'oneShotSecond': function() {
delete this.attributes['yes_no']; // already deleted
// removed code for simplicity
var self = this;
// removed code for simplicity
console.log(info);
if (info) {
console.log('here in if condition');
self.emit(':tell', 'sample text');
} else {
self.emit(':tell', 'sorry failed');
}
});
}
};
The first emit is working. The console.log in other function are happening. But emit is failing.
No logs in cloudwatch also. It just ends after printing the console.log data points.
Any help?
I am not sure if I understand
alexa.emit('oneShotSecond');
However I would have done it like below
oneShotSecond(this);
And then
'oneShotSecond': function(self) { // use self.emit}
I have a Meteor method inside that am calling the soap function.
Meteor is executing all the statement before its getting the response from soap client.
So i am getting a result as undefined.
I want to promise the soap execution before executing other statements in the method.
createSoapConnection(){
var Soap = require('soap');
var url = 'https://xxxxxx/index.php/api/v2_soap/?wsdl';
var args = {username: 'xxxxxx', apiKey: 'xxxxxx'};
let client = Soap.createClient(url, function(err, client){
let result = client.login(args, function(err, result) {
let sessionId = result.loginReturn.$value;
console.log(sessionId);
return {
conn: client,
sessionId: sessionId
};
});
});
}
I am calling this method by this meteor method.
addsoapmessage(){
let a = Meteor.call("createSoapConnection");
console.log(a);
}
In the console am getting undefined as a result. after that the session ID is getting printed. How do i solve this?
Meteor methods don't return anything. You can ask for a callback, which will fire when it's done, but the callback won't pass back a return value, only an error if it found one.
The best way to deal with this is to get the method to save the result in a collection, and rely on a subscription to let the client see it reactively.
Alternatively you can store the returned data in a server variable, which is then only accessible by the server code (but that might work, as other server methods might want to access the values.
Implement a callback function in your meteor call
let a = Meteor.call("createSoapConnection", function (error, result) {
// display the error to the user and abort
if (error)
console.error(error.reason);
else {
console.log(result);
}
});
meteor add zardak:soap
Install this package in root of application folder. then try with those following codes.
var url = 'http://example.com/wsdl?wsdl';
var args = {name: 'value'};
try {
var client = Soap.createClient(url);
var result = client.MyFunction(args);
return result; // or send this result to the function where ever you want.
}
catch (err) {
if(err.error === 'soap-creation') {
console.log('SOAP Client creation failed');
}
else if (err.error === 'soap-method') {
console.log('SOAP Method call failed');
}
}
You can do any soap api calls with these functions. for more details visit : https://atmospherejs.com/zardak/soap
fuction(url,args)
{
soap = Npm.require('soap');
var createClient=Meteor.wrapAsync(soap.createClient,soap);
var client=createClient(url);
var finalFunc=Meteor.wrapAsync(client.youfunction,soap);
var result=finalFunc(args);
return result;
}
I've been working with Meteor and the stripe package to try and make a customer. So First I have my client side code which calls a method on the server so when clicked i have in the client.js:
Meteor.call('usersignup', function (error, result) {
console.log (result);
});
So this calls the Method on the server.js:
var Future = Npm.require('fibers/future');
var stripe = StripeAPI('my key'); // secret stripe API key
Meteor.methods({
usersignup: function(cusEmail){
var fut = new Future();
stripe.customers.create(
{ email: cusEmail },
function(err, customer) {
if (err) {
console.log(err);
fut.ret;
}
fut.ret(customer);
}
);
return fut.wait();
},
userfail: function(cusid){
var fut = new Future();
stripe.customers.retrieve(cusid, function(err, result) {
if(err){
console.log(err);
fut.ret;
}
fut.ret(err, result);
});
return fut.wait();
}
});
Now this works and creates a customer when I log onto the stripe.com dashboard but I'm trying to get the response returned to the client well at least the customer id for now and print it in the console. This is where I can't seem to get it to work. It'll log undefined when I do console.log(result). Any ideas?
EDIT: So I put the fiber and the stripe key as global variables now and don't get an error but the returns don't seem to be returning any values. so on the client side I have:
'click #signupsubmit': function (event) {
console.log("hello");
var whatis = getVal(); // function gets value of forms and returns object
var testid;
var cusid = Meteor.call('usersignup', whatis.email, function (error, result) {
if (error) {
console.log(err.message);
return;
}
console.log(result);
console.log("meteor call");
testid = result;
return (result);
});
console.log("outside call");
console.log(testid);
console.log(cusid);
},
});
So i've been running some console.log tests and it seems it executes the meteor.call and keeps going down the line. Console.log of both testid and cusid return undefined but a couple seconds later I receive the console.log of result and the string "meteor call" from inside the meteor.call. Is there a way to wait for the meteor call to finish then run the rest of what is in my click function? so console output will go like:
"hello"
"outside call"
test id undefined
cusid undefined
"meteor call"
"result"
Keep in mind that the stripe API doesn't use Fibers. You need to put it in manually. The callback doesn't reach the client because by then it would have already got a response (its async)
You can use something like this to wait for a result from the stripe callback before a result is returned to the client:
var stripe = StripeAPI('mykeygoeshere'); // secret stripe API key
var Future = Npm.require('fibers/future');
var fut = new Future();
stripe.customers.create(
{ email: 'hello#example.org' },
function(err, customer) {
if (err) {
console.log(err.message);
fut.ret;
}
fut.ret("customer id", customer.id);
}
);
return fut.wait();
Here a Future is used and it waits for a result to be received from the stripe callback before a result is returned to the client.
More info can be found on Fibers/Futures & Synchronous Callbacks incuding how to go about them & when to use them:
Meteor: Calling an asynchronous function inside a Meteor.method and returning the result
https://github.com/laverdet/node-fibers
https://gist.github.com/possibilities/3443021
Here's something simpler. Meteor now has Meteor.wrapAsync() for this kind of situation:
var stripe = StripeAPI("key");
Meteor.methods({
yourMethod: function(callArg) {
var charge = Meteor.wrapAsync(stripe.charges.create, stripe.charges);
charge({
amount: amount,
currency: "usd",
//I passed the stripe token in callArg
card: callArg.stripeToken,
}, function(err, charge) {
if (err && err.type === 'StripeCardError') {
// The card has been declined
throw new Meteor.Error("stripe-charge-error", err.message);
}
//Insert your 'on success' code here
});
}
});
I found this post really helpful:
Meteor: Proper use of Meteor.wrapAsync on server