Update Arrays in node.js on disconnection in socket.io - node.js

I am trying to create a new socket.io real time analytic connection. I have two types of users. Normal users and their drivers.
Here is the code for authorization
io.configure(function()
{
io.set('authorization', function(handshake, callback)
{
var userId = handshakeData.query.userId;
var type = handshakeData.query.type;
var accessKey = handshakeData.query.accessKey;
var query = "";
if(type = '')
query = 'SELECT * FROM users WHERE id = ' + userId + ' AND accessKey = ' + accessKey;
else
query = 'SELECT * FROM drivers WHERE id = ' + userId + ' AND accessKey = ' + accessKey;
db.query(query)
.on('result', function(data)
{
if(data)
{
if(type == '')
{
var index = users.indexOf(userId);
if (index != -1)
{
users.push(userId)
}
}
else
{
var index = drivers.indexOf(userId);
if (index != -1)
{
drivers.push(userId)
}
}
}
else
{
socket.emit('failedAuthentication', "Unable to authenticate");
}
})
.on('end', function(){
socket.emit('failedAuthentication', "Unable to authenticate");
})
});
});
For disconnection i have this
socket.on('disconnect', function()
{
});
i want to remove the very userId i added on disconnect. How would i do that. can i append anything to socket or what should i do?

If you're just trying to remove the userId from your users and drivers arrays, you can do this:
socket.on('disconnect', function() {
// remove userId from users and drivers arrays
var index;
index = users.indexOf(userId);
if (index !== -1) {
users.splice(index, 1);
}
index = drivers.indexOf(userId);
if (index !== -1) {
drivers.splice(index, 1);
}
});
Or, you can DRY it up a bit:
function removeItem(array, item) {
var index = array.indexOf(item);
if (index !== -1) {
array.splice(index, 1);
}
}
socket.on('disconnect', function() {
removeItem(users, userId);
removeItem(drivers, userId);
});
This code assumes that you put this in the same closure where the userId variable is present. If you are not doing that, then you will probably need to put the userId as a property on the socket object so that it is accessible when you need it. You don't show the larger context of how your code is organized or where this event handler is located so we can't make a more specific recommendation without seeing that.

Related

node.js how to get data from redis database inside in middleware

I'm doing middleware module that will extract data from redis and put to req.my_session.[here]
This is function that call inside app.use();
function parse_cookies(req){
if(req.headers.cookie != null){
var result = req.headers.cookie.match(new RegExp('m:[^=]*=[^; ]*', 'ig'));
if(result != null){
for(var i = 0; i < result.length; i++){
var result1 = result[i].split('=');
req.my_session[result1[0].substr(2)] = result1[1];
// get from redis value
client.get('sess:'+result1[1], function(err, reply) {
// reply is null when the key is missing
console.log(reply);
let li = i;
req.my_session[result1[0].substr(2)] = reply;
console.log('li = ' + li);
console.log('result1.lenght= ' + result.length);
if(i == result.length){
console.log('call the next');
}
});
}
}
}
} // parse_cookies
in console i outputs always 3, how can I get all data from database using redis.get and on last data call next() function for get out from my function?
problem it's get data from database in my middleware, I can't because redis has callback function
client.get("missingkey", function(err, reply) {
// reply is null when the key is missing
console.log(reply);
});
I think the issue is becuase of async in loop you can try the following
function parse_cookies(req){
if(req.headers.cookie != null){
var result = req.headers.cookie.match(new RegExp('m:[^=]*=[^; ]*', 'ig'));
if(result != null){
var promises = [];
for(var i = 0; i < result.length; i++){
var result1 = result[i].split('=');
promises.push(getFromRd(req, result1));
}
return Promise.all(promises)
.then(() => {
return next()
})
.catch((e) => {
return next({error: e})
})
}
}
} // parse_cookies
function getFromRd(req, result1) {
req.my_session[result1[0].substr(2)] = result1[1];
// get from redis value
return client.get('sess:'+result1[1], function(err, reply) {
if (err) {
throw Error(' failed to find ' + 'sess:' + result1[1])
}
// reply is null when the key is missing
console.log(reply);
let li = i;
req.my_session[result1[0].substr(2)] = reply;
console.log('li = ' + li);
console.log('result1.lenght= ' + result.length);
return {success:true}
});
}

