diff --git a/packages/rocketchat-authorization/server/models/Permissions.coffee b/packages/rocketchat-authorization/server/models/Permissions.coffee index 8d03fe331c59..8115fa7cc06d 100644 --- a/packages/rocketchat-authorization/server/models/Permissions.coffee +++ b/packages/rocketchat-authorization/server/models/Permissions.coffee @@ -1,6 +1,6 @@ RocketChat.models.Permissions = new class extends RocketChat.models._Base constructor: -> - @_initModel 'permissions' + super('permissions') # FIND findByRole: (role, options) -> diff --git a/packages/rocketchat-authorization/server/models/Roles.coffee b/packages/rocketchat-authorization/server/models/Roles.coffee index 8489afa1d47a..ad50b0302f38 100644 --- a/packages/rocketchat-authorization/server/models/Roles.coffee +++ b/packages/rocketchat-authorization/server/models/Roles.coffee @@ -1,6 +1,6 @@ RocketChat.models.Roles = new class extends RocketChat.models._Base constructor: -> - @_initModel 'roles' + super('roles') @tryEnsureIndex { 'name': 1 } @tryEnsureIndex { 'scope': 1 } diff --git a/packages/rocketchat-channel-settings/server/functions/saveRoomName.coffee b/packages/rocketchat-channel-settings/server/functions/saveRoomName.coffee index 929b05fa8712..29da21805946 100644 --- a/packages/rocketchat-channel-settings/server/functions/saveRoomName.coffee +++ b/packages/rocketchat-channel-settings/server/functions/saveRoomName.coffee @@ -1,4 +1,4 @@ -RocketChat.saveRoomName = (rid, name, user) -> +RocketChat.saveRoomName = (rid, name) -> room = RocketChat.models.Rooms.findOneById rid if room.t not in ['c', 'p'] diff --git a/packages/rocketchat-emoji-custom/server/models/EmojiCustom.js b/packages/rocketchat-emoji-custom/server/models/EmojiCustom.js index 9d95273ee33c..6c3845ad3d49 100644 --- a/packages/rocketchat-emoji-custom/server/models/EmojiCustom.js +++ b/packages/rocketchat-emoji-custom/server/models/EmojiCustom.js @@ -1,7 +1,6 @@ class EmojiCustom extends RocketChat.models._Base { constructor() { - super(); - this._initModel('custom_emoji'); + super('custom_emoji'); this.tryEnsureIndex({ 'name': 1 }); this.tryEnsureIndex({ 'aliases': 1 }); diff --git a/packages/rocketchat-highlight-words/client.coffee b/packages/rocketchat-highlight-words/client.coffee index cf227cf2522c..ed2c42655ed9 100644 --- a/packages/rocketchat-highlight-words/client.coffee +++ b/packages/rocketchat-highlight-words/client.coffee @@ -22,4 +22,4 @@ class HighlightWordsClient message.html = msg return message -RocketChat.callbacks.add 'renderMessage', HighlightWordsClient, RocketChat.callbacks.priority.MEDIUM, 'highlight-words' +RocketChat.callbacks.add 'renderMessage', HighlightWordsClient, RocketChat.callbacks.priority.MEDIUM + 1, 'highlight-words' diff --git a/packages/rocketchat-importer/server/models/Imports.coffee b/packages/rocketchat-importer/server/models/Imports.coffee index ad32bd3cea6f..2e966dc83809 100644 --- a/packages/rocketchat-importer/server/models/Imports.coffee +++ b/packages/rocketchat-importer/server/models/Imports.coffee @@ -1,3 +1,3 @@ Importer.Imports = new class Importer.Imports extends RocketChat.models._Base constructor: -> - @_initModel 'import' + super('import') diff --git a/packages/rocketchat-importer/server/models/RawImports.coffee b/packages/rocketchat-importer/server/models/RawImports.coffee index 684e1c43fa56..1495423ea4ac 100644 --- a/packages/rocketchat-importer/server/models/RawImports.coffee +++ b/packages/rocketchat-importer/server/models/RawImports.coffee @@ -1,3 +1,3 @@ Importer.RawImports = new class Importer.RawImports extends RocketChat.models._Base constructor: -> - @_initModel 'raw_imports' + super('raw_imports') diff --git a/packages/rocketchat-integrations/server/models/Integrations.coffee b/packages/rocketchat-integrations/server/models/Integrations.coffee index 8ca464e07ce9..21a570244746 100644 --- a/packages/rocketchat-integrations/server/models/Integrations.coffee +++ b/packages/rocketchat-integrations/server/models/Integrations.coffee @@ -1,6 +1,6 @@ RocketChat.models.Integrations = new class extends RocketChat.models._Base constructor: -> - @_initModel 'integrations' + super('integrations') # FIND diff --git a/packages/rocketchat-irc/irc.server.coffee b/packages/rocketchat-irc/irc.server.coffee index 5ca927d8459f..beb3cc9846fd 100644 --- a/packages/rocketchat-irc/irc.server.coffee +++ b/packages/rocketchat-irc/irc.server.coffee @@ -1,389 +1,389 @@ -net = Npm.require('net') -Lru = Npm.require('lru-cache') - -MESSAGE_CACHE_SIZE = 200 -IRC_PORT = 6667 -IRC_HOST = 'irc.freenode.net' - -ircClientMap = {} -ircReceiveMessageCache = Lru MESSAGE_CACHE_SIZE -ircSendMessageCache = Lru MESSAGE_CACHE_SIZE - -bind = (f) -> - g = Meteor.bindEnvironment (self, args...) -> f.apply(self, args) - (args...) -> g @, args... - -async = (f, args...) -> - Meteor.wrapAsync(f)(args...) - -class IrcClient - constructor: (@loginReq) -> - @user = @loginReq.user - @user.username = @user.name - ircClientMap[@user._id] = this - @ircPort = IRC_PORT - @ircHost = IRC_HOST - @msgBuf = [] - - @isConnected = false - @isDistroyed = false - @socket = new net.Socket - @socket.setNoDelay - @socket.setEncoding 'utf-8' - @socket.setKeepAlive true - @onConnect = bind @onConnect - @onClose = bind @onClose - @onTimeout = bind @onTimeout - @onError = bind @onError - @onReceiveRawMessage = bind @onReceiveRawMessage - @socket.on 'data', @onReceiveRawMessage - @socket.on 'close', @onClose - @socket.on 'timeout', @onTimeout - @socket.on 'error', @onError - - @isJoiningRoom = false - @receiveMemberListBuf = {} - @pendingJoinRoomBuf = [] - - @successLoginMessageRegex = /Welcome to the freenode Internet Relay Chat Network/ - @failedLoginMessageRegex = /You have not registered/ - @receiveMessageRegex = /^:(\S+)!~\S+ PRIVMSG (\S+) :(.+)$/ - @receiveMemberListRegex = /^:\S+ \d+ \S+ = #(\S+) :(.*)$/ - @endMemberListRegex = /^.+#(\S+) :End of \/NAMES list.$/ - @addMemberToRoomRegex = /^:(\S+)!~\S+ JOIN #(\S+)$/ - @removeMemberFromRoomRegex = /^:(\S+)!~\S+ PART #(\S+)$/ - @quiteMemberRegex = /^:(\S+)!~\S+ QUIT .*$/ - - connect: (@loginCb) => - @socket.connect @ircPort, @ircHost, @onConnect - @initRoomList() - - disconnect: () -> - @isDistroyed = true - @socket.destroy() - - onConnect: () => - console.log '[irc] onConnect -> '.yellow, @user.username, 'connect success.' - @socket.write "NICK #{@user.username}\r\n" - @socket.write "USER #{@user.username} 0 * :Real Name\r\n" - # message order could not make sure here - @isConnected = true - @socket.write msg for msg in @msgBuf - - onClose: (data) => - console.log '[irc] onClose -> '.yellow, @user.username, 'connection close.' - @isConnected = false - if @isDistroyed - delete ircClientMap[@user._id] - else - @connect() - - onTimeout: () => - console.log '[irc] onTimeout -> '.yellow, @user.username, 'connection timeout.', arguments - - onError: () => - console.log '[irc] onError -> '.yellow, @user.username, 'connection error.', arguments - - onReceiveRawMessage: (data) => - data = data.toString().split('\n') - for line in data - line = line.trim() - console.log "[#{@ircHost}:#{@ircPort}]:", line - # Send heartbeat package to irc server - if line.indexOf('PING') == 0 - @socket.write line.replace('PING :', 'PONG ') - continue - - matchResult = @receiveMessageRegex.exec line - if matchResult - @onReceiveMessage matchResult[1], matchResult[2], matchResult[3] - continue - - matchResult = @receiveMemberListRegex.exec line - if matchResult - @onReceiveMemberList matchResult[1], matchResult[2].split ' ' - continue - - matchResult = @endMemberListRegex.exec line - if matchResult - @onEndMemberList matchResult[1] - continue - - matchResult = @addMemberToRoomRegex.exec line - if matchResult - @onAddMemberToRoom matchResult[1], matchResult[2] - continue - - matchResult = @removeMemberFromRoomRegex.exec line - if matchResult - @onRemoveMemberFromRoom matchResult[1], matchResult[2] - continue - - matchResult = @quiteMemberRegex.exec line - if matchResult - @onQuiteMember matchResult[1] - continue - - matchResult = @successLoginMessageRegex.exec line - if matchResult - @onSuccessLoginMessage() - continue - - matchResult = @failedLoginMessageRegex.exec line - if matchResult - @onFailedLoginMessage() - continue - - onSuccessLoginMessage: () -> - console.log '[irc] onSuccessLoginMessage -> '.yellow - if @loginCb - @loginCb null, @loginReq - - onFailedLoginMessage: () -> - console.log '[irc] onFailedLoginMessage -> '.yellow - @loginReq.allowed = false - @disconnect() - if @loginCb - @loginCb null, @loginReq - - onReceiveMessage: (source, target, content) -> - now = new Date - timestamp = now.getTime() - - cacheKey = [source, target, content].join ',' - console.log '[irc] ircSendMessageCache.get -> '.yellow, 'key:', cacheKey, 'value:', ircSendMessageCache.get(cacheKey), 'ts:', (timestamp - 1000) - if ircSendMessageCache.get(cacheKey) > (timestamp - 1000) - return - else - ircSendMessageCache.set cacheKey, timestamp - - console.log '[irc] onReceiveMessage -> '.yellow, 'source:', source, 'target:', target, 'content:', content - source = @createUserWhenNotExist source - if target[0] == '#' - room = RocketChat.models.Rooms.findOneByName target.substring(1) - else - room = @createDirectRoomWhenNotExist(source, @user) - - message = - msg: content - ts: now - cacheKey = "#{source.username}#{timestamp}" - ircReceiveMessageCache.set cacheKey, true - console.log '[irc] ircReceiveMessageCache.set -> '.yellow, 'key:', cacheKey - RocketChat.sendMessage source, message, room - - onReceiveMemberList: (roomName, members) -> - @receiveMemberListBuf[roomName] = @receiveMemberListBuf[roomName].concat members - - onEndMemberList: (roomName) -> - newMembers = @receiveMemberListBuf[roomName] - console.log '[irc] onEndMemberList -> '.yellow, 'room:', roomName, 'members:', newMembers.join ',' - room = RocketChat.models.Rooms.findOneByNameAndType roomName, 'c' - unless room - return - - oldMembers = room.usernames - appendMembers = _.difference newMembers, oldMembers - removeMembers = _.difference oldMembers, newMembers - - for member in appendMembers - @createUserWhenNotExist member - - RocketChat.models.Rooms.removeUsernamesById room._id, removeMembers - RocketChat.models.Rooms.addUsernamesById room._id, appendMembers - - @isJoiningRoom = false - roomName = @pendingJoinRoomBuf.shift() - if roomName - @joinRoom - t: 'c' - name: roomName - - sendRawMessage: (msg) -> - console.log '[irc] sendRawMessage -> '.yellow, msg.slice(0, -2) - if @isConnected - @socket.write msg - else - @msgBuf.push msg - - sendMessage: (room, message) -> - console.log '[irc] sendMessage -> '.yellow, 'userName:', message.u.username - target = '' - if room.t == 'c' - target = "##{room.name}" - else if room.t == 'd' - for name in room.usernames - if message.u.username != name - target = name - break - - cacheKey = [@user.username, target, message.msg].join ',' - console.log '[irc] ircSendMessageCache.set -> '.yellow, 'key:', cacheKey, 'ts:', message.ts.getTime() - ircSendMessageCache.set cacheKey, message.ts.getTime() - msg = "PRIVMSG #{target} :#{message.msg}\r\n" - @sendRawMessage msg - - initRoomList: -> - roomsCursor = RocketChat.models.Rooms.findByTypeContainigUsername 'c', @user.username, - fields: - name: 1 - t: 1 - - rooms = roomsCursor.fetch() - for room in rooms - @joinRoom(room) - - joinRoom: (room) -> - if room.t isnt 'c' or room.name == 'general' - return - - if @isJoiningRoom - @pendingJoinRoomBuf.push room.name - else - console.log '[irc] joinRoom -> '.yellow, 'roomName:', room.name, 'pendingJoinRoomBuf:', @pendingJoinRoomBuf.join ',' - msg = "JOIN ##{room.name}\r\n" - @receiveMemberListBuf[room.name] = [] - @sendRawMessage msg - @isJoiningRoom = true - - leaveRoom: (room) -> - if room.t isnt 'c' - return - msg = "PART ##{room.name}\r\n" - @sendRawMessage msg - - getMemberList: (room) -> - if room.t isnt 'c' - return - msg = "NAMES ##{room.name}\r\n" - @receiveMemberListBuf[room.name] = [] - @sendRawMessage msg - - onAddMemberToRoom: (member, roomName) -> - if @user.username == member - return - - console.log '[irc] onAddMemberToRoom -> '.yellow, 'roomName:', roomName, 'member:', member - @createUserWhenNotExist member - - RocketChat.models.Rooms.addUsernameByName roomName, member - - onRemoveMemberFromRoom: (member, roomName)-> - console.log '[irc] onRemoveMemberFromRoom -> '.yellow, 'roomName:', roomName, 'member:', member - RocketChat.models.Rooms.removeUsernameByName roomName, member - - onQuiteMember: (member) -> - console.log '[irc] onQuiteMember ->'.yellow, 'username:', member - RocketChat.models.Rooms.removeUsernameFromAll member - - Meteor.users.update {name: member}, - $set: - status: 'offline' - - createUserWhenNotExist: (name) -> - user = Meteor.users.findOne {name: name} - unless user - console.log '[irc] createNotExistUser ->'.yellow, 'userName:', name - Meteor.call 'registerUser', - email: "#{name}@rocketchat.org" - pass: 'rocketchat' - name: name - Meteor.users.update {name: name}, - $set: - status: 'online' - username: name - user = Meteor.users.findOne {name: name} - return user - - - createDirectRoomWhenNotExist: (source, target) -> - console.log '[irc] createDirectRoomWhenNotExist -> '.yellow, 'source:', source, 'target:', target - rid = [source._id, target._id].sort().join('') - now = new Date() - RocketChat.models.Rooms.upsert - _id: rid - , - $set: - usernames: [source.username, target.username] - $setOnInsert: - t: 'd' - msgs: 0 - ts: now - - RocketChat.models.Subscriptions.upsert - rid: rid - $and: [{'u._id': target._id}] - , - $setOnInsert: - name: source.username - t: 'd' - open: false - alert: false - unread: 0 - u: - _id: target._id - username: target.username - return { - t: 'd' - _id: rid - } - -IrcClient.getByUid = (uid) -> - return ircClientMap[uid] - -IrcClient.create = (login) -> - unless login.user? - return login - unless login.user._id of ircClientMap - ircClient = new IrcClient login - return async ircClient.connect - - return login - - -class IrcLoginer - constructor: (login) -> - console.log '[irc] validateLogin -> '.yellow, login - return IrcClient.create login - - -class IrcSender - constructor: (message) -> - name = message.u.username - timestamp = message.ts.getTime() - cacheKey = "#{name}#{timestamp}" - if ircReceiveMessageCache.get cacheKey - return message - - room = RocketChat.models.Rooms.findOneById message.rid, { fields: { name: 1, usernames: 1, t: 1 } } - ircClient = IrcClient.getByUid message.u._id - ircClient.sendMessage room, message - return message - - -class IrcRoomJoiner - constructor: (user, room) -> - ircClient = IrcClient.getByUid user._id - ircClient.joinRoom room - return room - - -class IrcRoomLeaver - constructor: (user, room) -> - ircClient = IrcClient.getByUid user._id - ircClient.leaveRoom room - return room - - -class IrcLogoutCleanUper - constructor: (user) -> - ircClient = IrcClient.getByUid user._id - ircClient.disconnect() - return user - -RocketChat.callbacks.add 'beforeValidateLogin', IrcLoginer, RocketChat.callbacks.priority.LOW -RocketChat.callbacks.add 'beforeSaveMessage', IrcSender, RocketChat.callbacks.priority.LOW -RocketChat.callbacks.add 'beforeJoinRoom', IrcRoomJoiner, RocketChat.callbacks.priority.LOW -RocketChat.callbacks.add 'beforeCreateChannel', IrcRoomJoiner, RocketChat.callbacks.priority.LOW -RocketChat.callbacks.add 'beforeLeaveRoom', IrcRoomLeaver, RocketChat.callbacks.priority.LOW -RocketChat.callbacks.add 'afterLogoutCleanUp', IrcLogoutCleanUper, RocketChat.callbacks.priority.LOW +net = Npm.require('net') +Lru = Npm.require('lru-cache') + +MESSAGE_CACHE_SIZE = 200 +IRC_PORT = 6667 +IRC_HOST = 'irc.freenode.net' + +ircClientMap = {} +ircReceiveMessageCache = Lru MESSAGE_CACHE_SIZE +ircSendMessageCache = Lru MESSAGE_CACHE_SIZE + +bind = (f) -> + g = Meteor.bindEnvironment (self, args...) -> f.apply(self, args) + (args...) -> g @, args... + +async = (f, args...) -> + Meteor.wrapAsync(f)(args...) + +class IrcClient + constructor: (@loginReq) -> + @user = @loginReq.user + @user.username = @user.name + ircClientMap[@user._id] = this + @ircPort = IRC_PORT + @ircHost = IRC_HOST + @msgBuf = [] + + @isConnected = false + @isDistroyed = false + @socket = new net.Socket + @socket.setNoDelay + @socket.setEncoding 'utf-8' + @socket.setKeepAlive true + @onConnect = bind @onConnect + @onClose = bind @onClose + @onTimeout = bind @onTimeout + @onError = bind @onError + @onReceiveRawMessage = bind @onReceiveRawMessage + @socket.on 'data', @onReceiveRawMessage + @socket.on 'close', @onClose + @socket.on 'timeout', @onTimeout + @socket.on 'error', @onError + + @isJoiningRoom = false + @receiveMemberListBuf = {} + @pendingJoinRoomBuf = [] + + @successLoginMessageRegex = /Welcome to the freenode Internet Relay Chat Network/ + @failedLoginMessageRegex = /You have not registered/ + @receiveMessageRegex = /^:(\S+)!~\S+ PRIVMSG (\S+) :(.+)$/ + @receiveMemberListRegex = /^:\S+ \d+ \S+ = #(\S+) :(.*)$/ + @endMemberListRegex = /^.+#(\S+) :End of \/NAMES list.$/ + @addMemberToRoomRegex = /^:(\S+)!~\S+ JOIN #(\S+)$/ + @removeMemberFromRoomRegex = /^:(\S+)!~\S+ PART #(\S+)$/ + @quiteMemberRegex = /^:(\S+)!~\S+ QUIT .*$/ + + connect: (@loginCb) => + @socket.connect @ircPort, @ircHost, @onConnect + @initRoomList() + + disconnect: () -> + @isDistroyed = true + @socket.destroy() + + onConnect: () => + console.log '[irc] onConnect -> '.yellow, @user.username, 'connect success.' + @socket.write "NICK #{@user.username}\r\n" + @socket.write "USER #{@user.username} 0 * :Real Name\r\n" + # message order could not make sure here + @isConnected = true + @socket.write msg for msg in @msgBuf + + onClose: (data) => + console.log '[irc] onClose -> '.yellow, @user.username, 'connection close.' + @isConnected = false + if @isDistroyed + delete ircClientMap[@user._id] + else + @connect() + + onTimeout: () => + console.log '[irc] onTimeout -> '.yellow, @user.username, 'connection timeout.', arguments + + onError: () => + console.log '[irc] onError -> '.yellow, @user.username, 'connection error.', arguments + + onReceiveRawMessage: (data) => + data = data.toString().split('\n') + for line in data + line = line.trim() + console.log "[#{@ircHost}:#{@ircPort}]:", line + # Send heartbeat package to irc server + if line.indexOf('PING') == 0 + @socket.write line.replace('PING :', 'PONG ') + continue + + matchResult = @receiveMessageRegex.exec line + if matchResult + @onReceiveMessage matchResult[1], matchResult[2], matchResult[3] + continue + + matchResult = @receiveMemberListRegex.exec line + if matchResult + @onReceiveMemberList matchResult[1], matchResult[2].split ' ' + continue + + matchResult = @endMemberListRegex.exec line + if matchResult + @onEndMemberList matchResult[1] + continue + + matchResult = @addMemberToRoomRegex.exec line + if matchResult + @onAddMemberToRoom matchResult[1], matchResult[2] + continue + + matchResult = @removeMemberFromRoomRegex.exec line + if matchResult + @onRemoveMemberFromRoom matchResult[1], matchResult[2] + continue + + matchResult = @quiteMemberRegex.exec line + if matchResult + @onQuiteMember matchResult[1] + continue + + matchResult = @successLoginMessageRegex.exec line + if matchResult + @onSuccessLoginMessage() + continue + + matchResult = @failedLoginMessageRegex.exec line + if matchResult + @onFailedLoginMessage() + continue + + onSuccessLoginMessage: () -> + console.log '[irc] onSuccessLoginMessage -> '.yellow + if @loginCb + @loginCb null, @loginReq + + onFailedLoginMessage: () -> + console.log '[irc] onFailedLoginMessage -> '.yellow + @loginReq.allowed = false + @disconnect() + if @loginCb + @loginCb null, @loginReq + + onReceiveMessage: (source, target, content) -> + now = new Date + timestamp = now.getTime() + + cacheKey = [source, target, content].join ',' + console.log '[irc] ircSendMessageCache.get -> '.yellow, 'key:', cacheKey, 'value:', ircSendMessageCache.get(cacheKey), 'ts:', (timestamp - 1000) + if ircSendMessageCache.get(cacheKey) > (timestamp - 1000) + return + else + ircSendMessageCache.set cacheKey, timestamp + + console.log '[irc] onReceiveMessage -> '.yellow, 'source:', source, 'target:', target, 'content:', content + source = @createUserWhenNotExist source + if target[0] == '#' + room = RocketChat.models.Rooms.findOneByName target.substring(1) + else + room = @createDirectRoomWhenNotExist(source, @user) + + message = + msg: content + ts: now + cacheKey = "#{source.username}#{timestamp}" + ircReceiveMessageCache.set cacheKey, true + console.log '[irc] ircReceiveMessageCache.set -> '.yellow, 'key:', cacheKey + RocketChat.sendMessage source, message, room + + onReceiveMemberList: (roomName, members) -> + @receiveMemberListBuf[roomName] = @receiveMemberListBuf[roomName].concat members + + onEndMemberList: (roomName) -> + newMembers = @receiveMemberListBuf[roomName] + console.log '[irc] onEndMemberList -> '.yellow, 'room:', roomName, 'members:', newMembers.join ',' + room = RocketChat.models.Rooms.findOneByNameAndType roomName, 'c' + unless room + return + + oldMembers = room.usernames + appendMembers = _.difference newMembers, oldMembers + removeMembers = _.difference oldMembers, newMembers + + for member in appendMembers + @createUserWhenNotExist member + + RocketChat.models.Rooms.removeUsernamesById room._id, removeMembers + RocketChat.models.Rooms.addUsernamesById room._id, appendMembers + + @isJoiningRoom = false + roomName = @pendingJoinRoomBuf.shift() + if roomName + @joinRoom + t: 'c' + name: roomName + + sendRawMessage: (msg) -> + console.log '[irc] sendRawMessage -> '.yellow, msg.slice(0, -2) + if @isConnected + @socket.write msg + else + @msgBuf.push msg + + sendMessage: (room, message) -> + console.log '[irc] sendMessage -> '.yellow, 'userName:', message.u.username + target = '' + if room.t == 'c' + target = "##{room.name}" + else if room.t == 'd' + for name in room.usernames + if message.u.username != name + target = name + break + + cacheKey = [@user.username, target, message.msg].join ',' + console.log '[irc] ircSendMessageCache.set -> '.yellow, 'key:', cacheKey, 'ts:', message.ts.getTime() + ircSendMessageCache.set cacheKey, message.ts.getTime() + msg = "PRIVMSG #{target} :#{message.msg}\r\n" + @sendRawMessage msg + + initRoomList: -> + roomsCursor = RocketChat.models.Rooms.findByTypeContainigUsername 'c', @user.username, + fields: + name: 1 + t: 1 + + rooms = roomsCursor.fetch() + for room in rooms + @joinRoom(room) + + joinRoom: (room) -> + if room.t isnt 'c' or room.name == 'general' + return + + if @isJoiningRoom + @pendingJoinRoomBuf.push room.name + else + console.log '[irc] joinRoom -> '.yellow, 'roomName:', room.name, 'pendingJoinRoomBuf:', @pendingJoinRoomBuf.join ',' + msg = "JOIN ##{room.name}\r\n" + @receiveMemberListBuf[room.name] = [] + @sendRawMessage msg + @isJoiningRoom = true + + leaveRoom: (room) -> + if room.t isnt 'c' + return + msg = "PART ##{room.name}\r\n" + @sendRawMessage msg + + getMemberList: (room) -> + if room.t isnt 'c' + return + msg = "NAMES ##{room.name}\r\n" + @receiveMemberListBuf[room.name] = [] + @sendRawMessage msg + + onAddMemberToRoom: (member, roomName) -> + if @user.username == member + return + + console.log '[irc] onAddMemberToRoom -> '.yellow, 'roomName:', roomName, 'member:', member + @createUserWhenNotExist member + + RocketChat.models.Rooms.addUsernameByName roomName, member + + onRemoveMemberFromRoom: (member, roomName)-> + console.log '[irc] onRemoveMemberFromRoom -> '.yellow, 'roomName:', roomName, 'member:', member + RocketChat.models.Rooms.removeUsernameByName roomName, member + + onQuiteMember: (member) -> + console.log '[irc] onQuiteMember ->'.yellow, 'username:', member + RocketChat.models.Rooms.removeUsernameFromAll member + + Meteor.users.update {name: member}, + $set: + status: 'offline' + + createUserWhenNotExist: (name) -> + user = Meteor.users.findOne {name: name} + unless user + console.log '[irc] createNotExistUser ->'.yellow, 'userName:', name + Meteor.call 'registerUser', + email: "#{name}@rocketchat.org" + pass: 'rocketchat' + name: name + Meteor.users.update {name: name}, + $set: + status: 'online' + username: name + user = Meteor.users.findOne {name: name} + return user + + + createDirectRoomWhenNotExist: (source, target) -> + console.log '[irc] createDirectRoomWhenNotExist -> '.yellow, 'source:', source, 'target:', target + rid = [source._id, target._id].sort().join('') + now = new Date() + RocketChat.models.Rooms.upsert + _id: rid + , + $set: + usernames: [source.username, target.username] + $setOnInsert: + t: 'd' + msgs: 0 + ts: now + + RocketChat.models.Subscriptions.upsert + rid: rid + $and: [{'u._id': target._id}] + , + $setOnInsert: + name: source.username + t: 'd' + open: false + alert: false + unread: 0 + u: + _id: target._id + username: target.username + return { + t: 'd' + _id: rid + } + +IrcClient.getByUid = (uid) -> + return ircClientMap[uid] + +IrcClient.create = (login) -> + unless login.user? + return login + unless login.user._id of ircClientMap + ircClient = new IrcClient login + return async ircClient.connect + + return login + + +class IrcLoginer + constructor: (login) -> + console.log '[irc] validateLogin -> '.yellow, login + return IrcClient.create login + + +class IrcSender + constructor: (message) -> + name = message.u.username + timestamp = message.ts.getTime() + cacheKey = "#{name}#{timestamp}" + if ircReceiveMessageCache.get cacheKey + return message + + room = RocketChat.models.Rooms.findOneById message.rid, { fields: { name: 1, usernames: 1, t: 1 } } + ircClient = IrcClient.getByUid message.u._id + ircClient.sendMessage room, message + return message + + +class IrcRoomJoiner + constructor: (user, room) -> + ircClient = IrcClient.getByUid user._id + ircClient.joinRoom room + return room + + +class IrcRoomLeaver + constructor: (user, room) -> + ircClient = IrcClient.getByUid user._id + ircClient.leaveRoom room + return room + + +class IrcLogoutCleanUper + constructor: (user) -> + ircClient = IrcClient.getByUid user._id + ircClient.disconnect() + return user + +RocketChat.callbacks.add 'beforeValidateLogin', IrcLoginer, RocketChat.callbacks.priority.LOW +RocketChat.callbacks.add 'beforeSaveMessage', IrcSender, RocketChat.callbacks.priority.LOW +RocketChat.callbacks.add 'beforeJoinRoom', IrcRoomJoiner, RocketChat.callbacks.priority.LOW +RocketChat.callbacks.add 'beforeCreateChannel', IrcRoomJoiner, RocketChat.callbacks.priority.LOW +RocketChat.callbacks.add 'beforeLeaveRoom', IrcRoomLeaver, RocketChat.callbacks.priority.LOW +RocketChat.callbacks.add 'afterLogoutCleanUp', IrcLogoutCleanUper, RocketChat.callbacks.priority.LOW diff --git a/packages/rocketchat-lib/server/lib/roomTypes.coffee b/packages/rocketchat-lib/server/lib/roomTypes.coffee index 6a43a125aa5b..db0a3d2f17a3 100644 --- a/packages/rocketchat-lib/server/lib/roomTypes.coffee +++ b/packages/rocketchat-lib/server/lib/roomTypes.coffee @@ -12,6 +12,19 @@ RocketChat.roomTypes = new class roomTypesServer extends roomTypesCommon @roomTypes[roomType].publish = callback + setRoomFind: (roomType, callback) -> + if @roomTypes[roomType]?.roomFind? + throw new Meteor.Error 'room-find-exists', 'Room find for the given type already exists' + + unless @roomTypes[roomType]? + @roomTypes[roomType] = {} + + @roomTypes[roomType].roomFind = callback + + getRoomFind: (roomType) -> + return unless @roomTypes[roomType]?.roomFind? + return @roomTypes[roomType].roomFind + ### run the publish for a room type @param scope: Meteor publish scope @param roomType: room type (e.g.: c (for channels), d (for direct channels)) @@ -20,4 +33,3 @@ RocketChat.roomTypes = new class roomTypesServer extends roomTypesCommon runPublish: (scope, roomType, identifier) -> return unless @roomTypes[roomType]?.publish? return @roomTypes[roomType].publish.call scope, identifier - diff --git a/packages/rocketchat-lib/server/models/Messages.coffee b/packages/rocketchat-lib/server/models/Messages.coffee index 5144153c779a..adcd977b733f 100644 --- a/packages/rocketchat-lib/server/models/Messages.coffee +++ b/packages/rocketchat-lib/server/models/Messages.coffee @@ -1,6 +1,6 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base constructor: -> - @_initModel 'message' + super('message') @tryEnsureIndex { 'rid': 1, 'ts': 1 } @tryEnsureIndex { 'ts': 1 } diff --git a/packages/rocketchat-lib/server/models/Reports.coffee b/packages/rocketchat-lib/server/models/Reports.coffee index edadbd9bb8fb..c37b2735aba3 100644 --- a/packages/rocketchat-lib/server/models/Reports.coffee +++ b/packages/rocketchat-lib/server/models/Reports.coffee @@ -1,6 +1,6 @@ RocketChat.models.Reports = new class extends RocketChat.models._Base constructor: -> - @_initModel 'reports' + super('reports') # INSERT diff --git a/packages/rocketchat-lib/server/models/Rooms.coffee b/packages/rocketchat-lib/server/models/Rooms.coffee index 12129537fc7c..7fd5262bb1f6 100644 --- a/packages/rocketchat-lib/server/models/Rooms.coffee +++ b/packages/rocketchat-lib/server/models/Rooms.coffee @@ -1,6 +1,6 @@ RocketChat.models.Rooms = new class extends RocketChat.models._Base constructor: -> - @_initModel 'room' + super('room') @tryEnsureIndex { 'name': 1 }, { unique: 1, sparse: 1 } @tryEnsureIndex { 'default': 1 } diff --git a/packages/rocketchat-lib/server/models/Settings.coffee b/packages/rocketchat-lib/server/models/Settings.coffee index 2fb9a723e9bb..80b3bcb9fb49 100644 --- a/packages/rocketchat-lib/server/models/Settings.coffee +++ b/packages/rocketchat-lib/server/models/Settings.coffee @@ -1,6 +1,6 @@ RocketChat.models.Settings = new class extends RocketChat.models._Base constructor: -> - @_initModel 'settings' + super('settings') @tryEnsureIndex { 'blocked': 1 }, { sparse: 1 } @tryEnsureIndex { 'hidden': 1 }, { sparse: 1 } diff --git a/packages/rocketchat-lib/server/models/Subscriptions.coffee b/packages/rocketchat-lib/server/models/Subscriptions.coffee index 96aa25077e98..3f295809c695 100644 --- a/packages/rocketchat-lib/server/models/Subscriptions.coffee +++ b/packages/rocketchat-lib/server/models/Subscriptions.coffee @@ -1,6 +1,6 @@ RocketChat.models.Subscriptions = new class extends RocketChat.models._Base constructor: -> - @_initModel 'subscription' + super('subscription') @tryEnsureIndex { 'rid': 1, 'u._id': 1 }, { unique: 1 } @tryEnsureIndex { 'rid': 1, 'alert': 1, 'u._id': 1 } diff --git a/packages/rocketchat-lib/server/models/Uploads.coffee b/packages/rocketchat-lib/server/models/Uploads.coffee index 6bef26dcfd70..01cbeedf3d2c 100644 --- a/packages/rocketchat-lib/server/models/Uploads.coffee +++ b/packages/rocketchat-lib/server/models/Uploads.coffee @@ -1,6 +1,6 @@ RocketChat.models.Uploads = new class extends RocketChat.models._Base constructor: -> - @_initModel 'uploads' + super('uploads') @tryEnsureIndex { 'rid': 1 } @tryEnsureIndex { 'uploadedAt': 1 } diff --git a/packages/rocketchat-lib/server/models/_Base.js b/packages/rocketchat-lib/server/models/_Base.js index 65ceecea134c..d2ac1f12a4fd 100644 --- a/packages/rocketchat-lib/server/models/_Base.js +++ b/packages/rocketchat-lib/server/models/_Base.js @@ -11,20 +11,26 @@ try { } class ModelsBase extends EventEmitter { - _baseName() { - return baseName; - } - - _initModel(name) { - check(name, String); + constructor(model) { + super(); - this.name = name; - - this.model = new Mongo.Collection(this._baseName() + name); + if (Match.test(model, String)) { + this.name = model; + this.collectionName = this.baseName + this.name; + this.model = new Mongo.Collection(this.collectionName); + } else { + this.name = model._name; + this.collectionName = this.name; + this.model = model; + } this.tryEnsureIndex({ '_updatedAt': 1 }); } + get baseName() { + return baseName; + } + setUpdatedAt(record = {}, checkQuery = false, query) { if (checkQuery === true) { if (!query || Object.keys(query).length === 0) { diff --git a/packages/rocketchat-livechat/server/methods/takeInquiry.js b/packages/rocketchat-livechat/server/methods/takeInquiry.js index 6933818a19b2..79a717ab9932 100644 --- a/packages/rocketchat-livechat/server/methods/takeInquiry.js +++ b/packages/rocketchat-livechat/server/methods/takeInquiry.js @@ -41,10 +41,16 @@ Meteor.methods({ RocketChat.models.Rooms.changeAgentByRoomId(inquiry.rid, usernames, agent); + room.usernames = usernames; + room.servedBy = { + _id: agent.agentId, + username: agent.username + }; + // mark inquiry as taken RocketChat.models.LivechatInquiry.takeInquiry(inquiry._id); // return room corresponding to inquiry (for redirecting agent to the room route) - return RocketChat.models.Rooms.findOneById(inquiry.rid); + return room; } }); diff --git a/packages/rocketchat-livechat/server/models/LivechatCustomField.js b/packages/rocketchat-livechat/server/models/LivechatCustomField.js index d4c9a4803db2..8c3d7bf3a6bd 100644 --- a/packages/rocketchat-livechat/server/models/LivechatCustomField.js +++ b/packages/rocketchat-livechat/server/models/LivechatCustomField.js @@ -3,8 +3,7 @@ */ class LivechatCustomField extends RocketChat.models._Base { constructor() { - super(); - this._initModel('livechat_custom_field'); + super('livechat_custom_field'); } // FIND diff --git a/packages/rocketchat-livechat/server/models/LivechatDepartment.js b/packages/rocketchat-livechat/server/models/LivechatDepartment.js index b2997f19af4a..08627f550ef5 100644 --- a/packages/rocketchat-livechat/server/models/LivechatDepartment.js +++ b/packages/rocketchat-livechat/server/models/LivechatDepartment.js @@ -3,8 +3,7 @@ */ class LivechatDepartment extends RocketChat.models._Base { constructor() { - super(); - this._initModel('livechat_department'); + super('livechat_department'); } // FIND diff --git a/packages/rocketchat-livechat/server/models/LivechatDepartmentAgents.js b/packages/rocketchat-livechat/server/models/LivechatDepartmentAgents.js index 2a0552d0f318..681a6c73eecb 100644 --- a/packages/rocketchat-livechat/server/models/LivechatDepartmentAgents.js +++ b/packages/rocketchat-livechat/server/models/LivechatDepartmentAgents.js @@ -3,8 +3,7 @@ */ class LivechatDepartmentAgents extends RocketChat.models._Base { constructor() { - super(); - this._initModel('livechat_department_agents'); + super('livechat_department_agents'); } findByDepartmentId(departmentId) { diff --git a/packages/rocketchat-livechat/server/models/LivechatExternalMessage.js b/packages/rocketchat-livechat/server/models/LivechatExternalMessage.js index 0b8fd708b2e3..cd7143a3d0e1 100644 --- a/packages/rocketchat-livechat/server/models/LivechatExternalMessage.js +++ b/packages/rocketchat-livechat/server/models/LivechatExternalMessage.js @@ -1,7 +1,6 @@ class LivechatExternalMessage extends RocketChat.models._Base { constructor() { - super(); - this._initModel('livechat_external_message'); + super('livechat_external_message'); } // FIND diff --git a/packages/rocketchat-livechat/server/models/LivechatInquiry.js b/packages/rocketchat-livechat/server/models/LivechatInquiry.js index c528c728da17..29439c3a0dbd 100644 --- a/packages/rocketchat-livechat/server/models/LivechatInquiry.js +++ b/packages/rocketchat-livechat/server/models/LivechatInquiry.js @@ -1,7 +1,6 @@ class LivechatInquiry extends RocketChat.models._Base { constructor() { - super(); - this._initModel('livechat_inquiry'); + super('livechat_inquiry'); this.tryEnsureIndex({ 'rid': 1 }); // room id corresponding to this inquiry this.tryEnsureIndex({ 'name': 1 }); // name of the inquiry (client name for now) diff --git a/packages/rocketchat-livechat/server/models/LivechatOfficeHour.js b/packages/rocketchat-livechat/server/models/LivechatOfficeHour.js index ef77da9a560f..0232d3e8e848 100644 --- a/packages/rocketchat-livechat/server/models/LivechatOfficeHour.js +++ b/packages/rocketchat-livechat/server/models/LivechatOfficeHour.js @@ -1,7 +1,6 @@ class LivechatOfficeHour extends RocketChat.models._Base { constructor() { - super(); - this._initModel('livechat_office_hour'); + super('livechat_office_hour'); this.tryEnsureIndex({ 'day': 1 }); // the day of the week monday - sunday this.tryEnsureIndex({ 'start': 1 }); // the opening hours of the office diff --git a/packages/rocketchat-livechat/server/models/LivechatPageVisited.js b/packages/rocketchat-livechat/server/models/LivechatPageVisited.js index ff44dadc8dcf..b28bb416d983 100644 --- a/packages/rocketchat-livechat/server/models/LivechatPageVisited.js +++ b/packages/rocketchat-livechat/server/models/LivechatPageVisited.js @@ -3,8 +3,7 @@ */ class LivechatPageVisited extends RocketChat.models._Base { constructor() { - super(); - this._initModel('livechat_page_visited'); + super('livechat_page_visited'); this.tryEnsureIndex({ 'token': 1 }); this.tryEnsureIndex({ 'ts': 1 }); diff --git a/packages/rocketchat-livechat/server/models/LivechatTrigger.js b/packages/rocketchat-livechat/server/models/LivechatTrigger.js index a582b9d4f192..c7145759c0da 100644 --- a/packages/rocketchat-livechat/server/models/LivechatTrigger.js +++ b/packages/rocketchat-livechat/server/models/LivechatTrigger.js @@ -3,8 +3,7 @@ */ class LivechatTrigger extends RocketChat.models._Base { constructor() { - super(); - this._initModel('livechat_trigger'); + super('livechat_trigger'); } // FIND diff --git a/packages/rocketchat-oauth2-server-config/server/models/OAuthApps.coffee b/packages/rocketchat-oauth2-server-config/server/models/OAuthApps.coffee index 5f95a6c2d32e..62bc4b7db342 100644 --- a/packages/rocketchat-oauth2-server-config/server/models/OAuthApps.coffee +++ b/packages/rocketchat-oauth2-server-config/server/models/OAuthApps.coffee @@ -1,6 +1,6 @@ RocketChat.models.OAuthApps = new class extends RocketChat.models._Base constructor: -> - @_initModel 'oauth_apps' + super('oauth_apps') # FIND diff --git a/packages/rocketchat-oembed/server/models/OEmbedCache.coffee b/packages/rocketchat-oembed/server/models/OEmbedCache.coffee index bdc3a72af1e9..251eb3b6e6ab 100644 --- a/packages/rocketchat-oembed/server/models/OEmbedCache.coffee +++ b/packages/rocketchat-oembed/server/models/OEmbedCache.coffee @@ -1,6 +1,6 @@ RocketChat.models.OEmbedCache = new class extends RocketChat.models._Base constructor: -> - @_initModel 'oembed_cache' + super('oembed_cache') # FIND ONE diff --git a/packages/rocketchat-smarsh-connector/server/models/SmarshHistory.js b/packages/rocketchat-smarsh-connector/server/models/SmarshHistory.js index 8b28da7b9634..21cc11e04713 100644 --- a/packages/rocketchat-smarsh-connector/server/models/SmarshHistory.js +++ b/packages/rocketchat-smarsh-connector/server/models/SmarshHistory.js @@ -1,6 +1,5 @@ RocketChat.smarsh.History = new class extends RocketChat.models._Base { constructor() { - super(); - super._initModel('smarsh_history'); + super('smarsh_history'); } }; diff --git a/packages/rocketchat-spotify/lib/spotify.coffee b/packages/rocketchat-spotify/lib/spotify.coffee index 330c359e317f..d83fd8d52dbb 100644 --- a/packages/rocketchat-spotify/lib/spotify.coffee +++ b/packages/rocketchat-spotify/lib/spotify.coffee @@ -53,6 +53,6 @@ class Spotify return message -RocketChat.callbacks.add 'beforeSaveMessage', Spotify.transform, RocketChat.callbacks.priority.LOW -RocketChat.callbacks.add 'renderMessage', Spotify.render +RocketChat.callbacks.add 'beforeSaveMessage', Spotify.transform, RocketChat.callbacks.priority.LOW, 'spotify-save' +RocketChat.callbacks.add 'renderMessage', Spotify.render, RocketChat.callbacks.priority.MEDIUM, 'spotify-render' RocketChat.Spotify = Spotify diff --git a/packages/rocketchat-statistics/server/models/MRStatistics.coffee b/packages/rocketchat-statistics/server/models/MRStatistics.coffee index 135982f71d8f..fd3134baefc5 100644 --- a/packages/rocketchat-statistics/server/models/MRStatistics.coffee +++ b/packages/rocketchat-statistics/server/models/MRStatistics.coffee @@ -1,6 +1,6 @@ RocketChat.models.MRStatistics = new class extends RocketChat.models._Base constructor: -> - @_initModel 'mr_statistics' + super('mr_statistics') # FIND ONE diff --git a/packages/rocketchat-statistics/server/models/Statistics.coffee b/packages/rocketchat-statistics/server/models/Statistics.coffee index bbd7b4fbcc11..4eb8f650b9c1 100644 --- a/packages/rocketchat-statistics/server/models/Statistics.coffee +++ b/packages/rocketchat-statistics/server/models/Statistics.coffee @@ -1,6 +1,6 @@ RocketChat.models.Statistics = new class extends RocketChat.models._Base constructor: -> - @_initModel 'statistics' + super('statistics') @tryEnsureIndex { 'createdAt': 1 } diff --git a/packages/rocketchat-ui/views/app/room.coffee b/packages/rocketchat-ui/views/app/room.coffee index 973f24ddd5d4..6b2b3f66a7fc 100644 --- a/packages/rocketchat-ui/views/app/room.coffee +++ b/packages/rocketchat-ui/views/app/room.coffee @@ -68,8 +68,8 @@ Template.room.helpers return {} unless roomData if roomData.t in ['d', 'l'] - username = _.without roomData.usernames, Meteor.user().username - return Session.get('user_' + username + '_status') || 'offline' + subscription = RocketChat.models.Subscriptions.findOne({rid: this._id}); + return Session.get('user_' + subscription.name + '_status') || 'offline' else return 'offline' diff --git a/server/methods/getUsersOfRoom.js b/server/methods/getUsersOfRoom.js new file mode 100644 index 000000000000..b9f496dec71d --- /dev/null +++ b/server/methods/getUsersOfRoom.js @@ -0,0 +1,36 @@ +Meteor.methods({ + getUsersOfRoom(roomId, showAll) { + if (!Meteor.userId()) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getUsersOfRoom' }); + } + + const room = Meteor.call('canAccessRoom', roomId, Meteor.userId()); + if (!room) { + throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'getUsersOfRoom' }); + } + + const filter = (record) => { + if (!record._user) { + console.log('Subscription without user', record._id); + return false; + } + + if (showAll === true) { + return true; + } + + return record._user.status !== 'offline'; + }; + + const map = (record) => { + return record._user.username; + }; + + const records = RocketChat.models.Subscriptions.findByRoomId(roomId).fetch(); + + return { + total: records.length, + records: records.filter(filter).map(map) + }; + } +}); diff --git a/server/publications/spotlight.coffee b/server/publications/spotlight.coffee index 19754853f596..9981a6dd5a6a 100644 --- a/server/publications/spotlight.coffee +++ b/server/publications/spotlight.coffee @@ -13,7 +13,7 @@ Meteor.methods result.users = RocketChat.models.Users.findByActiveUsersUsernameExcept(text, usernames, { limit: 5, fields: { username: 1, status: 1 }, sort: { username: 1 } }).fetch() if type.rooms is true and RocketChat.authz.hasPermission this.userId, 'view-c-room' - username = RocketChat.models.Users.findOne(this.userId, {username: 1}).username + username = RocketChat.models.Users.findOneById(this.userId, { username: 1 }).username result.rooms = RocketChat.models.Rooms.findByNameAndTypeNotContainingUsername(regex, 'c', username, { limit: 5, fields: { t: 1, name: 1 }, sort: { name: 1 } }).fetch() return result