Refactor server for flexibility.
Esse commit está contido em:
+1
-1
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Ajax IM</title>
|
||||
<script src="js/jquery-1.11.0.js" type="text/javascript"></script>
|
||||
<script src="js/jquery-1.11.1.js" type="text/javascript"></script>
|
||||
<script src="js/md5.js" type="text/javascript"></script>
|
||||
<script src="js/store.js" type="text/javascript"></script>
|
||||
<script src="js/dateformat.js" type="text/javascript"></script>
|
||||
|
||||
+46
-44
@@ -55,7 +55,7 @@ AjaxIM = function(options, actions) {
|
||||
}, actions);
|
||||
|
||||
if (!store.get('sessionid')) {
|
||||
store.set('sessionid', uid(40));
|
||||
store.set('sessionid', AjaxIM.uid(40));
|
||||
}
|
||||
|
||||
// If Socket.IO is available, create a socket
|
||||
@@ -63,24 +63,26 @@ AjaxIM = function(options, actions) {
|
||||
$.getScript(this.settings.pollServer+'/socket.io/socket.io.js', function(){
|
||||
self.socket = io(self.settings.pollServer);
|
||||
self.socket.on('client', function(event) {
|
||||
event = $.extend(true, {}, event);
|
||||
self.dispatchEvent(event);
|
||||
event = $.extend(true, {}, event);
|
||||
self.dispatchEvent(event);
|
||||
});
|
||||
var event = {type: 'hello', from: store.get('user'), sessionID: store.get('sessionid')};
|
||||
self.sendEvent(event);
|
||||
var event = {type: 'hello', from: store.get('user')};
|
||||
self.sendEvent(event, function() {}, function() {});
|
||||
});
|
||||
|
||||
// We load the theme dynamically based on the passed
|
||||
// settings. If the theme is set to false, we assume
|
||||
// that the user is going to load it himself.
|
||||
this.themeLoaded = false;
|
||||
if(this.settings.theme) {
|
||||
if(typeof document.createStyleSheet == 'function')
|
||||
if (this.settings.theme) {
|
||||
if(typeof document.createStyleSheet == 'function') {
|
||||
document.createStyleSheet(this.settings.theme + '/theme.css');
|
||||
else
|
||||
} else {
|
||||
$('body').append('<link rel="stylesheet" href="' +
|
||||
this.settings.theme + '/theme.css" />');
|
||||
$('<div>').appendTo('body').load(this.settings.theme + '/theme.html #imjs-bar, .imjs-tooltip',
|
||||
}
|
||||
$('<div>').appendTo('body').load(this.settings.theme +
|
||||
'/theme.html #imjs-bar, .imjs-tooltip',
|
||||
function() {
|
||||
self.themeLoaded = true;
|
||||
self.setup();
|
||||
@@ -115,7 +117,6 @@ AjaxIM = function(options, actions) {
|
||||
var obj = $(this);
|
||||
self.send(obj.parents('.imjs-chatbox').data('username'), obj.val());
|
||||
}
|
||||
|
||||
var obj = $(this);
|
||||
obj.val('');
|
||||
obj.height(obj.data('height'));
|
||||
@@ -409,7 +410,7 @@ $.extend(AjaxIM.prototype, {
|
||||
self.request(
|
||||
this.actions.listen,
|
||||
'GET',
|
||||
{},
|
||||
{type: 'hello', from: store.get('user'), sessionid: store.get('sessionid')},
|
||||
function(event) {
|
||||
if($.isArray(event)) {
|
||||
$.each(event, function(key, event) {
|
||||
@@ -471,7 +472,7 @@ $.extend(AjaxIM.prototype, {
|
||||
},
|
||||
|
||||
onMessage: function(event) {
|
||||
this.incoming(event.from, event.body);
|
||||
this.incoming(event.from, event.body);
|
||||
},
|
||||
|
||||
onStatus: function(event) {
|
||||
@@ -969,6 +970,10 @@ $.extend(AjaxIM.prototype, {
|
||||
});
|
||||
},
|
||||
|
||||
signOff: function() {
|
||||
this.status('offline', '');
|
||||
},
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{status(s, message)}}}** ===
|
||||
//
|
||||
// Sets the user's status and status message. It is possible to not
|
||||
@@ -1001,7 +1006,7 @@ $.extend(AjaxIM.prototype, {
|
||||
self.offline = true;
|
||||
$('.imjs-input').attr('disabled', true);
|
||||
|
||||
var event = {type: 'signoff'};
|
||||
var event = {type: 'signoff', message: message};
|
||||
this.sendEvent(event, function(result) {
|
||||
if(result.type == 'success')
|
||||
$(self).trigger('changeStatusSuccessful', [value, null]);
|
||||
@@ -1302,8 +1307,8 @@ $.extend(AjaxIM.prototype, {
|
||||
|
||||
var tab_pos = tab.position();
|
||||
if(tab_pos.top >= $('#imjs-bar').height() ||
|
||||
tab_pos.left < 0 ||
|
||||
tab_pos.right > $(document).width()) {
|
||||
tab_pos.left < 0 ||
|
||||
tab_pos.right > $(document).width()) {
|
||||
$('.imjs-scroll').css('display', '');
|
||||
tab.css('display', 'none');
|
||||
needScrollers = true;
|
||||
@@ -1356,6 +1361,7 @@ $.extend(AjaxIM.prototype, {
|
||||
},
|
||||
|
||||
sendEvent: function(event, successFunc, failureFunc) {
|
||||
event.sessionid = store.get('sessionid');
|
||||
event.id = this.eventId++;
|
||||
var evt = $.extend({}, event);
|
||||
evt['_status'] = {
|
||||
@@ -1402,17 +1408,17 @@ $.extend(AjaxIM.prototype, {
|
||||
},
|
||||
|
||||
dispatchEvent: function(event) {
|
||||
if (event.id && this.unconfirmedEvents[event.id]) {
|
||||
event['_status'] = $.extend({}, this.unconfirmedEvents[event.id]['_status'], event['_status']);
|
||||
delete this.unconfirmedEvents[event.id];
|
||||
if (event['_status']['sent']) {
|
||||
event['_status']['successFunc'](event);
|
||||
} else {
|
||||
event['_status']['failureFunc'](event);
|
||||
}
|
||||
} else {
|
||||
$(this).trigger(event.type, event);
|
||||
}
|
||||
if (event.id && this.unconfirmedEvents[event.id]) {
|
||||
event['_status'] = $.extend({}, this.unconfirmedEvents[event.id]['_status'], event['_status']);
|
||||
delete this.unconfirmedEvents[event.id];
|
||||
if (event['_status']['sent']) {
|
||||
event['_status']['successFunc'](event);
|
||||
} else {
|
||||
event['_status']['failureFunc'](event);
|
||||
}
|
||||
} else {
|
||||
$(this).trigger(event.type, event);
|
||||
}
|
||||
},
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{request(url, data, successFunc, failureFunc)}}}** ===
|
||||
@@ -1437,7 +1443,6 @@ $.extend(AjaxIM.prototype, {
|
||||
|
||||
var jsonp = (url.substring(0, 1) !== '/');
|
||||
var success = false;
|
||||
data['sessionid'] = store.get('sessionid');
|
||||
$.ajax({
|
||||
url: url,
|
||||
data: data,
|
||||
@@ -1465,8 +1470,7 @@ $.extend(AjaxIM.prototype, {
|
||||
};
|
||||
var noopfn = function() {
|
||||
var noopdone = false;
|
||||
var event = {type: 'noop'};
|
||||
event['sessionid'] = store.get('sessionid');
|
||||
var event = {type: 'noop', from: store.get('user'), sessionid: store.get('sessionid')};
|
||||
$.ajax({
|
||||
url: self.actions.noop,
|
||||
data: event,
|
||||
@@ -1548,7 +1552,19 @@ AjaxIM.incoming = function(event) {
|
||||
$(AjaxIM.client).trigger(event.type, event);
|
||||
};
|
||||
|
||||
AjaxIM.eventID = 1;
|
||||
AjaxIM.uid = function(n){
|
||||
var chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', nn='';
|
||||
for(var c=0; c < n; c++){
|
||||
nn += chars.substr(0|Math.random() * chars.length, 1);
|
||||
}
|
||||
return nn;
|
||||
};
|
||||
|
||||
AjaxIM.onObj = function(obj, func) {
|
||||
return function(evt, event) {
|
||||
$.proxy(func, obj)(event);
|
||||
};
|
||||
};
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{l10n}}}** ===
|
||||
//
|
||||
@@ -1584,21 +1600,7 @@ AjaxIM.l10n = {
|
||||
defaultAway: 'I\'m away.'
|
||||
};
|
||||
|
||||
AjaxIM.onObj = function(obj, func) {
|
||||
return function(evt, event) {
|
||||
$.proxy(func, obj)(event);
|
||||
};
|
||||
};
|
||||
|
||||
AjaxIM.debug = true;
|
||||
function _dbg(msg) {
|
||||
if(AjaxIM.debug && window.console) console.log(msg);
|
||||
}
|
||||
|
||||
function uid(n){
|
||||
var chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', nn='';
|
||||
for(var c=0; c < n; c++){
|
||||
nn += chars.substr(0|Math.random() * chars.length, 1);
|
||||
}
|
||||
return nn;
|
||||
}
|
||||
|
||||
externo
+1
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -1,22 +0,0 @@
|
||||
/*!
|
||||
* Ajax IM
|
||||
* Ajax Instant Messeneger
|
||||
* http://ajaxim.com/
|
||||
*
|
||||
* Copyright 2010, Joshua Gross
|
||||
* Licensed under the MIT license.
|
||||
* [License URL]
|
||||
*
|
||||
* Includes:
|
||||
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
||||
* v2.1, Copyright 2002, Paul Johnston
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for more info
|
||||
*
|
||||
* Date Format 1.2.3
|
||||
* http://blog.stevenlevithan.com/archives/date-time-format
|
||||
* Copyright 2009 Steven Levithan
|
||||
* MIT license
|
||||
*/
|
||||
(function($) {
|
||||
externo
-4
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+320
-349
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+4
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -1,2 +0,0 @@
|
||||
|
||||
})(jQuery || $);
|
||||
+63
-64
@@ -2,26 +2,27 @@
|
||||
var express = require('express'),
|
||||
app = express(),
|
||||
http = require('http').Server(app),
|
||||
io = require('socket.io')(http),
|
||||
// io = require('socket.io')(http), // uncomment to enable Socket.IO
|
||||
bodyParser = require('body-parser'),
|
||||
sys = require('sys'),
|
||||
packages = require('./libs/packages'),
|
||||
o_ = require('./libs/utils');
|
||||
|
||||
o_.merge(global, require('./settings'));
|
||||
try { o_.merge(global, require('./settings.local')); } catch(e) {}
|
||||
|
||||
var reapInterval = (typeof io === 'undefined')? 60 * 1000: -1;
|
||||
|
||||
//app.set('env', 'development');
|
||||
app.use(require('method-override')());
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.urlencoded());
|
||||
app.use(bodyParser.urlencoded({extended: true}));
|
||||
var mw = require('./middleware/im')({
|
||||
maxAge: 60 * 1000,
|
||||
reapInterval: 60 * 1000,
|
||||
authentication: require('./libs/authentication/' + AUTH_LIBRARY)
|
||||
maxAge: 60 * 1000,
|
||||
reapInterval: reapInterval,
|
||||
authentication: require('./libs/authentication/' + AUTH_LIBRARY)
|
||||
});
|
||||
app.use(mw.session);
|
||||
var hub = mw.hub;
|
||||
var store = mw.store;
|
||||
|
||||
app.set('root', __dirname);
|
||||
|
||||
@@ -29,29 +30,53 @@ if ('development' == app.get('env')) {
|
||||
app.set('views', __dirname + '/dev/views');
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
app.use(require("morgan")());
|
||||
app.use(require("morgan")('combined'));
|
||||
require('./dev/app')('/dev', app);
|
||||
app.use(express.static(
|
||||
require('path').join(__dirname, '../client')));
|
||||
app.use(require('express-error-handler')({dumpExceptions: true, showStack: true}));
|
||||
}
|
||||
|
||||
io.on('connection', function(socket){
|
||||
socket.on('server', function(event) {
|
||||
if (event.type == 'hello') {
|
||||
event.socketio = socket;
|
||||
hub.get(event, function(err, sess) {
|
||||
sess.touch();
|
||||
store.set(event.sessionID, sess);
|
||||
});
|
||||
} else {
|
||||
hub.find(event.from, function(from) {
|
||||
from.socketio = socket;
|
||||
from.dispatch(hub, event);
|
||||
});
|
||||
}
|
||||
// Socket.IO handlers
|
||||
if (typeof io !== 'undefined') {
|
||||
io.on('connection', function(socket){
|
||||
var username = null;
|
||||
socket.on('server', function(event) {
|
||||
event.reply = function(status) {
|
||||
if (status) {
|
||||
this._status = status;
|
||||
}
|
||||
delete this.reply;
|
||||
socket.emit('client', this);
|
||||
};
|
||||
var unauthenticated = function() {
|
||||
event.reply({sent: false, e: 'unauthenticated'});
|
||||
};
|
||||
store.get(event, function(event, user) {
|
||||
if ((event.type == 'hello') && user) {
|
||||
username = user.data('username');
|
||||
store.set(username, user);
|
||||
event.reply({sent: true});
|
||||
} else if ((event.type != 'hello')) {
|
||||
store.find('username', event.from, function(from) {
|
||||
if (from) {
|
||||
from.dispatch(event);
|
||||
} else {
|
||||
unauthenticated();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
unauthenticated();
|
||||
}
|
||||
}, socket);
|
||||
});
|
||||
socket.on('disconnect', function() {
|
||||
if (username) {
|
||||
store.reap(username);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
http.listen(APP_PORT, APP_HOST, function(){
|
||||
console.log('Ajax IM server started...');
|
||||
@@ -60,50 +85,24 @@ http.listen(APP_PORT, APP_HOST, function(){
|
||||
// Listener endpoint; handled in middleware
|
||||
app.get('/app/listen', function(){});
|
||||
|
||||
app.use('/app/message', function(req, res) {
|
||||
res.find(req.param('to'), function(to) {
|
||||
if(to) {
|
||||
res.message(to, req.event);
|
||||
} else {
|
||||
req.event._status = {sent: false, e: 'not online'};
|
||||
res.jsonp(req.event);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.use('/app/message/typing', function(req, res) {
|
||||
if(~packages.TYPING_STATES.indexOf('typing' + req.param('state'))) {
|
||||
res.find(req.param('to'), function(user) {
|
||||
if(user) {
|
||||
req.event.status = 'typing' + req.param('state');
|
||||
res.message(user, req.event);
|
||||
} else {
|
||||
// Typing updates do not receive confirmations,
|
||||
// as they are not important enough.
|
||||
req.event._status = {sent: false, e: 'invalid user'};
|
||||
res.jsonp(req.event);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
req.event._status = {sent: false, e: 'invalid state'};
|
||||
res.jsonp(req.event);
|
||||
}
|
||||
});
|
||||
|
||||
app.use('/app/status', function(req, res) {
|
||||
if(~packages.STATUSES.indexOf(req.param('status'))) {
|
||||
res.status(req.event);
|
||||
} else {
|
||||
req.event._status = {sent: false, e: 'invalid status'};
|
||||
res.jsonp(req.event);
|
||||
}
|
||||
});
|
||||
|
||||
// HTTP handlers
|
||||
app.use('/app/noop', function(req, res) {
|
||||
req.event._status = {sent: true};
|
||||
res.jsonp(req.event);
|
||||
});
|
||||
|
||||
app.use('/app/signoff', function(req, res) {
|
||||
res.signOff(req.event);
|
||||
app.use('/app/message', function(req, res) {
|
||||
res.message();
|
||||
});
|
||||
|
||||
app.use('/app/message/typing', function(req, res) {
|
||||
res.typing();
|
||||
});
|
||||
|
||||
app.use('/app/status', function(req, res) {
|
||||
res.status();
|
||||
});
|
||||
|
||||
app.use('/app/signoff', function(req, res) {
|
||||
res.signOff();
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ doctype html
|
||||
html(lang="en")
|
||||
head
|
||||
title Ajax IM
|
||||
script(src='/js/jquery-1.11.0.js', type='text/javascript')
|
||||
script(src='/js/jquery-1.11.1.js', type='text/javascript')
|
||||
script(src='/js/md5.js', type='text/javascript')
|
||||
script(src='/js/store.js', type='text/javascript')
|
||||
script(src='/js/dateformat.js', type='text/javascript')
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
var o_ = require('../../utils');
|
||||
var User = require('../../../middleware/im/user');
|
||||
|
||||
exports.authenticate = function(request, callback, hub) {
|
||||
// Verify user based on request.
|
||||
// On failure, redirect user to auth form
|
||||
var username = request.from;
|
||||
if (!username) {
|
||||
username = 'username' + (++hub.uid);
|
||||
exports.authenticate = function(store, event, callback) {
|
||||
// remove authentication from event
|
||||
var sessionid = event.sessionid;
|
||||
delete event.sessionid;
|
||||
|
||||
// find the user
|
||||
var user = event.from? store.sessions[event.from]: undefined;
|
||||
|
||||
// create, validate or reject user
|
||||
if (user) {
|
||||
// found the user so check authentication
|
||||
if (sessionid && (sessionid === user.data('sessionid'))) {
|
||||
event.from = user.data('username');
|
||||
callback(event, user);
|
||||
} else {
|
||||
event._status = {sent: false, e: 'not authenticated'};
|
||||
callback(event);
|
||||
}
|
||||
} else if (event.type == 'hello') {
|
||||
store.find('sessionid', sessionid, function(user) {
|
||||
if (user) {
|
||||
// relogin as same user
|
||||
event.from = user.data('username');
|
||||
callback(event, user);
|
||||
} else {
|
||||
// if no username requested, assign user name
|
||||
if (!event.from) {
|
||||
event.from = 'username' + (++store.uid);
|
||||
}
|
||||
// everybody is your friend!
|
||||
var friends = o_.values(store.sessions).map(function(friend) {
|
||||
return friend.data('username');
|
||||
});
|
||||
// you're even friends with yourself!
|
||||
friends.push(event.from);
|
||||
// create new user
|
||||
user = new User(store, {
|
||||
username: event.from,
|
||||
sessionid: sessionid,
|
||||
displayname: 'John Smith',
|
||||
otherinfo: 'any other relevant key/values'
|
||||
}, friends);
|
||||
callback(event, user);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event._status = {sent: false, e: 'not authenticated'};
|
||||
callback(event);
|
||||
}
|
||||
callback({
|
||||
username: username,
|
||||
displayname: 'John Smith',
|
||||
otherinfo: 'any other relevant key/values'
|
||||
});
|
||||
};
|
||||
|
||||
exports.friends = function(request, data, callback, hub) {
|
||||
// Create a friends list based on given user data
|
||||
callback(o_.values(hub.sessions).map(function(friend) {
|
||||
return friend.data('username');
|
||||
}));
|
||||
};
|
||||
+55
-40
@@ -1,63 +1,80 @@
|
||||
var url = require('url'),
|
||||
Hub = require('./im/hub'),
|
||||
packages = require('../libs/packages'),
|
||||
o_ = require('../libs/utils');
|
||||
|
||||
module.exports = function setupHub(options) {
|
||||
options = options || {};
|
||||
|
||||
store = new Hub(options);
|
||||
var store = new Hub(options);
|
||||
|
||||
return {hub: store, session: function session(req, res, next) {
|
||||
return {store: store, session: function session(req, res, next) {
|
||||
req.sessionStore = store;
|
||||
|
||||
req.sessionID = req.param('sessionid');
|
||||
// create the event object
|
||||
req.event = o_.extend({}, req.query, req.body, req.params);
|
||||
o_.deletekey(req.event, 'callback');
|
||||
o_.deletekey(req.event, '_');
|
||||
|
||||
if(url.parse(req.url).pathname.substring(0, 5) !== '/app/') {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
req.event.reply = function(status) {
|
||||
if (status) {
|
||||
this._status = status;
|
||||
}
|
||||
delete this.reply;
|
||||
res.jsonp(this);
|
||||
};
|
||||
|
||||
if(req.sessionID) {
|
||||
store.get(req, function(err, sess) {
|
||||
if(err) {
|
||||
next(err);
|
||||
var unauthenticated = function() {
|
||||
req.event.reply({sent: false, e: 'unauthenticated'});
|
||||
};
|
||||
|
||||
// set event handlers to unauthenticated by default
|
||||
res.message = res.typing = res.status = res.signOff = unauthenticated;
|
||||
|
||||
if(url.parse(req.url).pathname.substring(0, 5) === '/app/') {
|
||||
store.get(req.event, function(event, user) {
|
||||
if(!user) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!sess) {
|
||||
next(new Error(JSON.stringify({
|
||||
type: 'error',
|
||||
error: 'not authenticated'})));
|
||||
return;
|
||||
}
|
||||
|
||||
sess.touch();
|
||||
user.touch();
|
||||
if(url.parse(req.url).pathname === '/app/listen') {
|
||||
req.connection.setTimeout(5 * 60 * 1000);
|
||||
sess.listener(res);
|
||||
store.set(req.sessionID, sess);
|
||||
user.listener(res);
|
||||
store.set(user.data('username'), user);
|
||||
|
||||
if(msg = sess.message_queue.shift())
|
||||
sess._send.apply(sess, msg);
|
||||
if(msg = user.message_queue.shift()) {
|
||||
user._send.apply(user, msg);
|
||||
}
|
||||
} else {
|
||||
req.event = o_.extend({}, req.query, req.body, req.params);
|
||||
o_.deletekey(req.event, 'callback');
|
||||
o_.deletekey(req.event, 'sessionid');
|
||||
o_.deletekey(req.event, '_');
|
||||
req.event.from = sess.data('username');
|
||||
req.event.from = user.data('username');
|
||||
}
|
||||
|
||||
req.session = sess;
|
||||
res.session = sess;
|
||||
res.find = store.find.bind(store);
|
||||
res.message = function(to, event) {
|
||||
store.message(res, to, event);
|
||||
res.message = function() {
|
||||
user.message(req.event);
|
||||
};
|
||||
res.status = function(event) {
|
||||
req.session.status(res, event);
|
||||
res.typing = function() {
|
||||
if(~packages.TYPING_STATES.indexOf('typing' + req.event.state)) {
|
||||
store.find('username', req.event.to, function(to) {
|
||||
if(to) {
|
||||
req.event.status = 'typing' + req.event.state;
|
||||
user.message(req.event);
|
||||
} else {
|
||||
// Typing updates do not receive confirmations,
|
||||
// as they are not important enough.
|
||||
req.event.reply({sent: true});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
req.event.reply({sent: false, e: 'invalid state'});
|
||||
}
|
||||
};
|
||||
res.signOff = function(event) {
|
||||
store.signOff(req.sessionID, res, event);
|
||||
res.status = function() {
|
||||
user.status(req.event);
|
||||
};
|
||||
res.signOff = function() {
|
||||
user.signOff(req.event);
|
||||
};
|
||||
|
||||
if(url.parse(req.url).pathname !== '/app/listen') {
|
||||
@@ -65,9 +82,7 @@ module.exports = function setupHub(options) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
next(new Error(JSON.stringify({
|
||||
type: 'error',
|
||||
error: 'not authenticated'})));
|
||||
next();
|
||||
}
|
||||
}};
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ var Hub = module.exports = function Hub(options) {
|
||||
|
||||
if(this.reapInterval !== -1) {
|
||||
setInterval(function(self) {
|
||||
self.reap(self.maxAge);
|
||||
self.reapCheck(self.maxAge);
|
||||
}, this.reapInterval, this);
|
||||
}
|
||||
|
||||
@@ -24,9 +24,10 @@ var Hub = module.exports = function Hub(options) {
|
||||
var sids = Object.keys(this.sessions), sid, sess;
|
||||
for(sid in this.sessions) {
|
||||
sess = this.sessions[sid];
|
||||
if(sess.data('username') == event.from) {
|
||||
if(sess.listeners.length)
|
||||
if (sess.data('username') == event.from) {
|
||||
if (sess.listeners.length) {
|
||||
sess.send({type: 'goodbye'});
|
||||
}
|
||||
delete this.sessions[sid];
|
||||
break;
|
||||
}
|
||||
@@ -35,66 +36,56 @@ var Hub = module.exports = function Hub(options) {
|
||||
}, this));
|
||||
};
|
||||
|
||||
Hub.prototype.destroy = function(sid, fn) {
|
||||
this.set(sid, null, fn);
|
||||
};
|
||||
|
||||
Hub.prototype.reap = function(ms) {
|
||||
var threshold = +new Date - ms,
|
||||
sids = Object.keys(this.sessions);
|
||||
Hub.prototype.reapCheck = function(ms) {
|
||||
var threshold = +new Date - ms;
|
||||
var sids = Object.keys(this.sessions);
|
||||
for(var i = 0, len = sids.length; i < len; ++i) {
|
||||
var sid = sids[i], sess = this.sessions[sid];
|
||||
if(sess.lastAccess < threshold) {
|
||||
var event = {type: 'status', from: sess.data('username'), status: 'offline', message: ''};
|
||||
this.events.emit('update', event);
|
||||
delete this.sessions[sid];
|
||||
sess.close();
|
||||
var sid = sids[i];
|
||||
if(this.sessions[sid].lastAccess < threshold) {
|
||||
this.reap(sid);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Hub.prototype.get = function(req, fn) {
|
||||
if(this.sessions[req.sessionID]) {
|
||||
if (!this.sessions[req.sessionID].req) {
|
||||
this.sessions[req.sessionID].req = req;
|
||||
}
|
||||
fn(null, this.sessions[req.sessionID]);
|
||||
} else {
|
||||
this.auth.authenticate(req, o_.bind(function(data) {
|
||||
if(data) {
|
||||
var session = new User(req, data);
|
||||
if (req.socketio) {
|
||||
session.socketio = req.socketio;
|
||||
}
|
||||
this.set(req.sessionID, session);
|
||||
Hub.prototype.reap = function(sid) {
|
||||
var sess = this.sessions[sid];
|
||||
console.log('reaping '+sess.data('username'));
|
||||
var event = {type: 'status', from: sess.data('username'), status: 'offline', message: ''};
|
||||
this.events.emit('update', event);
|
||||
delete this.sessions[sid];
|
||||
sess.close();
|
||||
};
|
||||
|
||||
this.auth.friends(req, data, o_.bind(function(friends) {
|
||||
var friends_copy = friends.slice();
|
||||
o_.values(this.sessions).filter(function(friend) {
|
||||
return ~friends.indexOf(friend.data('username'));
|
||||
}).forEach(function(friend) {
|
||||
var username = friend.data('username');
|
||||
friends_copy[friends_copy.indexOf(username)] =
|
||||
[username, friend.status()];
|
||||
}, this);
|
||||
|
||||
session._friends(friends_copy);
|
||||
session.events.addListener('status',
|
||||
o_.bind(function(value, message) {
|
||||
var event = {type: 'status', from: session.data('username'), status: value, message: message};
|
||||
this.events.emit('update', event);
|
||||
}, this));
|
||||
this.events.addListener('update',
|
||||
o_.bind(session.receivedUpdate, session));
|
||||
this.set(req.sessionID, session);
|
||||
fn(null, session);
|
||||
}, this), this);
|
||||
session.status(null, {status: packages.STATUSES[0], message: ''});
|
||||
} else {
|
||||
fn();
|
||||
Hub.prototype.get = function(event, fn, socket) {
|
||||
this.auth.authenticate(this, event, o_.bind(function(event, user) {
|
||||
if (user) {
|
||||
if (socket) {
|
||||
user.socketio = socket;
|
||||
}
|
||||
}, this), this);
|
||||
}
|
||||
if (this.sessions[user.data('username')]) {
|
||||
fn(event, user);
|
||||
return;
|
||||
}
|
||||
this.set(user.data('username'), user);
|
||||
var friends = user.friends;
|
||||
var friends_copy = friends.slice();
|
||||
o_.values(this.sessions).filter(function(friend) {
|
||||
return ~friends.indexOf(friend.data('username'));
|
||||
}).forEach(function(friend) {
|
||||
var username = friend.data('username');
|
||||
friends_copy[friends_copy.indexOf(username)] = [username, friend.status()];
|
||||
}, this);
|
||||
user._friends(friends_copy);
|
||||
user.events.addListener('status', o_.bind(function(value, message) {
|
||||
var event = {type: 'status', from: user.data('username'), status: value, message: message};
|
||||
this.events.emit('update', event);
|
||||
}, this));
|
||||
this.events.addListener('update', o_.bind(user.receivedUpdate, user));
|
||||
fn(event, user);
|
||||
} else {
|
||||
fn(event);
|
||||
}
|
||||
}, this));
|
||||
};
|
||||
|
||||
Hub.prototype.set = function(sid, sess, fn) {
|
||||
@@ -102,11 +93,11 @@ Hub.prototype.set = function(sid, sess, fn) {
|
||||
fn && fn();
|
||||
};
|
||||
|
||||
Hub.prototype.find = function(username, fn) {
|
||||
Hub.prototype.find = function(key, value, fn) {
|
||||
for(var sid in this.sessions) {
|
||||
var session = this.sessions[sid],
|
||||
sess_username = session.data('username');
|
||||
if(sess_username == username) {
|
||||
var session = this.sessions[sid];
|
||||
var user_value = session.data(key);
|
||||
if (user_value == value) {
|
||||
fn(session);
|
||||
return;
|
||||
}
|
||||
@@ -114,31 +105,12 @@ Hub.prototype.find = function(username, fn) {
|
||||
fn(false);
|
||||
};
|
||||
|
||||
Hub.prototype.message = function(res, to, event) {
|
||||
try {
|
||||
to.send(event);
|
||||
event._status = {sent: true};
|
||||
if (res) {
|
||||
res.jsonp(event);
|
||||
Hub.prototype.dispatch = function(event) {
|
||||
this.find('username', event.from, function(from) {
|
||||
if (from) {
|
||||
from.dispatch(event);
|
||||
} else {
|
||||
this.find(event.from, function(from) {
|
||||
from.socketio.emit('client', event);
|
||||
});
|
||||
event.reply({sent: false, e: 'not authenticated'});
|
||||
}
|
||||
} catch(e) {
|
||||
event._status = {sent: false, e: e.description};
|
||||
res.jsonp(event);
|
||||
}
|
||||
};
|
||||
|
||||
Hub.prototype.signOff = function(sid, res, event) {
|
||||
if (sid in this.sessions) {
|
||||
event.status = 'offline';
|
||||
event.message = '';
|
||||
this.events.emit('update', event);
|
||||
}
|
||||
event._status = {sent: true};
|
||||
if (res) {
|
||||
res.jsonp(event);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2,14 +2,13 @@ var events = require('events'),
|
||||
packages = require('../../libs/packages'),
|
||||
o_ = require('../../libs/utils');
|
||||
|
||||
var User = module.exports = function(req, data) {
|
||||
this.req = req;
|
||||
this.id = req.sessionID;
|
||||
var User = module.exports = function(store, data, friends) {
|
||||
this.store = store;
|
||||
this.connection = null;
|
||||
this.listeners = [];
|
||||
this.message_queue = [];
|
||||
this.convos = {};
|
||||
this._data = data;
|
||||
this.friends = friends;
|
||||
|
||||
this.events = new events.EventEmitter();
|
||||
this._status = packages.STATUSES[0];
|
||||
@@ -102,7 +101,6 @@ User.prototype._send = function(type, event, res) {
|
||||
};
|
||||
|
||||
User.prototype.data = function(key, def) {
|
||||
if(key == 'id') return this.id;
|
||||
return this._data[key] || this['_' + key] ||
|
||||
(typeof this[key] != 'function' && this[key]) ||
|
||||
def || false;
|
||||
@@ -112,24 +110,49 @@ User.prototype.touch = function() {
|
||||
this.lastAccess = +new Date;
|
||||
};
|
||||
|
||||
User.prototype.status = function(res, event) {
|
||||
if(!event)
|
||||
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);
|
||||
event._status = {sent: true};
|
||||
if (res) {
|
||||
res.jsonp(event);
|
||||
if (event.reply) {
|
||||
event.reply({sent: true});
|
||||
}
|
||||
};
|
||||
|
||||
User.prototype.dispatch = function(hub, event) {
|
||||
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') {
|
||||
hub.find(event.to, function(to) {
|
||||
hub.message(null, to, event);
|
||||
});
|
||||
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'});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário