Twilio Programmable Chat REST API response events - node.js

twilioClient.chat.services(service_SID)
.channels
.each(channels => console.log(channels.sid));
From the above code, how can I check if the request is Success or not.
What I tried is :
twilioClient.chat.services(service_SID)
.channels
.each(channels => console.log(channels.sid))
.then(function (err, docs) {
if (err) {
//console.log('error ' + err);
return res.status(500).send('Problem in retrieving channels');
}
res.status(200).json({
message: 'Channels retrieved sucessfully',
docs: docs
});
})
I need something like this to know the response. Did I need to promise?. I dont know about promise yet. Can someone pls provide an example or tutorial.

Twilio developer evangelist here.
When using the each function to map over the remote resource, it's not using a Promise. each expects to work. However, you can provide a function to each that can be called once the request is complete or if there is an error. You can pass that function as the option done in the second argument. Here is how you would do that:
twilioClient.chat.services(service_SID)
.channels
.each((channel => console.log(channel.sid)), { done: error => {
if (error) {
console.error("There was an error loading the channels.", error);
} else {
console.log("All the channels were successfully loaded.")
}
});
If you are looking to load the channels in one go, then each might not be the right function for you. You can also use list which returns the list of channels rather than a channel at a time. For example:
twilioClient.chat.services(service_SID)
.channels
.list({ limit: 50 }, (error, channels) => {
if (error) {
console.error("There was an error loading the channels.", error);
} else {
console.log("Here are your channels: ", channels);
}
});
Let me know if that helps at all.

Related

how to send fetched data node js

Hello i have a request which fetch some json data from third party API:
request({
url: 'https://api.steampowered.com/IEconService/GetTradeOffers/v1/?key=MYAPIKEY&get_sent_offers=1&active_only=1&format=json',
json: true
}, (err, responser, body, undefined) => {
tradeItems = JSON.stringify(body.response['trade_offers_sent'][0].items_to_give);
});
How can i send tradeItems fetched data to offer.addTheirItems value?
client.on('webSession', function(sessionID, cookies) {
manager.setCookies(cookies, function(err) {
if (err) {
console.log(err);
process.exit(1);
return;
}
let offer = manager.createOffer("https://steamcommunity.com/tradeoffer/new/?partner=123456789&token=1234");
offer.addTheirItems();
offer.setMessage("");
offer.send(function(err, status) {
if (err) {
console.log(err);
return;
}
First, that's are javascript's async issue.
The solution is in many ways.
change the request function to async function. and make tradeItems variable to outside from request function.
I recommend request-promise module
move below codes to in upper code's callback function.
This is a simple answer because your sample code is separated into two parts.

Keep variable between promises in a function?

On firebase function I need to get data from Paypal and do 4 things :
1. returns an empty HTTP 200 to them.
2. send the complete message back to PayPal using `HTTPS POST`.
3. get back "VERIFIED" message from Paypal.
4. *** write something to my Firebase database only here.
What I do now works but i am having a problem with (4).
exports.contentServer = functions.https.onRequest((request, response) => {
....
let options = {
method: 'POST',
uri: "https://ipnpb.sandbox.paypal.com/cgi-bin/webscr",
body: verificationBody
};
// ** say 200 to paypal
response.status(200).end();
// ** send POST to paypal back using npm request-promise
return rp(options).then(body => {
if (body === "VERIFIED") {
//*** problem is here!
return admin.firestore().collection('Users').add({request.body}).then(writeResult => {return console.log("Request completed");});
}
return console.log("Request completed");
})
.catch(error => {
return console.log(error);
})
As you can see when I get final VERIFIED from Paypal I try to write to the db with admin.firestore().collection('Users')..
I get a warning on compile :
Avoid nesting promises
for the write line.
How and where should I put this write at that stage of the promise ?
I understand that this HTTPS Cloud Function is called from Paypal.
By doing response.status(200).end(); at the beginning of your HTTP Cloud Function you are terminating it, as explained in the doc:
Important: Make sure that all HTTP functions terminate properly. By
terminating functions correctly, you can avoid excessive charges from
functions that run for too long. Terminate HTTP functions with
res.redirect(), res.send(), or res.end().
This means that in most cases the rest of the code will not be executed at all or the function will be terminated in the middle of the asynchronous work (i.e. the rp() or the add() methods)
You should send the response to the caller only when all the asynchronous work is finished. The following should work:
exports.contentServer = functions.https.onRequest((request, response) => {
let options = {
method: 'POST',
uri: "https://ipnpb.sandbox.paypal.com/cgi-bin/webscr",
body: verificationBody
};
// ** send POST to paypal back using npm request-promise
return rp(options)
.then(body => {
if (body === "VERIFIED") {
//*** problem is here!
return admin.firestore().collection('Users').add({ body: request.body });
} else {
console.log("Body is not verified");
throw new Error("Body is not verified");
}
})
.then(docReference => {
console.log("Request completed");
response.send({ result: 'ok' }); //Or any other object, or empty
})
.catch(error => {
console.log(error);
response.status(500).send(error);
});
});
I would suggest you watch the official Video Series on Cloud Functions from Doug Stevenson (https://firebase.google.com/docs/functions/video-series/) and in particular the first video on Promises titled "Learn JavaScript Promises (Pt.1) with HTTP Triggers in Cloud Functions".

need to res.json() to two separate endpoints, throws headers error (node/express)

I'm having an issue sending the same json object to two separate endpoints. I need to send one copy to a database, and the other copy back to the client. I'm getting can't set headers after they are sent. Which I have gathered is an error saying that res.json() is called once, and can not be called a second time because the headers have been "baked in". I'm pretty newb to development, any suggestions or explanation would be very helpful.
Note: the whole code executes successfully, then crashes the server with the error message above.
paypal.payment.execute(paymentId, execute_payment_json, function (error, payment) {
if (error) {
console.log(error.response);
throw error;
} else {
console.log("Get Payment Response");
console.log(JSON.stringify(payment));
const userData = {paymentID : payment.id};
UserData.addUserData(userData, function(err, userData) {
if (err) {
throw err;
}
res.json(userData);
});
res.json(userData)
}
});
})
You are right when you write that you can't call res.json() a second time. You can only send one response per request. res.json() sends a response, so you can only call it once (you have probably seen this question already).
You don't have to send a response to the database. Only the client that sent the request should receive a response. Calling res.json() will not send anything to the database. In order to store the userData object in the database, you have to call the function that does that. In your case, I assume you are doing that with UserData.addUserData(). This is where the storing happens, not by sending a response to it.
The function you send in as an argument to UserData.addUserData() is most likely a callback that is called AFTER storing the userData object is finished. Basically, UserData.addUserData() will do all the stuff it's supposed to do, and then continue with the function you have written after that. In there you can call res.json(). You can remove the last call to res.json(). It's not needed as you will call it in the callback function after storing in the database is finished.
paypal.payment.execute(paymentId, execute_payment_json, function (error, payment) {
if (error) {
console.log(error.response);
throw error;
} else {
console.log("Get Payment Response");
console.log(JSON.stringify(payment));
const userData = {paymentID : payment.id};
UserData.addUserData(userData, function(err, userData) {
if (err) {
throw err;
}
res.json(userData);
});
}
});
})

Capture a JSON GET response in a variable?

I'm using request-promise to get data from an endpoint that I have.
Is it posible to 'capture' a json response in a variable to use it anywhere?
try{
var gamer = '';//variable to capture json data
var options = {
uri: 'http://localhost:4000/gamers/'+gamer._id+'/find',
json: true
};
RequestPromise(options)
.then(function (data) {
gamer = data;//capturing response
})
.catch(function (err) {
console.log("Error saving player data !");
});
.... do something with gamer ....
}catch(err){
res.status(500).send({
message: err.message || 'An error occurred generating player teams !'
});
}
The reason that I need to do this is because actually I don't have access to the database to get that information, so my only option is to consume an API to get information through collections id's.
Your doing a lot of things correctly already. The issue is your gamer variable will get assigned the value you expect first when your promise resolves. There are many ways to skin this cat, but to get you started try performing whatever you want to perform on the gamer variable in .then(), like this:
try{
var gamer = '';//variable to capture json data
var options = {
uri: 'http://localhost:4000/gamers/'+gamer._id+'/find',
json: true
};
RequestPromise(options)
.then(function (data) {
gamer = data;//capturing response
// here is the rigth place perofrm operations on the answer, as this part of the code gets executed after promise reolves. BTW. Then you don't need variable gamer.
})
.catch(function (err) {
console.log("Error saving player data !");
});
// here is not the right place to do something with gamer as this is executed as soon as promise is initialized, not as it resolves. This means your variable will have initial value here
}catch(err){
res.status(500).send({
message: err.message || 'An error occurred generating player teams !'
});
}

Can you publish multiple messages to an SNS topic using an AWS Lambda function backed by node.js 8.10?

There is a related question regarding how to publish s single message: Can you publish a message to an SNS topic using an AWS Lambda function backed by node.js?
However, my question is related to publish more than one message.
I am using node 8.10 and my handler is asynchronous.
You can use the Promise.all() feature to encapsulate multiple calls to sns.publish.
Create a one-notification-publish function that returns Promise:
.
function onePublishPromise(notificationParams){
return new Promise((resolve, reject) => {
sns.publish(notificationParams, function(err, data) {
if (err) {
console.error("Unable to send notification message. Error JSON:", JSON.stringify(err, null, 2));
reject(err);
} else {
console.log("Results from sending notification message: ", JSON.stringify(data, null, 2));
resolve(null);
}
});
});
}
Create and send notifications in parallel:
// Create notifications params
const notifications = [
{
Subject: 'A new notification',
Message: 'Some message',
TopicArn: 'arn:aws:sns:us-west-1:000000000:SomeTopic'
}
// , ...
];
// Send all notifications
const notificationsDelivery = notifications.map(onePublishPromise);
// Wait for delivery results
Promise.all(notificationsDelivery).then(callback).catch(callback);
callback will be called after all messages published (successfully or not)
The related question uses context.done, which would end the lambda before making a second call. Using
sns.publish(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
you can make more calls, e.g.
sns.publish(params2, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
Whether you want to use async.waterfall, nest the calls or let them go asynchronously is up to you.

Resources