Arquivos
AjaxIM/server/middleware/im/user.js
T
2014-10-09 14:26:31 -07:00

159 linhas
4.1 KiB
JavaScript

var events = require('events'),
packages = require('../../libs/packages'),
o_ = require('../../libs/utils');
var User = module.exports = function(store, data, friends) {
this.store = store;
this.connection = null;
this.listeners = [];
this.message_queue = [];
this._data = data;
this.friends = friends;
this.events = new events.EventEmitter();
this._status = packages.STATUSES[0];
this._status_message = '';
this.interval = setInterval(o_.bind(this._expireConns, this), 500);
};
User.prototype.close = function() {
clearInterval(this.interval);
var conn,
noop = JSON.stringify({type: 'noop'}),
noop_headers = {
'Content-Type': 'application/json',
'Content-Length': noop.length
};
for(var i = this.listeners.length-1; i >= 0; i--) {
conn = this.listeners[i].connection;
this.listeners[i].writeHead(200, noop_headers);
this.listeners[i].end(noop);
}
};
User.prototype.receivedUpdate = function(event) {
event = o_.extend({}, event);
event.to = this.data('username');
if(this.friends.indexOf(event.from))
this.send(event);
};
User.prototype._friends = function(friends) {
this.friends = friends;
this.send({
type: 'hello',
username: this.data('username'),
friends: friends
});
};
User.prototype._expireConns = function() {
var conn,
noop = JSON.stringify({type: 'noop'}),
noop_headers = {
'Content-Type': 'application/json',
'Content-Length': noop.length
};
for(var i = 0; i < this.listeners.length; i++) {
conn = this.listeners[i].connection;
if((Date.now() - conn._idleStart) >= conn._idleTimeout - 2000) {
this.listeners[i].writeHead(200, noop_headers);
this.listeners[i].end(noop);
this.listeners.splice(i, 1);
i--;
}
}
};
User.prototype.listener = function(conn) {
this.listeners.push(conn);
};
User.prototype.send = function(event) {
this._send('listener', event);
};
User.prototype._send = function(type, event, res) {
if (this.socketio) {
var id = event.id;
if (event.id) {
delete event.id;
}
this.socketio.emit('client', event);
if (id) {
event.id = id;
}
} else if(type == 'connection') {
// end a regular connection with a response
res.jsonp(event);
} else {
// end a long-polling connection with an event
if(!this.listeners.length)
return this.message_queue.push(arguments);
var cx = this.listeners.slice(), conn;
this.listeners = [];
while(conn = cx.shift()) {
conn.jsonp(event);
}
}
};
User.prototype.data = function(key, def) {
return this._data[key] || this['_' + key] ||
(typeof this[key] != 'function' && this[key]) ||
def || false;
};
User.prototype.touch = function() {
this.lastAccess = +new Date;
};
User.prototype.message = function(event) {
var self = this;
try {
self.store.find('username', event.to, function(to) {
if(to) {
to.send(event);
event.reply({sent: true});
} else {
event.reply({sent: false, e: 'not online'});
}
});
} catch(e) {
event.reply({sent: false, e: e.description});
}
};
User.prototype.status = function(event) {
if (!event) {
return this._status;
}
this._status = event.status;
this._status_message = event.message;
this.events.emit('status', event.status, event.message);
if (event.reply) {
event.reply({sent: true});
}
};
User.prototype.signOff = function(event) {
event.status = 'offline';
this.store.events.emit('update', event);
event.reply({sent: true});
};
User.prototype.dispatch = function(event) {
if (event.type == 'message') {
this.message(event);
} else if (event.type == 'status') {
this.status(event);
} else if (event.type == 'signoff') {
this.signOff(event);
} else {
event.reply({sent: false, e: 'invalid event type'});
}
};