Node reply to tweet does not actually reply

I'm using the Twit Node library to reply to tweets in a stream and while it's working perfectly the tweeted reply does not show up as a reply on the timeline, instead, it appears as a standalone tweet, not linked to a prior conversation.
Here's my code:
function tweetEvent(eventMsg) {
var replyto = eventMsg.in_reply_to_screen_name;
var text = eventMsg.text;
var from = eventMsg.user.screen_name;
console.log(replyto + ' ' + from);
if( (text.indexOf('myhandle') >= 0) || (from != 'myhandle')) {
var reply = replies[Math.floor(Math.random() * replies.length)];
var newtweet = '#' + from + ' ' + reply;
tweetIt(newtweet);
}
}
function tweetIt(txt) {
var tweet = {
status: txt
}
T.post('statuses/update', tweet, tweeted);
function tweeted(err, data, response) {
if (err) {
console.log("Something went wrong!");
} else {
console.log("It worked!");
}
}
}
In order for the reply to show up in the timeline using the Twitter API, you need the following:
// the status update or tweet ID in which we will reply
var nameID = eventMsg.id_str;
Also needed is the parameter in_reply_to_status_id in your tweet status. See the updates to your code below and it should now preserve the conversation:
function tweetEvent(eventMsg) {
var replyto = eventMsg.in_reply_to_screen_name;
var text = eventMsg.text;
var from = eventMsg.user.screen_name;
// the status update or tweet ID in which we will reply
var nameID = eventMsg.id_str;
console.log(replyto + ' ' + from);
if( (text.indexOf('myhandle') >= 0) || (from != 'myhandle')) {
var reply = replies[Math.floor(Math.random() * replies.length)];
var newtweet = '#' + from + ' ' + reply;
tweetIt(newtweet);
}
function tweetIt(txt) {
var tweet = {
status: txt,
in_reply_to_status_id: nameID
}
}
T.post('statuses/update', tweet, tweeted);
function tweeted(err, data, response) {
if (err) {
console.log("Something went wrong!");
} else {
console.log("It worked!");
}
}
}

Underscore _.contains method always failed inside mongoose promise query

Hi im using mongoose query inside socket.io event, so far so good. I want to check if a user is a member to a private room then fetch messages. So i use underscore method _.contains() but is always return false. I don't know what wrong with the code cuz logging both list and checked item it should return true
socket.on('add user', function (data) {
var username = data.username;
var userId = data.userId;
var currentroom = data.room ? data.room : '559c02cfd2ad52cc276b7491';
// we store the username in the socket session for this client
socket.username = username;
socket.userid = userId;
// add the client's username to the global list
usernames[username] = username;
++numUsers;
socket.emit('login', {
numUsers: numUsers
});
var room = new roomModel();
return room.getRoomParticipants(currentroom)
.then(function(res) {
console.log('checking room');
console.log(res);
if (!res) {
throw new Error('Couldn\'t get room participants!');
}
res = res[0];
var participants = res.participants;
return participants;
})
.then(function(participants) {
if (!_.contains(participants, socket.userid)) {
console.log('have failed');
return null;
}
_.each(participants, function(item) {
var user = new userModel();
user.getById(item)
.then(function(res) {
if (res) {
rommates[res._id] = res;
}
})
});
return roommates;
})
.then(function(participants) {
var message = new messageModel();
message.roomMessages(currentroom, msgLimit)
.then(function(res) {
_.each(res, function(item) {
var data = {};
var user = rommates[res._id];
data.username = user.username;
data.message = item.msg;
data.time = item.created_at;
socket.emit('new message', data);
});
});
})
.then(null, function(err) {
logger.debug(err);
});
});
Solved it by replacing
if (!_.contains(participants, socket.userid)) {
return null;
}
with
var participants = _.object(res.participants);
var allowed = _.find(res.participants, function(item) {
return item == socket.userid;
});
if (!allowed) {
throw new Error('User ' + socket.userid + ' is not allowed to room ' + currentroom);
}

Promise to retrieve Timeline

Using Parse.com for few months now, I started to create some Cloud Function To let me create and retrieve some element in a TimeLine
I need to get my information from timeline's class and once I retrieve elements, I have to call getStat to add in the same object Widgets both information from my query and from the results from getStat.
I have tried to use Promise to achieve this, but not sure it was the best way to deal with it. Any suggestions / help ?
Parse.Cloud.define("getTimeline", function(request, response) {
var user = request.params.user;
var limit = request.params.limit;
var page = request.params.page;
if (limit === undefined) limit = 10;
if (page === undefined) page = 0;
var Timeline = Parse.Object.extend("timeline");
var query = new Parse.Query(Timeline);
query.equalTo("user", user);
query.descending('createdAt');
query.limit(limit);
query.skip(page * limit);
var Widgets = {};
query.find().then(function(results) {
var promise = Parse.Promise.as();
_.each(results, function(result) {
var Widget = new Object();
Widget.data = result;
var timeline_id = result.get('timeline_id');
promise = promise.then(function() {
return Parse.Cloud.run('getStats', {
'timeline_id': timeline_id
}).then(function(stat) {
Widget.stat = stat;
Widgets[timeline_id] = Widget;
});
});
});
return promise;
}).then(function() {
response.success(Widgets);
},
function(error) {
response.error("Error: " + error.code + " " + error.message);
});
});

Notifying caller about error from callback in node.js on error from sqlite3 call

In node.js + sqlite3:
What is a good way to notify a caller from a callback about errors and get the caller to try again ? When we get a database locked error - would like to try and run the query again.
TestController.prototype.addDevices = function (number_of_devices, callback_after_all_devices_have_been_added) {
var controller = this;
var db = controller.connectToDb();
for(i = 0; i < number_of_devices; i++) {
db.each("SELECT api_key as ak FROM user_table ORDER BY RANDOM() LIMIT 1", function(err, row) {
//sometimes we get a SQLITE: database locked error
if (err !== null) {
console.log("Error found");
//i-- this will not work - but how do we do it then?
return;
}
console.log("Error: " + err);
//code to process if we get an entry from the user_table ..
});
}
}
This is how I managed to solve this - added a retry counter and moved the problem code to its own function, passing in the epilogue as a callback. It works - but is this a good way?
(other than using promises or the async module?)
TestController.prototype.addDevices = function (number_of_devices, callback_after_all_devices_have_been_added) {
var number_of_users = 0;
var controller = this;
controller.pending_db_writes_for_device = number_of_devices;
for(i = 0; i < number_of_devices; i++) {
var api_key = controller.getRandomAPIKeyFromDB(10,function(access_key) {
var mac_address = controller.generateRandomMAC();
var friendly_name = Faker.random.array_element(["Washing Machine","Television","Dishwasher","Set top box"]);
var description = Faker.Lorem.sentence(5);
controller.registerDeviceWithAPI(mac_address, friendly_name, description, access_key, callback_after_all_devices_have_been_added);
});
}
}
TestController.prototype.getRandomAPIKeyFromDB = function (retry_counter, callback) {
var controller = this;
var db = controller.connectToDb();
console.log("Retry counter: "+ retry_counter);
db.each("SELECT api_key as ak FROM user_table ORDER BY RANDOM() LIMIT 1", function(err, row) {
if (err !== null) {
console.log("Error: " + err + "retry count: "+ retry_counter);
console.log("Error found");
if(retry_counter === 0) {
console.log("Bailing out after retry limit reached");
return;
}
controller.getRandomAPIKeyFromDB(--retry_counter,callback);
}
else {
console.log("Successfully got api key: " + row.ak);
callback(row.ak);
}
}
);
}

Resources