libphonejs - how to use it? - javascript

I've got the following attempt to send an SMS
var number = '**********'
sendText: function(phone, callback) {
// maybe needs a .then() ?
var formattedPhone = Phone.format(Phone.parse(phone, 'US'), 'International_plaintext')
var messageBody = 'test'
client.sms.messages.create({
to: formattedPhone,
from: number,
body: messageBody
})
}, function(error, message) {
if (error) {
console.log("SMS ERROR sending to: " + formattedPhone)
callback(error)
} else {
console.log("SMS sent to: " + formattedPhone)
callback(null, message)
}
}
It doesn't print an error or a success string to console - is it the Phone.format(Phone.parse()) call that's causing it by blocking the thread or something?

You have syntax error. The callback function for error message is outside the braces.
https://github.com/TwilioDevEd/api-snippets/blob/master/rest/messages/send-message/example-1.2.x.js
sendText: function(phone, callback) {
// maybe needs a .then() ?
var formattedPhone = Phone.format(Phone.parse(phone, 'US'), 'International_plaintext')
var messageBody = 'test';
client.sms.messages.create({
to: formattedPhone,
from: number,
body: messageBody
/*})*/ // remove this should be deleted
}, function(error, message) {
if (error) {
console.log("SMS ERROR sending to: " + formattedPhone)
callback(error)
} else {
console.log("SMS sent to: " + formattedPhone)
callback(null, message)
}
});
}

Related

Callback to Async/await

I have been trying to convert my existing Node JS code from function callback to Async Await, because a new SDK came out and callbacks are deprecated. These are the related codes. The code is communicating and publishing to a mqtt broker.
First here I call the ToggleX method
super.controlToggleX(channel, value, (err, res) => {
if (err) {
this.log(`Toggle Response: err: ${err}`);
}
this.log(`Toggle Response: res: ${JSON.stringify(res)}`);
});
After that in the controlToggleX method I set the payload for the message and make the publlish to the broker.
controlToggleX(channel, onoff, callback) {
const payload = { togglex: { channel, onoff: onoff ? 1 : 0 } };
return this.publishMessage('SET', 'Appliance.Control.ToggleX', payload, callback);
}
In the publishMessage I compile the message to the broker and publish it. After publishing I waiting for the response and to keep track of the ongoing messages I create the waitingMessageIds array.
publishMessage(method, namespace, payload, callback) {
this.clientResponseTopic = `/app/${this.userId}-${appId}/subscribe`;
const messageId = crypto.createHash('md5').update(generateRandomString(16)).digest('hex');
const timestamp = Math.round(new Date().getTime() / 1000); // int(round(time.time()))
const signature = crypto.createHash('md5').update(messageId + this.key + timestamp).digest('hex');
const data = {
header: {
from: this.clientResponseTopic,
messageId,
method,
namespace,
payloadVersion: 1,
sign: signature,
timestamp,
},
payload,
};
this.client.publish(`/appliance/${this.uuid}/subscribe`, JSON.stringify(data));
if (callback) {
this.waitingMessageIds[messageId] = {};
this.waitingMessageIds[messageId].callback = callback;
this.waitingMessageIds[messageId].timeout = setTimeout(() => {
// this.log('TIMEOUT');
if (this.waitingMessageIds[messageId].callback) {
this.waitingMessageIds[messageId].callback(new Error('Timeout'));
}
delete this.waitingMessageIds[messageId];
}, 20000);
}
this.emit('rawSendData', data);
return messageId;
}
When a new message comes from the broker I check the waitingMessageIds array, the messageId is in the array? If yes I delete the Timer and process the message with the callback coming from the publishing.
this.client.on('message', (topic, message) => {
if (!message) return;
// message is Buffer
try {
message = JSON.parse(message.toString());
} catch (err) {
this.emit('error', `JSON parse error: ${err}`);
return;
}
if (message.header.from && !message.header.from.includes(this.uuid)) return;
if (this.waitingMessageIds[message.header.messageId]) {
if (this.waitingMessageIds[message.header.messageId].timeout) {
clearTimeout(this.waitingMessageIds[message.header.messageId].timeout);
}
this.waitingMessageIds[message.header.messageId].callback(null, message.payload || message);
delete this.waitingMessageIds[message.header.messageId];
} else if (message.header.method === 'PUSH') {
const namespace = message.header ? message.header.namespace : '';
this.log('Found message');
this.emit('data', namespace, message.payload || message);
}
this.emit('rawData', message);
});
mqtt package is working with callback, but the async-mqtt is returning Promise so it is going to be good for me.
I was successfull to publish with it, and after that point I put the messageId to the array and start a timer, but when the reply came i was not been able to proocess the waitingMessageIds and return to the original point (super.controlToggleX).
Could somebody please help me. Thank
Edit:
I tried to rewrite PublishMessage with async-mqtts and it looks like this:
async publishMessage(method, namespace, payload) {
.
.
.
try {
await this.client.publish(`/appliance/${this.uuid}/subscribe`, JSON.stringify(data));
} catch (err) {
return new Error(err);
}
this.waitingMessageIds[messageId] = {};
// this.waitingMessageIds[messageId].callback = callback;
this.waitingMessageIds[messageId].timeout = setTimeout(() => {
// this.log('TIMEOUT');
if (this.waitingMessageIds[messageId].callback) {
this.waitingMessageIds[messageId].callback(new Error('Timeout'));
}
delete this.waitingMessageIds[messageId];
}, 20000);
this.emit('rawSendData', data);
return messageId;
}
Because with the await publish waits for the response I do not need check if it is a callback, i just put the messageId into the waitingmessageIds array.
When I process the incoming message in this.client.on('message' I don not know how to change this -> this.waitingMessageIds[message.header.messageId].callback(null, message.payload || message);

HTTP request callback not firing

I am making a skill for the Amazon Echo. In my handlers, I have an intent (SelectGardenIntent) that obtains the user_id (needed for following HTTP requests) from the access token successfully, as well as a variable called gardenNumber which is a slot value. To complete the request, I need two other values, the garden_id and the dev_id. I use this gardenNumber and pass it into a function called getGardenId, which will assign the one of the data from the HTTP request to the variable garden_id I have defined in index.js. There are no issues with user_id and gardenNumber. When the function is run, there are no errors from the request, but the callback function with the response is also not executed. The user_id, "about to enter request", and "req done" are correctly logged when tested, but the other log statements in the callback function are not since it is not run. The result is that garden_id is undefined. dev_id is obtained in another method that depends on this garden_id, so dev_id is also undefined. Please help me on this issue. I have pasted the relevant code below.
...
var user_id, garden_id, dev_id;
...
function getGardenId (gardenNumber) {
console.log(user_id);
var path = '/api/rest/client/getgardeninfo?&userid=' + user_id;
var options = {
hostname: server_ip,
port: 80,
path: path,
method: 'GET'
}
console.log("about to enter request");
var req = http.request(options, (res) => {
console.log('entered request');
if (res.statusCode === 200) {
console.log('successful request');
res.setEncoding('utf8');
var body = "";
res.on('data', (chunk) => {
console.log('adding data');
body += chunk.toString();
});
res.on('end', () => {
var obj = JSON.parse(body);
console.log('successfully parsed');
if (obj.error === 200) {
console.log('##gardenid successfully obtained');
garden_id = obj.data[gardenNumber - 1].id;
} else {
console.log("parsing error");
}
});
} else {
console.log("failed request");
}
}); } catch(e) {
console.log("ERROR");
}
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
req.on('finish', () => {
console.log('ended');
})
req.end();
console.log("req done");
}
...
var handlers = {
...
'SelectGardenIntent': function () {
//var filledSlots = delegateSlotCollection.call(this);
var gardenNumber = this.event.request.intent.slots.Garden.value;
user_id = this.event.session.user.accessToken;
getGardenId(gardenNumber);
getDevId(garden_id);
this.emit(':tell', `OK, garden ${gardenNumber} selected, user id is ${user_id}, garden id is ${garden_id}, device id is ${dev_id}`);
}
...
}
You'd better use npm request to make calls.
request.get({
url: 'http://' + server_ip + '/api/rest/client/getgardeninfo?&userid=' + user_id
}, function (err, res, body) {
console.log(body);
})

