From f7f8c901f4bc39c3ed0a2bdfe1cbaa1ee6957999 Mon Sep 17 00:00:00 2001 From: Wu Cheng-Han Date: Mon, 1 Jun 2015 18:04:25 +0800 Subject: Marked as 0.2.9 --- lib/logger.js | 21 ++++++ lib/realtime.js | 193 ++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 175 insertions(+), 39 deletions(-) create mode 100644 lib/logger.js (limited to 'lib') 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)); } }); } -- cgit v1.2.3