summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/logger.js21
-rw-r--r--lib/realtime.js193
2 files changed, 175 insertions, 39 deletions
diff --git a/lib/logger.js b/lib/logger.js
new file mode 100644
index 00000000..c843330b
--- /dev/null
+++ b/lib/logger.js
@@ -0,0 +1,21 @@
+var winston = require('winston');
+winston.emitErrs = true;
+
+var logger = new winston.Logger({
+ transports: [
+ new winston.transports.Console({
+ level: 'debug',
+ handleExceptions: true,
+ json: false,
+ colorize: true
+ })
+ ],
+ exitOnError: false
+});
+
+module.exports = logger;
+module.exports.stream = {
+ write: function(message, encoding){
+ logger.info(message);
+ }
+}; \ No newline at end of file
diff --git a/lib/realtime.js b/lib/realtime.js
index e3800275..1a57c77e 100644
--- a/lib/realtime.js
+++ b/lib/realtime.js
@@ -7,6 +7,8 @@ var async = require('async');
var LZString = require('lz-string');
var shortId = require('shortid');
var randomcolor = require("randomcolor");
+var Chance = require('chance'),
+ chance = new Chance();
//core
var config = require("../config.js");
@@ -18,11 +20,22 @@ var User = require("./user.js");
//public
var realtime = {
+ onAuthorizeSuccess: onAuthorizeSuccess,
+ onAuthorizeFail: onAuthorizeFail,
secure: secure,
connection: connection,
getStatus: getStatus
};
+function onAuthorizeSuccess(data, accept) {
+ accept(null, true);
+}
+
+function onAuthorizeFail(data, message, error, accept) {
+ if (error) throw new Error(message);
+ accept(null, true);
+}
+
function secure(socket, next) {
try {
var handshakeData = socket.request;
@@ -53,8 +66,10 @@ var updater = setInterval(function () {
if (note.isDirty) {
if (config.debug)
console.log("updater found dirty note: " + key);
- var title = Note.getNoteTitle(LZString.decompressFromBase64(note.body));
- db.saveToDB(key, title, note.body,
+ var body = LZString.decompressFromUTF16(note.body);
+ var title = Note.getNoteTitle(body);
+ body = LZString.compressToBase64(body);
+ db.saveToDB(key, title, body,
function (err, result) {});
note.isDirty = false;
}
@@ -72,7 +87,7 @@ function getStatus(callback) {
var distinctaddresses = [];
Object.keys(users).forEach(function (key) {
var value = users[key];
- if(value.login)
+ if (value.login)
regusers++;
var found = false;
for (var i = 0; i < distinctaddresses.length; i++) {
@@ -83,9 +98,9 @@ function getStatus(callback) {
}
if (!found) {
distinctaddresses.push(value.address);
- if(value.login)
+ if (value.login)
distinctregusers++;
- }
+ }
});
User.getUserCount(function (err, regcount) {
if (err) {
@@ -129,17 +144,25 @@ function emitOnlineUsers(socket) {
Object.keys(notes[notename].users).forEach(function (key) {
var user = notes[notename].users[key];
if (user)
- users.push({
- id: user.id,
- color: user.color,
- cursor: user.cursor
- });
+ users.push(buildUserOutData(user));
});
notes[notename].socks.forEach(function (sock) {
- sock.emit('online users', {
- count: notes[notename].socks.length,
+ var out = {
users: users
- });
+ };
+ out = LZString.compressToUTF16(JSON.stringify(out));
+ sock.emit('online users', out);
+ });
+}
+
+function emitUserStatus(socket) {
+ var notename = getNotenameFromSocket(socket);
+ if (!notename || !notes[notename]) return;
+ notes[notename].socks.forEach(function (sock) {
+ if (sock != socket) {
+ var out = buildUserOutData(users[socket.id]);
+ sock.emit('user status', out);
+ }
});
}
@@ -198,7 +221,8 @@ function startConnection(socket) {
isConnectionBusy = false;
return console.error(err);
}
- var body = data.rows[0].content;
+ var body = LZString.decompressFromBase64(data.rows[0].content);
+ body = LZString.compressToUTF16(body);
notes[notename] = {
socks: [],
body: body,
@@ -232,8 +256,10 @@ function disconnect(socket) {
notes[notename].socks.splice(index, 1);
}
if (Object.keys(notes[notename].users).length <= 0) {
- var title = Note.getNoteTitle(LZString.decompressFromBase64(notes[notename].body));
- db.saveToDB(notename, title, notes[notename].body,
+ var body = LZString.decompressFromUTF16(notes[notename].body);
+ var title = Note.getNoteTitle(body);
+ body = LZString.compressToBase64(body);
+ db.saveToDB(notename, title, body,
function (err, result) {
delete notes[notename];
if (config.debug) {
@@ -265,20 +291,80 @@ function disconnect(socket) {
}
}
+function buildUserOutData(user) {
+ var out = {
+ id: user.id,
+ login: user.login,
+ userid: user.userid,
+ color: user.color,
+ cursor: user.cursor,
+ name: user.name,
+ idle: user.idle,
+ type: user.type
+ };
+ return out;
+}
+
+function updateUserData(socket, user) {
+ //retrieve user data from passport
+ if (socket.request.user && socket.request.user.logged_in) {
+ var profile = JSON.parse(socket.request.user.profile);
+ user.name = profile.displayName || profile.username;
+ user.userid = socket.request.user._id;
+ user.login = true;
+ } else {
+ user.userid = null;
+ user.name = 'Guest ' + chance.last();
+ user.login = false;
+ }
+}
function connection(socket) {
+ //split notename from socket
+ var notename = getNotenameFromSocket(socket);
+
+ //initialize user data
+ //random color
+ var color = randomcolor({
+ luminosity: 'light'
+ });
+ //make sure color not duplicated or reach max random count
+ if (notename && notes[notename]) {
+ var randomcount = 0;
+ var maxrandomcount = 5;
+ var found = false;
+ do {
+ Object.keys(notes[notename].users).forEach(function (user) {
+ if (user.color == color) {
+ found = true;
+ return;
+ }
+ });
+ if (found) {
+ color = randomcolor({
+ luminosity: 'light'
+ });
+ randomcount++;
+ }
+ } while (found && randomcount < maxrandomcount);
+ }
+ //create user data
users[socket.id] = {
id: socket.id,
address: socket.handshake.address,
'user-agent': socket.handshake.headers['user-agent'],
otk: shortId.generate(),
- color: randomcolor({
- luminosity: 'light'
- }),
+ color: color,
cursor: null,
- login: false
+ login: false,
+ userid: null,
+ name: null,
+ idle: false,
+ type: null
};
+ updateUserData(socket, users[socket.id]);
+ //start connection
connectionSocketQueue.push(socket);
startConnection(socket);
@@ -293,61 +379,88 @@ function connection(socket) {
notes[notename].isDirty = true;
}
});
-
+
+ //received user status
socket.on('user status', function (data) {
- if(data)
- users[socket.id].login = data.login;
+ var notename = getNotenameFromSocket(socket);
+ if (!notename) return;
+ if (config.debug)
+ console.log('SERVER received [' + notename + '] user status from [' + socket.id + ']: ' + JSON.stringify(data));
+ if (data) {
+ var user = users[socket.id];
+ user.idle = data.idle;
+ user.type = data.type;
+ }
+ emitUserStatus(socket);
});
- socket.on('online users', function () {
+ //reveiced when user logout or changed
+ socket.on('user changed', function () {
+ console.log('user changed');
+ var notename = getNotenameFromSocket(socket);
+ if (!notename || !notes[notename]) return;
+ updateUserData(socket, notes[notename].users[socket.id]);
emitOnlineUsers(socket);
});
+ //received sync of online users request
+ socket.on('online users', function () {
+ var notename = getNotenameFromSocket(socket);
+ if (!notename || !notes[notename]) return;
+ var users = [];
+ Object.keys(notes[notename].users).forEach(function (key) {
+ var user = notes[notename].users[key];
+ if (user)
+ users.push(buildUserOutData(user));
+ });
+ var out = {
+ users: users
+ };
+ out = LZString.compressToUTF16(JSON.stringify(out));
+ socket.emit('online users', out);
+ });
+
+ //check version
socket.on('version', function () {
socket.emit('version', config.version);
});
+ //received cursor focus
socket.on('cursor focus', function (data) {
var notename = getNotenameFromSocket(socket);
if (!notename || !notes[notename]) return;
users[socket.id].cursor = data;
+ var out = buildUserOutData(users[socket.id]);
notes[notename].socks.forEach(function (sock) {
if (sock != socket) {
- var out = {
- id: socket.id,
- color: users[socket.id].color,
- cursor: data
- };
sock.emit('cursor focus', out);
}
});
});
+ //received cursor activity
socket.on('cursor activity', function (data) {
var notename = getNotenameFromSocket(socket);
if (!notename || !notes[notename]) return;
users[socket.id].cursor = data;
+ var out = buildUserOutData(users[socket.id]);
notes[notename].socks.forEach(function (sock) {
if (sock != socket) {
- var out = {
- id: socket.id,
- color: users[socket.id].color,
- cursor: data
- };
sock.emit('cursor activity', out);
}
});
});
+ //received cursor blur
socket.on('cursor blur', function () {
var notename = getNotenameFromSocket(socket);
if (!notename || !notes[notename]) return;
users[socket.id].cursor = null;
+ var out = {
+ id: socket.id
+ };
notes[notename].socks.forEach(function (sock) {
if (sock != socket) {
- var out = {
- id: socket.id
- };
if (sock != socket) {
sock.emit('cursor blur', out);
}
@@ -365,7 +478,7 @@ function connection(socket) {
socket.on('change', function (op) {
var notename = getNotenameFromSocket(socket);
if (!notename) return;
- op = LZString.decompressFromBase64(op);
+ op = LZString.decompressFromUTF16(op);
if (op)
op = JSON.parse(op);
if (config.debug)
@@ -390,10 +503,12 @@ function connection(socket) {
if (sock != socket) {
if (config.debug)
console.log('SERVER emit sync data out [' + notename + ']: ' + sock.id + ', op:' + JSON.stringify(op));
- sock.emit('change', LZString.compressToBase64(JSON.stringify(op)));
+ sock.emit('change', LZString.compressToUTF16(JSON.stringify(op)));
}
});
break;
+ default:
+ console.log('SERVER received uncaught [' + notename + '] data changed: ' + socket.id + ', op:' + JSON.stringify(op));
}
});
}