Socket.IO - Callback to user who emited only

I am making a chat application which requires users to log in, I have so far managed to get the login system working by using UserApp.io, but I cant seem to find a way which would send a "Callback" back to the user who has emited the information to the server.
So for index.html, when a login form is submitted, it would gather the values of the two fields and emit the data to the backend.
$('form#login').submit(function() {
var data = {};
data.email = $("#login_email").val();
data.password = $("#login_password").val();
socket.emit('user login', data);
});
In the index.js file, it receives the details and checks using the UserApp API that the user is valid and all the details are correct. It also retrieves information like the first and last name.
socket.on('user login', function (user) {
logger.info('Receiving login info for "' + user.email + '"...');
UserApp.User.login({"login": user.email, "password": user.password}, function (error, result) {
if (error) {
logger.error('Login failed: ' + error.message);
} else {
var userToken = result.token;
var userID = result.user_id;
console.log("User has logged in.");
UserApp.User.get({
"user_id": userID
}, function (error, result) {
if (error) {
logger.error(error.message);
} else {
logger.info(result[0]['first_name'] + " " + result[0]['last_name'] + " Has logged in!")
}
});
}
});
});
So here is my issue. I cant seem to find a way of giving a callback to index.html so it can show errors like "Incorrect username".
So is there a way of giving a callback to one person, more specificly, the person who submitted the login form?
Any help would be appreciated.
Thanks.
socket.io has acknowledgement callbacks, here are the docs
http://socket.io/docs/#sending-and-getting-data-(acknowledgements)
Add a callback function as the third argument when emitting
$('form#login').submit(function() {
var data = {};
data.email = $("#login_email").val();
data.password = $("#login_password").val();
socket.emit('user login', data, function (result) {
console.log(result);
});
});
and then the callback function server side can have an additional parameter which is the callback you defined when emitting
socket.on('user login', function (user, callback) {
logger.info('Receiving login info for "' + user.email + '"...');
UserApp.User.login({"login": user.email, "password": user.password}, function (error, result) {
if (error) {
logger.error('Login failed: ' + error.message);
} else {
var userToken = result.token;
var userID = result.user_id;
console.log("User has logged in.");
UserApp.User.get({
"user_id": userID
}, function (error, result) {
if (error) {
logger.error(error.message);
} else {
logger.info(result[0]['first_name'] + " " + result[0]['last_name'] + " Has logged in!")
return callback('your results');
}
});
}
});
});

