diff --git a/client/lib/RoomManager.coffee b/client/lib/RoomManager.coffee index 1edc98059b98..61c703c66a18 100644 --- a/client/lib/RoomManager.coffee +++ b/client/lib/RoomManager.coffee @@ -30,12 +30,15 @@ Meteor.startup -> ChatMessage.update {_id: recordAfter._id}, {$set: {tick: new Date}} +onDeleteMessageStream = (msg) -> + ChatMessage.remove _id: msg._id + + @RoomManager = new class defaultTime = 600000 # 10 minutes openedRooms = {} subscription = null msgStream = new Meteor.Stream 'messages' - deleteMsgStream = new Meteor.Stream 'delete-message' onlineUsers = new ReactiveVar {} Dep = new Tracker.Dependency @@ -52,7 +55,7 @@ Meteor.startup -> if openedRooms[typeName].rid? msgStream.removeListener openedRooms[typeName].rid - deleteMsgStream.removeListener openedRooms[typeName].rid + RocketChat.Notifications.unRoom openedRooms[typeName].rid, 'deleteMessage', onDeleteMessageStream openedRooms[typeName].ready = false openedRooms[typeName].active = false @@ -101,8 +104,7 @@ Meteor.startup -> RoomManager.close type + FlowRouter.getParam('name') FlowRouter.go FlowRouter.current().route.name, name: msg.msg - deleteMsgStream.on openedRooms[typeName].rid, (msg) -> - ChatMessage.remove _id: msg._id + RocketChat.Notifications.onRoom openedRooms[typeName].rid, 'deleteMessage', onDeleteMessageStream Dep.changed() diff --git a/client/lib/msgTyping.coffee b/client/lib/msgTyping.coffee index 96944a0082c9..58aa3fe15298 100644 --- a/client/lib/msgTyping.coffee +++ b/client/lib/msgTyping.coffee @@ -1,5 +1,4 @@ @MsgTyping = do -> - stream = new Meteor.Stream 'typing' timeout = 15000 timeouts = {} renew = true @@ -11,7 +10,7 @@ addStream = (room) -> if _.isEmpty usersTyping[room]?.users usersTyping[room] = { users: {} } - stream.on room, (typing) -> + RocketChat.Notifications.onRoom room, 'typing', (typing) -> unless typing?.username is Meteor.user()?.username if typing.start users = usersTyping[room].users @@ -41,7 +40,7 @@ renew = false selfTyping.set true - stream.emit 'typing', { room: room, username: Meteor.user()?.username, start: true } + RocketChat.Notifications.notifyRoom room, 'typing', { room: room, username: Meteor.user()?.username, start: true } clearTimeout timeouts[room] timeouts[room] = Meteor.setTimeout -> stop(room) @@ -51,10 +50,10 @@ renew = true selfTyping.set false if timeouts?[room]? - clearTimeout(timeouts[room]) + clearTimeout(timeouts[room]) timeouts[room] = null - stream.emit 'typing', { room: room, username: Meteor.user()?.username, stop: true } - + RocketChat.Notifications.notifyRoom room, 'typing', { room: room, username: Meteor.user()?.username, stop: true } + get = (room) -> dep.depend() unless usersTyping[room] @@ -62,9 +61,9 @@ users = usersTyping[room].users return _.keys(users) or [] - return { + return { start: start stop: stop get: get selfTyping: selfTyping - } \ No newline at end of file + } diff --git a/client/notifications/updateAvatar.coffee b/client/notifications/updateAvatar.coffee new file mode 100644 index 000000000000..fc63c7b1a972 --- /dev/null +++ b/client/notifications/updateAvatar.coffee @@ -0,0 +1,3 @@ +Meteor.startup -> + RocketChat.Notifications.onAll 'updateAvatar', (data) -> + updateAvatarOfUsername data.username diff --git a/client/views/account/avatar/prompt.coffee b/client/views/account/avatar/prompt.coffee index b7bb43a53419..13177d928571 100644 --- a/client/views/account/avatar/prompt.coffee +++ b/client/views/account/avatar/prompt.coffee @@ -34,11 +34,9 @@ Template.avatarPrompt.events 'click .select-service': -> if @service is 'initials' Meteor.call 'resetAvatar' - updateAvatarOfUsername Meteor.user().username toastr.success t('Avatar_changed_successfully') else Meteor.call 'setAvatarFromService', @blob, @contentType, @service, -> - updateAvatarOfUsername Meteor.user().username toastr.success t('Avatar_changed_successfully') 'click .login-with-service': (event, template) -> diff --git a/packages/meteor-streams/LICENSE b/packages/meteor-streams/LICENSE new file mode 100755 index 000000000000..8a2cc4f283d4 --- /dev/null +++ b/packages/meteor-streams/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2013 Arunoda Susiripala + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/packages/meteor-streams/README.md b/packages/meteor-streams/README.md new file mode 100755 index 000000000000..5e6dac0ec2ec --- /dev/null +++ b/packages/meteor-streams/README.md @@ -0,0 +1,10 @@ +# Meteor Streams [![Build Status](https://travis-ci.org/arunoda/meteor-streams.png?branch=master)](https://travis-ci.org/arunoda/meteor-streams) + +DB less realtime communication for meteor + +## Development Status +Project development status is [inactive](https://github.com/arunoda/meteor-streams/issues/21#issuecomment-59030380). + +## [Documentation](http://arunoda.github.io/meteor-streams/) + +[![Meteor Streams - DB less realtime communication for meteor](http://i.imgur.com/ZB3g3AK.png)](http://arunoda.github.io/meteor-streams/) diff --git a/packages/meteor-streams/lib/client.js b/packages/meteor-streams/lib/client.js new file mode 100755 index 000000000000..2df62a2ed2e2 --- /dev/null +++ b/packages/meteor-streams/lib/client.js @@ -0,0 +1,48 @@ +Meteor.Stream = function Stream(name, callback) { + EV.call(this); + + var self = this; + var streamName = 'stream-' + name; + var collection = new Meteor.Collection(streamName); + var subscription; + var subscriptionId; + + var connected = false; + var pendingEvents = []; + + self._emit = self.emit; + + collection.find({}).observe({ + "added": function(item) { + if(item.type == 'subscriptionId') { + subscriptionId = item._id; + connected = true; + pendingEvents.forEach(function(args) { + self.emit.apply(self, args); + }); + pendingEvents = []; + } else { + var context = {}; + context.subscriptionId = item.subscriptionId; + context.userId = item.userId; + self._emit.apply(context, item.args); + } + } + }); + + subscription = Meteor.subscribe(streamName, callback); + + self.emit = function emit() { + if(connected) { + Meteor.call(streamName, subscriptionId, arguments); + } else { + pendingEvents.push(arguments); + } + }; + + self.close = function close() { + subscription.stop(); + }; +} + +_.extend(Meteor.Stream.prototype, EV.prototype); diff --git a/packages/meteor-streams/lib/ev.js b/packages/meteor-streams/lib/ev.js new file mode 100755 index 000000000000..b02870db4d17 --- /dev/null +++ b/packages/meteor-streams/lib/ev.js @@ -0,0 +1,44 @@ +function _EV() { + var self = this; + var handlers = {}; + + self.emit = function emit(event) { + var args = Array.prototype.slice.call(arguments, 1); + + if(handlers[event]) { + for(var lc=0; lc -1) + handlers[event].splice(index, 1); + } + }; + + self.removeAllListeners = function removeAllListeners(event) { + handlers[event] = undefined; + }; +} + +EV = _EV; diff --git a/packages/meteor-streams/lib/server.js b/packages/meteor-streams/lib/server.js new file mode 100755 index 000000000000..bda32e698fd2 --- /dev/null +++ b/packages/meteor-streams/lib/server.js @@ -0,0 +1,114 @@ +var EventEmitter = Npm.require('events').EventEmitter; +var util = Npm.require('util'); +var Fibers = Npm.require('fibers'); + +Meteor.Stream = function Stream(name) { + EV.call(this); + + var self = this; + var streamName = 'stream-' + name; + var allowFunction; + var allowResultCache = true; + var allowResults = {}; + var filters = []; + + self.name = name; + + var events = new EventEmitter(); + events.setMaxListeners(0); + + var disconnectEvents = new EV(); + + self._emit = self.emit; + self.emit = function emit() { + self.emitToSubscriptions(arguments, null, null); + }; + + var defaultResult = (typeof(Package) == 'object' && Package.insecure)? true: Meteor.Collection.insecure === true; + self.permissions = new Meteor.Stream.Permission(defaultResult, true); + + self.addFilter = function addFilter(callback) { + filters.push(callback); + }; + + self.emitToSubscriptions = function emitToSubscriptions(args, subscriptionId, userId) { + events.emit('item', {args: args, userId: userId, subscriptionId: subscriptionId}); + }; + + Meteor.publish(streamName, function() { + check(arguments, Match.Any); + var subscriptionId = Random.id(); + var publication = this; + + //send subscription id as the first document + publication.added(streamName, subscriptionId, {type: 'subscriptionId'}); + publication.ready(); + events.on('item', onItem); + + function onItem(item) { + Fibers(function() { + var id = Random.id(); + if(self.permissions.checkPermission('read', subscriptionId, publication.userId, item.args)) { + //do not send again this to the sender + if(subscriptionId != item.subscriptionId) { + publication.added(streamName, id, item); + publication.removed(streamName, id); + } + } + }).run(); + } + + publication.onStop(function() { + //trigger related onDisconnect handlers if exists + Fibers(function() { + disconnectEvents.emit(subscriptionId); + disconnectEvents.removeAllListeners(subscriptionId); + }).run(); + events.removeListener('item', onItem); + }); + }); + + var methods = {}; + methods[streamName] = function(subscriptionId, args) { + check(arguments, Match.Any); + //in order to send this to the server callback + var userId = this.userId; + Fibers(function() { + var methodContext = {}; + methodContext.userId = userId; + methodContext.subscriptionId = subscriptionId; + + //in order to send this to the serve callback + methodContext.allowed = self.permissions.checkPermission('write', subscriptionId, methodContext.userId, args); + if(methodContext.allowed) { + //apply filters + args = applyFilters(args, methodContext); + self.emitToSubscriptions(args, subscriptionId, methodContext.userId); + //send to firehose if exists + if(self.firehose) { + self.firehose(args, subscriptionId, methodContext.userId); + } + } + //need to send this to server always + self._emit.apply(methodContext, args); + + //register onDisconnect handlers if provided + if(typeof(methodContext.onDisconnect) == 'function') { + disconnectEvents.on(subscriptionId, methodContext.onDisconnect) + } + + }).run(); + }; + Meteor.methods(methods); + + function applyFilters(args, context) { + var eventName = args.shift(); + filters.forEach(function(filter) { + args = filter.call(context, eventName, args); + }); + args.unshift(eventName); + return args; + } +}; + +util.inherits(Meteor.Stream, EV); \ No newline at end of file diff --git a/packages/meteor-streams/lib/stream_permission.js b/packages/meteor-streams/lib/stream_permission.js new file mode 100755 index 000000000000..8437db926d13 --- /dev/null +++ b/packages/meteor-streams/lib/stream_permission.js @@ -0,0 +1,42 @@ +Meteor.Stream.Permission = function (acceptAll, cacheAll) { + var options = { + "read": { + results: {} + }, + "write": { + results: {} + } + }; + + this.read = function(func, cache) { + options['read']['func'] = func; + options['read']['doCache'] = (cache === undefined)? cacheAll: cache; + }; + + this.write = function(func, cache) { + options['write']['func'] = func; + options['write']['doCache'] = (cache === undefined)? cacheAll: cache; + }; + + this.checkPermission = function(type, subscriptionId, userId, args) { + var eventName = args[0]; + var namespace = subscriptionId + '-' + eventName; + var result = options[type].results[namespace]; + + if(result === undefined) { + var func = options[type].func; + if(func) { + var context = {subscriptionId: subscriptionId, userId: userId}; + result = func.apply(context, args); + if(options[type].doCache) { + options[type].results[namespace] = result; + } + return result; + } else { + return acceptAll; + } + } else { + return result; + } + }; +} diff --git a/packages/meteor-streams/package.js b/packages/meteor-streams/package.js new file mode 100755 index 000000000000..0b2b99d974d7 --- /dev/null +++ b/packages/meteor-streams/package.js @@ -0,0 +1,11 @@ +Package.describe({ + name: 'arunoda:streams', + version: '0.1.17', + summary: "DB less realtime communication for meteor" +}); + +Package.on_use(function (api, where) { + api.use('underscore', ['client', 'server']); + api.add_files(['lib/ev.js', 'lib/server.js', 'lib/stream_permission.js'], 'server'); + api.add_files(['lib/ev.js', 'lib/client.js'], 'client'); +}); diff --git a/packages/rocketchat-lib/client/Notifications.coffee b/packages/rocketchat-lib/client/Notifications.coffee new file mode 100644 index 000000000000..ef2b1cd62aa0 --- /dev/null +++ b/packages/rocketchat-lib/client/Notifications.coffee @@ -0,0 +1,47 @@ +RocketChat.Notifications = new class + constructor: -> + @debug = true + @streamAll = new Meteor.Stream 'notify-all' + @streamRoom = new Meteor.Stream 'notify-room' + @streamUser = new Meteor.Stream 'notify-user' + + if @debug is true + @onAll -> console.log "RocketChat.Notifications: onAll", arguments + @onUser -> console.log "RocketChat.Notifications: onAll", arguments + + + notifyRoom: (room, eventName, args...) -> + console.log "RocketChat.Notifications: notifyRoom", arguments if @debug is true + + args.unshift "#{room}/#{eventName}" + @streamRoom.emit.apply @streamRoom, args + + notifyUser: (userId, eventName, args...) -> + console.log "RocketChat.Notifications: notifyUser", arguments if @debug is true + + args.unshift "#{userId}/#{eventName}" + @streamUser.emit.apply @streamUser, args + + + onAll: (eventName, callback) -> + @streamAll.on eventName, callback + + onRoom: (room, eventName, callback) -> + console.log 'onRoom' + if @debug is true + @streamRoom.on room, -> console.log "RocketChat.Notifications: onRoom #{room}", arguments + + @streamRoom.on "#{room}/#{eventName}", callback + + onUser: (eventName, callback) -> + @streamUser.on "#{Meteor.userId()}/#{eventName}", callback + + + unAll: (callback) -> + @streamAll.removeListener 'notify', callback + + unRoom: (room, eventName, callback) -> + @streamRoom.removeListener "#{room}/#{eventName}", callback + + unUser: (callback) -> + @streamUser.removeListener Meteor.userId(), callback diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js index c176316291e2..554dfd907173 100644 --- a/packages/rocketchat-lib/package.js +++ b/packages/rocketchat-lib/package.js @@ -8,51 +8,53 @@ Package.describe({ Package.onUse(function(api) { api.versionsFrom('1.0'); - api.use([ - 'reactive-dict', - 'coffeescript', - 'random', - 'underscore', - 'underscorestring:underscore.string' - ]); - - api.addFiles('lib/core.coffee', ['server', 'client']); - api.addFiles('lib/callbacks.coffee', ['server', 'client']); - api.addFiles('lib/slashCommand.coffee', ['server', 'client']); - - api.addFiles([ - 'server/functions/checkUsernameAvailability.coffee', - 'server/functions/setUsername.coffee' - ], ['server']); - - api.addFiles([ - 'server/methods/joinDefaultChannels.coffee', - 'server/methods/setAdminStatus.coffee', - 'server/methods/setUsername.coffee', - 'server/methods/updateUser.coffee' - ], ['server']); - - api.addFiles('server/sendMessage.coffee', ['server']); - - api.addFiles([ - 'settings/lib/settings.coffee', - 'settings/lib/rocketchat.coffee' - ], ['server', 'client']); - - api.addFiles('settings/client/startup.coffee', ['client']); - api.addFiles('settings/client/rocketchat.coffee', ['client']); - - api.addFiles([ - 'settings/server/methods.coffee', - 'settings/server/publication.coffee', - 'settings/server/startup.coffee', - 'settings/server/updateServices.coffee', - 'settings/server/addOAuthService.coffee' - ], ['server']); - - api.addFiles('server/cdn.coffee', ['server']); - - api.export(['RocketChat'], ['server', 'client']); + api.use('reactive-dict'); + api.use('coffeescript'); + api.use('random'); + api.use('underscore'); + api.use('underscorestring:underscore.string'); + + + // COMMON + api.addFiles('lib/core.coffee'); + api.addFiles('lib/callbacks.coffee'); + api.addFiles('lib/slashCommand.coffee'); + + api.addFiles('settings/lib/settings.coffee'); + api.addFiles('settings/lib/rocketchat.coffee'); + + + // CLIENT + api.addFiles('client/Notifications.coffee', 'client'); + + api.addFiles('settings/client/startup.coffee', 'client'); + api.addFiles('settings/client/rocketchat.coffee', 'client'); + + + // SERVER + api.addFiles('server/functions/checkUsernameAvailability.coffee', 'server'); + api.addFiles('server/functions/setUsername.coffee', 'server'); + + api.addFiles('server/methods/joinDefaultChannels.coffee', 'server'); + api.addFiles('server/methods/setAdminStatus.coffee', 'server'); + api.addFiles('server/methods/setUsername.coffee', 'server'); + api.addFiles('server/methods/updateUser.coffee', 'server'); + + api.addFiles('server/sendMessage.coffee', 'server'); + + api.addFiles('server/Notifications.coffee', 'server'); + + api.addFiles('settings/server/methods.coffee', 'server'); + api.addFiles('settings/server/publication.coffee', 'server'); + api.addFiles('settings/server/startup.coffee', 'server'); + api.addFiles('settings/server/updateServices.coffee', 'server'); + api.addFiles('settings/server/addOAuthService.coffee', 'server'); + + api.addFiles('server/cdn.coffee', 'server'); + + + // EXPORT + api.export('RocketChat'); }); Package.onTest(function(api) { diff --git a/packages/rocketchat-lib/server/Notifications.coffee b/packages/rocketchat-lib/server/Notifications.coffee new file mode 100644 index 000000000000..a2d732ea30f9 --- /dev/null +++ b/packages/rocketchat-lib/server/Notifications.coffee @@ -0,0 +1,46 @@ +RocketChat.Notifications = new class + constructor: -> + self = @ + + @debug = true + + @streamAll = new Meteor.Stream 'notify-all' + @streamRoom = new Meteor.Stream 'notify-room' + @streamUser = new Meteor.Stream 'notify-user' + + + @streamAll.permissions.write -> return @userId? + @streamAll.permissions.read -> return @userId? + + @streamRoom.permissions.write -> return @userId? + @streamRoom.permissions.read (eventName) -> + if not @userId? then return false + + roomId = eventName.split('/')[0] + + user = Meteor.users.findOne @userId, {fields: {username: 1}} + return ChatRoom.findOne({_id: roomId, usernames: user.username}, {fields: {_id: 1}})? + + @streamUser.permissions.write -> return @userId? + @streamUser.permissions.read (eventName) -> + userId = eventName.split('/')[0] + return @userId? and @userId is userId + + + notifyAll: (eventName, args...) -> + console.log 'notifyAll', arguments if @debug is true + + args.unshift eventName + @streamAll.emit.apply @streamAll, args + + notifyRoom: (room, eventName, args...) -> + console.log 'notifyRoom', arguments if @debug is true + + args.unshift "#{room}/#{eventName}" + @streamRoom.emit.apply @streamRoom, args + + notifyUser: (userId, eventName, args...) -> + console.log 'notifyUser', arguments if @debug is true + + args.unshift "#{userId}/#{eventName}" + @streamUser.emit.apply @streamUser, args diff --git a/packages/rocketchat-webrtc/common.js b/packages/rocketchat-webrtc/common.js deleted file mode 100644 index a4cd85fd3604..000000000000 --- a/packages/rocketchat-webrtc/common.js +++ /dev/null @@ -1 +0,0 @@ -stream = new Meteor.Stream('webrtc'); \ No newline at end of file diff --git a/packages/rocketchat-webrtc/package.js b/packages/rocketchat-webrtc/package.js index b80b4e649100..fe0e62fb242a 100644 --- a/packages/rocketchat-webrtc/package.js +++ b/packages/rocketchat-webrtc/package.js @@ -8,18 +8,12 @@ Package.describe({ Package.onUse(function(api) { api.versionsFrom('1.0'); - api.use([ - 'coffeescript', - 'arunoda:streams@0.1.17', - 'rocketchat:lib@0.0.1' - ]); + api.use('rocketchat:lib@0.0.1', 'client'); - api.addFiles('common.js'); - api.addFiles('adapter.js', ['client']); - api.addFiles('webrtc.js', ['client']); - api.addFiles('server.js', ['server']); + api.addFiles('adapter.js', 'client'); + api.addFiles('webrtc.js', 'client'); - api.export('webrtc') + api.export('webrtc'); }); diff --git a/packages/rocketchat-webrtc/server.js b/packages/rocketchat-webrtc/server.js deleted file mode 100644 index d305ebe10c57..000000000000 --- a/packages/rocketchat-webrtc/server.js +++ /dev/null @@ -1,18 +0,0 @@ -webrtc = { - stream: stream -} - -stream.permissions.write(function(eventName) { - console.log('stream.permissions.write', this.userId); - return eventName == 'send' && this.userId; -}); - -stream.permissions.read(function(eventName) { - console.log('stream.permissions.read', this.userId, eventName); - return this.userId == eventName; -}); - -stream.on('send', function(data) { - console.log('send', data); - stream.emit(data.to, data); -}); \ No newline at end of file diff --git a/packages/rocketchat-webrtc/webrtc.js b/packages/rocketchat-webrtc/webrtc.js index 7fc220647073..dfc03dace1b2 100644 --- a/packages/rocketchat-webrtc/webrtc.js +++ b/packages/rocketchat-webrtc/webrtc.js @@ -10,12 +10,11 @@ webrtc = { {url: "stun:stun.l.google.com:19302"} ] }, - stream: stream, send: function(data) { data.to = webrtc.to; data.room = webrtc.room; data.from = Meteor.user().username; - stream.emit('send', data); + RocketChat.Notifications.notifyUser(data.to, 'webrtc', data); }, stop: function(sendEvent) { if (webrtc.pc) { @@ -23,7 +22,7 @@ webrtc = { webrtc.pc.close(); } if (sendEvent != false) { - stream.emit('send', {to: webrtc.to, room: webrtc.room, from: Meteor.userId(), close: true}); + RocketChat.Notifications.notifyUser(webrtc.to, 'webrtc', {to: webrtc.to, room: webrtc.room, from: Meteor.userId(), close: true}); } } }, @@ -126,7 +125,7 @@ webrtc.start = function (isCaller, fromUsername) { } } -stream.on(Meteor.userId(), function(data) { +RocketChat.Notifications.onUser('webrtc', function(data) { webrtc.log('stream.on', Meteor.userId(), data) if (!webrtc.to) { webrtc.to = data.room.replace(Meteor.userId(), ''); diff --git a/server/methods/deleteMessage.coffee b/server/methods/deleteMessage.coffee index 2ad455583626..cb2756262634 100644 --- a/server/methods/deleteMessage.coffee +++ b/server/methods/deleteMessage.coffee @@ -48,4 +48,4 @@ Meteor.methods t: 'rm' ets: new Date() else - deleteMsgStream.emit message.rid, { _id: message._id } + RocketChat.Notifications.notifyRoom message.rid, 'deleteMessage', { _id: message._id } diff --git a/server/methods/resetAvatar.coffee b/server/methods/resetAvatar.coffee index a1dcb3e55ba7..2b49fdbf3db0 100644 --- a/server/methods/resetAvatar.coffee +++ b/server/methods/resetAvatar.coffee @@ -10,4 +10,6 @@ Meteor.methods RocketChatFileAvatarInstance.deleteFile "#{user.username}.jpg" Meteor.users.update user._id, {$unset: {avatarOrigin: 1}} + + RocketChat.Notifications.notifyAll 'updateAvatar', {username: user.username} return diff --git a/server/methods/setAvatarFromService.coffee b/server/methods/setAvatarFromService.coffee index f2ad06a6f629..475c005a5983 100644 --- a/server/methods/setAvatarFromService.coffee +++ b/server/methods/setAvatarFromService.coffee @@ -16,7 +16,10 @@ Meteor.methods rs = RocketChatFile.bufferToStream new Buffer(image, 'base64') ws = RocketChatFileAvatarInstance.createWriteStream "#{user.username}.jpg", contentType ws.on 'end', Meteor.bindEnvironment -> - Meteor.users.update {_id: user._id}, {$set: {avatarOrigin: service}} + Meteor.setTimeout -> + Meteor.users.update {_id: user._id}, {$set: {avatarOrigin: service}} + RocketChat.Notifications.notifyAll 'updateAvatar', {username: user.username} + , 500 rs.pipe(ws) return diff --git a/server/stream/messages.coffee b/server/stream/messages.coffee index 6c514272f7df..5cf342530488 100644 --- a/server/stream/messages.coffee +++ b/server/stream/messages.coffee @@ -1,5 +1,4 @@ @msgStream = new Meteor.Stream 'messages' -@deleteMsgStream = new Meteor.Stream 'delete-message' msgStream.permissions.write (eventName) -> console.log('stream.permissions.write', this.userId); @@ -20,17 +19,6 @@ msgStream.permissions.read (eventName) -> return false -deleteMsgStream.permissions.write (eventName) -> - return false - -deleteMsgStream.permissions.read (eventName) -> - try - canAccess = Meteor.call 'canAccessRoom', eventName, this.userId - - return !!canAccess - catch e - return false - Meteor.startup -> filter = _hidden: { $ne: true } diff --git a/server/stream/streamBroadcast.coffee b/server/stream/streamBroadcast.coffee index 7fd13ad79182..06fa472ea6b2 100644 --- a/server/stream/streamBroadcast.coffee +++ b/server/stream/streamBroadcast.coffee @@ -18,11 +18,11 @@ connections[record.extraInformation.port].disconnect() delete connections[record.extraInformation.port] - broadcast = (streamName, eventName, args, userId) -> + broadcast = (streamName, args, userId) -> for port, connection of connections if connection.status().connected is true - console.log 'broadcast to', port, streamName, eventName, args - connection.call 'stream', streamName, eventName, args + console.log 'broadcast to', port, streamName, args + connection.call 'stream', streamName, args Meteor.methods @@ -36,24 +36,26 @@ for streamName, stream of streams do (streamName, stream) -> - emitters[streamName] = stream.emit - stream.emit = (eventName, args...) -> - broadcast streamName, eventName, args - emitters[streamName].apply {}, arguments + emitters[streamName] = stream.emitToSubscriptions + stream.emitToSubscriptions = (args, subscriptionId, userId) -> + if subscriptionId isnt 'broadcasted' + broadcast streamName, args + + emitters[streamName] args, subscriptionId, userId Meteor.methods - stream: (streamName, eventName, args) -> - console.log 'method stream', streamName, eventName, args - args.unshift eventName - emitters[streamName]?.apply {}, args + stream: (streamName, args) -> + console.log 'method stream', streamName, args + if not emitters[streamName]? + console.log "Stream for broadcast with name #{streamName} does not exists".red + else + emitters[streamName].call null, args, 'broadcasted' Meteor.startup -> config = - 'typing': typingStream - 'deleteMsgStream': deleteMsgStream - - if webrtc - config['webrtc.stream'] = webrtc.stream + 'RocketChat.Notifications.streamAll': RocketChat.Notifications.streamAll + 'RocketChat.Notifications.streamRoom': RocketChat.Notifications.streamRoom + 'RocketChat.Notifications.streamUser': RocketChat.Notifications.streamUser startStreamBroadcast config diff --git a/server/stream/typingStream.coffee b/server/stream/typingStream.coffee deleted file mode 100644 index 1746817ef33f..000000000000 --- a/server/stream/typingStream.coffee +++ /dev/null @@ -1,10 +0,0 @@ -@typingStream = new Meteor.Stream 'typing' - -typingStream.permissions.read -> - return true - -typingStream.permissions.write -> - return true - -typingStream.on 'typing', (typing) -> - typingStream.emit typing.room, _.pick(typing, 'username', 'start', 'stop')