Can't set headers after they are sent error. I am not calling render()/json() twice

I have trying to return a response to the client after an entry has been made to the database. I have written the following code to achieve the required result, however I am getting
Error: Can't set headers after they are sent.
I am not calling response.json() or response.render() twice anywhere for this response. So why is this error occuring?
router.post('/yolo', jsonParser, function(req, res, next) {
response = res;
shortUrl = shortenTheUrl(req.body.textBoxValue);
var insertDataInTableQuery = "INSERT INTO `WinGoku`.`ShortenedUrlsTable` (`OriginalUrl`, `ShortUrl`) VALUES('"+req.body.textBoxValue+ "', '"+ shortUrl +"')";
runSQLQuery(insertDataInTableQuery, sendResponseToClient);
});
function runSQLQuery(query, callbackFunction) {
connection.query(query, function(error) {
if(error) {
console.log(query);
console.log("QueryError: "+ error);
if(callbackFunction != undefined)
callbackFunction({type: "alert", errorMessage: error});
}
if(callbackFunction != undefined)
callbackFunction({type: "alert", errorMessage: "successful"});
});
}
function sendResponseToClient(queryExecutionResult) {
console.log("1: "+ queryExecutionResult["type"] + " 2: "+ queryExecutionResult["errorMessage"]);
response.json({shortenedUrl: shortUrl, type: queryExecutionResult["type"], message: queryExecutionResult["errorMessage"]});
^
error here. Can't set headers after they are sent
}
You might be calling response.json() twice, if the query fails and instead of returning from the error clause, it executes query successful clause as well. So you must put a return statment at the end of error clause. This should fix the problem.
function runSQLQuery(query, callbackFunction) {
connection.query(query, function(error) {
if(error) {
console.log(query);
console.log("QueryError: "+ error);
if(callbackFunction != undefined)
callbackFunction({type: "alert", errorMessage: error});
return; // this should fix the problem!
}
if(callbackFunction != undefined)
callbackFunction({type: "alert", errorMessage: "successful"});
});
}
you are not ending response so that error is comming.
Try modifying your code like this:
router.post('/yolo', jsonParser, function(req, res, next) {
response = res;
shortUrl = shortenTheUrl(req.body.textBoxValue);
var insertDataInTableQuery = "INSERT INTO `WinGoku`.`ShortenedUrlsTable` (`OriginalUrl`, `ShortUrl`) VALUES('"+req.body.textBoxValue+ "', '"+ shortUrl +"')";
runSQLQuery(insertDataInTableQuery, sendResponseToClient, function(data){
res.end();
});
});

Parse Update Row in Node.js

I'm trying to run the following code:
exports.updateProfile = function(req, res) {
var Profile = Parse.Object.extend("Profile");
var query = new Parse.Query(Profile);
query.equalTo("username", req.body.username);
query.first({
success: function(Profile) {
Profile.save(null, {
success: function(profile) {
profile.set(req.body, { //It breaks here...
success: function(object) {
res.send({"error":"none"});
},
error: function (object, error) {
res.send({"error":"Error: " + error.code + " " + error.message});
}
});
},
error: function (object, error) {
res.send({"error":"Error: " + error.code + " " + error.message});
}
});
},
error: function (object, error) {
res.send({"error":"Error: " + error.code + " " + error.message});
}
});
}
However, neither the success nor error methods are called at the "It breaks here" line. Any ideas or better ways to update Parse rows using Node.js? Thanks.
exports.updateProfile = function(req, res) {
var Profile = Parse.Object.extend("Profile");
var query = new Parse.Query(Profile);
query.equalTo("username", req.body.username);
query.first().then(function(Profile){
Profile.set("columnName", value);//value might be you are getting from req.body
Profile.save().then(function(saved){
res.send({"error":"none"});
}, function(error){
res.send(error);
});
}, function(error){
res.send(error);
});
}
This might be the thing you are looking for. Try this approach hope it will help. You were saving an object that is not yet modified, That could be the reason why it is not coming to the call back method. Refactored the code to remove the invalid save call.

Categories